Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

complex source point Gaussian beam #1303

Merged
merged 6 commits into from
Aug 5, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/meep.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1682,6 +1682,9 @@ class fields {
void add_volume_source(component c, const src_time &src, const volume &,
std::complex<double> amp = 1.0);
void require_component(component c);
void gaussianbeam_3d(std::complex<double> *EH, const vec &x0, const vec &x,
const vec &kdir, double w0, double freq, double eps,
double mu, const vec &E0);
stevengj marked this conversation as resolved.
Show resolved Hide resolved

// mpb.cpp

Expand Down
98 changes: 98 additions & 0 deletions src/sources.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -436,4 +436,102 @@ void fields::add_volume_source(component c, const src_time &src, const volume &w
require_component(c);
}

/* Given the field-strength vector E0 for a Gaussian beam centered at x0 with beam waist w0 and propagation direction kdir,
compute the E/H fields EH[6] (6 components) at x for a frequency freq in the homogeneous 3d medium eps and mu.

Adapted from code by M. T. Homer Reid in his SCUFF-EM package
(file scuff-em/src/libs/libIncField/GaussianBeam.cc), which is GPL v2+. */

oskooi marked this conversation as resolved.
Show resolved Hide resolved
void fields::gaussianbeam_3d(std::complex<double> *EH, const vec &x0, const vec &x,
stevengj marked this conversation as resolved.
Show resolved Hide resolved
const vec &kdir, double w0, double freq, double eps,
double mu, const vec &E0) {
if (x0.dim == Dcyl) abort("wrong dimensionality in gaussianbeam_3d");

double n = sqrt(eps * mu);
double k = 2 * pi * freq * n;
double impedance = 1/sqrt(eps);
double zR = k * w0 * w0 / 2; // Rayleigh range
double kzR = k*zR;

vec xrel = x0 - x;

vec zhat = kdir / abs(kdir);

double rho = abs(vec(zhat.y()*xrel.z()-zhat.z()*xrel.y(),
zhat.z()*xrel.x()-zhat.x()*xrel.z(),
zhat.x()*xrel.y()-zhat.y()*xrel.x()));
double zhatdotxrel = zhat & xrel;

bool UseRescaledFG = false;

complex<double> zc = complex<double>(zhatdotxrel,-zR);
complex<double> Rsq = rho*rho + zc*zc;
complex<double> R = sqrt(Rsq);
complex<double> kR = k*R, kR2 = kR*kR, kR3 = kR2*kR;

complex<double> f,g,fmgbRsq;
if (abs(kR) > 1e-4) {
complex<double> coskR, sinkR;
if (fabs(imag(kR)) > 30.0) {
UseRescaledFG = true;
complex<double> ExpI = exp(complex<double>(0,1.0)*real(kR));
complex<double> ExpPlus = exp(imag(kR)-kzR); // should imag(kR) + kzR ?
complex<double> ExpMinus = exp(-(imag(kR)+kzR));
coskR = 0.5*(ExpI*ExpMinus + conj(ExpI)*ExpPlus);
sinkR = -0.5*complex<double>(0,1.0)*(ExpI*ExpMinus - conj(ExpI)*ExpPlus);
} else {
coskR = cos(kR);
sinkR = sin(kR);
}
f = -3.0 * (coskR/kR2 - sinkR/kR3);
g = 1.5 * (sinkR/kR + coskR/kR2 - sinkR/kR3);
fmgbRsq = (f-g)/Rsq;
} else {
complex<double> kR4 = kR2*kR2;
// Taylor series expansion for small R
f = kR4/280.0 - kR2/10.0 + 1.0;
g = 3.0*kR4/280.0 - kR2/5.0 + 1.0;
fmgbRsq = (kR4/5040.0 - kR2/140.0 + 0.1)*(k*k);
}
complex<double> i2fk = 0.5*complex<double>(0,1)*f*k;

double rnorm = abs(E0);
vec xhat = E0 / rnorm;
vec yhat = vec(zhat.y()*xhat.z()-zhat.z()*xhat.y(),
zhat.z()*xhat.x()-zhat.x()*xhat.z(),
zhat.x()*xhat.y()-zhat.y()*xhat.x());
double xhatdotxrel = xhat & xrel;
double yhatdotxrel = yhat & xrel;

complex<double> gb_Ex = g + fmgbRsq * xhatdotxrel * xhatdotxrel + i2fk * zc;
complex<double> gb_Ey = fmgbRsq * xhatdotxrel * yhatdotxrel;
complex<double> gb_Ez = fmgbRsq * xhatdotxrel * zc - i2fk * xhatdotxrel;
complex<double> gb_Hx = EH[1];
complex<double> gb_Hy = g + fmgbRsq * yhatdotxrel * yhatdotxrel + i2fk * zc;
complex<double> gb_Hz = fmgbRsq * yhatdotxrel * zc - i2fk * yhatdotxrel;

vec E_real = (vec(xhatdotxrel,0,0)*real(gb_Ex) + vec(0,yhatdotxrel,0)*real(gb_Ey) + vec(0,0,zhatdotxrel)*real(gb_Ez))*rnorm;
vec H_real = (vec(xhatdotxrel,0,0)*real(gb_Hx) + vec(0,yhatdotxrel,0)*real(gb_Hy) + vec(0,0,zhatdotxrel)*real(gb_Hz))*rnorm;

vec E_imag = (vec(xhatdotxrel,0,0)*imag(gb_Ex) + vec(0,yhatdotxrel,0)*imag(gb_Ey) + vec(0,0,zhatdotxrel)*imag(gb_Ez))*rnorm;
vec H_imag = (vec(xhatdotxrel,0,0)*imag(gb_Hx) + vec(0,yhatdotxrel,0)*imag(gb_Hy) + vec(0,0,zhatdotxrel)*imag(gb_Hz))*rnorm;

double Eorig;
if (UseRescaledFG)
Eorig = 3/(2*kzR*kzR*kzR) * (kzR*(kzR-1) + 0.5*(1.0-exp(-2.0*kzR)));
else
Eorig = 3/(2*kzR*kzR*kzR) * (exp(kzR)*kzR*(kzR-1) + sinh(kzR));

E_real = E_real / Eorig;
E_imag = E_imag / Eorig;
EH[0] = complex<double>(E_real.x(),E_imag.x());
EH[1] = complex<double>(E_real.y(),E_imag.y());
EH[2] = complex<double>(E_real.z(),E_imag.z());
H_real = H_real / (Eorig*impedance);
H_imag = H_imag / (Eorig*impedance);
EH[3] = complex<double>(H_real.x(),H_imag.x());
EH[4] = complex<double>(H_real.y(),H_imag.y());
EH[5] = complex<double>(H_real.z(),H_imag.z());
}

} // namespace meep