Set<MultipleDeriv> applyTx(const Set<MultipleDeriv>& s, const MultiIndex& x) { Set<MultipleDeriv> rtn; for (Set<MultipleDeriv>::const_iterator i=s.begin(); i!=s.end(); i++) { const MultipleDeriv& md = *i; for (MultipleDeriv::const_iterator j=md.begin(); j!=md.end(); j++) { const Deriv& d = *j; if (d.isFunctionalDeriv()) { const MultiIndex& mi = d.opOnFunc().mi(); MultiIndex miNew = mi+x; if (miNew.isValid()) { Deriv dNew = d.derivWrtMultiIndex(miNew); MultipleDeriv mdNew = md; mdNew.erase(mdNew.find(d)); mdNew.put(dNew); rtn.put(mdNew); } } } } return rtn; }
void SparsitySuperset::addDeriv(const Deriv& d, const DerivState& state) { MultipleDeriv md; md.put(d); addDeriv(md, state); }
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); } }
bool hasParameter(const MultipleDeriv& d) { for (MultipleDeriv::const_iterator i=d.begin(); i!=d.end(); i++) { if (i->isParameter()) return true; } return false; }
bool MultipleDeriv::containsDeriv(const MultipleDeriv& x) const { for (MultipleDeriv::const_iterator i=x.begin(); i!=x.end(); i++) { if ( count(*i) <= x.count(*i) ) return false; } return true; }
int main(int argc, char** argv) { typedef Array<OrderedPair<Array<MultiSet<int> >, Array<MultipleDeriv> > > CR; try { GlobalMPISession session(&argc, &argv); Expr u = new UnknownFunctionStub("u"); Expr v = new UnknownFunctionStub("v"); Expr w = new UnknownFunctionStub("w"); int nArgs = 2; MultipleDeriv md = makeDeriv(u,u); int order = md.order(); for (int l=1; l<=order; l++) { Array<int> s(l, nArgs); Array<Array<int> > distinctQ = indexCombinations(s); Set<MultiSet<int> > q; for (int p=0; p<distinctQ.size(); p++) { q.put(makeMultiSet(distinctQ[p])); } if (l > 1) cout << " + " << std::endl; for (Set<MultiSet<int> >::const_iterator i=q.begin(); i!=q.end(); i++) { const MultiSet<int>& lambda = *i; if (lambda != *(q.begin())) cout << " + " << std::endl; cout << "f_" << lambda << " * ["; for (int s=1; s<=md.order(); s++) { CR p = chainRuleTerms(s, lambda, md); bool firstTerm = true; for (CR::const_iterator j=p.begin(); j!=p.end(); j++) { if (!firstTerm) cout << "+"; firstTerm = false; Array<MultiSet<int> > K = j->first(); Array<MultipleDeriv> L = j->second(); write(md, K, L); } } cout << "]" << std::endl; } } } catch(std::exception& e) { Out::println(e.what()); } }
MultipleDeriv FunctionalPolynomial::successorTerm(const MultipleDeriv& md) const { MultipleDeriv rtn; unsigned int k = 0; for (MultipleDeriv::const_iterator i=md.begin(); i!=md.end(); i++, k++) { if (k < md.size()-1) rtn.put(*i); } return rtn; }
FunctionalPolynomial::FunctionalPolynomial(const RCP<ScalarExpr>& expr) : funcs_(), funcMultiIndices_(), coeffs_(), keys_() { TEUCHOS_TEST_FOR_EXCEPTION(!isConvertibleToPoly(expr.get()), std::logic_error, "FunctionalPolynomial ctor called with an argument that " "cannot be converted to a polynomial"); int funcID; MultiIndex mi; Deriv deriv; const SymbolicFuncElement* s = dynamic_cast<const SymbolicFuncElement*>(expr.get()); if (s != 0) { mi = MultiIndex(); deriv = funcDeriv(s); } const DerivOfSymbFunc* d = dynamic_cast<const DerivOfSymbFunc*>(expr.get()); if (d != 0) { deriv = d->representMeAsFunctionalDeriv(); } MultipleDeriv mu; mu.put(deriv); if (d != 0 || s != 0) { funcs_.put(funcID, expr); Set<MultiIndex> miSet; miSet.put(mi); funcMultiIndices_.put(funcID, miSet); Expr coeff = 1.0; RCP<ScalarExpr> cPtr = rcp_dynamic_cast<ScalarExpr>(coeff.ptr()); coeffs_.resize(2); keys_.resize(2); coeffs_[1].put(mu, cPtr); keys_[1].put(mu); } else { TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "impossible case in FunctionalPolynomial ctor"); } }
MultipleDeriv MultipleDeriv::factorOutDeriv(const Deriv& x) const { MultipleDeriv rtn = *this; MultipleDeriv::iterator i = rtn.find(x); /* remove a single copy of the given derivative */ if (i != rtn.end()) rtn.erase(i); if (rtn.size() == this->size()) return MultipleDeriv(); return rtn; }
MultipleDeriv MultipleDeriv::product(const MultipleDeriv& other) const { MultipleDeriv rtn; for (MultipleDeriv::const_iterator i=this->begin(); i!=this->end(); i++) { rtn.put(*i); } for (MultipleDeriv::const_iterator i=other.begin(); i!=other.end(); i++) { rtn.put(*i); } return rtn; }
Set<MultipleDeriv> EvaluatableExpr::setDivision(const Set<MultipleDeriv>& a, const Set<MultipleDeriv>& b) const { Set<MultipleDeriv> rtn; for (Set<MultipleDeriv>::const_iterator i=a.begin(); i!=a.end(); i++) { for (Set<MultipleDeriv>::const_iterator j=b.begin(); j!=b.end(); j++) { MultipleDeriv c = i->factorOutDeriv(*j); if (c.size() != 0) rtn.put(c); if (*i == *j) rtn.put(MultipleDeriv()); } } return rtn; }
void MultipleDeriv ::productRulePermutations(ProductRulePerms& perms) const { int N = order(); if (N==0) { MultipleDeriv md0; DerivPair p(md0, md0); perms.put(p, 1); return; } int p2 = pow2(N); for (int i=0; i<p2; i++) { MultipleDeriv left; MultipleDeriv right; Array<int> bits = bitsOfAnInteger(i, N); int j=0; MultipleDeriv::const_iterator iter; for (iter=this->begin(); iter != this->end(); iter++, j++) { if (bits[j]==true) { left.put(*iter); } else { right.put(*iter); } } DerivPair p(left, right); if (!perms.containsKey(p)) { perms.put(p, 1); } else { int count = perms.get(p); perms.put(p, count+1); } } }
Set<MultipleDeriv> DiffOpEvaluator ::increasedDerivs(const MultipleDeriv& mu, const Set<MultipleDeriv>& W1, int verb) const { Tabs tabs; SUNDANCE_MSG3(verb, tabs << "computing increased derivs"); Set<MultipleDeriv> rtn; for (Set<MultipleDeriv>::const_iterator i=W1.begin(); i!=W1.end(); i++) { MultipleDeriv md = *i; TEUCHOS_TEST_FOR_EXCEPT(md.order() != 1); Deriv lambda = *(md.begin()); MultipleDeriv lambdaMu = mu; lambdaMu.put(lambda); rtn.put(lambdaMu); } SUNDANCE_MSG3(verb, tabs << "increased derivs = " << rtn); return rtn; }
int factorial(const MultipleDeriv& ms) { Sundance::Map<Deriv, int> counts; for (MultipleDeriv::const_iterator i=ms.begin(); i!=ms.end(); i++) { if (counts.containsKey(*i)) counts[*i]++; else counts.put(*i, 1); } int rtn = 1; for (Sundance::Map<Deriv, int>::const_iterator i=counts.begin(); i!=counts.end(); i++) { int f = 1; for (int j=1; j<=i->second; j++) f *= j; rtn *= f; } return rtn; }
Set<Deriv> FunctionalPolynomial ::findFuncsForSummation(const Set<MultipleDeriv>& prevSet, const MultipleDeriv& currentDeriv) const { Set<Deriv> rtn; for (Set<MultipleDeriv>::const_iterator i = prevSet.begin(); i != prevSet.end(); i++) { const MultipleDeriv& mdPrev = *i; TEUCHOS_TEST_FOR_EXCEPTION(currentDeriv.size()+1 != mdPrev.size(), std::logic_error, "deriv orders must differ by 1. Found " "currentDeriv.size()=" << currentDeriv.size() << " while mdPrev.size()=" << mdPrev.size()); /* We are looking for cases where the previous multiple derivative * is equal to the current plus one *greater* element. In such cases, the * set difference will contain exactly one element, and that element * will be greater than or equal to the the upper bound of the current * set */ Set<Deriv> tmp; set_difference(mdPrev.begin(), mdPrev.end(), currentDeriv.begin(), currentDeriv.end(), inserter(tmp, tmp.begin())); if (tmp.size()==1) { const Deriv& d = *(tmp.begin()); if (currentDeriv.upper_bound(d) == currentDeriv.end()) rtn.put(d); } } return rtn; }
void SparsitySuperset::addDeriv(const MultipleDeriv& d, const DerivState& state) { maxOrder_ = std::max(d.order(), maxOrder_); if (containsDeriv(d)) { const DerivState& oldState = states_[getIndex(d)]; if (state > oldState) { states_[getIndex(d)] = state; numConstantDerivs_--; numVectorDerivs_++; } } else { int index = derivs_.size(); derivs_.append(d); states_.append(state); derivToIndexMap_.put(d, index); MultiIndex mi; for (MultipleDeriv::const_iterator i=d.begin(); i != d.end(); i++) { if (i->isCoordDeriv()) { MultiIndex m; int dir = i->coordDerivDir(); m[dir] = 1; mi = mi + m; } } multiIndex_.append(mi); if (state==ConstantDeriv) numConstantDerivs_++; else numVectorDerivs_++; } }
MultipleDeriv MultipleDeriv::factorOutDeriv(const MultipleDeriv& x) const { MultipleDeriv rtn = *this; for (MultipleDeriv::const_iterator i=x.begin(); i!=x.end(); i++) { MultipleDeriv::iterator j = rtn.find(*i); /* remove a single copy of the given derivative */ if (j != rtn.end()) rtn.erase(j); } if (rtn.size() == this->size()) return MultipleDeriv(); return rtn; }
Deriv DiffOpEvaluator::remainder(const MultipleDeriv& big, const MultipleDeriv& little, int verb) const { Tabs tab; SUNDANCE_MSG5(verb, tab << "computing remainder: big=" << big << ", little=" << little); TEUCHOS_TEST_FOR_EXCEPT(big.order()-little.order() != 1); MultipleDeriv r; if (little.order()==0) r = big; else r = big.factorOutDeriv(little); SUNDANCE_MSG5(verb, tab << "remainder = " << r); TEUCHOS_TEST_FOR_EXCEPT(r.order() != 1); return *(r.begin()); }
Set<MultipleDeriv> DiffOpEvaluator ::backedDerivs(const MultipleDeriv& mu, const Set<MultipleDeriv>& W1, int verb) const { Tabs tabs; SUNDANCE_MSG3(verb, tabs << "computing backed-out derivs for mu= " << mu << ", W1=" << W1); Set<MultipleDeriv> rtn; if (mu.order() != 0) { const MultiIndex& alpha = expr()->mi(); for (Set<MultipleDeriv>::const_iterator i=W1.begin(); i!=W1.end(); i++) { const MultipleDeriv& md = *i; TEUCHOS_TEST_FOR_EXCEPT(md.order() != 1); Deriv lambda = *(md.begin()); if (lambda.isCoordDeriv()) continue; TEUCHOS_TEST_FOR_EXCEPT(!lambda.isFunctionalDeriv()); FunctionIdentifier lambda_fid = lambda.fid(); const MultiIndex& lambda_mi = lambda.opOnFunc().mi(); for (MultipleDeriv::const_iterator j=mu.begin(); j!=mu.end(); j++) { const Deriv& d = *j; if (d.isCoordDeriv()) continue; FunctionIdentifier d_fid = d.fid(); const MultiIndex& d_mi = d.opOnFunc().mi(); if (d_fid != lambda_fid) continue; if (!(alpha + lambda_mi == d_mi)) continue; MultipleDeriv z = mu.factorOutDeriv(d); z.put(lambda); rtn.put(z); } } } SUNDANCE_MSG3(verb, tabs << "backed-out derivs = " << rtn); return rtn; }
EFDEEvaluator::EFDEEvaluator( const ExplicitFunctionalDerivativeElement* expr, const EvalContext& context ) : UnaryEvaluator<ExplicitFunctionalDerivativeElement>(expr, context), constValIndexToArgIndexMap_(), varValIndexToArgIndexMap_() { Tabs tabs; SUNDANCE_VERB_LOW(tabs << "initializing EFDE evaluator for " << expr->toString()); SUNDANCE_VERB_MEDIUM(tabs << "return sparsity " << std::endl << *(this->sparsity)()); /* * This evaluator requires no calculations. All that is done is to * map derivatives (md, fd) in the argument's result arrays to * derivatives (md) in this expression's result arrays. */ int vecResultIndex = 0; int constResultIndex = 0; const Deriv& fd = expr->fd(); for (int i=0; i<this->sparsity()->numDerivs(); i++) { const MultipleDeriv& d = this->sparsity()->deriv(i); const DerivState& myState = this->sparsity()->state(i); if (myState==ConstantDeriv) { Tabs tab2; SUNDANCE_VERB_HIGH(tab2 << "deriv is constant, will be stored at index " << constResultIndex << " in the const result array"); addConstantIndex(i, constResultIndex++); } else { Tabs tab2; SUNDANCE_VERB_HIGH(tab2 << "deriv is variable, will be stored at index " << vecResultIndex << " in the var result array"); addVectorIndex(i, vecResultIndex++); } MultipleDeriv dArg = d; dArg.put(fd); int argIndex = argSparsitySuperset()->getIndex(dArg); TEST_FOR_EXCEPTION(argIndex==-1, RuntimeError, "Derivative " << dArg << " expected in argument but not found"); const DerivState& argState = argSparsitySuperset()->state(argIndex); TEST_FOR_EXCEPTION(argState != myState, InternalError, "mismatched states"); if (argState==ConstantDeriv) { int constArgIndex = argEval()->constantIndexMap().get(argIndex); constValIndexToArgIndexMap_.append(constArgIndex); } else { int vectorArgIndex = argEval()->vectorIndexMap().get(argIndex); varValIndexToArgIndexMap_.append(vectorArgIndex); } } SUNDANCE_VERB_HIGH(tabs << " constant index map " << constValIndexToArgIndexMap_ << std::endl << " vector index map " << varValIndexToArgIndexMap_ ); }
void FunctionalPolynomial ::stepRecurrence(int level, const Map<MultipleDeriv, std::string>& sPrev, Map<MultipleDeriv, std::string>& sCurr) const { Set<MultipleDeriv> allKeys; Set<MultipleDeriv> inducedKeys; Set<MultipleDeriv> prevKeys; for (Map<MultipleDeriv, std::string>::const_iterator i = sPrev.begin(); i != sPrev.end(); i++) { inducedKeys.put(successorTerm(i->first)); } for (Map<MultipleDeriv, std::string>::const_iterator i = sPrev.begin(); i != sPrev.end(); i++) { prevKeys.put(i->first); } Out::os() << "keys from prev level are " << prevKeys << std::endl; Out::os() << "induced keys are " << inducedKeys << std::endl; Out::os() << "natural keys are " << keys_[level] << std::endl; allKeys.merge(inducedKeys); allKeys.merge(keys_[level]); Out::os() << "keys active at this level are " << allKeys << std::endl; for (Set<MultipleDeriv>::const_iterator i = allKeys.begin(); i != allKeys.end(); i++) { const MultipleDeriv& key = *i; Out::os() << "working on key " << key << std::endl; std::string str; if (coeffs_[level].containsKey(key)) { str = coeffs_[level].get(key)->toString(); } Set<Deriv> funcs = findFuncsForSummation(prevKeys, key); Out::os() << "funcs to sum are " << funcs << std::endl; for (Set<Deriv>::const_iterator j = funcs.begin(); j != funcs.end(); j++) { MultipleDeriv prevKey = key; Out::os() << "prev key = " << prevKey << std::endl; Out::os() << "func = " << *j << std::endl; // if (key.size() > 0 && key.upper_bound(*j) == key.end()) // { // Out::os() << "skipping" << std::endl; // continue; // } prevKey.put(*j); TEUCHOS_TEST_FOR_EXCEPTION(!sPrev.containsKey(prevKey), std::logic_error, "inconsisent key lookup"); const std::string& prevStr = sPrev.get(prevKey); std::string funcStr = (*j).toString(); if (str.length() > 0) str += " + "; str += funcStr + "*(" + prevStr + ")"; } if (str.length() > 0) sCurr.put(key, str); } }
ProductEvaluator::ProductEvaluator(const ProductExpr* expr, const EvalContext& context) : BinaryEvaluator<ProductExpr>(expr, context), maxOrder_(this->sparsity()->maxOrder()), resultIndex_(maxOrder_+1), resultIsConstant_(maxOrder_+1), hasWorkspace_(maxOrder_+1), workspaceIsLeft_(maxOrder_+1), workspaceIndex_(maxOrder_+1), workspaceCoeffIndex_(maxOrder_+1), workspaceCoeffIsConstant_(maxOrder_+1), ccTerms_(maxOrder_+1), cvTerms_(maxOrder_+1), vcTerms_(maxOrder_+1), vvTerms_(maxOrder_+1), startingVectors_(maxOrder_+1), startingParities_(maxOrder_+1) { int verb = context.evalSetupVerbosity(); try { Tabs tabs(0); { Tabs tab; Tabs tabz; SUNDANCE_MSG1(verb, tabs << "initializing product evaluator for " << expr->toString()); SUNDANCE_MSG2(verb, tab << "return sparsity " << std::endl << tabz << *(this->sparsity)()); SUNDANCE_MSG2(verb, tab << "left sparsity " << std::endl << tabz << *(leftSparsity()) << std::endl << tabz << "right sparsity " << std::endl << tabz << *(rightSparsity())); SUNDANCE_MSG3(verb, tab << "left vector index map " << leftEval()->vectorIndexMap() << std::endl << tabz << "right vector index map " << rightEval()->vectorIndexMap() << std::endl << tabz << "left constant index map " << leftEval()->constantIndexMap() << std::endl << tabz << "right constant index map " << rightEval()->constantIndexMap()); } int vecResultIndex = 0; int constResultIndex = 0; for (int i=0; i<this->sparsity()->numDerivs(); i++) { Tabs tab0; const MultipleDeriv& d = this->sparsity()->deriv(i); SUNDANCE_MSG2(verb, tabs << std::endl << tabs << "finding rules for deriv " << d); int order = d.order(); /* Determine the index into which the result will be written */ bool resultIsConstant = this->sparsity()->state(i)==ConstantDeriv; resultIsConstant_[order].append(resultIsConstant); if (resultIsConstant) { SUNDANCE_MSG3(verb, tab0 << std::endl << tab0 << "result will be in constant index " << constResultIndex); resultIndex_[order].append(constResultIndex); addConstantIndex(i, constResultIndex); constResultIndex++; } else { SUNDANCE_MSG3(verb, tab0 << std::endl << tab0 << "result will be in constant index " << vecResultIndex); resultIndex_[order].append(vecResultIndex); addVectorIndex(i, vecResultIndex); vecResultIndex++; } /* If possible, we want to do the calculations in-place, writing into * one of the two operand's results vectors for the same derivative. * Provided that we process derivatives in descending order, it is * safe to destroy the operands' result vectors. */ int dnLeftIndex = leftSparsity()->getIndex(d); int dnRightIndex = rightSparsity()->getIndex(d); bool hasVectorWorkspace = false; bool workspaceIsLeft = false; int workspaceIndex = -1; int workspaceCoeffIndex = -1; bool workspaceCoeffIsConstant = false; bool dnLeftIsConst = false; if (dnLeftIndex != -1) { dnLeftIsConst = leftSparsity()->state(dnLeftIndex)==ConstantDeriv; } bool dnRightIsConst = false; if (dnRightIndex != -1) { dnRightIsConst = rightSparsity()->state(dnRightIndex)==ConstantDeriv; } /* First try to use the left result as a workspace */ if (dnLeftIndex != -1 && !dnLeftIsConst && rightSparsity()->containsDeriv(MultipleDeriv())) { /* We can write onto left vector */ hasVectorWorkspace = true; workspaceIndex = leftEval()->vectorIndexMap().get(dnLeftIndex); SUNDANCE_MSG3(verb, tab0 << "using left as workspace"); workspaceIsLeft = true; int d0RightIndex = rightSparsity()->getIndex(MultipleDeriv()); bool d0RightIsConst = rightSparsity()->state(d0RightIndex)==ConstantDeriv; workspaceCoeffIsConstant = d0RightIsConst; if (d0RightIsConst) { workspaceCoeffIndex = rightEval()->constantIndexMap().get(d0RightIndex); } else { workspaceCoeffIndex = rightEval()->vectorIndexMap().get(d0RightIndex); } } /* If the left didn't provide a workspace, try the right */ if (!hasVectorWorkspace && dnRightIndex != -1 && !dnRightIsConst && leftSparsity()->containsDeriv(MultipleDeriv())) { /* We can write onto right vector */ hasVectorWorkspace = true; workspaceIndex = rightEval()->vectorIndexMap().get(dnRightIndex); workspaceIsLeft = false; SUNDANCE_MSG3(verb, tab0 << "using right as workspace"); int d0LeftIndex = leftSparsity()->getIndex(MultipleDeriv()); bool d0LeftIsConst = leftSparsity()->state(d0LeftIndex)==ConstantDeriv; workspaceCoeffIsConstant = d0LeftIsConst; if (d0LeftIsConst) { workspaceCoeffIndex = leftEval()->constantIndexMap().get(d0LeftIndex); } else { workspaceCoeffIndex = leftEval()->vectorIndexMap().get(d0LeftIndex); } } if (hasVectorWorkspace && verb > 2) { std::string wSide = "right"; MultipleDeriv wsDeriv; if (workspaceIsLeft) { wSide = "left"; wsDeriv = leftSparsity()->deriv(dnLeftIndex); } else { wsDeriv = rightSparsity()->deriv(dnRightIndex); } SUNDANCE_MSG2(verb, tab0 << "has workspace vector: " << wSide << " deriv= " << wsDeriv << ", coeff index= " << workspaceCoeffIndex); } else { SUNDANCE_MSG2(verb, tab0 << "has no workspace vector"); } hasWorkspace_[order].append(hasVectorWorkspace); workspaceIsLeft_[order].append(workspaceIsLeft); workspaceIndex_[order].append(workspaceIndex); workspaceCoeffIndex_[order].append(workspaceCoeffIndex); workspaceCoeffIsConstant_[order].append(workspaceCoeffIsConstant); ProductRulePerms perms; d.productRulePermutations(perms); SUNDANCE_MSG4(verb, tabs << "product rule permutations " << perms); Array<Array<int> > ccTerms; Array<Array<int> > cvTerms; Array<Array<int> > vcTerms; Array<Array<int> > vvTerms; Array<int> startingVector; ProductParity startingParity; bool hasStartingVector = false; for (ProductRulePerms::const_iterator iter = perms.begin(); iter != perms.end(); iter++) { Tabs tab1; MultipleDeriv dLeft = iter->first.first(); MultipleDeriv dRight = iter->first.second(); int multiplicity = iter->second; /* skip this combination if we've already pulled it out * for workspace */ if (hasVectorWorkspace && workspaceIsLeft && dLeft.order()==order) continue; if (hasVectorWorkspace && !workspaceIsLeft && dRight.order()==order) continue; if (!leftSparsity()->containsDeriv(dLeft) || !rightSparsity()->containsDeriv(dRight)) continue; int iLeft = leftSparsity()->getIndex(dLeft); int iRight = rightSparsity()->getIndex(dRight); if (iLeft==-1 || iRight==-1) continue; SUNDANCE_MSG4(verb, tab1 << "left deriv=" << dLeft); SUNDANCE_MSG4(verb, tab1 << "right deriv=" << dRight); bool leftIsConst = leftSparsity()->state(iLeft)==ConstantDeriv; bool rightIsConst = rightSparsity()->state(iRight)==ConstantDeriv; if (leftIsConst) { Tabs tab2; SUNDANCE_MSG4(verb, tab2 << "left is const"); int leftIndex = leftEval()->constantIndexMap().get(iLeft); if (rightIsConst) { SUNDANCE_MSG4(verb, tab2 << "right is const"); int rightIndex = rightEval()->constantIndexMap().get(iRight); ccTerms.append(tuple(leftIndex, rightIndex, multiplicity)); } else { SUNDANCE_MSG4(verb, tab2 << "right is vec"); int rightIndex = rightEval()->vectorIndexMap().get(iRight); if (!hasVectorWorkspace && !hasStartingVector) { SUNDANCE_MSG4(verb, tab1 << "found c-v starting vec"); startingVector = tuple(leftIndex, rightIndex, multiplicity); hasStartingVector = true; startingParity = ConstVec; } else { SUNDANCE_MSG4(verb, tab1 << "found c-v term"); cvTerms.append(tuple(leftIndex, rightIndex, multiplicity)); } } } else { Tabs tab2; SUNDANCE_MSG4(verb, tab2 << "left is vec"); int leftIndex = leftEval()->vectorIndexMap().get(iLeft); if (rightIsConst) { SUNDANCE_MSG4(verb, tab2 << "right is const"); int rightIndex = rightEval()->constantIndexMap().get(iRight); if (!hasVectorWorkspace && !hasStartingVector) { SUNDANCE_MSG4(verb, tab1 << "found v-c starting vec"); startingVector = tuple(leftIndex, rightIndex, multiplicity); hasStartingVector = true; startingParity = VecConst; } else { SUNDANCE_MSG4(verb, tab1 << "found v-c term"); vcTerms.append(tuple(leftIndex, rightIndex, multiplicity)); } } else { SUNDANCE_MSG4(verb, tab2 << "right is vec"); int rightIndex = rightEval()->vectorIndexMap().get(iRight); if (!hasVectorWorkspace && !hasStartingVector) { SUNDANCE_MSG4(verb, tab1 << "found v-v starting vec"); startingVector = tuple(leftIndex, rightIndex, multiplicity); hasStartingVector = true; startingParity = VecVec; } else { SUNDANCE_MSG4(verb, tab1 << "found v-v term"); vvTerms.append(tuple(leftIndex, rightIndex, multiplicity)); } } } } ccTerms_[order].append(ccTerms); cvTerms_[order].append(cvTerms); vcTerms_[order].append(vcTerms); vvTerms_[order].append(vvTerms); startingVectors_[order].append(startingVector); startingParities_[order].append(startingParity); if (verb > 2) { Tabs tab0; Out::os() << tab0 << "deriv " << i << " order=" << order ; if (resultIsConstant) { Out::os() << " constant result, index= "; } else { Out::os() << " vector result, index= "; } Out::os() << resultIndex_[order] << std::endl; { Tabs tab1; if (hasStartingVector) { Out::os() << tab1 << "starting vector " << startingVector << std::endl; } Out::os() << tab1 << "c-c terms " << ccTerms << std::endl; Out::os() << tab1 << "c-v terms " << cvTerms << std::endl; Out::os() << tab1 << "v-c terms " << vcTerms << std::endl; Out::os() << tab1 << "v-v terms " << vvTerms << std::endl; } } } if (verb > 2) { Out::os() << tabs << "maps: " << std::endl; Out::os() << tabs << "vector index map " << vectorIndexMap() << std::endl; Out::os() << tabs << "constant index map " << constantIndexMap() << std::endl; } } catch(std::exception& e) { TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, "exception detected in ProductEvaluator: expr=" << expr->toString() << std::endl << "exception=" << e.what()); } }
MultipleDeriv makeMultiDeriv(const Deriv& d) { MultipleDeriv rtn; rtn.put(d); return rtn; }