pythondifferential-equationsrunge-kuttalorenz-system

Lorenz attractor with Runge-Kutta python


  1. Hello I have to program a python function to solve Lorenz differential equations using Runge-Kutta 2cond grade

Differential equation

sigma=10, r=28 and b=8/3

with initial conditions (x,y,z)=(0,1,0)

this is the code i wrote, but it throws me an error saying overflow encountered in double_scalars, and I don't see what is wrong with the program

from pylab import *
def runge_4(r0,a,b,n,f1,f2,f3):
    def f(r,t):
        x=r[0]
        y=r[1]
        z=r[2]
        fx=f1(x,y,z,t)
        fy=f2(x,y,z,t)
        fz=f3(x,y,z,t)
        return array([fx,fy,fz],float)
    h=(b-a)/n
    lista_t=arange(a,b,h)
    print(lista_t)
    X,Y,Z=[],[],[]
    for t in lista_t:
        k1=h*f(r0,t)
        print("k1=",k1)
        k2=h*f(r0+0.5*k1,t+0.5*h)
        print("k2=",k2)
        k3=h*f(r0+0.5*k2,t+0.5*h)
        print("k3=",k3)
        k4=h*f(r0+k3,t+h)
        print("k4=",k4)
        r0+=(k1+2*k2+2*k3+k4)/float(6)
        print(r0)
        X.append(r0[0])
        Y.append(r0[1])
        Z.append(r0[2])
    return array([X,Y,Z])

def f1(x,y,z,t):
    return 10*(y-x)
def f2(x,y,z,t):
    return 28*x-y-x*z
def f3(x,y,z,t):
    return x*y-(8.0/3.0)*z
#and I run it
r0=[1,1,1]

runge_4(r0,1,50,20,f1,f2,f3)

Solution

  • Solving differential equations numerically can be challenging. If you choose too high step sizes, the solution will accumulate high errors and can even become unstable, as in your case.

    Either you should drastically reduce the step size (h) or just use the adaptive Runge Kutta method provided by scipy:

    from numpy import array, linspace
    from scipy.integrate import solve_ivp
    import pylab
    from mpl_toolkits import mplot3d
    
    def func(t, r):
        x, y, z = r 
        fx = 10 * (y - x)
        fy = 28 * x - y - x * z
        fz = x * y - (8.0 / 3.0) * z
        return array([fx, fy, fz], float)
    
    # and I run it
    r0 = [0, 1, 0]
    sol = solve_ivp(func, [0, 50], r0, t_eval=linspace(0, 50, 5000))
    
    # and plot it
    fig = pylab.figure()
    ax = pylab.axes(projection="3d")
    ax.plot3D(sol.y[0,:], sol.y[1,:], sol.y[2,:], 'blue')
    pylab.show()
    

    This solver uses 4th and 5th order Runge Kutta combination and controls the deviation between them by adapting the step size. See more usage documentation here: https://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.solve_ivp.html

    enter image description here