我正在尝试使用 python 求解恒星建模的基本方程。我有 ODE 系统和所需的变量:
from scipy.integrate import odeint
from scipy.integrate import solve_bvp
import numpy as np
import matplotlib.pyplot as plt
#Constants (for now)
G = 6.67e-8
X = 0.71
Y = 0.28
Z = 0.01
#Mr is the mass contained within a certain radius
#kappa is opacity
#nabla is the energy transport assuming the whole star is radiative
#rho is density
#r, P, L, T is max radius, pressure, luminosity, and temperature respectively
def coupled_differential_equations(P, T, r, L, Mr):
#rho = (P*(2.1945*1e-3)/(0.0821*T))
#kappa = (4e25*(1+X)*(Z+1e-3)*(P*(2.1945*1e-3)/(0.0821*T)/(T**3.5)))
#nabla = ((3 * 4e25*(1+X)*(Z+1e-3)*(P*(2.1945*1e-3)/(0.0821*T)/(T**3.5)) * L * P)/(16 * np.pi * 1.38e-23 * T**4)*(1 / G * Mr))
dr_dMr = (1 / (4 * np.pi * r**2 * P*(2.1945*1e-3)/(0.0821*T)))
dP_dMr = -((G * Mr) / (4 * np.pi * r**4))
dL_dMr = 9.5 * 10e-37 * X**2 * (P*(2.1945*1e-3)/(0.0821*T))**2 * T**4
dT_dMr = -(((3 * 4e25*(1+X)*(Z+1e-3)*(P*(2.1945*1e-3)/(0.0821*T)/(T**3.5)) * L * P)/(16 * np.pi * 1.38e-23 * T**4)*(1 / G * Mr))*(T/P))*((G * M)/(4 * np.pi * r**4))
return np.vstack([dr_dMr, dP_dMr, dL_dMr, dT_dMr])
#***************************************************************************
def boundary_conditions(ya, yb, P, T, L, Mr):
# Boundary conditions at the center
center_conditions = np.array([ya[0], ya[2], ya[3]])
# Boundary conditions at the surface
surface_conditions = np.array([yb[1], yb[3] - 1e-6, yb[2] - Mr])
return np.concatenate([center_conditions, surface_conditions])
#Current issue is that P, T, r, L, Mr, kappa is not defined outside of the function??? seems to require initial guess but it's a bvp so it shouldn't need one???
# Initial values and range for r
initial_r = 1e-3
final_r = 3.9e5
x = np.linspace(initial_r, final_r, 100)
y_a = np.zeros((4, x.size))
# Solve BVP using solve_bvp
sol = solve_bvp(coupled_differential_equations, boundary_conditions, x, y_a)
# Extract the solution
r_solution = sol.x
y_solution = sol.y
# Plot the results
plt.plot(r_solution, y_solution[0], label='r')
plt.plot(r_solution, y_solution[1], label='P')
plt.plot(r_solution, y_solution[2], label='L')
plt.plot(r_solution, y_solution[3], label='T')
plt.xlabel('r')
plt.legend()
plt.show()
边界条件是恒星的中心和表面。在中心(Mr=0),r=0,l=0。在表面(Mr=M,所有质量),rho=0,T = (L/(8pi(r^2)sigma)^(1/4),其中 sigma 是玻尔兹曼常数。
当我运行代码时,目前显示
sol = solve_bvp(coupled_differential_equations, boundary_conditions, x, y_a)
中的 Coupled_Differential_equations 参数缺少参数,但是当我添加 (Mr, P, T, L, r, kappa) 时,它说变量不是定义的。 scipy手册(https://docs.scipy.org/doc/scipy/reference/ generated/scipy.integrate.solve_bvp.html)在将颂歌系统插入solve_bvp时似乎不需要争论。
我需要有一个初步的猜测(比如拍摄方法)吗?我现在有点不知道该怎么办...
我对编码还很陌生,但如果有人可以提供一些关于如何让solve_bvp工作的指示,或者说实话我做错了什么,我将非常感激!
仍然有很多遗漏,所以这个答案将是不完整的,但我会解决你的一些问题(主要是语法)并告诉你你遗漏了什么。
首先,对于
scipy.integrate.solve_bvp
,ODE 函数签名应该是 f(x, y)
。您目前没有这个,因为您独立传递所有 y
值,并且最后有 x
。它应该是这样的:
def coupled_differential_equations(x, y):
Mr = x
P, T, r, L = y
dr_dMr = (1 / (4 * np.pi * r**2 * P*(2.1945*1e-3)/(0.0821*T)))
dP_dMr = -((G * Mr) / (4 * np.pi * r**4))
dL_dMr = 9.5 * 10e-37 * X**2 * (P*(2.1945*1e-3)/(0.0821*T))**2 * T**4
dT_dMr = -(((3 * 4e25*(1+X)*(Z+1e-3)*(P*(2.1945*1e-3)/(0.0821*T)/(T**3.5)) * L * P)/(16 * np.pi * 1.38e-23 * T**4)*(1 / G * Mr))*(T/P))*((G * Mr)/(4 * np.pi * r**4))
return np.vstack([dr_dMr, dP_dMr, dL_dMr, dT_dMr])
(我还用
M
替换了 Mr
,因为 M
未定义,但也许 M
应该在某个地方定义。
其次,边界条件函数应该具有函数签名
bc(ya, yb)
,但是您再次传递了更多。这里,ya
和yb
将分别包含初始和最终网格位置处的P
、T
、r
和L
(按顺序)的值。您有一个由 4 个一阶 ODE 组成的系统,因此只能指定 4 个边界条件。这是一个数学要求(否则你会过度定义系统)。您的边界条件应如下所示:
def boundary_conditions(ya, yb):
# At the center (Mr=0), r=0, and l=0
# At the surface (Mr=M, all the mass), rho=0, T = (L/(8pi(r^2)sigma)^(1/4),
# where sigma is the Boltzman constant.
center_conditions = [ya[2], ya[3]]
surface_conditions = [yb[1] - (L/(8*np.pi*yb[2]**2*sigma))**0.25, ??]
return np.array(center_conditions + surface_conditions)
这里的问题是(1)你缺少一个边界条件(我不确定你如何从其他值中得到
rho
)和(2)你需要在某处定义西格玛(这很简单)。
一旦有了这些,您就需要修复调用函数的方式。由于
Mr
是您的自变量而不是 r
(我不确定您为什么这样做,但您确实这样做了),因此您的网格 x
必须是 Mr
的值范围。我不知道这些是什么,所以你必须填写它们。
Mr_initial = ??
Mr_final = ??
Mr = np.linspace(Mr_initial, Mr_final, 100)
剩下的几行是:
y0 = np.zeros((4, Mr.size))
sol = solve_bvp(coupled_differential_equations, boundary_conditions, Mr, y0)
y_solutions = sol.y
fig, axes = plt.subplots(1, 4)
labels = ["P", "T", "r", "L"]
for y_sol, label, ax in zip(y_solutions, plot_labels, axes):
ax.plot(Mr, y_sol)
ax.set_xlabel("Mr")
ax.set_ylabel(label)
fig.show()
注意:我更改了绘图标签的顺序以匹配
coupled_differential_equations
中的顺序(只要保持一致,顺序并不重要),并且我将绘图放在自己的子图中,因为它们可能有不同的内容秤。