简体   繁体   中英

System of ODEs using Runge-kutta fourth order in Python

I am writing a python program to solve 2x2 system of First Order Differential Equations given both initial conditions. My code:

from math import *
import numpy as np

np.set_printoptions(precision=6) ## control numpy's decimal output :)

form1 = raw_input('Enter the 1st function of u & v only >> ')
form2 = raw_input('Enter the 2nd function of u & v only >> ')
start = input("Enter the lower limit of the interval >> ")
stop = input("Enter the upper limit of the interval >> ")
h = input("Using step size? ")

N = int(np.round((stop - start)/h, decimals = 4))  ##calculate the     number of times to iterate
## np.round fixes a python bug returning 2.99999997 instead of 
## 3 which reduced the number of times iterated by -1
k = np.zeros((2, 4))

u = np.zeros((N +1,)) ## fill our u's first with  N+1 0's
v = np.zeros((N +1,)) ## fill our v's first with  N+1 0's


u[0] = input("Give me an initial value for u'>> ")
v[0] = input("Give me the second initial value for v' >> ")
t = np.arange(start, stop + h, h)


def f1(t, u, v):
    return eval(form1)

def f2(t, u, v):
    return eval(form2)
##for u now

def trialu():
    for j in range(0, N):
        k[0, 0] = h * f1(t[j], u[j], v[j])
        k[1, 0] = h * f2(t[j], u[j], v[j])
        k[0, 1] = h * f1(t[j] + h/2, u[j] + 0.5*k[0, 0], v[j] + 0.5*k[1, 0])
        k[1, 1] = h * f2(t[j] + h/2, u[j] + 0.5*k[0, 0], v[j] + 0.5*k[1, 0])
        k[0, 2] = h * f1(t[j] + h/2, u[j] + 0.5*k[0, 1], v[j] + 0.5*k[1, 1])
        k[1, 2] = h * f2(t[j] + h/2, u[j] + 0.5*k[0, 1], v[j] + 0.5*k[1, 1]) 
        k[0, 3] = h * f1(t[j], u[j] + k[0, 2], v[j] + k[1, 2])
        k[1, 3] = h * f2(t[j], u[j] + k[0, 2], v[j] + k[1, 2])
        u[j+1] = u[j] + (k[0, 0] + 2*k[0, 1] + 2*k[0, 2] + k[0, 3])/6
        v[j+1] = v[j] + (k[1, 0] + 2*k[1, 1] + 2*k[1, 2] + k[1, 3])/6
    return u

I know I can return (u, v) but I want to print "u ~ ", u differently and also v on another line but it seems that I just have to repeat trialu to return v, Is there a better way? without repeating def trialu() ? I also want to print k for j = 1, 2, ... seperately?
An example is to solve u' = -3*u + 2*v and v' = 3*u - 4*v from [0,0.4] using step size of h = 0.1 and u[0] = 0 and v = 0.5 .

I'm not sure what you're asking, maybe this is useful:

# example u and v
u = [1.003, 1.002, 1.001]
v = [0, 0, 0]

for i, (uapprox, vapprox) in enumerate(zip(u, v)):
    print "on iteration", i, "u ~", uapprox, "and v ~", vapprox

Output:

on iteration 0 u ~ 1.003 and v ~ 0
on iteration 1 u ~ 1.002 and v ~ 0
on iteration 2 u ~ 1.001 and v ~ 0

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM