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 #ifndef SUNDANCE_DERIV_H 00032 #define SUNDANCE_DERIV_H 00033 00034 #include "SundanceDefs.hpp" 00035 #include "SundanceSpatialDerivSpecifier.hpp" 00036 #include "SundanceFunctionIdentifier.hpp" 00037 #include "Teuchos_RefCountPtr.hpp" 00038 00039 namespace Sundance 00040 { 00041 using namespace Sundance; 00042 using namespace Teuchos; 00043 class SymbolicFunc; 00044 class Parameter; 00045 class SymbolicFuncElement; 00046 class SymbolicFuncDescriptor; 00047 class CommonFuncDataStub; 00048 00049 enum DerivType {CoordDT, FunctionalDT, NullDT}; 00050 00051 /** 00052 * The purpose of this class is to represent first-order 00053 * spatial or functional differential operators. This object 00054 * should not be confused with the user-level Derivative 00055 * object, which represents spatial differential operators as appearing 00056 * in a user-level problem specification. 00057 * 00058 * <h4> Functional vs spatial derivatives </h4> 00059 * 00060 * The bridge theorem involves expressions of the form 00061 * \f[ 00062 * \frac{\partial \mathcal{F}}{\partial L(u)} L(\phi_u) 00063 * \f] 00064 * and 00065 * \f[ 00066 * \frac{\partial^2 \mathcal{F}}{\partial L(u)\partial M(v)} 00067 * L(\phi_u)M(\psi_v) 00068 * \f] 00069 * where \f$L(u)\f$ is some spatial differential operator acting on the 00070 * function \f$u\f$, and \f$\phi_u\f$ is a basis function with which 00071 * \f$u\f$ is represented. 00072 * A derivative such as \f$\frac{\partial \mathcal{F}}{\partial L(u)}\f$ will 00073 * be called a functional derivative to distinguish it from derivatives 00074 * with respect to spatial coordinates, such as 00075 * \f$\frac{\partial \mathcal{F}}{\partial x}\f$. 00076 * The following table shows the types of derivative currently supported. 00077 * <table> 00078 * <tr> 00079 * <td>Operation</td> 00080 * <td>Geometry of derivative value</td> 00081 * <td>Operating function geometry</td> 00082 * <td>Operating spatial operator</td> 00083 * <td>Operating function subtype</td> 00084 * </tr> 00085 * <tr> 00086 * <td>\f$ \frac{\partial}{\partial x}\f$ </td> 00087 * <td> Scalar </td> 00088 * <td> Coordinate component </td> 00089 * <td> N/A </td> 00090 * <td> N/A </td> 00091 * </tr> 00092 * <tr> 00093 * <td>\f$ \frac{\partial}{\partial p}\f$ </td> 00094 * <td> Scalar </td> 00095 * <td> Scalar (\f$L^2\f$)</td> 00096 * <td> Identity </td> 00097 * <td> SymbolicFuncElement </td> 00098 * </tr> 00099 * <tr> 00100 * <td>\f$ \frac{\partial}{\partial D_\alpha p}\f$ </td> 00101 * <td> Coordinate component </td> 00102 * <td> Scalar (\f$H^1\f$)</td> 00103 * <td> Partial derivative \f$D_\alpha\f$ </td> 00104 * <td> SymbolicFuncElement </td> 00105 * </tr> 00106 * <tr> 00107 * <td>\f$ \frac{\partial}{\partial D_n p}\f$ </td> 00108 * <td> Normal component </td> 00109 * <td> Scalar (\f$H^1\f$) </td> 00110 * <td> Normal derivative \f${\bf n}\cdot \nabla\f$ </td> 00111 * <td> SymbolicFuncElement </td> 00112 * </tr> 00113 * <tr> 00114 * <td>\f$ \frac{\partial}{\partial \mathrm{div}({\bf u})}\f$ </td> 00115 * <td> Scalar </td> 00116 * <td> Vector (\f${\bf H}(div)\f$)</td> 00117 * <td> Divergence </td> 00118 * <td> SymbolicFunc </td> 00119 * </tr> 00120 * <tr> 00121 * <td>\f$ \frac{\partial}{\partial {\bf u\cdot e_\alpha}}\f$ </td> 00122 * <td> Coordinate component </td> 00123 * <td> Vector (\f${\bf H}^1\f$, \f${\bf H}(div)\f$, or \f${\bf H}(curl)\f$)</td> 00124 * <td> Inner product with coordinate unit vector </td> 00125 * <td> SymbolicFuncElement </td> 00126 * </tr> 00127 * <tr> 00128 * <td>\f$ \frac{\partial}{\partial {\bf u\cdot n}}\f$ </td> 00129 * <td> Normal component </td> 00130 * <td> Vector (\f${\bf H}^1\f$ or \f${\bf H}(div)\f$)</td> 00131 * <td> Inner product with normal unit vector </td> 00132 * <td> SymbolicFunc </td> 00133 * </tr> 00134 * <tr> 00135 * <td>\f$ \frac{\partial}{\partial D_\alpha ({\bf u\cdot e_\beta})}\f$ </td> 00136 * <td> Coordinate component </td> 00137 * <td> Vector (\f${\bf H}^1\f$) </td> 00138 * <td> Inner product with normal unit vector </td> 00139 * <td> SymbolicFuncElement </td> 00140 * </tr> 00141 * </table> 00142 */ 00143 class Deriv : public EnumTypeField<DerivType> 00144 { 00145 public: 00146 /** An empty ctor is needed for use with std::vector. The empty 00147 * ctor creates a null derivative, representing an identity operator.*/ 00148 Deriv(); 00149 00150 /** Construct a deriv wrt a coordinate, e.g., \f$D_x\f$. */ 00151 Deriv(int coordDir); 00152 00153 /** Construct a deriv wrt an object of length one, for example, 00154 * a scalar function or a single component of a vector function, or 00155 * possibly a spatial derivative of such an object. 00156 * Examples: 00157 * <ul> 00158 * <li> \f$T\f$ is a scalar-valued function 00159 * */ 00160 Deriv( 00161 const SymbolicFuncElement* func, 00162 const SpatialDerivSpecifier& d 00163 ); 00164 00165 /** Construct a deriv wrt a function */ 00166 Deriv( 00167 const SymbolicFunc* func, 00168 const SpatialDerivSpecifier& d 00169 ); 00170 00171 00172 /** Comparison operator for use in sets and maps */ 00173 bool operator<(const Deriv& other) const ; 00174 00175 /** Equality test operator */ 00176 bool operator==(const Deriv& other) const ; 00177 00178 /** Write to a std::string 00179 * \param verbose If true, write all details for the object. If false, 00180 * write a simple description giving only the function name and the 00181 * specification of a derivative. 00182 */ 00183 std::string toString(bool verbose=false) const ; 00184 00185 /** True if this is a derivative wrt a spatial coordinate */ 00186 bool isCoordDeriv() const {return type()==CoordDT;} 00187 00188 /** True if this is a derivative wrt a function 00189 * or a spatial derivative of a function */ 00190 bool isFunctionalDeriv() const {return type()==FunctionalDT;} 00191 00192 /** True if my operative function is a test function */ 00193 bool isTestFunction() const ; 00194 00195 /** True if my operative function is unknown */ 00196 bool isUnknownFunction() const ; 00197 00198 /** True if my operative function is a parameter */ 00199 bool isParameter() const ; 00200 00201 /** Create a new functional derivative in which the function 00202 * has been differentiated spatially by the given multi index, for example, 00203 * <tt>derivWrtMultiIndex(MultiIndex(0,0,1))</tt> transforms 00204 * \f$\frac{\partial}{\partial p}\f$ to 00205 * \f$\frac{\partial}{\partial D_z p}\f$ 00206 * */ 00207 Deriv derivWrtMultiIndex(const MultiIndex& mi) const ; 00208 00209 /** Whether it's possible to take a spatial derivative of this object */ 00210 bool canBeDifferentiated() const ; 00211 00212 /** \brief Return the DOF ID of my operative function, for 00213 example, if I am \f$\frac{\partial}{\partial D_y u_x}\f$ then 00214 return <tt>dofID</tt>\f$({\bf u})\f$. 00215 If I'm not a functional derivative, 00216 throw an error. 00217 */ 00218 int dofID() const ; 00219 00220 /** Return the ID for my operative function */ 00221 const FunctionIdentifier& fid() const ; 00222 00223 /** Return the spatial derivative acting on my operative function */ 00224 const SpatialDerivSpecifier& opOnFunc() const ; 00225 00226 /** Indicate my algebra type */ 00227 const AlgebraSpecifier& algSpec() const {return myAlgSpec_;} 00228 00229 /** Indicate the algebra type of my operative function */ 00230 const AlgebraSpecifier& funcAlgSpec() const ; 00231 00232 /** Return a pointer to my function's data */ 00233 RCP<const CommonFuncDataStub> data() const ; 00234 00235 /** If I am a coordinate derivative, return my direction */ 00236 int coordDerivDir() const ; 00237 00238 /** Return a pointer to my operative function */ 00239 const SymbolicFuncElement* symbFuncElem() const {return symbFuncElem_;} 00240 00241 /** Return a pointer to my operative function */ 00242 const SymbolicFunc* symbFunc() const {return symbFunc_;} 00243 00244 private: 00245 /** */ 00246 static AlgebraSpecifier derivAlgSpec(const AlgebraSpecifier& a, 00247 const SpatialDerivSpecifier& sds); 00248 00249 /** */ 00250 const SymbolicFuncDescriptor* sfdPtr() const ; 00251 00252 /** */ 00253 void checkConsistencyOfOperations() const ; 00254 00255 AlgebraSpecifier myAlgSpec_; 00256 00257 FunctionIdentifier fid_; 00258 00259 SpatialDerivSpecifier sds_; 00260 00261 const SymbolicFuncElement* symbFuncElem_; 00262 00263 const SymbolicFunc* symbFunc_; 00264 00265 int coordDerivDir_; 00266 00267 }; 00268 00269 /** \relates Deriv */ 00270 Deriv coordDeriv(int d); 00271 00272 /** \relates Deriv */ 00273 Deriv coordDeriv(const MultiIndex& mi); 00274 00275 /** \relates Deriv */ 00276 Deriv funcDeriv(const SymbolicFuncElement* symbFunc); 00277 00278 /** \relates Deriv */ 00279 Deriv funcDeriv(const SymbolicFuncElement* symbFunc, const MultiIndex& mi); 00280 00281 /** \relates Deriv */ 00282 Deriv funcDeriv(const SymbolicFunc* symbFunc); 00283 00284 /** \relates Deriv */ 00285 Deriv funcDeriv(const SymbolicFunc* symbFunc, const MultiIndex& mi); 00286 00287 /** \relates Deriv */ 00288 Deriv normalDeriv(const SymbolicFuncElement* symbFunc); 00289 00290 Deriv divergenceDeriv(const SymbolicFunc* symbFunc); 00291 00292 00293 } 00294 00295 namespace std 00296 { 00297 /** \relates Deriv */ 00298 inline ostream& operator<<(std::ostream& os, const Sundance::Deriv& d) 00299 { 00300 os << d.toString(); return os; 00301 } 00302 } 00303 00304 00305 #endif