Runge Kutta constants diverging for Lorenz system?

Question:

I’m trying to solve the Lorenz system using the 4th order Runge Kutta method, where

dx/dt=a*(y-x)
dy/dt=x(b-z)-y
dx/dt=x*y-c*z

Since this system doesn’t depend explicity on time, it’s possibly to ignore that part in the iteration, so I just have
dX=F(x,y,z)

def func(x0):
    a=10
    b=38.63
    c=8/3
    fx=a*(x0[1]-x0[0])
    fy=x0[0]*(b-x0[2])-x0[1]
    fz=x0[0]*x0[1]-c*x0[2]
    return np.array([fx,fy,fz])

def kcontants(f,h,x0):
    k0=h*f(x0)
    k1=h*f(f(x0)+k0/2)
    k2=h*f(f(x0)+k1/2)
    k3=h*f(f(x0)+k2)
    #note returned K is a matrix
    return np.array([k0,k1,k2,k3])

x0=np.array([-8,8,27])
h=0.001

t=np.arange(0,50,h)
result=np.zeros([len(t),3])

for time in range(len(t)):
    if time==0:
        k=kcontants(func,h,x0)
        result[time]=func(x0)+(1/6)*(k[0]+2*k[1]+2*k[2]+k[3])
    else:
        k=kcontants(func,h,result[time-1])
        result[time]=result[time-1]+(1/6)*(k[0]+2*k[1]+2*k[2]+k[3])

The result should be the Lorenz atractors, however my code diverges around the fifth iteration, and it’s because the contants I create in kconstants do, however I checked and I’m pretty sure the runge kutta impletmentation is not to fault… (at least i think)

edit:

Found a similar post ,yet can’t figure what I’m doing wrong

Asked By: Matías Saavedra

||

Answers:

Have you looked at different initial values for your calculation? Do the ones you’ve chosen make sense? I.e. are they physical? From past experience with rk you can sometimes get very confusing results if you pick silly starting parameters.

Answered By: PirateNinjas

You have an extra call of f(x0) in the calculation of k1, k2 and k3. Change the function kcontants to

def kcontants(f,h,x0):
    k0=h*f(x0)
    k1=h*f(x0 + k0/2)
    k2=h*f(x0 + k1/2)
    k3=h*f(x0 + k2)
    #note returned K is a matrix
    return np.array([k0,k1,k2,k3])
Answered By: Warren Weckesser

Goodnight. This and version I made using the scipy edo integrator, scipy.integrate.odeint.

# Author      : Carlos Eduardo da Silva Lima
# Theme       : Movement of a Plant around a fixed star
# Language    : Python
# date        : 11/19/2022
# Environment : Google Colab

import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
from scipy.optimize import root
from scipy.linalg import eig
from mpl_toolkits.mplot3d import Axes3D

##################################
# Condições inicial e parãmetros #
##################################
t_inicial = 0
t_final = 100
N = 10000
h = 1e-3

x_0 = 1.0
y_0 = 1.0
z_0 = 1.0

#####################
# Equação de Lorenz #
#####################
def Lorenz(r,t,sigma,rho,beta):

  x = r[0]; y = r[1]; z = r[2]

  edo1 = sigma*(y-x)
  edo2 = x*(rho-z)-y
  edo3 = x*y-beta*z
  return np.array([edo1,edo2,edo3])

t = np.linspace(t_inicial,t_final,N)
r_0 = np.array([x_0,y_0,z_0])
#sol = odeint(Lorenz,r_0,t,rtol=1e-6,args = (10,28,8/3))
sol = odeint(Lorenz, r_0, t, args=(10,28,8/3), Dfun=None, col_deriv=0, full_output=0, ml=None, mu=None, rtol=1e-9, atol=1e-9, tcrit=None, h0=0.0, hmax=0.0, hmin=0.0, ixpr=0, mxstep=0, mxhnil=0, mxordn=12, mxords=5, printmessg=0, tfirst=False)

'''x = sol[:,0]
y = sol[:,1]
z = sol[:,2]'''
x, y, z = sol.T

# Plot
plt.style.use('dark_background')
ax = plt.figure(figsize = (10,10)).add_subplot(projection='3d')
ax.plot(x,y,z,'m-',lw=0.5, linewidth = 1.5)
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_zlabel("Z")
ax.set_title("Atrator de Lorenz")
plt.show()

In this second part, I simulate two Lorenz systems to verify the sensitive dependencies of the systems to the initial conditions. In the second system, I add a certain amount of eps = 1e-3 to the initial conditions of x(t0), y(t0) and z(t0).

# Depedência com as condições iniciais
eps = 1e-3
r_0_eps = np.array([x_0+eps,y_0+eps,z_0+eps])
sol_eps = odeint(Lorenz, r_0_eps, t, args=(10,28,8/3), Dfun=None, col_deriv=0, full_output=0, ml=None, mu=None,
             rtol=1e-9, atol=1e-9, tcrit=None, h0=0.0, hmax=0.0, hmin=0.0, ixpr=0, mxstep=0, mxhnil=0, mxordn=12, mxords=5, printmessg=0, tfirst=False)

'''x_eps = sol_eps[:,0]
y_eps = sol_eps[:,1]
z_eps = sol_eps[:,2]'''
x_eps, y_eps, z_eps = sol_eps.T

# Plot
plt.style.use('dark_background')
ax = plt.figure(figsize = (10,10)).add_subplot(projection='3d')
ax.plot(x,y,z,'r-',lw=1.5)
ax.plot(x_eps,y_eps,z_eps,'b-.',lw=1.1)
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_zlabel("Z")
ax.set_title("Lorenz Attractor")
plt.show()

Hope I helped, see you :).

Answered By: Carllos Limma