Set<MultipleDeriv> DiffOp::internalFindW(int order, const EvalContext& context) const { Tabs tabs(0); int verb = context.setupVerbosity(); SUNDANCE_MSG2(verb, tabs << "DiffOp::internalFindW(order=" << order << ") for " << toString()); Set<MultipleDeriv> rtn ; if (order <= 2) { Tabs tab1; const Set<MultipleDeriv>& W1 = evaluatableArg()->findW(1, context); const Set<MultipleDeriv>& WArg = evaluatableArg()->findW(order, context); const Set<MultipleDeriv>& WArgPlus = evaluatableArg()->findW(order+1, context); SUNDANCE_MSG5(verb, tab1 << "W1 = " << W1); SUNDANCE_MSG5(verb, tab1 << "WArg = " << WArg); SUNDANCE_MSG5(verb, tab1 << "WArgPlus = " << WArgPlus); Set<MultipleDeriv> Tx = applyTx(WArg, mi_); Set<MultipleDeriv> ZXx = applyZx(W1, mi_).setUnion(Xx(mi_)); SUNDANCE_MSG5(verb, tab1 << "Tx(Warg) = " << Tx); SUNDANCE_MSG5(verb, tab1 << "ZXx(W1) = " << ZXx); Set<MultipleDeriv> WargPlusOslashZXx = setDivision(WArgPlus, ZXx); SUNDANCE_MSG5(verb, tab1 << "WArgPlus / ZXx = " << WargPlusOslashZXx); rtn = WargPlusOslashZXx.setUnion(Tx); } SUNDANCE_MSG3(verb, tabs << "W[" << order << "]=" << rtn); SUNDANCE_MSG3(verb, tabs << "done with DiffOp::internalFindW(" << order << ") for " << toString()); return rtn; }
Set<MultipleDeriv> ExplicitFunctionalDerivativeElement ::internalFindC(int order, const EvalContext& context) const { Tabs tabs(0); int verb = context.setupVerbosity(); SUNDANCE_MSG2(verb, tabs << "ExplicitFunctionalDerivativeElement::internalFindC() for " << toString()); Set<MultipleDeriv> rtn ; if (order < 3) { Tabs tab1; SUNDANCE_MSG5(verb, tab1 << "finding R"); const Set<MultipleDeriv>& R = findR(order, context); SUNDANCE_MSG5(verb, tab1 << "R=" << R); SUNDANCE_MSG5(verb, tab1 << "finding C for arg"); const Set<MultipleDeriv>& argC = evaluatableArg()->findC(order+1, context); SUNDANCE_MSG5(verb, tab1 << "argC=" << argC); MultipleDeriv me(fd_); Set<MultipleDeriv> tmp = setDivision(argC, makeSet(me)); rtn = tmp.intersection(R); } SUNDANCE_MSG2(verb, tabs << "C[" << order << "]=" << rtn); SUNDANCE_MSG2(verb, tabs << "done with ExplicitFunctionalDerivativeElement::internalFindC for " << toString()); return rtn; }
Set<MultipleDeriv> ExplicitFunctionalDerivativeElement ::internalFindW(int order, const EvalContext& context) const { Tabs tab0(0); int verb = context.setupVerbosity(); SUNDANCE_MSG2(verb, tab0 << "ExplicitFunctionalDerivativeElement::internalFindW(order=" << order << ") for " << toString()); Set<MultipleDeriv> rtn ; if (order < 3) { Tabs tab1; const Set<MultipleDeriv>& WArgPlus = evaluatableArg()->findW(order+1, context); SUNDANCE_MSG5(verb, tab1 << "WArgPlus = " << WArgPlus); MultipleDeriv me(fd_); Set<MultipleDeriv> WargPlusOslashFD = setDivision(WArgPlus, makeSet(me)); SUNDANCE_MSG5(verb, tab1 << "WArgPlus / fd = " << WargPlusOslashFD); rtn = WargPlusOslashFD; } SUNDANCE_MSG2(verb, tab0 << "W[" << order << "]=" << rtn); SUNDANCE_MSG2(verb, tab0 << "done with ExplicitFunctionalDerivativeElement::internalFindW(" << order << ") for " << toString()); return rtn; }
Set<MultipleDeriv> DiffOp::internalFindC(int order, const EvalContext& context) const { Tabs tabs(0); int verb = context.setupVerbosity(); SUNDANCE_MSG2(verb, tabs << "DiffOp::internalFindC() for " << toString()); Set<MultipleDeriv> rtn ; { Tabs tab1; SUNDANCE_MSG5(verb, tab1 << "finding R"); const Set<MultipleDeriv>& R = findR(order, context); SUNDANCE_MSG5(verb, tab1 << "finding V"); const Set<MultipleDeriv>& V = findV(order, context); /** Call findC() to ensure that the argument has C tabulated */ evaluatableArg()->findC(order, context); SUNDANCE_MSG5(verb, tab1 << "R=" << R); SUNDANCE_MSG5(verb, tab1 << "V=" << V); rtn = R.setDifference(V); SUNDANCE_MSG3(verb, tabs << "C[" << order << "]=" << rtn); } SUNDANCE_MSG2(verb, tabs << "C[" << order << "]=R\\V = " << rtn); SUNDANCE_MSG2(verb, tabs << "done with DiffOp::internalFindC for " << toString()); return rtn; }
void DiffOp::requestMultiIndexAtEvalPoint(const MultiIndex& mi, const MultipleDeriv& u, const EvalContext& context) const { int verb = context.setupVerbosity(); Tabs tab0(0); SUNDANCE_MSG3(verb, tab0 << "DiffOp::requestMultiIndexAtEvalPoint() for=" << toString()); TEUCHOS_TEST_FOR_EXCEPT(u.size() != 1); const Deriv& d = *(u.begin()); if (d.isFunctionalDeriv()) { const SpatialDerivSpecifier& sds = d.opOnFunc(); TEUCHOS_TEST_FOR_EXCEPTION(sds.isDivergence(), std::logic_error, "divergence operators not possible within DiffOp"); TEUCHOS_TEST_FOR_EXCEPTION(sds.isNormal(), std::logic_error, "normal deriv operators not possible within DiffOp"); const MultiIndex& newMi = sds.mi(); const SymbolicFuncElement* sfe = d.symbFuncElem(); TEUCHOS_TEST_FOR_EXCEPT(sfe == 0); const EvaluatableExpr* evalPt = sfe->evalPt(); const ZeroExpr* z = dynamic_cast<const ZeroExpr*>(evalPt); if (z != 0) return; const DiscreteFuncElement* df = dynamic_cast<const DiscreteFuncElement*>(evalPt); df->addMultiIndex(newMi); df->findW(1, context); df->findV(1, context); df->findC(1, context); } }
Set<MultiSet<int> > ProductExpr::internalFindQ_V(int order, const EvalContext& context) const { Tabs tab0(0); int verb = context.setupVerbosity(); SUNDANCE_MSG2(verb, tab0 << "ProdExpr::internalFindQ_V(" << order << ")"); Set<MultiSet<int> > rtn; if (order > 1) return rtn; const Set<MultipleDeriv>& vLeft = leftEvaluatable()->findV(0, context); const Set<MultipleDeriv>& vRight = rightEvaluatable()->findV(0, context); if (order==0) { if (vLeft.size() > 0) { rtn.put(makeMultiSet<int>(0)); } if (vRight.size() > 0) { rtn.put(makeMultiSet<int>(1)); } } if (order==1) { if (vLeft.size() > 0) rtn.put(makeMultiSet<int>(1)); if (vRight.size() > 0) rtn.put(makeMultiSet<int>(0)); } SUNDANCE_MSG2(verb, tab0 << "Q_V[" << order << "]=" << rtn); return rtn; }
Set<MultipleDeriv> ConstantExpr::internalFindC(int order, const EvalContext& context) const { Tabs tab; SUNDANCE_MSG2(context.setupVerbosity(), tab << "ConstantExpr::internalFindC is forwarding to findR()"); return findR(order, context); }
Set<MultipleDeriv> ConstantExpr::internalFindV(int order, const EvalContext& context) const { Set<MultipleDeriv> rtn; Tabs tab; SUNDANCE_MSG2(context.setupVerbosity(), tab << "ConstantExpr::internalFindV is a no-op"); return rtn; }
Set<MultipleDeriv> UnknownParameterElement::internalFindV(int order, const EvalContext& context) const { Tabs tab; SUNDANCE_MSG2(context.setupVerbosity(), tab << "UPE::internalFindV is a no-op"); Set<MultipleDeriv> rtn; return rtn; }
Set<MultipleDeriv> ZeroExpr::internalFindC(int order, const EvalContext& context) const { Set<MultipleDeriv> rtn; Tabs tab; SUNDANCE_MSG2(context.setupVerbosity(), tab << "ZeroExpr::internalFindC found" << rtn << " for order=" << order); return rtn; }
RCP<Array<Set<MultipleDeriv> > > ExplicitFunctionalDerivativeElement ::internalDetermineR(const EvalContext& context, const Array<Set<MultipleDeriv> >& RInput) const { Tabs tab0(0); int verb = context.setupVerbosity(); SUNDANCE_MSG2(verb, tab0 << "ExplicitFunctionalDerivativeElement::internalDetermineR for=" << toString()); SUNDANCE_MSG2(verb, tab0 << "RInput = " << RInput ); RCP<Array<Set<MultipleDeriv> > > rtn = rcp(new Array<Set<MultipleDeriv> >(RInput.size())); { Tabs tab1; for (int i=0; i<RInput.size(); i++) { Tabs tab2; const Set<MultipleDeriv>& Wi = findW(i, context); SUNDANCE_MSG5(verb, tab2 << "W[" << i << "] = " << Wi ); (*rtn)[i] = RInput[i].intersection(Wi); } Array<Set<MultipleDeriv> > RArg(RInput.size()+1); MultipleDeriv me(fd_); for (int order=1; order<=RInput.size(); order++) { Tabs tab2; SUNDANCE_MSG3(verb, tab2 << "order = " << order); if (RInput[order-1].size() == 0) continue; const Set<MultipleDeriv>& WArg = evaluatableArg()->findW(order, context); const Set<MultipleDeriv>& RMinus = (*rtn)[order-1]; SUNDANCE_MSG3(verb, tab2 << "RInput = " << RInput[order-1]); SUNDANCE_MSG3(verb, tab2 << "FD times RInput = " << setProduct(RMinus, makeSet(me))); RArg[order].merge(setProduct(RMinus, makeSet(me)).intersection(WArg)); } SUNDANCE_MSG3(verb, tab1 << "RArg = " << RArg); SUNDANCE_MSG3(verb, tab1 << "calling determineR() for arg " << evaluatableArg()->toString()); evaluatableArg()->determineR(context, RArg); } printR(verb, rtn); SUNDANCE_MSG2(verb, tab0 << "done with ExplicitFunctionalDerivativeElement::internalDetermineR for " << toString()); /* all done */ return rtn; }
Set<MultipleDeriv> ConstantExpr::internalFindW(int order, const EvalContext& context) const { Set<MultipleDeriv> rtn; if (order==0) rtn.put(MultipleDeriv()); Tabs tab; SUNDANCE_MSG2(context.setupVerbosity(), tab << "ConstantExpr::internalFindW found" << rtn << " for order=" << order); return rtn; }
RCP<SparsitySuperset> EvaluatableExpr::sparsitySuperset(const EvalContext& context) const { Tabs tab; SUNDANCE_MSG2(context.setupVerbosity(), tab << "getting sparsity superset for " << toString()); RCP<SparsitySuperset> rtn; if (sparsity_.containsKey(context)) { Tabs tab1; SUNDANCE_MSG2(context.setupVerbosity(), tab1 << "reusing previously computed data..."); rtn = sparsity_.get(context); } else { Tabs tab1; SUNDANCE_MSG2(context.setupVerbosity(), tab1 << "computing from scratch..."); const Set<MultipleDeriv>& R = findR(context); const Set<MultipleDeriv>& C = findC(context); const Set<MultipleDeriv>& V = findV(context); if (context.setupVerbosity() > 4) { Out::os() << tab1 << "R=" << R << endl; Out::os() << tab1 << "C=" << C << endl; Out::os() << tab1 << "V=" << V << endl; } rtn = rcp(new SparsitySuperset(C.intersection(R), V.intersection(R))); sparsity_.put(context, rtn); } return rtn; }
Set<MultipleDeriv> DiffOp::internalFindV(int order, const EvalContext& context) const { Tabs tabs(0); int verb = context.setupVerbosity(); SUNDANCE_MSG2(verb, tabs << "DiffOp::internalFindV(" << order << ") for " << toString()); Set<MultipleDeriv> rtn; if (order <= 2) { Tabs tab1; const Set<MultipleDeriv>& W1 = evaluatableArg()->findW(1, context); const Set<MultipleDeriv>& VArg = evaluatableArg()->findV(order, context); const Set<MultipleDeriv>& VArgPlus = evaluatableArg()->findV(order+1, context); const Set<MultipleDeriv>& WArg = evaluatableArg()->findW(order, context); const Set<MultipleDeriv>& WArgPlus = evaluatableArg()->findW(order+1, context); SUNDANCE_MSG5(verb, tab1 << "W1=" << W1); SUNDANCE_MSG5(verb, tab1 << "VArg=" << VArg); SUNDANCE_MSG5(verb, tab1 << "VArgPlus=" << VArgPlus); SUNDANCE_MSG5(verb, tab1 << "WArg=" << WArg); SUNDANCE_MSG5(verb, tab1 << "WArgPlus=" << WArgPlus); Set<MultipleDeriv> Tx = applyTx(VArg, mi_); Set<MultipleDeriv> Zx = applyZx(W1, mi_); SUNDANCE_MSG5(verb, tab1 << "Tx(Varg) = " << Tx); SUNDANCE_MSG5(verb, tab1 << "Zx(W1) = " << Zx); Set<MultipleDeriv> WargPlusOslashZx = setDivision(WArgPlus, Zx); Set<MultipleDeriv> VargPlusOslashXx = setDivision(VArgPlus, Xx(mi_)); SUNDANCE_MSG5(verb, tab1 << "WArgPlus / Z_alpha = " << WargPlusOslashZx); SUNDANCE_MSG5(verb, tab1 << "VArgPlus / X_alpha = " << VargPlusOslashXx); rtn = WargPlusOslashZx.setUnion(VargPlusOslashXx).setUnion(Tx); SUNDANCE_MSG5(verb, tab1 << "WArgPlus/Z union VArgPlus/X union T =" << rtn); rtn = rtn.intersection(findR(order, context)); } SUNDANCE_MSG2(verb, tabs << "V[" << order << "]=" << rtn); SUNDANCE_MSG2(verb, tabs << "done with DiffOp::internalFindV(" << order << ") for " << toString()); return rtn; }
Set<MultiSet<int> > ProductExpr::internalFindQ_W(int order, const EvalContext& context) const { Tabs tab0(0); int verb = context.setupVerbosity(); SUNDANCE_MSG2(verb, tab0 << "ProdExpr::internalFindQ_W(" << order << ")"); Set<MultiSet<int> > rtn; if (order > 2) return rtn; if (order==2) { rtn.put(makeMultiSet<int>(0,1)); return rtn; } Tabs tab1; SUNDANCE_MSG3(verb, tab1 << "calling findW(0) for left"); const Set<MultipleDeriv>& wLeft = leftEvaluatable()->findW(0, context); SUNDANCE_MSG3(verb, tab1 << "found wLeft(0)=" << wLeft); SUNDANCE_MSG3(verb, tab1 << "calling findW(0) for right"); const Set<MultipleDeriv>& wRight = rightEvaluatable()->findW(0, context); SUNDANCE_MSG3(verb, tab1 << "found wRight(0)=" << wRight); if (order==0) { if (wLeft.size() > 0) { rtn.put(makeMultiSet<int>(0)); } if (wRight.size() > 0) { rtn.put(makeMultiSet<int>(1)); } } if (order==1) { if (wLeft.size() > 0) rtn.put(makeMultiSet<int>(1)); if (wRight.size() > 0) rtn.put(makeMultiSet<int>(0)); } SUNDANCE_MSG2(verb, tab0 << "Q_W[" << order << "]=" << rtn); return rtn; }
Set<MultipleDeriv> UnknownParameterElement::internalFindW(int order, const EvalContext& context) const { Tabs tab; SUNDANCE_MSG2(context.setupVerbosity(), tab << "in UPE::internalFindW, order=" << order); Set<MultipleDeriv> rtn; if (order==0) { if (!evalPtIsZero()) rtn.put(MultipleDeriv()); } else if (order==1) { MultipleDeriv md = makeMultiDeriv(funcDeriv(this)); rtn.put(md); } return rtn; }
Array<Set<MultipleDeriv> > EvaluatableExpr ::computeInputR(const EvalContext& context, const Array<Set<MultiSet<int> > >& funcIDCombinations, const Array<Set<MultiIndex> >& spatialDerivs) const { int verb = context.setupVerbosity(); Tabs tabs(0); SUNDANCE_MSG2(verb, tabs << "in EE::computeInputR()"); Array<Set<MultipleDeriv> > rtn(funcIDCombinations.size()); for (int order=0; order<funcIDCombinations.size(); order++) { Tabs tabs1; SUNDANCE_MSG2(verb, tabs << "order=" << order); SUNDANCE_MSG2(verb, tabs1 << "funcID combs=" << funcIDCombinations[order]); const Set<MultipleDeriv>& W = findW(order, context); SUNDANCE_MSG2(verb, tabs1 << "W[order=" << order << "]=" << W); for (Set<MultipleDeriv>::const_iterator i=W.begin(); i!=W.end(); i++) { Tabs tab2; const MultipleDeriv& nonzeroDeriv = *i; if (nonzeroDeriv.isInRequiredSet(funcIDCombinations[order], spatialDerivs[order])) { SUNDANCE_MSG2(verb, tab2 << "md=" << nonzeroDeriv << " added to inputR"); rtn[order].put(nonzeroDeriv); } else { SUNDANCE_MSG2(verb, tab2 << "md=" << nonzeroDeriv << " not needed"); } } } SUNDANCE_MSG2(verb, tabs << "inputR=" << rtn); return rtn; }
CellDiameterExprEvaluator::CellDiameterExprEvaluator( const CellDiameterExpr* expr, const EvalContext& context) : SubtypeEvaluator<CellDiameterExpr>(expr, context), stringRep_(expr->toString()) { Tabs tabs; int verb = context.setupVerbosity(); SUNDANCE_MSG1(verb, tabs << "initializing cell diameter expr evaluator for " << expr->toString()); SUNDANCE_MSG2(verb, tabs << "return sparsity " << std::endl << *(this->sparsity)()); TEUCHOS_TEST_FOR_EXCEPTION(this->sparsity()->numDerivs() > 1, std::logic_error, "CellDiameterExprEvaluator ctor found a sparsity table " "with more than one entry. The bad sparsity table is " << *(this->sparsity)()); /* * There is only one possible entry in the nozeros table for a * cell diameter expression: a zeroth derivative. */ for (int i=0; i<this->sparsity()->numDerivs(); i++) { const MultipleDeriv& d = this->sparsity()->deriv(i); TEUCHOS_TEST_FOR_EXCEPTION(d.order()!=0, std::logic_error, "CellDiameterExprEvaluator ctor found an entry in the " "sparsity superset that is not a zeroth-order derivative. " "The bad entry is " << this->sparsity()->deriv(i) << ". The superset is " << *(this->sparsity)()); addVectorIndex(i, 0); } }
RCP<Array<Set<MultipleDeriv> > > EvaluatableExpr ::internalDetermineR(const EvalContext& context, const Array<Set<MultipleDeriv> >& RInput) const { Tabs tab0(0); int verb = context.setupVerbosity(); RCP<Array<Set<MultipleDeriv> > > rtn = rcp(new Array<Set<MultipleDeriv> >(RInput.size())); SUNDANCE_MSG2(verb, tab0 << "EE::internalDetermineR() for " << toString() ); SUNDANCE_MSG2(verb, tab0 << "RInput = " << RInput ); for (int i=0; i<RInput.size(); i++) { Tabs tab1; if (RInput[i].size()==0) continue; const Set<MultipleDeriv>& Wi = findW(i, context); SUNDANCE_MSG3(verb, tab1 << "W[" << i << "] = " << Wi ); (*rtn)[i] = RInput[i].intersection(Wi); } printR(verb, rtn); return rtn; }
Set<MultipleDeriv> ExplicitFunctionalDerivativeElement ::internalFindV(int order, const EvalContext& context) const { Tabs tabs(0); int verb = context.setupVerbosity(); SUNDANCE_MSG2(verb, tabs << "ExplicitFunctionalDerivativeElement::internalFindV(" << order << ") for " << toString()); Set<MultipleDeriv> rtn; { Tabs tab1; SUNDANCE_MSG5(verb, tab1 << "finding R"); const Set<MultipleDeriv>& R = findR(order, context); SUNDANCE_MSG5(verb, tab1 << "finding C"); const Set<MultipleDeriv>& C = findC(order, context); rtn = R.setDifference(C); } SUNDANCE_MSG2(verb, tabs << "V[" << order << "]=" << rtn); SUNDANCE_MSG2(verb, tabs << "done with ExplicitFunctionalDerivativeElement::internalFindV(" << order << ") for " << toString()); return rtn; }
RCP<Array<Set<MultipleDeriv> > > DiffOp::internalDetermineR(const EvalContext& context, const Array<Set<MultipleDeriv> >& RInput) const { Tabs tab0(0); int verb = context.setupVerbosity(); SUNDANCE_MSG2(verb, tab0 << "DiffOp::internalDetermineR for=" << toString()); SUNDANCE_MSG2(verb, tab0 << "RInput = " << RInput ); RCP<Array<Set<MultipleDeriv> > > rtn = rcp(new Array<Set<MultipleDeriv> >(RInput.size())); { Tabs tab1; for (int i=0; i<RInput.size(); i++) { Tabs tab2; const Set<MultipleDeriv>& Wi = findW(i, context); SUNDANCE_MSG5(verb, tab2 << "W[" << i << "] = " << Wi ); (*rtn)[i] = RInput[i].intersection(Wi); } const Set<MultipleDeriv>& W1 = evaluatableArg()->findW(1, context); SUNDANCE_MSG3(verb, tab1 << "arg W1 = " << W1); Set<MultipleDeriv> ZxXx = applyZx(W1, mi_).setUnion(Xx(mi_)); SUNDANCE_MSG3(verb, tab1 << "Z union X = " << ZxXx); Array<Set<MultipleDeriv> > RArg(RInput.size()+1); RArg[0].put(MultipleDeriv()); RArg[1].put(MultipleDeriv(coordDeriv(mi_.firstOrderDirection()))); for (int order=0; order<RInput.size(); order++) { Tabs tab2; const Set<MultipleDeriv>& WArgPlus = evaluatableArg()->findW(order+1, context); const Set<MultipleDeriv>& WArg = evaluatableArg()->findW(order, context); SUNDANCE_MSG3(verb, tab2 << "order = " << order); SUNDANCE_MSG3(verb, tab2 << "RInput = " << RInput[order]); SUNDANCE_MSG3(verb, tab2 << "WArg = " << WArg); SUNDANCE_MSG3(verb, tab2 << "WArgPlus = " << WArgPlus); SUNDANCE_MSG3(verb, tab2 << "ZxXx times RInput = " << setProduct(ZxXx, RInput[order])); SUNDANCE_MSG3(verb, tab2 << "Tx(RInput, " << -mi_ << ") = " << applyTx(RInput[order], -mi_) ); RArg[order+1].merge(setProduct(ZxXx, RInput[order]).intersection(WArgPlus)); RArg[order].merge(applyTx(RInput[order], -mi_).intersection(WArg)); } SUNDANCE_MSG3(verb, tab1 << "RArg = " << RArg); SUNDANCE_MSG2(verb, tab1 << "calling determineR() for arg " << evaluatableArg()->toString()); evaluatableArg()->determineR(context, RArg); /* inform the evaluation points of all functions appearing in the argument * that we'll need their spatial derivatives in direction mi(). */ SUNDANCE_MSG3(verb, tab1 << "calling findR(1) to determine required spatial derivatives "); const Set<MultipleDeriv>& RArg1 = evaluatableArg()->findR(1, context); SUNDANCE_MSG3(verb, tab1 << "RArg1 = " << RArg1); for (Set<MultipleDeriv>::const_iterator i=RArg1.begin(); i!=RArg1.end(); i++) { requestMultiIndexAtEvalPoint(mi(), *i, context); } } printR(verb, rtn); SUNDANCE_MSG2(verb, tab0 << "done with DiffOp::internalDetermineR for " << toString()); /* all done */ return rtn; }
DerivSet SymbPreprocessor::setupVariations(const Expr& expr, const Expr& vars, const Expr& varEvalPts, const Expr& unks, const Expr& unkEvalPts, const Expr& unkParams, const Expr& unkParamEvalPts, const Expr& fixedFields, const Expr& fixedFieldEvalPts, const Expr& fixedParams, const Expr& fixedParamEvalPts, const EvalContext& context, const ComputationType& compType) { TimeMonitor t(preprocTimer()); Tabs tab; const EvaluatableExpr* e = dynamic_cast<const EvaluatableExpr*>(expr.ptr().get()); Array<Set<MultiSet<int> > > funcDerivs(3); Array<Set<MultiIndex> > spatialDerivs(3); int verb=context.setupVerbosity(); SUNDANCE_BANNER1(verb, tab, "in setupVariations()"); verbosity<EvaluatableExpr>() = verb; SUNDANCE_MSG1(verb, tab << "************ setting up variations of expr: " << expr << std::endl << tab << "context is " << context << std::endl << tab << "conp type is " << compType << std::endl << tab << "vars are " << vars << std::endl << tab << "unks are " << unks << std::endl << tab << "unk parameters " << unkParams << std::endl << tab << "fixed parameters " << fixedParams << std::endl << tab << "the eval points for the vars are " << varEvalPts << std::endl << tab << "the eval points for the unks are " << unkEvalPts << std::endl << tab << "the eval points for the unknown parameters are " << unkParamEvalPts << std::endl << tab << "the eval points for the fixed parameters are " << fixedParamEvalPts << tab << std::endl); TEUCHOS_TEST_FOR_EXCEPTION(e==0, std::logic_error, "Non-evaluatable expr " << expr.toString() << " given to SymbPreprocessor::setupExpr()"); /* make flat lists of variations, unknowns, parameters, and fixed fields */ Expr v = vars.flatten(); Expr v0 = varEvalPts.flatten(); Expr u = unks.flatten(); Expr u0 = unkEvalPts.flatten(); Expr alpha = unkParams.flatten(); Expr alpha0 = unkParamEvalPts.flatten(); Expr beta = fixedParams.flatten(); Expr beta0 = fixedParamEvalPts.flatten(); Expr f = fixedFields.flatten(); Expr f0 = fixedFieldEvalPts.flatten(); Set<int> varID = processInputFuncs<SymbolicFuncElement>(v, v0); Set<int> unkID = processInputFuncs<UnknownFuncElement>(u, u0); Set<int> fixedID = processInputFuncs<UnknownFuncElement>(f, f0); Set<int> unkParamID = processInputParams<UnknownParameterElement>(alpha, alpha0); Set<int> fixedParamID = processInputParams<UnknownParameterElement>(beta, beta0); /* put together the set of functions that are active differentiation * variables */ SUNDANCE_MSG2(verb, tab << "forming active set"); Array<Sundance::Set<MultiSet<int> > > activeFuncIDs(3); if (context.needsDerivOrder(0)) activeFuncIDs[0].put(MultiSet<int>()); if (context.topLevelDiffOrder() >= 1) { for (Set<int>::const_iterator i=varID.begin(); i != varID.end(); i++) { if (context.needsDerivOrder(1)) activeFuncIDs[1].put(makeMultiSet<int>(*i)); if (context.topLevelDiffOrder()==2) { for (Set<int>::const_iterator j=unkID.begin(); j != unkID.end(); j++) { activeFuncIDs[2].put(makeMultiSet<int>(*i, *j)); } if (compType==MatrixAndVector) { for (Set<int>::const_iterator j=unkParamID.begin(); j != unkParamID.end(); j++) { activeFuncIDs[2].put(makeMultiSet<int>(*i, *j)); } } else if (compType==Sensitivities) { for (Set<int>::const_iterator j=fixedParamID.begin(); j != fixedParamID.end(); j++) { activeFuncIDs[2].put(makeMultiSet<int>(*i, *j)); } } } } } SUNDANCE_MSG1(verb, tab << std::endl << tab << " ************* Finding nonzeros for expr " << std::endl << tab); for (int i=0; i<=context.topLevelDiffOrder(); i++) { Tabs tab2; SUNDANCE_MSG4(verb, tab2 << "diff order=" << i << ", active funcs=" << activeFuncIDs[i]); } Set<MultiIndex> miSet; miSet.put(MultiIndex()); e->registerSpatialDerivs(context, miSet); SUNDANCE_MSG2(verb, tab << std::endl << tab << " ************* finding required functions" << std::endl << tab); SUNDANCE_MSG2(verb, tab << "activeFuncIDs are = " << activeFuncIDs); SUNDANCE_MSG2(verb, tab << "spatial derivs are = " << spatialDerivs); Array<Set<MultipleDeriv> > RInput = e->computeInputR(context, activeFuncIDs, spatialDerivs); SUNDANCE_MSG3(verb, tab << std::endl << tab << " ************* Top-level required funcs are " << RInput << std::endl << tab); SUNDANCE_MSG2(verb, tab << std::endl << tab << " ************* Calling determineR()" << std::endl << tab); e->determineR(context, RInput); SUNDANCE_MSG1(verb, tab << std::endl << tab << " ************* Finding sparsity structure " << std::endl << tab); DerivSet derivs = e->sparsitySuperset(context)->derivSet(); SUNDANCE_MSG1(verb, tab << std::endl << tab << "Nonzero deriv set = " << derivs); SUNDANCE_MSG1(verb, tab << std::endl << tab << " ************* Setting up evaluators for expr " << std::endl << tab); int saveVerb = context.setupVerbosity(); context.setSetupVerbosity(0); e->setupEval(context); if (verb>1) { SUNDANCE_MSG1(verb, tab << std::endl << tab << " ************* Nonzeros are:"); e->displayNonzeros(Out::os(), context); } context.setSetupVerbosity(saveVerb); return derivs; }
DiffOpEvaluator ::DiffOpEvaluator(const DiffOp* expr, const EvalContext& context) : UnaryEvaluator<DiffOp>(expr, context), isConstant_(this->sparsity()->numDerivs()), resultIndices_(this->sparsity()->numDerivs()), constantMonomials_(this->sparsity()->numDerivs()), vectorMonomials_(this->sparsity()->numDerivs()), constantFuncCoeffs_(this->sparsity()->numDerivs()), vectorFuncCoeffs_(this->sparsity()->numDerivs()), funcEvaluators_(), constantCoeffFuncIndices_(this->sparsity()->numDerivs()), constantCoeffFuncMi_(this->sparsity()->numDerivs()), vectorCoeffFuncIndices_(this->sparsity()->numDerivs()), vectorCoeffFuncMi_(this->sparsity()->numDerivs()) { int verb = context.setupVerbosity(); Tabs tabs; SUNDANCE_MSG1(verb, tabs << "initializing diff op evaluator for " << expr->toString()); { Tabs tab0; SUNDANCE_MSG2(verb, tab0 << "return sparsity " << std::endl << *(this->sparsity)()); SUNDANCE_MSG2(verb, tab0 << "argument sparsity subset " << std::endl << *(argSparsitySuperset())); Map<const DiscreteFuncElementEvaluator*, int> funcToIndexMap; int vecResultIndex = 0; int constResultIndex = 0; for (int i=0; i<this->sparsity()->numDerivs(); i++) { Tabs tab1; const MultipleDeriv& resultDeriv = this->sparsity()->deriv(i); SUNDANCE_MSG3(verb, tab0 << "working out procedure for computing " << resultDeriv); if (this->sparsity()->state(i)==ConstantDeriv) { Tabs tab2; addConstantIndex(i, constResultIndex); resultIndices_[i] = constResultIndex++; isConstant_[i] = true; SUNDANCE_MSG3(verb, tab2 << "deriv is constant, will be stored at index " << resultIndices_[i] << " in the const result array"); } else { Tabs tab2; addVectorIndex(i, vecResultIndex); resultIndices_[i] = vecResultIndex++; isConstant_[i] = false; SUNDANCE_MSG3(verb, tab2 << "deriv is variable, will be stored at index " << resultIndices_[i] << " in the var result array"); } int order = resultDeriv.order(); const Set<MultipleDeriv>& RArg = argExpr()->findR(order, context); const Set<MultipleDeriv>& RArgPlus = argExpr()->findR(order+1, context); const Set<MultipleDeriv>& W1Arg = argExpr()->findW(1, context); SUNDANCE_MSG3(verb, tab1 << "RArg = " << RArg); SUNDANCE_MSG3(verb, tab1 << "RArgPlus = " << RArgPlus); SUNDANCE_MSG3(verb, tab1 << "W1Arg = " << W1Arg); Set<MultipleDeriv> funcTermCoeffs = RArgPlus.intersection(increasedDerivs(resultDeriv, W1Arg, verb)); SUNDANCE_MSG3(verb, tab1 << "function term coeffs = " << funcTermCoeffs); if (funcTermCoeffs.size()==0) { SUNDANCE_MSG3(verb, tab1 << "no direct chain rule terms"); } else { SUNDANCE_MSG3(verb, tab1 << "getting direct chain rule terms"); } for (Set<MultipleDeriv>::const_iterator j=funcTermCoeffs.begin(); j != funcTermCoeffs.end(); j++) { Tabs tab2; SUNDANCE_MSG3(verb, tab2 << "getting coefficient of " << *j); int argIndex = argSparsitySuperset()->getIndex(*j); TEUCHOS_TEST_FOR_EXCEPTION(argIndex==-1, std::runtime_error, "Derivative " << *j << " expected in argument " "but not found"); Deriv lambda = remainder(*j, resultDeriv, verb); if (lambda.isCoordDeriv()) { Tabs tab3; SUNDANCE_MSG3(verb, tab2 << "detected coordinate deriv"); if (lambda.coordDerivDir()!=expr->mi().firstOrderDirection()) { SUNDANCE_MSG3(verb, tab2 << "direction mismatch, skipping"); continue; } const DerivState& argState = argSparsitySuperset()->state(argIndex); if (argState==ConstantDeriv) { int constArgIndex = argEval()->constantIndexMap().get(argIndex); constantMonomials_[i].append(constArgIndex); } else { int vectorArgIndex = argEval()->vectorIndexMap().get(argIndex); vectorMonomials_[i].append(vectorArgIndex); } } else if (lambda.opOnFunc().isPartial() || lambda.opOnFunc().isIdentity()) { Tabs tab3; SUNDANCE_MSG3(verb, tab3 << "detected functional deriv " << lambda); const SymbolicFuncElement* f = lambda.symbFuncElem(); const MultiIndex& mi = expr->mi() + lambda.opOnFunc().mi(); SUNDANCE_MSG3(verb, tab3 << "modified multiIndex is " << mi); const TestFuncElement* t = dynamic_cast<const TestFuncElement*>(f); if (t != 0) continue; const UnknownFuncElement* u = dynamic_cast<const UnknownFuncElement*>(f); TEUCHOS_TEST_FOR_EXCEPTION(u==0, std::logic_error, "Non-unknown function detected where an unknown " "function was expected in " "DiffOpEvaluator ctor"); const EvaluatableExpr* evalPt = u->evalPt(); const ZeroExpr* z = dynamic_cast<const ZeroExpr*>(evalPt); if (z != 0) continue; TEUCHOS_TEST_FOR_EXCEPTION(z != 0, std::logic_error, "DiffOpEvaluator detected identically zero " "function"); const DiscreteFuncElement* df = dynamic_cast<const DiscreteFuncElement*>(evalPt); TEUCHOS_TEST_FOR_EXCEPTION(df==0, std::logic_error, "DiffOpEvaluator ctor: evaluation point of " "unknown function " << u->toString() << " is not a discrete function"); const SymbolicFuncElementEvaluator* uEval = dynamic_cast<const SymbolicFuncElementEvaluator*>(u->evaluator(context).get()); const DiscreteFuncElementEvaluator* dfEval = uEval->dfEval(); TEUCHOS_TEST_FOR_EXCEPTION(dfEval==0, std::logic_error, "DiffOpEvaluator ctor: evaluator for " "evaluation point is not a " "DiscreteFuncElementEvaluator"); TEUCHOS_TEST_FOR_EXCEPTION(!dfEval->hasMultiIndex(mi), std::logic_error, "DiffOpEvaluator ctor: evaluator for " "discrete function " << df->toString() << " does not know about multiindex " << mi.toString()); int fIndex; int miIndex = dfEval->miIndex(mi); if (funcToIndexMap.containsKey(dfEval)) { fIndex = funcToIndexMap.get(dfEval); } else { fIndex = funcEvaluators_.size(); funcEvaluators_.append(dfEval); funcToIndexMap.put(dfEval, fIndex); } const DerivState& argState = argSparsitySuperset()->state(argIndex); if (argState==ConstantDeriv) { int constArgIndex = argEval()->constantIndexMap().get(argIndex); constantCoeffFuncIndices_[i].append(fIndex); constantCoeffFuncMi_[i].append(miIndex); constantFuncCoeffs_[i].append(constArgIndex); } else { int vectorArgIndex = argEval()->vectorIndexMap().get(argIndex); vectorCoeffFuncIndices_[i].append(fIndex); vectorCoeffFuncMi_[i].append(miIndex); vectorFuncCoeffs_[i].append(vectorArgIndex); } } else { TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "DiffOpEvaluator has been asked to preprocess a Deriv that " "is not a simple partial derivative. The problem child is: " << lambda); } } Set<MultipleDeriv> isolatedTerms = RArg.intersection(backedDerivs(resultDeriv, W1Arg, verb)); if (isolatedTerms.size()==0) { SUNDANCE_MSG3(verb, tab1 << "no indirect chain rule terms"); } else { SUNDANCE_MSG3(verb, tab1 << "getting indirect chain rule terms"); SUNDANCE_MSG3(verb, tab1 << "isolated terms = " << isolatedTerms); } for (Set<MultipleDeriv>::const_iterator j=isolatedTerms.begin(); j != isolatedTerms.end(); j++) { int argIndex = argSparsitySuperset()->getIndex(*j); TEUCHOS_TEST_FOR_EXCEPTION(argIndex==-1, std::runtime_error, "Derivative " << *j << " expected in argument " "but not found"); const DerivState& argState = argSparsitySuperset()->state(argIndex); if (argState==ConstantDeriv) { int constArgIndex = argEval()->constantIndexMap().get(argIndex); constantMonomials_[i].append(constArgIndex); } else { int vectorArgIndex = argEval()->vectorIndexMap().get(argIndex); vectorMonomials_[i].append(vectorArgIndex); } } } } if (verb > 2) { Out::os() << tabs << "instruction tables for summing spatial/functional chain rule" << std::endl; for (int i=0; i<this->sparsity()->numDerivs(); i++) { Tabs tab1; Out::os() << tab1 << "deriv " << sparsity()->deriv(i) << std::endl; { Tabs tab2; Out::os() << tab2 << "constant monomials: " << constantMonomials_[i] << std::endl; Out::os() << tab2 << "vector monomials: " << vectorMonomials_[i] << std::endl; Out::os() << tab2 << "constant coeff functions: " << std::endl; for (int j=0; j<constantFuncCoeffs_[i].size(); j++) { Tabs tab3; Out::os() << tab3 << "func=" << constantCoeffFuncIndices_[i][j] << " mi=" << constantCoeffFuncMi_[i][j] << std::endl; } Out::os() << tab2 << "vector coeff functions: " << std::endl; for (int j=0; j<vectorFuncCoeffs_[i].size(); j++) { Tabs tab3; Out::os() << tab3 << "func=" << vectorCoeffFuncIndices_[i][j] << " mi=" << vectorCoeffFuncMi_[i][j] << std::endl; } } } } }
CoordExprEvaluator::CoordExprEvaluator(const CoordExpr* expr, const EvalContext& context) : SubtypeEvaluator<CoordExpr>(expr, context), doValue_(false), doDeriv_(false), stringRep_(expr->toString()) { int verb = context.setupVerbosity(); Tabs tabs; SUNDANCE_MSG1(verb, tabs << "initializing coord expr evaluator for " << expr->toString()); SUNDANCE_MSG2(verb, tabs << "return sparsity " << std::endl << tabs << *(this->sparsity)()); TEUCHOS_TEST_FOR_EXCEPTION(this->sparsity()->numDerivs() > 2, std::logic_error, "CoordExprEvaluator ctor found a sparsity table " "with more than two entries. The bad sparsity table is " << *(this->sparsity)()); /* * There are only two possible entries in the nozeros table for a * coordinate expression: a zeroth derivative, and a first-order * spatial derivative in the same direction as the expr's coordinate. */ for (int i=0; i<this->sparsity()->numDerivs(); i++) { const MultipleDeriv& d = this->sparsity()->deriv(i); /* for a zeroth-order derivative, evaluate the coord expr */ if (d.order()==0) { doValue_ = true; addVectorIndex(i, 0); } else /* for a first-order deriv, make sure it's in the proper direction, * then evaluate the spatial derivative. */ { TEUCHOS_TEST_FOR_EXCEPTION(!this->sparsity()->isSpatialDeriv(i), std::logic_error, "CoordExprEvaluator ctor found an entry in the " "sparsity superset that is not a spatial derivative. " "The bad entry is " << this->sparsity()->deriv(i) << ". The superset is " << *(this->sparsity)()); const MultiIndex& mi = this->sparsity()->multiIndex(i); TEUCHOS_TEST_FOR_EXCEPTION(mi.order() != 1, std::logic_error, "CoordExprEvaluator ctor found a multiindex of " "order != 1. Bad multiindex is " << mi.toString()); TEUCHOS_TEST_FOR_EXCEPTION(mi[expr->dir()]!=1, std::logic_error, "CoordExprEvaluator sparsity pattern has an " "element corresponding to differentiation wrt " "a coordinate direction other than that of the " "coord expr's direction"); doDeriv_ = true; addConstantIndex(i, 0); } } }