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

WIP: mode-solver improvements #333

Merged
merged 6 commits into from
May 17, 2018
Merged

WIP: mode-solver improvements #333

merged 6 commits into from
May 17, 2018

Conversation

stevengj
Copy link
Collaborator

No description provided.

@oskooi
Copy link
Collaborator

oskooi commented May 13, 2018

Is this ready to be merged? We have a test involving a binary grating (below) for which the analytic result is known using scalar diffraction theory. The diffraction/transmission efficiency is [2/(πq)]^2 for q odd where q is the diffraction order (the q even modes have zero efficiency). Thus, as an example, the row with "grating:, " from the output with "1" (for q) in the second column should have a fourth column of [2/(π*1)] ^2 = 0.40528, etc.

import meep as mp
import math

resolution = 20        # pixels/um                                                                                                                                                 

nglass = 1.5
glass = mp.Medium(index=nglass)

dsub = 3               # substrate thickness                                                                                                                                       
dair = 3               # air padding between grating and pml                                                                                                                       
gp = 10.0              # grating period                                                                                                                                            
gh = 0.5               # grating height                                                                                                                                            
gdc = 0.5              # grating duty cycle                                                                                                                                        

lambda_min = 0.4       # vacuum wavelength                                                                                                                                         
lambda_max = 0.8       # vacuum wavelength                                                                                                                                         
fmin = 1/lambda_max
fmax = 1/lambda_min
fcen = 0.5*(fmin+fmax)
df = fmax-fmin

dpml = lambda_max      # PML thickness                                                                                                                                             
sx = dpml+dsub+gh+dair+dpml
sy = gp

cell_size = mp.Vector3(sx,sy,0)
pml_layers = [mp.PML(thickness=dpml,direction=mp.X)]

geometry = [ mp.Block(material=glass, size=mp.Vector3(dpml+dsub,mp.inf,mp.inf), center=mp.Vector3(-0.5*sx+0.5*(dpml+dsub),0,0)),
             mp.Block(material=glass, size=mp.Vector3(gh,gdc*gp,mp.inf), center=mp.Vector3(-0.5*sx+dpml+dsub+0.5*gh,0,0)) ]

k_point = mp.Vector3(0,0,0)

src_pos = -0.5*sx+dpml
sources = [ mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Ez, center=mp.Vector3(src_pos,0,0), size=mp.Vector3(0,sy,0)) ]

sim = mp.Simulation(resolution=resolution,
                    cell_size=cell_size,
                    boundary_layers=pml_layers,
                    geometry=geometry,
                    k_point=k_point,
                    sources=sources)

# fmode is the frequency corresponding to free-space wavelength lambda=0.535 um                                                                                                    
fmode = 1.0/0.535
xm = 0.5*sx-dpml
mflux = sim.add_eigenmode(fmode, 0, 1, mp.FluxRegion(center=mp.Vector3(xm,0,0), size=mp.Vector3(0,sy,0)))

sim.run(until_after_sources=mp.stop_when_fields_decayed(50, mp.Ez, mp.Vector3(xm,0), 1e-6))

##################################################                                                                                                                                 
# kpoint_function to compute propagation vector                                                                                                                                    
# for diffraction order #mode at frequency freq                                                                                                                                    
##################################################                                                                                                                                 
def kpoint_func(freq, mode):
  k0 = freq
  ky = (mode-1)/gp
  if ky<k0:
      kx=math.sqrt(k0*k0-ky*ky)
      return mp.Vector3(kx,ky,0.0)
  return mp.Vector3(0.0,0.0,0.0)

##################################################                                                                                                                                 
# get eigenmode coefficients of propagating modes                                                                                                                                  
##################################################                                                                                                                                 
for nm in range(1,10):
  kpoint = kpoint_func(fmode, nm)
  if kpoint.x > 0.0:
     alpha = sim.get_eigenmode_coefficients(mflux, [nm], kpoint_func)
     alpha0Plus  = alpha[2*0 + 0]  # coefficient of forward-traveling fundamental mode                                                                                             
     alpha0Minus = alpha[2*0 + 1]  # coefficient of backward-traveling fundamental mode                                                                                            
     angle=math.atan2(kpoint.y,kpoint.x) * 180/math.pi
     if (mp.am_master()):
       print("grating:, {}, {}, {}, {}, {}".format(fmode,nm-1,angle,abs(alpha0Plus**2),abs(alpha0Minus**2)))

