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

Site Contact