SundanceDeriv.hpp
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 #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

Site Contact