def test_bTrapezoidn(): """ Test of numerical trapezoid outer moments against point gravity. Tests ----- bqlmn.trapezoid : function """ iR, oR = 1, 2 beta = np.pi / 3 t = 1 vol = (oR - iR) * np.cos(beta) * (oR + iR) * np.sin(beta) * t mout = gshp.trapezoid(1, iR, oR, t, beta, 60, 60) mmout2 = pgm.Qmomentsb(5, glb.translate_point_array(mout, [0, 0, .5])) Qlmb2 = bqlmn.trapezoid(5, 1 / vol, 0, t, iR, oR, beta) assert (abs(Qlmb2 - mmout2) < .01).all() mmout3 = pgm.Qmomentsb(5, glb.translate_point_array(mout, [0, 0, -.5])) Qlmb3 = bqlmn.trapezoid(5, 1 / vol, -t, 0, iR, oR, beta) assert (abs(Qlmb3 - mmout3) < .01).all() beta = np.pi / 4 vol = (oR - iR) * np.cos(beta) * (oR + iR) * np.sin(beta) * t mout4 = gshp.trapezoid(1, iR, oR, t, beta, 60, 60) mmout4 = pgm.Qmomentsb(5, glb.translate_point_array(mout4, [0, 0, .5])) Qlmb4 = bqlmn.trapezoid(5, 1 / vol, 0, t, iR, oR, beta) assert (abs(Qlmb4 - mmout4) < .01).all() beta = np.pi / 5 vol = (oR - iR) * np.cos(beta) * (oR + iR) * np.sin(beta) * t mout5 = gshp.trapezoid(1, iR, oR, t, beta, 60, 60) mmout5 = pgm.Qmomentsb(5, glb.translate_point_array(mout5, [0, 0, .5])) Qlmb5 = bqlmn.trapezoid(5, 1 / vol, 0, t, iR, oR, beta) assert (abs(Qlmb5 - mmout5) < .01).all()
def test_bAnnulusn(): """ Test of numerical annulus outer moments against point gravity. Tests ----- bqlmn.annulus : function """ mout = gshp.wedge(1, 1, 2, 1, np.pi / 2, 60, 60) mmout2 = pgm.Qmomentsb(5, glb.translate_point_array(mout, [0, 0, .5])) Qlmb2 = bqlmn.annulus(5, 2 / (np.pi * (2**2 - 1)), 0, 1, 1, 2, np.pi / 2) assert (abs(Qlmb2 - mmout2) < .002).all() mmout3 = pgm.Qmomentsb(5, glb.translate_point_array(mout, [0, 0, -.5])) Qlmb3 = bqlmn.annulus(5, 2 / (np.pi * (2**2 - 1)), -1, 0, 1, 2, np.pi / 2) assert (abs(Qlmb3 - mmout3) < .002).all() mout3 = gshp.wedge(1, 1, 2, 1, np.pi / 3, 60, 60) mmout3 = pgm.Qmomentsb(5, glb.translate_point_array(mout3, [0, 0, .5])) Qlmb3 = bqlmn.annulus(5, 3 / (np.pi * (2**2 - 1)), 0, 1, 1, 2, np.pi / 3) assert (abs(Qlmb3 - mmout3) < .002).all() mout4 = gshp.wedge(1, 1, 2, 1, np.pi / 4, 60, 60) mmout4 = pgm.Qmomentsb(5, glb.translate_point_array(mout4, [0, 0, .5])) Qlmb4 = bqlmn.annulus(5, 4 / (np.pi * (2**2 - 1)), 0, 1, 1, 2, np.pi / 4) assert (abs(Qlmb4 - mmout4) < .002).all() mout5 = gshp.wedge(1, 1, 2, 1, np.pi / 5, 60, 60) mmout5 = pgm.Qmomentsb(5, glb.translate_point_array(mout5, [0, 0, .5])) Qlmb5 = bqlmn.annulus(5, 5 / (np.pi * (2**2 - 1)), 0, 1, 1, 2, np.pi / 5) assert (abs(Qlmb5 - mmout5) < .002).all()
def test_shell_theorem(): """ Check that Newton's shell theorem holds. That is a spherical shell behaves as a point of equal mass at the center of the shell. Additionally, a point inside the sphere experiences no force. Tests ----- glb.point_matrix_gravity : function """ d = 20 R = 10 shell = gshp.spherical_random_shell(1, R, 100000) # A point outside should see force from point at origin of shell mass 1kg m1 = np.array([1, d, 0, 0]) F, T = glb.point_matrix_gravity(m1, shell) threshold = 6 * np.finfo(float).eps assert abs(F[0] / (glb.BIG_G / d**2) + 1) < .01 assert abs(F[1]) < threshold assert abs(F[2]) < threshold # point inside should see no force m2 = np.array([1, 0, 0, 0]) # translate randomly in box contained in shell Rlim = R * .5 / np.sqrt(3) p = rand.rand(3) * 2 * Rlim - Rlim m2 = glb.translate_point_array(m2, p) F2, T2 = glb.point_matrix_gravity(m2, shell) # Fails so increased threshold assert (abs(F2) < 10 * threshold).all()
def test_sheet_uniformity(): """ Check that the gravitational force from an infinite sheet is approximately a constant as a function of distance. Tests ----- glb.point_matrix_gravity : function """ m = np.array([1, 0, 0, 0]) N = 100 r = 140 t = 0.01 xspace = 0.005 rspace = 0.5 mass = np.pi * r * r * t sheet = gshp.annulus(mass, 0, r, t, int(r / rspace), int(t / xspace)) f = np.zeros([N, 3]) ds = np.zeros(N) for k in range(N): x = rand.randn() * rspace y = rand.randn() * rspace ds[k] = 2 * rand.rand() + rspace s = glb.translate_point_array(m, [x, y, ds[k]]) f[k], torq = glb.point_matrix_gravity(s, sheet) expectedF = 2 * np.pi * glb.BIG_G * t fs = np.array([f[k, 2] for k in range(N) if abs(ds[k]) > 1]) assert (abs(abs(fs / expectedF) - 1) < 0.2).all()
def translate(self, tvec, inner): self.pointmass = glb.translate_point_array(self.pointmass, tvec) self.com += tvec if self.inner and inner: self.qlm = trs.translate_qlm(self.qlm, tvec) elif self.inner and not inner: self.inner = False self.qlm = trs.translate_q2Q(self.qlm, tvec) else: self.qlm = trs.translate_Qlmb(self.qlm, tvec)
def test_translate(): """ Check that moving a point mass at the origin to [1, 1, 1] works. Tests ----- glb.translate_point_array : function """ m = np.array([1, 0, 0, 0]) o = glb.translate_point_array(m, [1, 1, 1]) assert (o == [1, 1, 1, 1]).all()
def test_bAnnulus(): """ Test of explicit annulus outer moments against point gravity. Tests ----- bqlm.annulus : function """ mout = gshp.wedge(1, 1, 2, 1, np.pi / 2, 60, 60) mmout2 = pgm.Qmomentsb(5, glb.translate_point_array(mout, [0, 0, .5])) Qlmb2 = bqlm.annulus(5, 2 / (np.pi * (2**2 - 1)), 1, 1, 2, 0, np.pi / 2) assert (abs(Qlmb2 - mmout2) < .002).all() mmout3 = pgm.Qmomentsb(5, glb.translate_point_array(mout, [0, 0, -.5])) Qlmb3 = bqlm.annulus(5, 2 / (np.pi * (2**2 - 1)), -1, 1, 2, 0, np.pi / 2) assert (abs(Qlmb3 - mmout3) < .002).all() mout3 = gshp.wedge(1, 1, 2, 1, np.pi / 3, 60, 60) mmout3 = pgm.Qmomentsb(5, glb.translate_point_array(mout3, [0, 0, .5])) Qlmb3 = bqlm.annulus(5, 3 / (np.pi * (2**2 - 1)), 1, 1, 2, 0, np.pi / 3) assert (abs(Qlmb3 - mmout3) < .002).all() mout4 = gshp.wedge(1, 1, 2, 1, np.pi / 4, 60, 60) mmout4 = pgm.Qmomentsb(5, glb.translate_point_array(mout4, [0, 0, .5])) Qlmb4 = bqlm.annulus(5, 4 / (np.pi * (2**2 - 1)), 1, 1, 2, 0, np.pi / 4) assert (abs(Qlmb4 - mmout4) < .002).all() mout5 = gshp.wedge(1, 1, 2, 1, np.pi / 5, 60, 60) mmout5 = pgm.Qmomentsb(5, glb.translate_point_array(mout5, [0, 0, .5])) Qlmb5 = bqlm.annulus(5, 5 / (np.pi * (2**2 - 1)), 1, 1, 2, 0, np.pi / 5) assert (abs(Qlmb5 - mmout5) < .002).all() # Test that a L<5 works (we'll do 3) Qlmb3 = bqlm.annulus(3, 3 / (np.pi * (2**2 - 1)), 1, 1, 2, 0, np.pi / 3) mmout3 = pgm.Qmomentsb(3, glb.translate_point_array(mout3, [0, 0, .5])) assert (np.shape(Qlmb3) == (4, 7)) assert (abs(Qlmb3 - mmout3) < .002).all()
def test_Q2Q(): """ Check that the outer to outer translate method matches PointGravity. """ R = 100 M = 1 m2 = np.array([[M, R, 0, 0], [M, -R, 0, 0]]) # Get outer moments of points at +/-R Qm2 = pgm.Qmomentsb(10, m2) # Get outer moments of translated points Qm2b = pgm.Qmomentsb(10, glb.translate_point_array(m2, [0.1, 0, 0])) # Find outer moments from inner qm0 and qm0b translated to +/-R Qlmp2 = trs.translate_Qlmb(Qm2, [0.1, 0, 0]) assert (abs(Qlmp2-Qm2b) < 10*np.finfo(float).eps).all()
def test_q2q(): """ Check that the inner to inner translate method matches PointGravity. """ d = 1 m = 1 m1 = np.array([[m, d, 0, 0], [m, -d, 0, 0]]) # Find inner moments around origin qm1 = pgm.qmoments(10, m1) # Find inner moments if translated by [.1, 0, 0] qm1p = pgm.qmoments(10, glb.translate_point_array(m1, [.1, 0, 0])) # Find moments translated by [.1, 0, 0] qlmp = trs.translate_qlm(qm1, [0.1, 0, 0]) assert (abs(qlmp-qm1p) < 11*np.finfo(float).eps).all()
def test_Q2Q_SS(): """ Check that the outer to outer translate method matches CS translation. """ R = 100 M = 1 m2 = np.array([[M, R, 0, 0], [M, -R, 0, 0]]) # Get outer moments of points at +/-R Qm2 = pgm.Qmomentsb(10, m2) # Get outer moments of translated points Qm2b = pgm.Qmomentsb(10, glb.translate_point_array(m2, [0, 0, 0.1])) # Find outer moments from inner qm0 and qm0b translated to +/-R ssms = trr.transl_newt_z_SS(10, .1) Qlmp2 = trr.apply_trans_mat(Qm2, ssms) assert (abs(Qlmp2-Qm2b) < 10*np.finfo(float).eps).all()
def test_q2q_RR(): """ Check that the inner to inner translate method matches EGA translation. """ d = 1 m = 1 m1 = np.array([[m, d, 0, 0], [m, -d, 0, 0]]) # Find inner moments around origin qm1 = pgm.qmoments(10, m1) # Find inner moments if translated by [.1, 0, 0] qm1p = pgm.qmoments(10, glb.translate_point_array(m1, [0, 0, 0.1])) # Find moments translated by [.1, 0, 0] rrms = trr.transl_newt_z_RR(10, .1) qlmp = trr.apply_trans_mat(qm1, rrms) assert (abs(qlmp-qm1p) < 11*np.finfo(float).eps).all()
def test_translate2(): """ Check that translating 6 normally distributed masses keeps masses the same and deviation the same. Tests ----- glb.translate_point_array : function """ N = 6 for k in range(100): v = rand.randn(3) m = rand.randn(N, 4) o = glb.translate_point_array(m, v) # check we didn't change mass assert (m[:, 0] == o[:, 0]).all() # Check positions match assert (abs(m[:, 1:] - o[:, 1:] + v) < 6 * np.finfo(float).eps).all()
def test_q2Q_SR(): """ Check that the inner to outer translate method matches PointGravity. This translation method is worse for smaller translations. For R=10, the error approaches 1e7*epsilon. """ d = 1 R = 100 m = 1 m1 = np.array([[m, d, 0, 0], [m, -d, 0, 0]]) m2 = glb.translate_point_array(m1, [0, 0, R]) # Create inner moments of each points at +/-r qm0 = pgm.qmoments(10, np.array(m1)) # Get outer moments of points at +/-R Qm2 = pgm.Qmomentsb(10, m2) # Find outer moments from inner qm0 and qm0b translated to +/-R srms = trr.transl_newt_z_SR(10, R) Qlm = trr.apply_trans_mat(qm0, srms) assert (abs(Qlm-Qm2) < 11*np.finfo(float).eps).all()
def test_ISL(): """ Tests ----- glb.point_matrix_gravity : function """ m = gshp.annulus(1, 0, 1, 1, 10, 5) for k in range(100): # translate randomly in z in range (2, 10**5)m exp = rand.rand() * 5 + 2 d = 10.**exp # translate randomly around y=0 ~N(0,.01) r = rand.randn() * 0.01 md = glb.translate_point_array(m, [0, r, d]) f, t = glb.point_matrix_gravity(m, md) # Check that there's roughly no torque assert np.sum(abs(t)) < 6 * np.finfo(float).eps # check that the force falls like 1/d**2 assert (abs(f[2] - glb.BIG_G / d**2) / (glb.BIG_G / d**2)) < 0.001 return True
# -*- coding: utf-8 -*- """ Created on Sat Jun 20 11:09:40 2020 @author: John Greendeer Lee """ import numpy as np import newt.glib as glb import newt.glibShapes as gshp # Create a cylinder cyl = gshp.annulus(1, 0, 1, 1, 10, 10) # Inner cylinders on radius of 1m cyl1 = glb.translate_point_array(cyl, [5, 0, 0]) # Outer cylinders on radius of 5m cyl2 = glb.translate_point_array(cyl, [20, 0, 0]) # Combination of three inner cylinders m1 = np.concatenate([ cyl1, glb.rotate_point_array(cyl1, 2 * np.pi / 3, [0, 0, 1]), glb.rotate_point_array(cyl1, -2 * np.pi / 3, [0, 0, 1]) ]) # Combination of three outer cylinders m2 = np.concatenate([ cyl2, glb.rotate_point_array(cyl2, 2 * np.pi / 3, [0, 0, 1]), glb.rotate_point_array(cyl2, -2 * np.pi / 3, [0, 0, 1]) ]) fig, ax = glb.display_points(m1, m2) ax.set_zlim([-20, 20])
""" Script for comparison of translation methods. Fast rotation + z-translation vs regular translation. """ lmax = 20 # Create 2 points with mass1, at x=+/-1 d = 1 m = 1 m1 = np.array([[m, d, 0, 0], [m, -d, 0, 0]]) # Find inner moments around origin qm1 = pgm.qmoments(lmax, m1) # Find inner moments if translated by [.1, 0, 0] rvec = [0.1, 0, 0] qm1p = pgm.qmoments(lmax, glb.translate_point_array(m1, rvec)) # Find moments translated by [.1, 0, 0] using d'Urso, Adelberger tic1 = time.perf_counter() qm1p2 = trs.translate_qlm(qm1, rvec) toc1 = time.perf_counter() # Time the recursive method combined with recursive translation tic2 = time.perf_counter() r = np.sqrt(rvec[0]**2 + rvec[1]**2 + rvec[2]**2) if r == 0 or r == rvec[2]: phi, theta = 0, 0 else: phi = np.arctan2(rvec[1], rvec[0]) theta = np.arccos(rvec[2]/r) rrms = trr.transl_newt_z_RR(lmax, r)