def delta( r, M, a, Q, c=constant.c.value, G=constant.G.value, Cc=constant.coulombs_const.value ): """ Returns the value r^2 - Rs * r + a^2 Specific to Boyer-Lindquist coordinates Parameters ---------- r : float Component r in vector M : float Mass of the massive body a : float Any constant Q : float Charge on the massive body c : float Speed of light G : float Gravitational constant Cc : float Coulomb's constant Returns ------- float The value r^2 - Rs * r + a^2 + Rq^2 """ Rs = utils.schwarzschild_radius_dimensionless(M, c, G) return (r ** 2) - (Rs * r) + (a ** 2) + (charge_length_scale(Q, c, G, Cc) ** 2)
def radius_ergosphere(M, a, theta=np.pi / 2, coord="BL", c=constant.c.value, G=constant.G.value): """ Calculate the radius of ergospere of Kerr black hole at a specific azimuthal angle Parameters ---------- M : float Mass of massive body a : float Black hole spin factor theta : float Angle from z-axis in Boyer-Lindquist coordinates in radians. Defaults to pi/2. coord : str Output coordinate system. 'BL' for Boyer-Lindquist & 'Spherical' for spherical. Defaults to 'BL'. Returns ------- ~numpy.array [Radius of ergosphere(R), angle from z axis(theta)] in BL/Spherical coordinates """ Rs = schwarzschild_radius_dimensionless(M, c, G) Re = 0.5 * (Rs + np.sqrt((Rs**2) - 4 * (a**2) * (np.cos(theta)**2))) if coord == "BL": ans = np.array([Re, theta], dtype=float) else: ans = utils.CartesianToSpherical_pos( utils.BLToCartesian_pos(np.array([Re, theta, 0.0]), a))[:2] return ans
def scaled_spin_factor(a, M, c=constant.c.value, G=constant.G.value): """ Returns a scaled version of spin factor(a) Parameters ---------- a : float Number between 0 & 1 M : float Mass of massive body c : float Speed of light. Defaults to speed in SI units. G : float Gravitational constant. Defaults to Gravitaional Constant in SI units. Returns ------- float Scaled spinf factor to consider changed units Raises ------ ValueError If a not between 0 & 1 """ half_scr = (schwarzschild_radius_dimensionless(M, c, G)) / 2 if a < 0 or a > 1: raise ValueError("a to be supplied between 0 and 1") return a * half_scr
def event_horizon(M, a, theta=np.pi / 2, coord="BL", c=constant.c.value, G=constant.G.value): """ Calculate the radius of event horizon of Kerr black hole Parameters ---------- M : float Mass of massive body a : float Black hole spin factor theta : float Angle from z-axis in Boyer-Lindquist coordinates in radians. Mandatory for coord=='Spherical'. Defaults to pi/2. coord : str Output coordinate system. 'BL' for Boyer-Lindquist & 'Spherical' for spherical. Defaults to 'BL'. Returns ------- ~numpy.array [Radius of event horizon(R), angle from z axis(theta)] in BL/Spherical coordinates """ Rs = schwarzschild_radius_dimensionless(M, c, G) Rh = 0.5 * (Rs + np.sqrt((Rs**2) - 4 * (a**2))) if coord == "BL": ans = np.array([Rh, theta], dtype=float) else: ans = (BoyerLindquist(Rh * u.m, theta * u.rad, 0.0 * u.rad, a * u.m).to_spherical().si_values()[:2]) return ans
def test_radius_ergosphere_for_nonrotating_case(): M = 5e27 a = 0.0 _scr = schwarzschild_radius_dimensionless(M) a1 = kerr_utils.radius_ergosphere(M, a, np.pi / 5) a2 = kerr_utils.radius_ergosphere(M, a, np.pi / 5, "Spherical") assert_allclose(a1, a2, rtol=1e-4, atol=0.0) assert_allclose(a1[0], _scr, rtol=1e-4, atol=0.0)
def test_event_horizon_for_nonrotating_case(): M = 5e27 a = 0.0 _scr = schwarzschild_radius_dimensionless(M) a1 = kerr_utils.event_horizon(M, a, np.pi / 4) a2 = kerr_utils.event_horizon(M, a, np.pi / 4, "Spherical") assert_allclose(a1, a2, rtol=1e-4, atol=0.0) assert_allclose(a1[0], _scr, rtol=1e-4, atol=0.0)
def radius_ergosphere( M, a, Q, theta=np.pi / 2, coord="BL", c=constant.c.value, G=constant.G.value, Cc=constant.coulombs_const.value, ): """ Calculate the radius of ergospere of Kerr-Newman black hole at a specific azimuthal angle Parameters ---------- M : float Mass of massive body a : float Black hole spin factor Q : float Charge on the black hole theta : float Angle from z-axis in Boyer-Lindquist coordinates in radians. Mandatory for coord=='Spherical'. Defaults to pi/2. coord : str Output coordinate system. 'BL' for Boyer-Lindquist & 'Spherical' for spherical. Defaults to 'BL'. c : float Speed of light G : float Gravitational constant Cc : float Coulomb's constant Returns ------- ~numpy.array [Radius of event horizon(R), angle from z axis(theta)] in BL/Spherical coordinates """ Rs = schwarzschild_radius_dimensionless(M, c, G) rQsq = (Q**2) * G * Cc / c**4 Rh = 0.5 * Rs + np.sqrt((Rs**2) / 4 - a**2 * np.cos(theta)**2 - rQsq) if coord == "BL": ans = np.array([Rh, theta], dtype=float) else: ans = (BoyerLindquist(Rh * u.m, theta * u.rad, 0.0 * u.rad, a * u.m).to_spherical().si_values()[:2]) return ans
def test_calculate_trajectory(coords, time, M, start_lambda, end_lambda, OdeMethodKwargs): _scr = schwarzschild_radius_dimensionless(M) obj = Kerr.from_BL(coords, M, time) ans = obj.calculate_trajectory( start_lambda=start_lambda, end_lambda=end_lambda, OdeMethodKwargs=OdeMethodKwargs, ) ans = ans[1] testarray = list() for i in ans: g = kerr_utils.metric(i[1], i[2], M.value, coords.a.to(u.m).value) testarray.append(g[0][0] * (i[4]**2) + g[1][1] * (i[5]**2) + g[2][2] * (i[6]**2) + g[3][3] * (i[7]**2) + 2 * g[0][3] * i[4] * i[7]) testarray = np.array(testarray, dtype=float) comparearray = np.ones(shape=ans[:, 4].shape, dtype=float) assert_allclose(testarray, comparearray, 1e-4)
def delta(r, M, a, c=constant.c.value, G=constant.G.value): """ Returns the value r^2 - Rs * r + a^2 Specific to Boyer-Lindquist coordinates Parameters ---------- r : float Component r in vector M : float Mass of massive body a : float Any constant Returns ------- float The value r^2 - Rs * r + a^2 """ Rs = schwarzschild_radius_dimensionless(M, c, G) return (r**2) - (Rs * r) + (a**2)
def radius_ergosphere( M, a, theta=np.pi / 2, coord="BL", c=constant.c.value, G=constant.G.value ): """ Calculate the radius of ergospere of Kerr black hole at a specific azimuthal angle Parameters ---------- M : float Mass of massive body a : float Black hole spin factor theta : float Angle from z-axis in Boyer-Lindquist coordinates in radians. Defaults to pi/2. coord : str Output coordinate system. 'BL' for Boyer-Lindquist & 'Spherical' for spherical. Defaults to 'BL'. c : float Speed of light G : float Gravitational constant Returns ------- ~numpy.array [Radius of ergosphere(R), angle from z axis(theta)] in BL/Spherical coordinates """ Rs = schwarzschild_radius_dimensionless(M, c, G) Re = 0.5 * (Rs + np.sqrt((Rs ** 2) - 4 * (a ** 2) * (np.cos(theta) ** 2))) if coord == "BL": ans = np.array([Re, theta], dtype=float) else: ans = ( BoyerLindquist(Re * u.m, theta * u.rad, 0.0 * u.rad, a * u.m) .to_spherical() .si_values()[:2] ) return ans
def metric(r, theta, M, a, c=constant.c.value, G=constant.G.value): """ Returns the Kerr Metric Parameters ---------- r : float Distance from the centre theta : float Angle from z-axis M : float Mass of massive body a : float Black Hole spin factor c : float Speed of light Returns ------- ~numpy.array Numpy array of shape (4,4) """ Rs = schwarzschild_radius_dimensionless(M, c, G) m = np.zeros(shape=(4, 4), dtype=float) sg, dl = sigma(r, theta, a), delta(r, M, a, c, G) c2 = c ** 2 # set the diagonal/off-diagonal terms of metric m[0, 0] = 1 - (Rs * r / sg) m[1, 1] = (sg / dl) * (-1 / c2) m[2, 2] = -1 * sg / c2 m[3, 3] = ( (-1 / c2) * ((r ** 2) + (a ** 2) + (Rs * r * (np.sin(theta) ** 2) * ((a ** 2) / sg))) * (np.sin(theta) ** 2) ) m[0, 3] = m[3, 0] = Rs * r * a * (np.sin(theta) ** 2) / (sg * c) return m
def dmetric_dx( r, theta, M, a, Q, c=constant.c.value, G=constant.G.value, Cc=constant.coulombs_const.value, ): """ Returns differentiation of each component of Kerr-Newman metric tensor w.r.t. t, r, theta, phi Parameters ---------- r : float Distance from the centre theta : float Angle from z-axis M : float Mass of the massive body a : float Black Hole spin factor Q : float Charge on the massive body c : float Speed of light G : float Gravitational constant Cc : float Coulomb's constant Returns ------- dmdx : ~numpy.array Numpy array of shape (4,4,4) dmdx[0], dmdx[1], dmdx[2] & dmdx[3] is differentiation of metric w.r.t. t, r, theta & phi respectively """ Rs = utils.schwarzschild_radius_dimensionless(M, c, G) dmdx = np.zeros((4, 4, 4), dtype=float) rh2, dl = rho(r, theta, a) ** 2, delta(r, M, a, Q, c, G, Cc) c2 = c ** 2 # metric is invariant on t & phi # differentiation of metric wrt r def due_to_r(): nonlocal dmdx drh2dr = 2 * r dddr = 2 * r - Rs dmdx[1, 0, 0] = (dddr * rh2 - drh2dr * (dl - (a * np.sin(theta)) ** 2)) / ( rh2 ** 2 ) dmdx[1, 1, 1] = (-1 / (c2 * (dl ** 2))) * (drh2dr * dl - dddr * rh2) dmdx[1, 2, 2] = -drh2dr / c2 dmdx[1, 3, 3] = ((np.sin(theta) ** 2) / (c2 * (rh2 ** 2))) * ( ( (((a * np.sin(theta)) ** 2) * dddr - 4 * (r ** 3) - 4 * (r * (a ** 2))) * rh2 ) - (drh2dr * (((a * np.sin(theta)) ** 2) * dl - ((r ** 2 + a ** 2) ** 2))) ) dmdx[1, 0, 3] = dmdx[1, 3, 0] = ( (-a) * (np.sin(theta) ** 2) / (c * (rh2 ** 2)) ) * ((dddr - 2 * r) * rh2 - drh2dr * (dl - r ** 2 - a ** 2)) # differentiation of metric wrt theta def due_to_theta(): nonlocal dmdx drh2dth = -2 * (a ** 2) * np.cos(theta) * np.sin(theta) dmdx[2, 0, 0] = ( (-2 * (a ** 2) * np.sin(theta) * np.cos(theta)) * rh2 - drh2dth * (dl - ((a * np.sin(theta)) ** 2)) ) / (rh2 ** 2) dmdx[2, 1, 1] = -drh2dth / (c2 * dl) dmdx[2, 2, 2] = -drh2dth / c2 dmdx[2, 3, 3] = (1 / (c2 * (rh2 ** 2))) * ( ( ( (4 * (a ** 2) * (np.sin(theta) ** 3) * np.cos(theta) * dl) - (2 * np.sin(theta) * np.cos(theta) * ((r ** 2 + a ** 2) ** 2)) ) * rh2 ) - ( drh2dth * (((a * np.sin(theta)) ** 2) * dl - ((r ** 2 + a ** 2) ** 2)) * (np.sin(theta) ** 2) ) ) dmdx[2, 0, 3] = dmdx[2, 3, 0] = ( (-a * (dl - r ** 2 - a ** 2)) / (c * (rh2 ** 2)) ) * ( (2 * np.sin(theta) * np.cos(theta) * rh2) - (drh2dth * (np.sin(theta) ** 2)) ) due_to_r() due_to_theta() return dmdx
def test_scaled_spin_factor(): a = 0.8 M = 5e24 a1 = kerr_utils.scaled_spin_factor(a, M) a2 = schwarzschild_radius_dimensionless(M) * a * 0.5 assert_allclose(a2, a1, rtol=1e-9)
def dmetric_dx(r, theta, M, a, c=constant.c.value, G=constant.G.value): """ Returns differentiation of each component of Kerr metric tensor w.r.t. t, r, theta, phi Parameters ---------- r : float Distance from the centre theta : float Angle from z-axis M : float Mass of massive body a : float Black Hole spin factor c : float Speed of light Returns ------- dmdx : ~numpy.array Numpy array of shape (4,4,4) dmdx[0], dmdx[1], dmdx[2] & dmdx[3] is differentiation of metric w.r.t. t, r, theta & phi respectively """ Rs = schwarzschild_radius_dimensionless(M, c, G) dmdx = np.zeros(shape=(4, 4, 4), dtype=float) sg, dl = sigma(r, theta, a), delta(r, M, a, c, G) c2 = c**2 # metric is invariant on t & phi # differentiation of metric wrt r def due_to_r(): nonlocal dmdx dsdr = 2 * r dddr = 2 * r - Rs tmp = (Rs * (sg - r * dsdr) / sg) * (1 / sg) dmdx[1, 0, 0] = -1 * tmp dmdx[1, 1, 1] = (-1 / c2) * (dsdr - (sg * (dddr / dl))) / dl dmdx[1, 2, 2] = (-1 / c2) * dsdr dmdx[1, 3, 3] = ((-1 / c2) * (2 * r + (a**2) * (np.sin(theta)**2) * tmp) * (np.sin(theta)**2)) dmdx[1, 0, 3] = dmdx[1, 3, 0] = (1 / c) * (a * (np.sin(theta)**2) * tmp) # differentiation of metric wrt theta def due_to_theta(): nonlocal dmdx dsdth = -2 * (a**2) * np.cos(theta) * np.sin(theta) tmp = (-1 / sg) * Rs * r * dsdth / sg dmdx[2, 0, 0] = -1 * tmp dmdx[2, 1, 1] = (-1 / c2) * (dsdth / dl) dmdx[2, 2, 2] = (-1 / c2) * dsdth dmdx[2, 3, 3] = (-1 / c2) * (2 * np.sin(theta) * np.cos(theta) * ((r**2) + (a**2)) + tmp * (a**2) * (np.sin(theta)**4) + (4 * (np.sin(theta)**3) * np.cos(theta) * (a**2) * r * Rs / sg)) dmdx[2, 0, 3] = dmdx[2, 3, 0] = (a / c) * ( (np.sin(theta)**2) * tmp + (2 * np.sin(theta) * np.cos(theta) * Rs * r / sg)) due_to_r() due_to_theta() return dmdx