SundanceSumEvaluator.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 "SundanceSumEvaluator.hpp"
00043 #include "SundanceEvalManager.hpp"
00044 #include "SundanceSumExpr.hpp"
00045 #include "SundanceProductExpr.hpp"
00046 
00047 #include "PlayaTabs.hpp"
00048 #include "SundanceOut.hpp"
00049 
00050 using namespace Sundance;
00051 using namespace Sundance;
00052 using namespace Sundance;
00053 using namespace Teuchos;
00054 
00055 
00056 
00057 
00058 SumEvaluator::SumEvaluator(const SumExpr* se,
00059                            const EvalContext& context)
00060   : BinaryEvaluator<SumExpr>(se, context), 
00061     sign_(se->sign()),
00062     singleRightConstant_(),
00063     singleRightVector_(),
00064     singleLeftConstant_(),
00065     singleLeftVector_(),
00066     ccSums_(),
00067     cvSums_(),
00068     vcSums_(),
00069     vvSums_()
00070 {
00071   Tabs tabs(0);
00072   int verb = context.evalSetupVerbosity();
00073 
00074   if (verb > 1)
00075     {
00076       Out::os() << tabs << "initializing sum evaluator for " 
00077            << se->toString() << std::endl;
00078     }
00079 
00080   int constantCounter = 0;
00081   int vectorCounter = 0;
00082 
00083   if (verb > 2)
00084     {
00085       Out::os() << std::endl << tabs << "return sparsity ";
00086       this->sparsity()->print(Out::os());
00087       Out::os() << std::endl << tabs << "left sparsity ";
00088       leftSparsity()->print(Out::os());
00089       Out::os() << std::endl << tabs << "right sparsity " ;
00090       rightSparsity()->print(Out::os());
00091       Out::os() << std::endl;
00092       
00093       Out::os() << tabs << "left vector index map " << leftEval()->vectorIndexMap() << std::endl;
00094       Out::os() << tabs << "right vector index map " << rightEval()->vectorIndexMap() << std::endl;
00095       
00096       Out::os() << tabs << "left constant index map " << leftEval()->constantIndexMap() << std::endl;
00097       Out::os() << tabs << "right constant index map " << rightEval()->constantIndexMap() << std::endl;
00098     }
00099 
00100   for (int i=0; i<this->sparsity()->numDerivs(); i++)
00101     {
00102       const MultipleDeriv& d = this->sparsity()->deriv(i);
00103       TEUCHOS_TEST_FOR_EXCEPTION(!leftSparsity()->containsDeriv(d) 
00104                          && !rightSparsity()->containsDeriv(d),
00105                          std::logic_error,
00106                          "deriv " << d.toString() 
00107                          << " was not found in either left or right operand "
00108                          "of expr " << expr()->toString());
00109       
00110       int iLeft = -1;
00111       int iRight = -1;
00112       
00113       if (leftSparsity()->containsDeriv(d)) 
00114         {
00115           iLeft = leftSparsity()->getIndex(d);
00116         }
00117 
00118       if (rightSparsity()->containsDeriv(d)) 
00119         {
00120           iRight = rightSparsity()->getIndex(d);
00121         }
00122 
00123       SUNDANCE_MSG2(verb, tabs << "deriv " << d);
00124 
00125       if (iLeft == -1) /* case where the left operand is zero */
00126         {
00127           SUNDANCE_MSG3(verb, tabs << "left operand is zero ");
00128           if (rightSparsity()->state(iRight)==ConstantDeriv)
00129             {
00130               int rc = rightEval()->constantIndexMap().get(iRight);
00131               singleRightConstant_.append(tuple(constantCounter, rc));
00132               addConstantIndex(i, constantCounter++);
00133               SUNDANCE_MSG4(verb, tabs << "single right constant " 
00134                                  << singleRightConstant_[singleRightConstant_.size()-1]);
00135             }
00136           else
00137             {
00138               int rv = rightEval()->vectorIndexMap().get(iRight);
00139               singleRightVector_.append(tuple(vectorCounter, rv));
00140               addVectorIndex(i, vectorCounter++);
00141               SUNDANCE_MSG4(verb, tabs << "single right vector " 
00142                                  << singleRightVector_[singleRightVector_.size()-1]);
00143             }
00144         }
00145       else if (iRight == -1) /* case where the right operand is zero */
00146         {
00147           SUNDANCE_MSG3(verb, tabs << "right operand is zero ");
00148           if (leftSparsity()->state(iLeft)==ConstantDeriv)
00149             {
00150               int lc = leftEval()->constantIndexMap().get(iLeft);
00151               singleLeftConstant_.append(tuple(constantCounter, lc));
00152               addConstantIndex(i, constantCounter++);
00153               SUNDANCE_MSG4(verb, tabs << "single left constant " 
00154                                  << singleLeftConstant_[singleLeftConstant_.size()-1]);
00155             }
00156           else
00157             {
00158               int lv = leftEval()->vectorIndexMap().get(iLeft);
00159               singleLeftVector_.append(tuple(vectorCounter, lv));
00160               addVectorIndex(i, vectorCounter++);
00161               SUNDANCE_MSG4(verb, tabs << "single left vector " 
00162                                  << singleLeftVector_[singleLeftVector_.size()-1]);
00163             }
00164         }
00165       else /* both are nonzero */
00166         {
00167           SUNDANCE_MSG4(verb, tabs << "both operands are nonzero ");
00168           bool leftIsConstant = leftSparsity()->state(iLeft)==ConstantDeriv;
00169           bool rightIsConstant = rightSparsity()->state(iRight)==ConstantDeriv;
00170           
00171           if (leftIsConstant && rightIsConstant)
00172             {
00173               SUNDANCE_MSG4(verb, tabs << "both operands are constant");
00174               int lc = leftEval()->constantIndexMap().get(iLeft);
00175               int rc = rightEval()->constantIndexMap().get(iRight);
00176               ccSums_.append(tuple(constantCounter, lc, rc));
00177               addConstantIndex(i, constantCounter++);
00178               SUNDANCE_MSG4(verb, tabs << "c-c sum " << ccSums_[ccSums_.size()-1]);
00179             }
00180           else if (leftIsConstant)
00181             {
00182               SUNDANCE_MSG4(verb, tabs << "left operand is constant");
00183               int lc = leftEval()->constantIndexMap().get(iLeft);
00184               int rv = rightEval()->vectorIndexMap().get(iRight);
00185               cvSums_.append(tuple(vectorCounter, lc, rv));
00186               addVectorIndex(i, vectorCounter++);
00187               SUNDANCE_MSG4(verb, tabs << "c-v sum " << cvSums_[cvSums_.size()-1]);
00188             }
00189           else if (rightIsConstant)
00190             {
00191               SUNDANCE_MSG4(verb, tabs << "right operand is constant");
00192               int lv = leftEval()->vectorIndexMap().get(iLeft);
00193               int rc = rightEval()->constantIndexMap().get(iRight);
00194               vcSums_.append(tuple(vectorCounter, lv, rc));
00195               addVectorIndex(i, vectorCounter++);
00196               SUNDANCE_MSG4(verb, tabs << "v-c sum " << vcSums_[vcSums_.size()-1]);
00197             }
00198           else
00199             {
00200               SUNDANCE_MSG4(verb, tabs << "both operands are vectors");
00201               int lv = leftEval()->vectorIndexMap().get(iLeft);
00202               int rv = rightEval()->vectorIndexMap().get(iRight);
00203               vvSums_.append(tuple(vectorCounter, lv, rv));
00204               addVectorIndex(i, vectorCounter++);
00205               SUNDANCE_MSG4(verb, tabs << "v-v sum " << vvSums_[vvSums_.size()-1]);
00206             }
00207         }
00208     }
00209 }
00210 
00211 void SumEvaluator
00212 ::internalEval(const EvalManager& mgr,
00213                Array<double>& constantResults,
00214                Array<RCP<EvalVector> >& vectorResults) const 
00215 { 
00216   //  TimeMonitor timer(evalTimer());
00217   Tabs tabs(0);
00218 
00219   SUNDANCE_MSG1(mgr.verb(),
00220                tabs << "SumEvaluator::eval() expr=" << expr()->toString());
00221 
00222   /* evaluate the children */
00223   Array<RCP<EvalVector> > leftVectorResults; 
00224   Array<RCP<EvalVector> > rightVectorResults; 
00225   Array<double> leftConstResults;
00226   Array<double> rightConstResults;
00227   evalChildren(mgr, leftConstResults, leftVectorResults,
00228                rightConstResults, rightVectorResults);
00229 
00230   if (verb() > 2)
00231     {
00232       Out::os() << tabs << "left operand " << std::endl;
00233       mgr.showResults(Out::os(), leftSparsity(), leftVectorResults,
00234                             leftConstResults);
00235       Out::os() << tabs << "right operand " << std::endl;
00236       mgr.showResults(Out::os(), rightSparsity(), rightVectorResults,
00237                              rightConstResults);
00238     }
00239   
00240   constantResults.resize(this->sparsity()->numConstantDerivs());
00241   vectorResults.resize(this->sparsity()->numVectorDerivs());
00242 
00243   /* Do constant terms with left=0 */
00244   for (int i=0; i<singleRightConstant_.size(); i++)
00245     {
00246       Tabs tab1;
00247       constantResults[singleRightConstant_[i][0]]
00248         = sign_*rightConstResults[singleRightConstant_[i][1]];
00249       SUNDANCE_MSG2(mgr.verb(), tab1 << "sum for "
00250                            << constantResultDeriv(singleRightConstant_[i][0])
00251                            << ": L=0, R=" 
00252                            << sign_*rightConstResults[singleRightConstant_[i][1]]);
00253     }
00254 
00255   /* Do constant terms with right=0 */
00256   for (int i=0; i<singleLeftConstant_.size(); i++)
00257     {
00258       Tabs tab1;
00259       constantResults[singleLeftConstant_[i][0]]
00260         = leftConstResults[singleLeftConstant_[i][1]];
00261       SUNDANCE_MSG2(mgr.verb(), tab1 << "sum for " 
00262                            << constantResultDeriv(singleLeftConstant_[i][0])
00263                            << ": L=" 
00264                            << leftConstResults[singleLeftConstant_[i][1]]
00265                            << " R=0");
00266     }
00267 
00268   /* Do vector terms with left=0 */
00269   for (int i=0; i<singleRightVector_.size(); i++)
00270     {
00271       Tabs tab1;
00272       if (sign_ < 0.0) rightVectorResults[singleRightVector_[i][1]]->multiply_S(sign_);
00273       vectorResults[singleRightVector_[i][0]]
00274         = rightVectorResults[singleRightVector_[i][1]];
00275       SUNDANCE_MSG2(mgr.verb(), tab1 << "sum for "
00276                            << vectorResultDeriv(singleRightVector_[i][0])
00277                            << ": L=0, R=" 
00278                            << sign_ << "*" << 
00279                            rightVectorResults[singleRightVector_[i][1]]->str());
00280     }
00281 
00282   /* Do vector terms with right=0 */
00283   for (int i=0; i<singleLeftVector_.size(); i++)
00284     { 
00285       Tabs tab1;
00286       vectorResults[singleLeftVector_[i][0]]
00287         = leftVectorResults[singleLeftVector_[i][1]];
00288       SUNDANCE_MSG2(mgr.verb(), tab1 << "sum for " 
00289                            << vectorResultDeriv(singleLeftVector_[i][0])
00290                            << ": L=" 
00291                            << leftVectorResults[singleLeftVector_[i][1]]->str()
00292                            << " R=0");
00293     }
00294 
00295   /** Do constant-constant terms */
00296   for (int i=0; i<ccSums_.size(); i++)
00297     {
00298       Tabs tab1;
00299       constantResults[ccSums_[i][0]]
00300         = leftConstResults[ccSums_[i][1]] 
00301         + sign_*rightConstResults[ccSums_[i][2]];
00302       SUNDANCE_MSG2(mgr.verb(), tab1 << "c-c sum for " 
00303                            << constantResultDeriv(ccSums_[i][0])
00304                            << ": L=" << leftConstResults[ccSums_[i][1]] 
00305                            << " R=" << sign_*rightConstResults[ccSums_[i][2]]);
00306     }
00307 
00308   /** Do constant-vector sums */
00309   for (int i=0; i<cvSums_.size(); i++)
00310     {
00311       Tabs tab1;
00312       RCP<EvalVector>& v = rightVectorResults[cvSums_[i][2]];
00313       SUNDANCE_MSG2(mgr.verb(), tab1 << "doing c-v sum for " 
00314                            << vectorResultDeriv(cvSums_[i][0])
00315                            << ": L=" << leftConstResults[cvSums_[i][1]] 
00316                            << " R=" << sign_ << "*" 
00317                            << rightVectorResults[cvSums_[i][2]]->str());
00318       if (isOne(sign_))
00319         {
00320           v->add_S(leftConstResults[cvSums_[i][1]]);
00321         }
00322       else
00323         {
00324           v->multiply_S_add_S(sign_, leftConstResults[cvSums_[i][1]]);
00325         }
00326       vectorResults[cvSums_[i][0]] = v;
00327     }
00328 
00329   /* Do vector-constant sums */
00330   for (int i=0; i<vcSums_.size(); i++)
00331     {
00332       Tabs tab1;
00333       RCP<EvalVector>& v = leftVectorResults[vcSums_[i][1]] ;
00334       SUNDANCE_MSG2(mgr.verb(), tab1 << "doing v-c sum for " 
00335                            << vectorResultDeriv(vcSums_[i][0])
00336                            << ": L=" << leftVectorResults[vcSums_[i][1]]->str()
00337                            << " R=" 
00338                            << sign_*rightConstResults[vcSums_[i][2]]);
00339       v->add_S(sign_*rightConstResults[vcSums_[i][2]]);
00340       vectorResults[vcSums_[i][0]] = v;
00341     }
00342 
00343   /* Do vector-vector sums */
00344   for (int i=0; i<vvSums_.size(); i++)
00345     {
00346       Tabs tab1;
00347       RCP<EvalVector>& v = leftVectorResults[vvSums_[i][1]];
00348       SUNDANCE_MSG2(mgr.verb(), tab1 << "doing v-v sum for " 
00349                            << vectorResultDeriv(vvSums_[i][0])
00350                            << ": L=" 
00351                            << leftVectorResults[vvSums_[i][1]]->str() 
00352                            << " R=" << sign_ << "*" 
00353                            << rightVectorResults[vvSums_[i][2]]->str());
00354       if (isOne(sign_))
00355         {
00356           v->add_V(rightVectorResults[vvSums_[i][2]].get());
00357         }
00358       else
00359         {
00360           v->add_SV(sign_, rightVectorResults[vvSums_[i][2]].get());
00361         }
00362       vectorResults[vvSums_[i][0]] = v;
00363     }
00364   
00365   if (mgr.verb() > 1)
00366     {
00367       Out::os() << tabs << "sum result " << std::endl;
00368       mgr.showResults(Out::os(), this->sparsity(), vectorResults,
00369           constantResults);
00370     }
00371 }
00372 
00373 

Site Contact