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 "SundanceExprWithChildren.hpp"
00043 #include "SundanceCombinatorialUtils.hpp"
00044 #include "PlayaTabs.hpp"
00045 #include "SundanceOut.hpp"
00046 #include "SundanceExpr.hpp"
00047 #include "SundanceEvaluatorFactory.hpp"
00048 #include "SundanceEvaluator.hpp"
00049 #include "SundanceNullEvaluator.hpp"
00050 #include "SundanceUnknownFuncElement.hpp"
00051 #include "SundanceTestFuncElement.hpp"
00052 #include "SundanceUnaryExpr.hpp"
00053
00054 using namespace Sundance;
00055 using namespace Sundance;
00056
00057 using namespace Sundance;
00058 using namespace Teuchos;
00059
00060
00061
00062
00063 ExprWithChildren::ExprWithChildren(const Array<RCP<ScalarExpr> >& children)
00064 : EvaluatableExpr(),
00065 children_(children),
00066 contextToQWMap_(4),
00067 contextToQVMap_(4),
00068 contextToQCMap_(4)
00069 {}
00070
00071 bool ExprWithChildren::lessThan(const ScalarExpr* other) const
00072 {
00073 const ExprWithChildren* c = dynamic_cast<const ExprWithChildren*>(other);
00074 TEUCHOS_TEST_FOR_EXCEPTION(c==0, std::logic_error, "cast should never fail at this point");
00075
00076 if (children_.size() < c->children_.size()) return true;
00077 if (children_.size() > c->children_.size()) return false;
00078
00079 for (int i=0; i<children_.size(); i++)
00080 {
00081 Expr me = Expr::handle(children_[i]);
00082 Expr you = Expr::handle(c->children_[i]);
00083 if (me.lessThan(you)) return true;
00084 if (you.lessThan(me)) return false;
00085 }
00086 return false;
00087 }
00088
00089
00090
00091 bool ExprWithChildren::isConstant() const
00092 {
00093 for (int i=0; i<children_.size(); i++)
00094 {
00095 if (!children_[i]->isConstant()) return false;
00096 }
00097 return true;
00098 }
00099
00100 bool ExprWithChildren::isIndependentOf(const Expr& u) const
00101 {
00102 for (int i=0; i<children_.size(); i++)
00103 {
00104 if (!children_[i]->isIndependentOf(u)) return false;
00105 }
00106 return true;
00107 }
00108
00109 const EvaluatableExpr* ExprWithChildren::evaluatableChild(int i) const
00110 {
00111 const EvaluatableExpr* e
00112 = dynamic_cast<const EvaluatableExpr*>(children_[i].get());
00113
00114 TEUCHOS_TEST_FOR_EXCEPTION(e==0, std::logic_error,
00115 "ExprWithChildren: cast of child ["
00116 << children_[i]->toString()
00117 << " to evaluatable expr failed");
00118
00119 return e;
00120 }
00121
00122 int ExprWithChildren::maxDiffOrderOnDiscreteFunctions() const
00123 {
00124 int biggest = -1;
00125 for (int i=0; i<numChildren(); i++)
00126 {
00127 int x = evaluatableChild(i)->maxDiffOrderOnDiscreteFunctions();
00128 if (x > biggest) biggest = x;
00129 }
00130 return biggest;
00131 }
00132
00133 bool ExprWithChildren::hasDiscreteFunctions() const
00134 {
00135 for (int i=0; i<numChildren(); i++)
00136 {
00137 if (evaluatableChild(i)->hasDiscreteFunctions()) return true;
00138 }
00139 return false;
00140 }
00141
00142
00143 void ExprWithChildren::accumulateFuncSet(Set<int>& funcIDs,
00144 const Set<int>& activeSet) const
00145 {
00146 for (int i=0; i<children_.size(); i++)
00147 {
00148 children_[i]->accumulateFuncSet(funcIDs, activeSet);
00149 }
00150 }
00151
00152 void ExprWithChildren::registerSpatialDerivs(const EvalContext& context,
00153 const Set<MultiIndex>& miSet) const
00154 {
00155 for (int i=0; i<children_.size(); i++)
00156 {
00157 evaluatableChild(i)->registerSpatialDerivs(context, miSet);
00158 }
00159 EvaluatableExpr::registerSpatialDerivs(context, miSet);
00160 }
00161
00162 void ExprWithChildren::setupEval(const EvalContext& context) const
00163 {
00164 Tabs tabs;
00165 int verb = context.evalSetupVerbosity();
00166 SUNDANCE_MSG1(verb, tabs << "expr " + toString()
00167 << ": creating evaluators for children");
00168 RCP<SparsitySuperset> ss = sparsitySuperset(context);
00169 SUNDANCE_MSG2(verb, tabs << "my sparsity superset = "
00170 << std::endl << *ss);
00171
00172
00173
00174
00175 if (ss->numDerivs() > 0)
00176 {
00177 for (int i=0; i<children_.size(); i++)
00178 {
00179 Tabs tabs1;
00180 SUNDANCE_MSG1(verb, tabs1 << "creating evaluator for child "
00181 << evaluatableChild(i)->toString());
00182 evaluatableChild(i)->setupEval(context);
00183 }
00184 }
00185
00186 if (!evaluators().containsKey(context))
00187 {
00188 RCP<Evaluator> eval;
00189 if (ss->numDerivs()>0)
00190 {
00191 eval = rcp(createEvaluator(this, context));
00192 }
00193 else
00194 {
00195 SUNDANCE_MSG2(verb,
00196 tabs << "EWC: no results needed... creating null evaluator");
00197 eval = rcp(new NullEvaluator());
00198 }
00199 evaluators().put(context, eval);
00200 }
00201 }
00202
00203 void ExprWithChildren::showSparsity(std::ostream& os,
00204 const EvalContext& context) const
00205 {
00206 Tabs tab0;
00207 os << tab0 << "Node: " << toString() << std::endl;
00208 sparsitySuperset(context)->print(os);
00209 for (int i=0; i<children_.size(); i++)
00210 {
00211 Tabs tab1;
00212 os << tab1 << "Child " << i << std::endl;
00213 evaluatableChild(i)->showSparsity(os, context);
00214 }
00215 }
00216
00217
00218 bool ExprWithChildren::everyTermHasTestFunctions() const
00219 {
00220 for (int i=0; i<children_.size(); i++)
00221 {
00222 if (evaluatableChild(i)->everyTermHasTestFunctions()) return true;
00223 }
00224 return false;
00225 }
00226
00227
00228 bool ExprWithChildren::hasTestFunctions() const
00229 {
00230 for (int i=0; i<children_.size(); i++)
00231 {
00232 if (evaluatableChild(i)->hasTestFunctions()) return true;
00233 }
00234 return false;
00235 }
00236
00237
00238 bool ExprWithChildren::hasUnkFunctions() const
00239 {
00240 for (int i=0; i<children_.size(); i++)
00241 {
00242 if (evaluatableChild(i)->hasUnkFunctions()) return true;
00243 }
00244 return false;
00245 }
00246
00247
00248 void ExprWithChildren::getUnknowns(Set<int>& unkID, Array<Expr>& unks) const
00249 {
00250 for (int i=0; i<children_.size(); i++)
00251 {
00252 const RCP<ExprBase>& e = children_[i];
00253 const UnknownFuncElement* u
00254 = dynamic_cast<const UnknownFuncElement*>(e.get());
00255 if (u != 0)
00256 {
00257 Expr expr(e);
00258 if (!unkID.contains(u->fid().dofID()))
00259 {
00260 unks.append(expr);
00261 unkID.put(u->fid().dofID());
00262 }
00263 }
00264 else
00265 {
00266 evaluatableChild(i)->getUnknowns(unkID, unks);
00267 }
00268 }
00269 }
00270
00271 void ExprWithChildren::getTests(Set<int>& varID, Array<Expr>& vars) const
00272 {
00273 for (int i=0; i<children_.size(); i++)
00274 {
00275 const RCP<ExprBase>& e = children_[i];
00276 const TestFuncElement* u
00277 = dynamic_cast<const TestFuncElement*>(e.get());
00278 if (u != 0)
00279 {
00280 Expr expr(e);
00281 if (!varID.contains(u->fid().dofID()))
00282 {
00283 vars.append(expr);
00284 varID.put(u->fid().dofID());
00285 }
00286
00287 }
00288 else
00289 {
00290 evaluatableChild(i)->getTests(varID, vars);
00291 }
00292 }
00293 }
00294
00295
00296 int ExprWithChildren::countNodes() const
00297 {
00298 if (nodesHaveBeenCounted())
00299 {
00300 return 0;
00301 }
00302
00303
00304 int count = EvaluatableExpr::countNodes();
00305
00306
00307 for (int i=0; i<children_.size(); i++)
00308 {
00309 if (!evaluatableChild(i)->nodesHaveBeenCounted())
00310 {
00311 count += evaluatableChild(i)->countNodes();
00312 }
00313 }
00314 return count;
00315 }
00316
00317 Set<MultipleDeriv>
00318 ExprWithChildren::product(const Array<int>& J, const Array<int>& K,
00319 DerivSubsetSpecifier dss,
00320 const EvalContext& context) const
00321 {
00322 TEUCHOS_TEST_FOR_EXCEPTION(J.size() != K.size(), std::logic_error,
00323 "mismatched index set sizes");
00324 TEUCHOS_TEST_FOR_EXCEPTION(J.size() == 0, std::logic_error,
00325 "empty index set");
00326
00327 Set<MultipleDeriv> rtn
00328 = evaluatableChild(J[0])->findDerivSubset(K[0], dss, context);
00329
00330 for (int i=1; i<J.size(); i++)
00331 {
00332 const Set<MultipleDeriv>& S
00333 = evaluatableChild(J[i])->findDerivSubset(K[i], dss, context);
00334 rtn = setProduct(rtn, S);
00335 }
00336
00337 return rtn;
00338 }
00339
00340 Set<MultipleDeriv>
00341 ExprWithChildren::internalFindV(int order, const EvalContext& context) const
00342 {
00343 Tabs tab0;
00344 int verb = context.setupVerbosity();
00345 SUNDANCE_MSG2(verb, tab0 << "EWC::internalFindV(" << order
00346 << ") for " << toString());
00347
00348 Set<MultipleDeriv> rtn;
00349
00350
00351
00352
00353 if (order==0)
00354 {
00355 Tabs tab1;
00356 SUNDANCE_MSG3(verb, tab1 << "case: order=0");
00357 for (int i=0; i<numChildren(); i++)
00358 {
00359 if (!childIsRequired(i, order, context)) continue;
00360 const Set<MultipleDeriv>& childV0
00361 = evaluatableChild(i)->findV(0, context);
00362 rtn.merge(childV0);
00363 }
00364 const Set<MultipleDeriv>& R0 = findR(0, context);
00365 rtn = rtn.intersection(R0);
00366
00367 SUNDANCE_MSG3(verb, tab0 << "V[" << order << "]=" << rtn);
00368 SUNDANCE_MSG3(verb, tab0 << "done with EWC::internalFindV(" << order
00369 << ") for " << toString());
00370 return rtn;
00371 }
00372
00373
00374 SUNDANCE_MSG3(verb, tab0 << "getting required set");
00375 const Set<MultipleDeriv>& RM = findR(order, context);
00376 SUNDANCE_MSG3(verb, tab0 << "RM=" << RM);
00377 Array<Array<Array<int> > > comp = compositions(order);
00378 for (int i=1; i<=order; i++)
00379 {
00380 Tabs tab1;
00381 SUNDANCE_MSG3(verb, tab1 << "i=" << i << " out of order=" << order);
00382 const Set<MultiSet<int> >& QC = findQ_C(i, context);
00383 SUNDANCE_MSG3(verb, tab1 << "QC[" << i << "] = " << QC);
00384 for (Set<MultiSet<int> >::const_iterator j=QC.begin(); j!=QC.end(); j++)
00385 {
00386 Tabs tab2;
00387 Array<int> J = j->elements();
00388 const Array<Array<int> >& K = comp[J.size()-1];
00389 SUNDANCE_MSG3(verb, tab2 << "J=" << J);
00390 SUNDANCE_MSG3(verb, tab2 << "K=" << K);
00391
00392 for (int k=0; k<K.size(); k++)
00393 {
00394 Tabs tab3;
00395 Set<MultipleDeriv> RProd = product(J, K[k],
00396 RequiredNonzeros, context);
00397 Set<MultipleDeriv> CProd = product(J, K[k],
00398 ConstantNonzeros, context);
00399 SUNDANCE_MSG3(verb, tab3 << "CProd = " << CProd);
00400 SUNDANCE_MSG3(verb, tab3 << "RProd = " << RProd);
00401 rtn.merge(RProd.setDifference(CProd));
00402 }
00403 }
00404
00405 const Set<MultiSet<int> >& QV = findQ_V(i, context);
00406 SUNDANCE_MSG3(verb, tab1 << "QV[" << i << "] = " << QV);
00407 for (Set<MultiSet<int> >::const_iterator j=QV.begin(); j!=QV.end(); j++)
00408 {
00409 Tabs tab2;
00410 Array<int> J = j->elements();
00411 const Array<Array<int> >& K = comp[J.size()-1];
00412 SUNDANCE_MSG3(verb, tab2 << "J=" << J);
00413 SUNDANCE_MSG3(verb, tab2 << "K=" << K);
00414
00415 for (int k=0; k<K.size(); k++)
00416 {
00417 Tabs tab3;
00418 Set<MultipleDeriv> RProd = product(J, K[k],
00419 RequiredNonzeros, context);
00420 SUNDANCE_MSG3(verb, tab3 << "RProd = " << RProd);
00421 rtn.merge(RProd);
00422 }
00423 }
00424 }
00425
00426 SUNDANCE_MSG3(verb, tab0 << "rtn before intersection = " << rtn);
00427 rtn = rtn.intersection(RM);
00428 SUNDANCE_MSG2(verb, tab0 << "V[" << order << "]=" << rtn);
00429 SUNDANCE_MSG2(verb, tab0 << "done with EWC::internalFindV(" << order
00430 << ") for " << toString());
00431
00432 return rtn;
00433 }
00434
00435
00436 Set<MultipleDeriv>
00437 ExprWithChildren::internalFindC(int order, const EvalContext& context) const
00438 {
00439 Tabs tab0;
00440 Set<MultipleDeriv> rtn;
00441 bool started = false;
00442 int verb = context.setupVerbosity();
00443
00444 SUNDANCE_MSG2(verb, tab0 << "EWC::internalFindC(" << order
00445 << ") for " << toString());
00446
00447
00448 if (order==0)
00449 {
00450 for (int i=0; i<numChildren(); i++)
00451 {
00452 if (!childIsRequired(i, 0, context)) continue;
00453 const Set<MultipleDeriv>& childV0
00454 = evaluatableChild(i)->findV(0, context);
00455 rtn.merge(childV0);
00456 }
00457 const Set<MultipleDeriv>& R0 = findR(0, context);
00458 rtn = R0.setDifference(rtn);
00459 SUNDANCE_MSG3(verb, tab0 << "C[" << order << "]=" << rtn);
00460 SUNDANCE_MSG3(verb, tab0 << "done with EWC::internalFindC(" << order
00461 << ") for " << toString());
00462 return rtn;
00463 }
00464
00465
00466
00467 Array<Array<Array<int> > > comp = compositions(order);
00468 const Set<MultipleDeriv>& RM = findR(order, context);
00469 for (int i=1; i<=order; i++)
00470 {
00471 Tabs tab1;
00472 SUNDANCE_MSG3(verb, tab1 << "i=" << i << " up to order=" << order);
00473
00474
00475 const Set<MultiSet<int> >& QC = findQ_C(i, context);
00476 SUNDANCE_MSG5(verb, tab1 << "finding CProd union (R\\RProd) over QC");
00477 SUNDANCE_MSG5(verb, tab1 << "QC = " << QC);
00478
00479
00480 for (Set<MultiSet<int> >::const_iterator j=QC.begin(); j!=QC.end(); j++)
00481 {
00482 Tabs tab2;
00483 Array<int> J = j->elements();
00484 const Array<Array<int> >& K = comp[J.size()-1];
00485 SUNDANCE_MSG5(verb, tab2 << "J=" << J);
00486 SUNDANCE_MSG5(verb, tab2 << "K=" << K);
00487
00488 for (int k=0; k<K.size(); k++)
00489 {
00490 Tabs tab3;
00491 Set<MultipleDeriv> RProd = product(J, K[k],
00492 RequiredNonzeros, context);
00493 Set<MultipleDeriv> CProd = product(J, K[k],
00494 ConstantNonzeros, context);
00495 SUNDANCE_MSG5(verb, tab3 << "CProd = " << CProd);
00496 SUNDANCE_MSG5(verb, tab3 << "RProd = " << RProd);
00497 Set<MultipleDeriv> X = CProd.setUnion(RM.setDifference(RProd));
00498 if (!started)
00499 {
00500 rtn = X;
00501 started = true;
00502 }
00503 else
00504 {
00505 rtn = rtn.intersection(X);
00506 }
00507 }
00508 }
00509
00510 const Set<MultiSet<int> >& QV = findQ_V(i, context);
00511 SUNDANCE_MSG5(verb, tab1 << "finding R\\RProd over QV");
00512 SUNDANCE_MSG5(verb, tab1 << "QV = " << QV);
00513
00514 for (Set<MultiSet<int> >::const_iterator j=QV.begin(); j!=QV.end(); j++)
00515 {
00516 Tabs tab2;
00517 Array<int> J = j->elements();
00518 const Array<Array<int> >& K = comp[J.size()-1];
00519 SUNDANCE_MSG5(verb, tab2 << "J=" << J);
00520 SUNDANCE_MSG5(verb, tab2 << "K=" << K);
00521
00522 for (int k=0; k<K.size(); k++)
00523 {
00524 Tabs tab3;
00525 Set<MultipleDeriv> RProd = product(J, K[k],
00526 RequiredNonzeros, context);
00527 Set<MultipleDeriv> X = RM.setDifference(RProd);
00528 if (!started)
00529 {
00530 rtn = X;
00531 started = true;
00532 }
00533 else
00534 {
00535 rtn = rtn.intersection(X);
00536 }
00537 SUNDANCE_MSG5(verb, tab3 << "RProd = " << RProd);
00538 }
00539 }
00540 }
00541
00542 rtn = rtn.intersection(RM);
00543 SUNDANCE_MSG2(verb, tab0 << "C[" << order << "]=" << rtn);
00544 SUNDANCE_MSG2(verb, tab0 << "done with EWC::internalFindC(" << order
00545 << ") for " << toString());
00546 return rtn;
00547 }
00548
00549
00550
00551 Set<MultipleDeriv>
00552 ExprWithChildren::internalFindW(int order, const EvalContext& context) const
00553 {
00554 Tabs tab0;
00555 int verb = context.setupVerbosity();
00556 Set<MultipleDeriv> rtn;
00557 SUNDANCE_MSG2(verb, tab0 << "EWC::internalFindW(order="
00558 << order << ") for " << toString());
00559 Tabs tabz;
00560
00561 if (order==0)
00562 {
00563 Tabs tab1;
00564 SUNDANCE_MSG2(verb, tab1 << "** CASE: order=0");
00565
00566
00567
00568 if (!(isLinear() || isProduct()))
00569 {
00570 Tabs tab2;
00571 SUNDANCE_MSG3(verb, tab2 << "I am neither product nor linear");
00572 rtn.put(MultipleDeriv());
00573 SUNDANCE_MSG3(verb, tab2 << "W[" << order << "]=" << rtn);
00574 SUNDANCE_MSG3(verb, tab2 << "done with EWC::internalFindW for "
00575 << toString());
00576 return rtn;
00577 }
00578
00579
00580
00581
00582 SUNDANCE_MSG3(verb, tab1 << "getting Q");
00583 const Set<MultiSet<int> >& Q = findQ_W(0, context);
00584
00585
00586
00587 if (Q.size()==0)
00588 {
00589 Tabs tab2;
00590 SUNDANCE_MSG3(verb, tab2 << "W[" << order << "]=" << rtn);
00591 SUNDANCE_MSG3(verb, tab2 << "done with EWC::internalFindW for "
00592 << toString());
00593 return rtn;
00594 }
00595
00596
00597 if (isLinear())
00598 {
00599 Tabs tab2;
00600 SUNDANCE_MSG3(verb, tab2 << "I am a linear combination");
00601 rtn.put(MultipleDeriv());
00602 SUNDANCE_MSG3(verb, tab2 << "W[" << order << "]=" << rtn);
00603 SUNDANCE_MSG3(verb, tab2 << "done with EWC::internalFindW for "
00604 << toString());
00605 return rtn;
00606 }
00607
00608
00609
00610
00611
00612
00613
00614 if (((int) Q.size()) == numChildren())
00615 {
00616 rtn.put(MultipleDeriv());
00617 }
00618 SUNDANCE_MSG2(verb, tab1 << "I am a product");
00619 SUNDANCE_MSG2(verb, tab1 << "W[" << order << "]=" << rtn);
00620 SUNDANCE_MSG2(verb, tab0 << "done with EWC::internalFindW for "
00621 << toString());
00622 return rtn;
00623 }
00624
00625
00626
00627 Array<Array<Array<int> > > comp = compositions(order);
00628 for (int i=1; i<=order; i++)
00629 {
00630 Tabs tab1;
00631 SUNDANCE_MSG2(verb, tab1 << "** CASE order=" << i);
00632
00633 const Set<MultiSet<int> >& QW = findQ_W(i, context);
00634
00635 SUNDANCE_MSG3(verb, tab1 << "QW=" << QW);
00636
00637 for (Set<MultiSet<int> >::const_iterator j=QW.begin(); j!=QW.end(); j++)
00638 {
00639 Array<int> J = j->elements();
00640 const Array<Array<int> >& K = comp[J.size()-1];
00641
00642 for (int k=0; k<K.size(); k++)
00643 {
00644 Set<MultipleDeriv> WProd = product(J, K[k], AllNonzeros, context);
00645 rtn.merge(WProd);
00646 }
00647 }
00648 }
00649
00650 SUNDANCE_MSG2(verb, tabz << "W[" << order << "]=" << rtn);
00651 SUNDANCE_MSG2(verb, tab0 << "done with EWC::internalFindW for "
00652 << toString());
00653 return rtn;
00654 }
00655
00656 const Set<MultiSet<int> >&
00657 ExprWithChildren::findQ_W(int order,
00658 const EvalContext& context) const
00659 {
00660 Tabs tab1;
00661 int verb = context.setupVerbosity();
00662 SUNDANCE_MSG2(verb, tab1 << "finding Q_W");
00663 if (!contextToQWMap_[order].containsKey(context))
00664 {
00665 contextToQWMap_[order].put(context, internalFindQ_W(order, context));
00666 }
00667 else
00668 {
00669 SUNDANCE_MSG5(verb, tab1 << "using previously computed Q_W");
00670 }
00671 return contextToQWMap_[order].get(context);
00672
00673 }
00674
00675 const Set<MultiSet<int> >&
00676 ExprWithChildren::findQ_V(int order,
00677 const EvalContext& context) const
00678 {
00679 if (!contextToQVMap_[order].containsKey(context))
00680 {
00681 contextToQVMap_[order].put(context, internalFindQ_V(order, context));
00682 }
00683 return contextToQVMap_[order].get(context);
00684 }
00685
00686 const Set<MultiSet<int> >&
00687 ExprWithChildren::findQ_C(int order,
00688 const EvalContext& context) const
00689 {
00690 if (!contextToQCMap_[order].containsKey(context))
00691 {
00692 contextToQCMap_[order].put(context, internalFindQ_C(order, context));
00693 }
00694 return contextToQCMap_[order].get(context);
00695 }
00696
00697
00698 const Set<MultiSet<int> >& ExprWithChildren::getI_N() const
00699 {
00700 if (!cachedI_N().containsKey(numChildren()))
00701 {
00702 Set<MultiSet<int> > x;
00703 for (int i=0; i<numChildren(); i++)
00704 {
00705 x.put(makeMultiSet<int>(i));
00706 }
00707 cachedI_N().put(numChildren(), x);
00708 }
00709 return cachedI_N().get(numChildren());
00710 }
00711
00712 Set<MultiSet<int> > ExprWithChildren::indexSetProduct(const Set<MultiSet<int> >& a,
00713 const Set<MultiSet<int> >& b) const
00714 {
00715 Set<MultiSet<int> > rtn;
00716 for (Set<MultiSet<int> >::const_iterator i=a.begin(); i!=a.end(); i++)
00717 {
00718 for (Set<MultiSet<int> >::const_iterator j=b.begin(); j!=b.end(); j++)
00719 {
00720 MultiSet<int> ab = (*i).merge(*j);
00721 rtn.put(ab);
00722 }
00723 }
00724 return rtn;
00725 }
00726
00727
00728 Set<MultiSet<int> > ExprWithChildren::internalFindQ_V(int order,
00729 const EvalContext& context) const
00730 {
00731 Tabs tab0;
00732 int verb = context.setupVerbosity();
00733 SUNDANCE_MSG2(verb, tab0 << "EWC::internalFindQ_V(order=" << order <<")");
00734 Set<MultiSet<int> > rtn;
00735
00736 if (!isLinear())
00737 {
00738 bool isVar = false;
00739 for (int i=0; i<numChildren(); i++)
00740 {
00741 if (childIsRequired(i,order,context) && evaluatableChild(i)->findV(0, context).size() != 0)
00742 {
00743 isVar=true;
00744 break;
00745 }
00746 }
00747 if (isVar) rtn = findQ_W(order, context);
00748 }
00749
00750 SUNDANCE_MSG2(verb, tab0 << "Q_V = " << rtn);
00751 return rtn;
00752 }
00753
00754 Set<MultiSet<int> > ExprWithChildren::internalFindQ_C(int order,
00755 const EvalContext& context) const
00756 {
00757 if (isLinear()) return findQ_W(order,context);
00758
00759 return findQ_W(order,context).setDifference(findQ_V(order, context));
00760 }
00761
00762
00763 Set<MultiSet<int> > ExprWithChildren
00764 ::internalFindQ_W(int order,
00765 const EvalContext& context) const
00766 {
00767 Tabs tab0;
00768 int verb = context.setupVerbosity();
00769 SUNDANCE_MSG2(verb, tab0 << "in internalFindQ_W");
00770 Set<MultiSet<int> > rtn;
00771 const Set<MultiSet<int> >& I_N = getI_N();
00772 SUNDANCE_MSG2(verb, tab0 << "I_N=" << I_N);
00773
00774 if (isLinear())
00775 {
00776 Tabs tab1;
00777
00778
00779 if (order==1)
00780 {
00781 SUNDANCE_MSG3(verb, tab1 << "is linear, order=1, so Q_W = I_N");
00782 return I_N;
00783 }
00784
00785 if (order==0)
00786 {
00787 SUNDANCE_MSG3(verb, tab1 << "is linear, order=0");
00788 for (int i=0; i<numChildren(); i++)
00789 {
00790 const Set<MultipleDeriv>& W_i = evaluatableChild(i)->findW(0,context);
00791 SUNDANCE_MSG3(verb, tab1 << "is linear, order=0");
00792 if (W_i.size() > 0)
00793 {
00794 Tabs tab2;
00795 SUNDANCE_MSG3(verb, tab2 << "child " << i << " is nonzero");
00796 rtn.put(makeMultiSet(i));
00797 }
00798 else
00799 {
00800 Tabs tab2;
00801 SUNDANCE_MSG3(verb, tab2 << "child " << i << " is zero");
00802 }
00803 }
00804 }
00805 }
00806 else
00807 {
00808 Tabs tab1;
00809 SUNDANCE_MSG3(verb, tab1 << "is nonlinear, using all index set products");
00810 rtn = I_N;
00811
00812 for (int i=1; i<order; i++)
00813 {
00814 rtn = indexSetProduct(rtn, I_N);
00815 }
00816 }
00817 SUNDANCE_MSG2(verb, tab0 << "rtn=" << rtn);
00818 return rtn;
00819 }
00820
00821 bool ExprWithChildren::childIsRequired(int index, int diffOrder,
00822 const EvalContext& context) const
00823 {
00824 const Set<MultiSet<int> >& Q = findQ_W(diffOrder, context);
00825 for (Set<MultiSet<int> >::const_iterator it=Q.begin(); it != Q.end(); it++)
00826 {
00827 if (it->contains(index)) return true;
00828 }
00829 return true;
00830 }
00831
00832 RCP<Array<Set<MultipleDeriv> > > ExprWithChildren
00833 ::internalDetermineR(const EvalContext& context,
00834 const Array<Set<MultipleDeriv> >& RInput) const
00835 {
00836 Tabs tab0;
00837 int verb = context.setupVerbosity();
00838 RCP<Array<Set<MultipleDeriv> > > rtn
00839 = rcp(new Array<Set<MultipleDeriv> >(RInput.size()));
00840
00841 SUNDANCE_MSG2(verb, tab0 << "in internalDetermineR() for " << toString());
00842 SUNDANCE_MSG2(verb, tab0 << "RInput = " << RInput);
00843
00844
00845
00846 for (int i=0; i<RInput.size(); i++)
00847 {
00848 if (RInput[i].size()==0) continue;
00849 const Set<MultipleDeriv>& Wi = findW(i, context);
00850 (*rtn)[i] = RInput[i].intersection(Wi);
00851 }
00852
00853 int maxOrder = rtn->size()-1;
00854
00855 const Set<MultiSet<int> >& Q1 = findQ_W(1, context);
00856 const Set<MultiSet<int> >& Q2 = findQ_W(2, context);
00857 const Set<MultiSet<int> >& Q3 = findQ_W(3, context);
00858
00859 SUNDANCE_MSG3(verb, tab0 << "Q1 = " << Q1);
00860 SUNDANCE_MSG3(verb, tab0 << "Q2 = " << Q2);
00861 SUNDANCE_MSG3(verb, tab0 << "Q3 = " << Q3);
00862
00863 for (int i=0; i<numChildren(); i++)
00864 {
00865 Tabs tab1;
00866 MultiSet<int> mi = makeMultiSet(i);
00867 SUNDANCE_MSG4(verb, tab1 << "i=" << i << ", Q1_i = " << mi );
00868 TEUCHOS_TEST_FOR_EXCEPTION(mi.size() != 1, std::logic_error, "unexpected multiset size");
00869
00870 Set<MultipleDeriv> R11;
00871 Set<MultipleDeriv> R12;
00872 Set<MultipleDeriv> R13;
00873 Set<MultipleDeriv> R22;
00874 Set<MultipleDeriv> R23;
00875 Set<MultipleDeriv> R33;
00876 if (maxOrder >= 1)
00877 {
00878 R11 = (*rtn)[1];
00879 if (maxOrder >=2) R22 = (*rtn)[2];
00880 if (maxOrder >=3) R33 = (*rtn)[3];
00881 }
00882 if (maxOrder >= 2)
00883 {
00884 Tabs tab2;
00885 Set<MultiSet<int> > jSet = setDivision(Q2, i);
00886 SUNDANCE_MSG5(verb, tab2 << "Q2/i = " << jSet);
00887 for (Set<MultiSet<int> >::const_iterator
00888 j=jSet.begin(); j!=jSet.end(); j++)
00889 {
00890 Tabs tab3;
00891 TEUCHOS_TEST_FOR_EXCEPTION(j->size()!=1, std::logic_error,
00892 "unexpected set size");
00893 int jIndex = *(j->begin());
00894 SUNDANCE_MSG5(verb, tab3 << "j=" << jIndex );
00895 const Set<MultipleDeriv>& W1j = evaluatableChild(jIndex)->findW(1, context);
00896 Set<MultipleDeriv> ROverW = setDivision((*rtn)[2], W1j);
00897 R12.merge(ROverW);
00898 SUNDANCE_MSG5(verb, tab3 << "R2=" << (*rtn)[2] );
00899 SUNDANCE_MSG5(verb, tab3 << "W1(j)=" << W1j );
00900 SUNDANCE_MSG5(verb, tab3 << "R2/W1(j)=" << ROverW );
00901
00902 if (maxOrder>=3)
00903 {
00904 const Set<MultipleDeriv>& W2j
00905 = evaluatableChild(jIndex)->findW(2, context);
00906 R13.merge(setDivision((*rtn)[3], W2j));
00907 R23.merge(setDivision((*rtn)[3], W1j));
00908 }
00909 }
00910 }
00911 if (maxOrder >= 3)
00912 {
00913 Set<MultiSet<int> > jkSet = setDivision(Q3, i);
00914 for (Set<MultiSet<int> >::const_iterator
00915 jk=jkSet.begin(); jk!=jkSet.end(); jk++)
00916 {
00917 TEUCHOS_TEST_FOR_EXCEPTION(jk->size()!=2, std::logic_error,
00918 "unexpected set size");
00919 Array<int> jka = jk->elements();
00920 int j = jka[0];
00921 int k = jka[1];
00922 const Set<MultipleDeriv>& W1j = evaluatableChild(j)->findW(1, context);
00923 const Set<MultipleDeriv>& W1k = evaluatableChild(k)->findW(1, context);
00924 R13.merge(setDivision((*rtn)[3], setProduct(W1j, W1k)));
00925 }
00926 }
00927 SUNDANCE_MSG5(verb, tab1 << "R11 = " << R11 );
00928 SUNDANCE_MSG5(verb, tab1 << "R12 = " << R12 );
00929 SUNDANCE_MSG5(verb, tab1 << "R13 = " << R13 );
00930 SUNDANCE_MSG5(verb, tab1 << "R22 = " << R22 );
00931 SUNDANCE_MSG5(verb, tab1 << "R23 = " << R23 );
00932 SUNDANCE_MSG5(verb, tab1 << "R33 = " << R33 );
00933 Set<MultipleDeriv> R1 = R11;
00934 R1.merge(R12);
00935 R1.merge(R13);
00936 Set<MultipleDeriv> R2 = R22;
00937 R2.merge(R23);
00938 Set<MultipleDeriv> R3 = R33;
00939
00940 Set<MultipleDeriv> R0;
00941 bool childIsNeeded = (*rtn)[0].size() > 0;
00942 if (!childIsNeeded && R1.size() > 0) childIsNeeded = childIsRequired(i, 2, context);
00943 if (!childIsNeeded && R2.size() > 0) childIsNeeded = childIsRequired(i, 3, context);
00944 if (!childIsNeeded && R3.size() > 0) childIsNeeded = childIsRequired(i, 4, context);
00945 if (childIsNeeded) R0.put(MultipleDeriv());
00946
00947 Array<Set<MultipleDeriv> > RChild;
00948
00949 RChild.append(R0);
00950 if (maxOrder >= 1) RChild.append(R1);
00951 if (maxOrder >= 2) RChild.append(R2);
00952 if (maxOrder >= 3) RChild.append(R3);
00953 SUNDANCE_MSG4(verb, tab1 << "RChild = " << RChild );
00954 evaluatableChild(i)->determineR(context, RChild);
00955 }
00956
00957 printR(verb, rtn);
00958 SUNDANCE_MSG2(verb, tab0 << "done with EWC::internalDetermineR for "
00959 << toString());
00960
00961 return rtn;
00962 }
00963
00964
00965
00966
00967 void ExprWithChildren::displayNonzeros(std::ostream& os, const EvalContext& context) const
00968 {
00969 Tabs tabs0(0);
00970 os << tabs0 << "Nonzeros of " << toString() << std::endl;
00971 if (context.setupVerbosity() > 4)
00972 {
00973 os << tabs0 << "Diving into children " << std::endl;
00974 }
00975
00976 for (int i=0; i<numChildren(); i++)
00977 {
00978 Tabs tab1;
00979 if (context.setupVerbosity() > 4) os << tab1 << "Child " << i << std::endl;
00980 evaluatableChild(i)->displayNonzeros(os, context);
00981 }
00982
00983 if (context.setupVerbosity() > 4)
00984 os << tabs0 << "Printing nonzeros for parent " << toString() << std::endl;
00985 const Set<MultipleDeriv>& W = findW(context);
00986 const Set<MultipleDeriv>& R = findR(context);
00987 const Set<MultipleDeriv>& C = findC(context);
00988
00989
00990 for (Set<MultipleDeriv>::const_iterator i=W.begin(); i != W.end(); i++)
00991 {
00992 Tabs tab1;
00993 std::string state = "Variable";
00994 if (C.contains(*i)) state = "Constant";
00995 if (!R.contains(*i)) state = "Not Required";
00996 os << tab1 << std::setw(25) << std::left << i->toString() << ": " << state << std::endl;
00997 }
00998 }
00999
01000
01001 namespace Sundance {
01002
01003 Array<Array<std::pair<int, Array<MultipleDeriv> > > >
01004 chainRuleDerivsOfArgs(int nArgs,
01005 const MultiSet<int>& bSet,
01006 const MultipleDeriv& c)
01007 {
01008 Array<Array<std::pair<int, Array<MultipleDeriv> > > > rtn;
01009
01010
01011 Array<int> b(nArgs, 0);
01012 int J = 0;
01013 for (MultiSet<int>::const_iterator i=bSet.begin(); i!=bSet.end(); i++)
01014 {
01015 b[*i]++;
01016 J++;
01017 }
01018
01019
01020 Sundance::Map<Deriv, int> counts;
01021 Array<Deriv> d;
01022 typedef Sundance::Map<Deriv, int>::const_iterator iter;
01023 for (MultipleDeriv::const_iterator i=c.begin(); i!=c.end(); i++)
01024 {
01025 if (!counts.containsKey(*i)) counts.put(*i, 1);
01026 else counts[*i]++;
01027 d.append(*i);
01028 }
01029
01030 Array<Array<Array<Array<int> > > > a;
01031 Array<int> s;
01032 for (iter i=counts.begin(); i!=counts.end(); i++)
01033 {
01034 Array<Array<int> > tmp = nonNegCompositions(i->second, J);
01035 Array<Array<Array<int> > > ai = bStructure(b, tmp);
01036 a.append(ai);
01037 s.append(ai.size());
01038 }
01039
01040 Array<Array<int> > ic = indexCombinations(s);
01041
01042
01043
01044 Array<Array<Array<Array<int> > > > all;
01045 for (int i=0; i<ic.size(); i++)
01046 {
01047 bool good = true;
01048 int numFuncs = ic[i].size();
01049 Array<Array<Array<int> > > tmp;
01050
01051 Array<Array<int> > aTot(nArgs);
01052 for (int j=0; j<nArgs; j++)
01053 {
01054 if (b[j] > 0) aTot[j].resize(b[j]);
01055 for (int k=0; k<b[j]; k++) aTot[j][k] = 0;
01056 }
01057 for (int f=0; f<numFuncs; f++)
01058 {
01059 bool skip = false;
01060 const Array<Array<int> >& e = a[f][ic[i][f]];
01061 for (int j=0; j<nArgs; j++)
01062 {
01063 for (int k=0; k<b[j]; k++)
01064 {
01065 aTot[j][k] += e[j][k];
01066 }
01067 }
01068 if (!skip) tmp.append(e);
01069 }
01070
01071 for (int j=0; j<nArgs; j++)
01072 {
01073 for (int k=0; k<b[j]; k++)
01074 {
01075 if (aTot[j][k] == 0) good = false;
01076 }
01077 }
01078 if (good) all.append(tmp);
01079 }
01080
01081
01082 for (int p=0; p<all.size(); p++)
01083 {
01084 Array<std::pair<int, Array<MultipleDeriv> > > terms;
01085 for (int j=0; j<nArgs; j++)
01086 {
01087 std::pair<int, Array<MultipleDeriv> > factors;
01088 factors.first = j;
01089 for (int k=0; k<b[j]; k++)
01090 {
01091 MultipleDeriv md;
01092 for (int i=0; i<all[p].size(); i++)
01093 {
01094 int order = all[p][i][j][k];
01095 if (order > 0)
01096 {
01097 md.put(d[i]);
01098 }
01099 }
01100 if (md.order() > 0) factors.second.append(md);
01101 }
01102 if (factors.second.size() > 0) terms.append(factors);
01103 }
01104 rtn.append(terms);
01105 }
01106
01107 return rtn;
01108 }
01109
01110
01111 Array<Array<Array<int> > > bStructure(const Array<int>& b,
01112 const Array<Array<int> >& tmp)
01113 {
01114 Array<Array<Array<int> > > rtn(tmp.size());
01115
01116 for (int p=0; p<tmp.size(); p++)
01117 {
01118 int count=0;
01119 rtn[p].resize(b.size());
01120 for (int j=0; j<b.size(); j++)
01121 {
01122 rtn[p][j].resize(b[j]);
01123 for (int k=0; k<b[j]; k++, count++)
01124 {
01125 rtn[p][j][k] = tmp[p][count];
01126 }
01127 }
01128 }
01129 return rtn;
01130 }
01131
01132 Array<OrderedPair<Array<MultiSet<int> >, Array<MultipleDeriv> > >
01133 chainRuleTerms(int s,
01134 const MultiSet<int>& lambda,
01135 const MultipleDeriv& nu)
01136 {
01137 Array<Array<MultiSet<int> > > allK = multisetCompositions(s, lambda);
01138
01139 Array<MultipleDeriv> allL = multisetSubsets(nu).elements();
01140
01141 Array<Array<int> > indexTuples = distinctIndexTuples(s, allL.size());
01142
01143 Array<Array<MultipleDeriv> > allLTuples;
01144 for (int i=0; i<indexTuples.size(); i++)
01145 {
01146 Array<MultipleDeriv> t(s);
01147 for (int p=0; p<s; p++) t[p] = allL[indexTuples[i][p]];
01148 allLTuples.append(t);
01149 }
01150
01151 Array<OrderedPair<Array<MultiSet<int> >, Array<MultipleDeriv> > > rtn;
01152 for (int i=0; i<allLTuples.size(); i++)
01153 {
01154 for (int j=0; j<allK.size(); j++)
01155 {
01156 MultipleDeriv result;
01157 for (int p=0; p<s; p++)
01158 {
01159 for (unsigned int q=0; q<allK[j][p].size(); q++)
01160 {
01161 result = result.product(allLTuples[i][p]);
01162 }
01163 }
01164 if (result==nu)
01165 {
01166 OrderedPair<Array<MultiSet<int> >, Array<MultipleDeriv> >
01167 kl(allK[j], allLTuples[i]);
01168 rtn.append(kl);
01169 }
01170 }
01171 }
01172 return rtn;
01173 }
01174
01175 Set<MultipleDeriv> multisetSubsets(const MultipleDeriv& nu)
01176 {
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188 Array<Deriv> elements = nu.elements();
01189
01190
01191
01192 int n = elements.size();
01193 int maxNumSubsets = pow2(n);
01194
01195 Set<MultipleDeriv> rtn;
01196
01197
01198
01199
01200 for (int i=1; i<maxNumSubsets; i++)
01201 {
01202 Array<int> bits = bitsOfAnInteger(i, n);
01203 MultipleDeriv md;
01204 for (int j=0; j<n; j++)
01205 {
01206 if (bits[j] == 1) md.put(elements[j]);
01207 }
01208 rtn.put(md);
01209 }
01210 return rtn;
01211 }
01212
01213
01214
01215 int chainRuleMultiplicity(const MultipleDeriv& nu,
01216 const Array<MultiSet<int> >& K,
01217 const Array<MultipleDeriv>& L)
01218 {
01219 int rtn = factorial(nu);
01220 for (int i=0; i<K.size(); i++)
01221 {
01222 rtn = rtn/factorial(K[i]);
01223 int lFact = factorial(L[i]);
01224 int lPow = 1;
01225 int kNorm = K[i].size();
01226 for (int j=0; j<kNorm; j++) lPow *= lFact;
01227 TEUCHOS_TEST_FOR_EXCEPT(rtn % lPow != 0);
01228 rtn = rtn/lPow;
01229 }
01230 return rtn;
01231 }
01232
01233
01234 }
01235
01236
01237