设置
设置如下:观察点P位于磁盘上是否位于磁盘上,具体取决于磁盘半径$ r_m $,以及观察点P的径向距离(投影到磁盘上到O )R_O。该问题的另一个重要参数是磁盘和观察点之间的高度距离,指出l纸张提供了3个公式此后显示的公式,具体取决于$ r_o $和$ r_m $:import pandas as pd
data = [
0, 3.4732594, np.nan , 0.5,
0.2, 3.4184435, 3.41844, 0.5,
0.4, 3.2435434, 3.24354, 0.5,
0.6, 2.9185178, 2.91852, 0.5,
0.8, 2.4122535, 2.41225, 0.5,
1.0, 1.7687239, 1.76872, 0.5,
1.2, 1.1661307, 1.16614, 0.5,
1.4, 0.7428889, 0.742893, 0.5,
1.6, 0.4841273, 0.484130, 0.5,
1.8, 0.3287007, 0.328702, 0.5,
2.0, 0.2324189, 0.232420, 0.5,
0, 1.8403024, np.nan , 1,
0.2, 1.8070933, 1.80709, 1,
0.4, 1.7089486, 1.70895, 1,
0.6, 1.5517370, 1.55174, 1,
0.8, 1.3488367, 1.34883, 1,
1.0, 1.1226876, 1.12269, 1,
1.2, 0.9003572, 0.900369, 1,
1.4, 0.7039130, 0.703917, 1,
1.6, 0.5436956, 0.543705, 1,
1.8, 0.4195415, 0.419543, 1,
2.0, 0.3257993, 0.325801, 1,
0, 1.0552591, np.nan, 1.5,
0.2, 1.0405177, 1.04052, 1.5,
0.4, 0.9975504, 0.997549, 1.5,
0.6, 0.9301028, 0.930101, 1.5,
0.8, 0.8441578, 0.844152, 1.5,
1.0, 0.7472299, 0.747229, 1.5,
1.2, 0.6472056, 0.647217, 1.5,
1.4, 0.5509617, 0.550965, 1.5,
1.6, 0.4632819, 0.463285, 1.5,
1.8, 0.3866757, 0.386678, 1.5,
2.0, 0.3217142, 0.321716, 1.5,
0, 0.6633335, np.nan , 2,
0.2, 0.6566352, 0.656633, 2,
0.4, 0.6370508, 0.637049, 2,
0.6, 0.6060694, 0.606068, 2,
0.8, 0.5659755, 0.565969, 2,
1.0, 0.5195359, 0.519535, 2,
1.2, 0.4696858, 0.469697, 2,
1.4, 0.4191714, 0.419175, 2,
1.6, 0.3702014, 0.370204, 2,
1.8, 0.3243908, 0.324392, 2,
2.0, 0.282707, 0.282709, 2,
]
columns = ['ro_rm', 'Omega', 'Omega_a', 'L_rm']
reshaped_data = [data[i:i + 4] for i in range(0, len(data), 4)]
df = pd.DataFrame(reshaped_data, columns=columns)
论文中提供了总体数学推导,我有兴趣仅复制Python函数中的最终方程式 - 不幸的是,我在所有3个情况下都会获得不同的结果(RO
RM),我怀疑我的代码中的某个地方有一个错误。import numpy as np
from scipy.special import ellipkinc, ellipk, ellipe, ellipeinc
def E(k):
"""Complete elliptic integral of the second kind."""
return ellipe(k)
def E_(ksi, k):
"""Incomplete elliptic integral of the second kind."""
return ellipeinc(ksi, k)
def K(k):
"""Complete elliptic integral of the first kind."""
return ellipk(k)
def F(ksi, k):
"""Incomplete elliptic integral of the first kind."""
return ellipkinc(ksi, k)
import numpy as np
from scipy.special import ellipkinc, ellipk, ellipe, ellipeinc
def GAMMA0(ksi, k):
"""
Heuman's Lambda function (Λ₀(ξ, k)).
- ksi: ξ, calculated from the formula in the image.
- k: Modulus of the elliptic integrals.
"""
kp = np.sqrt(1 - k**2) # Complementary modulus
# Complete and incomplete elliptic integrals
K_k = ellipk(k) # K(k): Complete elliptic integral of the first kind
E_k = ellipe(k) # E(k): Complete elliptic integral of the second kind
F_ksi_kp = ellipkinc(ksi, kp) # F(ξ, k'): Incomplete elliptic integral of the first kind
E_ksi_kp = ellipeinc(ksi, kp) # E(ξ, k'): Incomplete elliptic integral of the second kind
# Formula for Λ₀(ξ, k)
return (2 / np.pi) * (E_k * F_ksi_kp + K_k * E_ksi_kp - K_k * F_ksi_kp)
def compute_xi(alpha, k):
"""
Compute ξ (ksi) based on the formula:
ξ = sin⁻¹(sqrt((α² - k²) / (α² * k'²))).
- alpha: α, related to the geometry of the system.
- k: Modulus of the elliptic integrals.
"""
kp = np.sqrt(1 - k**2) # Complementary modulus
numerator = alpha**2 - k**2
denominator = alpha**2 * kp**2
sqrt_argument = numerator / denominator
return np.arcsin(np.sqrt(sqrt_argument))
def disk_SA_(L, r_m, r_o):
"""Solid angle of a disk viewed from an off-axis point.
- L: Height above the disk (z coordinate).
- r_m: Radius of the disk.
- r_o: Radial position of the observation point.
"""
R_max = np.sqrt(L**2 + (r_o + r_m)**2)
R1 = np.sqrt(L**2 + (r_o - r_m)**2)
k = np.sqrt(4 * r_o * r_m / (L**2 + (r_o + r_m)**2))
alpha = np.sqrt(4 * r_o * r_m / ((r_o + r_m)**2))
ksi = compute_xi(alpha, k)
if r_o <= r_m:
if r_o == r_m:
return np.pi - 2 * L / R_max * K(k)
elif r_o == 0:
return 2 * np.pi * (1 - L / R_max)
else:
return 2 * np.pi - 2 * L / R_max * K(k) - np.pi * GAMMA0(ksi, k)
else:
return -2 * L / R_max * K(k) + np.pi * GAMMA0(ksi, k)
最终功能
disk_SA_
depebugging
casince ro = rm具有最简单的方程式,仅依赖于rmax和k(k),我首先检查这些数量。 rmax此数量是根据基本参数R0,RM和L(在等式(12)之后)给出的:
所以我的代码似乎还可以。LLE的移动
R_max = np.sqrt(L**2 + (r_o + r_m)**2)
在等式(12)之后还给出了中间变量k,AS:
所以我的代码
K(k)
现在只有K实现要检查。论文指出:
SoK是Legendre的第一类椭圆形成部分,如果我没记错的话,它将在Scipy中在以下网址实现:Https://docs.scipy.org/doc/doc/scipy/scipy/reference/reference/generate/generated/generated/scipy.special.special。 ellipk.html
so使用
k = np.sqrt(4 * r_o * r_m / (L**2 + (r_o + r_m)**2))
def K(k):
"""Complete elliptic integral of the first kind."""
return ellipk(k)
正确的最终结果是正确的。这不是根据测试案例之间的比较:
np.pi - 2 * L / R_max * K(k)
lo/rm = 1的索引= 4的示例(所有结果都是错误的,但是专注于ro = rm允许更容易固定错误,因为方程更简单):
文档r_m = 1
r_os = np.arange(0, 2.2, 0.2)
Ls = [0.5, 1, 1.5, 2]
data = []
for r_o in r_os:
for L in Ls:
sa = disk_SA_(L, r_m, r_o)
sa_integ = disk_SA(0*m, r_o*m, L*m, r_m*m, method='dblquad').value
sa_integ_trapz = disk_SA(0*m, r_o*m, L*m, r_m*m, method='trapz').value
data.append([r_o, r_m, r_o/r_m, L, L/r_m, sa, sa_integ, sa_integ_trapz])
df_results = pd.DataFrame(
data, columns=["r_o", "r_m", "ro_rm", "L", "L_rm", "Omega_implem"]
)
df = pd.merge(df, df_results, on=["ro_rm", 'L_rm'])
df['implem_ok'] = np.isclose(df['Omega'], df['Omega_implem'])
指出存在不同的参数化。看起来Scipy's使用$ m = k^2 $作为参数,因此您要将$ k^2 $传递到其中。