如何阻止Runge-Kutta2(Heun)方法爆炸?

问题描述 投票:0回答:1

我目前正在尝试使用一些通用的显式Runge-Kutta方法来编写一些python代码,以解决一阶ODE的任意系统,该方法由值alpha,gamma(均为维m的向量)和beta(值为L的下三角矩阵)定义用户传递的Butcher表的维度mxm)。我的代码似乎适用于单个ODE,并在几个不同的示例上对其进行了测试,但是我正努力将我的代码推广到矢量值ODE(即系统)。

特别是,我尝试使用我的代码中提供的Butcher Tableau值定义的Heun方法来求解Van der Pol振荡器ODE(简化为一阶系统),但收到错误

  • “ RuntimeWarning:在double_scalars f = lambda t,u: np.array(... etc)中遇到溢出”和
  • “ RuntimeWarning:在添加kvec[i] = f(t+alpha[i]*h,y+h*sum)中遇到无效的值]

紧跟着我的解决方案向量明显爆炸了。请注意,下面注释掉的代码是我尝试并已正确解决的单个ODE的示例之一。谁能帮忙吗?这是我的代码:

import numpy as np 

def rk(t,y,h,f,alpha,beta,gamma):
    '''Runga Kutta iteration'''
    return y + h*phi(t,y,h,f,alpha,beta,gamma)

def phi(t,y,h,f,alpha,beta,gamma):
    '''Phi function for the Runga Kutta iteration'''
    m = len(alpha)
    count = np.zeros(len(f(t,y)))
    kvec = k(t,y,h,f,alpha,beta,gamma)
    for i in range(1,m+1):
        count = count + gamma[i-1]*kvec[i-1]
    return count

def k(t,y,h,f,alpha,beta,gamma):
    '''returning a vector containing each step k_{i} in the m step Runga Kutta method'''
    m = len(alpha)
    kvec = np.zeros((m,len(f(t,y))))
    kvec[0] = f(t,y)
    for i in range(1,m):
        sum = np.zeros(len(f(t,y)))
        for l in range(1,i+1):
            sum = sum + beta[i][l-1]*kvec[l-1]
        kvec[i] = f(t+alpha[i]*h,y+h*sum)
    return kvec

def timeLoop(y0,N,f,alpha,beta,gamma,h,rk):
    '''function that loops through time using the RK method'''
    t  = np.zeros([N+1])
    y  = np.zeros([N+1,len(y0)])
    y[0] = y0
    t[0] = 0
    for i in range(1,N+1):
        y[i] = rk(t[i-1],y[i-1], h, f,alpha,beta,gamma)
        t[i] = t[i-1]+h
    return t,y

#################################################################

'''f  = lambda t,y: (c-y)**2
Y  = lambda t: np.array([(1+t*c*(c-1))/(1+t*(c-1))])
h0 = 1
c = 1.5
T = 10
alpha = np.array([0,1])
gamma = np.array([0.5,0.5])
beta = np.array([[0,0],[1,0]])
eff_rk   = compute(h0,Y(0),T,f,alpha,beta,gamma,rk, Y,11)'''

#constants
mu = 100
T = 1000
h = 0.01
N = int(T/h)

#initial conditions
y0 = 0.02
d0 = 0
init = np.array([y0,d0])

#Butcher Tableau for Heun's method
alpha = np.array([0,1])
gamma = np.array([0.5,0.5])
beta = np.array([[0,0],[1,0]])

#rhs of the ode system
f = lambda t,u: np.array([u[1],mu*(1-u[0]**2)*u[1]-u[0]])

#solving the system
time, sol = timeLoop(init,N,f,alpha,beta,gamma,h,rk)
print(sol)
python numerical-methods ode differential-equations runge-kutta
1个回答
0
投票
您的步长不够小。具有mu=100的Van der Pol振荡器是一种快速慢速系统,在模式切换时具有非常陡峭的匝数,因此相当刚性。对于显式方法,这需要较小的步长,最小的合理步长为1e-51e-6。您已经获得了针对h=0.001的极限循环的解决方案,其最大速度为150。
© www.soinside.com 2019 - 2024. All rights reserved.