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