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 "SundanceExpr.hpp"
00043 #include "SundanceListExpr.hpp"
00044 #include "SundanceSumExpr.hpp"
00045 #include "SundanceProductExpr.hpp"
00046 #include "SundanceConstantExpr.hpp"
00047 #include "SundanceCoordExpr.hpp"
00048 #include "SundanceDerivative.hpp"
00049 #include "SundanceDiffOp.hpp"
00050
00051
00052 #include "SundanceUnaryMinus.hpp"
00053 #include "SundanceZeroExpr.hpp"
00054 #include "SundanceComplexExpr.hpp"
00055 #include "SundanceOut.hpp"
00056 #include "PlayaTabs.hpp"
00057 #include "SundanceStdSumTransformations.hpp"
00058 #include "SundanceStdProductTransformations.hpp"
00059 #include "SundanceNonlinearUnaryOp.hpp"
00060 #include "SundanceStdMathOps.hpp"
00061 #include "SundanceParameter.hpp"
00062 #include "SundanceSpectralBasis.hpp"
00063 #include "SundanceSpectralExpr.hpp"
00064 #include "SundanceUnknownFuncElement.hpp"
00065 #include "SundanceTestFuncElement.hpp"
00066 #include "Teuchos_TimeMonitor.hpp"
00067
00068 using namespace Sundance;
00069 using namespace Sundance;
00070
00071 using namespace Teuchos;
00072 using namespace Sundance;
00073
00074 static Time& sumTimer()
00075 {
00076 static RCP<Time> rtn
00077 = TimeMonitor::getNewTimer("symbolic sum");
00078 return *rtn;
00079 }
00080
00081 static Time& unaryMinusTimer()
00082 {
00083 static RCP<Time> rtn
00084 = TimeMonitor::getNewTimer("symbolic unary minus");
00085 return *rtn;
00086 }
00087
00088
00089 static Time& trySumComplexTimer()
00090 {
00091 static RCP<Time> rtn
00092 = TimeMonitor::getNewTimer("test for complex sum");
00093 return *rtn;
00094 }
00095
00096 static Time& tryMultiplyComplexTimer()
00097 {
00098 static RCP<Time> rtn
00099 = TimeMonitor::getNewTimer("test for complex product");
00100 return *rtn;
00101 }
00102
00103
00104
00105 static Time& prodTimer()
00106 {
00107 static RCP<Time> rtn
00108 = TimeMonitor::getNewTimer("symbolic product");
00109 return *rtn;
00110 }
00111
00112
00113 Expr::Expr(const double& c)
00114 : Playa::Handle<ExprBase>(new ConstantExpr(c))
00115 {}
00116
00117 Expr::Expr(const std::complex<double>& c)
00118 : Playa::Handle<ExprBase>(new ComplexExpr(new ConstantExpr(c.real()),
00119 new ConstantExpr(c.imag())))
00120 {}
00121
00122 bool Expr::isComplex() const
00123 {
00124 return dynamic_cast<const ComplexExpr*>(ptr().get()) != 0;
00125 }
00126
00127
00128
00129 bool Expr::isSpectral() const
00130 {
00131 return dynamic_cast<const SpectralExpr*>(ptr().get()) != 0;
00132 }
00133
00134
00135
00136
00137 XMLObject Expr::toXML() const
00138 {
00139 TimeMonitor t(outputTimer());
00140
00141 return ptr()->toXML();
00142 }
00143
00144 string Expr::toString() const
00145 {
00146 TimeMonitor t(outputTimer());
00147
00148 TeuchosOStringStream ss;
00149 ptr()->toText(ss, false);
00150 return TEUCHOS_OSTRINGSTREAM_GET_C_STR(ss);
00151 }
00152
00153
00154 bool Expr::sameAs(const Expr& other) const
00155 {
00156 if (this->lessThan(other)) return false;
00157 if (other.lessThan(*this)) return false;
00158 return true;
00159 }
00160
00161 bool Expr::operator<(const Expr& other) const
00162 {
00163 return this->lessThan(other);
00164 }
00165
00166 bool Expr::lessThan(const Expr& other) const
00167 {
00168 RCP<ScalarExpr> sThis = rcp_dynamic_cast<ScalarExpr>(ptr());
00169 RCP<ScalarExpr> sOther = rcp_dynamic_cast<ScalarExpr>(other.ptr());
00170
00171 TEUCHOS_TEST_FOR_EXCEPTION(sThis.get()==0, std::logic_error,
00172 "ordering not defined for non-scalar expression "
00173 << toString());
00174
00175 TEUCHOS_TEST_FOR_EXCEPTION(sOther.get()==0, std::logic_error,
00176 "ordering not defined for non-scalar expressions"
00177 << other.toString());
00178
00179
00180 const ConstantExpr* cMe = dynamic_cast<const ConstantExpr*>(sThis.get());
00181 const ConstantExpr* cOther = dynamic_cast<const ConstantExpr*>(sOther.get());
00182
00183
00184 if (cMe != 0 && cOther==0) return true;
00185 if (cOther != 0 && cMe==0) return false;
00186 if (cOther != 0 && cMe != 0) return cMe->lessThan(cOther);
00187
00188
00189
00190 const SpatiallyConstantExpr* scMe
00191 = dynamic_cast<const SpatiallyConstantExpr*>(sThis.get());
00192 const SpatiallyConstantExpr* scOther
00193 = dynamic_cast<const SpatiallyConstantExpr*>(sOther.get());
00194 if (scMe != 0 && scOther==0) return true;
00195 if (scOther != 0 && scMe==0) return false;
00196
00197
00198
00199 if (sThis->typeName() < sOther->typeName()) return true;
00200 if (sThis->typeName() > sOther->typeName()) return false;
00201
00202
00203 return sThis->lessThan(sOther.get());
00204 }
00205
00206 Sundance::Map<Expr, int> Expr::getSumTree() const
00207 {
00208 RCP<ScalarExpr> sThis = rcp_dynamic_cast<ScalarExpr>(ptr());
00209
00210 TEUCHOS_TEST_FOR_EXCEPTION(sThis.get()==0, std::logic_error,
00211 "etSumTree() not defined for non-scalar expression "
00212 << toString());
00213
00214 const SumExpr* s = dynamic_cast<const SumExpr*>(sThis.get());
00215 const UnaryMinus* u = dynamic_cast<const UnaryMinus*>(sThis.get());
00216 if (s != 0)
00217 {
00218 return s->getSumTree();
00219 }
00220 else if (u != 0)
00221 {
00222 Sundance::Map<Expr, int> rtn;
00223 rtn.put(u->arg(), -1);
00224 return rtn;
00225 }
00226 else
00227 {
00228 Sundance::Map<Expr, int> rtn;
00229 rtn.put(*this, 1);
00230 return rtn;
00231 }
00232
00233 }
00234
00235 bool Expr::tryAddComplex(const Expr& L, const Expr& R, int sign,
00236 Expr& rtn) const
00237 {
00238 TimeMonitor t(trySumComplexTimer());
00239 TEUCHOS_TEST_FOR_EXCEPTION(L.size() != 1 || R.size() != 1, std::logic_error,
00240 "non-scalar exprs should have been reduced before "
00241 "call to tryAddComplex(). Left=" << L << " right="
00242 << R);
00243 if (L.isComplex() || R.isComplex())
00244 {
00245 if (sign > 0)
00246 {
00247 rtn = new ComplexExpr(L.real() + R.real(),
00248 L.imag() + R.imag());
00249 }
00250 else
00251 {
00252 rtn = new ComplexExpr(L.real() - R.real(),
00253 L.imag() - R.imag());
00254 }
00255 return true;
00256 }
00257 else
00258 {
00259 return false;
00260 }
00261 }
00262
00263
00264
00265 bool Expr::tryMultiplyComplex(const Expr& L, const Expr& R,
00266 Expr& rtn) const
00267 {
00268 TimeMonitor t(tryMultiplyComplexTimer());
00269 TEUCHOS_TEST_FOR_EXCEPTION(L.size() != 1 || R.size() != 1, std::logic_error,
00270 "non-scalar exprs should have been reduced before "
00271 "call to tryMultiplyComplex(). Left=" << L << " right="
00272 << R);
00273
00274 if (L.isComplex() || R.isComplex())
00275 {
00276 if (Re(L).sameAs(Re(R)) && Im(L).sameAs(-Im(R)))
00277 {
00278 rtn = Re(R)*Re(R) + Im(R)*Im(R);
00279 }
00280 else
00281 {
00282 Expr re = Re(L)*Re(R) - Im(L)*Im(R);
00283 Expr im = Re(L)*Im(R) + Im(L)*Re(R);
00284 rtn = new ComplexExpr(re, im);
00285 }
00286 return true;
00287 }
00288 else
00289 {
00290 return false;
00291 }
00292 }
00293
00294
00295
00296
00297 Expr Expr::operator+(const Expr& other) const
00298 {
00299 TimeMonitor t(opTimer());
00300 TimeMonitor ts(sumTimer());
00301
00302
00303 if (this->size()!=1 || other.size()!=1)
00304 {
00305 TEUCHOS_FUNC_TIME_MONITOR("plus branch 1");
00306 Array<Expr> rtn(this->size());
00307 TEUCHOS_TEST_FOR_EXCEPTION(this->size() != other.size(), std::runtime_error,
00308 "mismatched list structures in operands L="
00309 << *this << ", R=" << other);
00310 for (int i=0; i<this->size(); i++)
00311 {
00312 rtn[i] = (*this)[i] + other[i];
00313 }
00314 return new ListExpr(rtn);
00315 }
00316 else
00317 {
00318 TEUCHOS_FUNC_TIME_MONITOR("plus branch 2");
00319 Expr rtn;
00320
00321 if (tryAddComplex((*this)[0], other[0], 1, rtn)) return rtn;
00322
00323 return (*this)[0].sum(other[0], 1);
00324 }
00325 }
00326
00327 Expr Expr::operator-(const Expr& other) const
00328 {
00329 TimeMonitor t(opTimer());
00330 TimeMonitor ts(sumTimer());
00331
00332
00333 if (this->size()!=1 || other.size()!=1)
00334 {
00335 TEUCHOS_FUNC_TIME_MONITOR("minus branch 1");
00336 Array<Expr> rtn(this->size());
00337 TEUCHOS_TEST_FOR_EXCEPTION(this->size() != other.size(), std::runtime_error,
00338 "mismatched list structures in operands L="
00339 << *this << ", R=" << other);
00340 for (int i=0; i<this->size(); i++)
00341 {
00342 rtn[i] = (*this)[i] - other[i];
00343 }
00344 return new ListExpr(rtn);
00345 }
00346 else
00347 {
00348 TEUCHOS_FUNC_TIME_MONITOR("minus branch 2");
00349 Expr rtn;
00350
00351 if (tryAddComplex((*this)[0], other[0], -1, rtn)) return rtn;
00352
00353 return (*this)[0].sum(other[0], -1);
00354 }
00355 }
00356
00357
00358 Expr Expr::sum(const Expr& other, int sign) const
00359 {
00360 TEUCHOS_FUNC_TIME_MONITOR("Expr::sum()");
00361 RCP<ScalarExpr> rtn;
00362 RCP<ScalarExpr> sThis = rcp_dynamic_cast<ScalarExpr>(ptr());
00363 RCP<ScalarExpr> sOther = rcp_dynamic_cast<ScalarExpr>(other.ptr());
00364
00365 TEUCHOS_TEST_FOR_EXCEPTION(ptr().get()==NULL, std::logic_error,
00366 "Expr::sum() detected null this pointer");
00367
00368 TEUCHOS_TEST_FOR_EXCEPTION(sThis.get()==NULL, std::logic_error,
00369 "Expr::sum(): Left operand " << toString()
00370 << " is a non-scalar expression. All list structure "
00371 "should have been handled before this point");
00372
00373 TEUCHOS_TEST_FOR_EXCEPTION(sOther.get()==NULL, std::logic_error,
00374 "Expr::sum(): Right operand " << other.toString()
00375 << " is a non-scalar expression. All list structure "
00376 "should have been handled before this point");
00377
00378 static StdSumTransformations trans;
00379
00380 if (trans.doTransform(sThis, sOther, sign, rtn))
00381 {
00382 if (SymbolicTransformation::classVerbosity() > 0)
00383 {
00384 Out::println("Expr::sum() transformed sum\n["
00385 + toString() + "+"
00386 + other.toString() + "]\n to\n ["
00387 + rtn->toString() + "]");
00388 }
00389 return handle(rtn);
00390 }
00391
00392 else return new SumExpr(sThis, sOther, sign);
00393 }
00394
00395
00396 Expr Expr::operator*(const Expr& other) const
00397 {
00398 TimeMonitor t(opTimer());
00399 TimeMonitor tp(prodTimer());
00400 Tabs tab1;
00401
00402
00403 if (this->size() == 1 && other.size()==1)
00404 {
00405 Expr rtn;
00406
00407 if (tryMultiplyComplex((*this)[0], other[0], rtn))
00408 {
00409 return rtn;
00410 }
00411
00412 rtn = (*this)[0].multiply(other[0]);
00413 return rtn;
00414 }
00415
00416
00417 if (this->size()==1)
00418 {
00419 Array<Expr> rtn(other.size());
00420 for (int i=0; i<other.size(); i++)
00421 {
00422 rtn[i] = (*this)[0] * other[i];
00423 }
00424 return new ListExpr(rtn);
00425 }
00426
00427
00428 if (other.size()==1)
00429 {
00430 Array<Expr> rtn(this->size());
00431 for (int i=0; i<this->size(); i++)
00432 {
00433 rtn[i] = (*this)[i] * other[0];
00434 }
00435 return new ListExpr(rtn);
00436 }
00437
00438
00439 if (this->size() == totalSize() && other.size()==other.totalSize()
00440 && this->size() == other.size())
00441 {
00442 Expr rtn = new ZeroExpr();
00443
00444 for (int i=0; i<this->size(); i++)
00445 {
00446 rtn = rtn + (*this)[i]*other[i];
00447 }
00448 return rtn;
00449 }
00450
00451
00452
00453 int cols = (*this)[0].size();
00454 bool rectangular = true;
00455 for (int i=0; i<this->size(); i++)
00456 {
00457 if ((*this)[i].size() != cols) rectangular = false;
00458 }
00459 TEUCHOS_TEST_FOR_EXCEPTION(!rectangular, std::runtime_error,
00460 "Expr::operator* detected list-list multiplication "
00461 "with a non-rectangular left operator "
00462 << toString());
00463
00464 TEUCHOS_TEST_FOR_EXCEPTION(cols != other.size(), std::runtime_error,
00465 "Expr::operator* detected mismatched dimensions in "
00466 "list-list multiplication. Left operator is "
00467 << toString() << ", right operator is "
00468 << other.toString());
00469
00470 Array<Expr> rtn(this->size());
00471 for (int i=0; i<this->size(); i++)
00472 {
00473 rtn[i] = (*this)[i] * other;
00474 }
00475
00476 return new ListExpr(rtn);
00477 }
00478
00479 Expr Expr::divide(const Expr& other) const
00480 {
00481 RCP<ScalarExpr> sOther = rcp_dynamic_cast<ScalarExpr>(other.ptr());
00482 Expr recip = new NonlinearUnaryOp(sOther, rcp(new StdReciprocal()));
00483 return (*this)[0].multiply(recip);
00484 }
00485
00486 Expr Expr::multiply(const Expr& other) const
00487 {
00488 RCP<ScalarExpr> rtn;
00489 RCP<ScalarExpr> sThis = rcp_dynamic_cast<ScalarExpr>(ptr());
00490 RCP<ScalarExpr> sOther = rcp_dynamic_cast<ScalarExpr>(other.ptr());
00491
00492 TEUCHOS_TEST_FOR_EXCEPTION(sThis.get()==NULL, std::logic_error,
00493 "Expr::multiply(): Left operand " << toString()
00494 << " is a non-scalar expression. All list structure "
00495 "should have been handled before this point");
00496
00497 TEUCHOS_TEST_FOR_EXCEPTION(sOther.get()==NULL, std::logic_error,
00498 "Expr::multiply(): Right operand " << other.toString()
00499 << " is a non-scalar expression. All list structure "
00500 "should have been handled before this point");
00501
00502 static StdProductTransformations trans;
00503
00504 if (trans.doTransform(sThis, sOther, rtn))
00505 {
00506 if (SymbolicTransformation::classVerbosity() > 0)
00507 {
00508 Out::println("Expr::operator*() transformed product\n["
00509 + toString() + "*"
00510 + other.toString() + "]\n to\n ["
00511 + rtn->toString() + "]");
00512 }
00513 return handle(rtn);
00514 }
00515
00516 return new ProductExpr(sThis, sOther);
00517 }
00518
00519 Expr Expr::operator-() const
00520 {
00521 TimeMonitor t(opTimer());
00522 TimeMonitor t1(unaryMinusTimer());
00523 Tabs tabs;
00524
00525 if (this->isComplex())
00526 {
00527 return new ComplexExpr(-real(), -imag());
00528 }
00529
00530
00531 if (this->size()==1)
00532 {
00533
00534 const SpectralExpr* se
00535 = dynamic_cast<const SpectralExpr*>((*this)[0].ptr().get());
00536 if (se != 0)
00537 {
00538 SpectralBasis basis = se->getSpectralBasis();
00539 Array<Expr> coeff(basis.nterms());
00540
00541 for(int i=0; i<basis.nterms(); i++)
00542 {
00543 coeff[i] = - se->getCoeff(i);
00544 }
00545 Expr rtn = new SpectralExpr( basis, coeff);
00546 return rtn;
00547 }
00548
00549
00550 const ConstantExpr* c
00551 = dynamic_cast<const ConstantExpr*>((*this)[0].ptr().get());
00552 const UnaryMinus* u
00553 = dynamic_cast<const UnaryMinus*>((*this)[0].ptr().get());
00554
00555 if (c != 0)
00556 {
00557 if (c->value()==0.0)
00558 {
00559 return new ZeroExpr();
00560 }
00561 else
00562 {
00563 return new ConstantExpr(-1.0 * c->value());
00564 }
00565 }
00566 else if (u != 0)
00567 {
00568 return u->arg();
00569 }
00570 else
00571 {
00572 RCP<ScalarExpr> sThis
00573 = rcp_dynamic_cast<ScalarExpr>((*this)[0].ptr());
00574 TEUCHOS_TEST_FOR_EXCEPTION(sThis.get()==NULL, std::logic_error,
00575 "Expr::operator-(): Operand " << (*this)[0].toString()
00576 << " is a non-scalar expression. All list structure "
00577 "should have been handled before this point");
00578 return new UnaryMinus(sThis);
00579 }
00580 }
00581
00582
00583 Array<Expr> rtn(this->size());
00584 for (int i=0; i<this->size(); i++)
00585 {
00586 rtn[i] = -((*this)[i]);
00587 }
00588 return new ListExpr(rtn);
00589 }
00590
00591
00592 Expr Expr::operator/(const Expr& other) const
00593 {
00594 TimeMonitor t(opTimer());
00595
00596
00597
00598 TEUCHOS_TEST_FOR_EXCEPTION(other.size() != 1,
00599 std::runtime_error,
00600 "Expr::operator/ detected division by a non-scalar "
00601 "expression " << toString());
00602
00603 TEUCHOS_TEST_FOR_EXCEPTION(other.isSpectral(), std::logic_error,
00604 "Division by a Spectral Expr is not yet defined");
00605
00606
00607 if (other.isComplex())
00608 {
00609 Expr magSq = other.real()*other.real() + other.imag()*other.imag();
00610 return (*this) * other.conj() / magSq;
00611 }
00612
00613
00614 if (isComplex() && !other.isComplex())
00615 {
00616 return new ComplexExpr(real()/other, imag()/other);
00617 }
00618
00619
00620 if (isSpectral() && !other.isSpectral() && !other.isComplex())
00621 {
00622 const SpectralExpr* se
00623 = dynamic_cast<const SpectralExpr*>((*this)[0].ptr().get());
00624
00625 SpectralBasis basis = se->getSpectralBasis();
00626 Array<Expr> coeff(basis.nterms());
00627
00628 for(int i=0; i<basis.nterms(); i++)
00629 {
00630 coeff[i] = se->getCoeff(i)/ other[0];
00631 }
00632 Expr rtn = new SpectralExpr( basis, coeff);
00633 return rtn;
00634 }
00635
00636
00637 if (this->size()==1)
00638 {
00639 return (*this)[0].divide(other[0]);
00640 }
00641
00642
00643 Array<Expr> rtn(this->size());
00644 for (int i=0; i<this->size(); i++)
00645 {
00646 rtn[i] = (*this)[i] / other;
00647 }
00648 return new ListExpr(rtn);
00649 }
00650
00651 const Expr& Expr::operator[](int i) const
00652 {
00653 TEUCHOS_TEST_FOR_EXCEPTION(ptr().get()==NULL, std::logic_error,
00654 "null this detected in Expr::operator[].");
00655
00656 TEUCHOS_TEST_FOR_EXCEPTION(i<0 || i>=(int) this->size(), std::runtime_error,
00657 "Expr::operator[]() index i=" << i << " out of range [0, "
00658 << this->size() << " in expr " << toString());
00659
00660 const ListExpr* le = dynamic_cast<const ListExpr*>(ptr().get());
00661
00662 if (le != 0)
00663 {
00664 const Expr& rtn = le->element(i);
00665 TEUCHOS_TEST_FOR_EXCEPTION(rtn.size() == 0, std::logic_error,
00666 "attempt to access an empty list; this should "
00667 "never happen because the case should have been "
00668 "dealt with earlier");
00669 if (rtn.size()==1)
00670 {
00671 TEUCHOS_TEST_FOR_EXCEPTION(rtn[0].ptr().get()==NULL, std::logic_error,
00672 "null return detected in Expr::operator[]. This="
00673 << toString() << ", i=" << i);
00674 return rtn[0];
00675 }
00676 TEUCHOS_TEST_FOR_EXCEPTION(rtn.ptr().get()==NULL, std::logic_error,
00677 "null return detected in Expr::operator[]. This="
00678 << toString() << ", i=" << i);
00679 return rtn;
00680 }
00681
00682 return *this;
00683 }
00684
00685 void Expr::append(const Expr& expr)
00686 {
00687 ListExpr* le = dynamic_cast<ListExpr*>(ptr().get());
00688
00689 if (le != 0)
00690 {
00691 le->append(expr);
00692 return;
00693 }
00694 else
00695 {
00696 if (ptr().get()==0)
00697 {
00698 Array<Expr> e(1);
00699 e[0] = expr;
00700 ptr() = rcp(new ListExpr(e));
00701 }
00702 else
00703 {
00704 Array<Expr> e(2);
00705 e[0] = *this;
00706 e[1] = expr;
00707 ptr() = rcp(new ListExpr(e));
00708 }
00709 }
00710 }
00711
00712 Expr Expr::flatten() const
00713 {
00714 const ListExpr* le = dynamic_cast<const ListExpr*>(ptr().get());
00715
00716 if (le != 0)
00717 {
00718 return le->flatten();
00719 }
00720 return *this;
00721 }
00722
00723 Expr Expr::flattenSpectral() const
00724 {
00725 Array<Expr> rtn(size());
00726 for (int i=0; i<size(); i++)
00727 {
00728 if ((*this)[i].size() == 1)
00729 {
00730 const SpectralExpr* se
00731 = dynamic_cast<const SpectralExpr*>((*this)[i][0].ptr().get());
00732 if (se != 0)
00733 {
00734 int nt = se->getSpectralBasis().nterms();
00735 Array<Expr> e(nt);
00736 for (int j=0; j<nt; j++)
00737 {
00738 e[j] = se->getCoeff(j);
00739 }
00740 rtn[i] = new ListExpr(e);
00741 }
00742 else
00743 {
00744 rtn[i] = (*this)[i];
00745 }
00746 }
00747 else
00748 {
00749 rtn[i] = (*this)[i].flattenSpectral();
00750 }
00751 }
00752 Expr r = new ListExpr(rtn);
00753 return r.flatten();
00754 }
00755
00756 int Expr::size() const
00757 {
00758 if (ptr().get()==0) return 0;
00759
00760 const ListExpr* le = dynamic_cast<const ListExpr*>(ptr().get());
00761
00762 if (le != 0)
00763 {
00764 return le->size();
00765 }
00766 return 1;
00767 }
00768
00769 int Expr::totalSize() const
00770 {
00771 if (ptr().get()==0) return 0;
00772
00773 const ListExpr* le = dynamic_cast<const ListExpr*>(ptr().get());
00774
00775 if (le != 0)
00776 {
00777 return le->totalSize();
00778 }
00779 return 1;
00780 }
00781
00782 Expr Expr::real() const
00783 {
00784 if (isComplex())
00785 {
00786 const ComplexExpr* cx = dynamic_cast<const ComplexExpr*>(ptr().get());
00787 return cx->real();
00788 }
00789 else if (size() > 1)
00790 {
00791 Array<Expr> rtn(size());
00792 for (int i=0; i<size(); i++)
00793 {
00794 rtn[i] = (*this)[i].real();
00795 }
00796 return new ListExpr(rtn);
00797 }
00798 else
00799 {
00800 return *this;
00801 }
00802 }
00803
00804 Expr Expr::imag() const
00805 {
00806 if (isComplex())
00807 {
00808 const ComplexExpr* cx = dynamic_cast<const ComplexExpr*>(ptr().get());
00809 return cx->imag();
00810 }
00811 else if (size() > 1)
00812 {
00813 Array<Expr> rtn(size());
00814 for (int i=0; i<size(); i++)
00815 {
00816 rtn[i] = (*this)[i].imag();
00817 }
00818 return new ListExpr(rtn);
00819 }
00820 else
00821 {
00822 return 0.0;
00823 }
00824
00825 }
00826
00827 Expr Expr::conj() const
00828 {
00829 if (size()==1)
00830 {
00831 if (isComplex())
00832 {
00833 return new ComplexExpr(real(), -imag());
00834 }
00835 else return real();
00836 }
00837 else
00838 {
00839 Array<Expr> rtn(size());
00840 for (int i=0; i<size(); i++)
00841 {
00842 rtn[i] = (*this)[i].conj();
00843 }
00844 return new ListExpr(rtn);
00845 }
00846 }
00847
00848 void Expr::setParameterValue(const double& value)
00849 {
00850 Parameter* pe = dynamic_cast<Parameter*>(ptr().get());
00851 TEUCHOS_TEST_FOR_EXCEPTION(pe==0, std::runtime_error,
00852 "Expr " << *this << " is not a Parameter expr, and "
00853 "so setParameterValue() should not be called");
00854 pe->setValue(value);
00855 }
00856
00857 double Expr::getParameterValue() const
00858 {
00859 const Parameter* pe = dynamic_cast<const Parameter*>(ptr().get());
00860 TEUCHOS_TEST_FOR_EXCEPTION(pe==0, std::runtime_error,
00861 "Expr " << *this << " is not a Parameter expr, and "
00862 "so getParameterValue() should not be called");
00863 return pe->value();
00864 }
00865
00866
00867 bool Expr::isIndependentOf(const Expr& u) const
00868 {
00869 TEUCHOS_TEST_FOR_EXCEPTION(ptr().get()==0, std::runtime_error,
00870 "function called on null expression");
00871
00872 return scalarExpr()->isIndependentOf(u);
00873 }
00874
00875
00876 bool Expr::isLinearForm(const Expr& u) const
00877 {
00878 TEUCHOS_TEST_FOR_EXCEPTION(ptr().get()==0, std::runtime_error,
00879 "function called on null expression");
00880
00881 return scalarExpr()->isLinearForm(u);
00882 }
00883
00884
00885
00886 bool Expr::isQuadraticForm(const Expr& u) const
00887 {
00888 TEUCHOS_TEST_FOR_EXCEPTION(ptr().get()==0, std::runtime_error,
00889 "function called on null expression");
00890
00891 return scalarExpr()->isQuadraticForm(u);
00892 }
00893
00894
00895
00896 bool Expr::isLinearInTests() const
00897 {
00898 TEUCHOS_TEST_FOR_EXCEPTION(ptr().get()==0, std::runtime_error,
00899 "function called on null expression");
00900
00901 return scalarExpr()->isLinearInTests();
00902 }
00903
00904
00905 bool Expr::hasTestFunctions() const
00906 {
00907 TEUCHOS_TEST_FOR_EXCEPTION(ptr().get()==0, std::runtime_error,
00908 "function called on null expression");
00909
00910 return scalarExpr()->hasTestFunctions();
00911 }
00912
00913
00914 bool Expr::everyTermHasTestFunctions() const
00915 {
00916 TEUCHOS_TEST_FOR_EXCEPTION(ptr().get()==0, std::runtime_error,
00917 "function called on null expression");
00918
00919 return scalarExpr()->everyTermHasTestFunctions();
00920 }
00921
00922 bool Expr::isTestElement() const
00923 {
00924 const TestFuncElement* uPtr
00925 = dynamic_cast<const TestFuncElement*>(ptr().get());
00926 return uPtr != 0;
00927 }
00928
00929
00930 bool Expr::isUnknownElement() const
00931 {
00932 const UnknownFuncElement* uPtr
00933 = dynamic_cast<const UnknownFuncElement*>(ptr().get());
00934 return uPtr != 0;
00935 }
00936
00937
00938 void Expr::getUnknowns(Set<int>& unkID,
00939 Array<Expr>& unks) const
00940 {
00941 TEUCHOS_TEST_FOR_EXCEPTION(ptr().get()==0, std::runtime_error,
00942 "function called on null expression");
00943
00944 const UnknownFuncElement* u
00945 = dynamic_cast<const UnknownFuncElement*>(ptr().get());
00946
00947 if (u != 0)
00948 {
00949 if (!unkID.contains(u->fid().dofID()))
00950 {
00951 unks.append(*this);
00952 unkID.put(u->fid().dofID());
00953 }
00954 }
00955 else
00956 {
00957 scalarExpr()->getUnknowns(unkID, unks);
00958 }
00959 }
00960
00961
00962 void Expr::getTests(Set<int>& varID, Array<Expr>& vars) const
00963 {
00964 TEUCHOS_TEST_FOR_EXCEPTION(ptr().get()==0, std::runtime_error,
00965 "function called on null expression");
00966
00967 const TestFuncElement* u
00968 = dynamic_cast<const TestFuncElement*>(ptr().get());
00969
00970 if (u != 0)
00971 {
00972 if (!varID.contains(u->fid().dofID()))
00973 {
00974 vars.append(*this);
00975 varID.put(u->fid().dofID());
00976 }
00977 }
00978 else
00979 {
00980 scalarExpr()->getTests(varID, vars);
00981 }
00982 }
00983
00984
00985 const ScalarExpr* Expr::scalarExpr() const
00986 {
00987 const ScalarExpr* se = dynamic_cast<const ScalarExpr*>(ptr().get());
00988 TEUCHOS_TEST_FOR_EXCEPTION(se==0, std::logic_error, "ScalarExpr expected here");
00989 return se;
00990 }
00991
00992 const FuncElementBase* Expr::funcElement() const
00993 {
00994 const FuncElementBase* fe
00995 = dynamic_cast<const FuncElementBase*>(ptr().get());
00996 return fe;
00997 }
00998
00999
01000
01001
01002 namespace Sundance
01003 {
01004 using namespace Sundance;
01005
01006 Expr Complex(const Expr& re, const Expr& im)
01007 {
01008 TEUCHOS_TEST_FOR_EXCEPTION(re.size() != im.size(), std::runtime_error,
01009 "arguments mismatched in Complex(). Real part="
01010 << re << ", imaginary part=" << im);
01011
01012 TEUCHOS_TEST_FOR_EXCEPTION(re.isComplex() || im.isComplex(), std::runtime_error,
01013 "recursively defined complex number. Real part="
01014 << re << ", imaginary part=" << im);
01015
01016 if (re.totalSize() > 1)
01017 {
01018 Array<Expr> rtn(re.size());
01019 for (int i=0; i<re.size(); i++)
01020 {
01021 rtn[i] = Complex(re[i], im[i]);
01022 }
01023 return new ListExpr(rtn);
01024 }
01025
01026 const ZeroExpr* zr = dynamic_cast<const ZeroExpr*>(re[0].ptr().get());
01027 const ZeroExpr* zi = dynamic_cast<const ZeroExpr*>(im[0].ptr().get());
01028
01029 if (zr == 0)
01030 {
01031 if (zi==0)
01032 {
01033 return new ComplexExpr(re, im);
01034 }
01035 else
01036 {
01037 return re;
01038 }
01039 }
01040 else
01041 {
01042 if (zi != 0)
01043 {
01044 return Expr(0.0);
01045 }
01046 else
01047 {
01048 return new ComplexExpr(0.0, im);
01049 }
01050 }
01051 return new ComplexExpr(re, im);
01052 }
01053
01054 Expr List(const Expr& a)
01055 {
01056 return new ListExpr(tuple(a));
01057 }
01058
01059 Expr List(const Expr& a, const Expr& b)
01060 {
01061 return new ListExpr(tuple(a,b));
01062 }
01063
01064 Expr List(const Expr& a, const Expr& b, const Expr& c)
01065 {
01066 return new ListExpr(tuple(a,b,c));
01067 }
01068
01069 Expr List(const Expr& a, const Expr& b, const Expr& c,
01070 const Expr& d)
01071 {
01072 return new ListExpr(tuple(a,b,c,d));
01073 }
01074
01075 Expr List(const Expr& a, const Expr& b, const Expr& c,
01076 const Expr& d, const Expr& e)
01077 {
01078 return new ListExpr(tuple(a,b,c,d,e));
01079 }
01080
01081 Expr List(const Expr& a, const Expr& b, const Expr& c,
01082 const Expr& d, const Expr& e, const Expr& f)
01083 {
01084 return new ListExpr(tuple(a,b,c,d,e,f));
01085 }
01086
01087 Expr List(const Expr& a, const Expr& b, const Expr& c,
01088 const Expr& d, const Expr& e, const Expr& f,
01089 const Expr& g)
01090 {
01091 return new ListExpr(tuple(a,b,c,d,e,f,g));
01092 }
01093
01094 Expr List(const Expr& a, const Expr& b, const Expr& c,
01095 const Expr& d, const Expr& e, const Expr& f,
01096 const Expr& g, const Expr& h)
01097 {
01098 return new ListExpr(tuple(a,b,c,d,e,f,g,h));
01099 }
01100
01101
01102 }
01103