def psi_x(z, x, beta): """ Eq.(24) from Ref[1] with argument zeta=0 and no constant factor e*beta**2/2/rho**2. Note that 'x' here corresponds to 'chi = x/rho', and 'z' here corresponds to 'xi = z/2/rho' in the paper. """ # z = np.float(z) # x = np.float(x) kap = kappa(z, x, beta) alp = alpha(z, x, beta) arg2 = -4 * (1 + x) / x**2 try: T1 = (1 / abs(x) / (1 + x) * ((2 + 2 * x + x**2) * ss.ellipkinc(alp, arg2) - x**2 * ss.ellipeinc(alp, arg2))) D = kap**2 - beta**2 * (1 + x)**2 * sin(2 * alp)**2 T2 = ((kap**2 - 2 * beta**2 * (1 + x)**2 + beta**2 * (1 + x) * (2 + 2 * x + x**2) * cos(2 * alp)) / beta / (1 + x) / D) T3 = -kap * sin(2 * alp) / D T4 = kap * beta**2 * (1 + x) * sin(2 * alp) * cos(2 * alp) / D T5 = 1 / abs(x) * ss.ellipkinc(alp, arg2) # psi_phi without e/rho**2 factor out = real((T1 + T2 + T3 + T4) - 2 / beta**2 * T5) except ZeroDivisionError: out = 0 # print(f"Oops! ZeroDivisionError at (z,x)= ({z:5.2f},{x:5.2f}). Returning 0.") return np.nan_to_num(out)
def d2q_conformal(z): """Conformal map from the unit disk to the standard square""" diskp = z * (1 + 1j) / np.sqrt(2) up = diskp.real vp = diskp.imag A = up**2 + vp**2 B = up**2 - vp**2 T = np.sqrt((1 + A**2)**2 - 4 * B**2) U = 1 + 2 * B - A**2 alpha = np.arccos(np.clip((2 * A - T) / U, -1, 1)) beta = np.arccos(np.clip(U / (2 * A + T), -1, 1)) xp = np.sign(up) * (2 * K - ellipkinc(alpha, 1 / 2)) yp = np.sign(vp) * ellipkinc(beta, 1 / 2) return (xp + 1j * yp) * (1 - 1j) / 2 / K
def ellippi(n, m): """ Complete elliptic integral of third kind (simplified version). .. FIXME: Incorrect, because of non-standard definitions of elliptic integral in the reference Reference --------- F. LAMARCHE and C. LEROY, Evaluation of the volume of a sphere with a cylinder by elliptic integrals, Computer Phys. Comm. 59 (1990) pg. 365 """ a2 = n k2 = m k2_a2 = k2 + a2 phi = np.arcsin(a2 / k2_a2) Kc = ellipk(k2) Ec = ellipe(k2) Ki = ellipkinc(phi, (1. - k2) ** 1) Ei = ellipeinc(phi, (1. - k2) ** 1) c1 = k2 / k2_a2 c2 = np.sqrt(a2 / (1 + a2) / k2_a2) return c1 * Kc + c2 * ((Kc - Ec) * Ki + Kc * Ei)
def ellippi(n, m): """ Complete elliptic integral of third kind (simplified version). .. FIXME: Incorrect, because of non-standard definitions of elliptic integral in the reference Reference --------- F. LAMARCHE and C. LEROY, Evaluation of the volume of a sphere with a cylinder by elliptic integrals, Computer Phys. Comm. 59 (1990) pg. 365 """ a2 = n k2 = m k2_a2 = k2 + a2 phi = np.arcsin(a2 / k2_a2) Kc = ellipk(k2) Ec = ellipe(k2) Ki = ellipkinc(phi, (1. - k2)**1) Ei = ellipeinc(phi, (1. - k2)**1) c1 = k2 / k2_a2 c2 = np.sqrt(a2 / (1 + a2) / k2_a2) return c1 * Kc + c2 * ((Kc - Ec) * Ki + Kc * Ei)
def _E_F_field(ellipsoid, kappa, phi): ''' Calculates the Legendre's normal elliptic integrals of first and second kinds which are used to calculate the potential fields outside the triaxial ellipsoid. Parameters: * ellipsoid : element of :class:`mesher.TriaxialEllipsoid`. * lamb: numpy array 1D Parameter lambda for each point in the ellipsoid system. * kappa: numpy array 1D Squared modulus of the elliptic integral. * phi: numpy array 1D Amplitude of the elliptic integral. Returns: F, E: numpy arrays 1D Legendre's normal elliptic integrals of first and second kinds. ''' E = ellipeinc(phi, kappa) F = ellipkinc(phi, kappa) return E, F
def ellipsoid_shape_func(a, b, c): phi = np.arccos(c/a) m = (a**2.-b**2.)/(a**2.-c**2.) la = a*b*c/((a**2.-b**2.)*np.sqrt(a**2.-c**2.))*(ellipkinc(phi,m)-ellipeinc(phi,m)) lc = b/(b**2.-c**2.)*(b-a*c/np.sqrt(a**2.-c**2.)*ellipeinc(phi,m)) lb = 1.-la-lc return la, lb, lc
def _E_F_field(a, b, c, kappa, phi): ''' Calculates the Legendre's normal elliptic integrals of first and second kinds which are used to calculate the potential fields outside the body. input: a: float - semi-axis a (in meters). b: float - semi-axis b (in meters). c: float - semi-axis c (in meters). kappa: float - an argument of the elliptic integrals. phi: numpy array 1D - an argument of the elliptic integrals. output: F: numpy array 1D - Legendre's normal elliptic integrals of first kind. E: numpy array 1D - Legendre's normal elliptic integrals of second kind. ''' assert a > b > c, 'a must be greater than b and b must be greater than c' assert (a > 0) and (b > 0) and (c > 0), 'a, b and c must \ be all positive' E = ellipeinc(phi, kappa * kappa) F = ellipkinc(phi, kappa * kappa) return E, F
def Int3(q, r, R): ''' Integral I3. ''' m = 4 * R * r / (q**2 + (r + R)**2) K0 = ellipk(m) # Complete elliptic integral of the first kind K1 = ellipk(1 - m) E0 = ellipe(m) # Complete elliptic integral of the second kind E1 = ellipe(1 - m) beta = np.arcsin(q / np.sqrt(q**2 + (R - r)**2)) K2 = ellipkinc(beta, 1 - m) # Incomplete elliptic integral of the first kind E2 = ellipeinc(beta, 1 - m) # Incomplete elliptic integral of the second kind Z = E2 - E1 * K2 / K1 # Jacobi zeta function lamb = K2 / K1 + 2 * K0 * Z / np.pi # Heuman’s lambda function I3 = -q * np.sqrt(m) * K0 / (2 * np.pi * R * np.sqrt(r * R)) + ( np.heaviside(r - R, 0.5) - np.heaviside(R - r, 0.5)) * lamb / ( 2 * R) + np.heaviside(R - r, 0.5) / R return I3
def psi_sx(z, x, beta): """ 2D longitudinal and transverse potential Eq. (23) from Ref[1] with no constant factor (e*beta**2/2/rho**2). Eq.(24) from Ref[1] with argument zeta=0 and no constant factor e*beta**2/2/rho**2. Note that 'x' here corresponds to 'chi = x/rho', and 'z' here corresponds to 'xi = z/2/rho' in the paper. This is the most efficient routine. Parameters ---------- z : array-like z/(2*rho) x : array-like x/rho beta : float Relativistic beta Returns ------- psi_s, psi_x : tuple(ndarray, ndarray) """ # beta**2 appears far more than beta. Use this in internal functions beta2 = beta**2 alp = alpha(z, x, beta2) kap = sqrt(x**2 + 4 * (1 + x) * sin(alp)**2) # kappa(z, x, beta2) inline sin2a = sin(2 * alp) cos2a = cos(2 * alp) # psi_s calc out_psi_s = (cos2a - 1 / (1 + x)) / (kap - beta * (1 + x) * sin2a) # psi_x calc arg2 = -4 * (1 + x) / x**2 ellipeinc = ss.ellipeinc(alp, arg2) ellipkinc = ss.ellipkinc(alp, arg2) T1 = (1 / abs(x) / (1 + x) * ((2 + 2 * x + x**2) * ellipkinc - x**2 * ellipeinc)) D = kap**2 - beta2 * (1 + x)**2 * sin2a**2 T2 = ((kap**2 - 2 * beta2 * (1 + x)**2 + beta2 * (1 + x) * (2 + 2 * x + x**2) * cos2a) / beta / (1 + x) / D) T3 = -kap * sin2a / D T4 = kap * beta2 * (1 + x) * sin2a * cos2a / D T5 = 1 / abs(x) * ellipkinc # psi_phi without e/rho**2 factor out_psi_x = (T1 + T2 + T3 + T4) - 2 / beta2 * T5 return out_psi_s, out_psi_x
def integrand(m, x, y, z, xi, alpha, host): lmbda = calculate_lambda(m, x, y, z, host) s2, m2, q2 = host.s * host.s, m * m, host.q * host.q rad = radius(x, y, z, host) return m**(1 - alpha) / ((1 + m * xi)**(3 - alpha)) * ellipkinc( np.sqrt((1 - s2) / (1 + lmbda / (m2 * rad * rad))), np.sqrt((1 - q2) / (1 - s2)))
def _E_F_demag(a, b, c): ''' Calculates the Legendre's normal elliptic integrals of first and second kinds which are used to calculate the demagnetizing factors. input: a: float - semi-axis a (in meters). b: float - semi-axis b (in meters). c: float - semi-axis c (in meters). output: F - Legendre's normal elliptic integrals of first kind. E - Legendre's normal elliptic integrals of second kind. ''' assert a > b > c, 'a must be greater than b and b must be greater than c' assert (a > 0) and (b > 0) and (c > 0), 'a, b and c must \ be all positive' kappa = np.sqrt(((a * a - b * b) / (a * a - c * c))) phi = np.arccos(c / a) E = ellipeinc(phi, kappa * kappa) F = ellipkinc(phi, kappa * kappa) return E, F
def old_psi_x(z, x, beta): """ Eq.(24) from Ref[1] with argument zeta=0 and no constant factor e*beta**2/2/rho**2. Note that 'x' here corresponds to 'chi = x/rho', and 'z' here corresponds to 'xi = z/2/rho' in the paper. """ beta2 = beta**2 alp = old_alpha(z, x, beta2) kap = sqrt(x**2 + 4*(1+x) * sin(alp)**2) # kappa(z, x, beta2) inline sin2a = sin(2*alp) cos2a = cos(2*alp) arg2 = -4 * (1+x) / x**2 ellipkinc = ss.ellipkinc(alp, arg2) ellipeinc = ss.ellipeinc(alp, arg2) T1 = (1/abs(x)/(1 + x) * ((2 + 2*x + x**2) * ellipkinc - x**2 * ellipeinc)) D = kap**2 - beta2 * (1 + x)**2 * sin2a**2 T2 = ((kap**2 - 2*beta2 * (1+x)**2 + beta2 * (1+x) * (2 + 2*x + x**2) * cos2a)/ beta/ (1+x)/ D) T3 = -kap * sin2a / D T4 = kap * beta2 * (1 + x) * sin2a * cos2a / D T5 = 1 / abs(x) * ellipkinc # psi_phi without e/rho**2 factor out = (T1 + T2 + T3 + T4) - 2 / beta2 * T5 return out
def demagEllipsoid(length, width, height, cgs=False): '''Returns the demag factors of an ellipsoid''' a = 0.5 * length # Semimajor b = 0.5 * width # Semiminor c = 0.5 * height # Semi-more-minor b1 = b / a b2 = np.sqrt(1.0 - b1 * b1) c1 = c / a c2 = np.sqrt(1.0 - c1 * c1) d2 = b2 / c2 d1 = np.sqrt(1.0 - d2 * d2) theta = np.arccos(c1) m = d2 * d2 E = special.ellipeinc(theta, m) # incomplete elliptic int of second kind F = special.ellipkinc(theta, m) # incomplete elliptic int of first kind Nxx = (b1 * c1) / (c2**3 * d2**2) * (F - E) Nyy = (b1 * c1) / (c2**3 * d2**2 * d1**2) * (E - d1 * d1 * F - d2 * d2 * c2 * c1 / b1) Nzz = (b1 * c1) / (c2**3 * d1**2) * (c2 * b1 / c1 - E) if cgs: return np.pi * 4.0 * np.array([Nxx, Nyy, Nzz]) else: return np.array([Nxx, Nyy, Nzz])
def _E_F_demag(ellipsoid): ''' Calculates the Legendre's normal elliptic integrals of first and second kinds which are used to calculate the demagnetizing factors. Parameters: * ellipsoid : element of :class:`mesher.TriaxialEllipsoid`. Returns: F, E : floats Legendre's normal elliptic integrals of first and second kinds, respectively. ''' a = ellipsoid.large_axis b = ellipsoid.intermediate_axis c = ellipsoid.small_axis kappa = (a * a - b * b) / (a * a - c * c) phi = np.arccos(c / a) # E = ellipeinc(phi, kappa*kappa) # F = ellipkinc(phi, kappa*kappa) E = ellipeinc(phi, kappa) F = ellipkinc(phi, kappa) return E, F
def calc_lambda_0(chi, zp, zm, En, Lz, aa, slr, x): """ Mino time as a function of polar angle, chi Parameters: chi (float): polar angle zp (float): polar root zm (float): polar root En (float): energy Lz (float): angular momentum aa (float): spin slr (float): semi-latus rectum x (float): inclination Returns: lambda_0 (float) """ beta = aa * aa * (1 - En * En) k = sqrt(zm / zp) k2 = k * k prefactor = 1 / sqrt(beta * zp) ellipticK_k = ellipk(k2) ellipticF = ellipkinc(pi / 2 - chi, k2) return prefactor * (ellipticK_k - ellipticF)
def d1(v): beta = np.arccos((v+1. - np.sqrt(3.)) / (v+1. + np.sqrt(3.))) sin75 = np.sin(75. * np.pi/180.) sin75 = sin75*sin75 result = (5./3.) * (v) * (((3.**0.25) * (np.sqrt(1. + v**3.)) * (scs.ellipeinc(beta, sin75) - (1. / (3.+np.sqrt(3.))) * scs.ellipkinc(beta, sin75))) + ((1. - (np.sqrt(3.)+1.)*v*v) / (v+1. + np.sqrt(3.)))) return result
def force_ring(n, m): qp = dq[n] qq = dq[m] rp = p[n] rq = p[m] d = rp**2 + rq**2 a = rp + rq sq_a = (a)**2 s = (rp - rq) four = 4 * (rp * rq) / sq_a val = 1 * (1 / (rp * s * np.sqrt(d))) * np.sqrt(d / sq_a) * \ (a * sp.ellipeinc(pi / 4, four) + a * \ sp.ellipeinc(3 * pi / 4, four) + s * \ (sp.ellipkinc(pi / 4, four) + \ sp.ellipkinc(3 * pi / 4, four))) val = qp * qq * val return val
def d1(v): beta = np.arccos((v + 1. - np.sqrt(3.)) / (v + 1. + np.sqrt(3.))) sin75 = np.sin(75. * np.pi / 180.) sin75 = sin75**2 return (5. / 3.) * (v) * ( ((3.**0.25) * (np.sqrt(1. + v**3.)) * (scs.ellipeinc(beta, sin75) - (1. / (3. + np.sqrt(3.))) * scs.ellipkinc(beta, sin75))) + ((1. - (np.sqrt(3.) + 1.) * v * v) / (v + 1. + np.sqrt(3.))))
def SurfaceAreaTri(La, Lb, Lc, p): phi = np.arccos(Lc / La) k = np.sqrt( (La * La * (Lb * Lb - Lc * Lc)) / (Lb * Lb * (La * La - Lc * Lc))) Fphik = special.ellipkinc(phi, k) Ephik = special.ellipeinc(phi, k) return 2.0 * np.pi * (Lc * Lc / p) + 2.0 * np.pi * ( La * Lb / p) * (Ephik * np.sin(phi) * np.sin(phi) + Fphik * np.cos(phi) * np.cos(phi)) / np.sin(phi)
def gendata(phis, alps): l = '%23s%23s%23s\n' % ('phi', 'k', 'F') # phi [rad] for i, alp in enumerate(alps): k = np.sin(d2r(alp)) m = k**2.0 for j, phi in enumerate(phis): p = d2r(phi) r = sp.ellipkinc(p, m) l += '%23.15e%23.15e%23.15e\n' % (p, k, r) return l
def F(theta, k): """ Elliptic integral of the first kind. Parameters ---------- theta : float k : float """ return ellipkinc(theta, k)
def test_ellint_1(): if NumCpp.NO_USE_BOOST and not NumCpp.STL_SPECIAL_FUNCTIONS: return a = np.random.rand(1).item() b = np.random.rand(1).item() assert (roundScaler(NumCpp.ellint_1_Scaler(a, b), NUM_DECIMALS_ROUND) == roundScaler(sp.ellipkinc(b, a**2), NUM_DECIMALS_ROUND)) shapeInput = np.random.randint(20, 100, [2, ]) shape = NumCpp.Shape(shapeInput[0].item(), shapeInput[1].item()) aArray = NumCpp.NdArray(shape) bArray = NumCpp.NdArray(shape) a = np.random.rand(shape.rows, shape.cols) b = np.random.rand(shape.rows, shape.cols) aArray.setArray(a) bArray.setArray(b) assert np.array_equal(roundArray(NumCpp.ellint_1_Array(aArray, bArray), NUM_DECIMALS_ROUND), roundArray(sp.ellipkinc(b, a**2), NUM_DECIMALS_ROUND))
def d1(v): """ d1(v) = D(a)/a where D is growth function see. Einsenstein 1997 """ beta = np.arccos((v+1.-np.sqrt(3.))/(v+1.+np.sqrt(3.))) sin75 = np.sin(75.*np.pi/180.) sin75 = sin75**2 ans = (5./3.)*(v)*(((3.**0.25)*(np.sqrt(1.+v**3.))*(scs.ellipeinc(beta,sin75)\ -(1./(3.+np.sqrt(3.)))*scs.ellipkinc(beta,sin75)))\ +((1.-(np.sqrt(3.)+1.)*v*v)/(v+1.+np.sqrt(3.)))) return ans
def ellipkOsc(x,m): """ Compute the oscillating part of elliptic function ?th kind, K Args: x (real): elliptic function arugment m (real): elliptic function modulus Returns: real """ return ellipkinc(x , m) - 2*x*ellipk(m)/(np.pi)
def ellipsoid_area(ellipsoid): """ Compute the surface of a define ellipsoid with its half-axes (a, b, c) """ c, b, a = sorted([ellipsoid['a'], ellipsoid['b'], ellipsoid['c']]) if a == b == c: area = 4*np.pi*a**2 else: phi = np.arccos(c/a) m = (a**2 * (b**2 - c**2)) / (b**2 * (a**2 - c**2)) temp = ellipeinc(phi, m)*np.sin(phi)**2 + ellipkinc(phi, m)*np.cos(phi)**2 area = 2*np.pi*(c**2 + a*b*temp/np.sin(phi)) return area
def growth_factor(z, Omega_m): a = 1.0/(1.0+z) v = (1.0+z)*(Omega_m/(1.0-Omega_m))**(1.0/3.0) phi = np.arccos((v+1.0-3.0**0.5)/(v+1.0+3.0**0.5)) m = (np.sin(75.0/180.0* np.pi))**2.0 part1c = 3.0**0.25 * (1.0+ v**3.0)**0.5 # first elliptic integral F_elliptic = special.ellipkinc(phi, m) # second elliptic integral Se_elliptic = special.ellipeinc(phi, m) part1 = part1c * ( Se_elliptic - 1.0/(3.0+3.0**0.5)*F_elliptic) part2 = (1.0 - (3.0**0.5 + 1.0)*v*v)/(v+1.0+3.0**0.5) d_1 = 5.0/3.0*v*(part1 + part2) # if a goes to 0, use d_11, when z=1100, d_1 is close to d_11 # d_11 = 1.0 - 2.0/11.0/v**3.0 + 16.0/187.0/v**6.0 return a*d_1
def surface_area(self): """float: Get the surface area.""" # Implemented from this example: # https://www.johndcook.com/blog/2014/07/06/ellipsoid-surface-area/ # It requires that a >= b >= c, so we sort the principal axes: c, b, a = sorted([self.a, self.b, self.c]) if a > c: phi = np.arccos(c / a) m = (a**2 * (b**2 - c**2)) / (b**2 * (a**2 - c**2)) elliptic_part = ellipeinc(phi, m) * np.sin(phi)**2 elliptic_part += ellipkinc(phi, m) * np.cos(phi)**2 elliptic_part /= np.sin(phi) else: elliptic_part = 1 result = 2 * np.pi * (c**2 + a * b * elliptic_part) return result
def area(rad): """Area of a spheroid Arguments --------- rad : dict {'a', 'b', 'c'} Equatorial1, Equatorial2, and polar radius """ a, b, c = rad['a'], rad['b'], rad['c'] if (a != c) and (b != c): #spheroid k = a**2*(b**2-c**2) / (b**2*(a**2-c**2)) phi = np.arccos(c/a) tmp = ellipeinc(phi, k)*sin(phi)**2 + ellipkinc(phi, k)*cos(phi)**2 out = 2*pi*c**2 + tmp*2*pi*a*b/sin(phi) else: #sphere out = 4*pi*a**2 return out
def area(rad): """Area of a spheroid Arguments --------- rad : dict {'a', 'b', 'c'} Equatorial1, Equatorial2, and polar radius """ a, b, c = rad['a'], rad['b'], rad['c'] if (a != c) and (b != c): #spheroid k = a**2 * (b**2 - c**2) / (b**2 * (a**2 - c**2)) phi = np.arccos(c / a) tmp = ellipeinc(phi, k) * sin(phi)**2 + ellipkinc(phi, k) * cos(phi)**2 out = 2 * pi * c**2 + tmp * 2 * pi * a * b / sin(phi) else: #sphere out = 4 * pi * a**2 return out
def gentable(phis, alps): # header l = '%7s' % 'alp|phi' for phi in phis: l += '%12.0f' % phi l += '\n' # table for i, alp in enumerate(alps): k = np.sin(d2r(alp)) m = k**2.0 l += '%7.0f' % alp for j, phi in enumerate(phis): r = sp.ellipkinc(d2r(phi), m) l += '%12.8f' % r l += '\n' if (i + 1) % 5 == 0: l += '\n' return l
def calc_wr(psi, ups_r, En, Lz, Q, aa, slr, ecc, x): """ Computes wr by analytic evaluation of the integral in Drasco and Hughes (2005) Note that this currently only works for [0, pi], but could be extended with a little bit of work. """ a1 = (1 - ecc**2) * (1 - En**2) b1 = 2 * (1 - En**2 - (1 - ecc**2) / slr) c1 = (((3 + ecc**2) * (1 - En**2)) / (1 - ecc**2) - 4 / slr + ((1 - ecc**2) * (aa**2 * (1 - En**2) + Lz**2 + Q)) / slr**2) if psi == pi: # the closed form function has a singularity at psi = pi # but it can be evaluated in integral form to be pi return pi else: return ((-2j * (1 - ecc**2) * ups_r * cos(psi / 2.)**2 * ellipkinc( 1j * arcsinh( sqrt((a1 - (-1 + ecc) * (b1 + c1 - c1 * ecc)) / (a1 + b1 + c1 - c1 * ecc**2 + sqrt( (b1**2 - 4 * a1 * c1) * ecc**2))) * tan(psi / 2.)), (a1 + b1 + c1 - c1 * ecc**2 + sqrt( (b1**2 - 4 * a1 * c1) * ecc**2)) / (a1 + b1 + c1 - c1 * ecc**2 - sqrt( (b1**2 - 4 * a1 * c1) * ecc**2))) * sqrt(2 + (2 * (a1 - (-1 + ecc) * (b1 + c1 - c1 * ecc)) * tan(psi / 2.)**2) / (a1 + b1 + c1 - c1 * ecc**2 - sqrt( (b1**2 - 4 * a1 * c1) * ecc**2))) * sqrt(1 + ((a1 - (-1 + ecc) * (b1 + c1 - c1 * ecc)) * tan(psi / 2.)**2) / (a1 + b1 + c1 - c1 * ecc**2 + sqrt( (b1**2 - 4 * a1 * c1) * ecc**2)))) / (sqrt((a1 - (-1 + ecc) * (b1 + c1 - c1 * ecc)) / (a1 + b1 + c1 - c1 * ecc**2 + sqrt( (b1**2 - 4 * a1 * c1) * ecc**2))) * slr * sqrt(2 * a1 + 2 * b1 + 2 * c1 + c1 * ecc**2 + 2 * (b1 + 2 * c1) * ecc * cos(psi) + c1 * ecc**2 * cos(2 * psi))))
def ellipsoid_SA(r): r = np.sort(r.reshape(-1), axis=0) a, b, c = r[2], r[1], r[0] if np.isclose(a, b) and np.isclose(b, c): #print('sphere') ellipsoid_area = 4 * np.pi * a**2 else: # https://www.johndcook.com/blog/2014/07/06/ellipsoid-surface-area/ if np.isclose(a, b): #print('oblate') m = 1 elif np.isclose(b, c): #print('prolate') m = 0 else: #print('triaxial') m = (a**2 * (b**2 - c**2)) / (b**2 * (a**2 - c**2)) phi = np.arccos(c / a) temp = ellipeinc(phi, m) * np.sin(phi)**2 + ellipkinc( phi, m) * np.cos(phi)**2 ellipsoid_area = 2 * np.pi * (c**2 + a * b * temp / np.sin(phi)) return ellipsoid_area
def calc_lambda_r(r, r1, r2, r3, r4, En): """ Mino time as a function of r (which in turn is a function of psi) Parameters: r (float): radius r1 (float): radial root r2 (float): radial root r3 (float): radial root r4 (float): radial root En (float): energy Returns: lambda (float) """ kr = ((r1 - r2) * (r3 - r4)) / ((r1 - r3) * (r2 - r4)) # if r1 == r2: # # circular orbit # print('Circular orbits currently do not work.') # return 0 yr = sqrt(((r - r2) * (r1 - r3)) / ((r1 - r2) * (r - r3))) F_asin = ellipkinc(arcsin(yr), kr) return (2 * F_asin) / (sqrt(1 - En * En) * sqrt((r1 - r3) * (r2 - r4)))
def ellipkinc_(f, k): return ellipkinc(f, k*k)
def I01(rho,h2,h3): phi=np.arcsin(h2/rho) alpha=np.arcsin(h3/h2) m=(np.sin(alpha)) m=m*m return 1/h2*sp.ellipkinc(phi,m)