You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Scipy实现圆盘立体角计算的结果不符问题排查

圆盘立体角计算实现与测试用例不符问题

问题背景

参考论文《Solid Angle Of A Disk OffAxis》实现圆盘立体角计算,将论文公式转为Python代码(使用Scipy椭圆积分函数),但计算结果与论文测试用例不一致,推测是数学符号与Scipy函数的映射存在误解。

观测点P的位置由圆盘半径$r_m$、观测点投影到圆盘的径向距离$r_O$、观测点与圆盘的高度距离$L$决定,论文根据$r_O$与$r_m$的关系提供了3种计算公式。

测试用例

论文提供基于$r_O/r_m$和$L/r_m$比值的测试数据,已解析为Python DataFrame,代码如下:

import pandas as pd
import numpy as np

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)

实现代码

已实现包含Heuman Lambda函数、椭圆积分函数及最终立体角计算函数disk_SA_的代码:

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)

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)

调试情况

针对$r_O=r_m$的简单情况,已验证$R_{max}$、参数$k$的计算逻辑正确,且确认使用Scipy的ellipk实现Legendre第一类完全椭圆积分$K(k)$,但计算结果仍与测试用例不符,请求定位错误。

内容的提问来源于stack exchange,提问作者mocquin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 05:44:56