def compute_ft(self, gvec): (gx, gy) = self._parse_ft_gvec(gvec) gabs = np.sqrt(np.abs(np.square(gx)) + np.abs(np.square(gy))) gabs += 1e-10 # To avoid numerical instability at zero ft = bd.exp(-1j*gx*self.x_cent - 1j*gy*self.y_cent)*self.r* \ 2*np.pi/gabs*bd.bessel1(gabs*self.r) return ft
def S_T_matrices_TE(omega, g, eps_array, d_array): """ Function to get a list of S and T matrices for D22 calculation """ assert len(d_array)==len(eps_array)-2, \ 'd_array should have length = num_layers' chi_array = chi(omega, g, eps_array) S11 = (chi_array[:-1] + chi_array[1:]) S12 = -chi_array[:-1] + chi_array[1:] S22 = S11 S21 = S12 S_matrices = 0.5 / chi_array[1:].reshape(-1,1,1) * \ bd.array([[S11,S12],[S21,S22]]).transpose([2,0,1]) T11 = bd.exp(1j*chi_array[1:-1]*d_array/2) T22 = bd.exp(-1j*chi_array[1:-1]*d_array/2) T_matrices = bd.array([[T11,bd.zeros(T11.shape)], [bd.zeros(T11.shape),T22]]).transpose([2,0,1]) return S_matrices, T_matrices
def compute_ft(self, gvec): """Compute Fourier transform of the polygon The polygon is assumed to take a value of 1 inside and a value of 0 outside. The Fourier transform calculation follows that of Lee, IEEE TAP (1984). Parameters ---------- gvec : np.ndarray of shape (2, Ng) g-vectors at which FT is evaluated """ (gx, gy) = self._parse_ft_gvec(gvec) (xj, yj) = self.x_edges, self.y_edges npts = xj.shape[0] ng = gx.shape[0] # Note: the paper uses +1j*g*x convention for FT while we use # -1j*g*x everywhere in legume gx = -gx[:, bd.newaxis] gy = -gy[:, bd.newaxis] xj = xj[bd.newaxis, :] yj = yj[bd.newaxis, :] ft = bd.zeros((ng), dtype=bd.complex); aj = (bd.roll(xj, -1, axis=1) - xj + 1e-10) / \ (bd.roll(yj, -1, axis=1) - yj + 1e-20) bj = xj - aj * yj # We first handle the Gx = 0 case ind_gx0 = np.abs(gx[:, 0]) < 1e-10 ind_gx = ~ind_gx0 if np.sum(ind_gx0) > 0: # And first the Gy = 0 case ind_gy0 = np.abs(gy[:, 0]) < 1e-10 if np.sum(ind_gy0*ind_gx0) > 0: ft = ind_gx0*ind_gy0*bd.sum(xj * bd.roll(yj, -1, axis=1)-\ yj * bd.roll(xj, -1, axis=1))/2 # Remove the Gx = 0, Gy = 0 component ind_gx0[ind_gy0] = False # Compute the remaining Gx = 0 components a2j = 1 / aj b2j = yj - a2j * xj bgtemp = gy * b2j agtemp1 = bd.dot(gx, xj) + bd.dot(gy, a2j * xj) agtemp2 = bd.dot(gx, bd.roll(xj, -1, axis=1)) + \ bd.dot(gy, a2j * bd.roll(xj, -1, axis=1)) denom = gy * (gx + bd.dot(gy, a2j)) ftemp = bd.sum(bd.exp(1j*bgtemp) * (bd.exp(1j*agtemp2) - \ bd.exp(1j*agtemp1)) * \ denom / (bd.square(denom) + 1e-50) , axis=1) ft = bd.where(ind_gx0, ftemp, ft) # Finally compute the general case for Gx != 0 if np.sum(ind_gx) > 0: bgtemp = bd.dot(gx, bj) agtemp1 = bd.dot(gy, yj) + bd.dot(gx, aj * yj) agtemp2 = bd.dot(gy, bd.roll(yj, -1, axis=1)) + \ bd.dot(gx, aj * bd.roll(yj, -1, axis=1)) denom = gx * (gy + bd.dot(gx, aj)) ftemp = -bd.sum(bd.exp(1j*bgtemp) * (bd.exp(1j * agtemp2) - \ bd.exp(1j * agtemp1)) * \ denom / (bd.square(denom) + 1e-50) , axis=1) ft = bd.where(ind_gx, ftemp, ft) return ft