00001 #pragma once
00002
00003 #include <iostream>
00004 #include <memory>
00005 #include "stdio.h"
00006 #include "basics.hh"
00007 #include "formula/elementFormulaRCP.hh"
00008 #include "formula/formula.hh"
00009 #include "geometry/formula.hh"
00010 #include "hp2D.hh"
00011
00012
00013
00014 #define pmlHolger_D 0
00015
00016 namespace concepts {
00017
00018
00019
00022 class FormulaExpImag1D : public concepts::Formula<Cmplx> {
00023 public:
00024 FormulaExpImag1D(const Real k, const Cmplx u = 1.0, Real x0 = 0.0)
00025 : k_(k), x0_(x0), u_(u) {}
00026
00027 virtual FormulaExpImag1D* clone() const {
00028 return new FormulaExpImag1D(k_, u_, x0_);
00029 }
00030
00031 virtual Cmplx operator() (const Real p, const Real t = 0.0) const {
00032 const Real arg = k_*(p-x0_);
00033 return Cmplx(cos(arg), sin(arg)) * u_;
00034 }
00035 virtual Cmplx operator() (const concepts::Real2d& p, const Real t = 0.0) const {
00036 return (*this)(p[0], t);
00037 }
00038 virtual Cmplx operator() (const concepts::Real3d& p, const Real t = 0.0) const {
00039 return (*this)(p[0], t);
00040 }
00041 protected:
00042 virtual std::ostream& info(std::ostream& os) const {
00043 return os << "FormulaExpImag1D(" << u_ << " * exp(i " << k_ << "(x - " << x0_ << ")))";
00044 }
00045 private:
00046 const Real k_, x0_;
00047 const Cmplx u_;
00048 };
00049
00050
00051
00054 class FormulaExpImag2D : public concepts::Formula<Cmplx> {
00055 public:
00056 FormulaExpImag2D(const Real2d k, const Cmplx u = 1.0, Real2d x0 = 0.0)
00057 : k(k), x0(x0), u(u) {}
00058
00059 virtual FormulaExpImag2D* clone() const {
00060 return new FormulaExpImag2D(k, u, x0);
00061 }
00062
00063 virtual Cmplx operator() (const Real p, const Real t = 0.0) const {
00064 conceptsThrowSimpleE("FormulaExpImag2D currently only supports 2D!"); assert(false);
00065 }
00066
00067 virtual Cmplx operator() (const concepts::Real2d& p, const Real t = 0.0) const
00068 {
00069 const Real arg = k[0]*(p[0]-x0[0])
00070 + k[1]*(p[1]-x0[1]) ;
00071
00072 return Cmplx(cos(arg), sin(arg)) * u;
00073 }
00074
00075 virtual Cmplx operator() (const concepts::Real3d& p, const Real t = 0.0) const {
00076 return (*this)( Real2d(p[0], p[1]), t);
00077 }
00078 protected:
00079 virtual std::ostream& info(std::ostream& os) const {
00080 return os << "FormulaExpImag2D(" << u << " * exp(i " << k << "(x - " << x0 << ")))";
00081 }
00082 public:
00083 const Real2d k, x0;
00084 const Cmplx u;
00085 };
00086
00087
00088
00091 class FormulaExpImag2DRadialDer : public concepts::Formula<Cmplx> {
00092 public:
00093
00094 FormulaExpImag2DRadialDer(const Real2d k, const Cmplx u = 1.0)
00095 : k(k), x0(0,0), u(u) {}
00096
00097 virtual FormulaExpImag2DRadialDer* clone() const {
00098 return new FormulaExpImag2DRadialDer(*this);
00099 }
00100
00101 virtual Cmplx operator() (const Real p, const Real t = 0.0) const {
00102 conceptsThrowSimpleE("FormulaExpImag2DRadialDer currently only supports 2D!"); assert(false);
00103 }
00104
00105 virtual Cmplx operator() (const concepts::Real2d& p, const Real t = 0.0) const
00106 {
00107 const Cmplx imag(0,1);
00108
00109 const Real arg = k[0]*(p[0]-x0[0])
00110 + k[1]*(p[1]-x0[1]) ;
00111 Cmplx val(cos(arg), sin(arg));
00112 val *= u;
00113
00114 const Real len = sqrt( p[0]*p[0] + p[1]*p[1] );
00115
00116 return Cmplx(0, (k[0]*p[0] + k[1]*p[1])/len) * val;
00117 }
00118
00119 virtual Cmplx operator() (const concepts::Real3d& p, const Real t = 0.0) const {
00120 return (*this)( Real2d(p[0], p[1]), t);
00121 }
00122 protected:
00123 virtual std::ostream& info(std::ostream& os) const {
00124 return os << "FormulaExpImag2DRadialDer(" << u << " * exp(i " << k << "(x - " << x0 << ")))";
00125 }
00126 public:
00127 const Real2d k, x0;
00128 const Cmplx u;
00129 };
00130
00131
00132
00136 class FormulaExpImag2DGrad : public concepts::Formula< concepts::Point<Cmplx, 2> >
00137 {
00138 public:
00139 FormulaExpImag2DGrad(const Real2d k, const Cmplx u = 1.0, Real2d x0 = Real2d(0,0))
00140 : k(k), x0(x0), u(u)
00141 { }
00142
00143 virtual FormulaExpImag2DGrad* clone() const {
00144 return new FormulaExpImag2DGrad(k, u, x0);
00145 }
00146
00147 virtual Cmplx2d operator() (const Real p, const Real t = 0.0) const {
00148 conceptsThrowSimpleE("FormulaExpImag2DGrad currently only supports 2D!"); assert(false);
00149 }
00150
00151 virtual Cmplx2d operator() (const concepts::Real2d& p, const Real t = 0.0) const
00152 {
00153 const Cmplx imag(0,1);
00154
00155 const Real arg = k[0]*(p[0]-x0[0])
00156 + k[1]*(p[1]-x0[1]) ;
00157 Cmplx val(cos(arg), sin(arg));
00158 val *= u;
00159
00160
00161
00162 return Cmplx2d( Cmplx(0, k[0])*val, Cmplx(0, k[1])*val );
00163 }
00164
00165 virtual Cmplx2d operator() (const concepts::Real3d& p, const Real t = 0.0) const {
00166
00167 return (*this)( Real2d(p[0], p[1]), t);
00168 }
00169 protected:
00170 virtual std::ostream& info(std::ostream& os) const {
00171 return os << "FormulaExpImag2DGrad(" << u << " * exp(i " << k << "(x - " << x0 << ")))";
00172 }
00173 public:
00174 const Real2d k, x0;
00175 const Cmplx u;
00176 };
00177
00178
00179
00180
00193 template< class F >
00194 class FormulaNormalOuterSP2D : public concepts::ElementFormula< F >
00195 {
00196 public:
00197 static const bool OUTER = true;
00198 static const bool INNER = false;
00199
00200 FormulaNormalOuterSP2D(
00201 const ElementFormulaContainer< concepts::Point<F, 2> > vf,
00202 Real2d center = Real2d(0,0), bool direction = OUTER)
00203 : vf(vf)
00204 , center(center)
00205 , direction(direction)
00206 { }
00207
00208 virtual FormulaNormalOuterSP2D* clone() const {
00209 return new FormulaNormalOuterSP2D(*this);
00210 }
00211
00212 virtual F operator() (const concepts::ElementWithCell<Real>& elm,
00213 const Real p, const Real t = 0.0) const
00214 {
00215 const concepts::Cell& c = elm.cell();
00216
00217 const Edge2d* cc = dynamic_cast<const concepts::Edge2d*> (&c);
00218 assert(cc);
00219
00220 Real2d normal = cc->jacobian(p);
00221 normal.ortho();
00222 normal /= normal.l2();
00223
00224 Real2d pp = elm.elemMap(p);
00225 pp -= center;
00226
00227 if ( ( normal.dot(pp) < 0 && direction == OUTER ) ||
00228 ( normal.dot(pp) > 0 && direction == INNER )
00229 )
00230 {
00231 normal *= -1;
00232 }
00233
00234 const concepts::Point<F, 2> u = vf.operator()(elm, p, t);
00235
00236
00237
00238
00239 return normal[0] * u[0] + normal[1] * u[1];
00240 }
00241
00242 virtual F operator() (const concepts::ElementWithCell<Real>& elm,
00243 const concepts::Real2d& p, const Real t = 0.0) const
00244 {
00245 conceptsThrowSimpleE("FormulaNormalOuterSP2D currently only supports 1D!"); assert(false);
00246 }
00247
00248 virtual F operator() (const concepts::ElementWithCell<Real>& elm,
00249 const concepts::Real3d& p, const Real t = 0.0) const {
00250 conceptsThrowSimpleE("FormulaNormalOuterSP2D currently only supports 1D!"); assert(false);
00251
00252 }
00253 protected:
00254 virtual std::ostream& info(std::ostream& os) const {
00255 return os << "FormulaNormalOuterSP2D(" << vf << ", " << center << ", " << direction << ")";
00256 }
00257 public:
00258 const ElementFormulaContainer< concepts::Point<F, 2> > vf;
00259 Real2d center;
00260 bool direction;
00261 };
00262
00263
00264
00268 template< class F, uint DIM, typename G = typename Realtype<F>::type>
00269 class ComposeFormulaMatVec : public concepts::ElementFormula< concepts::Point<F, DIM>, G >
00270 {
00271 public:
00272 ComposeFormulaMatVec(
00273 RCP<const ElementFormula< concepts::Mapping<F, DIM>, G> > A,
00274 RCP<const ElementFormula< concepts::Point<F, DIM> , G> > vf
00275 )
00276 : A(A)
00277 , vf(vf)
00278 { }
00279
00280 virtual ComposeFormulaMatVec* clone() const {
00281 return new ComposeFormulaMatVec(*this);
00282 }
00283
00284 virtual concepts::Point<F, DIM> operator() (const concepts::ElementWithCell<G>& elm,
00285 const Real p, const Real t = 0.0) const
00286 {
00287 return A->operator()(elm, p, t) * vf->operator()(elm, p, t);
00288 }
00289
00290 virtual concepts::Point<F, DIM> operator() (const concepts::ElementWithCell<G>& elm,
00291 const concepts::Real2d& p, const Real t = 0.0) const
00292 {
00293
00294
00295 return A->operator()(elm, p, t) * vf->operator()(elm, p, t);
00296 }
00297
00298 virtual concepts::Point<F, DIM> operator() (const concepts::ElementWithCell<G>& elm,
00299 const concepts::Real3d& p, const Real t = 0.0) const
00300 {
00301 return A->operator()(elm, p, t) * vf->operator()(elm, p, t);
00302 }
00303 protected:
00304 virtual std::ostream& info(std::ostream& os) const {
00305 return os << "ComposeFormulaMatVec(A=" << *A << ", vf="<< *vf << ")";
00306 }
00307 public:
00308 RCP<const ElementFormula< concepts::Mapping<F, DIM>, G> > A;
00309 RCP<const ElementFormula< concepts::Point<F, DIM>, G> > vf;
00310 };
00311
00312
00313
00314 template< class F, uint DIM, typename G = typename Realtype<F>::type>
00315 class ComposeFormulaVecEntry : public concepts::ElementFormula< F, G >
00316 {
00317 public:
00318 ComposeFormulaVecEntry(
00319 RCP<const ElementFormula< concepts::Point<F, DIM> , G> > vf,
00320 int index
00321 )
00322 : vf(vf)
00323 , index(index)
00324 { }
00325
00326 virtual ComposeFormulaVecEntry* clone() const {
00327 return new ComposeFormulaVecEntry(*this);
00328 }
00329
00330 virtual F operator() (const concepts::ElementWithCell<G>& elm,
00331 const Real p, const Real t = 0.0) const
00332 {
00333 return vf->operator()(elm, p, t)[index];
00334 }
00335
00336 virtual F operator() (const concepts::ElementWithCell<G>& elm,
00337 const concepts::Real2d& p, const Real t = 0.0) const
00338 {
00339 return vf->operator()(elm, p, t)[index];
00340 }
00341
00342 virtual F operator() (const concepts::ElementWithCell<G>& elm,
00343 const concepts::Real3d& p, const Real t = 0.0) const
00344 {
00345 return vf->operator()(elm, p, t)[index];
00346 }
00347 protected:
00348 virtual std::ostream& info(std::ostream& os) const {
00349 return os << "ComposeFormulaVecEntry(i=" << index << ", vf="<< *vf << ")";
00350 }
00351 public:
00352 RCP<const ElementFormula< concepts::Point<F, DIM>, G> > vf;
00353 int index;
00354 };
00355
00356
00357
00358 class FormulaIncPlaneWaveSource : public ElementFormula<Cmplx> {
00359 public:
00360 typedef std::map<int, double> MID;
00361
00362 FormulaIncPlaneWaveSource(ElementFormulaContainer<Cmplx> coeff_a
00363 , ElementFormulaContainer<Cmplx> coeff_b
00364
00365
00366 , RCP< concepts::FormulaExpImag2D > u_inc )
00367 : coeff_a(coeff_a)
00368 , coeff_b(coeff_b)
00369 , u_inc(u_inc)
00370 { }
00371
00372 virtual FormulaIncPlaneWaveSource* clone() const {
00373 return new FormulaIncPlaneWaveSource(*this);
00374 }
00375
00376 virtual Cmplx operator() (const ElementWithCell< Real > &elm, const Real3d &p, const Real t=0.0) const
00377 {
00378 Real2d px = elm.elemMap(p);
00379 return operator()(elm, p, px, t);
00380 }
00381
00382 virtual Cmplx operator() (const ElementWithCell< Real > &elm, const Real2d &p, const Real t=0.0) const
00383 {
00384 Real2d px = elm.elemMap(p);
00385 return operator()(elm, p, px, t);
00386 }
00387
00388 virtual Cmplx operator() (const ElementWithCell< Real > &elm, const Real p, const Real t=0.0) const
00389 {
00390 Real2d px = elm.elemMap(p);
00391 return operator()(elm, p, px, t);
00392 }
00393
00394 template <class RealNd>
00395 Cmplx operator() (const ElementWithCell< Real > &elm, const RealNd &p, Real2d px,
00396 const Real t=0.0) const
00397 {
00398 Real2d k = u_inc->k;
00399 Cmplx k2 = k[0]*k[0] + k[1]*k[1];
00400
00401 Cmplx a = coeff_a(elm, p);
00402 Cmplx b = coeff_b(elm, p);
00403
00404 if (a.real() != 1. || b.real() != 1.) {
00405 DEBUGL(pmlHolger_D, "a , b= " << a << ", " << b);
00406 DEBUGL(pmlHolger_D, "elemFrm value = " <<
00407 (b - a) * k2 * u_inc->operator()(elm.elemMap(p), t));
00408 } else {
00409
00410 }
00411
00412
00413 return (b - a) * k2 * u_inc->operator()(elm.elemMap(p), t);
00414
00415 }
00416
00417 static PiecewiseConstFormula<Cmplx> genTMCoeff(
00418 const MID& attToEps);
00419
00420 static PiecewiseConstFormula<Cmplx> genTECoeff(
00421 const MID& attToEps);
00422
00423 protected:
00424 virtual std::ostream& info(std::ostream& os) const {
00425 return os << "FormulaIncPlaneWaveSource(" << coeff_a << ", " << coeff_b << ")";
00426 }
00427 private:
00428 concepts::ElementFormulaContainer<Cmplx> coeff_a, coeff_b;
00429
00430
00431 RCP< concepts::FormulaExpImag2D > u_inc;
00432 };
00433
00434 PiecewiseConstFormula<Cmplx> FormulaIncPlaneWaveSource::genTMCoeff(
00435 const MID& attrToEps)
00436 {
00437 PiecewiseConstFormula<Cmplx> coeffs(1.);
00438 for(MID::const_iterator it = attrToEps.begin();
00439 it != attrToEps.end(); ++it)
00440 {
00441 coeffs[it->first] = it->second;
00442
00443 if(it->second < 0) {
00444 double abs_fact = 1e-2;
00445 printf("Adding absorbing material (%f %f) for attr %d\n",
00446 -it->second, abs_fact, it->first);
00447 coeffs[it->first] = -it->second;
00448 imag(coeffs[it->first]) = abs_fact;
00449 } else {
00450 printf("Adding non-absorbing material (%f %f) for attr %d\n",
00451 it->second, 0., it->first);
00452 }
00453 }
00454 return coeffs;
00455 }
00456
00457 PiecewiseConstFormula<Cmplx> FormulaIncPlaneWaveSource::genTECoeff(
00458 const MID& attrToEps)
00459 {
00460 PiecewiseConstFormula<Cmplx> coeffs(1.);
00461 for(MID::const_iterator it = attrToEps.begin();
00462 it != attrToEps.end(); ++it)
00463 {
00464 coeffs[it->first] = 1. / it->second;
00465
00466 if(it->second < 0) {
00467 coeffs[it->first] = -it->second;
00468 imag(coeffs[it->first]) = 1e-3;
00469 }
00470 }
00471 return coeffs;
00472 }
00473
00474
00475
00476 template<typename F=Real>
00477 class FormulaPMLPowerSigma : public concepts::Formula<F> {
00478 public:
00479 FormulaPMLPowerSigma(const Real offset, const int power=2
00480 , const F sigma0 = 5.0, const Real center=0)
00481 : offset(offset)
00482 , center(center)
00483 , power(power)
00484 , sigma0(sigma0)
00485 {}
00486
00487 virtual FormulaPMLPowerSigma* clone() const {
00488 return new FormulaPMLPowerSigma(offset, power, sigma0, center);
00489 }
00490
00491 bool inPMLregion(const concepts::Real p, const Real t = 0.0)
00492 {
00493 Real arg = fabs(p - center) - offset;
00494
00495 return arg >= 0;
00496 }
00497
00498 virtual F operator() (const Real p, const Real t = 0.0) const {
00499 Real arg = fabs(p - center) - offset;
00500
00501 if (arg < 0)
00502 return F(0);
00503 return sigma0 * powi(arg , power);
00504 }
00505
00506 virtual F operator() (const concepts::Real2d& p, const Real t = 0.0) const {
00507 return (*this)(p[0], t);
00508 }
00509
00510 virtual F operator() (const concepts::Real3d& p, const Real t = 0.0) const {
00511 return (*this)(p[0], t);
00512 }
00513 template<typename Real>
00514 static inline Real powi(Real x, int power) {
00515 #if 1
00516 Real res(1);
00517 for(int i = 0; i < power; ++i) {
00518 res *= x;
00519 }
00520 return res;
00521 #else
00522 return pow(x, power);
00523 #endif
00524 }
00525 protected:
00526 virtual std::ostream& info(std::ostream& os) const {
00527 return os << "FormulaPMLPowerSigma(" << sigma0 << " * ( |x - (" << center
00528 << ")| - " << offset << ")_+^" << power << ")))";
00529 }
00530 private:
00531 const Real offset;
00532 const Real center;
00533 const int power;
00534 const F sigma0;
00535 };
00536
00537
00538
00539 template<typename F=Real>
00540 class FormulaPMLPowerSigma2D : public concepts::Formula<F> {
00541 public:
00542 FormulaPMLPowerSigma2D(const Real offset, const int power=2,
00543 const F sigma0 = 5.0, const Real2d& center=Real2d(0,0))
00544 : offset(offset), center(center), power(power), sigma0(sigma0) {}
00545
00546 virtual FormulaPMLPowerSigma2D* clone() const {
00547 return new FormulaPMLPowerSigma2D(offset, power, sigma0, center);
00548 }
00549
00550 virtual F operator() (const Real p, const Real t = 0.0) const {
00551 conceptsThrowSimpleE("FormulaPMLPowerSigma2D currently only supports 2D!"); assert(false);
00552 }
00553
00554 bool inPMLregion(const concepts::Real2d& p, const Real t = 0.0)
00555 {
00556 Real arg = sqrt((p[0]-center[0])*(p[0]-center[0]) +
00557 (p[1]-center[1])*(p[1]-center[1])) -offset;
00558
00559 return arg >= 0;
00560 }
00561
00562 virtual F operator() (const concepts::Real2d& p, const Real t = 0.0) const {
00563 Real arg = sqrt((p[0]-center[0])*(p[0]-center[0]) +
00564 (p[1]-center[1])*(p[1]-center[1])) - offset;
00565 if (arg<0)
00566 return F(0);
00567 return sigma0 * powi(arg,power);
00568 }
00569
00570 virtual F operator() (const concepts::Real3d& p, const Real t = 0.0) const {
00571 return (*this)( Real2d(p[0], p[1]), t);
00572 }
00573
00574 template<typename Real>
00575 static inline Real powi(Real x, int power) {
00576 #if 1
00577 Real res(1);
00578 for (int i = 0; i < power; ++i) {
00579 res *= x;
00580 }
00581 return res;
00582 #else
00583 return pow(x, power);
00584 #endif
00585 }
00586 protected:
00587 virtual std::ostream& info(std::ostream& os) const{
00588 return os << "FormulaPMLPowerSigma2D(" << sigma0 << " * ( |x - (" << center[0]
00589 << "," << center[1] << ")| - " << offset << ")_+^" << power << ")))";
00590 }
00591 private:
00592 const Real offset;
00593 const Real2d& center;
00594 const int power;
00595 const F sigma0;
00596 };
00597
00598
00599
00600
00601
00602 template<typename F=Real>
00603 class FormulaPMLPowerSigmaB2D : public concepts::Formula<F> {
00604 public:
00605 FormulaPMLPowerSigmaB2D(const Real offset, const int power=2,
00606 const F sigma0 = 5.0, const Real2d& center=Real2d(0,0))
00607 : offset(offset), center(center), power(power), sigma0(sigma0) {}
00608
00609 virtual FormulaPMLPowerSigmaB2D* clone() const {
00610 return new FormulaPMLPowerSigmaB2D(offset, power, sigma0, center);
00611 }
00612
00613 virtual F operator() (const Real p, const Real t = 0.0) const {
00614 conceptsThrowSimpleE("FormulaPMLPowerSigma Bar 2D currently only supports 2D!"); assert(false);
00615 }
00616
00617 bool inPMLregion(const concepts::Real2d& p, const Real t = 0.0)
00618 {
00619 Real arg = sqrt((p[0]-center[0])*(p[0]-center[0]) +
00620 (p[1]-center[1])*(p[1]-center[1])) -offset;
00621
00622 return arg >= 0;
00623 }
00624
00625 virtual F operator() (const concepts::Real2d& p, const Real t = 0.0) const {
00626 Real rho = sqrt((p[0]-center[0])*(p[0]-center[0]) + (p[1]-center[1])*(p[1]-center[1]));
00627 Real arg = rho - offset;
00628 if (arg<0)
00629 return F(0);
00630 return sigma0 * powi( arg , power + 1) / (rho) / (power + 1);
00631 }
00632
00633 virtual F operator() (const concepts::Real3d& p, const Real t = 0.0) const {
00634 return (*this)( Real2d(p[0], p[1]), t);
00635 }
00636
00637 template<typename Real>
00638 static inline Real powi(Real x, int power) {
00639 #if 1
00640 Real res(1);
00641 for (int i = 0; i < power; ++i) {
00642 res *= x;
00643 }
00644 return res;
00645 #else
00646 return pow(x, power);
00647 #endif
00648 }
00649 protected:
00650 virtual std::ostream& info(std::ostream& os) const{
00651 return os << "FormulaPMLPowerSigma2D(" << sigma0 << " * ( |x - (" << center[0]
00652 << "," << center[1] << ")| - " << offset << ")_+^" << power << ")))";
00653 }
00654 private:
00655 const Real offset;
00656 const Real2d& center;
00657 const int power;
00658 const F sigma0;
00659 };
00660
00661
00662
00663 class FormulaPMLCart : public ElementFormula<Cmplx> {
00664 public:
00665 enum PMLMode { DXDX, DYDY, IDENT, DX, DY };
00666
00667 FormulaPMLCart(RCP<const ElementFormula<Cmplx> > coeff_a
00668 , RCP<const ElementFormula<Cmplx> > coeff_b
00669 , RCP<concepts::Formula<Real> > sigma_x
00670 , RCP<concepts::Formula<Real> > sigma_y
00671 , PMLMode mode
00672 , double omega
00673 )
00674 : coeff_a(coeff_a)
00675 , coeff_b(coeff_b)
00676 , sigma_x(sigma_x)
00677 , sigma_y(sigma_y)
00678 , mode(mode)
00679 , omega(omega)
00680 {}
00681
00682 virtual FormulaPMLCart* clone() const {
00683 std::cout << "FormulaPMLCart::clone() called " << *this << std::endl;
00684 return new FormulaPMLCart(*this);
00685 }
00686
00687 virtual Cmplx operator() (const ElementWithCell< Real > &elm, const Real3d &p, const Real t=0.0) const
00688 {
00689 Real2d px = elm.elemMap(p);
00690 return operator()(elm, p, px, t);
00691 }
00692 virtual Cmplx operator() (const ElementWithCell< Real > &elm, const Real2d &p, const Real t=0.0) const
00693 {
00694 Real2d px = elm.elemMap(p);
00695 return operator()(elm, p, px, t);
00696 }
00697 virtual Cmplx operator() (const ElementWithCell< Real > &elm, const Real p, const Real t=0.0) const
00698 {
00699 Real2d px = elm.elemMap(p);
00700 return operator()(elm, p, px, t);
00701 }
00702
00703 Cmplx gammaX(Real x) const {
00704 return Cmplx(1, (*sigma_x)(x) / omega);
00705 }
00706
00707 Cmplx gammaY(Real y) const {
00708
00709
00710 return Cmplx(1, (*sigma_y)(y) / omega);
00711 }
00712
00713 template <class RealNd>
00714 inline Cmplx operator() (const ElementWithCell< Real > &elm, const RealNd &p, Real2d px,
00715 const Real t=0.0) const
00716 {
00717 switch(mode) {
00718 case DXDX: return gammaY(px[1]) / gammaX(px[0]) * (*coeff_a)(elm, p);
00719 case DX: return gammaY(px[1]) * (*coeff_a)(elm, p);
00720 case DYDY: return gammaX(px[0]) / gammaY(px[1]) * (*coeff_a)(elm, p);
00721 case DY: return gammaX(px[0]) * (*coeff_a)(elm, p);
00722 case IDENT: return gammaX(px[0]) * gammaY(px[1]) * (*coeff_b)(elm, p);
00723 }
00724 conceptsThrowSimpleE("FormulaPMLCart has gone mad!"); assert(false);
00725 }
00726
00727
00728 protected:
00729 virtual std::ostream& info(std::ostream& os) const {
00730 return os << "FormulaPMLCart(coeffs: "
00731 << *coeff_a << ", " << *coeff_b << ", sigmas:"
00732 << *sigma_x << ", " << *sigma_y
00733 << ")";
00734 }
00735 private:
00736 RCP<const concepts::ElementFormula<Cmplx> > coeff_a;
00737 RCP<const concepts::ElementFormula<Cmplx> > coeff_b;
00738 RCP<concepts::Formula<Real> > sigma_x;
00739 RCP<concepts::Formula<Real> > sigma_y;
00740 PMLMode mode;
00741 double omega;
00742 };
00743
00744
00745
00746 template <class F, typename G = typename Realtype<F>::type>
00747 class FormulaPMLBoxRestriction : public ElementFormula<F, G> {
00748 public:
00749 FormulaPMLBoxRestriction(
00750 RCP<concepts::FormulaPMLPowerSigma<Real> > sigma_x
00751 , RCP<concepts::FormulaPMLPowerSigma<Real> > sigma_y
00752 , RCP<concepts::ElementFormula<F, G> > formula
00753 )
00754 : sigma_x(sigma_x)
00755 , sigma_y(sigma_y)
00756 , formula(formula)
00757 { }
00758
00759 virtual F operator() (const ElementWithCell< Real > &elm, const Real3d &p, const Real t=0.0) const
00760 {
00761 Real2d px = elm.elemMap(p);
00762 return operator()(elm, p, px, t);
00763 }
00764
00765 virtual F operator() (const ElementWithCell< Real > &elm, const Real2d &p, const Real t=0.0) const
00766 {
00767 Real2d px = elm.elemMap(p);
00768 return operator()(elm, p, px, t);
00769 }
00770
00771 virtual F operator() (const ElementWithCell< Real > &elm, const Real p, const Real t=0.0) const
00772 {
00773 Real2d px = elm.elemMap(p);
00774 return operator()(elm, p, px, t);
00775 }
00776
00777 template <class RealNd>
00778 F operator() (const ElementWithCell< Real > &elm, const RealNd &p, Real2d px,
00779 const Real t=0.0) const
00780 {
00781 if ( sigma_x->inPMLregion(px[0], t) || sigma_y->inPMLregion(px[1], t)) {
00782 return formula->operator()(elm, p, t);
00783 } else {
00784
00785
00786 return F(0);
00787
00788 }
00789 }
00790
00791 virtual FormulaPMLBoxRestriction* clone() const {
00792 return new FormulaPMLBoxRestriction(*this);
00793 }
00794
00795 protected:
00796 virtual std::ostream& info(std::ostream& os) const {
00797 return os << "FormulaPMLBoxRestriction(" << formula << " :" << *sigma_x << ", " << sigma_y << ")))";
00798 }
00799 private:
00800 RCP<concepts::FormulaPMLPowerSigma<Real> > sigma_x;
00801 RCP<concepts::FormulaPMLPowerSigma<Real> > sigma_y;
00802 RCP<concepts::ElementFormula<F> > formula;
00803 };
00804
00805
00806
00823 class FormulaPMLRadia : public ElementFormula<Cmplx> {
00824 public:
00825 enum PMLMode { AD1, AD2, AS, IDENT};
00826
00838 FormulaPMLRadia(const ElementFormulaContainer<Cmplx> coeff_a
00839 , const ElementFormulaContainer<Cmplx> coeff_b
00840 , RCP<concepts::Formula<Real> > sigma
00841 , RCP<concepts::Formula<Real> > sigmaB
00842 , PMLMode mode
00843 , double omega
00844 )
00845 : coeff_a(coeff_a)
00846 , coeff_b(coeff_b)
00847 , sigma(sigma)
00848 , sigmaB(sigmaB)
00849 , mode(mode)
00850 , omega(omega)
00851 {}
00852
00853 virtual FormulaPMLRadia* clone() const {
00854 return new FormulaPMLRadia(*this);
00855 }
00856
00857 virtual Cmplx operator() (const ElementWithCell< Real > &elm, const Real3d &p
00858 , const Real t=0.0) const
00859 {
00860 throw std::string("FormulaPMLRadia currently only supports 2D!");
00861 }
00862
00863 virtual Cmplx operator() (const ElementWithCell< Real > &elm, const Real p
00864 , const Real t=0.0) const
00865 {
00866 throw std::string("FormulaPMLRadia currently only supports 2D!");
00867 }
00869 Cmplx gamma(Real2d &p) const{
00870 return Cmplx(1, (*sigma )(p) / omega);
00871 }
00873 Cmplx gammaB(Real2d &p) const{
00874 return Cmplx(1, (*sigmaB)(p) / omega);
00875 }
00876
00877 Real c_c(Real2d &p) const{
00878 return (p[0]*p[0])/(p[0]*p[0]+p[1]*p[1]);
00879 }
00880
00881 Real s_s(Real2d &p) const{
00882 return (p[1]*p[1])/(p[0]*p[0]+p[1]*p[1]);
00883 }
00884
00885 Real s_c(Real2d &p) const{
00886 return (p[0]*p[1])/(p[0]*p[0]+p[1]*p[1]);
00887 }
00888
00889 virtual Cmplx operator() (const ElementWithCell< Real > &elm, const Real2d &p, const Real t = 0.0) const
00890 {
00891 Real2d px = elm.elemMap(p);
00892
00893 switch(mode) {
00894 case AD1: return (gammaB(px)/gamma(px)*c_c(px) + gamma(px)/gammaB(px)*s_s(px)) * (coeff_a)(elm, p);
00895 case AD2: return (gammaB(px)/gamma(px)*s_s(px) + gamma(px)/gammaB(px)*c_c(px)) * (coeff_a)(elm, p);
00896 case AS : return ((gammaB(px)/gamma(px) - gamma(px)/gammaB(px))*s_c(px)) * (coeff_a)(elm, p);
00897 case IDENT: return gamma(px) * gammaB(px) * (coeff_b)(elm, p);
00898 }
00899 throw std::string("FormulaPMLRadia has gone mad!!");
00900 }
00901
00902 protected:
00903 virtual std::ostream& info(std::ostream& os) const {
00904 return os << "FormulaPMLRadia(coeffs: " << coeff_a << ", " << coeff_b <<
00905 ", sigma" << *sigma << ")";
00906 }
00907 private:
00909 const ElementFormulaContainer<Cmplx> coeff_a;
00910 const ElementFormulaContainer<Cmplx> coeff_b;
00912 RCP<concepts::Formula<Real> > sigma;
00914 RCP<concepts::Formula<Real> > sigmaB;
00916 PMLMode mode;
00918 double omega;
00919 };
00920
00921 }