def fullDet(b, nu): a = rho * b i = ivp(nu, u1*a) / (u1*a * iv(nu, u1*a)) if nu == 1: k2 = -2 k = 0 else: k2 = 2 * nu / (u2 * b)**2 - 1 / (nu - 1) k = -1 X = (1 / (u1*a)**2 + 1 / (u2*a)**2) P1 = jn(nu, u2*a) * yn(nu, u2*b) - yn(nu, u2*a) * jn(nu, u2*b) P2 = (jvp(nu, u2*a) * yn(nu, u2*b) - yvp(nu, u2*a) * jn(nu, u2*b)) / (u2 * a) P3 = (jn(nu, u2*a) * yvp(nu, u2*b) - yn(nu, u2*a) * jvp(nu, u2*b)) / (u2 * b) P4 = (jvp(nu, u2*a) * yvp(nu, u2*b) - yvp(nu, u2*a) * jvp(nu, u2*b)) / (u2 * a * u2 * b) A = (n12 * i**2 - n32 * nu**2 * X**2) if nu == 1: B = 0 else: B = 2 * n22 * n32 * nu * X * (P1 * P4 - P2 * P3) return (n32 * k2 * A * P1**2 + (n12 + n22) * n32 * i * k2 * P1 * P2 - (n22 + n32) * k * A * P1 * P3 - (n12*n32 + n22*n22) * i * k * P1 * P4 + n22 * n32 * k2 * P2**2 - n22 * (n12 + n32) * i * k * P2 * P3 - n22 * (n22 + n32) * k * P2 * P4 - B)
def Psi(self, r, neff, wl, nu, C): u = self.u(r, neff, wl) if neff < self.maxIndex(wl): psi = (C[0] * jn(nu, u) + C[1] * yn(nu, u) if C[1] else C[0] * jn(nu, u)) psip = u * (C[0] * jvp(nu, u) + C[1] * yvp(nu, u) if C[1] else C[0] * jvp(nu, u)) else: psi = (C[0] * iv(nu, u) + C[1] * kn(nu, u) if C[1] else C[0] * iv(nu, u)) psip = u * (C[0] * ivp(nu, u) + C[1] * kvp(nu, u) if C[1] else C[0] * ivp(nu, u)) # if numpy.isnan(psi): # print(neff, self.maxIndex(wl), C, r) return psi, psip
def __delta(self, nu, u1r1, u2r1, s1, s2, s3, n1sq, n2sq, n3sq): """s3 is sign of Delta""" if s1 < 0: f = ivp(nu, u1r1) / (iv(nu, u1r1) * u1r1) # c else: jnnuu1r1 = jn(nu, u1r1) if jnnuu1r1 == 0: # Avoid zero division error return float("inf") f = jvp(nu, u1r1) / (jnnuu1r1 * u1r1) # a b d if s1 == s2: # b d kappa1 = -(n1sq + n2sq) * f / n2sq kappa2 = (n1sq * f * f / n2sq - nu**2 * n3sq / n2sq * (1 / u1r1**2 - 1 / u2r1**2)**2) else: # a c kappa1 = (n1sq + n2sq) * f / n2sq kappa2 = (n1sq * f * f / n2sq - nu**2 * n3sq / n2sq * (1 / u1r1**2 + 1 / u2r1**2)**2) d = kappa1**2 - 4 * kappa2 if d < 0: return numpy.nan return u2r1 * (nu / u2r1**2 + (kappa1 + s3 * sqrt(d)) * 0.5)
def get_left_int_error(n, order): a = 2 b = 30 intervals = np.linspace(0, 1, n, endpoint=True) ** 2 * (b-a) + a discr = CompositeLegendreDiscretization(intervals, order) x = discr.nodes assert abs(discr.integral(1+0*x) - (b-a)) < 1e-13 alpha = 4 from scipy.special import jv, jvp f = jvp(alpha, x) num_int_f = jv(alpha, a) + discr.left_indefinite_integral(f) int_f = jv(alpha, x) if 0: pt.plot(x.ravel(), num_int_f.ravel()) pt.plot(x.ravel(), int_f.ravel()) pt.show() L2_err = np.sqrt(discr.integral((num_int_f - int_f)**2)) return 1/n, L2_err
def _hefield(self, wl, nu, neff, r): self._heceq(neff, wl, nu) for i, rho in enumerate(self.fiber._r): if r < rho: break else: i += 1 layer = self.fiber.layers[i] n = layer.maxIndex(wl) u = layer.u(rho, neff, wl) urp = u * r / rho c1 = rho / u c2 = wl.k0 * c1 c3 = nu * c1 / r if r else 0 # To avoid div by 0 c6 = constants.Y0 * n * n if neff < n: B1 = jn(nu, u) B2 = yn(nu, u) F1 = jn(nu, urp) / B1 F2 = yn(nu, urp) / B2 if i > 0 else 0 F3 = jvp(nu, urp) / B1 F4 = yvp(nu, urp) / B2 if i > 0 else 0 else: c2 = -c2 B1 = iv(nu, u) B2 = kn(nu, u) F1 = iv(nu, urp) / B1 F2 = kn(nu, urp) / B2 if i > 0 else 0 F3 = ivp(nu, urp) / B1 F4 = kvp(nu, urp) / B2 if i > 0 else 0 A, B, Ap, Bp = layer.C[:, 0] + layer.C[:, 1] * self.alpha Ez = A * F1 + B * F2 Ezp = A * F3 + B * F4 Hz = Ap * F1 + Bp * F2 Hzp = Ap * F3 + Bp * F4 if r == 0 and nu == 1: # Asymptotic expansion of Ez (or Hz): # J1(ur/p)/r (r->0) = u/(2p) if neff < n: f = 1 / (2 * jn(nu, u)) else: f = 1 / (2 * iv(nu, u)) c3ez = A * f c3hz = Ap * f else: c3ez = c3 * Ez c3hz = c3 * Hz Er = c2 * (neff * Ezp - constants.eta0 * c3hz) Ep = c2 * (neff * c3ez - constants.eta0 * Hzp) Hr = c2 * (neff * Hzp - c6 * c3ez) Hp = c2 * (-neff * c3hz + c6 * Ezp) return numpy.array((Er, Ep, Ez)), numpy.array((Hr, Hp, Hz))
def circle_wg_tm_mn(mesh, m=31, n=11, phi=90.0, radi=25.0): x, y = mesh[0], mesh[1] r, t = np.sqrt(x**2 + y**2), np.arctan(y / x) b = radi x0_mn = jn_zeros(m, n)[-1] x1_mn = jnp_zeros(m, n)[-1] if m == 0: e_m = 1 else: e_m = 2 func = np.sqrt(e_m / np.pi) func *= 1 / np.abs(jvp(m + 1, x0_mn)) func *= (-jvp(m, x0_mn * r / b, 0) * np.cos(m * t) + m / x0_mn * jvp(m, x0_mn * r / b, 0) / r * np.sin(m * t)) return func
def get_coefficients(Nterms, wavenumber_b, wavenumber_d, radius, epsilon_d, epsilon_b): """Summarize the method.""" n = np.arange(-Nterms, Nterms + 1) kb, kd = wavenumber_b, wavenumber_d a = radius an = (-jv(n, kb * a) / hankel2(n, kb * a) * ((epsilon_d * jvp(n, kd * a) / (epsilon_b * kd * a * jv(n, kd * a)) - jvp(n, kb * a) / (kb * a * jv(n, kb * a))) / (epsilon_d * jvp(n, kd * a) / (epsilon_b * kd * a * jv(n, kd * a)) - h2vp(n, kb * a) / (kb * a * hankel2(n, kb * a))))) cn = 1 / jv(n, kd * a) * (jv(n, kb * a) + an * hankel2(n, kb * a)) return an, cn
def lpConstants(self, r, neff, wl, nu, A): u = self.u(r, neff, wl) if neff < self.maxIndex(wl): W = constants.pi / 2 return (W * (u * yvp(nu, u) * A[0] - yn(nu, u) * A[1]), W * (jn(nu, u) * A[1] - u * jvp(nu, u) * A[0])) else: return ((u * kvp(nu, u) * A[0] - kn(nu, u) * A[1]), (iv(nu, u) * A[1] - u * ivp(nu, u) * A[0]))
def cutoffHE2(b): nu = 2 a = rho * b i = ivp(2, u1*a) / (u1*a * iv(2, u1*a)) X = (1 / (u1*a)**2 + 1 / (u2*a)**2) P1 = jn(nu, u2*a) * yn(nu, u2*b) - yn(nu, u2*a) * jn(nu, u2*b) P2 = (jvp(nu, u2*a) * yn(nu, u2*b) - yvp(nu, u2*a) * jn(nu, u2*b)) / (u2 * a) P3 = (jn(nu, u2*a) * yvp(nu, u2*b) - yn(nu, u2*a) * jvp(nu, u2*b)) / (u2 * b) P4 = (jvp(nu, u2*a) * yvp(nu, u2*b) - yvp(nu, u2*a) * jvp(nu, u2*b)) / (u2 * a * u2 * b) A = 2 * nu / (u2 * b)**2 - 1 / (nu - 1) return (n22 / n32 * (i*P1 + P2) * (n12*i*P3 + n22 * P4) + (A * i * P1 + A * P2 + i*P3 + P4) * (n12*i*P1 + n22*P2) - n32 * nu**2 * X**2 * P1 * (A * P1 + P3) - n22 * nu * X * (nu * X * P1 * P3 + 2 * P1 * P4 - 2 * P2 * P3))
def te0G(self, y): ''' find the zeros of this function to find the TE0 modes works only for mu_h=mu_c=1 ''' aa = 4.0j * special.jvp(0, z) * np.log(y) / special.jv(0, y) / np.pi bb = self.cyl_n * y**2 - 4.0j / y / self.host_n return aa + bb
def solve_for_AB(k, R1, R2): # solve the system for A,B # # / J'_m(k R1) Y'_m(k R1) \ /A\ -- /0\ # \ J'_m(k R2) Y'_m(k R2) / \B/ -- \0/ M = numpy.zeros((2, 2)) M[0][0] = special.jvp(1, k * R1, 1) # Jprime_1 at R1 M[0][1] = special.yvp(1, k * R1, 1) # Yprime_1 at R1 M[1][0] = special.jvp(1, k * R2, 1) # Jprime_1 at R2 M[1][1] = special.yvp(1, k * R2, 1) # Yprime_1 at R2 # close but no cigar to zero, otherwise it returns x=(0,0) b = numpy.array([1.e-16, 1.e-16]) x = numpy.linalg.solve(M, b) return x[0], x[1]
def cutoffHE1(b): a = rho * b i = ivp(1, u1*a) / (u1*a * i1(u1*a)) X = (1 / (u1*a)**2 + 1 / (u2*a)**2) P = j1(u2*a) * y1(u2*b) - y1(u2*a) * j1(u2*b) Ps = (jvp(1, u2*a) * y1(u2*b) - yvp(1, u2*a) * j1(u2*b)) / (u2 * a) return (i * P + Ps) * (n12 * i * P + n22 * Ps) - n32 * X * X * P * P
def Er(self, r, z): """Radial field component dV/dr""" r /= self.r0 z /= self.r0 s = 0 for (n,c) in enumerate(self.cns): if n==0: continue s += self.cns[n]*exp(-bessel_j0n[n]*z)*bessel_j0n[n]*special.jvp(0,bessel_j0n[n]*r) return s/self.r0
def test_bessel(): x = np.linspace(0, 20, 100) for n in range(2): plt.plot(x, jn(n, x), 'r-') plt.plot(x, jvp(n, x), 'b-') #plt.ylim(0,3.5) plt.show()
def test_cylindrical_bessel_j_prime(): order = np.random.randint(0, 10) value = np.random.rand(1).item() assert (roundScaler(NumCpp.bessel_jn_prime_Scaler(order, value), NUM_DECIMALS_ROUND) == roundScaler( sp.jvp(order, value).item(), NUM_DECIMALS_ROUND)) shapeInput = np.random.randint(20, 100, [ 2, ]) shape = NumCpp.Shape(shapeInput[0].item(), shapeInput[1].item()) cArray = NumCpp.NdArray(shape) order = np.random.randint(0, 10) data = np.random.rand(shape.rows, shape.cols) cArray.setArray(data) assert np.array_equal( roundArray(NumCpp.bessel_jn_prime_Array(order, cArray), NUM_DECIMALS_ROUND), roundArray(sp.jvp(order, data), NUM_DECIMALS_ROUND))
def cutoffHE1(b): a = rho * b i = ivp(1, u1 * a) / (u1 * a * i1(u1 * a)) X = (1 / (u1 * a)**2 + 1 / (u2 * a)**2) P = j1(u2 * a) * y1(u2 * b) - y1(u2 * a) * j1(u2 * b) Ps = (jvp(1, u2 * a) * y1(u2 * b) - yvp(1, u2 * a) * j1(u2 * b)) / (u2 * a) return (i * P + Ps) * (n12 * i * P + n22 * Ps) - n32 * X * X * P * P
def hybrid_mode_HE_graphical(r_0, h_0, log_n, f0_0): f0 = f0_0 * 1e12 r = r_0 * 1e-6 h = h_0 * 1e-6 epsilon_0 = 1 epsilon_2 = epsilon_0 e1, e2 = drude_model_Si(log_n, f0) # e1,e2 = drude_lorentz_model_Si(11.68,0,0,f0) epsilon_1 = e1 c = 2.99792458e8 lam = c / f0 k0 = 2 * pi / lam n = 1 m = 0 beta = pi / h alpha = sqrt(k0**2 * epsilon_1 - beta**2) gamma1 = alpha gamma2 = sqrt(beta**2 - k0**2 * epsilon_0) u = gamma1 * r v = gamma2 * r # eta1 = jvp(1,u)/(u*j1(u)) + kvp(1,v)/(v*k1(v)) # eta2 = (epsilon_1*k0**2)*jvp(1, u) / (u * j1(u)) + (k0**2)*kvp(1, v) / (v * k1(v)) eta1 = jvp(n - 1, u) / (u * jvp(n, u)) - n / u**2 eta2 = 1j * hankel1(n - 1, 1, 1j * v) / v / hankel1(n, 1, 1j * v) - n / v**2 f_res_1 = abs( (eta1 + eta2) * (k0**2 * epsilon_1 * eta1 + k0**2 * epsilon_2 * eta2)) f_res_2 = (n**2 * beta**2 * (1 / u**2 + 1 / v**2)**2) # eta1 = jvp(n-1,u)/(u*jvp(n,u)) + hankel1(n-1,v)/(v*hankel1(n,v)) # eta2 = (epsilon_1*k0**2)*jvp(n-1, u) / (u * jvp(n,u)) + (k0**2)*hankel1(n-1, v) / (v * hankel1(n,v)) # eta3 = (beta**2) * (1/u**2 + 1/v**2)**2 # # f_res_1 = abs(eta1*eta2) # f_res_2 = eta3 return f_res_1, f_res_2
def integrand_nopoles(a, p_bar, nu): #minimum value of a to keep p_perp real; equation 27 a_min = (nu / nu_c) * (1. - np.cos(theta) * p_bar) / np.sqrt(1. - p_bar**2.) #check if a > a_min if(a <= a_min): return 0. #gamma in terms of a, p_bar; equation 23 gamma = (nu_c / nu) * a / (1. - np.cos(theta) * p_bar) #p_parallel, equation 21 p_parallel = gamma * m * c * p_bar #p_perp, equation 22 p_perp = m * c * np.sqrt(gamma**2. * (1. - p_bar**2.) - 1.) #this is gamma as a function of p_perp and p_parallel, equation 28 gamma_check = np.sqrt((p_perp/(m * c))**2. + (p_parallel/(m * c))**2. + 1.) #Omega, equation 8 Omega = omega_c / gamma omega = 2. * np.pi * nu #z, equation 5 z = omega * np.sin(theta) * p_perp / (gamma * m * c * Omega) #M, equation 6 M = (np.cos(theta) - (p_parallel / (gamma * m * c))) / np.sin(theta) #N, equation 7 N = p_perp / (gamma * m * c) #bessel function term in integrand (eq. 16); note that the 1/sin(pi * a) is taken out # so that we can use the CPV integration method bessel_term = np.pi * special.jv(a, z) * special.jvp(-a, z) #jv'(-a, z) blows up with a, and jv(a, z) goes to zero; #they limit to -1/(pi*z) * sin(pi*a) as a -> inf if(np.isnan(bessel_term) == True): bessel_term = - 1./z * np.sin(np.pi * a) jacobian = - m**3. * c**3. * (nu_c / nu) * gamma**2. / (p_perp * (1. - np.cos(theta) * p_bar)) #dp_perp * dp_parallel from equation dp_perp_dp_para = jacobian #*dadp_bar, which is notation we don't use for a numerical integral #d^3p from equation 26 d3p = 2. * np.pi * p_perp * dp_perp_dp_para ans = M * N / Omega * Df(gamma, nu) * bessel_term * d3p return ans
def far_fields(radius, frequency, r, theta, phi): """ Calculate the electric and magnetic fields in the far field of the aperture. :param r: The range to the field point (m). :param theta: The theta angle to the field point (rad). :param phi: The phi angle to the field point (rad). :param radius: The radius of the aperture (m). :param frequency: The operating frequency (Hz). :return: The electric and magnetic fields radiated by the aperture (V/m), (A/m). """ # Calculate the wavenumber k = 2.0 * pi * frequency / c # Calculate the wave impedance eta = sqrt(mu_0 / epsilon_0) # Calculate the argument for the Bessel function z = k * radius * sin(theta) # Calculate the Bessel function bessel_term1 = 0.5 * ones_like(z) index = z != 0.0 bessel_term1[index] = jv(1, z[index]) / z[index] # Calculate the Bessel function jnpz = 1.84118378134065 denominator = (1.0 - (z / jnpz)**2) index = denominator != 0.0 bessel_term2 = 0.377 * ones_like(z) bessel_term2[index] = jvp(1, z[index]) / denominator[index] # Define the radial-component of the electric far field (V/m) e_r = 0.0 # Define the theta-component of the electric far field (V/m) e_theta = 1j * k * radius * jv(1, jnpz) * exp( -1j * k * r) / r * sin(phi) * bessel_term1 # Define the phi-component of the electric far field (V/m) e_phi = 1j * k * radius * jv(1, jnpz) * exp( -1j * k * r) / r * cos(theta) * cos(phi) * bessel_term2 # Define the radial-component of the magnetic far field (A/m) h_r = 0.0 # Define the theta-component of the magnetic far field (A/m) h_theta = 1j * k * radius * jv(1, jnpz) * exp( -1j * k * r) / r * -cos(theta) * cos(phi) / eta * bessel_term2 # Define the phi-component of the magnetic far field (A/m) h_phi = 1j * k * radius * jv(1, jnpz) * exp( -1j * k * r) / r * sin(phi) / eta * bessel_term1 # Return all six components of the far field return e_r, e_theta, e_phi, h_r, h_theta, h_phi
def EH_fields(self, ri, ro, nu, neff, wl, EH, tm=True): """ modify EH in-place (for speed) """ n = self.maxIndex(wl) u = self.u(ro, neff, wl) if ri == 0: if nu == 0: if tm: self.C = numpy.array([1., 0., 0., 0.]) else: self.C = numpy.array([0., 0., 1., 0.]) else: self.C = numpy.zeros((4, 2)) self.C[0, 0] = 1 # Ez = 1 self.C[2, 1] = 1 # Hz = alpha elif nu == 0: self.C = numpy.zeros(4) if tm: c = constants.Y0 * n * n idx = (0, 3) self.C[:2] = self.tetmConstants(ri, ro, neff, wl, EH, c, idx) else: c = -constants.eta0 idx = (1, 2) self.C[2:] = self.tetmConstants(ri, ro, neff, wl, EH, c, idx) else: self.C = self.vConstants(ri, ro, neff, wl, nu, EH) # Compute EH fields if neff < n: c1 = wl.k0 * ro / u F3 = jvp(nu, u) / jn(nu, u) F4 = yvp(nu, u) / yn(nu, u) else: c1 = -wl.k0 * ro / u F3 = ivp(nu, u) / iv(nu, u) F4 = kvp(nu, u) / kn(nu, u) c2 = neff * nu / u * c1 c3 = constants.eta0 * c1 c4 = constants.Y0 * n * n * c1 EH[0] = self.C[0] + self.C[1] EH[1] = self.C[2] + self.C[3] EH[2] = (c2 * (self.C[0] + self.C[1]) - c3 * (F3 * self.C[2] + F4 * self.C[3])) EH[3] = (c4 * (F3 * self.C[0] + F4 * self.C[1]) - c2 * (self.C[2] + self.C[3])) return EH
def order1(self, ps, v0_in): """ Equation assuming O(1) periodic input Here we take the input as an phasor in the electrical RF domain and the output is returned as a phasor in the optical domain vm_in = [a0, a1, a2 ... an] where v(t) = sum_{k=0}^n a_k exp(j k w0) + c.c. vm_out = [a0, a1, a2 ... an, a-n ... a-1] where E(t) = sum_{k=-n}^n a_k exp(j k w0) Note: Currently only the dc and fundamental component of the signal are used. All other harmonics are assumed filtered out. """ #Output signal will be complex pso = ps.copy() pso.real = False #Assume only fundamental harmonic and DC at input a0 = v0_in[0] a1,theta1 = np.abs(v0_in[1]), np.angle(v0_in[1]) #Jacobi-Anger expansion k = pso.ms b1 = special.jv(k, self.v1*a1) * np.exp(1j*self.v1*a0 + 1j*k*(theta1+0.5*pi)) b2 = special.jv(k, self.v2*a1) * np.exp(1j*self.phi + 1j*self.v2*a0 + 1j*k*(theta1+0.5*pi)) bp1 = special.jvp(k, self.v1*a1) * np.exp(1j*self.v1*a0 + 1j*k*(theta1+0.5*pi)) bp2 = special.jvp(k, self.v2*a1) * np.exp(1j*self.phi + 1j*self.v2*a0 + 1j*k*(theta1+0.5*pi)) v0_out = self.eloss*self.Em*(b1 + self.a*b2) #Flag and store the O1 solution self.O1_solution = (ps,v0_in,b1,b2,bp1,bp2) self.O1_complete = True return pso, v0_out
def norm(self, w, h, alpha, a, b): pol, n, m = alpha en = 1 if n == 0 else 2 if self.clad(w).real < -1e6: radius = self.r if pol == 'E': u = jnp_zeros(n, m)[-1] jnu = jv(n, u) jnpu = 0.0 else: u = jn_zeros(n, m)[-1] jnu = 0.0 jnpu = jvp(n, u) return np.sqrt(a**2 * np.pi * radius**2 / en * (1 - n**2 / u**2) * jnu**2 + b**2 * np.pi * radius**2 / en * jnpu**2) # ac = a.conjugate() # bc = b.conjugate() u = self.samples.u(h**2, w, self.fill(w)) jnu = jv(n, u) jnpu = jvp(n, u) v = self.samples.v(h**2, w, self.clad(w)) knv = kv(n, v) knpv = kvp(n, v) # uc = u.conjugate() # jnuc = jnu.conjugate() # jnpuc = jnpu.conjugate() # vc = v.conjugate() # knvc = knv.conjugate() # knpvc = knpv.conjugate() val_u = 2 * np.pi * self.r**2 / en val_v = val_u * ((u * jnu) / (v * knv))**2 # val_v = val_u * (uc * u * jnuc * jnu) / (vc * v * knvc * knv) upart_diag = self.upart_diag(n, u, jnu, jnpu, u, jnu, jnpu) vpart_diag = self.vpart_diag(n, v, knv, knpv, v, knv, knpv) upart_off = self.upart_off(n, u, jnu, u, jnu) vpart_off = self.vpart_off(n, v, knv, v, knv) return np.sqrt(val_u * (a * (a * upart_diag + b * upart_off) + b * (b * upart_diag + a * upart_off)) - val_v * (a * (a * vpart_diag + b * vpart_off) + b * (b * vpart_diag + a * vpart_off)))
def u_jnu_jnpu_pec(num_n, num_m): us = np.empty((2, num_n, num_m)) jnus = np.empty((2, num_n, num_m)) jnpus = np.empty((2, num_n, num_m)) for n in range(num_n): us[0, n] = jnp_zeros(n, num_m) us[1, n] = jn_zeros(n, num_m) jnus[0, n] = jv(n, us[0, n]) jnus[1, n] = np.zeros(num_m) jnpus[0, n] = np.zeros(num_m) jnpus[1, n] = jvp(n, us[1, n]) return us, jnus, jnpus
def cutoffHE2(b): nu = 2 a = rho * b i = ivp(2, u1 * a) / (u1 * a * iv(2, u1 * a)) X = (1 / (u1 * a)**2 + 1 / (u2 * a)**2) P1 = jn(nu, u2 * a) * yn(nu, u2 * b) - yn(nu, u2 * a) * jn(nu, u2 * b) P2 = (jvp(nu, u2 * a) * yn(nu, u2 * b) - yvp(nu, u2 * a) * jn(nu, u2 * b)) / (u2 * a) P3 = (jn(nu, u2 * a) * yvp(nu, u2 * b) - yn(nu, u2 * a) * jvp(nu, u2 * b)) / (u2 * b) P4 = (jvp(nu, u2 * a) * yvp(nu, u2 * b) - yvp(nu, u2 * a) * jvp(nu, u2 * b)) / (u2 * a * u2 * b) A = 2 * nu / (u2 * b)**2 - 1 / (nu - 1) return (n22 / n32 * (i * P1 + P2) * (n12 * i * P3 + n22 * P4) + (A * i * P1 + A * P2 + i * P3 + P4) * (n12 * i * P1 + n22 * P2) - n32 * nu**2 * X**2 * P1 * (A * P1 + P3) - n22 * nu * X * (nu * X * P1 * P3 + 2 * P1 * P4 - 2 * P2 * P3))
def effective_coated_N1(self, filling, polarization, orders=1): ''' Calculate effective medium parameters using the coated cylinder model ''' R = self.radius k = self.k_host mu_h = 1.0 R2 = R / np.sqrt(filling) #aa0 = self.coeff(1,polarization) sum_ = 0.0 + 0j if polarization in ['H', 'TE']: if orders < 1: orders = 1 for m in np.arange(1, orders + 1): # bessel functions J0 = special.jv(m, k * R2) H0 = special.hankel1(m, k * R2) JD0 = special.jvp(m, k * R2) HD0 = special.h1vp(m, k * R2) aa1 = self.coeff(m, 'TE') denom = JD0 + HD0 * aa1 + 0j numer = (J0 + H0 * aa1) + 0j sum_ = sum_ + m * numer / denom term = self.host_eps / (k * R2) return term * sum_ + 0j else: for m in np.arange(1, orders + 1): J0 = special.jv(m, k * R2) H0 = special.hankel1(m, k * R2) JD0 = special.jvp(m, k * R2) HD0 = special.h1vp(m, k * R2) aa1 = self.coeff(m, 'TM') denom = JD0 + HD0 * aa1 + 0j numer = (J0 + H0 * aa1) + 0j sum_ = sum_ + m * numer / denom term = self.host_mu / (k * R2) return term * sum_ + 0j
def cyl_modal_coefs(N, kr, arrayType): """ Modal coefficients for rigid or open cylindrical array Parameters ---------- N : int Maximum spherical harmonic expansion order. kr: ndarray Wavenumber-radius product. Dimension = (l). arrayType: str 'open' or 'rigid'. Returns ------- b_N : ndarray Modal coefficients. Dimension = (l, N+1) Raises ----- TypeError, ValueError: if method arguments mismatch in type, dimension or value. Notes ----- The `arrayType` options are: - 'open' for open array of omnidirectional sensors - 'rigid' for sensors mounted on a rigid baffle. """ _validate_int('N', N) _validate_ndarray_1D('kr', kr, positive=True) _validate_string('arrayType', arrayType, choices=['open', 'rigid']) b_N = np.zeros((kr.size, N + 1), dtype='complex') for n in range(N + 1): if arrayType is 'open': b_N[:, n] = np.power(1j, n) * jv(n, kr) elif arrayType is 'rigid': jn = jv(n, kr) jnprime = jvp(n, kr, 1) hn = hankel2(n, kr) hnprime = h2vp(n, kr, 1) temp = np.power(1j, n) * (jn - (jnprime / hnprime) * hn) temp[np.where(kr == 0)] = 1 if n == 0 else 0. b_N[:, n] = temp return b_N
def linton_evans_coeffs(k, incAng, numCylinders, centres, radii, M): # Four-cylinder problem #if k<=20: # M=40 #elif 20<k<=40: # M=80 #elif 40<k<=60: # M=120 #elif 60<k<=120: # M=180 #elif k>120: # M=300 N = numCylinders origin = centres a = radii i = np.arange(0, N).reshape(-1, 1) j = np.arange(0, N).reshape(1, -1) R = np.sqrt((origin[j, 0] - origin[i, 0])**2 + (origin[j, 1] - origin[i, 1])**2) alpha = np.angle((origin[j, 0] - origin[i, 0]) + 1j * (origin[j, 1] - origin[i, 1])) q = np.repeat(np.arange(N), 2 * M + 1).reshape(-1, 1) # rows p = np.repeat(np.arange(N), 2 * M + 1).reshape(1, -1) # cols m = np.repeat([np.arange(-M, M + 1)], N, axis=0).reshape(-1, 1) # rows n = np.repeat([np.arange(-M, M + 1)], N, axis=0).reshape(1, -1) # cols # Right-hand vector Iq = np.exp( 1j * k * (origin[q, 0] * np.cos(incAng) + origin[q, 1] * np.sin(incAng))) exponential1 = np.exp(1j * m * (np.pi / 2 - incAng)) RHS = -Iq * exponential1 # Left-hand side matrix Znp = jvp(n, k * a[p]) / h1vp(n, k * a[p]) exponential2 = np.exp(1j * (n - m) * alpha[p, q]) Hnm = hankel1(n - m, k * R[p, q]) LHS = Znp * exponential2 * Hnm Identity = np.identity(2 * M + 1) for cyl in range(N): LHS[cyl * (2 * M + 1):(cyl + 1) * (2 * M + 1), cyl * (2 * M + 1):(cyl + 1) * (2 * M + 1)] = Identity # Solve for values of Anq A = np.linalg.solve(LHS, RHS) return A
def fb_1_grad(i, k, x, y, x0=0, y0=0): X = x - x0 Y = y - y0 r = np.sqrt(X**2 + Y**2) angle = np.arctan2(Y, X) idx = i + 1 j = special.jv(idx, k * r) dj = special.jvp(idx, k * r) c = np.cos(idx * angle) s = np.sin(idx * angle) dx = dj * k * X / r * s - j * c * Y / (X**2 + Y**2) * idx dy = dj * k * Y / r * s + j * c * X / (X**2 + Y**2) * idx return dx, dy
def _ehceq(self, neff, wl, nu): u, w = self._uw(wl, neff) v2 = u * u + w * w nco = self.fiber.maxIndex(0, wl) ncl = self.fiber.minIndex(1, wl) delta = (1 - ncl**2 / nco**2) / 2 jnu = jn(nu, u) knu = kn(nu, w) kp = kvp(nu, w) return (jvp(nu, u) * w * knu + kp * u * jnu * (1 - delta) - jnu * sqrt((u * kp * delta)**2 + ((nu * neff * v2 * knu) / (nco * u * w))**2))
def fb_ca_dk(i, k, x, y, nu=1, x0=0, y0=0, phi0=0, sym=None): X = x - x0 Y = y - y0 r = np.sqrt(X**2 + Y**2) #r[r==0] = 1e-16 angle = np.arctan2(Y, X) - phi0 if sym == None: idx = i + 1 if sym == "odd": idx = 2 * i + 1 if sym == "even": idx = 2 * i + 2 s = np.sin(nu * idx * angle) return r * special.jvp(nu * idx, k * r) * s
def eigensystem(b, m, ri, ro): r""" Computes the function associated with the eigensystem of the convected wave equation. The location of the zeros for this function correspond to the eigenvalues for the convected wave equation. The solution to the Bessel equation with boundary conditions applied yields a system of two linear equations. .. math:: A x = \begin{bmatrix} J'_m(\mu \lambda) & Y'_m(\mu \lambda) \\ J'_m(\mu) & Y'_m(\mu) \end{bmatrix} \begin{bmatrix} x_1 \\ x_2 \end{bmatrix} = 0 This procedure evaluates the function .. math:: det(A) = f(b) = J_m(b*ri)*Y_m(b*ro) - J_m(b*ro)*Y_m(b*ri) So, this procedure can be passed to another routine such as numpy to find zeros. Args: b (float): coordinate. m (int): circumferential wave number. ri (float): inner radius of a circular annulus. ro (float): outer radius of a circular annulus. """ f = sp.jvp(m, b * ri) * sp.yvp(m, b * ro) - sp.jvp(m, b * ro) * sp.yvp( m, b * ri) return f
def _ehceq(self, neff, wl, nu): u, w = self._uw(wl, neff) v2 = u*u + w*w nco = self.fiber.maxIndex(0, wl) ncl = self.fiber.minIndex(1, wl) delta = (1 - ncl**2 / nco**2) / 2 jnu = jn(nu, u) knu = kn(nu, w) kp = kvp(nu, w) return (jvp(nu, u) * w * knu + kp * u * jnu * (1 - delta) - jnu * sqrt((u * kp * delta)**2 + ((nu * neff * v2 * knu) / (nco * u * w))**2))
def coeff_int(self, order, polarization, freq_index=None): #if self.frequency == None: # raise Exception("ERROR: Frequency range has not been specified.") # for backward compatibility only mu1 = self.host_mu mu2 = self.cyl_mu if freq_index >= 0: z1 = self.kR_host[freq_index] z2 = self.kR_cyl[freq_index] k0 = self.k0[freq_index] kR_cyl = self.kR_cyl[freq_index] kR_host = self.kR_host[freq_index] else: z1 = self.kR_host z2 = self.kR_cyl k0 = self.k0 kR_cyl = self.kR_cyl kR_host = self.kR_host bn = self.coeff(order, polarization, freq_index) ### POLARIZATION if polarization in ['TE', 'H']: JD1 = special.jvp(order, z1) JD2 = special.jvp(order, z2) HD1 = special.h1vp(order, z1) numer = HD1 * bn + JD1 denom = JD2 return numer / denom elif polarization in ['TM', 'E']: J2 = special.jv(order, z2) J1 = special.jv(order, z1) H1 = special.hankel1(order, z1) numer = H1 * bn + J1 denom = J2 return numer / denom
def JnYn(maxn, resolution): delta = numpy.pi / resolution z_table = numpy.mgrid[min(minz_j(maxn), minz_y(maxn)) : max(maxz_j(maxn), maxz_y(maxn)) : delta] J_table = [] Jdot_table = [] Y_table = [] Ydot_table = [] for n in range(maxn + 1): J_table.append(special.jn(n, z_table)) Jdot_table.append(special.jvp(n, z_table)) Y_table.append(special.yn(n, z_table)) Ydot_table.append(special.yvp(n, z_table)) return z_table, J_table, Jdot_table, Y_table, Ydot_table
def Bescoef(k,r,a,n): """ The calculates the Bessel and Hankel function coef for the incident and scattered wave solution. spec.jv(v,z) - Bessel Func of the first kind of order v spec.jvp(v,z) - first derivative of BF of the first kinda of order v spec.h1vp(v,z) - first derivative of Hankel Func of order v spec.hankel1(v,z) - Hankel func of the first kind of order v """ kr , ka = k*r , k*a coef = -(spec.jvp(n,ka,n=1)/spec.h1vp(n,ka,n=1))*spec.hankel1(n,kr) return coef
def linton_evans_coeffs(k,incAng,numCylinders,centres,radii,M): # Four-cylinder problem #if k<=20: # M=40 #elif 20<k<=40: # M=80 #elif 40<k<=60: # M=120 #elif 60<k<=120: # M=180 #elif k>120: # M=300 N = numCylinders origin = centres a = radii i = np.arange(0,N).reshape(-1,1) j = np.arange(0,N).reshape(1,-1) R = np.sqrt((origin[j,0]-origin[i,0])**2+(origin[j,1]-origin[i,1])**2) alpha = np.angle((origin[j,0]-origin[i,0]) +1j*(origin[j,1]-origin[i,1])) q = np.repeat(np.arange(N),2*M+1).reshape(-1,1) # rows p = np.repeat(np.arange(N),2*M+1).reshape(1,-1) # cols m = np.repeat([np.arange(-M,M+1)],N,axis=0).reshape(-1,1) # rows n = np.repeat([np.arange(-M,M+1)],N,axis=0).reshape(1,-1) # cols # Right-hand vector Iq = np.exp(1j*k*(origin[q,0]*np.cos(incAng)+origin[q,1]*np.sin(incAng))) exponential1 = np.exp(1j*m*(np.pi/2-incAng)) RHS = - Iq * exponential1 # Left-hand side matrix Znp = jvp(n,k*a[p]) / h1vp(n,k*a[p]) exponential2 = np.exp(1j*(n-m)*alpha[p,q]) Hnm = hankel1(n-m,k*R[p,q]) LHS = Znp * exponential2 * Hnm Identity = np.identity(2*M+1) for cyl in range(N): LHS[cyl*(2*M+1):(cyl+1)*(2*M+1),cyl*(2*M+1):(cyl+1)*(2*M+1)] = Identity # Solve for values of Anq A=np.linalg.solve(LHS,RHS) return A
def _hefield(self, wl, nu, neff, r): rho = self.fiber.outerRadius(0) k = wl.k0 nco2 = self.fiber.maxIndex(0, wl)**2 ncl2 = self.fiber.minIndex(1, wl)**2 u = rho * k * sqrt(nco2 - neff**2) w = rho * k * sqrt(neff**2 - ncl2) v = rho * k * sqrt(nco2 - ncl2) jnu = jn(nu, u) knw = kn(nu, w) Delta = (1 - ncl2/nco2)/2 b1 = jvp(nu, u) / (u * jnu) b2 = kvp(nu, w) / (w * knw) F1 = (u * w / v)**2 * (b1 + (1 - 2 * Delta)*b2) / nu F2 = (v / (u * w))**2 * nu / (b1 + b2) a1 = (F2 - 1) / 2 a2 = (F2 + 1) / 2 a3 = (F1 - 1) / 2 a4 = (F1 + 1) / 2 a5 = (F1 - 1 + 2 * Delta) / 2 a6 = (F1 + 1 - 2 * Delta) / 2 if r < rho: jmur = jn(nu-1, u * r / rho) jpur = jn(nu+1, u * r / rho) jnur = jn(nu, u * r / rho) er = -(a1 * jmur + a2 * jpur) / jnu ephi = -(a1 * jmur - a2 * jpur) / jnu ez = u / (k * neff * rho) * jnur / jnu hr = Y0 * nco2 / neff * (a3 * jmur - a4 * jpur) / jnu hphi = -Y0 * nco2 / neff * (a3 * jmur + a4 * jpur) / jnu hz = Y0 * u * F2 / (k * rho) * jnur / jnu else: kmur = kn(nu-1, w * r / rho) kpur = kn(nu+1, w * r / rho) knur = kn(nu, w * r / rho) er = -u / w * (a1 * kmur - a2 * kpur) / knw ephi = -u / w * (a1 * kmur + a2 * kpur) / knw ez = u / (k * neff * rho) * knur / knw hr = Y0 * nco2 / neff * u / w * (a5 * kmur + a6 * kpur) / knw hphi = -Y0 * nco2 / neff * u / w * (a5 * kmur - a6 * kpur) / knw hz = Y0 * u * F2 / (k * rho) * knur / knw return numpy.array((er, ephi, ez)), numpy.array((hr, hphi, hz))
def coef(self, h, w, alpha): """Return the coefficients of TE- and TM- components which compose the hybrid mode. Args: h: A complex indicating the phase constant. w: A complex indicating the angular frequency alpha: A tuple (pol, n, m) where pol is 'M' for TM-like mode or 'E' for TE-like mode, n is the order of the mode, and m is the number of modes in the order and the polarization. Returns: a: A complex indicating the coefficient of TE-component b: A complex indicating the coefficient of TM-component """ e1 = self.fill(w) e2 = self.clad(w) pol, n, m = alpha w = w.real + 1j * w.imag h = h.real + 1j * h.imag if e2.real < -1e6: if pol == 'E': norm = self.norm(w, h, alpha, 1.0 + 0.0j, 0.0j) ai, bi = 1.0 / norm, 0.0 else: norm = self.norm(w, h, alpha, 0.0j, 1.0 + 0.0j) ai, bi = 0.0, 1.0 / norm else: u = self.samples.u(h**2, w, e1) v = self.samples.v(h**2, w, e2) knv = kv(n, v) knpv = kvp(n, v) jnu = jv(n, u) jnpu = jvp(n, u) ci = -n * (u**2 + v**2) * jnu * knv / (u * v) if pol == 'E': ci *= (h / w)**2 ci /= (e1 * jnpu * v * knv + e2 * knpv * u * jnu) norm = self.norm(w, h, alpha, 1.0 + 0.0j, ci) ai = 1.0 / norm bi = ci / norm else: ci /= (jnpu * v * knv + knpv * u * jnu) norm = self.norm(w, h, alpha, ci, 1.0 + 0.0j) bi = 1.0 / norm ai = ci / norm return ai, bi
def _hefield(self, wl, nu, neff, r): rho = self.fiber.outerRadius(0) k = wl.k0 nco2 = self.fiber.maxIndex(0, wl)**2 ncl2 = self.fiber.minIndex(1, wl)**2 u = rho * k * sqrt(nco2 - neff**2) w = rho * k * sqrt(neff**2 - ncl2) v = rho * k * sqrt(nco2 - ncl2) jnu = jn(nu, u) knw = kn(nu, w) Delta = (1 - ncl2 / nco2) / 2 b1 = jvp(nu, u) / (u * jnu) b2 = kvp(nu, w) / (w * knw) F1 = (u * w / v)**2 * (b1 + (1 - 2 * Delta) * b2) / nu F2 = (v / (u * w))**2 * nu / (b1 + b2) a1 = (F2 - 1) / 2 a2 = (F2 + 1) / 2 a3 = (F1 - 1) / 2 a4 = (F1 + 1) / 2 a5 = (F1 - 1 + 2 * Delta) / 2 a6 = (F1 + 1 - 2 * Delta) / 2 if r < rho: jmur = jn(nu - 1, u * r / rho) jpur = jn(nu + 1, u * r / rho) jnur = jn(nu, u * r / rho) er = -(a1 * jmur + a2 * jpur) / jnu ephi = -(a1 * jmur - a2 * jpur) / jnu ez = u / (k * neff * rho) * jnur / jnu hr = Y0 * nco2 / neff * (a3 * jmur - a4 * jpur) / jnu hphi = -Y0 * nco2 / neff * (a3 * jmur + a4 * jpur) / jnu hz = Y0 * u * F2 / (k * rho) * jnur / jnu else: kmur = kn(nu - 1, w * r / rho) kpur = kn(nu + 1, w * r / rho) knur = kn(nu, w * r / rho) er = -u / w * (a1 * kmur - a2 * kpur) / knw ephi = -u / w * (a1 * kmur + a2 * kpur) / knw ez = u / (k * neff * rho) * knur / knw hr = Y0 * nco2 / neff * u / w * (a5 * kmur + a6 * kpur) / knw hphi = -Y0 * nco2 / neff * u / w * (a5 * kmur - a6 * kpur) / knw hz = Y0 * u * F2 / (k * rho) * knur / knw return numpy.array((er, ephi, ez)), numpy.array((hr, hphi, hz))
def JnYn(maxn, resolution): delta = numpy.pi / resolution z_table = numpy.mgrid[min(minz_j(maxn),minz_y(maxn)): max(maxz_j(maxn), maxz_y(maxn)):delta] J_table = [] Jdot_table = [] Y_table = [] Ydot_table = [] for n in range(maxn+1): J_table.append(special.jn(n, z_table)) Jdot_table.append(special.jvp(n, z_table)) Y_table.append(special.yn(n, z_table)) Ydot_table.append(special.yvp(n, z_table)) return z_table, J_table, Jdot_table, Y_table, Ydot_table
def calc_bessel(x, y, radius, gradr=False): rho = (x**2 + y**2)**0.5 zero = special.jn_zeros(0, 1) # See RT2 p75 for derivation norm_fac = np.pi**0.5*special.jv(1, zero)*radius z = rho*zero/radius in_beam = rho <= radius E = pyfftw.byte_align(special.jv(0, z)*in_beam/norm_fac) if gradr: gradrhoE = special.jvp(0, z, 1)*in_beam/norm_fac*zero/radius gradxE = pyfftw.byte_align(mathx.divide0(gradrhoE*x, rho)) gradyE = pyfftw.byte_align(mathx.divide0(gradrhoE*y, rho)) return E, (gradxE, gradyE) else: return E
def jac(self, h2, args): """Return Jacobian of the characteristic equation Args: h2: A complex indicating the square of the phase constant. args: A tuple (w, n, e1, e2), where w indicates the angular frequency, n indicates the order of the modes, e1 indicates the permittivity of the core, and e2 indicates the permittivity of the clad. Returns: val: A complex indicating the Jacobian of the characteristic equation. """ w, pol, n, e1, e2 = args h2comp = h2.real + 1j * h2.imag u = self.u(h2comp, w, e1) v = self.v(h2comp, w, e2) jus = jv(n, u) jpus = jvp(n, u) kvs = kv(n, v) kpvs = kvp(n, v) du_dh2 = -self.r / (2 * u) dv_dh2 = self.r / (2 * v) te = jpus / u + kpvs * jus / (v * kvs) dte_du = (-(u * (1 - n**2 / u**2) * jus + 2 * jpus) / u**2 + jpus * kpvs / (v * kvs)) dte_dv = jus * (n**2 * kvs**2 / v + v * (kvs**2 - kpvs**2) - 2 * kvs * kpvs) / (v**2 * kvs**2) tm = e1 * jpus / u + e2 * kpvs * jus / (v * kvs) dtm_du = e1 * dte_du dtm_dv = e2 * dte_dv if n == 0: if pol == 'M': val = dtm_du * du_dh2 + dtm_dv * dv_dh2 else: val = dte_du * du_dh2 + dte_dv * dv_dh2 else: dre_dh2 = -(n / w)**2 * jus * (jus * ( (1 / u**2 + 1 / v**2)**2 - self.r * h2comp * (1 / u**4 - 1 / v**4)) + jpus * 2 * h2comp * (1 / u**2 + 1 / v**2)**2) val = ((dte_du * du_dh2 + dte_dv * dv_dh2) * tm + (dtm_du * du_dh2 + dtm_dv * dv_dh2) * te + dre_dh2) return val
def func_jac(self, h2, *args): """Return the value and Jacobian of the characteristic equation Args: h2: A complex indicating the square of the phase constant. Returns: val: 2 complexes indicating the left-hand value and Jacobian of the characteristic equation. """ w, pol, n, e1, e2 = args h2comp = h2.real + 1j * h2.imag u = self.u(h2comp, w, e1) v = self.v(h2comp, w, e2) jus = jv(n, u) jpus = jvp(n, u) kvs = kv(n, v) kpvs = kvp(n, v) du_dh2 = -self.r / (2 * u) dv_dh2 = self.r / (2 * v) te = jpus / u + kpvs * jus / (v * kvs) dte_du = (-(u * (1 - n**2 / u**2) * jus + 2 * jpus) / u**2 + jpus * kpvs / (v * kvs)) dte_dv = jus * (n**2 * kvs**2 / v + v * (kvs**2 - kpvs**2) - 2 * kvs * kpvs) / (v**2 * kvs**2) tm = e1 * jpus / u + e2 * kpvs * jus / (v * kvs) dtm_du = e1 * dte_du dtm_dv = e2 * dte_dv if n == 0: if pol == 'M': f = tm val = dtm_du * du_dh2 + dtm_dv * dv_dh2 else: f = te val = dte_du * du_dh2 + dte_dv * dv_dh2 else: f = (tm * te - h2comp * (n / w)**2 * ((1 / u**2 + 1 / v**2) * jus)**2) dre_dh2 = -(n / w)**2 * jus * (jus * ( (1 / u**2 + 1 / v**2)**2 - self.r * h2comp * (1 / u**4 - 1 / v**4)) + jpus * 2 * h2comp * (1 / u**2 + 1 / v**2)**2) val = ((dte_du * du_dh2 + dte_dv * dv_dh2) * tm + (dtm_du * du_dh2 + dtm_dv * dv_dh2) * te + dre_dh2) return f, val
def fb_ca_grad(i, k, x, y, nu=1, x0=0, y0=0, phi0=0, sym=None): X = x - x0 Y = y - y0 r = np.sqrt(X**2 + Y**2) #r[r==0] = 1e-16 angle = np.arctan2(Y, X) - phi0 if sym == None: idx = i + 1 if sym == "odd": idx = 2 * i + 1 if sym == "even": idx = 2 * i + 2 j = special.jv(idx * nu, k * r) dj = special.jvp(idx * nu, k * r) c = np.cos(nu * idx * angle) s = np.sin(nu * idx * angle) dx = dj * k * X / r * s - j * c * Y / (X**2 + Y**2) * nu * idx dy = dj * k * Y / r * s + j * c * X / (X**2 + Y**2) * nu * idx return dx, dy
def Y(self, w, h, alpha, a, b): """Return the effective admittance of the waveguide mode Args: w: A complex indicating the angular frequency h: A complex indicating the phase constant. alpha: A tuple (pol, n, m) where pol is 'M' for TM-like mode or 'E' for TE-like mode, n is the order of the mode, and m is the number of modes in the order and the polarization. a: A complex indicating the coefficient of TE-component b: A complex indicating the coefficient of TM-component Returns: y: A complex indicating the effective admittance """ pol, n, m = alpha e1 = self.fill(w) e2 = self.clad(w) en = 1 if n == 0 else 2 if e2.real < -1e6: if pol == 'E': val = h / w else: val = e1 * w / h else: u = self.samples.u(h**2, w, e1) jnu = jv(n, u) jnpu = jvp(n, u) v = self.samples.v(h**2, w, e2) knv = kv(n, v) knpv = kvp(n, v) val_u = 2 * np.pi * self.r**2 / en val_v = val_u * ((u * jnu) / (v * knv))**2 upart_diag = self.upart_diag(n, u, jnu, jnpu, u, jnu, jnpu) vpart_diag = self.vpart_diag(n, v, knv, knpv, v, knv, knpv) upart_off = self.upart_off(n, u, jnu, u, jnu) vpart_off = self.vpart_off(n, v, knv, v, knv) val = (val_u * (h / w * a * (a * upart_diag + b * upart_off) + e1 * w / h * b * (b * upart_diag + a * upart_off)) - val_v * (h / w * a * (a * vpart_diag + b * vpart_off) + e2 * w / h * b * (b * vpart_diag + a * vpart_off))) return val
def vConstants(self, ri, ro, neff, wl, nu, EH): a = numpy.zeros((4, 4)) n = self.maxIndex(wl) u = self.u(ro, neff, wl) urp = self.u(ri, neff, wl) if neff < n: B1 = jn(nu, u) B2 = yn(nu, u) F1 = jn(nu, urp) / B1 F2 = yn(nu, urp) / B2 F3 = jvp(nu, urp) / B1 F4 = yvp(nu, urp) / B2 c1 = wl.k0 * ro / u else: B1 = iv(nu, u) B2 = kn(nu, u) F1 = iv(nu, urp) / B1 if u else 1 F2 = kn(nu, urp) / B2 F3 = ivp(nu, urp) / B1 if u else 1 F4 = kvp(nu, urp) / B2 c1 = -wl.k0 * ro / u c2 = neff * nu / urp * c1 c3 = constants.eta0 * c1 c4 = constants.Y0 * n * n * c1 a[0, 0] = F1 a[0, 1] = F2 a[1, 2] = F1 a[1, 3] = F2 a[2, 0] = F1 * c2 a[2, 1] = F2 * c2 a[2, 2] = -F3 * c3 a[2, 3] = -F4 * c3 a[3, 0] = F3 * c4 a[3, 1] = F4 * c4 a[3, 2] = -F1 * c2 a[3, 3] = -F2 * c2 return numpy.linalg.solve(a, EH)
def _tmfield(self, wl, nu, neff, r): N = len(self.fiber) C = numpy.array((1, 0)) EH = numpy.zeros(4) ri = 0 for i in range(N-1): ro = self.fiber.outerRadius(i) layer = self.fiber.layers[i] n = layer.maxIndex(wl) u = layer.u(ro, neff, wl) if i > 0: C = layer.tetmConstants(ri, ro, neff, wl, EH, constants.Y0 * n * n, (0, 3)) if r < ro: break if neff < n: c1 = wl.k0 * ro / u F3 = jvp(nu, u) / jn(nu, u) F4 = yvp(nu, u) / yn(nu, u) else: c1 = -wl.k0 * ro / u F3 = ivp(nu, u) / iv(nu, u) F4 = kvp(nu, u) / kn(nu, u) c4 = constants.Y0 * n * n * c1 EH[0] = C[0] + C[1] EH[3] = c4 * (F3 * C[0] + F4 * C[1]) ri = ro else: layer = self.fiber.layers[-1] u = layer.u(ro, neff, wl) # C = return numpy.array((0, ephi, 0)), numpy.array((hr, 0, hz))
def eval_d_u_outwards(self, arg, sid): # Debug function # Only for true arc. At least at the moment k = self.k R = self.R a = self.a nu = self.nu r, th = domain_util.arg_to_polar_abs(self.boundary, a, arg, sid) d_u = 0 for m in range(1, self.m_max+1): ac = self.fft_a_coef[m-1] if sid == 0: d_u += ac * k * jvp(m*nu, k*r, 1) * np.sin(m*nu*(th-a)) elif sid == 1: d_u += ac * jv(m*nu, k*r) * m * nu * np.cos(m*nu*(th-a)) elif sid == 2: d_u += -ac * jv(m*nu, k*r) * m * nu * np.cos(m*nu*(th-a)) return d_u
def cylinder(wavenumber,xPlotPoints,yPlotPoints,radius=1.0): """ Analytical potential on hard cylinder with [1,0] incident wave (Jones)""" x = xPlotPoints y = yPlotPoints theta = np.arctan2(y,x) numPoints = len(x) nans=False,False N = 100 while any(nans)==False: N += 50 n = np.arange(0,N) neumann = 2*np.ones(N); neumann[0]=1 dJ = jvp(n,wavenumber*radius,1) H1 = hankel1(n,wavenumber*radius) dH1 = h1vp(n,wavenumber*radius,1) nans = np.isnan(dJ) + np.isnan(H1) + np.isnan(dH1) dJ = dJ.compress(np.logical_not(nans)) H1 = H1.compress(np.logical_not(nans)) dH1 = dH1.compress(np.logical_not(nans)) neumann = neumann.compress(np.logical_not(nans)) n = n.compress(np.logical_not(nans)) total = (-neumann * (1j**n) * dJ * H1 / dH1).reshape(-1,1) cosines = np.cos(n.reshape(-1,1)*theta) total = total * cosines incPotential = np.exp(1j*wavenumber*x).reshape(numPoints) fullPotential = np.sum(total,axis=0) + incPotential return fullPotential
def z(self,x): 'Z(x) equation that keeps showing up in waveguide modes' m, n, chi = self.m, self.n, self.root return yvp(m,chi,1)*jn(m,x)-jvp(m,chi,1)*yn(m,x)
def rJnp(r,n): return (0.5*sqrt(pi/(2*r))*jv(n+0.5,r) + sqrt(pi*r/2)*jvp(n+0.5,r))
def root_equation(self,m,c,x): '''Radial root equation of Phi for TE mode''' return yvp(m,x,1)*jvp(m,c*x,1)-jvp(m,x,1)*yvp(m,c*x,1)
def rfnd(self, n, x, d): return ss.jvp(n,x,d)
def E_theta(self, r, theta, z): return -(jvp(self.l,k1*r,1])/k1) * np.cos(self.l* theta)*np.sin(k3*z)
if __name__ == '__main__': mesh = [25, 50, 100, 200, 300,500,1000,2000] convergence = np.zeros((0,2)) for nPoints in mesh: y = homoCircle(nPoints, 1.0, 2.0, 1.0, 1.0, 1) scatMat = y.computeScatteringMatrix(y.Mmax) analScatMat = np.zeros(2*y.Mmax+1, dtype=complex) zc = y.nc*y.k zo = y.no*y.k eta = y.nc/y.no for i in range(2*y.Mmax+1): m = i-y.Mmax num = -(eta*jvp(m,zc)*hankel2(m,zo)-jn(m,zc)*h2vp(m,zo)) den = eta*jvp(m,zc)*hankel1(m,zo)-jn(m,zc)*h1vp(m,zo) analScatMat[i] = num/den err = np.amax(np.abs(np.diag(analScatMat)-scatMat)) print(err) print(analScatMat) # -- Mean areas of triangles convergence = np.insert(convergence, len(convergence), [np.mean(y.areas), err],axis=0) fig1 = plt.figure(figsize=(5,3)) ax1 = fig1.add_subplot(111) plt.plot(convergence[:,0],convergence[:,1], ls='--', marker='o', label=r"Numerical Error") p = np.polyfit(np.log(convergence[:,0]),np.log(convergence[:,1]),1) ynew = np.exp(np.polyval(p,np.log(convergence[:,0])))
def coeq(v0, nu, fiber): r1, r2 = fiber.rho n1, n2, n3 = fiber.n na = sqrt(max(fiber.n)**2 - n3**2) K0 = v0 / (na * r2) beta = K0 * n3 if n1 > n3: u1 = K0**2 * (n1**2 - n3**2) s1 = 1 else: u1 = K0**2 * (n3**2 - n1**2) s1 = -1 if n2 > n3: u2 = K0**2 * (n2**2 - n3**2) s2 = 1 else: u2 = K0**2 * (n3**2 - n2**2) s2 = -1 s = -s1 * s2 u1r1 = u1 * r1 u2r1 = u2 * r1 u2r2 = u2 * r2 X = (u2r1**2 + s * u1r1**2) * nu * beta if s1 == 1: Y = jvp(nu, u1r1) / jn(nu, u1r1) else: Y = ivp(nu, u1r1) / iv(nu, u1r1) ju2r1 = jn(nu, u2r1) if s2 == 1 else iv(nu, u2r1) nu2r1 = yn(nu, u2r1) if s2 == 1 else kn(nu, u2r1) jpu2r1 = jvp(nu, u2r1) if s2 == 1 else ivp(nu, u2r1) npu2r1 = yvp(nu, u2r1) if s2 == 1 else kvp(nu, u2r1) ju2r2 = jn(nu, u2r2) if s2 == 1 else iv(nu, u2r2) nu2r2 = yn(nu, u2r2) if s2 == 1 else kn(nu, u2r2) j1u2r2 = jn(nu+1, u2r2) n1u2r2 = yn(nu+1, u2r2) M = numpy.empty((4, 4)) M[0, 0] = X * ju2r1 M[0, 1] = X * nu2r1 M[0, 2] = -K0 * (jpu2r1 * u1r1 + s * Y * ju2r1 * u2r1) * u1r1 * u2r1 M[0, 3] = -K0 * (npu2r1 * u1r1 + s * Y * nu2r1 * u2r1) * u1r1 * u2r1 M[1, 0] = -K0 * (n2**2 * jpu2r1 * u1r1 + s * n1**2 * Y * ju2r1 * u2r1) * u1r1 * u2r1 M[1, 1] = -K0 * (n2**2 * npu2r1 * u1r1 + s * n1**2 * Y * nu2r1 * u2r1) * u1r1 * u2r1 M[1, 2] = X * ju2r1 M[1, 3] = X * nu2r1 D201 = nu * n3 / u2r2 * (j1u2r2 * nu2r2 - ju2r2 * yn(nu+1, u2r2)) D202 = -((n2**2 + n3**2) * nu * n1u2r2 * nu2r2 / u2r2 + n3**2 * nu * nu2r2**2 / (nu - 1)) D203 = -(n2**2 * nu * ju2r2 * n1u2r2 / u2r2 + n3**2 * nu * nu2r2 * j1u2r2 / u2r2 + n3**2 * nu * (j1u2r2 * nu2r2 + n1u2r2 * ju2r2) / (2 * (nu - 1))) D212 = -(n2**2 * nu * nu2r2 * j1u2r2 / u2r2 + n3**2 * nu * ju2r2 * n1u2r2 / u2r2 + n3**2 * nu * (n1u2r2 * ju2r2 + j1u2r2 * nu2r2) / (2 * (nu - 1))) D213 = -((n2**2 + n3**2) * nu * j1u2r2 * ju2r2 / u2r2 + n3**2 * nu * ju2r2**2 / (nu - 1)) D223 = nu * n2**2 * n3 / u2r2 * (j1u2r2 * nu2r2 - ju2r2 * n1u2r2) D30 = M[1, 1] * D201 - M[1, 2] * D202 + M[1, 3] * D203 D31 = M[1, 0] * D201 - M[1, 2] * D212 + M[1, 3] * D213 D32 = M[1, 0] * D202 - M[1, 1] * D212 + M[1, 3] * D223 D33 = M[1, 0] * D203 - M[1, 1] * D213 + M[1, 2] * D223 return M[0, 0] * D30 - M[0, 1] * D31 + M[0, 2] * D32 - M[0, 3] * D33
def z_dash(self,x): ''' Z'(x) equation for waveguide mode ''' m, n, chi = self.m, self.n, self.root # jvp(m,x,r) is the rth derivative of the bessel function of order m evaluated at x return yn(m,chi)*jvp(m,x,1)-jn(m,chi)*yvp(m,x,1)
def timeDelayEigenfunctionIm(r,m,nc,k): eps2 = np.imag(nc*nc) return np.imag(-1j*k*eps2*2.0*np.pi*r*r*np.conj(jn(m,nc*k*r))*jvp(m,nc*k*r))
def sMatrixElementCoefficients(k,n1,n2,m): A = -n1*hankel2(m,n2*k)*jvp(m,n1*k)+n2*jn(m,n1*k)*h2vp(m,n2*k) B = n1*hankel1(m,n2*k)*jvp(m,n1*k)-n2*jn(m,n1*k)*h1vp(m,n2*k) Ap = -n1*n1*jvp(m,n1*k,2)*hankel2(m,n2*k)+n2*n2*jn(m,n1*k)*h2vp(m,n2*k,2) Bp = n1*n1*jvp(m,n1*k,2)*hankel1(m,n2*k)-n2*n2*jn(m,n1*k)*h1vp(m,n2*k,2) return A, B, Ap, Bp