SundanceMultipleDeriv.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 "SundanceMultipleDeriv.hpp"
00043 #include "SundanceSymbolicFuncElement.hpp"
00044 
00045 using namespace Sundance;
00046 using namespace Sundance;
00047 using namespace Teuchos;
00048 
00049 MultipleDeriv::MultipleDeriv()
00050   : MultiSet<Deriv>()
00051 {}
00052 
00053 MultipleDeriv::MultipleDeriv(const Deriv& d)
00054   : MultiSet<Deriv>()
00055 {
00056   put(d);
00057 }
00058 MultipleDeriv::MultipleDeriv(const Deriv& d1, const Deriv& d2)
00059   : MultiSet<Deriv>()
00060 {
00061   put(d1);
00062   put(d2);
00063 }
00064 
00065 int MultipleDeriv::spatialOrder() const 
00066 {
00067   int rtn = 0;
00068   for (MultipleDeriv::const_iterator i=this->begin(); i!=this->end(); i++)
00069   {
00070     if (i->isCoordDeriv())
00071     {
00072       rtn += 1;
00073     }
00074   }
00075   return rtn;
00076 }
00077 
00078 MultiIndex MultipleDeriv::spatialDeriv() const
00079 {
00080   MultiIndex rtn;
00081   for (MultipleDeriv::const_iterator i=this->begin(); i!=this->end(); i++)
00082   {
00083     if (i->isCoordDeriv())
00084     {
00085       int d = i->coordDerivDir();
00086       rtn[d] += 1;
00087     }
00088   }
00089   return rtn;
00090 }
00091 
00092 MultiSet<FunctionIdentifier> MultipleDeriv::funcIDs() const
00093 {
00094   MultiSet<FunctionIdentifier> rtn;
00095   for (MultipleDeriv::const_iterator i=this->begin(); i!=this->end(); i++)
00096   {
00097     if (i->isFunctionalDeriv())
00098     {
00099       rtn.put(i->fid());
00100     }
00101     TEUCHOS_TEST_FOR_EXCEPTION(!i->isFunctionalDeriv(), std::runtime_error,
00102       "MultipleDeriv::funcIDs() found spatial deriv");
00103   }
00104   return rtn;
00105 }
00106 
00107 MultiSet<int> MultipleDeriv::dofIDs() const
00108 {
00109   MultiSet<int> rtn;
00110   for (MultipleDeriv::const_iterator i=this->begin(); i!=this->end(); i++)
00111   {
00112     if (i->isFunctionalDeriv())
00113     {
00114       int f = i->dofID();
00115       rtn.put(f);
00116     }
00117     TEUCHOS_TEST_FOR_EXCEPTION(!i->isFunctionalDeriv(), std::runtime_error,
00118       "MultipleDeriv::sharedFuncIDs() found spatial deriv");
00119   }
00120   return rtn;
00121 }
00122 
00123 MultipleDeriv MultipleDeriv::product(const MultipleDeriv& other) const 
00124 {
00125   MultipleDeriv rtn;
00126   
00127   for (MultipleDeriv::const_iterator i=this->begin(); i!=this->end(); i++)
00128   {
00129     rtn.put(*i);
00130   }
00131   for (MultipleDeriv::const_iterator i=other.begin(); i!=other.end(); i++)
00132   {
00133     rtn.put(*i);
00134   }
00135   return rtn;
00136 }
00137 
00138 MultipleDeriv MultipleDeriv::factorOutDeriv(const Deriv& x) const
00139 {
00140   MultipleDeriv rtn = *this;
00141 
00142   MultipleDeriv::iterator i = rtn.find(x);
00143 
00144   /* remove a single copy of the given derivative */
00145   if (i != rtn.end()) rtn.erase(i);
00146 
00147   if (rtn.size() == this->size()) return MultipleDeriv();
00148 
00149   return rtn;
00150 }
00151 
00152 
00153 bool MultipleDeriv::containsDeriv(const MultipleDeriv& x) const
00154 {
00155   for (MultipleDeriv::const_iterator i=x.begin(); i!=x.end(); i++)
00156   {
00157     if ( count(*i) <= x.count(*i) ) return false;
00158   }
00159   return true;
00160 }
00161 
00162 MultipleDeriv MultipleDeriv::factorOutDeriv(const MultipleDeriv& x) const
00163 {
00164   MultipleDeriv rtn = *this;
00165 
00166   for (MultipleDeriv::const_iterator i=x.begin(); i!=x.end(); i++)
00167   {
00168     MultipleDeriv::iterator j = rtn.find(*i);
00169 
00170     /* remove a single copy of the given derivative */
00171     if (j != rtn.end()) rtn.erase(j);
00172   }
00173 
00174   if (rtn.size() == this->size()) return MultipleDeriv();
00175   return rtn;
00176 }
00177 
00178 bool MultipleDeriv
00179 ::isInRequiredSet(const Set<MultiSet<int> >& funcCombinations,
00180   const Set<MultiIndex>& multiIndices) const
00181 {
00182   if (spatialOrder() == 0)
00183   {
00184     return funcCombinations.contains(dofIDs());
00185   }
00186   else
00187   {
00188     return multiIndices.contains(spatialDeriv());
00189   }
00190 }
00191 
00192 
00193 void MultipleDeriv
00194 ::productRulePermutations(ProductRulePerms& perms) const 
00195 {
00196   int N = order();
00197 
00198   if (N==0)
00199   {
00200     MultipleDeriv md0;
00201     DerivPair p(md0, md0);
00202     perms.put(p, 1);
00203     return;
00204   }
00205 
00206   int p2 = pow2(N);
00207 
00208   for (int i=0; i<p2; i++)
00209   {
00210     MultipleDeriv left;
00211     MultipleDeriv right;
00212     Array<int> bits = bitsOfAnInteger(i, N);
00213     int j=0; 
00214     MultipleDeriv::const_iterator iter;
00215     for (iter=this->begin(); iter != this->end(); iter++, j++)
00216     {
00217       if (bits[j]==true)
00218       {
00219         left.put(*iter);
00220       }
00221       else
00222       {
00223         right.put(*iter);
00224       }
00225     }
00226     DerivPair p(left, right);
00227     if (!perms.containsKey(p))
00228     {
00229       perms.put(p, 1);
00230     }
00231     else
00232     {
00233       int count = perms.get(p);
00234       perms.put(p, count+1);
00235     }
00236   }
00237 }
00238 
00239 Array<int> MultipleDeriv::bitsOfAnInteger(int x, int n)
00240 {
00241   TEUCHOS_TEST_FOR_EXCEPTION(x >= pow2(n), std::logic_error,
00242     "Invalid input to MultipleDeriv::bitsOfX");
00243                      
00244   Array<int> rtn(n);
00245 
00246   int r = x;
00247   for (int b=n-1; b>=0; b--)
00248   {
00249     rtn[b] = r/pow2(b);
00250     r = r - rtn[b]*pow2(b);
00251   }
00252   return rtn;
00253 }
00254 
00255 int MultipleDeriv::pow2(int n)
00256 {
00257   static Array<int> p2(1,1);
00258 
00259   if (n >= p2.size())
00260   {
00261     int oldN = p2.size(); 
00262     for (int i=oldN; i<=n; i++) p2.push_back(p2[i-1]*2);
00263   }
00264   
00265   return p2[n];
00266 }
00267 
00268 
00269 
00270 namespace Sundance
00271 {
00272 Set<MultipleDeriv> applyTx(const Set<MultipleDeriv>& s,
00273   const MultiIndex& x)
00274 {
00275   Set<MultipleDeriv> rtn;
00276 
00277   for (Set<MultipleDeriv>::const_iterator i=s.begin(); i!=s.end(); i++)
00278   {
00279     const MultipleDeriv& md = *i;
00280     for (MultipleDeriv::const_iterator j=md.begin(); j!=md.end(); j++)
00281     {
00282       const Deriv& d = *j;
00283       if (d.isFunctionalDeriv())
00284       {
00285         const MultiIndex& mi = d.opOnFunc().mi();
00286         MultiIndex miNew = mi+x;
00287         if (miNew.isValid())
00288         {
00289           Deriv dNew = d.derivWrtMultiIndex(miNew);
00290           MultipleDeriv mdNew = md;
00291           mdNew.erase(mdNew.find(d));
00292           mdNew.put(dNew);
00293           rtn.put(mdNew);
00294         }
00295       }
00296     }
00297   }
00298   return rtn;
00299 }
00300 
00301 Set<MultipleDeriv> Xx(const MultiIndex& x)
00302 {
00303   Set<MultipleDeriv> rtn;
00304 
00305   TEUCHOS_TEST_FOR_EXCEPTION(x.order() < 0 || x.order() > 1, std::logic_error,
00306     "invalid multiindex " << x << " in this context");
00307 
00308   MultipleDeriv xmd = makeMultiDeriv(coordDeriv(x.firstOrderDirection()));
00309   rtn.put(xmd);
00310   return rtn;
00311 }
00312 
00313 Set<MultipleDeriv> applyZx(const Set<MultipleDeriv>& W,
00314   const MultiIndex& x)
00315 {
00316   Set<MultipleDeriv> rtn;
00317 
00318   TEUCHOS_TEST_FOR_EXCEPTION(x.order() < 0 || x.order() > 1, std::logic_error,
00319     "invalid multiindex " << x << " in this context");
00320 
00321   for (Set<MultipleDeriv>::const_iterator i=W.begin(); i!=W.end(); i++)
00322   {
00323     const MultipleDeriv& md = *i;
00324     TEUCHOS_TEST_FOR_EXCEPTION(md.order() != 1, std::logic_error,
00325       "Only first-order multiple functional derivatives "
00326       "should appear in this function. The derivative "
00327       << md << " is not first-order.");
00328 
00329     const Deriv& d = *(md.begin());
00330 
00331     if (d.isFunctionalDeriv())
00332     {
00333       /* */
00334       TEUCHOS_TEST_FOR_EXCEPTION(!d.canBeDifferentiated(),
00335         std::logic_error, "function signature " << d << " cannot be "
00336         "differentiated further spatially");
00337       /* accept a functional derivative if the associated function 
00338        * is not identically zero */
00339       const SymbolicFuncElement* sfe = d.symbFuncElem();
00340       TEUCHOS_TEST_FOR_EXCEPTION(sfe==0, std::logic_error, 
00341         "can't cast function in "
00342         << d << " to a SymbolicFuncElement");
00343       if (sfe && !sfe->evalPtIsZero()) rtn.put(md);
00344     }
00345   }
00346   return rtn;
00347 }
00348 
00349 
00350     
00351 int factorial(const MultipleDeriv& ms)
00352 {
00353   Sundance::Map<Deriv, int> counts;
00354     
00355   for (MultipleDeriv::const_iterator i=ms.begin(); i!=ms.end(); i++)
00356   {
00357     if (counts.containsKey(*i)) counts[*i]++;
00358     else counts.put(*i, 1);
00359   }
00360 
00361   int rtn = 1;
00362   for (Sundance::Map<Deriv, int>::const_iterator
00363          i=counts.begin(); i!=counts.end(); i++)
00364   {
00365     int f = 1;
00366     for (int j=1; j<=i->second; j++) f *= j;
00367     rtn *= f;
00368   }
00369   return rtn;
00370 }
00371 
00372 MultipleDeriv makeMultiDeriv(const Deriv& d)
00373 {
00374   MultipleDeriv rtn;
00375   rtn.put(d);
00376   return rtn;
00377 }
00378 
00379 bool hasParameter(const MultipleDeriv& d)
00380 {
00381   for (MultipleDeriv::const_iterator i=d.begin(); i!=d.end(); i++)
00382   {
00383     if (i->isParameter()) return true;
00384   }
00385   return false;
00386 }
00387 
00388 
00389 
00390 }

Site Contact