SundanceDiffOp.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                             Sundance
00005 //                 Copyright 2011 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
00041 
00042 #include "SundanceDiffOp.hpp"
00043 #include "PlayaExceptions.hpp"
00044 
00045 #include "SundanceTestFuncElement.hpp"
00046 
00047 #include "SundanceCoordExpr.hpp"
00048 #include "SundanceZeroExpr.hpp"
00049 #include "PlayaTabs.hpp"
00050 #include "SundanceOut.hpp"
00051 
00052 using namespace Sundance;
00053 using namespace Sundance;
00054 
00055 using namespace Sundance;
00056 using namespace Teuchos;
00057 
00058 
00059 DiffOp::DiffOp(const MultiIndex& op, 
00060   const RCP<ScalarExpr>& arg)
00061   : UnaryExpr(arg), mi_(op), myCoordDeriv_(coordDeriv(op.firstOrderDirection())), requiredFunctions_(),
00062     ignoreFuncTerms_(false)
00063 {}
00064 
00065 void DiffOp::registerSpatialDerivs(const EvalContext& context, 
00066   const Set<MultiIndex>& miSet) const
00067 {
00068   EvaluatableExpr::registerSpatialDerivs(context, miSet);
00069   Set<MultiIndex> s;
00070   for (Set<MultiIndex>::const_iterator i=miSet.begin(); i!=miSet.end(); i++)
00071   {
00072     const MultiIndex& m = *i;
00073     s.put(m+mi_);
00074   }
00075   evaluatableArg()->registerSpatialDerivs(context, s);
00076 }
00077 
00078 
00079 std::ostream& DiffOp::toText(std::ostream& os, bool /* paren */) const 
00080 {
00081   std::string miStr = CoordExpr::coordName(mi_.firstOrderDirection(), "");
00082   os << "D[" << arg().toString() << ", " << miStr << "]";
00083   return os;
00084 }
00085 
00086 XMLObject DiffOp::toXML() const 
00087 {
00088   XMLObject rtn("DiffOp");
00089   rtn.addAttribute("m", mi_.toString());
00090   rtn.addChild(arg().toXML());
00091 
00092   return rtn;
00093 }
00094 
00095 
00096 Evaluator* DiffOp::createEvaluator(const EvaluatableExpr* expr,
00097   const EvalContext& context) const
00098 {
00099   return new DiffOpEvaluator(dynamic_cast<const DiffOp*>(expr), context);
00100 }
00101 
00102 
00103 
00104 void DiffOp::requestMultiIndexAtEvalPoint(const MultiIndex& mi,
00105   const MultipleDeriv& u,
00106   const EvalContext& context) const 
00107 {
00108   int verb = context.setupVerbosity();
00109   Tabs tab0(0);
00110   SUNDANCE_MSG3(verb, tab0 << "DiffOp::requestMultiIndexAtEvalPoint() for=" << toString());
00111   TEUCHOS_TEST_FOR_EXCEPT(u.size() != 1);
00112   const Deriv& d = *(u.begin());
00113 
00114   if (d.isFunctionalDeriv())
00115   {
00116     const SpatialDerivSpecifier& sds = d.opOnFunc();
00117 
00118     TEUCHOS_TEST_FOR_EXCEPTION(sds.isDivergence(), std::logic_error,
00119       "divergence operators not possible within DiffOp");
00120     TEUCHOS_TEST_FOR_EXCEPTION(sds.isNormal(), std::logic_error,
00121       "normal deriv operators not possible within DiffOp");
00122 
00123     const MultiIndex& newMi = sds.mi();
00124 
00125     const SymbolicFuncElement* sfe = d.symbFuncElem();
00126     TEUCHOS_TEST_FOR_EXCEPT(sfe == 0);
00127     const EvaluatableExpr* evalPt = sfe->evalPt();
00128     const ZeroExpr* z = dynamic_cast<const ZeroExpr*>(evalPt);
00129     if (z != 0) return;
00130     const DiscreteFuncElement* df 
00131       = dynamic_cast<const DiscreteFuncElement*>(evalPt);
00132     df->addMultiIndex(newMi);
00133     df->findW(1, context);
00134     df->findV(1, context);
00135     df->findC(1, context);
00136   }
00137 }
00138 
00139 
00140 RCP<Array<Set<MultipleDeriv> > > 
00141 DiffOp::internalDetermineR(const EvalContext& context,
00142   const Array<Set<MultipleDeriv> >& RInput) const
00143 {
00144   Tabs tab0(0);
00145   int verb = context.setupVerbosity();
00146 
00147   SUNDANCE_MSG2(verb, tab0 << "DiffOp::internalDetermineR for=" << toString());
00148   SUNDANCE_MSG2(verb, tab0 << "RInput = " << RInput );
00149 
00150   RCP<Array<Set<MultipleDeriv> > > rtn 
00151     = rcp(new Array<Set<MultipleDeriv> >(RInput.size()));
00152   
00153   {
00154     Tabs tab1;
00155     for (int i=0; i<RInput.size(); i++)
00156     {
00157       Tabs tab2;
00158       const Set<MultipleDeriv>& Wi = findW(i, context);
00159       SUNDANCE_MSG5(verb,  tab2 << "W[" << i << "] = " << Wi );
00160       (*rtn)[i] = RInput[i].intersection(Wi);
00161     }
00162 
00163     const Set<MultipleDeriv>& W1 = evaluatableArg()->findW(1, context);
00164     SUNDANCE_MSG3(verb, tab1 << "arg W1 = " << W1);
00165     Set<MultipleDeriv> ZxXx = applyZx(W1, mi_).setUnion(Xx(mi_));
00166     SUNDANCE_MSG3(verb, tab1 << "Z union X = " << ZxXx);
00167     Array<Set<MultipleDeriv> > RArg(RInput.size()+1);
00168     RArg[0].put(MultipleDeriv());
00169     RArg[1].put(MultipleDeriv(coordDeriv(mi_.firstOrderDirection())));
00170 
00171 
00172     
00173     for (int order=0; order<RInput.size(); order++)
00174     {
00175       Tabs tab2;
00176       const Set<MultipleDeriv>& WArgPlus = evaluatableArg()->findW(order+1, context);
00177       const Set<MultipleDeriv>& WArg = evaluatableArg()->findW(order, context);
00178       SUNDANCE_MSG3(verb, tab2 << "order = " << order);
00179       SUNDANCE_MSG3(verb, tab2 << "RInput = " << RInput[order]);
00180       SUNDANCE_MSG3(verb, tab2 << "WArg = " << WArg);
00181       SUNDANCE_MSG3(verb, tab2 << "WArgPlus = " << WArgPlus);
00182       SUNDANCE_MSG3(verb, tab2 << "ZxXx times RInput = " 
00183         << setProduct(ZxXx, RInput[order]));
00184       SUNDANCE_MSG3(verb, tab2 << "Tx(RInput, " << -mi_ << ") = " 
00185         << applyTx(RInput[order], -mi_) );
00186       RArg[order+1].merge(setProduct(ZxXx, RInput[order]).intersection(WArgPlus));
00187       RArg[order].merge(applyTx(RInput[order], -mi_).intersection(WArg));
00188     }
00189     SUNDANCE_MSG3(verb, tab1 << "RArg = " << RArg);
00190     
00191     SUNDANCE_MSG2(verb, tab1 << "calling determineR() for arg "
00192       << evaluatableArg()->toString());
00193     evaluatableArg()->determineR(context, RArg);
00194 
00195     /* inform the evaluation points of all functions appearing in the argument
00196      * that we'll need their spatial derivatives in direction mi(). */
00197     
00198     SUNDANCE_MSG3(verb, tab1 << "calling findR(1) to determine required spatial derivatives ");
00199     const Set<MultipleDeriv>& RArg1 = evaluatableArg()->findR(1, context);
00200     SUNDANCE_MSG3(verb, tab1 << "RArg1 = " << RArg1);
00201     for (Set<MultipleDeriv>::const_iterator i=RArg1.begin(); i!=RArg1.end(); i++)
00202     {
00203       requestMultiIndexAtEvalPoint(mi(), *i, context);
00204     }
00205   }
00206   printR(verb, rtn);
00207   SUNDANCE_MSG2(verb, tab0 << "done with DiffOp::internalDetermineR for "
00208     << toString());
00209   /* all done */  
00210   return rtn;
00211 }
00212 
00213 
00214 Set<MultipleDeriv> DiffOp::internalFindW(int order, const EvalContext& context) const
00215 {
00216   Tabs tabs(0);
00217   int verb = context.setupVerbosity();
00218 
00219   SUNDANCE_MSG2(verb, tabs << "DiffOp::internalFindW(order="
00220     << order << ") for " << toString());
00221 
00222   Set<MultipleDeriv> rtn ;
00223   if (order <= 2)
00224   {
00225     Tabs tab1;
00226     const Set<MultipleDeriv>& W1 = evaluatableArg()->findW(1, context);
00227     const Set<MultipleDeriv>& WArg = evaluatableArg()->findW(order, context);
00228     const Set<MultipleDeriv>& WArgPlus = evaluatableArg()->findW(order+1, context);
00229 
00230     SUNDANCE_MSG5(verb, tab1 << "W1 = " << W1);
00231     SUNDANCE_MSG5(verb, tab1 << "WArg = " << WArg);
00232     SUNDANCE_MSG5(verb, tab1 << "WArgPlus = " << WArgPlus);
00233     Set<MultipleDeriv> Tx = applyTx(WArg, mi_);
00234     Set<MultipleDeriv> ZXx = applyZx(W1, mi_).setUnion(Xx(mi_));
00235     SUNDANCE_MSG5(verb, tab1 << "Tx(Warg) = " << Tx);
00236     SUNDANCE_MSG5(verb, tab1 << "ZXx(W1) = " << ZXx);
00237     Set<MultipleDeriv> WargPlusOslashZXx = setDivision(WArgPlus, ZXx);
00238     SUNDANCE_MSG5(verb, tab1 << "WArgPlus / ZXx = " 
00239       << WargPlusOslashZXx);
00240     rtn = WargPlusOslashZXx.setUnion(Tx); 
00241   }
00242   SUNDANCE_MSG3(verb, tabs << "W[" << order << "]=" << rtn);
00243   SUNDANCE_MSG3(verb, tabs << "done with DiffOp::internalFindW(" << order << ") for "
00244     << toString());
00245 
00246   return rtn;
00247 }
00248 
00249 
00250 Set<MultipleDeriv> DiffOp::internalFindV(int order, const EvalContext& context) const
00251 {
00252   Tabs tabs(0);
00253   int verb = context.setupVerbosity();
00254   SUNDANCE_MSG2(verb, tabs << "DiffOp::internalFindV(" << order << ") for " 
00255     << toString());
00256 
00257   Set<MultipleDeriv> rtn;
00258   
00259   if (order <= 2)
00260   {
00261     Tabs tab1;
00262     const Set<MultipleDeriv>& W1 = evaluatableArg()->findW(1, context);
00263     const Set<MultipleDeriv>& VArg = evaluatableArg()->findV(order, context);
00264     const Set<MultipleDeriv>& VArgPlus 
00265       = evaluatableArg()->findV(order+1, context);
00266     const Set<MultipleDeriv>& WArg = evaluatableArg()->findW(order, context);
00267     const Set<MultipleDeriv>& WArgPlus 
00268       = evaluatableArg()->findW(order+1, context);
00269 
00270     SUNDANCE_MSG5(verb, tab1 << "W1=" << W1);
00271     SUNDANCE_MSG5(verb, tab1 << "VArg=" << VArg);
00272     SUNDANCE_MSG5(verb, tab1 << "VArgPlus=" << VArgPlus);
00273     SUNDANCE_MSG5(verb, tab1 << "WArg=" << WArg);
00274     SUNDANCE_MSG5(verb, tab1 << "WArgPlus=" << WArgPlus);
00275 
00276     Set<MultipleDeriv> Tx = applyTx(VArg, mi_);
00277     Set<MultipleDeriv> Zx = applyZx(W1, mi_);
00278     SUNDANCE_MSG5(verb, tab1 << "Tx(Varg) = " << Tx);
00279     SUNDANCE_MSG5(verb, tab1 << "Zx(W1) = " << Zx);
00280     Set<MultipleDeriv> WargPlusOslashZx = setDivision(WArgPlus, Zx);
00281     Set<MultipleDeriv> VargPlusOslashXx = setDivision(VArgPlus, Xx(mi_));
00282     SUNDANCE_MSG5(verb, tab1 << "WArgPlus / Z_alpha = " 
00283       << WargPlusOslashZx);
00284     SUNDANCE_MSG5(verb, tab1 << "VArgPlus / X_alpha = " 
00285       << VargPlusOslashXx);
00286     rtn = WargPlusOslashZx.setUnion(VargPlusOslashXx).setUnion(Tx); 
00287    
00288     SUNDANCE_MSG5(verb, tab1 << "WArgPlus/Z union VArgPlus/X union T =" << rtn);
00289     rtn = rtn.intersection(findR(order, context));
00290   }
00291 
00292   SUNDANCE_MSG2(verb, tabs << "V[" << order << "]=" << rtn);
00293   SUNDANCE_MSG2(verb, tabs << "done with DiffOp::internalFindV(" << order << ") for "
00294     << toString());
00295 
00296   return rtn;
00297 }
00298 
00299 
00300 Set<MultipleDeriv> DiffOp::internalFindC(int order, const EvalContext& context) const
00301 {
00302   Tabs tabs(0);
00303   int verb = context.setupVerbosity();
00304   SUNDANCE_MSG2(verb, tabs << "DiffOp::internalFindC() for " 
00305     << toString());
00306   Set<MultipleDeriv> rtn ;
00307 
00308   {
00309     Tabs tab1;
00310     SUNDANCE_MSG5(verb, tab1 << "finding R");
00311     const Set<MultipleDeriv>& R = findR(order, context);
00312     SUNDANCE_MSG5(verb, tab1 << "finding V");
00313     const Set<MultipleDeriv>& V = findV(order, context);
00314     /** Call findC() to ensure that the argument has C tabulated */
00315     evaluatableArg()->findC(order, context);
00316 
00317     SUNDANCE_MSG5(verb, tab1 << "R=" << R);
00318     SUNDANCE_MSG5(verb, tab1 << "V=" << V);
00319     rtn = R.setDifference(V);
00320     SUNDANCE_MSG3(verb, tabs << "C[" << order << "]=" << rtn);
00321   }
00322 
00323   SUNDANCE_MSG2(verb, tabs << "C[" << order << "]=R\\V = " << rtn);
00324   SUNDANCE_MSG2(verb, tabs << "done with DiffOp::internalFindC for "
00325     << toString());
00326   return rtn;
00327 }
00328 
00329 
00330 
00331 
00332 bool DiffOp::lessThan(const ScalarExpr* other) const
00333 {
00334   const DiffOp* d = dynamic_cast<const DiffOp*>(other);
00335   TEUCHOS_TEST_FOR_EXCEPTION(d==0, std::logic_error, "cast should never fail at this point");
00336   
00337   if (myCoordDeriv_ < d->myCoordDeriv_) return true;
00338   if (d->myCoordDeriv_ < myCoordDeriv_) return false;
00339   
00340   return ExprWithChildren::lessThan(other);
00341 }
00342 

Site Contact