SundanceEvaluatableExpr.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                              Sundance
00005 //                 Copyright (2005) Sandia Corporation
00006 // 
00007 // Copyright (year first published) Sandia Corporation.  Under the terms 
00008 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 
00009 // retains certain rights in this software.
00010 // 
00011 // This library is free software; you can redistribute it and/or modify
00012 // it under the terms of the GNU Lesser General Public License as
00013 // published by the Free Software Foundation; either version 2.1 of the
00014 // License, or (at your option) any later version.
00015 //  
00016 // This library is distributed in the hope that it will be useful, but
00017 // WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 // Lesser General Public License for more details.
00020 //                                                                                 
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License along with this library; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00024 // USA                                                                                
00025 // Questions? Contact Kevin Long (krlong@sandia.gov), 
00026 // Sandia National Laboratories, Livermore, California, USA
00027 // 
00028 // ************************************************************************
00029 /* @HEADER@ */
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 }

Site Contact