00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
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
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
00087
00088 for (int order=0; order<=maxOrder_; order++)
00089 {
00090 MultiSet<int> df;
00091
00092
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
00101
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
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