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

Site Contact