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 #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
00172
00173 TEUCHOS_TEST_FOR_EXCEPT(symbFuncElem_ == 0 && symbFunc_==0);
00174 TEUCHOS_TEST_FOR_EXCEPT(symbFuncElem_ != 0 && symbFunc_!=0);
00175
00176
00177 if (symbFuncElem_) return symbFuncElem_;
00178 if (symbFunc_) return symbFunc_;
00179 return symbFunc_;
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();
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;
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