简体   繁体   English

使用 Runge-Kutta 求解耦合微分方程

[英]Using Runge-Kutta to solve coupled differential equations

I have a system of coupled equations: the hydrostatic equilibrium equation, the mass continuity equation, and an equation of state of the ideal gas.我有一个耦合方程组:流体静力平衡方程、质量连续性方程和理想气体状态方程。 These are, in mathematical grammer,这些是,在数学语法中,

  1. \\frac{dP}{dr}=- \\rho*g , \\frac{dP}{dr}=- \\rho*g ,

where \\rho is the density and g is the gravitational acceleration.其中\\rho是密度, g是重力加速度。

  1. \\frac{dM}{dr}=4*pi* r^2*\\rho

and

  1. p=\\rho* k_B* T/(\\mu *m_p) , p=\\rho* k_B* T/(\\mu *m_p) ,

where k_B is boltzmann's constant, \\mu is the mean molecular weight, and m_p is the proton mass.其中k_Bm_p常数, \\mu是平均分子量, m_p是质子质量。

I want to solve these coupled equations using the Runge-Kutta numerical technique, and I herein show the python code I have devised to solve this problem:我想使用 Runge-Kutta 数值技术求解这些耦合方程,并在此展示我为解决此问题而设计的 python 代码:

from scipy.constants import m_p,G,k,pi
from pylab import *

#mu may be changed for different molecular composition:
mu=2
def g(r_atm, p_atm):
    T=165
    return 4*pi*r_atm**2*mu*m_p*p_atm/(k*T)

def f(r_atm,p_atm, m_atm):
    T=165
    return -mu*m_p*p_atm*G*m_atm/(k*T*r_atm**2)

def rk4_1(g,f, r0, p0,m0, r1, n):
    r_atm = [0]*(n + 1)
    p_atm = [0]*(n + 1)
    m_atm=[0]*(n + 1)
    h = (r1 - r0)/n
#    h=-20
    r_atm[0]=r0
    p_atm[0]=p0
    m_atm[0]=m0

    for i in range(0,10000000):
        if p_atm[i]<100000:

            k0 = h*g(r_atm[i], p_atm[i])

            l0 = h*f(r_atm[i], p_atm[i], m_atm[i])

            k1 = h*g(r_atm[i] + 0.5*h, p_atm[i] + 0.5*k0)

            l1 = h*f(r_atm[i] + 0.5*h, p_atm[i] + 0.5*l0, m_atm[i]+0.5*k0)

            k2 = h*g(r_atm[i] + 0.5*h, p_atm[i] + 0.5*k1)

            l2 = h*f(r_atm[i] + 0.5*h, p_atm[i] + 0.5*l1, m_atm[i]+0.5*k1)

            k3 = h*g(r_atm[i] + h, p_atm[i] + k2)

            l3 = h*f(r_atm[i] + h, p_atm[i] + l2,  m_atm[i]+k2)

            r_atm[i+1] = r0 + (i+1)*h
            p_atm[i+1] = p_atm[i] + (l0 + 2*l1 + 2*l2 + l3)/6
            m_atm[i+1] = m_atm[i] + (k0 + 2*k1 + 2*k2 + k3)/6

            else:
                break

        return h, r_atm, p_atm, m_atm

h, r_atm, p_atm, m_atm = rk4_1(g,f, 6.991e7, 1e-6*1e5, 1.898e27, 2.0e7,10000000) #bar to pascals (*1e5)

for intial conditions for the pressure, p_atm , radius, r_atm , and mass, m_atm , I use the values I have shown in h, r_atm, p_atm, m_atm = rk4_1(g,f, 6.991e7, 1e-6*1e5, 1.898e27, 2.0e7,10000000) .对于压力p_atm 、半径r_atm和质量m_atm初始条件,我使用我在h, r_atm, p_atm, m_atm = rk4_1(g,f, 6.991e7, 1e-6*1e5, 1.898e27, 2.0e7,10000000) Notice that I am approaching this boundary-value problem from the upper atmosphere (where the initial conditions are given) and progressing downward in the atmosphere (notice that h is negative).请注意,我正在从高层大气(给出初始条件)并在大气中向下推进(注意 h 为负)来解决这个边界值问题。 My intention is to evaluate this numerical integration from 10^-1 Pascals to 100000 Pascals.我的目的是评估这个从10^-1帕斯卡到100000帕斯卡的数值积分。 The result I get from running this code is that the pressure simply blows up to ~1e+123 in three steps, so there is obviously something terribly wrong streaming about, but it would help to have another eye or perspective, for this is the first time I am performing Runga-Kutta methodology.我从运行这段代码中得到的结果是,压力在三个步骤中简单地上升到~1e+123 ,所以显然有一些非常错误的流媒体,但是换个角度或视角会有所帮助,因为这是第一个时间我正在执行 Runga-Kutta 方法。

