用于解决ODE系统Python的Runge-Kutta 4 [英] Runge-Kutta 4 for solving systems of ODEs Python

查看:186
本文介绍了用于解决ODE系统Python的Runge-Kutta 4的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我为Runge-Kutta 4编写了用于求解ODE系统的代码。

对于一维ODE来说很好用,但是当我尝试求解 x''+ kx = 0 时,我在定义一个向量函数:

I wrote code for Runge-Kutta 4 for solving system of ODEs.
It works fine for 1-D ODE but when I try to solve x'' + kx = 0 I have a problem trying to define a vectorial function:

u1 = x u2 = x'= u1',则系统如下所示:

Let u1 = x and u2 = x' = u1', then the system looks like:

u1' = u2
u2' = -k*u1

如果 u =(u1,u2) f(u,t)=(u2,-k * u1),那么我们需要解决:

If u = (u1,u2) and f(u, t) = (u2, -k*u1), then we need to solve:

u' = f(u, t)


def f(u,t, omega=2):
    u, v = u
    return np.asarray([v, -omega**2*u])

我的整个代码是:

import numpy as np

def ode_RK4(f, X_0, dt, T):    
    N_t = int(round(T/dt))
    #  Create an array for the functions ui 
    u = np.zeros((len(X_0),N_t+1)) # Array u[j,:] corresponds to the j-solution
    t = np.linspace(0, N_t*dt, N_t + 1)
    # Initial conditions
    for j in range(len(X_0)):
        u[j,0] = X_0[j]
    # RK4
    for j in range(len(X_0)):
        for n in range(N_t):
            u1 = f(u[j,n] + 0.5*dt* f(u[j,n], t[n])[j], t[n] + 0.5*dt)[j]
            u2 = f(u[j,n] + 0.5*dt*u1, t[n] + 0.5*dt)[j]
            u3 = f(u[j,n] + dt*u2, t[n] + dt)[j]
            u[j, n+1] = u[j,n] + (1/6)*dt*( f(u[j,n], t[n])[j] + 2*u1 + 2*u2 + u3)
    
    return u, t

def demo_exp():
    import matplotlib.pyplot as plt
    
    def f(u,t):
        return np.asarray([u])

    u, t = ode_RK4(f, [1] , 0.1, 1.5)
    
    plt.plot(t, u[0,:],"b*", t, np.exp(t), "r-")
    plt.show()
    
def demo_osci():
    import matplotlib.pyplot as plt
    
    def f(u,t, omega=2):
        # u, v = u Here I've got a problem
        return np.asarray([v, -omega**2*u])
    
    u, t = ode_RK4(f, [2,0], 0.1, 2)
    
    for i in [1]:
        plt.plot(t, u[i,:], "b*")
    plt.show()
    

预先,谢谢。

推荐答案

您在正确的道路上,但是将RK等时间积分方法应用于矢量值ODE时,基本上可以做到完全相同

You are on the right path, but when applying time-integration methods such as RK to vector valued ODEs, one essentially does the exact same thing as in the scalar case, just with vectors.

因此,您跳过范围(len(X_0))j中 循环和关联的索引编制,并确保将初始值作为向量(numpy数组)传递。

Thus, you skip the for j in range(len(X_0)) loop and associated indexation and you make sure that you pass initial values as vectors (numpy arrays).

还清理了 t

Also cleaned up the indexation for t a little and stored the solution in a list.

import numpy as np

def ode_RK4(f, X_0, dt, T):    
    N_t = int(round(T/dt))
    # Initial conditions
    usol = [X_0]
    u = np.copy(X_0)
    
    tt = np.linspace(0, N_t*dt, N_t + 1)
    # RK4
    for t in tt[:-1]:
        u1 = f(u + 0.5*dt* f(u, t), t + 0.5*dt)
        u2 = f(u + 0.5*dt*u1, t + 0.5*dt)
        u3 = f(u + dt*u2, t + dt)
        u = u + (1/6)*dt*( f(u, t) + 2*u1 + 2*u2 + u3)
        usol.append(u)
    return usol, tt

def demo_exp():
    import matplotlib.pyplot as plt
    
    def f(u,t):
        return np.asarray([u])

    u, t = ode_RK4(f, np.array([1]) , 0.1, 1.5)
    
    plt.plot(t, u, "b*", t, np.exp(t), "r-")
    plt.show()
    
def demo_osci():
    import matplotlib.pyplot as plt
    
    def f(u,t, omega=2):
        u, v = u 
        return np.asarray([v, -omega**2*u])
    
    u, t = ode_RK4(f, np.array([2,0]), 0.1, 2)
    
    u1 = [a[0] for a in u]
    
    for i in [1]:
        plt.plot(t, u1, "b*")
    plt.show()

这篇关于用于解决ODE系统Python的Runge-Kutta 4的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