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