@oskooi
Copy link
Collaborator

oskooi commented May 13, 2018

The following is the output of the above test (3rd, 5th, and 6th columns only which show the diffraction order and mode coefficients for the forward and backward propagating fundamental mode) for the current master branch and this PR.

Current Master Branch (latest commit: "silence a few integer conversion warnings")

 0, 0.04240749580850259, 2.6342811152618364e-05
 1, 0.036946434200348294, 2.488231549318584e-05
 2, 0.160843752053553, 8.564276021591415e-05
 3, 0.09055589914059989, 4.561081950477279e-05
 4, 0.060287844418301574, 3.084102762968417e-05
 5, 0.10771512088397131, 5.802491800697049e-05
 6, 0.10135113949679495, 5.7145340981331965e-05
 7, 0.08776828788126628, 5.062469328582102e-05
 8, 0.00709444120633117, 3.538242292925065e-06

PR #333

 0, 0.04240749580850259, 2.6342811152618364e-05
 1, 0.01611786733968826, 1.083453999418189e-05
 2, 0.1746479060850232, 9.360561895457124e-05
 3, 0.011498327288429493, 5.989100173129363e-06
 4, 0.053832147366412016, 2.7379429388025336e-05
 5, 0.04674794285021875, 2.393174671864669e-05
 6, 5.016155819864778e-05, 4.19425720887738e-08
 7, 0.0005926432930837127, 5.803495074333708e-07
 8, 0.0011384747303681483, 7.046835311686956e-07

There is a slight difference but nevertheless the updated results still do not agree with the scalar diffraction theory. An even simpler check is that the last column should all be zeros.

@stevengj
Copy link
Collaborator Author

stevengj commented May 13, 2018

You should be using mp.Vector3(kx,0.0,0.0) … the ky here is automatically inferred by MPB. (It shouldn't affect the results, though, since putting in ky as any integer multiple of 1/gp is equivalent to ky=0, since 1/gp is the reciprocal lattice vector in the y direction.

#294 is also a problem here, since you want to really only look for TM modes — there are twice as many modes as you think, because the eigenmode coefficients are computing both polarizations here. Also, there is another factor of two in the number of modes because you are forgetting that each diffraction order is doubled (one going in the +y direction and one in the -y direction). For both these reasons, your kpoint_func is wrong.

Also, I'm not sure what scalar-diffraction method you are using, but I have a hard time believing this is an exact result — your supposedly exact answer doesn't even depend upon the refractive index of the glass. (If you set nglass=1 obviously the answer must change!)

@stevengj
Copy link
Collaborator Author

I've pushed a fix for #294. You can now pass an eig_parity=mp.TM to get_eigenmode_coefficients, which should eliminate the problem of the non-TM modes. You still have to correct your kpoint_func to return each diffracted order twice (except for the 0th order) to account for the ±ky modes.

@stevengj
Copy link
Collaborator Author

(Note, by the way, that the documentation for get_mode_coefficients needs to be updated — it seems to have been out of date for some time. But that can wait until after this PR.)

@oskooi
Copy link
Collaborator

oskooi commented May 13, 2018

The example is from Prof. George Barbastathis' 2.71 Optics class on OCW: see slide 9 of the lecture 16 notes. I was able to reproduce these results using the near2far approach as shown in these notes. The right figure on the first slide shows the relative amplitude of the diffraction peaks which agrees with the scalar theory.

@stevengj
Copy link
Collaborator Author

@ChristopherHogan, once this PR is merged we'll probably want to update mode_coeffs.py to a more stringent test — set eig_parity to something (e.g. mp.TM) and look at modes 1 and 3, not 1 and 2. The problem with looking at modes 1 and 2 is that these two modes are typically of different symmetry (especially if you don't fix the parity) and will be orthogonal by symmetry even if the mode calculation is somewhat off.

@stevengj
Copy link
Collaborator Author

@oskooi, did you have the wrong link? The slides you linked don't have anything about diffracted orders, and slide 9 is about ray tracing. You're not going to convince me that there is an exact answer independent of nglass — that is physically impossible, because if you set nglass=1 there is no diffraction at all.

@oskooi
Copy link
Collaborator

oskooi commented May 13, 2018

Oops, wrong link. Corrected now.

@stevengj
Copy link
Collaborator Author

By the way, I don't see why kpoint_func is needed at all here. I think the Newton solver should converge to the correct modes for each diffracted order even using the default guess.

@stevengj
Copy link
Collaborator Author

stevengj commented May 13, 2018

To use the result from the 2.71 notes, you have to choose the grating height S so that the phase difference is π between propagating a distance S in the glass vs. a distance S in the air. i.e. the thickness S must depend on both the index of the glass and the wavelength. It doesn't look like your code does this.

(Even if you choose S correctly to get the π binary phase, this is only an approximation, because it neglects diffraction within the thickness S of the grating, which is only accurate in the limit where the pitch Λ is much larger than both S and the wavelength λ. It doesn't look like you are operating in this limit, so I don't think the approximation will be super accurate for you even with the correct S.)

@oskooi
Copy link
Collaborator

oskooi commented May 13, 2018

The pitch Λ is 10 μm, the wavelength λ is 0.535 μm, and the grating height S is 0.5 μm so we are well within the scalar limit.

@oskooi
Copy link
Collaborator

oskooi commented May 13, 2018

I reran the test above using the latest version of this PR (commit "whoops") with slight modification to the last few lines to add the eig_parity argument and remove the kpoint_func:

for nm in range(1,10):
  alpha = sim.get_eigenmode_coefficients(mflux, [nm], eig_parity=mp.TM)
  alpha0Plus  = alpha[2*0 + 0]  # coefficient of forward-traveling fundamental mode                                                                                      
  alpha0Minus = alpha[2*0 + 1]  # coefficient of backward-traveling fundamental mode                                                                                     
  if (mp.am_master()):
    print("grating:, {}, {}, {}, {}".format(fmode,nm-1,abs(alpha0Plus**2),abs(alpha0Minus**2)))

The output, showing just the last three columns, is:

 0, 0.038862079483716526, 1.8544926362460716e-05
 1, 0.06249525732441384, 3.2135306906677464e-05
 2, 0.002924683376464619, 1.305279938984893e-06
 3, 0.0003706157916835195, 1.40792782502771e-07
 4, 2.6482381586396604e-05, 2.890660876012238e-08
 5, 0.0051542951282363084, 3.2635372746503596e-06
 6, 0.0213961097487549, 1.0708570288145908e-05
 7, 2.7892441172650813e-05, 2.449761115029649e-07
 8, 4.3062882643351686e-05, 1.9510962334992364e-07

The scalar theory is valid for λ=0.5 μm (which produces a π phase difference in the grating of height S=0.5 and index 1.5 with air). The results for the λ=0.535 μm, which is what we are currently using, should be similar. Obviously, the results are still incorrect.

Rather than focus on the second column which is the square of the mode coefficient for the forward-propagating fundamental mode (i.e., the diffraction efficiency), it would be better to find out why the last column (the squared mode coefficient of the backward-propagating fundamental model) is not 0.

One thing to notice in the MPB's find-k output messages is that the ky component is always 0 when it should be m/gp for an integer m (the diffraction order):

field decay(t = 300.15000000000003): 7.887677925044516e-08 / 0.18523590868943166 = 4.2581797346156434e-07
run 0 finished at t = 300.15000000000003 (12006 timesteps)
MPB solved for omega_1(1.86916,0,0) = 1.8698 after 24 iters
grating:, 1.8691588785046729, 0, 0.038862079483716526, 1.8544926362460716e-05
MPB solved for omega_2(1.86916,0,0) = 1.87193 after 24 iters
MPB solved for omega_2(1.86638,0,0) = 1.86914 after 1 iters
grating:, 1.8691588785046729, 1, 0.06249525732441384, 3.2135306906677464e-05
MPB solved for omega_3(1.86916,0,0) = 1.87221 after 30 iters
MPB solved for omega_3(1.8661,0,0) = 1.86914 after 1 iters
grating:, 1.8691588785046729, 2, 0.0025346967958214455, 1.0913984497479051e-06
MPB solved for omega_4(1.86916,0,0) = 1.87999 after 18 iters
MPB solved for omega_4(1.85826,0,0) = 1.86913 after 1 iters
grating:, 1.8691588785046729, 3, 0.0003706157916835195, 1.40792782502771e-07
MPB solved for omega_5(1.86916,0,0) = 1.88028 after 20 iters
MPB solved for omega_5(1.85797,0,0) = 1.86912 after 1 iters
grating:, 1.8691588785046729, 4, 2.6482381586396604e-05, 2.890660876012238e-08
MPB solved for omega_6(1.86916,0,0) = 1.89315 after 19 iters
MPB solved for omega_6(1.84486,0,0) = 1.86914 after 1 iters
grating:, 1.8691588785046729, 5, 0.0051542951282363084, 3.2635372746503596e-06
MPB solved for omega_7(1.86916,0,0) = 1.89331 after 23 iters
MPB solved for omega_7(1.84469,0,0) = 1.86912 after 1 iters
grating:, 1.8691588785046729, 6, 0.021417743577202927, 1.0801615294465195e-05
MPB solved for omega_8(1.86916,0,0) = 1.91178 after 17 iters
MPB solved for omega_8(1.82557,0,0) = 1.86914 after 1 iters
grating:, 1.8691588785046729, 7, 2.7892441172650813e-05, 2.449761115029649e-07
MPB solved for omega_9(1.86916,0,0) = 1.91181 after 17 iters
MPB solved for omega_9(1.82553,0,0) = 1.86913 after 1 iters
grating:, 1.8691588785046729, 8, 2.3733804988611842e-05, 1.44209926875965e-07

