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