00001 /* @HEADER@ */ 00002 // ************************************************************************ 00003 // 00004 // Sundance 00005 // Copyright 2011 Sandia Corporation 00006 // 00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 00008 // the U.S. Government retains certain rights in this software. 00009 // 00010 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu) 00038 // 00039 00040 /* @HEADER@ */ 00041 00042 #ifndef SUNDANCE_EXPR_H 00043 #define SUNDANCE_EXPR_H 00044 00045 #include "SundanceDefs.hpp" 00046 #include "SundanceExprBase.hpp" 00047 #include "SundanceFunctionIdentifier.hpp" 00048 #include "SundanceMap.hpp" 00049 #include "PlayaHandle.hpp" 00050 #include "Teuchos_RefCountPtr.hpp" 00051 #include "Teuchos_TimeMonitor.hpp" 00052 #include <complex> 00053 00054 00055 namespace Sundance 00056 { 00057 00058 class ScalarExpr; 00059 class FuncElementBase; 00060 00061 using namespace Sundance; 00062 /** 00063 * User-level expression class. Expr is a handle to a 00064 * reference-counted pointer to a ExprBase subtype. As such, 00065 * expression copies and assignments are shallow. 00066 * 00067 * <h2> Lists </h2> 00068 * 00069 * Expressions can be grouped into lists with an arbitrary structure. Important 00070 * special cases are scalar, vector, and tensor expressions. 00071 * 00072 * <h3> Creating Lists </h3> 00073 * 00074 * <ul> 00075 * <li> Vector expressions 00076 * \code 00077 * Expr v = List(vx, vy, vz); 00078 * \endcode 00079 * <li> Heterogeneous lists 00080 * \code 00081 * // Form vector {vx, vy, vz} 00082 * Expr v = List(vx, vy, vz); 00083 * Expr q = new TestFunction(new Lagrange(1)); 00084 * // Form heterogeneous list {{vx, vy, vz}, q} 00085 * Expr state = List(v, q); 00086 * \endcode 00087 * </ul> 00088 * 00089 * <h3> Probing Lists </h3> 00090 * 00091 * <ul> 00092 * <li> Finding the size of the top level of a list 00093 * \code 00094 * // Form vector {vx, vy, vz} 00095 * Expr v = List(vx, vy, vz); 00096 * Expr q = new TestFunction(new Lagrange(1)); 00097 * // Form heterogeneous list {{vx, vy, vz}, q} 00098 * Expr state = List(v, q); 00099 * // Check top-level size of state list {{vx, vy, vz}, q} 00100 * int stateSize = state.size(); // returns 2 00101 * \endcode 00102 * <li> Finding the total size of a list 00103 * \code 00104 * // Check total size of state list 00105 * int totalSize = state.totalSize(); // returns 4 00106 * \endcode 00107 * </ul> 00108 * 00109 * <h3> Manipulating Lists </h3> 00110 * 00111 * 00112 * 00113 * <h2> Arithmetic Operations </h2> 00114 * 00115 * <ul> 00116 * <li> Addition 00117 * \code 00118 * Expr sum = x + y; 00119 * \endcode 00120 * The operands must have identical list structures. 00121 * 00122 * <li> Subtraction 00123 * \code 00124 * Expr diff = x - y; 00125 * \endcode 00126 * The operands must have identical list structures. 00127 * 00128 * <li> Multiplication 00129 * \code 00130 * Expr product = x * y; 00131 * \endcode 00132 * The operands must have list 00133 * structures such that the product can be interpreted as a 00134 * scalar-vector product or as an inner product between vectors 00135 * or tensors. The multiplication operator is also used to 00136 * represent the application of a differential operator. 00137 * 00138 * <li> Division 00139 * \code 00140 * Expr quotient = x / y; 00141 * \endcode 00142 * The denominator must be scalar-valued. 00143 * </ul> 00144 * 00145 * <h2> Expression Subtypes </h2> 00146 * The user-level expression subtypes are listed below, along with examples of their use. 00147 * <ul> 00148 * <li> UnknownFunction - Represents an unknown function in a finite-element problem. 00149 * Unknown functions can be scalar-valued or vector valued. 00150 * 00151 * Example of creation of a scalar-valued unknown function: 00152 * \code 00153 * Expr u = new UnknownFunction(new Lagrange(1)); 00154 * \endcode 00155 * 00156 * Example of creation of a vector-valued unknown function: 00157 * \code 00158 * Expr u = new UnknownFunction(List(new Lagrange(1), new Lagrange(1))); 00159 * \endcode 00160 * 00161 * <li> TestFunction - Represents a test function in a finite-element problem. 00162 * Test functions can be scalar-valued or vector valued. 00163 * 00164 * Example of creation of a scalar-valued test function: 00165 * \code 00166 * Expr v = new TestFunction(new Lagrange(1)); 00167 * \endcode 00168 * 00169 * Example of creation of a vector-valued test function: 00170 * \code 00171 * Expr u = new TestFunction(List(new Lagrange(1), new Lagrange(1))); 00172 * \endcode 00173 * 00174 * <li> Derivative - Represents a spatial derivative operator. 00175 * Spatial derivatives are applied 00176 * using the multiplication operator. 00177 * \code 00178 * Expr dx = new Derivative(0); 00179 * Expr convect = (u*dx)*u; 00180 * \endcode 00181 * Derivative expressions are scalar valued. However, vector differential operators 00182 * can be created using the List operator. For example, 00183 * \code 00184 * Expr dx = new Derivative(0); 00185 * Expr dy = new Derivative(1); 00186 * Expr grad = List(dx, dy); 00187 * \endcode 00188 * 00189 * <li> CoordExpr - Represents a coordinate functions. 00190 * \code 00191 * Expr x = new CoordExpr(0); 00192 * Expr y = new CoordExpr(1); 00193 * Expr r = sqrt(x*x + y*y); 00194 * \endcode 00195 * Coordinate expressions are scalar valued. 00196 * 00197 * <li> CellDiameterExpr - Represents the diameter of a cell. Cell 00198 * diameters are often used in stabilized methods. 00199 * \code 00200 * Expr h = new CellDiameterExpr(); 00201 * Expr streamlineDiffusion = eps*h*h*((u*grad)*v)*((u*grad)*T); 00202 * \endcode 00203 * Cell diameter expressions are scalar valued. 00204 * </ul> 00205 */ 00206 class Expr : public Playa::Handle<ExprBase> 00207 { 00208 public: 00209 /* boilerplate handle ctors */ 00210 HANDLE_CTORS(Expr, ExprBase); 00211 00212 /** Construct with a constant. Creates a ConstantExpr. */ 00213 Expr(const double& c); 00214 00215 /** Construct with a complex constant. Creates a ComplexExpr. */ 00216 Expr(const std::complex<double>& c); 00217 00218 /** Add two expressions. The operands must have identical list 00219 * structures. 00220 */ 00221 Expr operator+(const Expr& other) const ; 00222 /** Subtract two expressions. The operands must have identical 00223 * list structures. */ 00224 Expr operator-(const Expr& other) const ; 00225 /** Multiply two expressions. The operands must have list 00226 * structures such that the product can be interpreted as a 00227 * scalar-vector product or as an inner product between vectors 00228 * or tensors. The multiplication operator is also used to 00229 * represent the application of a differential operator. 00230 */ 00231 Expr operator*(const Expr& other) const ; 00232 /** Divide one expression by another. The right operand must be 00233 a scalar. */ 00234 Expr operator/(const Expr& other) const ; 00235 00236 /** Divide an expression by a double. */ 00237 Expr operator/(const double& other) const 00238 {return operator*(1.0/other);} 00239 00240 /** Divide an expression by a complex. */ 00241 Expr operator/(const std::complex<double>& other) const 00242 {return operator*(1.0/other);} 00243 00244 /** Unary minus operator */ 00245 Expr operator-() const ; 00246 00247 /** Return real part of a complex expression */ 00248 Expr real() const ; 00249 00250 /** Return imaginary part of a complex expression */ 00251 Expr imag() const ; 00252 00253 /** Return complex conjugate */ 00254 Expr conj() const ; 00255 00256 00257 /** List element accessor */ 00258 const Expr& operator[](int i) const ; 00259 00260 /** Number of elements in top level of list */ 00261 int size() const ; 00262 00263 /** Total number of elements in list. */ 00264 int totalSize() const ; 00265 00266 /** Append a new element to this list */ 00267 void append(const Expr& expr); 00268 00269 /** Flatten this list */ 00270 Expr flatten() const ; 00271 00272 /** Flatten list and spectral structure */ 00273 Expr flattenSpectral() const ; 00274 00275 /** */ 00276 std::string toString() const ; 00277 00278 /** */ 00279 XMLObject toXML() const ; 00280 00281 /** */ 00282 bool isComplex() const ; 00283 00284 /** */ 00285 bool isSpectral() const; 00286 00287 /** */ 00288 bool isTestElement() const ; 00289 00290 /** */ 00291 bool isUnknownElement() const ; 00292 00293 /** */ 00294 void setParameterValue(const double& value); 00295 /** */ 00296 double getParameterValue() const ; 00297 00298 /** Indicate whether the expression is independent of the given 00299 * functions */ 00300 bool isIndependentOf(const Expr& u) const ; 00301 00302 00303 /** 00304 * Indicate whether the expression is nonlinear 00305 * with respect to test functions */ 00306 bool isLinearInTests() const ; 00307 00308 /** 00309 * Indicate whether every term in the expression contains test functions */ 00310 bool everyTermHasTestFunctions() const ; 00311 00312 /** 00313 * Indicate whether the expression contains test functions */ 00314 bool hasTestFunctions() const ; 00315 00316 /** Indicate whether the expression is linear in the given 00317 * functions */ 00318 bool isLinearForm(const Expr& u) const ; 00319 00320 /** Indicate whether the expression is quadratic in the given 00321 * functions */ 00322 bool isQuadraticForm(const Expr& u) const ; 00323 00324 /** Find the unknown functions appearing in this expression */ 00325 void getUnknowns(Set<int>& unkID, Array<Expr>& unks) const ; 00326 00327 /** Find the test functions appearing in this expression */ 00328 void getTests(Set<int>& testID, Array<Expr>& tests) const ; 00329 00330 00331 #ifndef DOXYGEN_DEVELOPER_ONLY 00332 00333 00334 00335 /** 00336 * Turn evaluation caching on 00337 */ 00338 static bool& evaluationCachingOn() {static bool rtn = true; return rtn;} 00339 00340 /** 00341 * Show parentheses around every pair of operands 00342 */ 00343 static bool& showAllParens() {static bool rtn = false; return rtn;} 00344 00345 /** Create a new handle for an existing ptr. */ 00346 static Expr handle(const RCP<ExprBase>& ptr) 00347 {return Expr(ptr);} 00348 00349 /** */ 00350 static Time& opTimer() 00351 { 00352 static RCP<Time> rtn 00353 = TimeMonitor::getNewTimer("Expr symbolic ops"); 00354 return *rtn; 00355 } 00356 /** */ 00357 static Time& outputTimer() 00358 { 00359 static RCP<Time> rtn 00360 = TimeMonitor::getNewTimer("Expr output"); 00361 return *rtn; 00362 } 00363 00364 /** Comparison operator for ordering expr trees, DO NOT use for comparison 00365 * of numerical values. */ 00366 bool lessThan(const Expr& other) const ; 00367 00368 /** Comparison operator for ordering expr trees, DO NOT use for comparison 00369 * of numerical values. */ 00370 bool operator<(const Expr& other) const ; 00371 00372 /** Equality test operator for ordering expr trees, DO NOT use for comparison 00373 * of numerical values. */ 00374 bool sameAs(const Expr& other) const ; 00375 00376 /** */ 00377 Sundance::Map<Expr, int> getSumTree() const ; 00378 00379 00380 00381 /** */ 00382 const ScalarExpr* scalarExpr() const ; 00383 00384 /** */ 00385 const FuncElementBase* funcElement() const ; 00386 00387 private: 00388 00389 00390 00391 /** Add two scalar expressions */ 00392 Expr sum(const Expr& other, int sign) const ; 00393 00394 /** Multiply two scalar expressions */ 00395 Expr multiply(const Expr& other) const ; 00396 00397 /** Divide two scalar expressions */ 00398 Expr divide(const Expr& other) const ; 00399 00400 /** Try transformations of complex addition */ 00401 bool tryAddComplex(const Expr& L, const Expr& R, int sign, 00402 Expr& rtn) const ; 00403 00404 /** Try transformations of complex multiplication */ 00405 bool tryMultiplyComplex(const Expr& L, const Expr& R, 00406 Expr& rtn) const ; 00407 00408 00409 00410 00411 #endif /* DOXYGEN_DEVELOPER_ONLY */ 00412 }; 00413 00414 /** \relates Expr */ 00415 inline std::ostream& operator<<(std::ostream& os, const Expr& e) 00416 { 00417 if (e.ptr().get()==0) {os << "Expr()"; return os;} 00418 return e.ptr()->toText(os, false); 00419 } 00420 00421 /** \relates Expr */ 00422 inline Expr operator+(const double& a, const Expr& x) 00423 {return Expr(a) + x;} 00424 00425 /** \relates Expr */ 00426 inline Expr operator-(const double& a, const Expr& x) 00427 {return Expr(a) - x;} 00428 00429 /** \relates Expr */ 00430 inline Expr operator*(const double& a, const Expr& x) 00431 {return Expr(a) * x;} 00432 00433 /** \relates Expr */ 00434 inline Expr operator/(const double& a, const Expr& x) 00435 {return Expr(a) / x;} 00436 00437 /** \relates Expr */ 00438 inline Expr operator+(const std::complex<double>& a, const Expr& x) 00439 {return Expr(a) + x;} 00440 00441 /** \relates Expr */ 00442 inline Expr operator-(const std::complex<double>& a, const Expr& x) 00443 {return Expr(a) - x;} 00444 00445 /** \relates Expr */ 00446 inline Expr operator*(const std::complex<double>& a, const Expr& x) 00447 {return Expr(a) * x;} 00448 00449 /** \relates Expr */ 00450 inline Expr operator/(const std::complex<double>& a, const Expr& x) 00451 {return Expr(a) / x;} 00452 00453 /** \relates Expr */ 00454 inline Expr Re(const Expr& a) {return a.real();} 00455 00456 /** \relates Expr */ 00457 inline Expr Im(const Expr& a) {return a.imag();} 00458 00459 /** \relates Expr */ 00460 inline Expr conj(const Expr& a) {return a.conj();} 00461 00462 /** \relates Expr */ 00463 Expr Complex(const Expr& real, const Expr& imag); 00464 00465 /** \relates Expr */ 00466 Expr List(const Expr& a); 00467 00468 /** \relates Expr */ 00469 Expr List(const Expr& a, const Expr& b); 00470 00471 /** \relates Expr */ 00472 Expr List(const Expr& a, const Expr& b, const Expr& c); 00473 00474 /** \relates Expr */ 00475 Expr List(const Expr& a, const Expr& b, const Expr& c, 00476 const Expr& d); 00477 00478 /** \relates Expr */ 00479 Expr List(const Expr& a, const Expr& b, const Expr& c, 00480 const Expr& d, const Expr& e); 00481 00482 /** \relates Expr */ 00483 Expr List(const Expr& a, const Expr& b, const Expr& c, 00484 const Expr& d, const Expr& e, const Expr& f); 00485 00486 /** \relates Expr */ 00487 Expr List(const Expr& a, const Expr& b, const Expr& c, 00488 const Expr& d, const Expr& e, const Expr& f, 00489 const Expr& g); 00490 00491 00492 /** \relates Expr */ 00493 Expr List(const Expr& a, const Expr& b, const Expr& c, 00494 const Expr& d, const Expr& e, const Expr& f, 00495 const Expr& g, const Expr& h); 00496 00497 /** \relates Expr */ 00498 Expr List(const Expr& a, const Expr& b, const Expr& c, 00499 const Expr& d, const Expr& e, const Expr& f, 00500 const Expr& g, const Expr& h, const Expr& i); 00501 00502 /** \relates Expr */ 00503 Expr List(const Expr& a, const Expr& b, const Expr& c, 00504 const Expr& d, const Expr& e, const Expr& f, 00505 const Expr& g, const Expr& h, const Expr& i, 00506 const Expr& j); 00507 00508 00509 00510 00511 } 00512 00513 #endif