Why, as you claimed earlier, should ky be 0? Also, note that the number of iterations for convergence is not a small number.

@stevengj
Copy link
Collaborator Author

stevengj commented May 13, 2018

ky=0 is equivalent to m/gp: these two differ by a reciprocal lattice vector. In any case, ky is ignored because it is set by the boundary conditions.

(The fact that all valid ky values are equivalent to 0 is the basis of diffraction theory: the only allowed diffracted orders are the planewave modes that are compatible with the periodic boundary conditions. Equivalently, in a periodic system, the ky of the incident planewave is conserved modulo reciprocal lattice vectors.)

@stevengj
Copy link
Collaborator Author

The coefficient of the backward-propagating mode won't be zero because of finite resolution. If you increase the resolution it should decrease. (This is for the same reason that an eigenmode source does not produce purely a forward-propagating mode at a finite resolution.)

@oskooi
Copy link
Collaborator

oskooi commented May 13, 2018

I ran the test at several resolutions (pixels/μm): 20, 40, 80, 160, 200. The backward mode coefficients do not seem to be changing noticeably. The forward mode coefficients are not converging to the expected result.

resolution=20

 0, 0.03886205417762769, 1.8545924461543852e-05
 1, 0.06249561222961188, 3.2128592050818806e-05
 2, 0.014856001457072478, 7.068920251474112e-06
 3, 0.00037058046516927443, 1.4128983614006662e-07
 4, 1.4227950230905137e-05, 2.0567699079204813e-08
 5, 0.005154356765465943, 3.2629238689631556e-06
 6, 0.021396236702834425, 1.0705401749787024e-05
 7, 2.7912154586525668e-05, 2.448935454846044e-07
 8, 4.982583917834202e-05, 2.4303729894710293e-07

resolution=200

 0, 0.0668285308957547, 1.2695880642506546e-05
 1, 0.13924723753215146, 2.4286013619237204e-06
 2, 0.008937055145497615, 2.3260648751966648e-06
 3, 6.284277586431266e-05, 8.754380133640149e-08
 4, 0.024727785550837517, 8.463488073605389e-07
 5, 0.011246540187198053, 2.576659447745279e-07
 6, 0.009428125313621138, 1.999243765040603e-07
 7, 0.00025290744998719765, 2.97696555496213e-07
 8, 0.0006176729650936493, 1.1533982318288858e-07

How can we verify that MPB is computing the correct mode since since we cannot use the wavevector from find-k to verify that the correct diffraction order is being computed?

@stevengj
Copy link
Collaborator Author

The backward mode coefficients do not seem to be changing noticeably.

Then maybe they are limited by something other than resolution, e.g. the PML thickness or the finite runtime or the eigensolver tolerance (which I think defaults to 1e-7). The coefficients are small enough that they look like they must be some sort of approximation error.

The forward mode coefficients are not converging to the expected result.

How can you tell? To compare to the (2/πq)² answer you need to:

  1. Normalize by dividing by the incident power.

  2. Take the (2/πq)² and multiply it by 1 - (n-1)²/(n+1)² to account for the transmittivity of the glass/air interface (which was taken to be 1 or "a.u." in the course notes), and also multiply by cos(θ) = kₓc/ω of each diffracted mode to convert from field amplitude (in the course notes) to power in the x direction (what Meep computes).

How can we verify that MPB is computing the correct mode since since we cannot use the wavevector from find-k to verify that the correct diffraction order is being computed?

Why can't you look at kₓ?

@oskooi
Copy link
Collaborator

oskooi commented May 13, 2018

The wavevectors from MPB's find-k routine which appear in the output do not agree with the expected analytic result of kx=sqrt(ω2-(2πm/Λ)2), which in units of 2π is simply sqrt(f2-(m/10)2) for frequency f=1/0.535.

The first five kx values should therefore be:

m=1, 1.8664819616307164
m=2, 1.8584280758460485
m=3, 1.8449268042642903
m=4, 1.8258573090723291
m=5, 1.8010427293911844

The values reported by MPB (at a resolution of 200 in Meep) are quite different:

m=1, 1.86624
m=2, 1.86604
m=3, 1.85822
m=4, 1.85823
m=5, 1.84457

Thus, it seems that there is some mixup in the modes MPB is calculating with the ones it should be calculating for this analysis. Perhaps this is related to adding eig_parity as a parameter?

Another indication that MPB is computing the wrong modes is that the mode coefficients of the forward-propagating mode for the even diffraction orders should all be zero. The output from earlier shows that these mode coefficients are not even close to zero.

@stevengj
Copy link
Collaborator Author

@oskooi, as I said above, for each kx there are actually two modes, at ±ky, which is why the MPB solutions are in pairs. When you account for this, the MPB modes are matching the analytic results to 1e-4. Hence, it appears MPB is computing exactly the correct modes.

@oskooi
Copy link
Collaborator

oskooi commented May 14, 2018

Two modes at ±ky for each kx would suggest that the "band indices" parameter passed to get_eigenmode_coefficients is not the diffraction order m but rather:

band index=1, m=0
band index=2, m=1, +ky
band index=3, m=1, -ky
band index=4, m=2, +ky
band index=5, m=2, -ky
...

The mode coefficients of the forward-propagating mode are quite different for the +ky and -ky diffraction orders even though the planewave is normally incident; how come? Given the symmetry of the problem, shouldn't they be equal?

Also, how can we reduce MPB's eigensolver tolerance and increase resolution to improve the accuracy of the results? Currently, there is no way to set these parameters through get_eigenmode_coefficients. Perhaps we should modify the function headers.

@stevengj
Copy link
Collaborator Author

Two modes at ±ky for each kx would suggest that the "band indices" parameter passed to get_eigenmode_coefficients is not the diffraction order m but rather:

It's exactly the band number in MPB, which refers to the modes in order of ω. As you say, this is not the diffraction order m, and it can't be because the diffraction order is signed (corresponding to ±ky).

The mode coefficients of the forward-propagating mode are quite different for the +ky and -ky diffraction orders even though the planewave is normally incident; how come? Given the symmetry of the problem, shouldn't they be equal?

Because of the degeneracy, MPB is giving you a "random" superposition of the ±ky solutions. The sum of their powers should be the same as the sum of the +ky and -ky powers.

If you pass the EVEN_Y parity, it will only compute the +ky + -ky (cosine) mode. (For ODD_Y, it will compute the sine mode, but this will have zero power because your source is even.)

At ky≠0 the degeneracy breaks and then each mode is a planewave. You could also put in a ky that is slightly ≠ 0, say 1e-6, to get planewave modes again. (Remember, you change ky via the boundary conditions.)

@stevengj
Copy link
Collaborator Author

Also, how can we reduce MPB's eigensolver tolerance and increase resolution to improve the accuracy of the results? Currently, there is no way to set these parameters through get_eigenmode_coefficients. Perhaps we should modify the function headers.

Yes, it should really have all of the same parameters (including eig_resolution and eigensolver_tol) as add_eigenmode_source.

@stevengj
Copy link
Collaborator Author

stevengj commented May 14, 2018

Yikes, I just noticed that get_eigenmode_coefficients sets the eigensolver tolerance to only 1e-4, which is even larger than I thought ... the default should be 1e-7, the same as the eigenmode source.

@oskooi
Copy link
Collaborator

oskooi commented May 15, 2018

I created a new kpoint_func routine that returns an initial guess which incorporates the ±ky ordering of the modes. Following your suggestion, I also added 1e-6 to ky to break the degeneracy:

