-
Notifications
You must be signed in to change notification settings - Fork 640
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
Python implementation for medium evaluations #862
Conversation
Thanks for the suggestions! The function Here is a test case showing both the ordinary and extraordinary axes for lithium niobate and barium borate: hf = h5py.File('materialData_ani.hdf5', 'r')
dataNames = ["BaB2","LiNO"]
testMaterials = [BaB2O4,LiNbO3]
names = ["BaB2O4","LiNbO3"]
plt.figure(figsize=(4,4))
for iter in range(len(testMaterials)):
# Pull Meep data
M = testMaterials[iter]
f0 = M.valid_freq_range[0]
f1 = M.valid_freq_range[1]
wavelength = np.linspace(1/f0,1/f1,1000)
freq = 1/wavelength
eps = M.epsilon(freq.tolist())
ne = [np.real(np.sqrt(num.c3.z)) for num in eps]
no = [np.real(np.sqrt(num.c1.x)) for num in eps]
# Pull refractiveindex.info data
ref = hf.get(dataNames[iter] + '_e')
wavelength_ref = ref[:,0]
ne_ref = ref[:,1]
ref = hf.get(dataNames[iter] + '_o')
wavelength_ref = ref[:,0]
no_ref = ref[:,1]
linewidth = 2
# Set up plot
plt.subplot(221 + 2*iter)
plt.plot(wavelength_ref,ne_ref,color='Red',linewidth=linewidth,label='ref')
plt.plot(wavelength,ne,'--',color='Blue',linewidth=linewidth,label='meep')
plt.title("{}".format(dataNames[iter]))
plt.legend()
plt.xlabel('Wavelength ($\mu$m)')
plt.grid(True)
plt.ylabel('n$_e$')
plt.subplot(221 + 2*iter+1)
plt.plot(wavelength_ref,no_ref,color='Red',linewidth=linewidth,label='ref')
plt.plot(wavelength,no,'--',color='Blue',linewidth=linewidth,label='meep')
plt.title("{}".format(dataNames[iter]))
plt.legend()
plt.grid(True)
plt.xlabel('Wavelength ($\mu$m)')
plt.ylabel('n$_o$')
plt.tight_layout()
plt.savefig('materialEval_ani.png')
plt.show() The previous simulations also still work. I still haven't refactored the function into Also, the |
Here is some anisotropic data on liquid crystal, for example: https://www.tandfonline.com/doi/full/10.1080/15421400600655816?scroll=top&needAccess=true& |
For a test, just comparing the output to two hard-coded values should be sufficient. |
To handle scalars and numpy arrays, you could do something like: if hasattr(freq, "__iter__"):
freqs = freq
else:
freqs = [freq] then, at the end, you can do something like if hasattr(freq, "__iter__"):
return result
else:
return result[1] You probably also want to make the result an Nx3x3 numpy array rather than a Python list. |
I just pushed an update that refactored the method to use a common The function can take either a scalar, list, or I added a test script that tests Si, LiNO3, and Au. I'm still looking for a decent material to test nondiagonal components. I also added one more Lorentzian to the Au and Ag entries to match the cited publication. |
My latest commit leverages broadcasting to streamline the computation. I've also modified the Matrix constructor to allow the user to either specify three column vectors (as in the current implementation) or to specify a diagonal vector and an off-diagonal vector. If we decide to keep this, we should modify the docs too. |
Note that you need to add the test to |
@@ -258,12 +258,17 @@ | |||
Ag_frq4 = 9.083*eV_um_scale # 0.137 um | |||
Ag_gam4 = 0.916*eV_um_scale | |||
Ag_sig4 = Ag_f4*Ag_plasma_frq**2/Ag_frq4**2 | |||
Ag_f5 = 5.646 | |||
Ag_frq5 = 20.29*eV_um_scale |
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 additional Lorentzian term corresponds to a resonance at a wavelength of 0.061 μm (or 61 nm) that is so far outside the optical range that it should not affect results but it will increase the computational expense due to the additional storage and time stepping of auxiliary fields. (This is why it was originally left out.) Is it really necessary?
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.
@@ -291,12 +296,17 @@ | |||
Au_frq4 = 4.304*eV_um_scale # 0.288 um | |||
Au_gam4 = 2.494*eV_um_scale | |||
Au_sig4 = Au_f4*Au_plasma_frq**2/Au_frq4**2 | |||
Au_f5 = 4.384 | |||
Au_frq5 = 13.32*eV_um_scale |
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 Lorentzian resonance is at 0.093 μm (or 93 nm). Similar to the additional Ag term; is it really necessary or should we just reduce the tolerance of the test slightly (i.e., matching the results to 4 decimal places rather than 6)?
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.
Same as before. Let me know if you want me to remove it.
* Python implementation for medium evaluations * Enabled full Chi1 tensor, small naming conventions * refactored method with test and updated materials * refactored matrix init and streamlined computation with broadcasting * squeeze output for scalar freq inputs * Add test to makefile * complex hermitian Matrix init * docs
The python portion of #475 that is used to evaluate material dispersion profiles at a given frequency/wavelength. Useful for making sure your profile really is what you expect. Also great for doing several MPB simulations across a band.
Here is a simple test script that pulls the profiles of Ag, Au, Si, and Cu and compares them to their original sources (stored in the attached h5 file):
materialData.hdf5.zip