SundanceDeriv.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 "SundanceDeriv.hpp"
00032 
00033 
00034 #include "PlayaExceptions.hpp"
00035 #include "SundanceParameter.hpp"
00036 #include "SundanceUnknownFuncElement.hpp"
00037 #include "SundanceSymbolicFuncElement.hpp"
00038 #include "SundanceSymbolicFunc.hpp"
00039 #include "SundanceCommonFuncDataStub.hpp"
00040 #include "SundanceTestFuncElement.hpp"
00041  
00042 
00043 using namespace Sundance;
00044 using namespace Sundance;
00045 
00046 using namespace Sundance;
00047 using namespace Teuchos;
00048 
00049 Deriv::Deriv()
00050   : EnumTypeField<DerivType>(NullDT), myAlgSpec_(ScalarAT), fid_(), sds_(), 
00051     symbFuncElem_(0), symbFunc_(0), coordDerivDir_(-1)
00052 {}
00053 
00054 Deriv::Deriv(int coordDerivDir)
00055   : EnumTypeField<DerivType>(CoordDT), myAlgSpec_(coordDerivDir),
00056     fid_(FunctionIdentifier()), sds_(), 
00057     symbFuncElem_(0), symbFunc_(0),
00058     coordDerivDir_(coordDerivDir)
00059 {}
00060 
00061 
00062 Deriv::Deriv(
00063   const SymbolicFuncElement* func,
00064   const SpatialDerivSpecifier& d
00065   )
00066   : EnumTypeField<DerivType>(FunctionalDT), myAlgSpec_(),
00067     fid_(), sds_(d),
00068     symbFuncElem_(func),
00069     symbFunc_(0), coordDerivDir_(-1)
00070 {
00071   TEUCHOS_TEST_FOR_EXCEPTION(func==0, std::logic_error, 
00072     "null function given to Deriv ctor");
00073   fid_ = func->fid();
00074   myAlgSpec_ = derivAlgSpec(fid_.algSpec(), d);
00075 
00076   checkConsistencyOfOperations();
00077 }
00078 
00079 Deriv::Deriv( 
00080   const SymbolicFunc* func,
00081   const SpatialDerivSpecifier& d
00082   )
00083   : EnumTypeField<DerivType>(FunctionalDT), myAlgSpec_(),
00084     fid_(), sds_(d),
00085     symbFuncElem_(0), symbFunc_(func), coordDerivDir_(-1)
00086 {
00087   TEUCHOS_TEST_FOR_EXCEPTION(func==0, std::logic_error, 
00088     "null function given to Deriv ctor");
00089   fid_ = func->fid();
00090   myAlgSpec_ = derivAlgSpec(fid_.algSpec(), d);
00091 
00092   checkConsistencyOfOperations();
00093 }
00094 
00095 
00096 void Deriv::checkConsistencyOfOperations() const 
00097 {
00098   TEUCHOS_TEST_FOR_EXCEPT(sds_.isDivergence() && !fid_.isVector());
00099   TEUCHOS_TEST_FOR_EXCEPT(sds_.isPartial() && fid_.isVector());
00100   TEUCHOS_TEST_FOR_EXCEPT(sds_.isNormal() && fid_.isVector());
00101 }
00102 
00103 
00104 bool Deriv::operator<(const Deriv& other) const 
00105 {
00106   if (type() < other.type()) return true;
00107   if (type() > other.type()) return false;
00108 
00109   if (type() == CoordDT)
00110   {
00111     return coordDerivDir() < other.coordDerivDir();
00112   }
00113   else 
00114   {
00115     OrderedPair<FunctionIdentifier, SpatialDerivSpecifier> me(fid(),sds_);
00116     OrderedPair<FunctionIdentifier, SpatialDerivSpecifier> you(other.fid(),other.sds_);
00117     return me < you;
00118   }
00119 }
00120 
00121 
00122 bool Deriv::operator==(const Deriv& other) const
00123 {
00124   return !(*this < other || other < *this);
00125 }
00126 
00127 std::string Deriv::toString(bool verb) const 
00128 {
00129   static Array<string> coords = tuple<string>("x", "y", "z");
00130   switch(type())
00131   {
00132     case CoordDT:
00133       return coords[coordDerivDir()];
00134     case FunctionalDT:
00135     {
00136       string f;
00137       if (symbFunc_!=0) f = symbFunc_->toString();
00138       else if (symbFuncElem_!=0) f = symbFuncElem_->toString();
00139       else TEUCHOS_TEST_FOR_EXCEPT(true);
00140 
00141       if (opOnFunc().isPartial() && opOnFunc().derivOrder()>0)
00142       {
00143         return "D[" + f + ", " 
00144           + coords[opOnFunc().mi().firstOrderDirection()] + "]";
00145       }
00146       else if (opOnFunc().isDivergence())
00147       {
00148         return "div(" + f + ")";
00149       }
00150       else if (opOnFunc().isNormal() && opOnFunc().derivOrder()>0)
00151       {
00152         return "D[" + f + ", normal]";
00153       }
00154       else if (opOnFunc().isIdentity()) 
00155       {
00156         return f;
00157       }
00158       else TEUCHOS_TEST_FOR_EXCEPT(1);
00159     }
00160     case NullDT:
00161       return "NullDeriv()";
00162     default:
00163       TEUCHOS_TEST_FOR_EXCEPT(1);
00164       return "NullDeriv";
00165   }
00166 }
00167 
00168 const SymbolicFuncDescriptor* Deriv::sfdPtr() const 
00169 {
00170   assertType(FunctionalDT);
00171   /* at this point, exactly one of the two function pointers should be
00172    * nonzero */
00173   TEUCHOS_TEST_FOR_EXCEPT(symbFuncElem_ == 0 && symbFunc_==0);
00174   TEUCHOS_TEST_FOR_EXCEPT(symbFuncElem_ != 0 && symbFunc_!=0);
00175   
00176   /* return the nonzero pointer */
00177   if (symbFuncElem_) return symbFuncElem_;
00178   if (symbFunc_) return symbFunc_;
00179   return symbFunc_; // -Wall
00180 }
00181 
00182 bool Deriv::isTestFunction() const 
00183 {
00184   if( isFunctionalDeriv() )
00185   {
00186     return sfdPtr()->isTestFunction();
00187   }
00188   return false;
00189 }
00190 
00191 bool Deriv::isUnknownFunction() const 
00192 {
00193   if( isFunctionalDeriv() )
00194   {
00195     return sfdPtr()->isUnknownFunction();
00196   }
00197   return false;
00198 }
00199 
00200 
00201 bool Deriv::isParameter() const 
00202 {
00203   if( isFunctionalDeriv() )
00204   {
00205     return sfdPtr()->isParameter();
00206   }
00207   return false;
00208 }
00209 
00210 int Deriv::dofID() const 
00211 {
00212   assertType(FunctionalDT);
00213   return fid_.dofID();
00214 }
00215 
00216 const AlgebraSpecifier& Deriv::funcAlgSpec() const 
00217 {
00218   assertType(FunctionalDT);
00219   return fid_.algSpec();
00220 }
00221 
00222 bool Deriv::canBeDifferentiated() const 
00223 {
00224   assertType(FunctionalDT);
00225   if (isParameter()) return false;
00226   return opOnFunc().isIdentity() || opOnFunc().isPartial();
00227 }
00228 
00229 int Deriv::coordDerivDir() const
00230 {
00231   assertType(CoordDT);
00232   return coordDerivDir_;
00233 }
00234 
00235 RCP<const CommonFuncDataStub> Deriv::data() const
00236 {
00237   assertType(FunctionalDT);
00238   TEUCHOS_TEST_FOR_EXCEPTION(symbFuncElem_==0 && symbFunc_==0, 
00239     std::logic_error,
00240     "Deriv::data() called, but deriv=" << *this << " does not contain a "
00241     "valid function");
00242   if (symbFuncElem_) return symbFuncElem_->commonData();
00243   if (symbFunc_) return symbFunc_->commonData();
00244   return symbFunc_->commonData(); // -Wall
00245 }
00246 
00247 const FunctionIdentifier& Deriv::fid() const 
00248 {
00249   assertType(FunctionalDT);
00250   return fid_;
00251 }
00252 
00253 const SpatialDerivSpecifier& Deriv::opOnFunc() const 
00254 {
00255   assertType(FunctionalDT);
00256   return sds_;
00257 }
00258 
00259 Deriv Deriv::derivWrtMultiIndex(const MultiIndex& mi) const
00260 {
00261   assertType(FunctionalDT);
00262   TEUCHOS_TEST_FOR_EXCEPTION(mi.order()>0 && sds_.isDivergence(), std::logic_error,
00263     "cannot take spatial derivative of an atomic divergence operation");
00264   TEUCHOS_TEST_FOR_EXCEPTION(mi.order()>0 && isParameter(), std::logic_error,
00265     "cannot take spatial derivative of a parameter");
00266 
00267   SpatialDerivSpecifier d = sds_.derivWrtMultiIndex(mi);
00268 
00269   if (symbFuncElem_ != 0)
00270   {
00271     return Deriv(symbFuncElem_, d);
00272   }
00273   else if (symbFunc_ != 0)
00274   {
00275     return Deriv(symbFunc_, d);
00276   }
00277   TEUCHOS_TEST_FOR_EXCEPTION(symbFuncElem_==0 && symbFunc_==0, 
00278     std::logic_error,
00279     "attempt to differentiate a null operative function");
00280   return *this; // -Wall
00281 }
00282 
00283 
00284 AlgebraSpecifier Deriv::derivAlgSpec(
00285   const AlgebraSpecifier& funcAlgSpec,
00286   const SpatialDerivSpecifier& d)
00287 {
00288   if (d.derivOrder()==0) 
00289   {
00290     return funcAlgSpec;
00291   }
00292   else if (d.isPartial()) 
00293   {
00294     return AlgebraSpecifier(d.mi().firstOrderDirection());
00295   }
00296   else if (d.isDivergence())
00297   {
00298     return ScalarAT;
00299   }
00300   else if (d.isNormal())
00301   {
00302     return NormalAT;
00303   }
00304   else
00305   {
00306     TEUCHOS_TEST_FOR_EXCEPT(true);
00307     return IdentitySDT;
00308   }
00309 }
00310 
00311 
00312 
00313 
00314 namespace Sundance
00315 {
00316 
00317 Deriv coordDeriv(int d) 
00318 {
00319   return Deriv(d);
00320 }
00321 
00322 Deriv coordDeriv(const MultiIndex& mi) 
00323 {
00324   return Deriv(mi.firstOrderDirection());
00325 }
00326 
00327 
00328 Deriv funcDeriv(const SymbolicFuncElement* symbFunc)
00329 {
00330   return Deriv(symbFunc, SpatialDerivSpecifier());
00331 }
00332 
00333 Deriv funcDeriv(const SymbolicFuncElement* symbFunc,
00334   const MultiIndex& mi)
00335 {
00336   return Deriv(symbFunc, SpatialDerivSpecifier(mi));
00337 }
00338 
00339 Deriv funcDeriv(const SymbolicFunc* symbFunc)
00340 {
00341   return Deriv(symbFunc, SpatialDerivSpecifier());
00342 }
00343 
00344 
00345 Deriv funcDeriv(const SymbolicFunc* symbFunc,
00346   const MultiIndex& mi)
00347 {
00348   return Deriv(symbFunc, SpatialDerivSpecifier(mi));
00349 }
00350 
00351 
00352 Deriv normalDeriv(const SymbolicFuncElement* symbFunc)
00353 {
00354   return Deriv(symbFunc, SpatialDerivSpecifier(NormalSDT, 1));
00355 }
00356 
00357 Deriv divergenceDeriv(const SymbolicFunc* symbFunc)
00358 {
00359   return Deriv(symbFunc, SpatialDerivSpecifier(DivSDT, 0));
00360 }
00361 
00362 }
00363 

Site Contact