-
Notifications
You must be signed in to change notification settings - Fork 629
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
tutorial for non-axisymmetric sources in cylindrical coordinates #2108
Comments
In particular, you can do two calculations
If you sum the LDOS(m) from (2), multiplying all of the m ≠ 0 terms by 2 (to account for the -m solutions), then it should converge to the answer from (1). (There might be a constant factor of 2 or π or something.) The farther off-axis you go, the more m's it should require to converge. Would be good to have a plot of LDOS(m) as a function of m from (2). I'm guessing you'll need m's up to about radius×ω. |
Two source polarizations/configurations to check:
|
Here is an initial attempt (not working) to demonstrate that the radiated flux in air from an However, there is a rather large discrepancy in the radiated flux for (1) and (2): 0.33 vs. 1014.46. This could mean there are scaling coefficients of the individual flux values in (2) that need to be included when computing their sum. """Verifies that the radiated flux from a point dipole in a
dielectric layer above a lossless ground plane computed in
cylindrical coordinates is the same for a dipole placed at
either r=0 or r≠0.
"""
import numpy as np
import matplotlib
matplotlib.use("agg")
import matplotlib.pyplot as plt
import meep as mp
resolution = 50 # pixels/μm
dpml = 0.5 # thickness of PML
dair = 1.0 # thickness of air padding
L = 6.0 # length of non-PML region
n = 2.4 # refractive index of surrounding medium
wvl = 1.0 # wavelength (in vacuum)
fcen = 1 / wvl # center frequency of source/monitor
# source properties (cylindrical)
df = 0.05 * fcen
cutoff = 10.0
src = mp.GaussianSource(fcen, fwidth=df, cutoff=cutoff)
# field decay termination criteria
tol = 1e-8
def radiated_flux(dmat: float, h: float, rpos: float, m: int) -> float:
"""Computes the radiated flux of a point dipole embedded
within a dielectric layer above a lossless ground plane in
cylindrical coordinates.
Args:
dmat: thickness of dielectric layer.
h: height of dipole above ground plane as fraction of dmat.
rpos: position of source in r direction.
m: angular φ dependence of the fields exp(imφ).
"""
sr = L + dpml
sz = dmat + dair + dpml
cell_size = mp.Vector3(sr, 0, sz)
boundary_layers = [
mp.PML(dpml, direction=mp.R),
mp.PML(dpml, direction=mp.Z, side=mp.High),
]
src_cmpt = mp.Er
src_pt = mp.Vector3(rpos, 0, -0.5 * sz + h * dmat)
sources = [mp.Source(src=src, component=src_cmpt, center=src_pt)]
geometry = [
mp.Block(
material=mp.Medium(index=n),
center=mp.Vector3(0, 0, -0.5 * sz + 0.5 * dmat),
size=mp.Vector3(mp.inf, mp.inf, dmat),
)
]
sim = mp.Simulation(
resolution=resolution,
cell_size=cell_size,
dimensions=mp.CYLINDRICAL,
m=m,
boundary_layers=boundary_layers,
sources=sources,
geometry=geometry,
)
flux_air = sim.add_flux(
fcen,
0,
1,
mp.FluxRegion(
center=mp.Vector3(0.5 * L, 0, 0.5 * sz - dpml),
size=mp.Vector3(L, 0, 0),
),
mp.FluxRegion(
center=mp.Vector3(L, 0, 0.5 * sz - dpml - 0.5 * dair),
size=mp.Vector3(0, 0, dair),
),
)
sim.run(
until_after_sources=mp.stop_when_fields_decayed(
20,
src_cmpt,
src_pt,
tol,
),
)
out_flux = mp.get_fluxes(flux_air)[0]
return out_flux
if __name__ == "__main__":
layer_thickness = 0.7 * wvl / n
dipole_height = 0.5
# (1) r = 0
rpos = 0
m = -1
ref_out_flux = radiated_flux(
layer_thickness,
dipole_height,
rpos,
m,
)
print(f"flux-ref:, {ref_out_flux}")
# (2) r ≠ 0
rpos = 0.215
num_m = 20
out_flux = np.zeros(num_m)
for m in range(num_m):
out_flux[m] = radiated_flux(
layer_thickness,
dipole_height,
rpos,
m,
)
print(f"flux:, {m}, {out_flux[m]}")
sum_out_flux = out_flux[0] + 2*np.sum(out_flux[1:])
print(f"flux-compare:, {ref_out_flux:.4f} (r=0), {sum_out_flux:.4f} (r≠0)") |
Hi Meep community, I was wondering if in this case(using cylindrical coordinates) is it possible to have a point like source object which is meant to be polarized along x. I know that for a plane wave excitation that is possible (based on the Tutorial on cylindrical coordinates) but for a point-like (dipole emitter) I am not fully sure if this works as well? I am interested in simulating such a dipole located at r=0 with a polarization given a single cartesian component. |
In cylindrical coordinates, the
We already have a tutorial for point dipole emission at |
Can you try two different nonzero radii (e.g. double the radius), and see if the answer just change proportional to r or r^2? |
You could also try Ep vs Er — they should be the same? |
Looks like the radiated flux varies as
This means there is likely a
The radiated flux is the (roughly the) same for
|
It appears that the further the point source is positioned from It would be useful to know apriori how many terms to compute in order to minimize the number of simulations necessary to obtain an accurate result using this approach. |
@kalosu, please don't post unrelated discussions in this issue. Start a new discussion thread if needed. |
I think there is a factor of 1/2πr that we are missing in the source normalization, which is why you are seeing (2πr)^2 scaling in the power (~ source^2). For r=0, I think this corresponds to r=0.5/resolution, so there will be a resolution-dependent factor for the r=0 source as we already saw in the LDOS calculations. (The fact that the Fourier series takes longer to converge with m as the radius increases is expected.) |
In order to empirically determine the constant factor which relates the radiated flux from (a) a point source at |
I think the correct factor for LDOS is probably Here, however, you aren't computing LDOS, you are computing total power, so I think maybe you're getting a missing 2πr factor from the current source normalization (since we normalize the currents as a delta function but IIRC we don't include the 2πr from a δ function in cylindrical coordinates?). Try plotting |
If you are still having a problem where the (m=+1, fcen=+1) simulation is not exactly a complex conjugate of (m=-1, fcen=-1), with the same flux, it would be good to dig into this. Maybe the (+1,+1) and (-1,-1) simulations for just a few timesteps — before the fields reach the PML — and see if the complex fields are exactly conjugates. If they aren't, then there is a complex factor we are missing in the timestepping? If they are, run it longer (until the fields reach the boundaries) to see if the PML is the source of the problem. |
Note that in order to give yourself the freedom to change the time profile as you change the radius, you might want to normalize the power by the Fourier transform of the current source. One way to get that is from the |
edit (1/16): improved the formatting of the results.
As previously reported, computing the radiated flux from an
Note: the third column (the radiated flux) consists of two values represented by constants As discussed, we would expect row 1 ( For reference, the correct set of results would be:
As a second experiment, we compare the complex fields (rather than the flux) obtained from
Note: the third and fourth columns consists of two values: Row 1 indicates that ( However, in the second experiment, row 3 indicates that ( --> Is it possible that the Poynting flux is somehow not being computed correctly in cylindrical coordinates? |
So it looks like you verified that the time-domain fields are complex conjugates. Maybe check that the raw dft fields are as expected. Then you can narrow it down to the Poynting flux routine. |
The time domain fields should be conjugates … The weird thing is that the conclusion from the table is that:
It's weird to me that flipping m has no effect since we clearly use the sign of Lines 266 to 271 in 19b8abe
Can you double-check that |
I verified that Following a request from @smartalecH, I verified that that DFT fields have the same properties as the time-domain fields shown in the second table of results above (as expected). ref: link to experiment 3 script and results. These results indicate that we likely need to look elsewhere for the cause of the discrepancy in the results among experiments 1 and 2/3. |
Maybe try a custom source that is purely real, so we can eliminate the variable of the source term, e.g. a source |
Unfortunately, this approach does not work. This is because a purely real source implemented as: sources = [
mp.Source(
src=mp.CustomSource(src_func=lambda t: np.sin(2*np.pi*fcen*t)),
center=mp.Vector3(),
component=mp.Er,
),
] produces purely real fields for a If instead we use a purely imaginary source ( |
Reviewing Maxwell's equations in cylindrical coordinates (reproduced below), a real current for |
From the equations, if you have a purely real Er source in equation (4), you will get purely real {Er, Ez, Hφ} and purely imaginary {Eφ, Hr, Hz}. (This is something we could exploit to get a factor-of-2 speedup for any m≠0, by the way?) If you flip the sign of m, then it should complex-conjugate the solution, which flips the signs of {Eφ, Hr, Hz}. It would be worth checking this for both m=1 and m=2 (it should be true for both), just in case there is a bug in the special handling at the origin for m=1. |
I also discovered from rerunning experiment #1 involving the radiated flux that |m|=2, 3, ... always produces the same flux for all four test cases:
This could be an indication that there is a bug only for the m=±1 case. |
In particular, this might be a bug in the realnum f_m_mult = ft == D_stuff ? 2 : (1 - 2 * cmp) * m; i.e. it was previously only correct for (Note that this affects both the PML and non-PML regions, regardless of the location of the source. It may have contributed to the degradation of the PML that we previously observed in #2148?) |
realnum f_m_mult = ft == D_stuff ? 2 : (1 - 2 * cmp) * m; Looks like this was indeed the bug. With this fix, the results for the m=±1 simulations are now consistent. Here is a summary of the updated results using this bug fix.
Confirmed.
Confirmed. Also, the first experiment now produces the same flux values for all four test cases which is similar to
These results can be the basis for a unit test for this feature which currently does not exist. Finally, the bug fix now resolves the slowly decaying fields at |
Note that if you vary the radial length L, the (time-averaged/frequency-domain) flux in the R and Z directions should go to nonzero constants since you are exciting a guided mode trapped in the waveguide. (Since you have PEC boundary conditions at the bottom, this corresponds to the odd-symmetry modes of the waveguide. For the in-plane polarization, that includes the fundamental mode, so I would expect waveguide modes to exist regardless of the thickness — there is no cutoff.) As to whether the R or Z flux is bigger, that depends. On the one hand, the waveguide modes have a large density of states than vacuum so point sources tend to preferentially radiate into them. On the other hand, you would couple better into the guided mode using a z-directed point source than an r-directed point source. |
Note also that you should only expect Poynting's theorem to hold up to discretization error, because we are using the Poynting flux ExH derived for the exact Maxwell equations, which is not quite the same as the discrete Poynting flux. |
Unfortunately, this discretization error does not seem to be the cause of the discrepancy in the results for the different I also tried using In summary: even though we have fixed a couple of bugs in the |
On 12/8/2022, @stevengj wrote:
As specified in Lines 476 to 479 in a6a1192
(The There is no |
My suggestion is to remove the waveguide (it slows down convergence with resolution) for now, fix the source position (at r ≠ 0), and plot the power P(L) - P(L+1) vs resolution. What we'd like to see is that this difference goes to zero. (You want a bunch of points here because as you know sometimes the convergence can be a bit oscillatory, so two data points might be deceptive.) If you want you can fix (If the difference stops decreasing with resolution at some point, check the runtime and the PML thickness.) |
I performed a series of tests for a single Additionally, here are two plots showing the radiated flux for |
Putting all the recent results and bug fixes together, it seems we could be getting closer to wrapping this up. If we plot Taking the above data and normalizing Based on this data, let's specify the normalized flux at all
|
Looks like the L dependence is conclusively a resolution effect. Is it converging with resolution or resolution^2? Similarly, would be good to plot the flux(2r) - flux(r) (normalized), for a fixed L, vs resolution, to see if that converges as well. |
P(2L) - P(L) is converging to zero quadratically with resolution (as expected). I have updated the log-log plot in the comment above to include the quadratic reference Also, based on an empirical analysis of the results involving the radiated flux |
The constant factor
Based on the results in this table, a plot of the relative error in Schematic of cell layout in cylindrical coordinates: scripts used to generate results: |
The quantity However, based on this data, the convergence rate seems to be much smaller than Here is a plot for just the |
Looks like Putting all the results together, to convert the Poynting flux |
Would be nice to do a tutorial for the other case mentioned at the beginning, an off-axis planewave. |
It would be nice to have a tutorial showing how to use non-axisymmetric sources in cylindrical coordinates by expanding the source in a exp(imφ) Fourier series. For example:
An off-axis planewave can be handled with the Jacobi–Anger expansion, as mentioned in tutorial with cylindrical coordinates and planewaves #902. Another example can be found in this paper eqs (5–10) and many other papers.
LDOS for off-axis points. This is a point source, so when expanded in a Fourier series it is just a constant as a function of m. Power orthogonality means that you can then just sum the LDOS's for different m's.
The text was updated successfully, but these errors were encountered: