-
Notifications
You must be signed in to change notification settings - Fork 626
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
shift-and-invert eigensolver based on solve_cw #1158
Conversation
Update: it seems to work! I tried it on the holey waveguide tutorial to solve for the resonance mode, and I got (Caveat: I'm not sure why it's giving the eigenfrequency as having a positive imaginary part, when it should be negative, so I'll need to look into this. But at least it is converging, and plotting the field pattern confirms that it seems to be finding the resonant mode.) import meep as mp
resolution = 20 # pixels/um
eps = 13 # dielectric constant of waveguide
w = 1.2 # width of waveguide
r = 0.36 # radius of holes
d = 1.4 # defect spacing (ordinary spacing = 1)
N = 5 # number of holes on either side of defect
sy = 6 # size of cell in y direction (perpendicular to wvg.)
pad = 2 # padding between last hole and PML edge
dpml = 1 # PML thickness
sx = 2*(pad+dpml+N)+d-1 # size of cell in x direction
cell = mp.Vector3(sx,sy,0)
blk = mp.Block(size=mp.Vector3(mp.inf,w,mp.inf), material=mp.Medium(epsilon=eps))
geometry = [blk]
for i in range(N):
geometry.append(mp.Cylinder(r, center=mp.Vector3(d/2+i)))
geometry.append(mp.Cylinder(r, center=mp.Vector3(-(d/2+i))))
pml_layers = [mp.PML(1.0)]
fcen = 0.25
df = 0.2
src = [mp.Source(mp.GaussianSource(fcen, fwidth=df),
component=mp.Hz,
center=mp.Vector3(0),
size=mp.Vector3(0,0))]
sym = [mp.Mirror(mp.X, phase=-1), mp.Mirror(mp.Y, phase=-1)]
sim = mp.Simulation(cell_size=cell, force_complex_fields=True,
geometry=geometry,
boundary_layers=pml_layers,
sources=src,
symmetries=sym,
resolution=resolution)
eigfreq = sim.solve_eigfreq(L=20, cwtol=1e-11, tol=1e-6) |
Hmm, now that I think about it, I'm not estimating the eigenvalue correctly, because the operator here is the discrete time-difference operator and not the ∂/∂t operator. |
Okay, I've pushed a patch that corrects the eigenvalue estimate for the time discretization. It still converges in 7 shift-and-invert iterations, but now the estimated frequency is If I give it the initial guess frequency 0.2351 computed by Harminv in the tutorial, then it converges to nearly the same eigenvalue estimate (Note that the Q is higher than in the tutorial because I have more holes surrounding the cavity.) |
If I change the number of holes to So, this is consistent with the Harminv result but is presumably more accurate. |
I have noticed that import meep as mp
w = 1.2 # width of waveguide
r = 0.36 # radius of holes
d = 1.4 # defect spacing (ordinary spacing = 1)
N = 3 # number of holes on either side of defect
sy = 6 # size of cell in y direction (perpendicular to wvg.)
pad = 2 # padding between last hole and PML edge
dpml = 1 # PML thickness
sx = 2*(pad+dpml+N)+d-1 # size of cell in x direction
geometry = [mp.Block(size=mp.Vector3(mp.inf,w,mp.inf), material=mp.Medium(epsilon=13))]
for i in range(N):
geometry.append(mp.Cylinder(r, center=mp.Vector3(d/2+i)))
geometry.append(mp.Cylinder(r, center=mp.Vector3(-(d/2+i))))
fcen = 0.25
src = [mp.Source(mp.ContinuousSource(fcen),
component=mp.Hz,
center=mp.Vector3(0),
size=mp.Vector3(0,0))]
sim = mp.Simulation(cell_size=mp.Vector3(sx,sy),
force_complex_fields=True,
geometry=geometry,
boundary_layers=[mp.PML(1.0)],
sources=src,
symmetries=[mp.Mirror(mp.X, phase=-1), mp.Mirror(mp.Y, phase=-1)],
resolution=20)
sim.init_sim()
eigfreq = sim.solve_eigfreq(tol=1e-7)
if mp.am_master():
print("eigfreq: {}".format(eigfreq)) |
Regarding the results being different — this is a bug, I forgot to call (Hopefully that will fix the speed, too, since the bug probably messed up the convergence rate.) |
One of the tests is timing out, but that is because it was taking 49 minutes and 51 seconds before and so even a few seconds more exceeds the 50-minute time limit. We'll need to split up that test. |
Rebased; the tests should run faster now thanks to #1161. |
Does this work in cylindrical coordinates too (e.g. for calculating bent waveguide modes?) What's the advantage of this approach vs the typical harminv approach? If I set up a broadband simulation, I could even "capture" the mode profiles using a DFT monitor at the resonance frequency and normalize out the source (as long as it runs long enough to converge...), right? |
I think cylindrical coordinates should be fine, but I don't recall trying it. The |
* shift-and-invert eigensolver based on solve_cw * fix typemap * correct eigenvalue estimate for time discretization * added some math background * better defaults for mode solver * tests, docs * whoops, missing sum_to_all for parallel case
Closes #1153. Adds a
sim.solve_eigfreq
method similar tosolve_cw
except that it returns an estimated eigenfrequency (and sets the fields to the corresponding eigenmode) based on shift-and-invert iteration around the source frequency.Currently untested, just an initial stab at this.Needs: