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