mirror of
https://codeberg.org/Yael-II/MSc2-Project-Chaos.git
synced 2026-03-14 20:06:28 +01:00
138 lines
5.1 KiB
Python
138 lines
5.1 KiB
Python
#!/usr/bin/env python
|
||
"""
|
||
Gottwald and Melbourne method
|
||
|
||
Study chaotic behaviour with the method of Gottwald & Melbourne (2003).
|
||
|
||
@ Author: Moussouni, Yaël (MSc student) & Bhat, Junaid Ramzan (MSc student)
|
||
@ Institution: Université de Strasbourg, CNRS, Observatoire astronomique
|
||
de Strasbourg, UMR 7550, F-67000 Strasbourg, France
|
||
@ Date: 2025-01-01
|
||
|
||
Licence:
|
||
Order and Chaos in a 2D potential
|
||
Copyright (C) 2025 Yaël Moussouni (yael.moussouni@etu.unistra.fr)
|
||
Bhat, Junaid Ramzan (junaid-ramzan.bhat@etu.unistra.fr)
|
||
|
||
gottwald_melbourne.py
|
||
Copyright (C) 2025 Bhat, Junaid Ramzan (junaid-ramzan.bhat@etu.unistra.fr)
|
||
|
||
This program is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation; either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
This program is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with this program. If not, see https://www.gnu.org/licenses/.
|
||
"""
|
||
|
||
import numpy as np
|
||
import matplotlib.pyplot as plt
|
||
from scipy.integrate import cumulative_trapezoid
|
||
|
||
import potentials as pot
|
||
import integrator as itg
|
||
import initial_conditions as init
|
||
|
||
# -----------------------------------------------------------------------------------
|
||
# Parameters
|
||
# -----------------------------------------------------------------------------------
|
||
DEFAULT_N_iter = 30000
|
||
DEFAULT_h = 0.01
|
||
DEFAULT_c = 1.7
|
||
|
||
E_all = np.array([1/100, 1/12, 1/10, 1/8, 1/6])
|
||
|
||
if "YII_1" in plt.style.available: plt.style.use("YII_1")
|
||
|
||
# -----------------------------------------------------------------------------------
|
||
# 1) Integrate Hénon–Heiles and Return x(t), etc.
|
||
# -----------------------------------------------------------------------------------
|
||
def compute_coordinates(E: float,
|
||
N_iter: int = DEFAULT_N_iter,
|
||
h: float = DEFAULT_h,
|
||
N_part: int = 1) -> tuple:
|
||
"""
|
||
Integrate Hénon–Heiles for N_iter steps at step size h for a single
|
||
random initial condition at energy E.
|
||
Returns:
|
||
t_part: array of times of length N_iter
|
||
x_part, y_part, u_part, v_part: arrays of length N_iter each
|
||
"""
|
||
# Generate 1 initial condition at energy E
|
||
W_init = init.n_energy_part(pot.hh_potential, N_part, E)
|
||
W0 = W_init[:, :, 0] # take first particle
|
||
|
||
# Perform integration using RK4
|
||
final_t, sol_array = itg.rk4(0.0, W0, h, N_iter, pot.hh_evolution)
|
||
# Reconstruct the time array using step size and number of iterations
|
||
|
||
# Extract coordinate arrays
|
||
x_part = sol_array[:, 0, 0]
|
||
y_part = sol_array[:, 0, 1]
|
||
u_part = sol_array[:, 1, 0]
|
||
v_part = sol_array[:, 1, 1]
|
||
|
||
return final_t, x_part, y_part, u_part, v_part
|
||
|
||
# -----------------------------------------------------------------------------------
|
||
# 2) Compute theta(t_i) in discrete form
|
||
# -----------------------------------------------------------------------------------
|
||
def compute_theta_discrete(t_array, x_array, c=DEFAULT_c):
|
||
int_x = cumulative_trapezoid(x_array, t_array, initial=0.0)
|
||
theta_array = c * t_array + int_x
|
||
return theta_array
|
||
|
||
# -----------------------------------------------------------------------------------
|
||
# 3) Compute p(t_i) in discrete form
|
||
# -----------------------------------------------------------------------------------
|
||
def compute_p_discrete(t_array, x_array, theta_array):
|
||
integrand = x_array * np.cos(theta_array)
|
||
p_array = cumulative_trapezoid(integrand, t_array, initial=0.0)
|
||
return p_array
|
||
|
||
# -----------------------------------------------------------------------------------
|
||
# Main: Compute p(t) for each energy and plot on a single graph
|
||
# -----------------------------------------------------------------------------------
|
||
if __name__ == "__main__":
|
||
fig, ax = plt.subplots() # single figure and axis
|
||
|
||
# Loop over energies and plot each p(t) on the same axis
|
||
i = 0
|
||
line_styles = ["-", "-", "--", ":", ":"]
|
||
for E in E_all:
|
||
# 1) Integrate Hénon–Heiles for current energy
|
||
t_part, x_part, y_part, u_part, v_part = compute_coordinates(E)
|
||
|
||
# 2) Compute theta(t) for current energy
|
||
theta_arr = compute_theta_discrete(t_part, x_part, c=DEFAULT_c)
|
||
|
||
# 3) Compute p(t) for current energy
|
||
p_arr = compute_p_discrete(t_part, x_part, theta_arr)
|
||
|
||
# Plot p(t) for the current energy on the same axis
|
||
ax.plot(t_part, p_arr,
|
||
line_styles[i],
|
||
color="C{}".format(i).replace("C1", "C5"),
|
||
label="$E={:.3f}$".format(E))
|
||
i += 1
|
||
|
||
#ax.set_title("$p(t)$ (Melbourne–Gottwald Test)")
|
||
ax.set_xlabel("$t$")
|
||
ax.set_ylabel("$p(t)$")
|
||
ax.legend()
|
||
|
||
# Enable both major and minor gridlines
|
||
#ax.grid(which='both', linestyle='--', linewidth=0.5)
|
||
#ax.minorticks_on()
|
||
|
||
fig.tight_layout()
|
||
fig.savefig("Figs/gottwald_melbourne.pdf")
|
||
plt.show()
|
||
|