10#ifndef waveprop_sources_hh
11#define waveprop_sources_hh
24#include "operator/sparseMatrix.hh"
38#ifdef HAS_MATLABINTERFACE
39#include "matfile/matlabMatfile.hh"
51 class FormulaExpImag1D :
public Formula<Cmplx> {
53 FormulaExpImag1D(
const Real k,
const Cmplx u = 1.0,
Real x0 = 0.0)
54 : k_(k), x0_(x0), u_(u) {}
61 const Real arg = k_*(p-x0_);
62 return Cmplx(cos(arg), sin(arg)) * u_;
65 return (*
this)(p[0], t);
68 return (*
this)(p[0], t);
71 virtual std::ostream&
info(std::ostream&
os)
const {
72 return os <<
concepts::typeOf(*
this)<<
"(" << u_ <<
" * exp(i " << k_ <<
"(x - " << x0_ <<
")))";
83 class FormulaExpImag2D :
public Formula<Cmplx> {
85 FormulaExpImag2D(
const Real2d k,
const Cmplx u = 1.0, Real2d x0 = 0.0)
86 : k(k), x0(x0), u(u) {}
98 const Real arg = k[0]*(p[0]-x0[0])
101 return Cmplx(cos(arg), sin(arg)) * u;
105 return (*
this)( Real2d(p[0], p[1]), t);
108 virtual std::ostream&
info(std::ostream&
os)
const {
109 return os <<
concepts::typeOf(*
this)<<
"(" << u <<
" * exp(i " << k <<
"(x - " << x0 <<
")))";
120 class FormulaExpImag2DRadialDer :
public Formula<Cmplx> {
123 FormulaExpImag2DRadialDer(
const Real2d k,
const Cmplx u = 1.0)
124 : k(k), x0(0,0), u(u) {}
136 const Real arg = k[0]*(p[0]-x0[0])
137 + k[1]*(p[1]-x0[1]) ;
138 Cmplx val(cos(arg), sin(arg));
143 return Cmplx(0, (k[0]*p[0] + k[1]*p[1])/
len) * val;
147 return (*
this)( Real2d(p[0], p[1]), t);
150 virtual std::ostream&
info(std::ostream&
os)
const {
151 return os <<
concepts::typeOf(*
this)<<
"(" << u <<
" * exp(i " << k <<
"(x - " << x0 <<
")))";
163 class FormulaExpImag2DGrad :
public Formula<Point<Cmplx, 2> >
166 FormulaExpImag2DGrad(
const Real2d k,
const Cmplx u = 1.0, Real2d x0 = Real2d(0,0))
182 const Real arg = k[0]*(p[0]-x0[0])
183 + k[1]*(p[1]-x0[1]) ;
184 Cmplx val(cos(arg), sin(arg));
192 virtual Cmplx2d
operator() (
const Real3d& p,
const Real t = 0.0)
const {
194 return (*
this)( Real2d(p[0], p[1]), t);
197 virtual std::ostream&
info(std::ostream&
os)
const {
198 return os <<
concepts::typeOf(*
this)<<
"(" << u <<
" * exp(i " << k <<
"(x - " << x0 <<
")))";
223 class FormulaNormalOuterSP2D :
public ElementFormula< F >
226 static const bool OUTER =
true;
227 static const bool INNER =
false;
229 FormulaNormalOuterSP2D(
230 const ElementFormulaContainer< Point<F, 2> > vf,
231 Real2d center = Real2d(0,0),
bool direction = OUTER)
234 , direction(direction)
242 const Real p,
const Real t = 0.0)
const
251 normal /= normal.
l2();
256 if ( ( normal.
dot(
pp) < 0 && direction == OUTER ) ||
257 ( normal.
dot(
pp) > 0 && direction == INNER )
263 const Point<F, 2> u = vf.operator()(elm, p, t);
268 return normal[0] * u[0] + normal[1] * u[1];
271 virtual F operator() (
const ElementWithCell<Real>& elm,
272 const Real2d& p,
const Real t = 0.0)
const
277 virtual F operator() (
const ElementWithCell<Real>& elm,
278 const Real3d& p,
const Real t = 0.0)
const {
283 virtual std::ostream&
info(std::ostream&
os)
const {
284 return os <<
concepts::typeOf(*
this)<<
"(" << vf <<
", " << center <<
", " << direction <<
")";
299 class ComposeFormulaMatVec :
public ElementFormula< Point<F, DIM>, G >
302 ComposeFormulaMatVec(
315 const Real p,
const Real t = 0.0)
const
317 return A->operator()(elm, p, t) * vf->operator()(elm, p, t);
325 return A->operator()(elm, p, t) * vf->operator()(elm, p, t);
331 return A->operator()(elm, p, t) * vf->operator()(elm, p, t);
334 virtual std::ostream&
info(std::ostream&
os)
const {
345 class ComposeFormulaVecEntry :
public ElementFormula< F, G >
348 ComposeFormulaVecEntry(
361 const Real p,
const Real t = 0.0)
const
363 return vf->operator()(elm, p, t)[index];
369 return vf->operator()(elm, p, t)[index];
375 return vf->operator()(elm, p, t)[index];
378 virtual std::ostream&
info(std::ostream&
os)
const {
390 class FormulaIncPlaneWaveSource :
public ElementFormula<Cmplx> {
392 typedef std::map<int, double> MID;
394 FormulaIncPlaneWaveSource(ElementFormulaContainer<Cmplx> coeff_a
395 , ElementFormulaContainer<Cmplx> coeff_b
409 return operator()(elm, p,
px, t);
414 Real2d
px = elm.elemMap(p);
415 return operator()(elm, p,
px, t);
420 Real2d
px = elm.elemMap(p);
421 return operator()(elm, p,
px, t);
424 template <
class RealNd>
426 const Real t=0.0)
const
429 Cmplx a = coeff_a(elm, p);
430 Cmplx b = coeff_b(elm, p);
431 return (b - a) * (k[0]*k[0] + k[1]*k[1]) * u_inc->operator()(elm.elemMap(p), t);
441 virtual std::ostream&
info(std::ostream&
os)
const {
453 for(MID::const_iterator it =
attrToEps.begin();
456 coeffs[it->first] = it->second;
460 printf(
"Adding absorbing material (%f %f) for attr %d\n",
462 coeffs[it->first] = -it->second;
463#ifdef __cplusplus >= 201103L
470 printf(
"Adding non-absorbing material (%f %f) for attr %d\n",
471 it->second, 0., it->first);
481 for(MID::const_iterator it =
attrToEps.begin();
484 coeffs[it->first] = 1. / it->second;
487 coeffs[it->first] = -it->second;
488#ifdef __cplusplus >= 201103L
489 coeffs[it->first].imag(1e-3);
508#ifdef HAS_MATLABINTERFACE
518 std::unique_ptr<Vector<Real> >
538 for (
uint i = 0; i < N_; i++){
539 (*epsilon_)(i)=epsilon(i);
541 for (
uint i = 0; i < N_-1; i++){
553 for (
uint i = 0 ; i < N_; i++)
558 Real w = omega_*omega_*(*epsilon_)(i) - kx_*kx_;
561 "problem in the " << i <<
" th layer, ky is complex");
563 (*ky_)(i) = -
sqrt(w);
564 a(i) = 1.0/(*epsilon_)(i);
566 for (
uint i=0; i < N_-1; i++)
568 M(i,i) =
exp(
IMAG * (*ky_)(i) *(*d_)(i) );
569 M(i,i+1) = -
exp(
IMAG * (*ky_)(i+1) *(*d_)(i) );
570 M(i,N_+i) =
exp(-1.0 *
IMAG * (*ky_)(i) *(*d_)(i) );
571 M(i,N_+i+1) = -
exp(-1.0 *
IMAG * (*ky_)(i+1) *(*d_)(i) );
573 M(N_+i,i) = a(i) * (*ky_)(i) *
exp(
IMAG* (*ky_)(i) *(*d_)(i) );
574 M(N_+i,i+1) = -1.0 * a(i+1) * (*ky_)(i+1) *
exp(
IMAG* (*ky_)(i+1) *(*d_)(i) );
575 M(N_+i,N_+i) = -1.0 * a(i) * (*ky_)(i) *
exp(-1.0*
IMAG* (*ky_)(i) *(*d_)(i) );
576 M(N_+i,N_+i+1) = a(i+1) * (*ky_)(i+1) *
exp(-1.0*
IMAG* (*ky_)(i+1) *(*d_)(i) );
578 for (
uint i=0; i<2* N_; i++)
584 M(2*N_-1,2*N_-1) = 1.0 ;
593 for (
uint i=0; i<2*N_;i++)
600 std::unique_ptr<concepts::Operator<Cmplx> > solver(
nullptr);
616 for (
uint i=0; i<N_; i++)
624 void ConstructFromBook()
629 Real normk2 = (kx_*kx_+(*ky_)(0)*(*ky_)(0))/(*epsilon_)(0);
630 for (
uint i = 0; i < N_; i++){
631 (*ky_)(i) =
sqrt(
normk2*(*epsilon_)(i)-kx_*kx_);
635 for (
int i = N_-2; i>=0; i--)
642 Cmplx R = (1.0-p)/(1.0+p);
651 for (
uint i = 1; i < N_; i++)
659 (*B_)(i) = (*B_)(i-1)*u/v;
660 (*A_)(i) = (*B_)(i)* (*rho_)(i);
662 (*A_)(0) = (*B_)(0)*(*rho_)(0);
666 std::cout <<
" epsilon = " << *epsilon_ << std::endl;
667 std::cout <<
" d = " << *d_ << std::endl;
668 std::cout <<
" kx = " << kx_ << std::endl;
669 std::cout <<
" omega = " << omega_ << std::endl;
670 std::cout <<
" ky = " << *ky_ << std::endl;
671 std::cout <<
" A = " << *A_ << std::endl;
672 std::cout <<
" B = " << *B_ << std::endl;
676#ifdef HAS_MATLABINTERFACE
685 return (*
this)(
Real2d(p[0], p[1]),t);
688 virtual Cmplx operator() (
const Real2d &p,
const Real t=0.0)
const
690 Cmplx coeff_a, coeff_b;
694 for(i = 0; i < N_-1; index = ++i)
695 if (p[1] >= (*d_)[i])
698 DEBUGL(FRMLAYPW_D,
"The point " << p <<
" is in the " << index <<
"th layer.");
700 coeff_a = (*A_)[index];
701 coeff_b = (*B_)[index];
702 KY = ((*ky_)[index]);
703 DEBUGL(FRMLAYPW_D,
"In this layer, A = " << coeff_a <<
", B = "
704 << coeff_b <<
", kx = " << kx_ <<
", ky = " <<
KY);
705 return coeff_a *
exp(
Cmplx(0, kx_*p[0]+
KY*p[1])) +
716 virtual std::ostream&
info(std::ostream&
os)
const {
718 <<
", A_:" << A_ <<
", B_:" << B_ <<
")";
721 const std::string filename_;
722 std::unique_ptr<Vector<Real> > d_;
723 std::unique_ptr<Vector<Real> > epsilon_;
724 std::unique_ptr<Vector<Cmplx> > rho_;
725 std::unique_ptr<Vector<Real> > ky_;
726 std::unique_ptr<Vector<Cmplx> > A_;
727 std::unique_ptr<Vector<Cmplx> > B_;
740#ifdef HAS_MATLABINTERFACE
749 std::unique_ptr<Vector<Real> >
kx(
matfile.getVector<
Real>(
"kx"));
768 for (
uint i = 0; i < N_; i++){
769 (*epsilon_)(i)=epsilon(i);
771 for (
uint i = 0; i < N_-1; i++){
783 for (
uint i = 0 ; i < N_; i++)
787 Real w = omega_*omega_*(*epsilon_)(i) - kx_*kx_;
790 "problem in the " << i <<
" th layer, ky is complex");
792 (*ky_)(i) = -
sqrt(w);
793 a(i) = 1.0/(*epsilon_)(i);
803 for (
uint i=0; i<2*N_;i++)
810 std::unique_ptr<concepts::Operator<Cmplx> > solver(
nullptr);
826 for (
uint i=0; i<N_; i++)
834 void ConstructFromBook(){
838 Real normk2 = (kx_*kx_+(*ky_)(0)*(*ky_)(0))/(*epsilon_)(0);
839 for (
uint i = 0; i < N_; i++){
840 (*ky_)(i) =
sqrt(
normk2*(*epsilon_)(i)-kx_*kx_);
844 for (
int i = N_-2; i>=0; i--)
851 Cmplx R = (1.0-p)/(1.0+p);
860 for (
uint i = 1; i < N_; i++)
868 (*B_)(i) = (*B_)(i-1)*u/v;
869 (*A_)(i) = (*B_)(i)* (*rho_)(i);
871 (*A_)(0) = (*B_)(0)*(*rho_)(0);
876 std::cout <<
" epsilon = " << *epsilon_ << std::endl;
877 std::cout <<
" d = " << *d_ << std::endl;
878 std::cout <<
" kx = " << kx_ << std::endl;
879 std::cout <<
" omega = " << omega_ << std::endl;
880 std::cout <<
" ky = " << *ky_ << std::endl;
881 std::cout <<
" A = " << *A_ << std::endl;
882 std::cout <<
" B = " << *B_ << std::endl;
890#ifdef HAS_MATLABINTERFACE
899 return (*
this)(
Real2d(p[0], p[1]),t);
902 virtual Cmplx2d operator() (
const Real2d &p,
const Real t=0.0)
const
904 Cmplx coeff_a, coeff_b;
908 for(i = 0; i < N_-1 ; index = ++i)
909 if (p[1] >= (*d_)[i])
912 DEBUGL(FRMLAYPW_D,
"The point " << p <<
" is in the " << index <<
"th layer.");
914 coeff_a = (*A_)[index];
915 coeff_b = (*B_)[index];
917 DEBUGL(FRMLAYPW_D,
"In this layer, A = " << coeff_a <<
", B = "
918 << coeff_b <<
", kx = " << kx_ <<
", ky = " <<
KY);
919 return Cmplx2d(
Cmplx(0.,1.)*kx_*coeff_a*
exp(
Cmplx(0.,kx_*p[0]+
KY*p[1])),
932 virtual std::ostream&
info(std::ostream&
os)
const {
934 <<
", A_:" << A_ <<
", B_:" << B_ <<
")";
937 const std::string filename_;
938 std::unique_ptr<Vector<Real> > d_;
939 std::unique_ptr<Vector<Real> > epsilon_;
940 std::unique_ptr<Vector<Cmplx> > rho_;
941 std::unique_ptr<Vector<Real> > ky_;
942 std::unique_ptr<Vector<Cmplx> > A_;
943 std::unique_ptr<Vector<Cmplx> > B_;
979 ~FormulaLayerPlaneWaveLayer() {};
988 return (*
this)(
Real2d(p[0], p[1]),t);
991 Cmplx operator() (
const Real2d &p,
const Real t=0.0)
const
1008 <<
", ky_: " <<
ky_ <<
")";
1042 ~FormulaLayerPlaneWaveLayerGrad() {};
1051 return (*
this)(
Real2d(p[0], p[1]),t);
1054 Cmplx2d operator() (
const Real2d &p,
const Real t=0.0)
const
1073 <<
", ky_: " <<
ky_ <<
")";
1108 uint N = epsilon.size();
1122 for (
uint i=0 ; i <
N; i++)
1124 Real w = omega*omega*epsilon(i)-
kx*
kx;
1126 "Problem in layer " << i <<
", ky is complex");
1128 a(i) = 1.0/epsilon(i);
1132 for (
uint i=0; i <
N-1; i++)
1134 M(i,i) =
exp(
I *
ky(i) *d(i) );
1135 M(i,i+1) = -
exp(
I *
ky(i+1) *d(i) );
1136 M(i,
N+i) =
exp(-1.0 *
I *
ky(i) *d(i) );
1137 M(i,
N+i+1) = -
exp(-1.0 *
I *
ky(i+1) *d(i) );
1139 M(
N+i,i) = a(i) *
ky(i) *
exp(
I*
ky(i) *d(i) );
1140 M(
N+i,i+1) = -1.0 * a(i+1) *
ky(i+1) *
exp(
I*
ky(i+1) *d(i) );
1141 M(
N+i,
N+i) = -1.0 * a(i) *
ky(i) *
exp(-1.0*
I*
ky(i) *d(i) );
1142 M(
N+i,
N+i+1) = a(i+1) *
ky(i+1) *
exp(-1.0*
I*
ky(i+1) *d(i) );
1144 for (
uint i=0; i<2*
N; i++)
1150 M(2*
N-1,2*
N-1) = 1.0 ;
1151 DEBUGL(FRMLAYTOT_D,
"M=" << M);
1156 std::unique_ptr<concepts::Operator<Cmplx> > solver(
nullptr);
1167 DEBUGL(FRMLAYTOT_D,
"sol=" << sol);
1170 solver.reset(
nullptr);
1173 std::map<int, int>::const_iterator it =
phystolayer.begin();
1179 <<
" to domain of physical label " <<
phys_label);
1183 this->
set(phys_label, formula);
1221 uint N = epsilon.size();
1235 for (
uint i=0 ; i <
N; i++)
1237 Real w = omega*omega*epsilon(i)-
kx*
kx;
1239 "Problem in layer " << i <<
", ky is complex");
1241 a(i) = 1.0/epsilon(i);
1245 for (
uint i=0; i <
N-1; i++)
1247 M(i,i) =
exp(
I *
ky(i) *d(i) );
1248 M(i,i+1) = -
exp(
I *
ky(i+1) *d(i) );
1249 M(i,
N+i) =
exp(-1.0 *
I *
ky(i) *d(i) );
1250 M(i,
N+i+1) = -
exp(-1.0 *
I *
ky(i+1) *d(i) );
1252 M(
N+i,i) = a(i) *
ky(i) *
exp(
I*
ky(i) *d(i) );
1253 M(
N+i,i+1) = -1.0 * a(i+1) *
ky(i+1) *
exp(
I*
ky(i+1) *d(i) );
1254 M(
N+i,
N+i) = -1.0 * a(i) *
ky(i) *
exp(-1.0*
I*
ky(i) *d(i) );
1255 M(
N+i,
N+i+1) = a(i+1) *
ky(i+1) *
exp(-1.0*
I*
ky(i+1) *d(i) );
1257 for (
uint i=0; i<2*
N; i++)
1263 M(2*
N-1,2*
N-1) = 1.0 ;
1264 DEBUGL(FRMLAYTOT_D,
"M=" << M);
1269 std::unique_ptr<concepts::Operator<Cmplx> > solver(
nullptr);
1280 DEBUGL(FRMLAYTOT_D,
"sol=" << sol);
1286 std::map<int, int>::const_iterator it =
phystolayer.begin();
1292 <<
" to domain of physical label " <<
phys_label);
1296 this->
set(phys_label, formula);
virtual F operator()(const concepts::ElementWithCell< G > &elm, const Real p, const Real t=0.0) const
virtual ComposeFormulaVecEntry * clone() const
Virtual copy constructor.
virtual std::ostream & info(std::ostream &os) const
Returns information in an output stream.
Real2d jacobian(Real x) const
virtual const Cell & cell() const =0
Returns the cell on which the element is built.
Point< F, dim > & ortho(const Point< F, dim > &a)
F dot(const Point< F, dim > &b) const
Inner product, i.e. for complex arguments: this * conjugate(b)
Real l2() const
Returns the Euclidian norm of the vector.
#define conceptsAssert(cond, exc)
#define DEBUGL(doit, msg)
#define conceptsAssert3(cond, exc, msg)
#define conceptsThrowSimpleE(msg)
std::string typeOf(const T &t)
Set< F > makeSet(uint n, const F &first,...)
std::complex< Real > Cmplx
Type for a complex number. It also depends on the setting of Real.