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

Site Contact