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 #ifndef SUNDANCE_MULTIPLEDERIV_H 00043 #define SUNDANCE_MULTIPLEDERIV_H 00044 00045 #include "SundanceDefs.hpp" 00046 #include "SundanceDeriv.hpp" 00047 #include "SundanceMultiSet.hpp" 00048 #include "SundanceOrderedTuple.hpp" 00049 #include "SundanceMap.hpp" 00050 #include "Teuchos_Array.hpp" 00051 00052 00053 00054 namespace Sundance 00055 { 00056 using namespace Sundance; 00057 class MultipleDeriv; 00058 /** */ 00059 typedef OrderedPair<MultipleDeriv, MultipleDeriv> DerivPair; 00060 00061 /** */ 00062 typedef Sundance::Map<DerivPair, int> ProductRulePerms; 00063 /** Class MultipleDeriv is a multiple functional derivative operator 00064 * represented as a multiset of first-order derivatives. 00065 * The derivatives are each Deriv objects, so the multiple 00066 * derivative can be an arbitrary mixture of spatial and 00067 * functional derivatives. 00068 * 00069 * <h3> Product rule application </h3> 00070 * 00071 * Class MultipleDeriv contains a utility method for computing the 00072 * derivatives that appear in the general product rule, as 00073 * used in automatic differentiation of products and spatial 00074 * derivatives. 00075 * The arbitrary order, multivariable product rule gives 00076 * the derivative of a product \f$L\cdot R\f$ 00077 * with respect to a multiset of variables 00078 * \f$\{u_1, u_2, \dots, u_N\}\f$ as the sum 00079 * \f[ D_{u_1} D_{u_2} \cdots D_{u_N} (L \cdot R) 00080 * =\sum_{i=1}^{2^N} \left[\prod_{j=1}^N D_{u_j}^{b_{i,j}}\right] L 00081 * \times \left[\prod_{j=1}^N D_{u_j}^{1-b_{i,j}}\right] R\f] 00082 * where \f$b_{i,j}\f$ is the \f$j\f$-th bit in the binary 00083 * representation of \f$i\f$. Method productRulePermutations() 00084 * enumerates all the permutations that apply to the left and right 00085 * operands in this sum, and returns the 00086 * arrays of left operators and right operators 00087 * through non-const reference arguments. 00088 * The left and right arguments return 00089 * 00090 * \f[ {\rm left = Array}_{i=1}^{2^N} 00091 * \{\prod_{j=1}^N D_{u_j}^{b_{i,j}}\}\f] 00092 * 00093 * \f[ {\rm right = Array}_{i=1}^{2^N} 00094 * \{\prod_{j=1}^N D_{u_j}^{1-b_{i,j}}\}\f] 00095 * 00096 * Each element in these arrays is a multiple derivative, and 00097 * is naturally represented with a MultipleDeriv object. 00098 */ 00099 class MultipleDeriv : public MultiSet<Deriv> 00100 { 00101 public: 00102 00103 /** Construct an empty multiple derivative */ 00104 MultipleDeriv(); 00105 00106 /** Construct a first-order multiple deriv */ 00107 MultipleDeriv(const Deriv& d); 00108 00109 /** Construct a second-order multiple deriv */ 00110 MultipleDeriv(const Deriv& d1, const Deriv& d2); 00111 00112 /** Return the order of this derivative. Since a 00113 * multiple derivative is a multiset of first-order 00114 * derivatives, the order of the multiple derivative is the 00115 * size of the set. */ 00116 int order() const {return this->size();} 00117 00118 /** Return the order of spatial differentiation in this 00119 * derivative */ 00120 int spatialOrder() const ; 00121 00122 /** Return a multiindex representing the spatial derivs in this 00123 * multiple derivative */ 00124 MultiIndex spatialDeriv() const ; 00125 00126 00127 /** Return by reference argument the partitioning of 00128 * derivatives when this derivative is applied to a product. 00129 */ 00130 void productRulePermutations(ProductRulePerms& perms) const ; 00131 00132 /** return the product of two multiple derivatives, which 00133 * is the union of the two multisets */ 00134 MultipleDeriv product(const MultipleDeriv& other) const ; 00135 00136 00137 /** 00138 * Return a copy of this derivative, but with the specified single 00139 * derivative removed. For example, if <t>this</t> is 00140 * \f$ \{u,v,w\} \f$, calling <t>factorOutDeriv(v)</t> will 00141 * return \f$\{u,w\}\f$. 00142 */ 00143 MultipleDeriv factorOutDeriv(const Deriv& x) const ; 00144 00145 00146 /** 00147 * Return a copy of this derivative, but with all single derivs 00148 * in the the argument removed. For example, if <t>this</t> is 00149 * \f$ \{u,v,w\} \f$, calling <t>factorOutDeriv(u,v)</t> will 00150 * return \f$\{w\}\f$. 00151 */ 00152 MultipleDeriv factorOutDeriv(const MultipleDeriv& x) const ; 00153 00154 00155 /** 00156 * Return true is all single derivatives appearing in x also appear in this. 00157 */ 00158 bool containsDeriv(const MultipleDeriv& x) const ; 00159 00160 00161 /** 00162 * 00163 */ 00164 bool isInRequiredSet(const Set<MultiSet<int> >& funcCombinations, 00165 const Set<MultiIndex>& multiIndices) const ; 00166 00167 /** */ 00168 MultiSet<FunctionIdentifier> funcIDs() const ; 00169 00170 /** */ 00171 MultiSet<int> dofIDs() const ; 00172 00173 /** \name Utilities used in computing product rule permutations */ 00174 //@ 00175 /** Compute the n-th power of 2 */ 00176 static int pow2(int n); 00177 00178 /** Compute the n bits of an integer x < 2^n. The bits are ordered 00179 * least-to-most significant. 00180 */ 00181 static Array<int> bitsOfAnInteger(int x, int n); 00182 //@} 00183 private: 00184 }; 00185 00186 00187 /** 00188 * \brief Tranform the input set S as follows: for each multiple derivative 00189 * in S, apply the multiindex x to each of its component functional derivatives 00190 * in turn. Note that the multiindex may have negative indices. Results with 00191 * negative multiindices are ignored. 00192 */ 00193 Set<MultipleDeriv> applyTx(const Set<MultipleDeriv>& S, 00194 const MultiIndex& x); 00195 /** 00196 * \brief Filter the input set W, allowing only coordinate derivatives in the 00197 * direction x and functional derivatives whose associated functions 00198 * have nonzero evaluation points. This function is used 00199 * in the spatial/functional chain rule to identify those terms resulting 00200 * from differentiation wrt x or functional derivatives. 00201 */ 00202 Set<MultipleDeriv> applyZx(const Set<MultipleDeriv>& W, 00203 const MultiIndex& x); 00204 00205 00206 /** */ 00207 Set<MultipleDeriv> Xx(const MultiIndex& x) ; 00208 00209 /** */ 00210 int factorial(const MultipleDeriv& ms); 00211 00212 00213 /** 00214 * 00215 */ 00216 template <class T> class increasingOrder 00217 : std::binary_function<T, T, bool> 00218 { 00219 public: 00220 bool operator()(const MultipleDeriv& a, 00221 const MultipleDeriv& b) const; 00222 }; 00223 /** 00224 * Functor increasingOrder() is used as a comparison method 00225 * for MultipleDeriv objects. When used in a set, it will sort 00226 * derivatives in order of increasing order of differentiation. 00227 * Sorting by differentiation order is useful in evaluation of 00228 * product and chain rules: if we evaluate higher-order derivatives 00229 * first, we can evaluate in place without destroying lower-order 00230 * derivatives. 00231 */ 00232 template <> class increasingOrder<MultipleDeriv> 00233 { 00234 public: 00235 bool operator()(const MultipleDeriv& a, 00236 const MultipleDeriv& b) const 00237 { 00238 if (a.order() < b.order()) return true; 00239 if (a.order() > b.order()) return false; 00240 00241 MultipleDeriv::const_iterator aIter; 00242 MultipleDeriv::const_iterator bIter; 00243 00244 for (aIter=a.begin(), bIter=b.begin(); 00245 aIter != a.end() && bIter != b.end(); 00246 aIter++, bIter++) 00247 { 00248 if (*aIter < *bIter) return true; 00249 if (*bIter < *aIter) return false; 00250 } 00251 00252 return false; 00253 } 00254 }; 00255 00256 00257 /** */ 00258 MultipleDeriv makeMultiDeriv(const Deriv& d); 00259 00260 /** */ 00261 bool hasParameter(const MultipleDeriv& d) ; 00262 00263 00264 } 00265 00266 00267 #endif