00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
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 ) 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
00196
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
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
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