def H_field_from_particle(self, i, x, y, z, source=True): """Compute the magnetic field around particle i Arguments: i particle number x x position (array-like) y y position (array-like) z z position (array-like) source Include the source field (bool, default=True) Returns: H[3,...] """ rad, theta, phi = miepy.coordinates.cart_to_sph( x, y, z, origin=self.position[i]) H_sph = miepy.expand_H(self.p_scat[i], self.material_data.k_b, mode=miepy.vsh_mode.outgoing, eps=self.material_data.eps_b, mu=self.material_data.mu_b)(rad, theta, phi) Hscat = miepy.coordinates.vec_sph_to_cart(H_sph, theta, phi) p = self.p_inc[i] if not source: p -= self.p_src[i] H_sph = miepy.expand_H(p, self.material_data.k_b, mode=miepy.vsh_mode.incident, eps=self.material_data.eps_b, mu=self.material_data.mu_b)(rad, theta, phi) Hinc = miepy.coordinates.vec_sph_to_cart(H_sph, theta, phi) return Hscat + Hinc
def test_power_2d_integration(self): """power by integrating Poynting vector in 2D plane""" lmax = 6 p_src = self.source.structure([0, 0, 0], k, lmax) a = 3000 * nm x = np.linspace(-a, a, 20) y = np.linspace(-a, a, 20) X, Y = np.meshgrid(x, y) R, THETA, PHI = miepy.coordinates.cart_to_sph(X, Y, 0) Efunc = miepy.expand_E(p_src, k, miepy.vsh_mode.incident) Hfunc = miepy.expand_H(p_src, k, miepy.vsh_mode.incident, 1, 1) E = Efunc(R, THETA, PHI) H = Hfunc(R, THETA, PHI) E = miepy.coordinates.vec_sph_to_cart(E, THETA, PHI) H = miepy.coordinates.vec_sph_to_cart(H, THETA, PHI) / Z0 S = 0.5 * np.linalg.norm(np.cross(E, np.conjugate(H), axis=0), axis=0) S = 0.5 * np.cross(E, np.conjugate(H), axis=0)[2] # S = 0.5*np.sum(np.abs(E)**2, axis=0) P = trapz_2d(x, y, S).real assert np.allclose(P, self.power, rtol=.04)
def H_field(self, x1, x2, x3, interior=True, source=True, mask=False, far=False, spherical=False): """Compute the magnetic field due to all particles Arguments: x1 x/r position (array-like) x2 y/theta position (array-like) x3 z/phi position (array-like) interior (optional) compute interior fields (bool, default=True) source (optional) include the source field (bool, default=True) mask (optional) set interior fields to 0 (bool, default=False) far (optional) use expressions valid only for far-field (bool, default=False) spherical (optional) input/output in spherical coordinates (bool, default=False) Returns: H[3,...] """ x1, x2, x3 = (np.asarray(x) for x in (x1, x2, x3)) shape = max(*[x.shape for x in (x1, x2, x3)], key=len) H = np.zeros((3, ) + shape, dtype=complex) if spherical: (x, y, z) = miepy.coordinates.sph_to_cart(x1, x2, x3, origin=self.origin) else: (x, y, z) = (x1, x2, x3) if far: expand = miepy.expand_H_far else: expand = partial(miepy.expand_H, mode=miepy.vsh_mode.outgoing) for i in range(self.Nparticles): rad, theta, phi = miepy.coordinates.cart_to_sph( x, y, z, origin=self.position[i]) H_sph = expand(self.p_scat[i], self.material_data.k_b, eps=self.material_data.eps_b, mu=self.material_data.mu_b)(rad, theta, phi) H += miepy.coordinates.vec_sph_to_cart(H_sph, theta, phi) if source: H += self.H_source(x, y, z, far=far, spherical=False) #TODO: what if x is scalar... if interior and not mask and not far: for i in range(self.Nparticles): x0, y0, z0 = self.position[i] idx = ((x - x0)**2 + (y - y0)**2 + (z - z0)**2 < self.particles[i].enclosed_radius()**2) k_int = 2 * np.pi * self.material_data.n[i] / self.wavelength rad, theta, phi = miepy.coordinates.cart_to_sph( x, y, z, origin=self.position[i]) H_sph = miepy.expand_H(self.p_int[i], k_int, eps=self.material_data.eps[i], mu=self.material_data.mu[i], mode=miepy.vsh_mode.interior)( rad[idx], theta[idx], phi[idx]) H[:, idx] = miepy.coordinates.vec_sph_to_cart( H_sph, theta[idx], phi[idx]) if mask and not far: for i in range(self.Nparticles): x0, y0, z0 = self.position[i] idx = ((x - x0)**2 + (y - y0)**2 + (z - z0)**2 < self.particles[i].enclosed_radius()**2) H[:, idx] = 0 #TODO: does this depend on the origin? if spherical: H = miepy.coordinates.vec_cart_to_sph(H, theta=x2, phi=x3) return H