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 #include "SundanceExpr.hpp"
00032 #include "SundanceIntegral.hpp"
00033 #include "SundanceStdSumTransformations.hpp"
00034 
00035 #include "SundanceSumExpr.hpp"
00036 #include "SundanceProductExpr.hpp"
00037 #include "SundanceConstantExpr.hpp"
00038 #include "SundanceCoordExpr.hpp"
00039 #include "SundanceDerivative.hpp"
00040 #include "SundanceDiffOp.hpp"
00041 
00042 
00043 #include "SundanceUnaryMinus.hpp"
00044 #include "SundanceZeroExpr.hpp"
00045 #include "SundanceFunctionalPolynomial.hpp"
00046 #include "SundanceSumOfIntegrals.hpp"
00047 #include "SundanceSumOfBCs.hpp"
00048 #include "SundanceNullCellFilterStub.hpp"
00049 #include "SundanceOut.hpp"
00050 #include "Teuchos_TimeMonitor.hpp"
00051 
00052 using namespace Sundance;
00053 using namespace Sundance;
00054 
00055 using namespace Teuchos;
00056 using namespace Sundance;
00057 
00058 static Time& polysumTimer() 
00059 {
00060   static RCP<Time> rtn 
00061     = TimeMonitor::getNewTimer("IdentifyPolynomialSum"); 
00062   return *rtn;
00063 }
00064 static Time& reorderSumTimer() 
00065 {
00066   static RCP<Time> rtn 
00067     = TimeMonitor::getNewTimer("ReorderSum"); 
00068   return *rtn;
00069 }
00070 
00071 static Time& removeUnaryMinusTimer() 
00072 {
00073   static RCP<Time> rtn 
00074     = TimeMonitor::getNewTimer("RemoveUnaryMinusFromSum"); 
00075   return *rtn;
00076 }
00077 
00078 static Time& removeZeroTimer() 
00079 {
00080   static RCP<Time> rtn 
00081     = TimeMonitor::getNewTimer("RemoveZeroFromSum"); 
00082   return *rtn;
00083 }
00084 
00085 static Time& sumConstantsTimer() 
00086 {
00087   static RCP<Time> rtn 
00088     = TimeMonitor::getNewTimer("SumConstants"); 
00089   return *rtn;
00090 }
00091 
00092 static Time& moveConstantsTimer() 
00093 {
00094   static RCP<Time> rtn 
00095     = TimeMonitor::getNewTimer("MoveConstantsToLeftOfSum"); 
00096   return *rtn;
00097 }
00098 
00099 static Time& rearrangeRightSumWithConstantTimer() 
00100 {
00101   static RCP<Time> rtn 
00102     = TimeMonitor::getNewTimer("RearrangeRightSumWithConstant"); 
00103   return *rtn;
00104 }
00105 
00106 static Time& rearrangeLeftSumWithConstantTimer() 
00107 {
00108   static RCP<Time> rtn 
00109     = TimeMonitor::getNewTimer("RearrangeLeftSumWithConstant"); 
00110   return *rtn;
00111 }
00112 
00113 static Time& sumIntegralsTimer() 
00114 {
00115   static RCP<Time> rtn 
00116     = TimeMonitor::getNewTimer("SumIntegrals"); 
00117   return *rtn;
00118 }
00119 
00120 
00121 
00122 
00123 StdSumTransformations::StdSumTransformations()
00124   : SumTransformationSequence()
00125 {
00126   append(rcp(new RemoveZeroFromSum()));
00127 
00128   
00129 
00130   append(rcp(new SumConstants()));
00131 
00132     append(rcp(new MoveConstantsToLeftOfSum()));
00133     append(rcp(new RearrangeRightSumWithConstant()));
00134     append(rcp(new RearrangeLeftSumWithConstant()));
00135   append(rcp(new IdentifyPolynomialSum()));
00136   append(rcp(new SumIntegrals()));
00137 }
00138 
00139 
00140 bool IdentifyPolynomialSum::doTransform(const RCP<ScalarExpr>& left, 
00141                                         const RCP<ScalarExpr>& right,
00142                                         int sign, 
00143                                         RCP<ScalarExpr>& rtn) const
00144 {
00145   TimeMonitor timer(polysumTimer());
00146   if (useOptimizedPolynomials())
00147     {
00148       
00149 
00150       if (FunctionalPolynomial::isConvertibleToPoly(left.get())
00151           && FunctionalPolynomial::isConvertibleToPoly(right.get()))
00152         {
00153           RCP<FunctionalPolynomial> lp = FunctionalPolynomial::toPoly(left);
00154           RCP<FunctionalPolynomial> rp = FunctionalPolynomial::toPoly(right);
00155           rtn = lp->addPoly(rp.get(), sign);
00156           return true;
00157         }
00158     }
00159   
00160   return false;
00161 }
00162 
00163 
00164 bool ReorderSum::doTransform(const RCP<ScalarExpr>& left, 
00165                              const RCP<ScalarExpr>& right,
00166                              int sign, RCP<ScalarExpr>& rtn) const
00167 {
00168   TimeMonitor timer(reorderSumTimer());
00169   
00170 
00171 
00172 
00173 
00174 
00175   Expr L = Expr::handle(left);
00176   Expr R = Expr::handle(right);
00177   Sundance::Map<Expr, int> tree = L.getSumTree();
00178   Sundance::Map<Expr, int>::const_reverse_iterator iL = tree.rbegin();
00179   Expr endOfLeft = iL->first;
00180   Sundance::Map<Expr, int> rightTree = R.getSumTree();
00181   Sundance::Map<Expr, int>::const_iterator iR = rightTree.begin();
00182   Expr startOfRight = iR->first;
00183 
00184   if (endOfLeft.lessThan(startOfRight))
00185     {
00186       Tabs tab1;
00187       SUNDANCE_VERB_MEDIUM(tab1 << "Terms are already ordered, doing nothing");
00188       return false;
00189     }
00190   else
00191     {
00192       Tabs tab1;
00193 
00194       for (Map<Expr, int>::const_iterator i=rightTree.begin(); i!=rightTree.end(); i++)
00195         {
00196           int leftCount = 0;
00197           if (tree.containsKey(i->first))
00198             {
00199               leftCount = tree[i->first];
00200             }
00201           int count = leftCount + sign * i->second;
00202           tree.put(i->first, count);
00203         }
00204       SUNDANCE_VERB_MEDIUM(tab1 << "Ordered terms are: " << tree);      
00205 
00206 
00207       Expr sum = new ZeroExpr();
00208 
00209       
00210 
00211       for (Map<Expr, int>::const_iterator i=tree.begin(); i!=tree.end(); i++)
00212         {
00213           const Expr& term = i->first;
00214           int count = i->second;
00215           if (count==0) continue;
00216           if (count==1) sum = sum + term;
00217           else if (count==-1) sum = sum - term;
00218           else sum = sum + count*term;
00219         }
00220       
00221       rtn = getScalar(sum);
00222       return true;
00223     }
00224 }
00225 
00226 #ifdef OLD_CODE
00227 
00228 bool ReorderSum::doTransform(const RCP<ScalarExpr>& left, 
00229                              const RCP<ScalarExpr>& right,
00230                              int sign, RCP<ScalarExpr>& rtn) const
00231 {
00232   Tabs tabs;
00233   SUNDANCE_VERB_LOW(tabs << "trying ReorderSum");
00234 
00235   Tabs tab0;
00236   SUNDANCE_VERB_MEDIUM(tab0 << "L=" << l->toString());
00237   SUNDANCE_VERB_MEDIUM(tab0 << "R=" << r->toString());
00238   const SumExpr* sLeft = dynamic_cast<const SumExpr*>(l.get());
00239   const SumExpr* sRight = dynamic_cast<const SumExpr*>(r.get());
00240 
00241   if (sLeft==0 && sRight==0)
00242     {
00243       Tabs tab1;
00244       if (Expr::handle(r).lessThan(Expr::handle(l)))
00245         {
00246           if (sign>0)
00247             {
00248               SUNDANCE_VERB_MEDIUM(tab1 << "Both are non-sums: R < L, so reordering to R+L");
00249               rtn = getScalar(Expr::handle(r) + Expr::handle(l));
00250             }
00251           else
00252             {
00253               SUNDANCE_VERB_MEDIUM(tab1 << "Both are non-sums: R < L, reordering to -R+L");
00254               rtn = getScalar(-Expr::handle(r) + Expr::handle(l));
00255             }
00256           return true;
00257         }
00258     }
00259 
00260 
00261   if (sLeft != 0)
00262     {
00263       Tabs tab1;
00264       Expr ll = sLeft->left();
00265       Expr lr = sLeft->right();
00266       int lSign = sLeft->sign();
00267       if (Expr::handle(r).lessThan(ll))
00268         {
00269           if (sign > 0)
00270             {
00271               SUNDANCE_VERB_MEDIUM(tab1 << "L is a sum: R < LL, reordering to R+L");
00272               rtn = getScalar(Expr::handle(r) + Expr::handle(l));
00273             }
00274           else
00275             {
00276               SUNDANCE_VERB_MEDIUM(tab1 << "L is a sum: R < LL, reordering to -R+L");
00277               rtn = getScalar(-Expr::handle(r) + Expr::handle(l));
00278             }
00279           return true;
00280         }
00281       if (Expr::handle(r).lessThan(lr)) 
00282         {
00283           if (sign > 0)
00284             {
00285               if (lSign > 0)
00286                 {
00287                   SUNDANCE_VERB_MEDIUM(tab1 << "L is a sum: LL < R < LR, reordering to LL + R + LR");
00288                   rtn = getScalar(ll + Expr::handle(r) + lr);
00289                 }
00290               else
00291                 {
00292                   SUNDANCE_VERB_MEDIUM(tab1 << "L is a sum: LL < R < LR, reordering to LL + R - LR");
00293                   rtn = getScalar(ll + Expr::handle(r) - lr);
00294                 }
00295             }
00296           else
00297             {
00298               if (lSign > 0)
00299                 {
00300                   SUNDANCE_VERB_MEDIUM(tab1 << "L is a sum: LL < R < LR, reordering to LL - R + LR");
00301                   rtn = getScalar(ll - Expr::handle(r) + lr);
00302                 }
00303               else
00304                 {
00305                   SUNDANCE_VERB_MEDIUM(tab1 << "L is a sum: LL < R < LR, "
00306                                        "reordering to LL - R - LR");
00307                   rtn = getScalar(ll - Expr::handle(r) - lr);
00308                 }
00309             }
00310           return true;
00311         }
00312     }
00313   if (sRight != 0)
00314     {
00315       Tabs tab1;
00316       Expr rl = sRight->left();
00317       Expr rr = sRight->right();
00318       int rSign = sRight->sign();
00319 
00320       if (rr.lessThan(Expr::handle(l)))
00321         {
00322           if (sign > 0)
00323             {
00324               SUNDANCE_VERB_MEDIUM(tab1 << "R is a sum: R < L, reordering to R+L");
00325               rtn = getScalar(Expr::handle(r) + Expr::handle(l));
00326             }
00327           else
00328             {
00329               SUNDANCE_VERB_MEDIUM(tab1 << "R is a sum: R < L, reordering to -R+L");
00330               rtn = getScalar(-Expr::handle(r) + Expr::handle(l));
00331             }
00332           return true;
00333         }
00334 
00335       if (rl.lessThan(Expr::handle(l)))
00336         {
00337           if (sign > 0)
00338             {
00339               if (rSign > 0)
00340                 {
00341                   SUNDANCE_VERB_MEDIUM(tab1 << "R is a sum: RL < L < RR, reordering to RL+L+RR");
00342                   rtn = getScalar(rl + Expr::handle(l) + rr);
00343                 }
00344               else
00345                 {
00346                   SUNDANCE_VERB_MEDIUM(tab1 << "R is a sum: RL < L < RR, reordering to RL+L-RR");
00347                   rtn = getScalar(rl + Expr::handle(l) - rr);
00348                 }
00349             }
00350           else
00351             {
00352               if (rSign > 0)
00353                 {
00354                   SUNDANCE_VERB_MEDIUM(tab1 << "R is a sum: RL < L < RR, reordering to -RL+L-RR");
00355                   rtn = getScalar(-rl + Expr::handle(l) - rr);
00356                 }
00357               else
00358                 {
00359                   SUNDANCE_VERB_MEDIUM(tab1 << "R is a sum: RL < L < RR, reordering to -RL+L+RR");
00360                   rtn = getScalar(-rl + Expr::handle(l) + rr);
00361                 }
00362             }
00363           return true;
00364         }
00365     }
00366   
00367   return false;
00368 }
00369 
00370 #endif
00371 
00372 
00373 bool RemoveZeroFromSum::doTransform(const RCP<ScalarExpr>& left, const RCP<ScalarExpr>& right,
00374                                     int sign, RCP<ScalarExpr>& rtn) const
00375 {
00376   TimeMonitor timer(removeZeroTimer());
00377   SUNDANCE_OUT(this->verb() > 1, 
00378                "trying RemoveZeroFromSum");
00379 
00380   
00381   
00382   
00383   const ConstantExpr* cl = dynamic_cast<const ConstantExpr*>(left.get());
00384   if (cl != 0 && (cl->value()==0.0 || cl->value()==-0.0))
00385     {
00386       if (verb() > 1)
00387         {
00388           Out::println("RemoveZeroFromSum identified left operand as zero.");
00389           Out::println("Applying transformation 0 + x --> x");
00390         }
00391       rtn = chooseSign(sign, right);
00392       return true;
00393     }
00394 
00395   
00396   const ConstantExpr* cr = dynamic_cast<const ConstantExpr*>(right.get());
00397   if (cr != 0 && (cr->value()==0.0 || cr->value()==-0.0)) 
00398     {
00399       if (verb() > 1)
00400         {
00401           Out::println("RemoveZeroFromSum identified right operand as zero.");
00402           Out::println("Applying transformation x + 0 --> x");
00403         }
00404       rtn = left;
00405       return true;
00406     }
00407 
00408   
00409   return false;
00410 }
00411 
00412 bool MoveConstantsToLeftOfSum::doTransform(const RCP<ScalarExpr>& left, const RCP<ScalarExpr>& right,
00413                                       int sign, RCP<ScalarExpr>& rtn) const
00414 {
00415   TimeMonitor timer(moveConstantsTimer());
00416 
00417   
00418 
00419   if (right->isConstant())
00420     {
00421       if (verb() > 1)
00422         {
00423           Out::println("MoveConstantsToLeftOfSum identified right "
00424                        "operand as constant.");
00425         }
00426       rtn = getScalar(Expr::handle(chooseSign(sign, right)) 
00427         + Expr::handle(left));
00428       return true;
00429     }
00430 
00431   return false;
00432 }
00433 
00434 
00435 bool RemoveUnaryMinusFromSum::doTransform(const RCP<ScalarExpr>& left,
00436                                           const RCP<ScalarExpr>& right,
00437                                           int sign, 
00438                                           RCP<ScalarExpr>& rtn) const
00439 {
00440   TimeMonitor timer(removeUnaryMinusTimer());
00441   SUNDANCE_OUT(this->verb() > 1, 
00442                "trying RemoveUnaryMinusFromSum");
00443 
00444   
00445 
00446   const UnaryMinus* ul = dynamic_cast<const UnaryMinus*>(left.get());
00447   const UnaryMinus* ur = dynamic_cast<const UnaryMinus*>(right.get());
00448   if (ul != 0 && ur != 0)
00449     {
00450       if (verb() > 1)
00451         {
00452           Out::println("RemoveUnaryMinusFromSum identified both "
00453                        "operands as unary minuses.");
00454         }
00455       rtn = getScalar(-(Expr::handle(chooseSign(sign, getScalar(ur->arg()))) 
00456                         + ul->arg()));
00457       return true;
00458     }
00459   else if (ul != 0)
00460     {
00461       if (verb() > 1)
00462         {
00463           Out::println("RemoveUnaryMinusFromSum identified left "
00464                        "operand as unary minus.");
00465         }
00466       if (sign > 0)
00467         {
00468           rtn = getScalar(-(ul->arg() - Expr::handle(right)));
00469         }
00470       else
00471         {
00472           rtn = getScalar(-(ul->arg() + Expr::handle(right)));
00473         }
00474       return true;
00475     }
00476   else if (ur != 0)
00477     {
00478       if (verb() > 1)
00479         {
00480           Out::println("RemoveUnaryMinusFromSum identified right "
00481                        "operand as unary minus.");
00482         }
00483       if (sign > 0)
00484         {
00485           rtn = getScalar(Expr::handle(left) - ur->arg());
00486         }
00487       else
00488         {
00489           rtn = getScalar(Expr::handle(left) + ur->arg());
00490         }
00491       return true;
00492     }
00493 
00494   return false;
00495 }
00496 
00497 bool SumConstants::doTransform(const RCP<ScalarExpr>& left, const RCP<ScalarExpr>& right,
00498                                int sign, RCP<ScalarExpr>& rtn) const
00499 {
00500   
00501   TimeMonitor timer(sumConstantsTimer());
00502   SUNDANCE_OUT(this->verb() > 1, 
00503                "trying SumConstants");
00504 
00505   
00506   if (left->isConstant() && right->isConstant())
00507     {
00508       if (verb() > 1)
00509         {
00510           Out::println("SumConstants identified both "
00511                        "operands as constant. No transformations applied.");
00512         }
00513       rtn = rcp(new SumExpr(left, right, sign));
00514       return true;
00515     }
00516   return false;
00517 }
00518 
00519 bool RearrangeRightSumWithConstant::doTransform(const RCP<ScalarExpr>& left, 
00520                                                 const RCP<ScalarExpr>& right,
00521                                                 int sign, RCP<ScalarExpr>& rtn) const
00522 {
00523   TimeMonitor timer(rearrangeRightSumWithConstantTimer());
00524   const SumExpr* sRight = dynamic_cast<const SumExpr*>(right.get());
00525 
00526   if (sRight != 0)
00527     {
00528       
00529 
00530 
00531       TEUCHOS_TEST_FOR_EXCEPTION(sRight->rightScalar()->isConstant(),
00532                          std::logic_error,
00533                          "RearrangeRightSumWithConstant: unexpected case, "
00534                          "constant expr"
00535                          << sRight->right() << " found as right operand "
00536                          "in sum " << right->toString());
00537 
00538       if (sRight->leftScalar()->isConstant())
00539         {      
00540           
00541 
00542           if (left->isConstant())
00543             {
00544               if (verb() > 1)
00545                 {
00546                   Out::println("RearrangeRightSumWithConstant::doTransform "
00547                                "identified right "
00548                                "operand as sum involving a constant, "
00549                                "and left operand as a constant. Applying "
00550                                "transformation alpha + (beta+u) "
00551                                "--> (alpha + beta) + u.");
00552                 }
00553               int s1 = sign;
00554               int s2 = sRight->sign();
00555               Expr alpha = Expr::handle(left);
00556               Expr beta = sRight->left();
00557               Expr u = sRight->right();
00558               rtn = getScalar((alpha + chooseSign(s1, beta)) + chooseSign(s1*s2,u));
00559             }
00560           else  
00561 
00562             {
00563               if (verb() > 1)
00564                 {
00565                   Out::println("RearrangeRightSumWithConstant::doTransform "
00566                                "identified right "
00567                                "operand as sum involving a constant, "
00568                                "and left operand as non-constant. Applying "
00569                                "transformation u + (alpha + v) "
00570                                "--> alpha + (u + v)");
00571                 }
00572               int s1 = sign;
00573               int s2 = sRight->sign();
00574               Expr u = Expr::handle(left);
00575               Expr alpha = sRight->left();
00576               Expr v = sRight->right();
00577               rtn = getScalar(chooseSign(s1, alpha) + (u + chooseSign(s1*s2, v)));
00578             }
00579           return true;
00580         }
00581     }
00582   return false;
00583 }
00584 
00585 
00586 bool RearrangeLeftSumWithConstant::doTransform(const RCP<ScalarExpr>& left, 
00587                                                 const RCP<ScalarExpr>& right,
00588                                                 int sign, RCP<ScalarExpr>& rtn) const
00589 {
00590   TimeMonitor timer(rearrangeLeftSumWithConstantTimer());
00591   const SumExpr* sLeft = dynamic_cast<const SumExpr*>(left.get());
00592 
00593   if (sLeft != 0 && !left->isConstant())
00594     {
00595       
00596 
00597 
00598       TEUCHOS_TEST_FOR_EXCEPTION(sLeft->rightScalar()->isConstant(),
00599                          std::logic_error,
00600                          "RearrangeLeftSumWithConstant::doTransform "
00601                          ": unexpected case, constant expr"
00602                          << sLeft->right() << " found as right operand "
00603                          "in sum " << left->toString());
00604       
00605       if (sLeft->leftScalar()->isConstant())
00606         {
00607           
00608 
00609           if (right->isConstant())
00610             {
00611               if (verb() > 1)
00612                 {
00613                   Out::println("RearrangeLeftSumWithConstant::doTransform "
00614                                "identified right "
00615                                "operand as constant, "
00616                                "and left operand as sum involving "
00617                                "a constant. Applying "
00618                                "transformation (alpha + u) + beta "
00619                                "--> (alpha + beta) + u.");
00620                 }
00621               int s2 = sign;
00622               int s1 = sLeft->sign();
00623               Expr alpha = sLeft->left();
00624               Expr beta = Expr::handle(right);
00625               Expr u = sLeft->right();
00626               rtn =  getScalar((alpha + chooseSign(s2, beta)) + chooseSign(s1, u));
00627             }
00628           else 
00629 
00630             {
00631               if (verb() > 1)
00632                 {
00633                   Out::println("RearrangeLeftSumWithConstant::doTransform "
00634                                "identified right "
00635                                "operand as non-constant, "
00636                                "and left operand as sum involving "
00637                                "a constant. Applying "
00638                                "transformation (alpha + u) + v "
00639                                "--> alpha + (u + v).");
00640                 }
00641               int s2 = sign;
00642               int s1 = sLeft->sign();
00643               Expr alpha = sLeft->left();
00644               Expr u = sLeft->right();
00645               Expr v = Expr::handle(right);
00646               rtn =  getScalar(alpha 
00647                 + (chooseSign(s1, u) + chooseSign(s2, v)));
00648             }
00649           return true;
00650         }
00651     }
00652   return false;
00653 }
00654 
00655 bool SumIntegrals::doTransform(const RCP<ScalarExpr>& left, 
00656                                const RCP<ScalarExpr>& right,
00657                                int sign, RCP<ScalarExpr>& rtn) const
00658 {
00659   TimeMonitor timer(sumIntegralsTimer());
00660   SUNDANCE_OUT(this->verb() > 1, 
00661                "trying SumIntegrals");
00662 
00663   const SumOfIntegrals* sLeft 
00664     = dynamic_cast<const SumOfIntegrals*>(left.get());
00665   const SumOfIntegrals* sRight 
00666     = dynamic_cast<const SumOfIntegrals*>(right.get());
00667 
00668   if (sLeft != 0 || sRight != 0)
00669     {
00670       
00671 
00672       bool leftIsBC = (dynamic_cast<const SumOfBCs*>(sLeft) != 0);
00673       bool rightIsBC = (dynamic_cast<const SumOfBCs*>(sRight) != 0);
00674       TEUCHOS_TEST_FOR_EXCEPTION((leftIsBC && !rightIsBC)
00675                          || (!leftIsBC && rightIsBC), std::runtime_error,
00676                          "Attempting to add EssentialBC and non-EssentialBC "
00677                          "integrals: L=" << left->toString() << ", R="
00678                          << right->toString());
00679 
00680       if (sLeft != 0 && sRight != 0)
00681         {
00682           SumOfIntegrals* l;
00683           if (!leftIsBC) l = new SumOfIntegrals(*sLeft);
00684           else l = new SumOfBCs(*dynamic_cast<const SumOfBCs*>(sLeft));
00685           l->merge(sRight, sign);
00686           rtn = rcp(l);
00687           return true;
00688         }
00689 
00690       
00691 
00692       TEUCHOS_TEST_FOR_EXCEPTION(leftIsBC, std::runtime_error,
00693                          "Attempting to add a BC " << left->toString()
00694                          << " and a global expression " << right->toString());
00695 
00696       TEUCHOS_TEST_FOR_EXCEPTION(rightIsBC, std::runtime_error,
00697                          "Attempting to add a BC " << right->toString()
00698                          << " and a global expression " << left->toString());
00699 
00700       if (sLeft != 0 && sRight == 0)
00701         {
00702           SumOfIntegrals* l = new SumOfIntegrals(*sLeft);
00703           const SpatiallyConstantExpr* cRight 
00704             = dynamic_cast<const SpatiallyConstantExpr*>(right.get());
00705 
00706           TEUCHOS_TEST_FOR_EXCEPTION(cRight == 0, std::logic_error,
00707                              "Attempting to add non-constant expression "
00708                              << right->toString() << " to an integral");
00709 
00710           Expr r = Integral(l->nullRegion(), Expr::handle(right));
00711           const SumOfIntegrals* sr 
00712             = dynamic_cast<const SumOfIntegrals*>(r.ptr().get());
00713           l->merge(sr, sign);
00714           rtn = rcp(l);
00715           return true;
00716         }
00717       else
00718         {
00719           SumOfIntegrals* r = new SumOfIntegrals(*sRight);
00720           if (sign < 0) r->changeSign();
00721 
00722           const SpatiallyConstantExpr* cLeft 
00723             = dynamic_cast<const SpatiallyConstantExpr*>(left.get());
00724 
00725           TEUCHOS_TEST_FOR_EXCEPTION(cLeft == 0, std::logic_error,
00726                              "Attempting to add non-constant expression "
00727                              << left->toString() << " to an integral");
00728 
00729           Expr l = Integral(r->nullRegion(), Expr::handle(right));
00730           const SumOfIntegrals* sl 
00731             = dynamic_cast<const SumOfIntegrals*>(l.ptr().get());
00732           r->merge(sl, 1);
00733           rtn = rcp(r);
00734           return true;
00735         }
00736 
00737     }
00738   else
00739     {
00740       return false;
00741     }
00742   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "this should not happen");
00743   return false; 
00744 }