SundanceDiffOpEvaluator.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 "SundanceDiffOpEvaluator.hpp"
00043 #include "SundanceEvalManager.hpp"
00044 #include "SundanceDiffOp.hpp"
00045 
00046 
00047 #include "PlayaTabs.hpp"
00048 #include "SundanceOut.hpp"
00049 #include "SundanceUnknownFuncElement.hpp"
00050 #include "SundanceTestFuncElement.hpp"
00051 #include "SundanceDiscreteFuncElement.hpp"
00052 #include "SundanceDiscreteFuncEvaluator.hpp"
00053 #include "SundanceEvaluatableExpr.hpp"
00054 #include "SundanceZeroExpr.hpp"
00055 
00056 using namespace Sundance;
00057 using namespace Sundance;
00058 using namespace Sundance;
00059 using namespace Teuchos;
00060 
00061 
00062 
00063 
00064 
00065 DiffOpEvaluator
00066 ::DiffOpEvaluator(const DiffOp* expr,
00067   const EvalContext& context)
00068   : UnaryEvaluator<DiffOp>(expr, context),
00069     isConstant_(this->sparsity()->numDerivs()),
00070     resultIndices_(this->sparsity()->numDerivs()),
00071     constantMonomials_(this->sparsity()->numDerivs()),
00072     vectorMonomials_(this->sparsity()->numDerivs()),
00073     constantFuncCoeffs_(this->sparsity()->numDerivs()),
00074     vectorFuncCoeffs_(this->sparsity()->numDerivs()),
00075     funcEvaluators_(),
00076     constantCoeffFuncIndices_(this->sparsity()->numDerivs()),
00077     constantCoeffFuncMi_(this->sparsity()->numDerivs()),
00078     vectorCoeffFuncIndices_(this->sparsity()->numDerivs()),
00079     vectorCoeffFuncMi_(this->sparsity()->numDerivs())
00080 {
00081   int verb = context.setupVerbosity();
00082   Tabs tabs;
00083   SUNDANCE_MSG1(verb, tabs << "initializing diff op evaluator for " 
00084     << expr->toString());
00085 
00086   {
00087     Tabs tab0;
00088   
00089     SUNDANCE_MSG2(verb, tab0 << "return sparsity " << std::endl << *(this->sparsity)());
00090 
00091     SUNDANCE_MSG2(verb, tab0 << "argument sparsity subset " << std::endl 
00092       << *(argSparsitySuperset()));
00093 
00094     Map<const DiscreteFuncElementEvaluator*, int> funcToIndexMap;
00095 
00096     int vecResultIndex = 0;
00097     int constResultIndex = 0;
00098   
00099     for (int i=0; i<this->sparsity()->numDerivs(); i++)
00100     {
00101       Tabs tab1;
00102       const MultipleDeriv& resultDeriv = this->sparsity()->deriv(i);
00103       SUNDANCE_MSG3(verb, tab0 << "working out procedure for computing " 
00104         << resultDeriv);
00105 
00106       if (this->sparsity()->state(i)==ConstantDeriv)
00107       {
00108         Tabs tab2;
00109         addConstantIndex(i, constResultIndex);
00110         resultIndices_[i] = constResultIndex++;
00111         isConstant_[i] = true;
00112         SUNDANCE_MSG3(verb, tab2 << "deriv is constant, will be stored at index "
00113           << resultIndices_[i] << " in the const result array");
00114       }
00115       else
00116       {
00117         Tabs tab2;
00118         addVectorIndex(i, vecResultIndex);
00119         resultIndices_[i] = vecResultIndex++;
00120         isConstant_[i] = false;
00121         SUNDANCE_MSG3(verb, tab2 << "deriv is variable, will be stored at index "
00122           << resultIndices_[i] << " in the var result array");
00123       }
00124 
00125       int order = resultDeriv.order();
00126       const Set<MultipleDeriv>& RArg 
00127         = argExpr()->findR(order, context);
00128       const Set<MultipleDeriv>& RArgPlus
00129         = argExpr()->findR(order+1, context);
00130       const Set<MultipleDeriv>& W1Arg 
00131         = argExpr()->findW(1, context);
00132 
00133         
00134       SUNDANCE_MSG3(verb, tab1 << "RArg = " << RArg);
00135       SUNDANCE_MSG3(verb, tab1 << "RArgPlus = " << RArgPlus);
00136       SUNDANCE_MSG3(verb, tab1 << "W1Arg = " << W1Arg);
00137 
00138       Set<MultipleDeriv> funcTermCoeffs 
00139         = RArgPlus.intersection(increasedDerivs(resultDeriv, W1Arg, verb));
00140       SUNDANCE_MSG3(verb, tab1 << "function term coeffs = " << funcTermCoeffs);
00141 
00142       
00143       if (funcTermCoeffs.size()==0)
00144       {
00145         SUNDANCE_MSG3(verb, tab1 << "no direct chain rule terms");
00146       }
00147       else
00148       {
00149         SUNDANCE_MSG3(verb, tab1 << "getting direct chain rule terms");
00150       }
00151 
00152 
00153       for (Set<MultipleDeriv>::const_iterator 
00154              j=funcTermCoeffs.begin(); j != funcTermCoeffs.end(); j++)
00155       {
00156         Tabs tab2;
00157         SUNDANCE_MSG3(verb, tab2 << "getting coefficient of " << *j);
00158 
00159         int argIndex = argSparsitySuperset()->getIndex(*j);
00160         TEUCHOS_TEST_FOR_EXCEPTION(argIndex==-1, std::runtime_error,
00161           "Derivative " << *j << " expected in argument "
00162           "but not found");
00163 
00164         Deriv lambda = remainder(*j, resultDeriv, verb);
00165 
00166         if (lambda.isCoordDeriv())
00167         {
00168           Tabs tab3;
00169           SUNDANCE_MSG3(verb, tab2 << "detected coordinate deriv");
00170           if (lambda.coordDerivDir()!=expr->mi().firstOrderDirection())
00171           {
00172             SUNDANCE_MSG3(verb, tab2 << "direction mismatch, skipping");
00173             continue;
00174           }
00175           const DerivState& argState = argSparsitySuperset()->state(argIndex);
00176           if (argState==ConstantDeriv)
00177           {
00178             int constArgIndex = argEval()->constantIndexMap().get(argIndex);
00179             constantMonomials_[i].append(constArgIndex);
00180           }
00181           else
00182           {
00183             int vectorArgIndex = argEval()->vectorIndexMap().get(argIndex);
00184             vectorMonomials_[i].append(vectorArgIndex);
00185           }
00186         }
00187         else if (lambda.opOnFunc().isPartial() || lambda.opOnFunc().isIdentity())
00188         {
00189           Tabs tab3;
00190           SUNDANCE_MSG3(verb, tab3 << "detected functional deriv " << lambda);
00191           const SymbolicFuncElement* f = lambda.symbFuncElem();
00192           const MultiIndex& mi = expr->mi() + lambda.opOnFunc().mi(); 
00193           SUNDANCE_MSG3(verb, tab3 << "modified multiIndex is " << mi);
00194 
00195           const TestFuncElement* t 
00196             = dynamic_cast<const TestFuncElement*>(f);
00197           if (t != 0) continue;
00198 
00199           const UnknownFuncElement* u 
00200             = dynamic_cast<const UnknownFuncElement*>(f);
00201           TEUCHOS_TEST_FOR_EXCEPTION(u==0, std::logic_error,
00202             "Non-unknown function detected where an unknown "
00203             "function was expected in "
00204             "DiffOpEvaluator ctor");
00205 
00206 
00207           const EvaluatableExpr* evalPt = u->evalPt();
00208           const ZeroExpr* z = dynamic_cast<const ZeroExpr*>(evalPt);
00209           if (z != 0) continue;
00210           TEUCHOS_TEST_FOR_EXCEPTION(z != 0, std::logic_error,
00211             "DiffOpEvaluator detected identically zero "
00212             "function");
00213 
00214           const DiscreteFuncElement* df 
00215             = dynamic_cast<const DiscreteFuncElement*>(evalPt);
00216           
00217           TEUCHOS_TEST_FOR_EXCEPTION(df==0, std::logic_error,
00218             "DiffOpEvaluator ctor: evaluation point of "
00219             "unknown function " << u->toString() 
00220             << " is not a discrete function");
00221 
00222           const SymbolicFuncElementEvaluator* uEval 
00223             = dynamic_cast<const SymbolicFuncElementEvaluator*>(u->evaluator(context).get());
00224 
00225           const DiscreteFuncElementEvaluator* dfEval = uEval->dfEval();
00226 
00227 
00228           TEUCHOS_TEST_FOR_EXCEPTION(dfEval==0, std::logic_error,
00229             "DiffOpEvaluator ctor: evaluator for "
00230             "evaluation point is not a "
00231             "DiscreteFuncElementEvaluator");
00232 
00233           TEUCHOS_TEST_FOR_EXCEPTION(!dfEval->hasMultiIndex(mi), std::logic_error,
00234             "DiffOpEvaluator ctor: evaluator for "
00235             "discrete function " << df->toString()
00236             << " does not know about multiindex "
00237             << mi.toString());
00238           
00239           int fIndex;
00240           int miIndex = dfEval->miIndex(mi);
00241           
00242           if (funcToIndexMap.containsKey(dfEval))
00243           {
00244             fIndex = funcToIndexMap.get(dfEval);
00245           }
00246           else
00247           {
00248             fIndex = funcEvaluators_.size();
00249             funcEvaluators_.append(dfEval);
00250             funcToIndexMap.put(dfEval, fIndex);
00251           }
00252 
00253             
00254           const DerivState& argState = argSparsitySuperset()->state(argIndex);
00255           if (argState==ConstantDeriv)
00256           {
00257             int constArgIndex = argEval()->constantIndexMap().get(argIndex);
00258             constantCoeffFuncIndices_[i].append(fIndex);
00259             constantCoeffFuncMi_[i].append(miIndex);
00260             constantFuncCoeffs_[i].append(constArgIndex);
00261           }
00262           else
00263           {
00264             int vectorArgIndex = argEval()->vectorIndexMap().get(argIndex);
00265             vectorCoeffFuncIndices_[i].append(fIndex);
00266             vectorCoeffFuncMi_[i].append(miIndex);
00267             vectorFuncCoeffs_[i].append(vectorArgIndex);
00268           }
00269         }
00270         else
00271         {
00272           TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
00273             "DiffOpEvaluator has been asked to preprocess a Deriv that "
00274             "is not a simple partial derivative. The problem child is: "
00275             << lambda);
00276         }
00277       }
00278       
00279       
00280       Set<MultipleDeriv> isolatedTerms 
00281         = RArg.intersection(backedDerivs(resultDeriv, W1Arg, verb));
00282       
00283       if (isolatedTerms.size()==0)
00284       {
00285         SUNDANCE_MSG3(verb, tab1 << "no indirect chain rule terms");
00286       }
00287       else
00288       {
00289         SUNDANCE_MSG3(verb, tab1 << "getting indirect chain rule terms");
00290         SUNDANCE_MSG3(verb, tab1 << "isolated terms = " << isolatedTerms);
00291       }
00292 
00293       for (Set<MultipleDeriv>::const_iterator 
00294              j=isolatedTerms.begin(); j != isolatedTerms.end(); j++)
00295       {
00296         int argIndex = argSparsitySuperset()->getIndex(*j);
00297         TEUCHOS_TEST_FOR_EXCEPTION(argIndex==-1, std::runtime_error,
00298           "Derivative " << *j << " expected in argument "
00299           "but not found");
00300         const DerivState& argState = argSparsitySuperset()->state(argIndex);
00301         if (argState==ConstantDeriv)
00302         {
00303           int constArgIndex = argEval()->constantIndexMap().get(argIndex);
00304           constantMonomials_[i].append(constArgIndex);
00305         }
00306         else
00307         {
00308           int vectorArgIndex = argEval()->vectorIndexMap().get(argIndex);
00309           vectorMonomials_[i].append(vectorArgIndex);
00310         }
00311       }
00312     }
00313   }
00314 
00315   if (verb > 2)
00316   {
00317     Out::os() << tabs << "instruction tables for summing spatial/functional chain rule" << std::endl;
00318     for (int i=0; i<this->sparsity()->numDerivs(); i++)
00319     {
00320       Tabs tab1;
00321       Out::os() << tab1 << "deriv " << sparsity()->deriv(i) << std::endl;
00322       {
00323         Tabs tab2;
00324         Out::os() << tab2 << "constant monomials: " << constantMonomials_[i]
00325                   << std::endl;
00326         Out::os() << tab2 << "vector monomials: " << vectorMonomials_[i]
00327                   << std::endl;
00328             
00329         Out::os() << tab2 << "constant coeff functions: " << std::endl;
00330         for (int j=0; j<constantFuncCoeffs_[i].size(); j++)
00331         {
00332           Tabs tab3;
00333           Out::os() << tab3 << "func=" << constantCoeffFuncIndices_[i][j]
00334                     << " mi=" << constantCoeffFuncMi_[i][j] << std::endl;
00335         } 
00336         Out::os() << tab2 << "vector coeff functions: " << std::endl;
00337         for (int j=0; j<vectorFuncCoeffs_[i].size(); j++)
00338         {
00339           Tabs tab3;
00340           Out::os() << tab3 << "func=" << vectorCoeffFuncIndices_[i][j]
00341                     << " mi=" << vectorCoeffFuncMi_[i][j] << std::endl;
00342         }
00343             
00344       }
00345     }
00346   }
00347 }
00348 
00349 
00350 Deriv DiffOpEvaluator::remainder(const MultipleDeriv& big, 
00351   const MultipleDeriv& little, int verb) const 
00352 {
00353   Tabs tab;
00354   SUNDANCE_MSG5(verb, tab << "computing remainder: big=" << big << ", little="
00355     << little);
00356   TEUCHOS_TEST_FOR_EXCEPT(big.order()-little.order() != 1);
00357 
00358   MultipleDeriv r;
00359   if (little.order()==0) r = big;
00360   else r = big.factorOutDeriv(little);
00361 
00362   SUNDANCE_MSG5(verb, tab << "remainder = " << r);
00363 
00364   TEUCHOS_TEST_FOR_EXCEPT(r.order() != 1);
00365 
00366   return *(r.begin());
00367 }
00368 
00369 Set<MultipleDeriv> DiffOpEvaluator
00370 ::increasedDerivs(const MultipleDeriv& mu,
00371   const Set<MultipleDeriv>& W1, int verb) const
00372 {
00373   Tabs tabs;
00374   SUNDANCE_MSG3(verb, tabs << "computing increased derivs");
00375   Set<MultipleDeriv> rtn;
00376   for (Set<MultipleDeriv>::const_iterator i=W1.begin(); i!=W1.end(); i++)
00377   {
00378     MultipleDeriv md = *i;
00379     TEUCHOS_TEST_FOR_EXCEPT(md.order() != 1);
00380     Deriv lambda = *(md.begin());
00381     MultipleDeriv lambdaMu = mu;
00382     lambdaMu.put(lambda);
00383     rtn.put(lambdaMu);
00384   }
00385   SUNDANCE_MSG3(verb, tabs << "increased derivs = " << rtn);
00386   return rtn;
00387 }
00388 
00389 Set<MultipleDeriv> DiffOpEvaluator
00390 ::backedDerivs(const MultipleDeriv& mu,
00391   const Set<MultipleDeriv>& W1, int verb) const
00392 {
00393   Tabs tabs;
00394   SUNDANCE_MSG3(verb, tabs << "computing backed-out derivs for mu= " << mu
00395     << ", W1=" << W1);
00396   Set<MultipleDeriv> rtn;
00397   if (mu.order() != 0) 
00398   {
00399     const MultiIndex& alpha = expr()->mi();
00400 
00401     for (Set<MultipleDeriv>::const_iterator i=W1.begin(); i!=W1.end(); i++)
00402     {
00403       const MultipleDeriv& md = *i;
00404       TEUCHOS_TEST_FOR_EXCEPT(md.order() != 1);
00405       Deriv lambda = *(md.begin());
00406       if (lambda.isCoordDeriv()) continue;
00407       TEUCHOS_TEST_FOR_EXCEPT(!lambda.isFunctionalDeriv());
00408       FunctionIdentifier lambda_fid = lambda.fid();
00409       const MultiIndex& lambda_mi = lambda.opOnFunc().mi(); 
00410       for (MultipleDeriv::const_iterator j=mu.begin(); j!=mu.end(); j++)
00411       {
00412         const Deriv& d = *j;
00413         if (d.isCoordDeriv()) continue;
00414         FunctionIdentifier d_fid = d.fid();
00415         const MultiIndex& d_mi = d.opOnFunc().mi(); 
00416         if (d_fid != lambda_fid) continue;
00417         if (!(alpha + lambda_mi == d_mi)) continue;
00418         MultipleDeriv z = mu.factorOutDeriv(d);
00419         z.put(lambda);
00420         rtn.put(z);
00421       }
00422     }
00423   }
00424   SUNDANCE_MSG3(verb, tabs << "backed-out derivs = " << rtn);
00425   return rtn;
00426 }
00427 
00428 
00429 
00430 void DiffOpEvaluator::internalEval(const EvalManager& mgr,
00431   Array<double>& constantResults,
00432   Array<RCP<EvalVector> >& vectorResults)  const
00433 {
00434   Tabs tabs;
00435   SUNDANCE_MSG1(mgr.verb(), tabs << "DiffOpEvaluator::eval() expr=" 
00436     << expr()->toString());
00437 
00438   /* evaluate the argument */
00439   Array<RCP<EvalVector> > argVectorResults;
00440   Array<double> argConstantResults;
00441 
00442   SUNDANCE_MSG2(mgr.verb(), tabs << "evaluating operand");
00443   evalOperand(mgr, argConstantResults, argVectorResults);
00444 
00445 
00446   if (mgr.verb() > 2)
00447   {
00448     Tabs tab1;
00449     Out::os() << tabs << "DiffOp operand results" << std::endl;
00450     mgr.showResults(Out::os(), argSparsitySuperset(), argVectorResults,
00451       argConstantResults);
00452   }
00453 
00454 
00455 
00456   /* evaluate the required discrete functions */
00457   SUNDANCE_MSG2(mgr.verb(), tabs << "evaluating discrete functions, num funcs= " << funcEvaluators_.size());
00458 
00459   Array<Array<RCP<EvalVector> > > funcVectorResults(funcEvaluators_.size());
00460   Array<double> funcConstantResults;
00461   for (int i=0; i<funcEvaluators_.size(); i++)
00462   {
00463     funcEvaluators_[i]->eval(mgr, funcConstantResults, funcVectorResults[i]);
00464   }
00465   
00466   constantResults.resize(this->sparsity()->numConstantDerivs());
00467   vectorResults.resize(this->sparsity()->numVectorDerivs());
00468   
00469   SUNDANCE_MSG3(mgr.verb(), tabs << "summing spatial/functional chain rule");
00470 
00471   for (int i=0; i<this->sparsity()->numDerivs(); i++)
00472   {
00473     Tabs tab1;
00474     SUNDANCE_MSG4(mgr.verb(), tab1 << "working on deriv " 
00475       << this->sparsity()->deriv(i));
00476 
00477     /* add constant monomials */
00478     SUNDANCE_MSG4(mgr.verb(), tab1 << "have " <<  constantMonomials_[i].size()
00479       << " constant monomials");
00480     double constantVal = 0.0;
00481     for (int j=0; j<constantMonomials_[i].size(); j++)
00482     {
00483       SUNDANCE_MSG4(mgr.verb(), tab1 << "adding in constant monomial (index "
00484         << constantMonomials_[i][j] 
00485         << " in arg results)");
00486       constantVal += argConstantResults[constantMonomials_[i][j]];
00487     }
00488     if (isConstant_[i])
00489     {
00490       constantResults[resultIndices_[i]] = constantVal;
00491       SUNDANCE_MSG4(mgr.verb(), tab1 << "result is constant: value=" 
00492         << constantVal);
00493       continue;
00494     }
00495 
00496     RCP<EvalVector> result;
00497     bool vecHasBeenAllocated = false;
00498 
00499     /* add in the vector monomials */
00500     const Array<int>& vm = vectorMonomials_[i];
00501     SUNDANCE_MSG4(mgr.verb(), tab1 << "have " << vm.size() 
00502       << " vector monomials");
00503     for (int j=0; j<vm.size(); j++)
00504     {
00505       Tabs tab2;
00506 
00507       const RCP<EvalVector>& v = argVectorResults[vm[j]];
00508 
00509       SUNDANCE_MSG4(mgr.verb(), tab2 << "found vec monomial term " << v->str());
00510 
00511       /* if we've not yet allocated a vector for the results, 
00512        * do so now, and set it to the initial value */ 
00513       if (!vecHasBeenAllocated)
00514       {
00515         SUNDANCE_MSG4(mgr.verb(), tab2 << "allocated result vector");
00516         result = mgr.popVector();
00517         vecHasBeenAllocated = true;
00518         if (isZero(constantVal))
00519         {
00520           result->setTo_V(v.get());
00521         }
00522         else
00523         {
00524           result->setTo_S_add_V(constantVal, v.get());
00525         }
00526       }
00527       else
00528       {
00529         result->add_V(v.get());
00530       }
00531       SUNDANCE_MSG4(mgr.verb(), tab2 << "result is " << result->str());
00532     }
00533       
00534     /* add in the function terms with constant coeffs */
00535     const Array<int>& cf = constantFuncCoeffs_[i];
00536     SUNDANCE_MSG4(mgr.verb(), tab1 << "adding " << cf.size()
00537       << " func terms with constant coeffs");
00538     for (int j=0; j<cf.size(); j++)
00539     {
00540       Tabs tab2;
00541       const double& coeff = argConstantResults[cf[j]];
00542       int fIndex = constantCoeffFuncIndices_[i][j];
00543       int miIndex = constantCoeffFuncMi_[i][j];
00544       const RCP<EvalVector>& fValue 
00545         = funcVectorResults[fIndex][miIndex];
00546 
00547       SUNDANCE_MSG4(mgr.verb(), tab2 << "found term: coeff= " 
00548         << coeff << ", func value=" << fValue->str());
00549           
00550       /* if we've not yet allocated a vector for the results, 
00551        * do so now, and set it to the initial value */ 
00552       if (!vecHasBeenAllocated)
00553       {
00554         SUNDANCE_MSG4(mgr.verb(), tab2 << "allocated result vector");
00555         result = mgr.popVector();
00556         vecHasBeenAllocated = true;
00557         if (isOne(coeff))
00558         {
00559           if (isZero(constantVal))
00560           {
00561             result->setTo_V(fValue.get());
00562           }
00563           else
00564           {
00565             result->setTo_S_add_V(constantVal, fValue.get());
00566           }
00567         }
00568         else
00569         {
00570           if (isZero(constantVal))
00571           {
00572             result->setTo_SV(coeff, fValue.get());
00573           }
00574           else
00575           {
00576             result->setTo_S_add_SV(constantVal, coeff, fValue.get());
00577           }
00578         }
00579       }
00580       else
00581       {
00582         if (isOne(coeff))
00583         {
00584           result->add_V(fValue.get());
00585         }
00586         else
00587         {
00588           result->add_SV(coeff, fValue.get());
00589         }
00590       }
00591       SUNDANCE_MSG4(mgr.verb(), tab2 << "result is " << result->str());
00592     }
00593 
00594       
00595     /* add in the function terms with vector coeffs */
00596     const Array<int>& vf = vectorFuncCoeffs_[i];
00597     SUNDANCE_MSG4(mgr.verb(), tab1 << "adding " << vf.size()
00598       << " func terms with vector coeffs");
00599     for (int j=0; j<vf.size(); j++)
00600     {
00601       Tabs tab2;
00602 
00603       const RCP<EvalVector>& coeff = argVectorResults[vf[j]];
00604       int fIndex = vectorCoeffFuncIndices_[i][j];
00605       int miIndex = vectorCoeffFuncMi_[i][j];
00606       const RCP<EvalVector>& fValue 
00607         = funcVectorResults[fIndex][miIndex];
00608 
00609       SUNDANCE_MSG4(mgr.verb(), tab2 << "found term: coeff= " 
00610         << coeff->str() << ", func value=" 
00611         << fValue->str());
00612           
00613       /* if we've not yet allocated a vector for the results, 
00614        * do so now, and set it to the initial value */ 
00615       if (!vecHasBeenAllocated)
00616       {
00617         SUNDANCE_MSG4(mgr.verb(), tab2 << "allocated result vector");
00618         result = mgr.popVector();
00619         vecHasBeenAllocated = true;
00620         result->setTo_VV(coeff.get(), fValue.get());
00621       }
00622       else
00623       {
00624         result->add_VV(coeff.get(), fValue.get());
00625       }
00626       SUNDANCE_MSG4(mgr.verb(), tab2 << "result is " << result->str());
00627     }
00628 
00629     TEUCHOS_TEST_FOR_EXCEPTION(!vecHasBeenAllocated, std::logic_error,
00630       "created empty vector in DiffOpEvaluator::internalEval");
00631     vectorResults[resultIndices_[i]] = result;
00632   }
00633 
00634   if (mgr.verb() > 1)
00635   {
00636     Out::os() << tabs << "diff op results" << std::endl;
00637     mgr.showResults(Out::os(), sparsity(), vectorResults,
00638       constantResults);
00639   }
00640   SUNDANCE_MSG1(mgr.verb(), tabs << "done spatial/functional chain rule");
00641 }
00642 
00643 
00644 
00645 void DiffOpEvaluator::resetNumCalls() const 
00646 {
00647   argEval()->resetNumCalls();
00648   for (int i=0; i<funcEvaluators_.size(); i++) 
00649   {
00650     funcEvaluators_[i]->resetNumCalls();
00651   }
00652   Evaluator::resetNumCalls();
00653 }

Site Contact