-
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
Enable Eigenmode Features with Dispersive Materials #919
Conversation
It looks like the serial implementation fails because the new routine doesn't like materials that have been rotated. It's able to pull the epsilon at those values just fine (using |
If MPB is giving that error it must be that your ε matrix is not positive-definite. |
This latest iteration fixes the original bug, which means that the routine can now use the In addition, I modified the The I'm a little stumped, so if anyone else with more experience with parallel h5 generation could look at it, that would be great. |
src/monitor.cpp
Outdated
if (eps.imag() == 0.0){ | ||
res = 1.0 / eps.real(); | ||
}else{ | ||
res = 1.0 / (std::sqrt(eps).real() * std::sqrt(eps).real()); |
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.
What's going on here? Why not just res = real(1.0 / eps)
?
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.
What we really want is real(1/n) ^2
, which is not the same as real(1.0 / eps)
if eps
is complex.
Output:
|
Note that this is not really doing the interpolation from the Yee grid correctly, so it is making a first-order error in principle. In practice, that error only shows up at the boundaries between materials, where it is hard to be accurate anyway, so let's just accept the 1st-order error for now and leave it to another PR to do the interpolation more correctly. |
The PR should be ready for merging. Here's a summary of the features:
As discussed, a better interpolation scheme is needed to improve the accuracy around the material boundaries. |
src/monitor.cpp
Outdated
Vinv[2 + 3*0] = 1/det * (V[1 + 3*0]*V[2 + 3*1] - V[1 + 3*1]*V[2 + 3*0]); | ||
Vinv[2 + 3*1] = 1/det * (V[0 + 3*1]*V[2 + 3*0] - V[0 + 3*0]*V[2 + 3*1]); | ||
Vinv[2 + 3*2] = 1/det * (V[0 + 3*0]*V[1 + 3*1] - V[0 + 3*1]*V[1 + 3*0]); | ||
if (det.real() == 0 && det.imag() == 0) abort("meep: Matrix is singular, aborting.\n"); |
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.
doesn't det == 0.0
work?
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.
I was just being safe -- do you want it changed?
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.
det == 0.0
seems clearer and is safe.
(You can't do det == 0
, on the other hand, because C++ doesn't let you mix complex<double>
with scalars of other types.)
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.
Just fixed with 8590db1
// Account for conductivity term | ||
if (conductivity[cc][dd]) { | ||
double conductivityCur = conductivity[cc][dd][idx]; | ||
eps = std::complex<double>(1.0, (conductivityCur/omega)) * eps; |
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.
This line looks off to me — it seems like you are doing an element-wise product rather than a matrix multiplication?
Since σ can only be a diagonal matrix currently, a matrix multiplication would multiply by conductivity[cc][cc]
(the diagonal element from row cc
), no?
What are the |
* first stab * begin with test files * bug fixes * update test * found one bug * bug fixes, h5 output, and array-slice output * fix serial bugs * more serial fixes * fix mu issue * disable h5 support * big fix * generalize matrix inverse and fix parallel bug * fix memory issue * add tutorial * minor fixes * refactor * check1 * case2 * add docs * cleanup * check3 * fix test * 1 more fix! * updates * det fix
The finished version of #475.
Modifies the
get_eigenmode
routines such that dispersive materials are now supported. Specifically, I modified theget_chi1inv()
function, which now evaluates the (real) inverse permittivity by summing all of the susceptibilities at a given point in a given direction for a specific field component at a specific frequency. It should be backward-compatible, as the default frequency is 0 (i.e. only the DC frequency is evaluated in this case).As mentioned, it only evaluates the real permittivity, since MPB's iterative solver can (currently) only solve for real eigenvalues.
That being said, this method still enables a lot of important features, one of them being S parameter extraction for dispersive materials (provided the materials are mostly dielectric).
Closes #415.
I've implemented a test that compares the actual permittivity, the return value of
chi1()
, and the "effective index" of a uniform medium (i.e. just the refractive index). All three should be the same.I check this for Silicon, SIlver, and Lithium Niobate so that we get a range of susceptibilities.