SundanceEvaluatableExpr.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                             Sundance
00005 //                 Copyright 2011 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
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 }

Site Contact