SundanceDerivOfSymbFuncEvaluator.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 "SundanceDerivOfSymbFuncEvaluator.hpp"
00043 #include "SundanceEvalManager.hpp"
00044 #include "SundanceDerivOfSymbFunc.hpp"
00045 
00046 #include "PlayaTabs.hpp"
00047 #include "SundanceOut.hpp"
00048 #include "SundanceUnknownFuncElement.hpp"
00049 #include "SundanceTestFuncElement.hpp"
00050 #include "SundanceDiscreteFuncElement.hpp"
00051 #include "SundanceDiscreteFuncEvaluator.hpp"
00052 #include "SundanceZeroExpr.hpp"
00053 
00054 using namespace Sundance;
00055 using namespace Sundance;
00056 using namespace Sundance;
00057 using namespace Teuchos;
00058 
00059 
00060 
00061 
00062 
00063 DerivOfSymbFuncEvaluator
00064 ::DerivOfSymbFuncEvaluator(const DerivOfSymbFunc* expr,
00065                            const EvalContext& context)
00066   : UnaryEvaluator<DerivOfSymbFunc>(expr, context),
00067     funcEvaluator_(),
00068     funcMiIndex_(-1),
00069     evalPtIsZero_(false),
00070     constResultIndex_(-1),
00071     funcSparsitySuperset_()
00072 {
00073   Tabs tabs;
00074   int verb = context.setupVerbosity();
00075   SUNDANCE_MSG1(verb, tabs << "initializing DerivOfSymbFunc evaluator for " 
00076                     << expr->toString());
00077 
00078   SUNDANCE_MSG2(verb, tabs << "return sparsity " << std::endl << *(this->sparsity)());
00079 
00080   const MultiIndex& mi = expr->mi();
00081   const SymbolicFuncElement* sf 
00082     = dynamic_cast<const SymbolicFuncElement*>(expr->evaluatableArg());
00083 
00084   TEUCHOS_TEST_FOR_EXCEPTION(sf==0, std::logic_error,
00085                      "Non-symbolic function detected where a symbolic "
00086                      "function was expected in "
00087                      "DerivOfSymbFuncEvaluator ctor");
00088   
00089   const TestFuncElement* t = dynamic_cast<const TestFuncElement*>(sf);
00090   const UnknownFuncElement* u = dynamic_cast<const UnknownFuncElement*>(sf);
00091 
00092   /* If we have a test function, its value will be zero. The only nonzero
00093    * functional derivative will be wrt D[f, mi]. The value of that deriv
00094    * is one. */
00095   if (t != 0)
00096     {
00097       constResultIndex_ = 0;
00098       addConstantIndex(0, constResultIndex_);
00099       evalPtIsZero_ = true;
00100       return;
00101     }
00102 
00103   /* If we have an unknown function, we need to see if it is to
00104    * be evaluated at zero. */
00105   
00106   TEUCHOS_TEST_FOR_EXCEPTION(u==0, std::logic_error,
00107                      "Non-unknown function detected where an unknown "
00108                      "function was expected in "
00109                      "DerivOfSymbFuncEvaluator ctor");
00110   
00111   const EvaluatableExpr* evalPt = u->evalPt();
00112   const ZeroExpr* z = dynamic_cast<const ZeroExpr*>(evalPt);
00113 
00114   if (z != 0) 
00115     {
00116       constResultIndex_ = 0;
00117       addConstantIndex(0, constResultIndex_);
00118       evalPtIsZero_ = true;
00119       return;
00120     }
00121   else
00122     {
00123       SUNDANCE_MSG2(verb, tabs << "setting up evaluation for discrete eval pt");
00124       u->setupEval(context);
00125     }
00126   
00127   int vecResultIndex = 0;
00128   for (int i=0; i<this->sparsity()->numDerivs(); i++)
00129     {
00130       if (this->sparsity()->state(i)==ConstantDeriv) 
00131         {
00132           constResultIndex_ = 0;
00133           addConstantIndex(i, constResultIndex_);
00134           continue;
00135         }
00136       else
00137         {
00138           addVectorIndex(i, vecResultIndex++);
00139           /* we have a nonzero evaluation point. We now need to find 
00140            * the index of my multiindex in the function's result set */
00141 
00142           const DiscreteFuncElement* df 
00143             = dynamic_cast<const DiscreteFuncElement*>(evalPt);
00144           
00145           TEUCHOS_TEST_FOR_EXCEPTION(df==0, std::logic_error,
00146                              "DerivOfSymbFuncEvaluator ctor: evaluation point of "
00147                              "unknown function " << u->toString() 
00148                              << " is not a discrete function");
00149   
00150           const SymbolicFuncElementEvaluator* uEval 
00151             = dynamic_cast<const SymbolicFuncElementEvaluator*>(u->evaluator(context).get());
00152           TEUCHOS_TEST_FOR_EXCEPTION(uEval==0, std::logic_error,
00153                              "DerivOfSymbFuncEvaluator ctor: null evaluator for "
00154                              "evaluation point");
00155           
00156           const DiscreteFuncElementEvaluator* dfEval = uEval->dfEval();
00157 
00158           TEUCHOS_TEST_FOR_EXCEPTION(dfEval==0, std::logic_error,
00159                              "DerivOfSymbFuncEvaluator ctor: evaluator for "
00160                              "evaluation point is not a "
00161                              "DiscreteFuncElementEvaluator");
00162 
00163           funcEvaluator_.append(dfEval);
00164           funcSparsitySuperset_ = dfEval->sparsity();
00165 
00166   
00167           TEUCHOS_TEST_FOR_EXCEPTION(!dfEval->hasMultiIndex(mi), std::logic_error,
00168                              "DerivOfSymbFuncEvaluator ctor: evaluator for "
00169                              "discrete function " << df->toString()
00170                              << " does not know about multiindex "
00171                              << mi.toString());
00172   
00173           funcMiIndex_ = dfEval->miIndex(mi);
00174         }
00175     }
00176 }
00177 
00178 
00179 
00180 void DerivOfSymbFuncEvaluator::internalEval(const EvalManager& mgr,
00181   Array<double>& constantResults,
00182   Array<RCP<EvalVector> >& vectorResults)  const
00183 {
00184   Tabs tabs;
00185   SUNDANCE_MSG1(mgr.verb(), tabs << "DerivOfSymbFuncEvaluator::eval() expr=" 
00186     << expr()->toString());
00187 
00188   /* if the function is a test or zero func, we can take a quick way out */
00189   if (evalPtIsZero_)
00190     {
00191       Tabs tabs1;
00192       SUNDANCE_MSG2(mgr.verb(), tabs1 << "taking zero function shortcut");
00193       constantResults.resize(1);
00194       constantResults[0] = 1.0;
00195       return;
00196     }
00197 
00198   if (constResultIndex_ >= 0)
00199     {
00200       constantResults.resize(1);
00201       constantResults[0] = 1.0;
00202     }
00203   if (funcMiIndex_ >= 0)
00204     {
00205       Tabs tabs1;
00206       SUNDANCE_MSG2(mgr.verb(), tabs1 << "evaluating argument");
00207       /* evaluate the argument */
00208       Array<RCP<EvalVector> > funcVectorResults;
00209       Array<double> funcConstantResults;
00210       
00211       funcEvaluator_[0]->eval(mgr, 
00212         funcConstantResults, funcVectorResults);
00213       if (mgr.verb() > 1)
00214         {
00215           Out::os() << tabs1 << "DerivOfSymbFunc results" << std::endl;
00216           funcSparsitySuperset_->print(Out::os(), funcVectorResults,
00217                                        funcConstantResults);
00218         }
00219       vectorResults.resize(1);
00220       vectorResults[0] = funcVectorResults[funcMiIndex_];
00221     }
00222 }
00223 
00224 
00225 
00226 void DerivOfSymbFuncEvaluator::resetNumCalls() const 
00227 {
00228   if (funcEvaluator_.size() > 0)
00229     {
00230       funcEvaluator_[0]->resetNumCalls();
00231     }
00232   Evaluator::resetNumCalls();
00233 }

Site Contact