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 "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 

Site Contact