1

I wrote a code to calculate the Characteristic Lyapunov Exponents in Python for a Lorenz system. I for sure did something wrong because the CLEs are way off but I cannot figure out what. I am using the Benettin et al. algorithm. I start by randomly choosing and initial state, and then 3 random tangent vectors that I orthonormalize using Gram Schmidt process (which also calculates the volumes). After the initialisation, I start iterating. I evolve the reference trajectory using Euler method and the tangent vectors using w(t+1)=L@w(t) where L is the Jacobian matrix at x(t) and w(t) is the tangent vector. I orthonormalize every northo and calculate the sum of log(volumes). Every iwrite the CLEs are printed out. If anyone has any idea what could be the issue, I'd be grateful. I am implementing this algorithm for a Lorenz system to validate it in order to use it for a different system.

Here is the code:

import numpy as np

def lorenz(x, y, z, sigma, rho, beta):
    dxdt = sigma * (y - x)
    dydt = x * (rho - z) - y
    dzdt = x * y - beta * z
    return [dxdt, dydt, dzdt]

def lorenz_L(x,y,z):
    return np.array([
    [-sigma, sigma, 0],
    [rho - z, -1, -x],
    [y, x, -beta]])   

def gram_schmidt(V):
    """
    Orthogonalize a set of vectors stored as the ROWS of matrix V.
    It also computes the volume generated the first i vectors for i=1,...,dim
    """
    # Get the number of vectors.
    n = V.shape[0]
    W = np.copy(V)
    R = np.zeros(n)
    VOL = np.zeros(n)
    for j in range(n):
        # To orthogonalize the vector in row j with respect to the
        # previous vectors, subtract from it its projection onto
        # each of the previous vectors.
        for k in range(j):
            W[j] -= np.dot(W[k], W[j]) * W[k]
        R[j] = np.linalg.norm(W[j])
        W[j] = W[j] / R[j]
        VOL[0]=R[0]
    for k in range(1,n):
        VOL[k]=VOL[k-1]*R[k]
    return W, VOL

# Parameters
sigma = 16.0
rho = 45.92
beta = 4.0

t_start = 0.0
t_end = 100.0
steps = 10000
northo = 1
iwrite = 1000 
num_points = steps * northo
dt = t_end/num_points
icont=0
dim=3

X = np.random.random(dim)

# Estimate Lyapunov exponents

num_lyapunov_exponents = dim
lyapunov_exponents = np.zeros(num_lyapunov_exponents)

num_vec=dim

sum_volumes = np.zeros(dim)
sum_lyapunov_exponents = np.zeros(dim)
cle = np.zeros(dim)

tangent_vec = np.random.random((dim,dim))
tangent_vec, _ = gram_schmidt(tangent_vec) 

for j in range(steps):
    for is_ in range(northo):
        icont=icont+1
        # velocities
        dX_dt = lorenz(X[0],X[1],X[2],sigma,rho,beta)

        # evolution of the reference trajectory
        for i in range(dim):
            X[i] = X[i] + dX_dt[i] * dt
 
        # stability matrix for Lorenz system
        L = lorenz_L(X[0],X[1],X[2])
        
        # evolve tangent vectors
        tangent_vec = (L@tangent_vec.T).T
        # for ivec in range(num_vec):
        #     tangent_vec[ivec] = L@tangent_vec[ivec]
    
    #orthonormalize
    tangent_vec, volumes = gram_schmidt(tangent_vec) 

    for i in range(dim):
        sum_volumes[i]=sum_volumes[i]+np.log(volumes[i])
    
    # calculate and print results
    if icont%iwrite == 0:
        t = icont*dt
        print(f'time : {t}, dt : {dt}, frame : {icont}')
        sum_lyapunov_exponents = sum_volumes / t
        cle[0]=sum_lyapunov_exponents[0]
        for l in range(1,dim):
            cle[l]=sum_lyapunov_exponents[l]-sum_lyapunov_exponents[l-1]
        for ii in range(dim):
            print(f'{ii+1}   {cle[ii]}')
        print()

I tried the above code, and I get Lyapunov exponents depending on what I set the time stepping values. I expect to get the theoretical expectation of a Kaplan York dimension of 2.07, First lyapunov exponent positive (1.5;2), the second zero and the third negative (-20;-30).

M409
  • 11
  • 2

0 Answers0