Go to the documentation of this file.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
00032
00033
00034
00035
00036
00037
00038
00039
00040
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
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
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
00338
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 }