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

Site Contact