Home | Doxygen Documentation | Tutorials | Developer Tools (restricted)

app-bholger/pml/pml_formula.h
Go to the documentation of this file.
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 //TODO: properly expand this list
00013 
00014 #define pmlHolger_D 0
00015 
00016 namespace concepts {
00017 
00018 // ******************************************************** FormulaExpImag1D **
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 // ******************************************************** FormulaExpImag2D **
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     //cout << "e^{i k x}: " << p << ", " << Cmplx(cos(arg), sin(arg)) * u << endl;
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 // *********************************************** FormulaExpImag2DRadialDer **
00088 
00091 class FormulaExpImag2DRadialDer : public concepts::Formula<Cmplx> {
00092 public:
00093   //FormulaExpImag2DRadialDer(const Real2d k, const Cmplx u = 1.0, Real2d x0 = Real2d(0,0)) 
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 // **************************************************** FormulaExpImag2DGrad **
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     //const Real len = sqrt( p[0]*p[0] + p[1]*p[1] );
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     //conceptsThrowSimpleE("FormulaExpImag2DGrad currently only supports 2D!"); assert(false);
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 // ************************************************** FormulaNormalOuterSP2D **
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); //pp /= pp.l2();
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     //std::cout << "normal " << elm.elemMap(p) << ": " << normal 
00237     //  << "SP: " << normal[0] * u[0] + normal[1] * u[1] << "center: " << center << std::endl;
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     //return (*this)( Real2d(p[0], p[1]), t);
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 // **************************************************** ComposeFormulaMatVec **
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     //cout << "p: " << p << A->operator()(elm, p, t) << vf->operator()(elm, p, t) 
00294     //  << "  =  " << A->operator()(elm, p, t) * vf->operator()(elm, p, t)  << endl;
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 // *************************************************** ComposeFormulaVecEntry **
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 // *********************************************** FormulaIncPlaneWaveSource **
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 /* RCP< PiecewiseConstFormula<Cmplx> > coeff_a */
00365 /*       , RCP< PiecewiseConstFormula<Cmplx> > coeff_b */
00366                             , RCP< concepts::FormulaExpImag2D > u_inc )
00367     : coeff_a(coeff_a) // CAN BE IMPROVED
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]; // (can be complex)
00400     //Attribute atr = elm.cell().connector().attrib();
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       //DEBUGL(1, "a,b,b-a = " << a << b << b-a);
00410     }
00411     // NOTE: the term k2=omega^2 is not contained in coeff_b
00412     // (difference to the documentation)
00413     return (b - a) * k2 * u_inc->operator()(elm.elemMap(p), t);
00414     //return (b - a * k2) * u_inc->operator()(elm.elemMap(p), t);
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 /*   RCP< concepts::ElementFormula<Cmplx> > coeff_a; */
00430 /*   RCP< concepts::ElementFormula<Cmplx> > coeff_b; */
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 // **************************************************** FormulaPMLPowerSigma **
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       //printf("sigma(%f), arg = %f, cen %f, off %f\n", p, arg, center, offset);
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 // ************************************************** FormulaPMLPowerSigma2D **
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 // ************************************************* FormulaPMLPowerSigmaB2D **
00599 
00600 // Sigma bar 2D for Ridia case, see Collino & Monk
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 // ********************************************************** FormulaPMLCart **
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       //std::cout << "gamma_y(" << y << ") " << Cmplx(1, (*sigma_y)(y) / omega) << std::endl;
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 // ************************************************ FormulaPMLBoxRestriction **
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       //cout << "out: " << px << p << formula->operator()(elm, p, t) << endl;
00785       
00786       return F(0);
00787       //return formula->operator()(elm, p, t);
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 // ******************************************************* FormulaPMLRadia **
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]); //\f$\cos^2\theta\f$
00879     }
00880     
00881     Real s_s(Real2d &p) const{
00882       return (p[1]*p[1])/(p[0]*p[0]+p[1]*p[1]); //\f$\sin^2\theta\f$
00883     }
00884     
00885     Real s_c(Real2d &p) const{
00886       return (p[0]*p[1])/(p[0]*p[0]+p[1]*p[1]); //\f$\cos\theta*\sin\theta\f$
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 } // namespace concepts

Home | Doxygen Documentation | Tutorials | Developer Tools (restricted)