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 get_kth_point_on_ellipse(k, n, a, b, accuracy=1e-4): if a == 0: return (0, 0) m = 1 - (b**2 / a**2) c = get_ellipse_circumference(a, b) expected = c * (k / n) # initial guess - as if its a circle phi = 2 * np.pi * k / n error = (a * ellipeinc(phi, m) - expected) / c if error < 0: phi_under = phi phi_over = 2 * np.pi elif error > 0: phi_under = 0 phi_over = phi else: return np.array([a * np.sin(phi), b * np.cos(phi)]) while abs(error) > accuracy: phi = (phi_over + phi_under) / 2 error = (a * ellipeinc(phi, m) - expected) / c if error < 0: phi_under = phi elif error > 0: phi_over = phi else: return np.array([a * np.sin(phi), b * np.cos(phi)]) return np.array([a * np.sin(phi), b * np.cos(phi)])
def hyperuniform_ellipse(N, a = 1, b = 2): '''Generate Hyperuniformly-Sampled 2-D Ellipse''' assert(a < b) # a must be length of minor semi-axis; b major semi-axis X = [[],[]] # init data list [[x],[y]] C = np.linspace(0, 1, N) # init color list for plotting angles = 2*np.pi*np.arange(N)/N if a != b: '''Given N points, combine scipy elliptic integral + optimize to find N equidistant points along ellilpse manifold, then convert to angles''' e = np.sqrt(1.0 - a**2 / b**2) tot_size = special.ellipeinc(2.0 * np.pi, e) arc_size = tot_size / N arcs = np.arange(N) * arc_size res = optimize.root( lambda x: (special.ellipeinc(x, e) - arcs), angles) angles = res.x arcs = special.ellipeinc(angles, e) for t in angles: X[0].append(a * np.cos(t)) # x X[1].append(b * np.sin(t)) # y return np.asarray(X), np.asarray(C)
def get_evenly_distributed_ellipse_coordinates( self, number_of_coordinates: int = 50) -> List[Tuple[float, float]]: """ Makes use of scipy.special.ellipeinc() which provides the numerical integral along the perimeter of the ellipse, and scipy.optimize.root() for solving the equal-arcs length equation for the angles. :param number_of_coordinates: number of evenly distributed points to generate along the ellipsis line :return: list of tuple's with coordinates along the ellipse line """ angles = 2 * np.pi * np.arange( number_of_coordinates) / number_of_coordinates e = (1.0 - self.minor_axis**2.0 / self.major_axis**2.0)**0.5 total_size = special.ellipeinc(2.0 * np.pi, e) arc_size = total_size / number_of_coordinates arcs = np.arange(number_of_coordinates) * arc_size res = optimize.root(lambda x: (special.ellipeinc(x, e) - arcs), angles) angles = res.x if self.width > self.height: x_points = list(self.major_axis * np.sin(angles)) y_points = list(self.minor_axis * np.cos(angles)) else: x_points = list(self.minor_axis * np.cos(angles)) y_points = list(self.major_axis * np.sin(angles)) coordinates = [(point_x + self.x_center, point_y + self.y_center) for point_x, point_y in zip(x_points, y_points)] return coordinates
def map_on_ellipse(xq, a=4, b=1, gap_angle=90): """Map 2D points on bend ellipse in 3D. Parameters ---------- xq: (n, 2) array-like The 2D points a, b: non-negative, scalar Ellipsis axis gap_angle: scalar in [0,360) Degree of the gap the bend ellipse should have. E.g. for 0 the data is mapped onto a closed ellipse. Returns ------- xyz: (n, 3) array-like Mapped 3D points """ gap_angle = np.deg2rad(gap_angle) / 2 # Range of the data x_min = np.min(xq[:, 0]) x_max = np.max(xq[:, 0]) width = x_max - x_min # Compute perimeter of the open ellipse a = abs(a) b = abs(b) major, minor = max(a, b), min(a, b) ecc = (1 - minor**2 / major**2)**2 offset = ellipeinc(gap_angle, ecc) diameter = major * (4 * ellipe(ecc) - offset) # Scale ellipse to match the span scale = width / diameter a *= scale b *= scale # Find the angles. We use the canonical parametrization. x_zeroed = xq[:, 0] - x_min alpha = (2 * np.pi - 2 * gap_angle) * x_zeroed / ( x_max - x_min) + gap_angle # initial guess for _ in range(6): # 6 Newton steps to solve inverse elliptic integral. # 6 Newton steps ought to be enough for anybody. f = major * ellipeinc(alpha, ecc) - (x_zeroed + major * offset) f_prime = major * np.sqrt(1 - ecc * np.sin(alpha)**2) alpha = alpha - f / f_prime xy = np.vstack((a * np.cos(alpha), b * np.sin(alpha))).T z = xq[:, 1] # z-axis is the previous y-axis, we only bend in the xy-plane xyz = np.hstack((xy, z.reshape(-1, 1))) return xyz
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 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 _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 _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 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 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 _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 _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 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 ellipse_points(ellipse, n=12): c = 0 dtheta = 0 C = ellipse.circumference.evalf() e = ellipse.eccentricity.evalf() a = ellipse.hradius b = ellipse.vradius points = [0] * n points[0] = [a.__round__(6), 0] points[n // 4] = [0, b.__round__(6)] points[2 * n // 4] = [-a.__round__(6), 0] points[3 * n // 4] = [0, -b.__round__(6)] k = 1 while (k < n // 4): while (c < k * C // n): c = a * ellipeinc(dtheta, round( e**2, 16)) # Not rounding causes TypeError at function dtheta += 0.01 x = a * np.cos(dtheta) y = b * np.sin(dtheta) x = x.__round__(6) y = y.__round__(6) points[k] = [+x, +y] points[k + n // 4] = [-x, +y] points[k + 2 * n // 4] = [-x, -y] points[k + 3 * n // 4] = [+x, -y] k += 1 return points
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 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 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 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 gendata(phis, alps): l = '%23s%23s%23s\n' % ('phi', 'k', 'E') # 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.ellipeinc(p, m) l += '%23.15e%23.15e%23.15e\n' % (p, k, r) return l
def calc_t_r(qr, r1, r2, r3, r4, En, Lz, aa, M=1): """ delta_t_r in Drasco and Hughes (2005) Parameters: qr (float) r1 (float): radial root r2 (float): radial root r3 (float): radial root r4 (float): radial root En (float): energy Lz (float): angular momentum aa (float): spin Keyword Args: M (float): mass Returns: t_r (float) """ psi_r = calc_psi_r(qr, r1, r2, r3, r4) kr = ((r1 - r2) * (r3 - r4)) / ((r1 - r3) * (r2 - r4)) rp = M + sqrt(-(aa**2) + M**2) rm = M - sqrt(-(aa**2) + M**2) hr = (r1 - r2) / (r1 - r3) hp = ((r1 - r2) * (r3 - rp)) / ((r1 - r3) * (r2 - rp)) hm = ((r1 - r2) * (r3 - rm)) / ((r1 - r3) * (r2 - rm)) return -((En * ( (-4 * (r2 - r3) * (-(((-2 * aa**2 + (4 - (aa * Lz) / En) * rm) * ((qr * float(ellippi(hm, kr))) / pi - float(ellippi(hm, psi_r, kr)))) / ((r2 - rm) * (r3 - rm))) + ((-2 * aa**2 + (4 - (aa * Lz) / En) * rp) * ((qr * float(ellippi(hp, kr))) / pi - float(ellippi(hp, psi_r, kr))) ) / ((r2 - rp) * (r3 - rp)))) / (-rm + rp) + 4 * (r2 - r3) * ((qr * float(ellippi(hr, kr))) / pi - float(ellippi(hr, psi_r, kr))) + (r2 - r3) * (r1 + r2 + r3 + r4) * ((qr * float(ellippi(hr, kr))) / pi - float(ellippi(hr, psi_r, kr))) + (r1 - r3) * (r2 - r4) * ((qr * ellipe(kr)) / pi - ellipeinc(psi_r, kr) + (hr * cos(psi_r) * sin(psi_r) * sqrt(1 - kr * sin(psi_r)**2)) / (1 - hr * sin(psi_r)**2)))) / sqrt( (1 - En**2) * (r1 - r3) * (r2 - r4)))
def generate_ellipse_angles(num, a, b): angles = 2 * numpy.pi * numpy.arange(num) / num if a < b: e = float((1.0 - a**2 / b**2)**0.5) tot_size = ellipeinc(2.0 * numpy.pi, e) arc_size = tot_size / num arcs = numpy.arange(num) * arc_size res = optimize.root(lambda x: (ellipeinc(x, e) - arcs), angles) angles = res.x elif b < a: e = float((1.0 - b**2 / a**2)**0.5) tot_size = ellipeinc(2.0 * numpy.pi, e) arc_size = tot_size / num arcs = numpy.arange(num) * arc_size res = optimize.root(lambda x: (ellipeinc(x, e) - arcs), angles) angles = numpy.pi / 2 + res.x else: numpy.arange(0, 2 * numpy.pi, 2 * numpy.pi / num) return angles
def test_ellint_2(): 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_2_Scaler(a, b), NUM_DECIMALS_ROUND) == roundScaler(sp.ellipeinc(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_2_Array(aArray, bArray), NUM_DECIMALS_ROUND), roundArray(sp.ellipeinc(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 ellipeOsc(x,m): """ Compute the oscillating part of elliptic function ?th kind, E Args: x (real): elliptic function arugment m (real): elliptic function modulus Returns: real """ return ellipeinc(x , m) - 2*x*ellipe(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 precomputeEllipticArc(grid_size, ratio): """ Precomputes the incomplete elliptic integrals on a grid of theta so that one can find the adress on a ellipse (x, y coordinates) for a given arc length, :math:`k = \\sqrt{1 - b^2/a^2}` where b is semi-minor and a is semi-major axis of the ellipse *Args:* grid_size: The number of points (on a=1 ellipse) where the incomplete elliptic integrals is computed ratio: b/a (semi-minor/semi-major) of Ellipse *Returns:* all_phi: the grid of angles (ellipse parameter) on which the arc lengths are evaluated all_path_lengths: the evaluated arc lengths """ k = np.sqrt(1- ratio**2) phi = np.linspace(0, np.pi/2, grid_size+1) ellip = scsp.ellipeinc(phi, k) # now the phi runs from 0 - pi/2 owing to symmetry of the ellipse # compute the arc length of the ellipse along the perimeter for phi from # 0 to 2pi, weave together 0-pi/2, and then pi/2-0 etc. max_val = ellip[-1] ellip = np.delete(ellip, -1) all_path_length = np.zeros(4*(grid_size) + 1 ) # four quarters of 0 - (pi/2 - grid) all_phi = np.zeros(4*(grid_size) + 1) # the last value is 2*pi all_path_length[0:grid_size] = ellip #the last element is for pi/2 all_path_length[(grid_size):(2*grid_size)] = (max_val - ellip[::-1]) + max_val #weaving requres reversing, #owing to the nature of arc length on an ellipse all_path_length[(2*grid_size):(3*grid_size)] = ellip + 2*max_val all_path_length[(3*grid_size):(4*grid_size)] = (max_val - ellip[::-1]) + 3*max_val all_path_length[-1] = 4*max_val for i in range(4): all_phi[i*(grid_size):(i+1)*(grid_size)] = phi[:-1] + i*phi[-1] all_phi[-1] = 2*np.pi return all_phi, all_path_length
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 calculate_ellipse_arc(ellipse, t): """ :param ellipse: :param t: :return: """ phi = EllipticIntegralHelper.convert_phi_to_t(t) ellipse_arc_from_y_axis = ellipse.semi_x_axis * spsp.ellipeinc( phi, ellipse.m) ellipse_arc = ellipse.circumference / 4 - ellipse_arc_from_y_axis return ellipse_arc
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 ellipeinc_(f, k): return ellipeinc(f, k*k)
def sin_length(phi,k,omega): ## The length of a sinusoid is a classic calculus problem that falls into an elliptic integral. m = 1 + k**2 * omega**2 return ellipeinc(pi/2+omega*phi, 1-1/m )*sqrt(m)/omega
def fun(x): return np.sqrt(37)/6.0 * ellipeinc(6*x, 36.0/37.0);
def fun(x): return ellipeinc(x,0.5);
a1b2 = 1 - (e*e) a1b = math.sqrt(a1b2) ### Case 2: b is semi-major axis of length 1; b = 1 > a b1b = b1b2 = a1a b1a2 = a1b2 b1a = a1b ### Append Cases 1 and 2 results to elis list elis.append( (subpct ### Percent of PI/2 to use for upper limit ,theta ### Upper limit Eccentric Anomaly angle ,e ### Eccentricity a.k.a. Elliptic Modulus ,a1b ### semi-minor axis b for a = 1 > b ,eli(a1a,a1b,substep) ### Case 1 arc length from a for b < a = 1 ,ellipeinc(math.pi/2,e2)-ellipeinc(math.pi/2-theta,e2) ### Case 1 actual ,eli(b1a,b1b,substep) ### Case 2 arc length from a for b = 1 > a ,ellipeinc(theta,e2) ### Case 2 actual ,) ) ######################################################################## ### Print out results for subpct,theta,e,a1b,a1eli,Ecompl,b1eli,E in elis: print('%s%3d %16.16f %10.8f %12.10f %12.10f %12.10f %12.4e %12.10f %12.10f %12.4e' %(e==0. and '\n' or '' ,subpct ### Upper limit, percent of PI/2 ,theta ### Upper limit Ecc. Anom. angle ,e ### Eccentricity ,a1b ### semi-minor axis ,a1eli ### Case 1 numerical result
from __future__ import division, print_function from math import pi from scipy.special import ellipeinc import sys J = float(sys.argv[1]) Gamma = 1 lam = J/(2*Gamma) theta = 4*lam/(1+lam)**2 print(ellipeinc(pi/2,theta)/(pi/2),1+lam) print("{:.15f}".format(-Gamma*2/pi*(1+lam)*ellipeinc(pi/2,theta)))