def test_rotated_spheroid_equals_rotated_light(material, atol): """cross-sections are the same if a spheroid is rotated or if the light is rotated""" theta = 1.3 phi = 0.7 source = miepy.sources.plane_wave([1,0], theta=theta, phi=phi) z_oriented = miepy.cluster(particles=miepy.spheroid([0,0,0], radius, 2*radius, material), source=source, wavelength=wavelength, lmax=lmax, medium=medium) C1 = z_oriented.cross_sections() source = miepy.sources.plane_wave([1,0]) q = miepy.quaternion.from_spherical_coords(theta, phi).inverse() oriented = miepy.cluster(particles=miepy.spheroid([0,0,0], radius, 2*radius, material, orientation=q), source=source, wavelength=wavelength, lmax=lmax, medium=medium) C2 = oriented.cross_sections() assert np.allclose(C1, C2, rtol=0, atol=atol)
def test_sphere_cluster_tmatrix_particle(): """sphere_cluster_particle in miepy.cluster yields the same results as miepy.sphere_cluster""" L = 155*nm lmax = 6 cluster = miepy.sphere_cluster(position=[[-L/2, 0,0], [L/2,0,0]], material=Ag, radius=75*nm, source=source, lmax=lmax, medium=medium, wavelength=800*nm) C1 = cluster.cross_sections() cluster.solve_cluster_coefficients() p1 = cluster.p_cluster particle = miepy.sphere_cluster_particle(cluster.position, cluster.radius, Ag, lmax=lmax) cluster = miepy.cluster(particles=particle, source=source, lmax=lmax, medium=medium, wavelength=800*nm) C2 = cluster.cross_sections() p2 = cluster.p_scat assert np.allclose(C1, C2, rtol=7e-4, atol=0), 'equal cross-sections' assert np.allclose(p1, p2, rtol=1e-2, atol=1e-12), 'equal cluster scattering coefficients'
def force_gmmt(): wavelengths = np.linspace(400 * nm, 1000 * nm, 100) eps = meep_ext.get_eps(material)(wavelengths) Au = miepy.data_material(wavelengths, eps) # Au = miepy.constant_material(3.5**2) # Au = miepy.materials.Au() particles = [] for i in range(9): orientation = miepy.quaternion.from_spherical_coords(theta[i], phi[i]) particles.append( miepy.cylinder(position=[x[i], y[i], z[i]], radius=radius, height=height, material=Au, orientation=orientation)) F = np.zeros([3, 9, len(wavelengths)], dtype=float) for i, wavelength in enumerate(pbar(wavelengths)): sol = miepy.cluster(particles=particles, source=miepy.sources.plane_wave([1, 0]), wavelength=wavelength, lmax=4) F[..., i] = sol.force() # if i == 0: # miepy.visualize(sol) return dict(wavelengths=wavelengths, force=F)
def gmt_sim(): material = miepy.materials.constant_material(3**2) q = miepy.quaternion.from_spherical_coords(0, 0) particles = [ miepy.regular_prism([0, 0, 0], 4, width=W, height=H, material=material, orientation=q) ] c = miepy.cluster(particles=particles, source=miepy.sources.plane_wave([1, 1j]), wavelength=600 * nm, lmax=8) x = np.linspace(-1.5 * W, 1.5 * W, 150) y = np.linspace(-1.5 * W, 1.5 * W, 150) X, Y = np.meshgrid(x, y) Z = np.zeros_like(X) E = c.E_field(X, Y, Z, mask=True) Ixy = np.sum(np.abs(E)**2, axis=0) R = particles[0].enclosed_radius() + 20 * nm phi = np.linspace(0, 2 * np.pi, 50) x = R * np.cos(phi) y = R * np.sin(phi) z = np.zeros_like(x) E = c.E_field(x, y, z) Iphi = np.sum(np.abs(E)**2, axis=0) return dict(phi=phi, X=X, Y=Y, Ixy=Ixy, Iphi=Iphi)
def force_gmmt(): wavelengths = np.linspace(400 * nm, 1000 * nm, 100) # eps = meep_ext.get_eps(material)(wavelengths) # Au = miepy.data_material(wavelengths, eps) material = miepy.constant_material(3.5**2) particles = [ miepy.cube([-sep / 2, 0, 0], 200 * nm, material), miepy.cube([sep / 2, 0, 0], 200 * nm, material) ] F1 = np.zeros((3, ) + wavelengths.shape, dtype=float) F2 = np.zeros((3, ) + wavelengths.shape, dtype=float) for i, wavelength in enumerate(pbar(wavelengths)): c = miepy.cluster(particles=particles, source=miepy.sources.plane_wave([1, 0]), wavelength=wavelength, lmax=4) q = miepy.quaternion.from_spherical_coords(0, 0) c.update(orientation=[q, q]) F1[:, i] = c.force_on_particle(1) q = miepy.quaternion.from_spherical_coords(0, np.pi / 4) c.update(orientation=[q, q]) F2[:, i] = c.force_on_particle(1) return dict(wavelengths=wavelengths, F1=F1, F2=F2)
def vis(): fig, ax = plt.subplots() norm = job.load(norm_sim) scat = job.load(scat_sim) ax.plot((1 / nm) / norm.frequency, scat.scattering / norm.incident * norm.area, 'o', color='C0', label='scattering (FDTD)') ax.plot((1 / nm) / norm.frequency, scat.absorption / norm.incident * norm.area, 'o', color='C1', label='absorption (FDTD)') ax.plot((1 / nm) / norm.frequency, (scat.scattering + scat.absorption) / norm.incident * norm.area, 'o', color='C2', label='extinction (FDTD)') wavelengths = np.linspace(400 * nm, 1000 * nm, 100) eps = meep_ext.get_eps(material)(wavelengths) Au = miepy.data_material(wavelengths, eps) # Au = miepy.constant_material(3.5**2) C, A, E = [np.zeros_like(wavelengths) for i in range(3)] particles = [] for i in range(9): orientation = miepy.quaternion.from_spherical_coords(theta[i], phi[i]) particles.append( miepy.cylinder(position=[x[i], y[i], z[i]], radius=radius, height=height, material=Au, orientation=orientation)) for i, wavelength in enumerate(pbar(wavelengths)): sol = miepy.cluster(particles=particles, source=miepy.sources.plane_wave([1, 0]), wavelength=wavelength, lmax=3) C[i], A[i], E[i] = sol.cross_sections() ax.axhline(0, linestyle='--', color='black') ax.plot(wavelengths / nm, C, color='C0', label='scattering (GMT)') ax.plot(wavelengths / nm, A, color='C1', label='absorption (GMT)') ax.plot(wavelengths / nm, E, color='C2', label='extinction (GMT)') ax.legend() ax.set(xlabel='wavelength (nm)', ylabel='cross-section') plt.show()
def gmt_sim(): wavelengths = np.linspace(400 * nm, 1000 * nm, 100) eps = meep_ext.get_eps(material)(wavelengths) Au = miepy.data_material(wavelengths, eps) Au = miepy.constant_material(3.5**2) C, A, E = [np.zeros_like(wavelengths) for i in range(3)] particles = [] # orientation = miepy.quaternion.from_spherical_coords(theta[i], phi[i]) particles.append(miepy.cube([0, 0, 0], W, material=Au, orientation=q)) for i, wavelength in enumerate(tqdm(wavelengths)): sol = miepy.cluster(particles=particles, source=miepy.sources.plane_wave([1, 0]), wavelength=wavelength, lmax=4) C[i], A[i], E[i] = sol.cross_sections() return dict(wavelengths=wavelengths, C=C, A=A, E=E)
def tests(Nmax, step=1): Nparticles = np.arange(1, Nmax+1, step) t_force, t_flux, t_build, t_solve, t_expand, t_tmatrix = [np.zeros_like(Nparticles, dtype=float) for i in range(6)] for i,N in enumerate(Nparticles): print(N, Nmax) positions = [[n*separation, 0, 0] for n in range(N)] particles = [miepy.spheroid(pos, radius, 0.5*radius, Ag) for pos in positions] mie = miepy.cluster(particles=particles, source=source, wavelength=600*nm, lmax=2) t_force[i] = time_function(mie.force) t_flux[i] = time_function(mie.cross_sections) t_build[i] = time_function(partial(miepy.interactions.particle_aggregate_tmatrix, mie.position, mie.tmatrix, mie.material_data.k_b)) A = miepy.interactions.particle_aggregate_tmatrix(mie.position, mie.tmatrix, k=mie.material_data.k_b) t_solve[i] = time_function(partial(solve_linear_system, A, mie.p_src, method=miepy.solver.bicgstab)) t_tmatrix[i] = time_function(partial(tmatrix_time, mie)) x = np.linspace(0, N*separation, 1) y = 2*radius*np.ones_like(x) z = np.zeros_like(x) t_expand[i] = time_function(partial(mie.E_field, x, y, z)) fig, ax = plt.subplots() ax.plot(Nparticles, t_force, label='force') ax.plot(Nparticles, t_flux, label='flux') ax.plot(Nparticles, t_build, label='build') ax.plot(Nparticles, t_solve, label='solve') ax.plot(Nparticles, t_expand, label='expand') ax.plot(Nparticles, t_tmatrix, label='tmatrix') ax.legend() ax.set(xlabel='number of particles', ylabel='runtime (s)') plt.show()
def test_tmatrix_sphere_is_sphere(material, atol): """tmatrix method with spheres should be equivalent to sphere cluster""" position = [[-300*nm, 0, 0], [300*nm, 0, 0]] spheres = miepy.sphere_cluster(position=position, radius=radius, material=material, source=source, wavelength=wavelength, lmax=lmax, medium=medium) particles = [miepy.sphere(pos, radius, material) for pos in position] cluster = miepy.cluster(particles=particles, source=source, wavelength=wavelength, lmax=lmax, medium=medium) print(np.max(np.abs(spheres.p_inc - cluster.p_inc))) assert np.allclose(spheres.p_inc, cluster.p_inc, rtol=0, atol=atol)