SundanceSymbolicFuncEvaluator.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 "SundanceSubtypeEvaluator.hpp"
00032 #include "SundanceEvalManager.hpp"
00033 #include "SundanceSymbolicFuncEvaluator.hpp"
00034 #include "SundanceDiscreteFuncEvaluator.hpp"
00035 #include "SundanceConstantEvaluator.hpp"
00036 #include "SundanceSymbolicFuncElement.hpp"
00037 #include "SundanceDiscreteFuncElement.hpp"
00038 #include "SundanceParameter.hpp"
00039 #include "SundanceZeroExpr.hpp"
00040 #include "SundanceSet.hpp"
00041 #include "SundanceTabs.hpp"
00042 #include "SundanceOut.hpp"
00043 
00044 using namespace Sundance;
00045 using namespace Sundance;
00046 
00047 using namespace Sundance;
00048 using namespace Teuchos;
00049 
00050 
00051 
00052 SymbolicFuncElementEvaluator
00053 ::SymbolicFuncElementEvaluator(const SymbolicFuncElement* expr, 
00054                                const EvalContext& context)
00055   : SubtypeEvaluator<SymbolicFuncElement>(expr, context),
00056     mi_(),
00057     spatialDerivPtrs_(),
00058     onePtrs_(),
00059     paramValuePtrs_(),
00060     df_(dynamic_cast<const DiscreteFuncElement*>(expr->evalPt())),
00061     p_(dynamic_cast<const Parameter*>(expr->evalPt())),
00062     stringReps_()
00063 {
00064   
00065   Tabs tabs;
00066   SUNDANCE_VERB_LOW(tabs << "initializing symbolic func evaluator for " 
00067                     << expr->toString());
00068 
00069   SUNDANCE_VERB_MEDIUM(tabs << "return sparsity " << std::endl << *(this->sparsity)());
00070 
00071   const ZeroExpr* z 
00072     = dynamic_cast<const ZeroExpr*>(expr->evalPt());
00073   
00074   TEST_FOR_EXCEPTION(z==0 && df_==0, InternalError,
00075                      "SymbolicFuncElementEvaluator ctor detected an "
00076                      "evaluation point=" << expr->toString()
00077                      << " that is neither zero nor a discrete "
00078                      "function.");
00079 
00080 
00081   static Array<string> coordNames;
00082   if (coordNames.size() != 3)
00083     {
00084       coordNames.resize(3);
00085       coordNames[0] = "x";
00086       coordNames[1] = "y";
00087       coordNames[2] = "z";
00088     }
00089   
00090   int constantCounter = 0;
00091   int vectorCounter = 0;
00092 
00093   Set<MultiIndex> miSet;
00094   
00095   for (int i=0; i<this->sparsity()->numDerivs(); i++) 
00096     {
00097       if (this->sparsity()->isSpatialDeriv(i))
00098         {
00099           /* evaluate the spatial deriv applied to the evaluation point */
00100           TEST_FOR_EXCEPTION(z != 0, InternalError,
00101                              "SymbolicFuncElementEvaluator ctor detected a "
00102                              "spatial derivative of a zero function. All "
00103                              "such expressions should have been "
00104                              "automatically eliminated by this point.");
00105           TEST_FOR_EXCEPTION(p_ != 0, InternalError,
00106                              "SymbolicFuncElementEvaluator ctor detected a "
00107                              "spatial derivative of a constant parameter. All "
00108                              "such expressions should have been "
00109                              "automatically eliminated by this point.");
00110 
00111           mi_.append(this->sparsity()->multiIndex(i));
00112           miSet.put(this->sparsity()->multiIndex(i));
00113           addVectorIndex(i, vectorCounter);
00114           spatialDerivPtrs_.append(vectorCounter++);
00115           int dir = this->sparsity()->multiIndex(i).firstOrderDirection();
00116           string deriv = "D[" + df_->name() + ", " + coordNames[dir] + "]";
00117           stringReps_.append(deriv);
00118         }
00119       else
00120         {
00121           TEST_FOR_EXCEPTION(this->sparsity()->deriv(i).order() > 1,
00122                              InternalError,
00123                              "SymbolicFuncElementEvaluator ctor detected a "
00124                              "nonzero functional derivative of order greater "
00125                              "than one. All such derivs should have been "
00126                              "identified as zero by this point. The bad "
00127                              "derivative is " << this->sparsity()->deriv(i)
00128                              << ", and the bad sparsity table is "
00129                              << *(this->sparsity)());
00130 
00131           if (this->sparsity()->deriv(i).order()==0)
00132             {
00133               TEST_FOR_EXCEPTION(z != 0, InternalError,
00134                              "SymbolicFuncElementEvaluator ctor detected a "
00135                              "zero-order derivative of a zero function. All "
00136                              "such expressions should have been "
00137                              "automatically eliminated by this point.");
00138               /* value of zeroth functional deriv is either 
00139                * a discrete function or a parameter */
00140               if (p_ == 0)
00141                 {
00142                   addVectorIndex(i, vectorCounter);
00143                   spatialDerivPtrs_.append(vectorCounter++);
00144                 }
00145               else
00146                 {
00147                   addConstantIndex(i, constantCounter);
00148                   paramValuePtrs_.append(constantCounter++);
00149                 }
00150               mi_.append(MultiIndex());
00151               miSet.put(MultiIndex());
00152               stringReps_.append(df_->name());
00153             }
00154           else
00155             {
00156               /* value of first functional deriv is one */
00157               addConstantIndex(i, constantCounter);
00158               onePtrs_.append(constantCounter++);
00159             }
00160         }
00161     }
00162 
00163   if (p_==0 && df_ != 0)
00164     {
00165       SUNDANCE_VERB_MEDIUM(tabs << "setting up evaluation for discrete eval pt");
00166       df_->setupEval(context);
00167       dfEval_ = dynamic_cast<const DiscreteFuncElementEvaluator*>(df_->evaluator(context).get());
00168     }
00169   else if (p_ != 0)
00170     {
00171       SUNDANCE_VERB_MEDIUM(tabs << "setting up evaluation for parameter eval pt");
00172       p_->setupEval(context);
00173       pEval_ = dynamic_cast<const ConstantEvaluator*>(p_->evaluator(context).get());
00174     }
00175 }
00176 
00177 
00178 
00179 
00180 void SymbolicFuncElementEvaluator
00181 ::internalEval(const EvalManager& mgr,
00182                Array<double>& constantResults,
00183                Array<RCP<EvalVector> >& vectorResults) const 
00184 {
00185   Tabs tabs;
00186   
00187   SUNDANCE_MSG1(mgr.verb(), 
00188     tabs << "SymbolicFuncElementEvaluator::eval: expr=" 
00189     << expr()->toString());
00190   SUNDANCE_MSG2(mgr.verb(), tabs << "sparsity = " 
00191     << std::endl << *(this->sparsity)());
00192 
00193   constantResults.resize(onePtrs_.size() + paramValuePtrs_.size());
00194   vectorResults.resize(spatialDerivPtrs_.size());
00195 
00196   /* Evaluate discrete functions if necessary */
00197   if (p_==0 && df_ != 0 && mi_.size() > 0)
00198     {
00199       for (int i=0; i<mi_.size(); i++)
00200         {
00201           vectorResults[i] = mgr.popVector();
00202           TEST_FOR_EXCEPTION(!vectorResults[i]->isValid(), 
00203                              InternalError,
00204                              "invalid evaluation vector allocated in "
00205                              "SymbolicFuncElementEvaluator::internalEval()");
00206           vectorResults[i]->setString(stringReps_[i]);
00207         }
00208       mgr.evalDiscreteFuncElement(df_, mi_, vectorResults);
00209       mgr.stack().setVecSize(vectorResults[0]->length());
00210     }
00211   if (p_!=0 && mi_.size() > 0)
00212     {
00213       Array<RCP<EvalVector> > paramVectorResults;
00214       Array<double> paramConstResults;
00215       pEval_->eval(mgr, paramConstResults, paramVectorResults);
00216       constantResults[paramValuePtrs_[0]] = paramConstResults[0];
00217     }
00218 
00219   /* Set the known one entries to one */
00220   for (int i=0; i<onePtrs_.size(); i++)
00221     {
00222       constantResults[onePtrs_[i]] = 1.0;
00223     }
00224   if (verb() > 2)
00225     {
00226       Out::os() << tabs << "results " << std::endl;
00227       this->sparsity()->print(Out::os(), vectorResults,
00228                             constantResults);
00229     }
00230   SUNDANCE_MSG1(mgr.verb(), tabs << "SymbolicFuncEvaluator::eval() done"); 
00231 
00232 }
00233 
00234 

Site Contact