def kpoint_func(freq, nmode):
  k0 = freq
  if nmode == 1:
    return mp.Vector3(k0,0,0)
  else:
    [d, m] = divmod(nmode,2)
    ky = d/gp
    kx=math.sqrt(k0*k0-ky*ky)
    return mp.Vector3(kx,ky+1e-6,0)

for nm in range(1,8):
  alpha = sim.get_eigenmode_coefficients(mflux, [nm], eig_parity=mp.ODD_Z, kpoint_func=kpoint_func)
  alpha0Plus  = alpha[2*0 + 0]  # coefficient of forward-traveling fundamental mode                                                                          
  alpha0Minus = alpha[2*0 + 1]  # coefficient of backward-traveling fundamental mode                                                                         
  if (mp.am_master()):
    if nm == 1:
      print("grating:, {}, {}, {}".format(nm,abs(alpha0Plus**2),abs(alpha0Minus**2)))
    else:
      [d, pm] = divmod(nm,2)
      print("grating:, {}, {}, {}, {}, {}".format(nm,d,pm,abs(alpha0Plus**2),abs(alpha0Minus**2)))

Even when taking into account the transmissivity of the air/glass interface and multiplying by cos(θ) = kₓc/ω for each diffracted mode, the results (at resolution=80) are still not in agreement:

 1, 0.04258652517675744, 7.774550988346972e-06
 2, 1, 0, 0.17075409197571695, 6.767729512714021e-06
 3, 1, 1, 0.028045687990630553, 2.320016659645905e-06
 4, 2, 0, 2.4260273381036984e-05, 2.9483769665411373e-06
 5, 2, 1, 0.0006593721068362915, 5.321264825680865e-07
 6, 3, 0, 0.015552258941603246, 9.071495304988063e-07
 7, 3, 1, 0.022938896389041587, 9.375332689992376e-07

Modes 4 (+ky) and 5 (-ky) for diffraction order m=2 should both have zero coefficient for the forward-propagating mode. Mode 4 seems to be close but not 5.

Also, the output from MPB is still showing ky=0 although this may not be an indication that the degeneracy persists:

MPB solved for omega_1(1.86916,0,0) = 1.87007 after 23 iters
MPB solved for omega_2(1.86648,0,0) = 1.86934 after 21 iters
MPB solved for omega_3(1.86648,0,0) = 1.8697 after 23 iters
MPB solved for omega_4(1.85843,0,0) = 1.86952 after 18 iters
MPB solved for omega_5(1.85843,0,0) = 1.86978 after 22 iters
MPB solved for omega_6(1.84493,0,0) = 1.8692 after 22 iters
MPB solved for omega_7(1.84493,0,0) = 1.86922 after 28 iters

It would be good to rerun this test by reducing MPB's tolerance and/or increasing resolution. Would it be possible to add a commit to this PR to make these parameters as keyword arguments (and also set their default values to be consistent with those in add_eigenmode_source)?

@stevengj stevengj merged commit 345864e into master May 17, 2018
@stevengj stevengj deleted the bettermodes branch May 17, 2018 02:06
bencbartlett pushed a commit to bencbartlett/meep that referenced this pull request Sep 9, 2021
* mpb match-freq should only search k in direction d

* adjust for bloch-periodic boundaries in get_eigenmode, so that it works for both sources and mode decomposition

* allow get_eigenmode to return NULL if mode was not found, clean up a memory leak in mode coefficients

* whoops

* add parity argument to get_eigenmode_coefficients (fises NanoComp#294)

* add missing get_eigenmode_coefficients parameters, fix defaults
if (match_frequency && kmatch == 0) {
vec cen = eig_vol.center();
kmatch = omega_src * sqrt(get_eps(cen)*get_mu(cen));
k[d-X] = kmatch * R[d-X][d-X]; // convert to reciprocal basis
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line seems problematic and may be the cause of the incorrect mode reported in #2107.

The fix: kmatch should be changed to (kmatch - kpara_sum) where kpara_sum is the sum of the magnitude of the parallel components of k (i.e., parallel to the monitor). Instead, this line assigns a single component (in the normal direction d) of k to be kmatch (in Cartesian coordinates). The resulting k therefore has the wrong magnitude if any of its other components are non-zero. This may explain why the mode found by MPB is not what is expected.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just an initial guess for the Newton iteration; it doesn't have to be that accurate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants