Runge-Kutta 4 zum Lösen von ODEs Python-Systemen

Aug 26 2020

Ich habe Code für Runge-Kutta 4 zum Lösen von ODE-Systemen geschrieben.
Es funktioniert gut für 1-D-ODE, aber wenn ich versuche zu lösen, habe x'' + kx = 0ich ein Problem beim Versuch, eine vektorielle Funktion zu definieren:

Lassen Sie u1 = xund u2 = x' = u1', dann sieht das System aus wie:

u1' = u2
u2' = -k*u1

Wenn u = (u1,u2)und f(u, t) = (u2, -k*u1), dann müssen wir lösen:

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

Mein gesamter Code lautet:

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()
    

Im Voraus danke.

Antworten

2 PeterMeisrimel Aug 27 2020 at 08:38

Sie sind auf dem richtigen Weg, aber wenn Sie Zeitintegrationsmethoden wie RK auf vektorwertige ODEs anwenden, tun Sie im Wesentlichen genau das Gleiche wie im skalaren Fall, nur mit Vektoren.

Auf diese Weise überspringen Sie die for j in range(len(X_0))Schleife und die zugehörige Indexierung und stellen sicher, dass Sie Anfangswerte als Vektoren (Numpy-Arrays) übergeben.

Bereinigte auch die Indexierung tein wenig und speicherte die Lösung in einer Liste.

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()
1 IvánReyes Aug 26 2020 at 23:22

Das Modell lautet wie folgt: Geben Sie hier die Bildbeschreibung ein

Aus dem Buch Programming for Computations - Python von Langtangen.