SundanceNonlinearUnaryOpEvaluator.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 "SundanceNonlinearUnaryOpEvaluator.hpp"
00032 #include "SundanceEvalManager.hpp"
00033 
00034 #include "PlayaTabs.hpp"
00035 #include "SundanceOut.hpp"
00036 #include "SundanceNonlinearUnaryOp.hpp"
00037 
00038 using namespace Sundance;
00039 using namespace Sundance;
00040 using namespace Sundance;
00041 using namespace Teuchos;
00042 
00043 
00044 
00045 
00046 
00047 NonlinearUnaryOpEvaluator
00048 ::NonlinearUnaryOpEvaluator(const NonlinearUnaryOp* expr,
00049                             const EvalContext& context)
00050   : ChainRuleEvaluator(expr, context),
00051     op_(expr->op()),
00052     maxOrder_(-1),
00053     argIsConstant_(true),
00054     argValueIndex_(-1)
00055 {
00056   Tabs tabs;
00057   SUNDANCE_VERB_LOW(tabs << "NonlinearUnaryOp evaluator ctor for " 
00058                     << expr->toString());
00059 
00060   
00061   const SparsitySuperset* sArg = childSparsity(0);
00062   SUNDANCE_VERB_HIGH(tabs << "arg sparsity " << *sArg);
00063   maxOrder_ = expr->sparsitySuperset(context)->maxOrder();
00064 
00065   /* See if the argument is non-constant */
00066   for (int i=0; i<sArg->numDerivs(); i++)
00067     {
00068       if (sArg->state(i) == VectorDeriv) 
00069         {
00070           argIsConstant_ = false;
00071           break;
00072         }
00073     }
00074 
00075   /* We will need derivatives of the operator wrt the argument value for
00076    * orders up to maxOrder. Define their locations in the argDeriv array. */
00077   for (int order=0; order<=maxOrder_; order++)
00078     {
00079       MultiSet<int> df;
00080       /* The index set for the N-th order arg deriv is the arg index (0)
00081        * replicated N times. */
00082       for (int i=0; i<order; i++) df.put(0);
00083 
00084       if (argIsConstant_) addConstArgDeriv(df, order);
00085       else addVarArgDeriv(df, order);
00086     }
00087 
00088   
00089   /* Find the index of the argument value (zeroth-order deriv) in the 
00090    * vector of derivatives of the argument */
00091   MultipleDeriv d0;
00092   TEUCHOS_TEST_FOR_EXCEPTION(!sArg->containsDeriv(d0), std::logic_error,
00093                      "NonlinearUnaryOpEvaluator::ctor did not find zeroth-order "
00094                      "derivative of argument");
00095   int d0Index = sArg->getIndex(d0);
00096   const Evaluator* argEv = childEvaluator(0);
00097   if (argIsConstant_) argValueIndex_ = argEv->constantIndexMap().get(d0Index);
00098   else argValueIndex_ = argEv->vectorIndexMap().get(d0Index);
00099 
00100 
00101   SUNDANCE_VERB_HIGH(tabs << "arg is constant: " << argIsConstant_);
00102   SUNDANCE_VERB_HIGH(tabs << "arg value index: " << argValueIndex_);
00103   /* Call init() at the base class to set up chain rule evaluation */
00104   init(expr, context);
00105 }
00106 
00107 
00108 void NonlinearUnaryOpEvaluator
00109 ::evalArgDerivs(const EvalManager& mgr,
00110                 const Array<RCP<Array<double> > >& constArgRes,
00111                 const Array<RCP<Array<RCP<EvalVector> > > >& vArgResults,
00112                 Array<double>& constArgDerivs,
00113                 Array<RCP<EvalVector> >& varArgDerivs) const
00114 {
00115   Tabs tabs;
00116   SUNDANCE_MSG1(mgr.verb(), tabs 
00117     << "NonlinearUnaryOpEvaluator::evalArgDerivs() for " 
00118     << expr()->toString());
00119   
00120   if (argIsConstant_)
00121     {
00122       double argValue = (*(constArgRes[0]))[argValueIndex_];
00123       constArgDerivs.resize(maxOrder_+1);
00124       switch(maxOrder_)
00125         {
00126         case 0:
00127           op_->eval0(&argValue, 1, &(constArgDerivs[0]));
00128           break;
00129         case 1:
00130           op_->eval1(&argValue, 1, &(constArgDerivs[0]), &(constArgDerivs[1]));
00131           break;
00132         case 2:
00133           op_->eval2(&argValue, 1, &(constArgDerivs[0]), &(constArgDerivs[1]),
00134                      &(constArgDerivs[2]));
00135           break;
00136         case 3:
00137           op_->eval3(&argValue, 1, &(constArgDerivs[0]), &(constArgDerivs[1]),
00138                      &(constArgDerivs[2]), &(constArgDerivs[3]));
00139           break;
00140         default:
00141           TEUCHOS_TEST_FOR_EXCEPT(true);
00142         }
00143     }
00144   else
00145     {
00146       Tabs tab1;
00147       SUNDANCE_MSG2(mgr.verb(), 
00148         tab1 << "argument is a vector: argValIndex=" << argValueIndex_);
00149       SUNDANCE_MSG2(mgr.verb(), 
00150         tab1 << "num vector results =" << vArgResults.size());
00151 
00152       const Array<RCP<EvalVector> >& av = *(vArgResults[0]);
00153 
00154       SUNDANCE_MSG2(mgr.verb(), 
00155         tab1 << "av size=" << av.size());
00156 
00157 
00158       const double* argValue = av[argValueIndex_]->start();
00159       varArgDerivs.resize(maxOrder_+1);
00160       varArgDerivs[0] = mgr.stack().popVector();
00161       int nx = varArgDerivs[0]->length();
00162 
00163       const std::string& argStr = (*(vArgResults[0]))[argValueIndex_]->str();
00164       if (EvalVector::shadowOps())
00165         {
00166           varArgDerivs[0]->setString(op_->name() + "(" + argStr + ")");
00167         }
00168 
00169       double* f = varArgDerivs[0]->start();
00170       double* df_dArg = 0 ;
00171       if (maxOrder_ >= 1) 
00172         {
00173           varArgDerivs[1] = mgr.stack().popVector();
00174           if (EvalVector::shadowOps())
00175             {
00176               varArgDerivs[1]->setString(op_->name() + "'(" + argStr + ")");
00177             }
00178           df_dArg = varArgDerivs[1]->start();
00179         }
00180       double* d2f_dArg2 = 0 ;
00181       if (maxOrder_ >= 2) 
00182         {
00183           varArgDerivs[2] =mgr.stack().popVector();
00184           if (EvalVector::shadowOps())
00185             {
00186               varArgDerivs[2]->setString(op_->name() + "''(" + argStr + ")");
00187             }
00188           d2f_dArg2 = varArgDerivs[2]->start();
00189         }
00190       double* d3f_dArg3 = 0 ;
00191       if (maxOrder_ >= 3) 
00192         {
00193           UnaryFunctor::fdStep()=1.0e-3;
00194           varArgDerivs[3] = mgr.stack().popVector();
00195           if (EvalVector::shadowOps())
00196             {
00197               varArgDerivs[3]->setString(op_->name() + "'''(" + argStr + ")");
00198             }
00199           d3f_dArg3 = varArgDerivs[3]->start();
00200         }
00201 
00202       switch(maxOrder_)
00203         {
00204         case 0:
00205           op_->eval0(argValue, nx, f);
00206           break;
00207         case 1:
00208           TEUCHOS_TEST_FOR_EXCEPT(df_dArg==0);
00209           op_->eval1(argValue, nx, f, df_dArg);
00210           break;
00211         case 2:
00212           TEUCHOS_TEST_FOR_EXCEPT(df_dArg==0);
00213           TEUCHOS_TEST_FOR_EXCEPT(d2f_dArg2==0);
00214           op_->eval2(argValue, nx, f, df_dArg, d2f_dArg2);
00215           break;
00216         case 3:
00217           TEUCHOS_TEST_FOR_EXCEPT(df_dArg==0);
00218           TEUCHOS_TEST_FOR_EXCEPT(d2f_dArg2==0);
00219           TEUCHOS_TEST_FOR_EXCEPT(d3f_dArg3==0);
00220           op_->eval3(argValue, nx, f, df_dArg, d2f_dArg2, d3f_dArg3);
00221           break;
00222         default:
00223           TEUCHOS_TEST_FOR_EXCEPT(true);
00224         }
00225     }
00226 
00227   SUNDANCE_MSG1(mgr.verb(),
00228     tabs << "done NonlinearUnaryOpEvaluator::evalArgDerivs() for " 
00229     << expr()->toString());
00230 }
00231 
00232 
00233 

Site Contact