def test_em_tensor_contravariant(): """ Tests skew-symmetric property of EM Tensor Theoretical background is required to write extensive tests. \ Right now only skew-symmetric property is being checked. """ M, a, Q = 1e22 * u.kg, 0.7 * u.one, 45.0 * u.C bl = BoyerLindquistDifferential( t=0. * u.s, r=5.5 * u.m, theta=2 * np.pi / 5 * u.rad, phi=0. * u.rad, v_r=200. * u.m / u.s, v_th=9. * u.rad / u.s, v_p=10. * u.rad / u.s ) x_vec = bl.position() # Using function from module mkn = KerrNewman(coords=bl, M=M, a=a, Q=Q) mkn_em_contra = mkn.em_tensor_contravariant(x_vec) assert_allclose(0., mkn_em_contra + np.transpose(mkn_em_contra), atol=1e-8)
def test_em_tensor_covariant(): """ Tests, if the calculated Maxwell Tensor is the same as that from the formula Formula for testing from https://arxiv.org/abs/gr-qc/0409025 """ M, a, Q = 2e22 * u.kg, 0.5 * u.one, 10.0 * u.C bl = BoyerLindquistDifferential(t=0. * u.s, r=1.5 * u.m, theta=3 * np.pi / 5 * u.rad, phi=0. * u.rad, v_r=0. * u.m / u.s, v_th=0. * u.rad / u.s, v_p=0. * u.rad / u.s) x_vec = bl.position() r, theta = x_vec[1], x_vec[2] alpha = BaseMetric.alpha(M, a) # Using function from module mkn = KerrNewman(coords=bl, M=M, a=a, Q=Q) mkn_em_cov = mkn.em_tensor_covariant(x_vec) # Checking Skew-Symmetry of Covariant Maxwell Tensor assert_allclose(0., mkn_em_cov + np.transpose(mkn_em_cov), atol=1e-8) th, r2, alpha2 = theta, r**2, alpha**2 # Unit Scaling factor for Charge scale_Q = np.sqrt(_G * _Cc) / _c**2 # Electric and Magnetic Fields D_r = (scale_Q * Q.value * (r2 - (alpha * np.cos(th))**2)) / ((r2 + (alpha * np.cos(th))**2)**2) D_th = ((alpha2) * (-(scale_Q * Q.value)) * np.sin(2 * th)) / ( (r2 + (alpha * np.cos(th))**2)**2) H_r = (2 * alpha * (scale_Q * Q.value) * (r2 + alpha2) * np.cos(th)) / (r * ((r2 + (alpha * np.cos(th))**2)**2)) H_th = ((alpha * (scale_Q * Q.value) * np.sin(th) * (r2 - (alpha * np.cos(th))**2)) / (r * ((r2 + (alpha * np.cos(th))**2)**2))) assert_allclose(D_r, mkn_em_cov[0, 1], rtol=1e-8) assert_allclose(r * D_th, mkn_em_cov[0, 2], rtol=1e-8) assert_allclose(-r * np.sin(theta) * H_th, mkn_em_cov[1, 3], rtol=1e-8) assert_allclose((r**2) * np.sin(theta) * H_r, mkn_em_cov[2, 3], rtol=1e-8)
def test_wrong_or_no_units_in_init(M, a, Q, q): """ Tests, if wrong or no units are flagged as error, while instantiation """ sph = SphericalDifferential( t=10000.0 * u.s, r=130.0 * u.m, theta=np.pi / 2 * u.rad, phi=-np.pi / 8 * u.rad, v_r=0.0 * u.m / u.s, v_th=0.0 * u.rad / u.s, v_p=0.0 * u.rad / u.s, ) bl = BoyerLindquistDifferential( t=10000.0 * u.s, r=130.0 * u.m, theta=np.pi / 2 * u.rad, phi=-np.pi / 8 * u.rad, v_r=0.0 * u.m / u.s, v_th=0.0 * u.rad / u.s, v_p=0.0 * u.rad / u.s, ) try: bm = BaseMetric(coords=sph, M=M, a=a, Q=Q) ms = Schwarzschild(coords=sph, M=M) mk = Kerr(coords=bl, M=M, a=a) mkn = KerrNewman(coords=bl, M=M, a=a, Q=Q, q=q) assert False except (u.UnitsError, TypeError): assert True
def test_calculate_trajectory_iterator_RuntimeWarning_kerrnewman(): M = 0.5 * 5.972e24 * u.kg a = 0. * u.one Q = 0. * u.C q = 0. * u.C / u.kg bl = BoyerLindquistDifferential( t=0.0 * u.s, r=306.0 * u.m, theta=np.pi / 2 * u.rad, phi=np.pi / 2 * u.rad, v_r=0.0 * u.m / u.s, v_th=-0.01 * u.rad / u.s, v_p=10.0 * u.rad / u.s, ) mkn = KerrNewman(coords=bl, M=M, a=a, Q=Q, q=q) end_lambda = 200. step_size = 0.4e-6 OdeMethodKwargs = {"stepsize": step_size} geod = Timelike(metric=mkn, coords=bl, end_lambda=end_lambda, step_size=step_size) with warnings.catch_warnings(record=True) as w: it = geod.calculate_trajectory_iterator( OdeMethodKwargs=OdeMethodKwargs, ) for _, _ in zip(range(1000), it): pass assert len(w) >= 1
def test_calculate_trajectory1_kerrnewman(): # This needs more investigation # the test particle should not move as gravitational & electromagnetic forces are balanced M = 0.5 * 5.972e24 * u.kg a = 0. * u.one Q = 11604461683.91822052001953125 * u.C q = _G * M.value / _Cc * u.C / u.kg r = 1e6 end_lambda = 1000.0 step_size = 0.5 bl = BoyerLindquistDifferential( t=0.0 * u.s, r=r * u.m, theta=np.pi / 2 * u.rad, phi=0.0 * u.rad, v_r=0.0 * u.m / u.s, v_th=0.0 * u.rad / u.s, v_p=0.0 * u.rad / u.s, ) mkn = KerrNewman(coords=bl, M=M, a=a, Q=Q, q=q) geod = Timelike(metric=mkn, coords=bl, end_lambda=end_lambda, step_size=step_size, return_cartesian=False) ans = geod.trajectory assert_allclose(ans[0][1], ans[-1][1], 1e-2)
def test_calculate_trajectory_iterator_RuntimeWarning_kerr(): M = 1e25 * u.kg a = 0. * u.one bl = BoyerLindquistDifferential( t=0.0 * u.s, r=306.0 * u.m, theta=np.pi / 2 * u.rad, phi=np.pi / 2 * u.rad, v_r=0.0 * u.m / u.s, v_th=0.01 * u.rad / u.s, v_p=10.0 * u.rad / u.s, ) mk = Kerr(coords=bl, M=M, a=a) end_lambda = 1. stepsize = 0.4e-6 OdeMethodKwargs = {"stepsize": stepsize} geod = Timelike(metric=mk, coords=bl, end_lambda=end_lambda, step_size=stepsize, return_cartesian=False) with warnings.catch_warnings(record=True) as w: it = geod.calculate_trajectory_iterator( OdeMethodKwargs=OdeMethodKwargs, ) for _, _ in zip(range(1000), it): pass assert len(w) >= 1
def bl(): return BoyerLindquistDifferential(t=0. * u.s, r=0.1 * u.m, theta=4 * np.pi / 5 * u.rad, phi=0. * u.rad, v_r=0. * u.m / u.s, v_th=0. * u.rad / u.s, v_p=0. * u.rad / u.s)
def bl_differential(): return BoyerLindquistDifferential( 1e3 * u.s, 10e3 * u.m, 1.5707963267948966 * u.rad, 0.7853981633974483 * u.rad, 10e3 * u.m / u.s, -20.0 * u.rad / u.s, 20.0 * u.rad / u.s )
def bl(): return BoyerLindquistDifferential( t=10000.0 * u.s, r=130.0 * u.m, theta=np.pi / 2 * u.rad, phi=-np.pi / 8 * u.rad, v_r=0.0 * u.m / u.s, v_th=0.0 * u.rad / u.s, v_p=0.0 * u.rad / u.s, )
def bl_differential2(): return BoyerLindquistDifferential( 1e3 * u.s, 4e3 * u.m, 2 * u.rad, 1 * u.rad, -100 * u.m / u.s, -1 * u.rad / u.s, 0.17453292519943295 * u.rad / u.s )
def test_f_vec_bl_kerr(): M, a = 6.73317655e26 * u.kg, 0.2 * u.one bl = BoyerLindquistDifferential(t=0. * u.s, r=1e6 * u.m, theta=4 * np.pi / 5 * u.rad, phi=0. * u.rad, v_r=0. * u.m / u.s, v_th=0. * u.rad / u.s, v_p=2e6 * u.rad / u.s) f_vec_expected = np.array([ 3.92128321e+03, 0.00000000e+00, 0.00000000e+00, 2.00000000e+06, -0.00000000e+00, 1.38196394e+18, -1.90211303e+12, -0.00000000e+00 ]) mk = Kerr(coords=bl, M=M, a=a) state = np.hstack((bl.position(), bl.velocity(mk))) f_vec = mk._f_vec(0., state) assert isinstance(f_vec, np.ndarray) assert_allclose(f_vec_expected, f_vec, rtol=1e-8)
def test_input(): """ Test input for some functions below """ bl = BoyerLindquistDifferential(t=0. * u.s, r=0.1 * u.m, theta=4 * np.pi / 5 * u.rad, phi=0. * u.rad, v_r=0. * u.m / u.s, v_th=0. * u.rad / u.s, v_p=0. * u.rad / u.s) M = 1e23 * u.kg a = 0.99 * u.one return bl, M, a
def test_compare_calculate_trajectory_iterator_bl(test_input): q, a, Q, el, ss = test_input bl_obj = BoyerLindquistDifferential( 1000.0 * u.km, 0.6 * np.pi * u.rad, np.pi / 8 * u.rad, 10000 * u.m / u.s, -0.01 * u.rad / u.s, 0.0 * u.rad / u.s, a, ) M = 0.5 * 5.972e24 * u.kg cl1 = KerrNewman.from_coords(coords=bl_obj, q=q, M=M, Q=Q) cl2 = KerrNewman.from_coords(coords=bl_obj, q=q, M=M, Q=Q) ans1 = cl1.calculate_trajectory(end_lambda=el, OdeMethodKwargs={"stepsize": ss})[1] it = cl2.calculate_trajectory_iterator(OdeMethodKwargs={"stepsize": ss}) ans2 = list() for _, val in zip(range(20), it): ans2.append(val[1]) ans2 = np.array(ans2) assert_allclose(ans1[:20], ans2)
def test_calculate_trajectory1(): # the test particle should not move as gravitational & electromagnetic forces are balanced M = 0.5 * 5.972e24 * u.kg r = 1000.0 * u.km end_lambda = 1000.0 stepsize = 0.5 tmp = _G * M.value / _cc q = tmp * u.C / u.kg a = 0 * u.km Q = 11604461683.91822052001953125 * u.C bl_obj = BoyerLindquistDifferential( r, 0.5 * np.pi * u.rad, 0 * u.rad, 0 * u.m / u.s, 0 * u.rad / u.s, 0.0 * u.rad / u.s, a, ) cl = KerrNewman.from_BL(bl_obj, q, M, Q) ans = cl.calculate_trajectory(end_lambda=end_lambda, OdeMethodKwargs={"stepsize": stepsize}) assert_allclose(ans[1][0][1], ans[1][-1][1], 1e-2)
def test_calculate_trajectory_iterator_RuntimeWarning(): bl_obj = BoyerLindquistDifferential( 306 * u.m, np.pi / 2 * u.rad, np.pi / 2 * u.rad, 0 * u.m / u.s, 0.01 * u.rad / u.s, 10 * u.rad / u.s, 0 * u.m, ) M = 1e25 * u.kg start_lambda = 0.0 OdeMethodKwargs = {"stepsize": 0.4e-6} cl = Kerr.from_BL(bl_obj, M) with warnings.catch_warnings(record=True) as w: it = cl.calculate_trajectory_iterator( start_lambda=start_lambda, OdeMethodKwargs=OdeMethodKwargs, stop_on_singularity=True, ) for _, _ in zip(range(1000), it): pass assert len(w) >= 1
def test_compare_calculate_trajectory_iterator_bl_kerrnewman(test_input): a, Q, q, end_lambda, step_size = test_input M = 0.5 * 5.972e24 * u.kg bl = BoyerLindquistDifferential( t=0.0 * u.s, r=1e6 * u.m, theta=0.6 * np.pi * u.rad, phi=np.pi / 8 * u.rad, v_r=1e4 * u.m / u.s, v_th=-0.01 * u.rad / u.s, v_p=0.0 * u.rad / u.s, ) mkn = KerrNewman(coords=bl, M=M, a=a, Q=Q, q=q) OdeMethodKwargs = {"stepsize": step_size} return_cartesian = False geod = Timelike(metric=mkn, coords=bl, end_lambda=end_lambda, step_size=step_size, return_cartesian=return_cartesian) traj = geod.trajectory traj_iter = geod.calculate_trajectory_iterator( OdeMethodKwargs=OdeMethodKwargs, return_cartesian=return_cartesian) traj_iter_list = list() for _, val in zip(range(20), traj_iter): traj_iter_list.append(val[1]) traj_iter_arr = np.array(traj_iter_list) assert_allclose(traj[:20], traj_iter_arr)
def bl2(): return BoyerLindquistDifferential(0. * u.s, 1. * u.m, np.pi / 2 * u.rad, 0.1 * u.rad, -0.1 * u.m / u.s, -0.01 * u.rad / u.s, 0.05 * u.rad / u.s)
def calculate_trajectory_iterator( self, start_lambda=0.0, stop_on_singularity=True, OdeMethodKwargs={"stepsize": 1e-3}, return_cartesian=False, ): """ Calculate trajectory in manifold according to geodesic equation. Yields an iterator. Parameters ---------- start_lambda : float Starting lambda, defaults to 0.0, (lambda ~= t) stop_on_singularity : bool Whether to stop further computation on reaching singularity, defaults to True OdeMethodKwargs : dict Kwargs to be supplied to the ODESolver, defaults to {'stepsize': 1e-3} Dictionary with key 'stepsize' along with an float value is expected. return_cartesian : bool True if coordinates and velocities are required in cartesian coordinates(SI units), defaults to Falsed Yields ------ float proper time ~numpy.ndarray array of [t, x1, x2, x3, velocity_of_time, v1, v2, v3] for each proper time(lambda). """ ODE = RK45(fun=self.f_vec, t0=start_lambda, y0=self.initial_vec, t_bound=1e300, **OdeMethodKwargs) crossed_event_horizon = False _scr = self.scr.value * 1.001 while True: if not return_cartesian: yield ODE.t, ODE.y else: v = ODE.y si_vals = (BoyerLindquistDifferential( v[1] * u.m, v[2] * u.rad, v[3] * u.rad, v[5] * u.m / u.s, v[6] * u.rad / u.s, v[7] * u.rad / u.s, self.a, ).cartesian_differential().si_values()) yield ODE.t, np.hstack((v[0], si_vals[:3], v[4], si_vals[3:])) ODE.step() if (not crossed_event_horizon) and (ODE.y[1] <= _scr): warnings.warn("particle reached Schwarzschild Radius. ", RuntimeWarning) if stop_on_singularity: break else: crossed_event_horizon = True
def calculate_trajectory( self, start_lambda=0.0, end_lambda=10.0, stop_on_singularity=True, OdeMethodKwargs={"stepsize": 1e-3}, return_cartesian=False, ): """ Calculate trajectory in manifold according to geodesic equation Parameters ---------- start_lambda : float Starting lambda(proper time), defaults to 0.0, (lambda ~= t) end_lamdba : float Lambda(proper time) where iteartions will stop, defaults to 100000 stop_on_singularity : bool Whether to stop further computation on reaching singularity, defaults to True OdeMethodKwargs : dict Kwargs to be supplied to the ODESolver, defaults to {'stepsize': 1e-3} Dictionary with key 'stepsize' along with an float value is expected. return_cartesian : bool True if coordinates and velocities are required in cartesian coordinates(SI units), defaults to False Returns ------- ~numpy.ndarray N-element array containing proper time. ~numpy.ndarray (n,8) shape array of [t, x1, x2, x3, velocity_of_time, v1, v2, v3] for each proper time(lambda). """ vecs = list() lambdas = list() crossed_event_horizon = False ODE = RK45(fun=self.f_vec, t0=start_lambda, y0=self.initial_vec, t_bound=end_lambda, **OdeMethodKwargs) _scr = self.scr.value * 1.001 while ODE.t < end_lambda: vecs.append(ODE.y) lambdas.append(ODE.t) ODE.step() if (not crossed_event_horizon) and (ODE.y[1] <= _scr): warnings.warn("particle reached Schwarzchild Radius. ", RuntimeWarning) if stop_on_singularity: break else: crossed_event_horizon = True vecs, lambdas = np.array(vecs), np.array(lambdas) if not return_cartesian: return lambdas, vecs else: cart_vecs = list() for v in vecs: si_vals = (BoyerLindquistDifferential( v[1] * u.m, v[2] * u.rad, v[3] * u.rad, v[5] * u.m / u.s, v[6] * u.rad / u.s, v[7] * u.rad / u.s, self.a, ).cartesian_differential().si_values()) cart_vecs.append( np.hstack((v[0], si_vals[:3], v[4], si_vals[3:]))) return lambdas, np.array(cart_vecs)
# end_tau = 0.01 # step_size = 0.3e-6 # ans = sph_obj.calculate_trajectory(end_lambda=end_tau, OdeMethodKwargs={"stepsize": step_size}) # # Can return ans in Cartesian by: # ans = sph_obj.calculate_trajectory(end_lambda=end_tau, OdeMethodKwargs={"stepsize": step_size}, return_cartesian=True) ''' Bodies - Can define the attractor and the corresponding revolving bodies Plotting and geodesic calculation is easier ''' # defining some bodies: spin_factor = 0.3 * u.m attractor = Body(name='BH', mass=1.989e30 * u.kg, a=spin_factor) bl_obj = BoyerLindquistDifferential(50e5 * u.km, np.pi/2 * u.rad, np.pi * u.rad, 0 * u.km / u.s, 0 * u.rad / u.s, 0 * u.rad / u.s, spin_factor) particle = Body(differential=bl_obj, parent=attractor) geodesic = Geodesic(body=particle, end_lambda=((1 * u.year).to(u.s)).value / 930, step_size=((0.02 * u.min).to(u.s)).value, metric=Kerr) geodesic.trajectory # returns the trajectory values # Plotting the trajectory values obj = GeodesicPlotter() obj.plot(geodesic) obj.show() ''' Symbolic Calculations - Currently SchwarzschildMetric() cannot be called from package: einsteinpy.symbolic
def bl(): return BoyerLindquistDifferential(0. * u.s, 1. * u.m, np.pi / 2 * u.rad, 0.1 * u.rad, 0. * u.m / u.s, 0.1 * u.rad / u.s, 951 * u.rad / u.s)
OdeMethodKwargs=OdeMethodKwargs, ) for _, _ in zip(range(1000), it): pass assert len(w) >= 1 @pytest.mark.parametrize( "bl, M, a, end_lambda, step_size", [ ( BoyerLindquistDifferential( t=0.0 * u.s, r=306.0 * u.m, theta=np.pi / 2.05 * u.rad, phi=np.pi / 2 * u.rad, v_r=0.0 * u.m / u.s, v_th=0.0 * u.rad / u.s, v_p=951.0 * u.rad / u.s, ), 4e24 * u.kg, 2e-3 * u.one, 0.001, 0.5e-6, ), ( BoyerLindquistDifferential( t=0.0 * u.s, r=1e3 * u.m, theta=0.15 * u.rad, phi=np.pi / 2 * u.rad,
from einsteinpy.coordinates import BoyerLindquistDifferential, CartesianDifferential from einsteinpy.metric import Kerr from einsteinpy.utils import kerr_utils, schwarzschild_radius_dimensionless _c = constant.c.value @pytest.mark.parametrize( "coords, time, M, start_lambda, end_lambda, OdeMethodKwargs", [ ( BoyerLindquistDifferential( 306 * u.m, np.pi / 2.05 * u.rad, np.pi / 2 * u.rad, 0 * u.m / u.s, 0 * u.rad / u.s, 951.0 * u.rad / u.s, 2e-3 * u.m, ), 0 * u.s, 4e24 * u.kg, 0.0, 0.001, { "stepsize": 0.5e-6 }, ), ( BoyerLindquistDifferential( 1 * u.km,