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 "SundanceEvaluatableExpr.hpp"
00043 #include "SundanceEvaluatorFactory.hpp"
00044 #include "SundanceEvaluator.hpp"
00045 #include "SundanceNullEvaluator.hpp"
00046 #include "SundanceEvalManager.hpp"
00047 #include "SundanceSymbolicFuncElement.hpp"
00048 #include "SundanceExpr.hpp"
00049 #include "PlayaTabs.hpp"
00050 #include "SundanceOut.hpp"
00051 #include "Teuchos_Utils.hpp"
00052
00053 using namespace Sundance;
00054 using namespace Teuchos;
00055 using std::endl;
00056
00057 TEUCHOS_TIMER(evalTimer, "Symbolic Evaluation")
00058
00059 EvaluatableExpr::EvaluatableExpr()
00060 : ScalarExpr(),
00061 evaluators_(),
00062 sparsity_(),
00063 nodesHaveBeenCounted_(false),
00064 contextToDSSMap_(numDerivSubsetTypes(), contextToDSSMap_ele_t(maxFuncDiffOrder()+1)),
00065 rIsReady_(false),
00066 allOrdersMap_(numDerivSubsetTypes())
00067 {}
00068
00069
00070 Time& EvaluatableExpr::evaluationTimer()
00071 {
00072 return evalTimer();
00073 }
00074
00075 string EvaluatableExpr::derivType(const DerivSubsetSpecifier& dss) const
00076 {
00077 switch(dss)
00078 {
00079 case RequiredNonzeros:
00080 return "R";
00081 case ConstantNonzeros:
00082 return "C";
00083 case VariableNonzeros:
00084 return "V";
00085 default:
00086 return "W";
00087 }
00088 }
00089
00090 void EvaluatableExpr::registerSpatialDerivs(const EvalContext& context,
00091 const Set<MultiIndex>& miSet) const
00092 {
00093 Tabs tab;
00094 if (activeSpatialDerivMap_.containsKey(context))
00095 {
00096 Set<MultiIndex> s = activeSpatialDerivMap_[context];
00097 s.merge(miSet);
00098 activeSpatialDerivMap_.put(context, s);
00099 }
00100 else
00101 {
00102 activeSpatialDerivMap_.put(context, miSet);
00103 }
00104 }
00105
00106 const Set<MultiIndex>& EvaluatableExpr
00107 ::activeSpatialDerivs(const EvalContext& context) const
00108 {
00109 TEUCHOS_TEST_FOR_EXCEPTION(!activeSpatialDerivMap_.containsKey(context),
00110 std::logic_error,
00111 "Unknown context " << context);
00112 return activeSpatialDerivMap_[context];
00113 }
00114
00115 RCP<SparsitySuperset>
00116 EvaluatableExpr::sparsitySuperset(const EvalContext& context) const
00117 {
00118 Tabs tab;
00119
00120 SUNDANCE_MSG2(context.setupVerbosity(),
00121 tab << "getting sparsity superset for " << toString());
00122
00123 RCP<SparsitySuperset> rtn;
00124
00125 if (sparsity_.containsKey(context))
00126 {
00127 Tabs tab1;
00128 SUNDANCE_MSG2(context.setupVerbosity(),
00129 tab1 << "reusing previously computed data...");
00130 rtn = sparsity_.get(context);
00131 }
00132 else
00133 {
00134 Tabs tab1;
00135 SUNDANCE_MSG2(context.setupVerbosity(),
00136 tab1 << "computing from scratch...");
00137 const Set<MultipleDeriv>& R = findR(context);
00138 const Set<MultipleDeriv>& C = findC(context);
00139 const Set<MultipleDeriv>& V = findV(context);
00140 if (context.setupVerbosity() > 4)
00141 {
00142 Out::os() << tab1 << "R=" << R << endl;
00143 Out::os() << tab1 << "C=" << C << endl;
00144 Out::os() << tab1 << "V=" << V << endl;
00145 }
00146 rtn = rcp(new SparsitySuperset(C.intersection(R), V.intersection(R)));
00147 sparsity_.put(context, rtn);
00148 }
00149 return rtn;
00150 }
00151
00152
00153
00154 const RCP<Evaluator>&
00155 EvaluatableExpr::evaluator(const EvalContext& context) const
00156 {
00157 TEUCHOS_TEST_FOR_EXCEPTION(!evaluators_.containsKey(context), std::runtime_error,
00158 "Evaluator not found for context " << context);
00159 return evaluators_.get(context);
00160 }
00161
00162 void EvaluatableExpr::evaluate(const EvalManager& mgr,
00163 Array<double>& constantResults,
00164 Array<RCP<EvalVector> >& vectorResults) const
00165 {
00166 TimeMonitor timer(evalTimer());
00167 evaluator(mgr.getRegion())->eval(mgr, constantResults, vectorResults);
00168 }
00169
00170 void EvaluatableExpr::setupEval(const EvalContext& context) const
00171 {
00172 Tabs tabs0(0);
00173 int verb = context.evalSetupVerbosity();
00174 SUNDANCE_MSG1(verb, tabs0 << "setupEval() for " << this->toString());
00175 if (!evaluators_.containsKey(context))
00176 {
00177 Tabs tabs;
00178 SUNDANCE_MSG2(verb, tabs << "creating new evaluator...");
00179 SUNDANCE_MSG2(verb, tabs << "my sparsity superset = " << std::endl
00180 << *sparsitySuperset(context));
00181 RCP<Evaluator> eval;
00182 if (sparsitySuperset(context)->numDerivs()>0)
00183 {
00184 SUNDANCE_MSG2(verb, tabs << "calling createEvaluator()");
00185 eval = rcp(createEvaluator(this, context));
00186 }
00187 else
00188 {
00189 SUNDANCE_MSG2(verb,
00190 tabs << "EE: no results needed... creating null evaluator");
00191 eval = rcp(new NullEvaluator());
00192 }
00193 evaluators_.put(context, eval);
00194 }
00195 else
00196 {
00197 Tabs tabs;
00198 SUNDANCE_MSG2(verb, tabs << "reusing existing evaluator...");
00199 }
00200 }
00201
00202 void EvaluatableExpr::showSparsity(std::ostream& os,
00203 const EvalContext& context) const
00204 {
00205 Tabs tab0;
00206 os << tab0 << "Node: " << toString() << std::endl;
00207 sparsitySuperset(context)->print(os);
00208 }
00209
00210
00211
00212 int EvaluatableExpr::maxOrder(const Set<MultiIndex>& m) const
00213 {
00214 int rtn = 0;
00215 for (Set<MultiIndex>::const_iterator i=m.begin(); i != m.end(); i++)
00216 {
00217 rtn = std::max(i->order(), rtn);
00218 }
00219 return rtn;
00220 }
00221
00222 const EvaluatableExpr* EvaluatableExpr::getEvalExpr(const Expr& expr)
00223 {
00224 const EvaluatableExpr* rtn
00225 = dynamic_cast<const EvaluatableExpr*>(expr[0].ptr().get());
00226 TEUCHOS_TEST_FOR_EXCEPTION(rtn==0, std::logic_error,
00227 "cast of " << expr
00228 << " failed in EvaluatableExpr::getEvalExpr()");
00229 TEUCHOS_TEST_FOR_EXCEPTION(expr.size() != 1, std::logic_error,
00230 "non-scalar expression " << expr
00231 << " in EvaluatableExpr::getEvalExpr()");
00232
00233 return rtn;
00234 }
00235
00236
00237 bool EvaluatableExpr::isEvaluatable(const ExprBase* expr)
00238 {
00239 return dynamic_cast<const EvaluatableExpr*>(expr) != 0;
00240 }
00241
00242
00243 int EvaluatableExpr::countNodes() const
00244 {
00245 nodesHaveBeenCounted_ = true;
00246 return 1;
00247 }
00248
00249
00250
00251 const Set<MultipleDeriv>&
00252 EvaluatableExpr::findW(int order,
00253 const EvalContext& context) const
00254 {
00255 return findDerivSubset(order, AllNonzeros, context);
00256 }
00257
00258 const Set<MultipleDeriv>&
00259 EvaluatableExpr::findV(int order,
00260 const EvalContext& context) const
00261 {
00262 return findDerivSubset(order, VariableNonzeros, context);
00263 }
00264
00265 const Set<MultipleDeriv>&
00266 EvaluatableExpr::findC(int order,
00267 const EvalContext& context) const
00268 {
00269 return findDerivSubset(order, ConstantNonzeros, context);
00270 }
00271
00272 const Set<MultipleDeriv>&
00273 EvaluatableExpr::findR(int order,
00274 const EvalContext& context) const
00275 {
00276 TEUCHOS_TEST_FOR_EXCEPTION(!rIsReady_, std::logic_error,
00277 "findR() cannot be used for initial computation of the "
00278 "R subset. Calling object is " << toString());
00279 return findDerivSubset(order, RequiredNonzeros, context);
00280 }
00281
00282
00283 const Set<MultipleDeriv>&
00284 EvaluatableExpr::findDerivSubset(int order,
00285 const DerivSubsetSpecifier& dss,
00286 const EvalContext& context) const
00287 {
00288 Tabs tabs;
00289 int verb = context.setupVerbosity();
00290 SUNDANCE_MSG2(verb, tabs << "finding " << derivType(dss)
00291 << "[" << order << "] for " << toString());
00292 if (contextToDSSMap_[dss][order].containsKey(context))
00293 {
00294 Tabs tab1;
00295 SUNDANCE_MSG3(verb, tab1 << "...reusing previously computed data");
00296 }
00297 else
00298 {
00299 Tabs tab1;
00300 SUNDANCE_MSG3(verb, tab1 << "...need to call find<Set>");
00301 switch(dss)
00302 {
00303 case AllNonzeros:
00304 contextToDSSMap_[dss][order].put(context, internalFindW(order, context));
00305 break;
00306 case RequiredNonzeros:
00307 break;
00308 case VariableNonzeros:
00309 contextToDSSMap_[dss][order].put(context, internalFindV(order, context));
00310 break;
00311 case ConstantNonzeros:
00312 contextToDSSMap_[dss][order].put(context, internalFindC(order, context));
00313 break;
00314 default:
00315 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "this should never happen");
00316 }
00317 }
00318
00319
00320 if (!contextToDSSMap_[dss][order].containsKey(context))
00321 {
00322 contextToDSSMap_[dss][order].put(context, Set<MultipleDeriv>());
00323 }
00324 const Set<MultipleDeriv>& rtn = contextToDSSMap_[dss][order].get(context);
00325 SUNDANCE_MSG2(verb, tabs << "found " << rtn);
00326 return rtn;
00327 }
00328
00329
00330 Set<MultipleDeriv>
00331 EvaluatableExpr::setProduct(const Set<MultipleDeriv>& a,
00332 const Set<MultipleDeriv>& b) const
00333 {
00334 Set<MultipleDeriv> rtn;
00335 for (Set<MultipleDeriv>::const_iterator i=a.begin(); i!=a.end(); i++)
00336 {
00337 for (Set<MultipleDeriv>::const_iterator j=b.begin(); j!=b.end(); j++)
00338 {
00339 rtn.put(i->product(*j));
00340 }
00341 }
00342 return rtn;
00343 }
00344
00345 Set<MultiSet<int> > EvaluatableExpr::setDivision(const Set<MultiSet<int> >& s,
00346 int index) const
00347 {
00348 Set<MultiSet<int> > rtn;
00349 for (Set<MultiSet<int> >::const_iterator
00350 i=s.begin(); i!=s.end(); i++)
00351 {
00352 if (i->contains(index))
00353 {
00354 MultiSet<int> e = *i;
00355 e.erase(e.find(index));
00356 rtn.put(e);
00357 }
00358 }
00359 return rtn;
00360 }
00361
00362
00363 Set<MultipleDeriv>
00364 EvaluatableExpr::setDivision(const Set<MultipleDeriv>& a,
00365 const Set<MultipleDeriv>& b) const
00366 {
00367 Set<MultipleDeriv> rtn;
00368 for (Set<MultipleDeriv>::const_iterator i=a.begin(); i!=a.end(); i++)
00369 {
00370 for (Set<MultipleDeriv>::const_iterator j=b.begin(); j!=b.end(); j++)
00371 {
00372 MultipleDeriv c = i->factorOutDeriv(*j);
00373 if (c.size() != 0) rtn.put(c);
00374 if (*i == *j) rtn.put(MultipleDeriv());
00375 }
00376 }
00377 return rtn;
00378 }
00379
00380 void EvaluatableExpr::determineR(const EvalContext& context,
00381 const Array<Set<MultipleDeriv> >& RInput) const
00382 {
00383 Tabs tabs;
00384 RCP<Array<Set<MultipleDeriv> > > additionToR
00385 = internalDetermineR(context, RInput);
00386
00387 for (int i=0; i<RInput.size(); i++)
00388 {
00389 if ((*additionToR)[i].size()==0) continue;
00390 if (!contextToDSSMap_[RequiredNonzeros][i].containsKey(context))
00391 {
00392 contextToDSSMap_[RequiredNonzeros][i].put(context, (*additionToR)[i]);
00393 }
00394 else
00395 {
00396 contextToDSSMap_[RequiredNonzeros][i][context].merge((*additionToR)[i]);
00397 }
00398 }
00399 rIsReady_ = true;
00400
00401 }
00402
00403 RCP<Array<Set<MultipleDeriv> > > EvaluatableExpr
00404 ::internalDetermineR(const EvalContext& context,
00405 const Array<Set<MultipleDeriv> >& RInput) const
00406 {
00407 Tabs tab0(0);
00408 int verb = context.setupVerbosity();
00409 RCP<Array<Set<MultipleDeriv> > > rtn
00410 = rcp(new Array<Set<MultipleDeriv> >(RInput.size()));
00411
00412 SUNDANCE_MSG2(verb, tab0 << "EE::internalDetermineR() for " << toString() );
00413 SUNDANCE_MSG2(verb, tab0 << "RInput = " << RInput );
00414
00415 for (int i=0; i<RInput.size(); i++)
00416 {
00417 Tabs tab1;
00418 if (RInput[i].size()==0) continue;
00419 const Set<MultipleDeriv>& Wi = findW(i, context);
00420 SUNDANCE_MSG3(verb, tab1 << "W[" << i << "] = " << Wi );
00421 (*rtn)[i] = RInput[i].intersection(Wi);
00422 }
00423
00424 printR(verb, rtn);
00425 return rtn;
00426 }
00427
00428
00429 Array<Set<MultipleDeriv> > EvaluatableExpr
00430 ::computeInputR(const EvalContext& context,
00431 const Array<Set<MultiSet<int> > >& funcIDCombinations,
00432 const Array<Set<MultiIndex> >& spatialDerivs) const
00433 {
00434 int verb = context.setupVerbosity();
00435 Tabs tabs(0);
00436 SUNDANCE_MSG2(verb, tabs << "in EE::computeInputR()");
00437 Array<Set<MultipleDeriv> > rtn(funcIDCombinations.size());
00438 for (int order=0; order<funcIDCombinations.size(); order++)
00439 {
00440 Tabs tabs1;
00441 SUNDANCE_MSG2(verb, tabs << "order=" << order);
00442 SUNDANCE_MSG2(verb, tabs1 << "funcID combs="
00443 << funcIDCombinations[order]);
00444 const Set<MultipleDeriv>& W = findW(order, context);
00445 SUNDANCE_MSG2(verb, tabs1 << "W[order=" << order << "]=" << W);
00446
00447 for (Set<MultipleDeriv>::const_iterator i=W.begin(); i!=W.end(); i++)
00448 {
00449 Tabs tab2;
00450 const MultipleDeriv& nonzeroDeriv = *i;
00451 if (nonzeroDeriv.isInRequiredSet(funcIDCombinations[order],
00452 spatialDerivs[order]))
00453 {
00454 SUNDANCE_MSG2(verb, tab2 << "md=" << nonzeroDeriv
00455 << " added to inputR");
00456 rtn[order].put(nonzeroDeriv);
00457 }
00458 else
00459 {
00460 SUNDANCE_MSG2(verb, tab2 << "md=" << nonzeroDeriv << " not needed");
00461 }
00462 }
00463 }
00464 SUNDANCE_MSG2(verb, tabs << "inputR=" << rtn);
00465 return rtn;
00466 }
00467
00468
00469 const Set<MultipleDeriv>& EvaluatableExpr::findW(const EvalContext& context) const
00470 {
00471 return findDerivSubset(AllNonzeros, context);
00472 }
00473
00474 const Set<MultipleDeriv>& EvaluatableExpr::findR(const EvalContext& context) const
00475 {
00476 return findDerivSubset(RequiredNonzeros, context);
00477 }
00478
00479 const Set<MultipleDeriv>& EvaluatableExpr::findC(const EvalContext& context) const
00480 {
00481 return findDerivSubset(ConstantNonzeros, context);
00482 }
00483
00484 const Set<MultipleDeriv>& EvaluatableExpr::findV(const EvalContext& context) const
00485 {
00486 return findDerivSubset(VariableNonzeros, context);
00487 }
00488
00489 const Set<MultipleDeriv>&
00490 EvaluatableExpr::findDerivSubset(const DerivSubsetSpecifier& dss,
00491 const EvalContext& context) const
00492 {
00493 if (!allOrdersMap_[dss].containsKey(context))
00494 {
00495 Set<MultipleDeriv> tmp;
00496 for (int i=0; i<=3; i++)
00497 {
00498 tmp.merge(findDerivSubset(i, dss, context));
00499 }
00500 allOrdersMap_[dss].put(context, tmp);
00501 }
00502
00503 return allOrdersMap_[dss].get(context);
00504 }
00505
00506 void EvaluatableExpr::displayNonzeros(std::ostream& os, const EvalContext& context) const
00507 {
00508 Tabs tabs0;
00509 os << tabs0 << "Nonzeros of " << toString() << std::endl;
00510
00511 const Set<MultipleDeriv>& W = findW(context);
00512 const Set<MultipleDeriv>& R = findR(context);
00513 const Set<MultipleDeriv>& C = findC(context);
00514 const Set<MultipleDeriv>& V = findV(context);
00515
00516 TEUCHOS_TEST_FOR_EXCEPT(C.intersection(V).size() != 0);
00517
00518 for (Set<MultipleDeriv>::const_iterator i=W.begin(); i != W.end(); i++)
00519 {
00520 Tabs tab1;
00521 std::string state = "Variable";
00522 if (C.contains(*i)) state = "Constant";
00523 if (!R.contains(*i)) state = "Not Required";
00524 os << tab1 << std::setw(25) << std::left << i->toString() << ": " << state << std::endl;
00525 }
00526 }
00527
00528
00529 void EvaluatableExpr::printR(int verb,
00530 const RCP<Array<Set<MultipleDeriv> > >& R) const
00531 {
00532 Tabs tab(0);
00533 const Array<Set<MultipleDeriv> >& r = *R;
00534 for (int order=0; order<r.size(); order++)
00535 {
00536 Tabs tab1;
00537 SUNDANCE_MSG2(verb, tab << "order=" << order);
00538 SUNDANCE_MSG2(verb, tab1 << "R[" << order << "]=" << r[order]);
00539 }
00540 }