-
Notifications
You must be signed in to change notification settings - Fork 641
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
Conversation
I would define two things:
|
Note that the only purpose of this is to create an equivalent current source, which must be a surface (a line in 2d or a plane in 3d). At the C++ level, the user will have to specify |
Note that because our source volume is finite, the user will need to ensure that the gaussian beam (evaluated in the source volume) is significantly narrower than the source volume (so that the currents/fields decay to a negligible value at the edge of the source). (We could even print out a warning if this is not the case, e.g. if the currents at the edge of the source volume are > 1% of the peak current.) |
A new |
… remove direction argument
To use You will need to change the |
…d two separate arguments for te/tm
Have you checked 3D yet? |
Yes, this is working in 3d as well. (I also tried removing the field scaling that Homer had included in his |
Are you planning to add swig/python support in this PR too? Seems pretty straightforward given all the current machinery. |
I was planning to create a separate PR for the Python API which would also include a test, documentation, and tutorial example. |
Results for 3d Gaussian beams at two different angles: 0° and 30° (rotation about x axis, 0° along +z axis). #include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <meep.hpp>
using namespace meep;
double one(const vec &) { return 1.0; }
int main(int argc, char **argv) {
meep::initialize mpi(argc, argv);
int s = 14;
int resolution = 30;
int dpml = 2;
grid_volume gv = vol3d(s, s, s, resolution);
gv.center_origin();
structure the_structure(gv, one, pml(dpml));
fields f(&the_structure);
double fcen = 1.0;
continuous_src_time src(fcen);
vec x0(0,0,0); // beam center
double theta = 30 * pi/180; // rotation angle around +x axis (0: +z axis)
vec kdir(0,sin(theta),cos(theta)); // beam propagation direction
double w0 = 1.0; // beam waist radius
std::complex<double> EO[3] = {1.0,0,0}; // polarization vector
gaussianbeam beam(x0, kdir, w0, fcen, 1.0, 1.0, EO);
volume vol(vec(-0.5*s,-0.5*s,0), vec(0.5*s,0.5*s,0));
f.add_volume_source(src, vol, beam);
while (f.time() < 10.0)
f.step();
volume output_vol(vec(-0.5*s+dpml,-0.5*s+dpml,-0.5*s+dpml),
vec(0.5*s-dpml,0.5*s-dpml,0.5*s-dpml));
f.output_hdf5(Ex, output_vol);
return 0;
}
|
…citation information to get_fields
double impedance = sqrt(mu/eps); | ||
double z0 = k * w0 * w0 / 2; // Rayleigh range | ||
double ZR = sqrt(mu/eps); | ||
double z0 = k * w0 * w0 / 2; | ||
double kz0 = k*z0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe all of these parameters should be computed once in the gaussianbeam
constructor, rather than each time gaussianbeam::get_fields
is called?
It probably makes little difference in performance, however, so we might as well leave it as-is for simplicity.
Would be nice to add a 2d C++ test. Maybe creating a focus like your example above (#1303 (comment)) but at a nonzero angle. Since the code seems to be working now, the test can just check to make sure that the intensity at the focal spot doesn't change in the future. Or maybe the test and documentation can wait until a future PR adds a Python API? |
This is not quite right for 2d, because we are just taking a slice of a circular-profile Gaussian beam.
|
In Python, we'll want a
%typecheck(SWIG_TYPECHECK_POINTER, fragment="NumPy_Fragments") std::complex<double> E0[3] {
$1 = is_array($input);
}
%typemap(in) std::complex<double> E0[3] {
std::complex<double> *pyE0 = (std::complex<double> *)array_data($input);
$1[0] = pyE0[0]; $1[1] = pyE0[1]; $1[2] = pyE0[2];
} |
At some point in the future, we could include a function to compute the beam power, and maybe normalize the beam to unit power. Homer provided a routine for this. However, that function won't work in 2d (#1308), where we'd either have to re-derive it or do a numerical (2d) quadrature to get the power. It's probably not worth the trouble, since it will be more reliable to do what you normally do in Meep — perform a separate normalization run. |
How would this be set up in |
An alternative to passing a source = [mp.GaussianBeamSource(src=mp.GaussianSource(fcen,df),
center=mp.Vector3(),
size=mp.Vector3(sx,sy,0),
x0=mp.Vector3(bx,by,bz),
kdir=mp.Vector3(kx,ky,kz),
w0=w0,
E0=mp.Vector3(cx,cy,cz))] The remaining parameters This approach was described in #711:comment and is more consistent with the API for |
That's fine. |
* complex source point Gaussian beam * add gaussianbeam class and add_volume_source function * automatically set direction of source volume to its normal vector and remove direction argument * move add_volume_source_check to private method of fields class and add two separate arguments for te/tm * move fields::add_volume_source_check definition from mpb.cpp to sources.cpp * replace has_tm() and has_te() functions with local variables and add citation information to get_fields
Fixes #711.
This PR adds a new function
gaussianbeam_3d
to thefields
class which computes the fields for a Gaussian beam using the complex source point method. The new function is based on @HomerReid's implementation from SCUFF-EM inGaussianBeam::GetFields
. The main difference is that the user-specified field-strength vectorE0
is real (because it is based on Meep'svec
object which only supports real-valued elements) whereas Homer supported the more general case of complex numbers. We could support a complex field-strength vector but this does not seem to be necessary.The next thing to do is to add the function
add_gaussianbeam_source
which callsgaussianbeam_3d
for every point in a given user-specified regionwhere
and uses these fields to compute the equivalent currents.A couple of issues regarding the API for
add_gaussianbeam_source
:where
object? Under what scenario would the beam center not lie in the 2d plane?make check
suite.