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()); } }
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 ::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; }
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_++; } }
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; }
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()); } }