As Wolph says, dividing by n might simply give you h=0 , depending on which version of Python you're using.正如沃尔夫所说,除以n可能只是给你h=0 ,这取决于你使用的 Python 版本。 If you're using 2.x, you should include from __future__ import division in the beginning, or handle the division in some other way (eg, divide by float(n) ).如果您使用的是 2.x,您应该在开头包含from __future__ import division ,或者以其他方式处理除法(例如,除以float(n) )。 (Oh, and I guess perhaps you also intended to use n in your loop, rather than hard-coding range(0,10000000) ? And there are a couple of indentation errors in the code as it stands, but I guess that's just from posting it here.) (哦,我想也许您还打算在循环中使用n ,而不是硬编码range(0,10000000) ?代码中存在一些缩进错误,但我想这只是来自贴在这里。)

This doesn't seem to be the main problem, though.不过,这似乎不是主要问题。 You say you get a high pressure early;你说你很早就有高压; when I run it, it gets really low?当我运行它时,它变得非常低? Even with proper divisions, I get p_atm[3] = -2.27e+97 , and from that, I start getting infinities ( inf and -inf ) and nan s.即使有适当的划分,我p_atm[3] = -2.27e+97得到p_atm[3] = -2.27e+97 ,然后我开始得到无穷大( inf-inf )和nan s。

It's hard, without knowing the specific problem better, to see if there's an error in your implementation, or if this is simply a matter of numerical instability.在不更好地了解具体问题的情况下,很难查看您的实现中是否存在错误,或者这是否仅仅是数值不稳定的问题。 It looks right to me, but I may very well have missed something (sort of hard to read.) If this is your first time with Runge–Kutta, I'd strongly suggest using an existing implementation rather than trying to get it right yourself.对我来说看起来不错,但我很可能漏掉了一些东西(有点难以阅读。)如果这是您第一次使用 Runge-Kutta,我强烈建议您使用现有的实现,而不是自己尝试把它弄好. Numerical computation and avoiding floating-point issues can be quite challenging.数值计算和避免浮点问题可能非常具有挑战性。 You're already using scipy — why not use their implementation of the R–K method, or related numerical integration solutions?您已经在使用scipy — 为什么不使用他们实现的 R-K 方法或相关的数值积分解决方案? have a look at scipy.integrate , for example.例如,看看scipy.integrate If nothing else, if the scipy integrators can't solve your problem, at least you know more about what your challenges are.如果不出scipy ,如果scipy集成商无法解决您的问题,至少您更了解您的挑战是什么。

Here's a version that uses decimals btw, it seems to work slightly better:这是一个使用小数的版本顺便说一句,它似乎工作得稍微好一点:

from decimal import Decimal as D
from scipy.constants import m_p,G,k,pi

m_p = D(m_p)
G = D(G)
k = D(k)
pi = D(pi)

# mu may be changed for different molecular composition:
mu = D(2)

def g(r_atm, p_atm):
    T = D(165)
    return D(4) * pi * r_atm ** D(2) * mu * m_p * p_atm/(k * T)


def f(r_atm,p_atm, m_atm):
    T = D(165)
    return -mu * m_p * p_atm * G * m_atm/(k * T * r_atm ** D(2))


def rk4_1(g,f, r0, p0,m0, r1, n):
    r_atm = [D(0)] * (n + 1)
    p_atm = [D(0)] * (n + 1)
    m_atm = [D(0)] * (n + 1)
    h = (r1 - r0) / n
    # h = -20
    r_atm[0] = r0
    p_atm[0] = p0
    m_atm[0] = m0

    for i in range(0, 10000000):
        if p_atm[i] < 100000:
            k0 = h * g(r_atm[i], p_atm[i])
            l0 = h * f(r_atm[i], p_atm[i], m_atm[i])
            k1 = h * g(r_atm[i] + D('0.5') * h, p_atm[i] + D('0.5') * k0)
            l1 = h * f(r_atm[i] + D('0.5') * h, p_atm[i] + D('0.5') * l0,
                       m_atm[i]+D('0.5') * k0)
            k2 = h * g(r_atm[i] + D('0.5') * h, p_atm[i] + D('0.5') * k1)
            l2 = h * f(r_atm[i] + D('0.5') * h, p_atm[i] + D('0.5') * l1,
                       m_atm[i]+D('0.5') * k1)
            k3 = h * g(r_atm[i] + h, p_atm[i] + k2)
            l3 = h * f(r_atm[i] + h, p_atm[i] + l2,  m_atm[i]+k2)

            r_atm[i + 1] = r0 + (i + 1) * h
            p_atm[i + 1] = p_atm[i]  +  (l0  +  D('2') * l1  +  D('2') * l2  +
                                         l3)/D('6')
            m_atm[i + 1] = m_atm[i]  +  (k0  +  D('2') * k1  +  D('2') * k2  +  k3)/D('6')

        else:
            break

    return h, r_atm, p_atm, m_atm

h, r_atm, p_atm, m_atm = rk4_1(
    g,
    f,
    D('6.991e7'),
    D('1e-6') * D('1e5'),
    D('1.898e27'),
    D('2.0e7'),
    10000000,
)  # bar to pascals (*1e5)

print 'h', h

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在python中使用Runge-Kutta求解耦合微分方程组 - Solving system of coupled differential equations using Runge-Kutta in python 使用 Runge-Kutta 求解数值四耦合微分方程 - Solving Numerical four coupled differential equations using Runge-Kutta Runge-Kutta实现两个微分方程组 - Runge-Kutta Implementation for a system of two differential equations 在 python 中使用四阶龙格库塔求解 3 个耦合非线性微分方程 - Solving 3 coupled nonlinear differential equations using 4th order Runge Kutta in python 我的 Runge-Kutta 四阶方法中的 numpy.float64 错误,用于一系列微分方程 - numpy.float64 error in my Runge-Kutta 4th-order method for a series of differential equations 使用forloop求解python中的耦合微分方程 - Using a forloop to solve coupled differential equations in python 使用Runge-Kutta 4进行卫星位置计算 - Satellite position computation using Runge-Kutta 4 在Python中使用Runge-Kutta的Lotka-Volterra方程(捕食者被捕食) - Lotka-Volterra equations(predator prey) using Runge-Kutta in Python Runge-Kutta:求解二阶微分方程时出错 - Runge-Kutta : error while solving a second order differential equation 使用 python 中的 4 阶龙格库塔求解方程组 - Solve a system of equations using Runge Kutta of order 4 in python
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM