mirror of
https://codeberg.org/Yael-II/MSc2-Project-Chaos.git
synced 2026-03-15 04:16:26 +01:00
update
This commit is contained in:
@@ -98,7 +98,7 @@ ax.set_xlabel("energy E")
|
||||
ax.set_ylabel("quantity mu")
|
||||
|
||||
fig.tight_layout()
|
||||
fig.savefig("mu")
|
||||
# fig.savefig("mu")
|
||||
|
||||
fig, ax = plt.subplots(1)
|
||||
ax.scatter(all_E, A, color="C0", s=5, marker="o", label="Data")
|
||||
@@ -106,7 +106,7 @@ ax.set_xlabel("energy E")
|
||||
ax.set_ylabel("area A")
|
||||
ax.legend()
|
||||
fig.tight_layout()
|
||||
fig.savefig("area")
|
||||
# fig.savefig("area")
|
||||
plt.show()
|
||||
|
||||
|
||||
@@ -1,9 +1,23 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Energies
|
||||
|
||||
Compute energies (kinetic or total)
|
||||
|
||||
@ 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: 2024-12-13
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
|
||||
def kinetic(W: np.ndarray) -> np.ndarray:
|
||||
"""Computes the kinetic energy.
|
||||
:param W: Phase-space vectors
|
||||
:returns T: Kinetic energy
|
||||
@param
|
||||
- W: Phase-space vectors
|
||||
@returns
|
||||
- T: Kinetic energy
|
||||
"""
|
||||
U = W[1,0]
|
||||
V = W[1,1]
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Initial Conditions
|
||||
|
||||
Generate initial conditions depending on different criteria
|
||||
|
||||
@ 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: 2024-11-29
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
POS_MIN = -1
|
||||
@@ -12,12 +24,14 @@ def mesh_grid(N: int = N_PART,
|
||||
ymin: float = POS_MIN,
|
||||
ymax: float = POS_MAX) -> np.ndarray:
|
||||
"""Generates a set of regularly sampled particles with no velocity
|
||||
:param N: number of particles
|
||||
:parma xmin: Minimum value for position x
|
||||
:param xmax: Maximum value for position x
|
||||
:param ymin: Minimum value for position y
|
||||
:param ymax: Maximum value for position y
|
||||
:returns W: Phase-space vector
|
||||
@ params:
|
||||
- N: number of particles
|
||||
- xmin: minimum value for position x
|
||||
- xmax: maximum value for position x
|
||||
- ymin: minimum value for position y
|
||||
- ymax: maximum value for position y
|
||||
@ returns:
|
||||
- W: phase-space vector
|
||||
"""
|
||||
X = np.linspace(xmin, xmax, N)
|
||||
Y = np.linspace(ymin, ymax, N)
|
||||
@@ -30,10 +44,14 @@ def one_part(x0: float = 0,
|
||||
v0: float = 0) -> np.ndarray:
|
||||
"""Generates a particle at position (x0, y0)
|
||||
with velocities (u0,v0)
|
||||
:param x0: Initial position x
|
||||
:param y0: Initial position y
|
||||
:param u0: Initial velocity u
|
||||
:param v0: Initial velocity v
|
||||
@ params:
|
||||
- N: number of particles
|
||||
- x0: initial position x
|
||||
- y0: initial position y
|
||||
- u0: initial velocity u
|
||||
- v0: initial velocity v
|
||||
@ returns:
|
||||
- W: phase-space vector
|
||||
"""
|
||||
X = x0
|
||||
Y = y0
|
||||
@@ -48,6 +66,18 @@ def n_energy_part(potential,
|
||||
xmax: float = +1,
|
||||
ymin: float = -0.5,
|
||||
ymax: float = +1):
|
||||
"""Generates N particles with an energy E in a potential.
|
||||
@ params:
|
||||
- potential: gravitational potential
|
||||
- N: number of particles
|
||||
- E: total energy
|
||||
- xmin: minimum value for position x
|
||||
- xmax: maximum value for position x
|
||||
- ymin: minimum value for position y
|
||||
- ymax: maximum value for position y
|
||||
@ returns:
|
||||
- W: an array of all the positions and velocities.
|
||||
"""
|
||||
X = []
|
||||
Y = []
|
||||
POT = []
|
||||
@@ -81,6 +111,22 @@ def n_energy_2part(potential,
|
||||
xmax: float = +1,
|
||||
ymin: float = -0.5,
|
||||
ymax: float = +1):
|
||||
"""Generate a sample of 2N particles with the energy E in a potential in
|
||||
two sets: one "normal" set (see n_energy_part), and a slightly shifted set
|
||||
with a separation sep.
|
||||
@ params:
|
||||
- potential: gravitational potential
|
||||
- N: number of particles
|
||||
- E: total energy
|
||||
- sep: the separation between the two sets
|
||||
- xmin: minimum value for position x
|
||||
- xmax: maximum value for position x
|
||||
- ymin: minimum value for position y
|
||||
- ymax: maximum value for position y
|
||||
@ returns:
|
||||
- (W1, W2): the two arrays of all the positions and velocities for
|
||||
each set.
|
||||
"""
|
||||
W_1 = n_energy_part(potential, N, E)
|
||||
W_2 = np.zeros_like(W_1)
|
||||
alpha = np.random.uniform(0, 2*np.pi, N)
|
||||
|
||||
@@ -1,7 +1,18 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Integrator
|
||||
|
||||
Integrate differential equations.
|
||||
|
||||
@ 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: 2024-11-29
|
||||
"""
|
||||
import numpy as np
|
||||
|
||||
def euler(x0, y0, h, n, func): # FIXME cannot be used with vectors
|
||||
"""
|
||||
"""DEPRECIATED - DO NOT USE
|
||||
Euler method adapted for state vector [[x, y], [u, v]]
|
||||
:param x0: initial time value
|
||||
:param y0: initial state vector [[x, y], [u, v]]
|
||||
@@ -25,7 +36,7 @@ def euler(x0, y0, h, n, func): # FIXME cannot be used with vectors
|
||||
|
||||
# Updated RK2 integrator
|
||||
def rk2(x0, y0, h, n, func): # FIXME cannot be used with vectors
|
||||
"""
|
||||
""" DEPRECIATED - DO NOT USE
|
||||
RK2 method adapted for state vector [[x, y], [u, v]]
|
||||
:param x0: initial time value
|
||||
:param y0: initial state vector [[x, y], [u, v]]
|
||||
@@ -54,14 +65,15 @@ def rk4(t0: float,
|
||||
h: float,
|
||||
n: int,
|
||||
func):
|
||||
"""
|
||||
RK4 method adapted for state vector [[x, y], [u, v]]
|
||||
:param x0: initial time value
|
||||
:param y0: initial state vector [[x, y], [u, v]]
|
||||
:param h: step size (time step)
|
||||
:param n: number of steps
|
||||
:param func: RHS of differential equation
|
||||
:returns: x array, solution array
|
||||
"""RK4 method adapted for state vector [[x, y], [u, v]]
|
||||
@ params
|
||||
- x0: initial time value
|
||||
- y0: initial state vector [[x, y], [u, v]]
|
||||
- h: step size (time step)
|
||||
- n: number of steps
|
||||
- func: RHS of differential equation
|
||||
@returns:
|
||||
- t, W: time and state (solution) arrays,
|
||||
"""
|
||||
time = np.zeros(n)
|
||||
W = np.zeros((n,) + np.shape(W0))
|
||||
@@ -84,4 +96,5 @@ def rk4(t0: float,
|
||||
|
||||
|
||||
def integrator_type(x0, y0, h, n, func, int_type):
|
||||
"""DEPRECIATED - DO NOT USE"""
|
||||
return int_type(x0, y0, h, n, func)
|
||||
|
||||
78
Source/plot_area.py
Normal file
78
Source/plot_area.py
Normal file
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Plot: Area
|
||||
|
||||
Plots areas
|
||||
|
||||
@ 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: 2024-11-29
|
||||
"""
|
||||
import os
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
if "YII_1" in plt.style.available: plt.style.use("YII_1")
|
||||
|
||||
OUT_DIR = "./Output/"
|
||||
FILENAME_PREFIX = "phase_separation_"
|
||||
EXTENSION = ".csv"
|
||||
|
||||
def plot_area(filelist: list, mu_c = 1e-4) -> int:
|
||||
"""
|
||||
Plot all the Poincaré sections in the file list.
|
||||
@params:
|
||||
- filelist: the list of files in the output directory, with the format
|
||||
"poincare_sections_{linear, parallel}_[1/E].csv"
|
||||
- title: title of the figure
|
||||
@returns:
|
||||
- 0.
|
||||
"""
|
||||
orderlist = np.argsort([(int(file
|
||||
.replace(FILENAME_PREFIX, "")
|
||||
.replace(EXTENSION, "")))
|
||||
for file in filelist])
|
||||
filelist = np.array(filelist)[orderlist]
|
||||
N = len(filelist)
|
||||
E = np.linspace(1/100, 1/6, N)
|
||||
mu = []
|
||||
for filename in filelist:
|
||||
with open(OUT_DIR + filename) as file:
|
||||
data = file.readlines()
|
||||
data = [np.float64(d.replace("\n", "")) for d in data]
|
||||
mu.append(data)
|
||||
mu = np.array(mu)
|
||||
|
||||
fig, ax = plt.subplots(1)
|
||||
ax.scatter([], [], s=1, color="k", label="Data")
|
||||
for i in range(len(mu)):
|
||||
Y = mu[i]
|
||||
ax.scatter([E[i]]*len(Y), Y, s=1, color="k", alpha=0.1)
|
||||
ax.scatter(E, np.mean(mu, axis=1), s=5,
|
||||
color="C1", marker="o", label="Mean")
|
||||
ax.scatter(E, np.median(mu, axis=1), s=5,
|
||||
color="C3", marker="s", label="Median")
|
||||
ax.plot(E, [mu_c]*len(E),
|
||||
color="C5", label="Critical value $\\mu_\\mathrm{{c}}$")
|
||||
ax.text(0.01, 1e-5, "Regular", va="bottom", ha="left", color="C5")
|
||||
ax.text(0.01, 1e-3, "Chaotic", va="top", ha="left", color="C5")
|
||||
ax.set_xlabel("Energy $E$")
|
||||
ax.set_ylabel("Phase-space squared distance $\\mu$")
|
||||
ax.set_yscale("log")
|
||||
ax.legend()
|
||||
fig.savefig("mu.pdf")
|
||||
|
||||
fig, ax = plt.subplots(1)
|
||||
N_reg = np.count_nonzero(mu < mu_c, axis=1)
|
||||
N = np.shape(mu)[1]
|
||||
Area = N_reg / N
|
||||
ax.scatter(E, Area, s=5, color="C0")
|
||||
ax.set_xlabel("Energy $E$")
|
||||
ax.set_ylabel("Area $N_\\mathrm{{reg}}/N_\\mathrm{{part}}$")
|
||||
fig.savefig("area.pdf")
|
||||
return 0
|
||||
|
||||
filelist = [f for f in os.listdir(OUT_DIR) if FILENAME_PREFIX in f]
|
||||
plot_area(filelist)
|
||||
plt.show()
|
||||
@@ -61,6 +61,10 @@ def plot_poincare_sections(filelist: list, title:str = "") -> int:
|
||||
while i < N:
|
||||
i += 1
|
||||
axs[i].axis('off')
|
||||
if "linear" in title: kind = "linear"
|
||||
elif "parallel" in title: kind = "parallel"
|
||||
else: kind = "error"
|
||||
fig.savefig("pcs_{}.pdf".format(kind))
|
||||
return 0
|
||||
print("\033[32m"
|
||||
+ "[P]arallel or [L]inear algorithm result, or [B]oth?"
|
||||
|
||||
101
Source/plot_poincare_sections_zoom.py
Normal file
101
Source/plot_poincare_sections_zoom.py
Normal file
@@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Plot: Poincaré Sections (Linear and Parallel)
|
||||
|
||||
Plots the Poincaré sections for different energies, computed either with linear
|
||||
or parallel algorithms.
|
||||
|
||||
@ 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: 2024-11-29
|
||||
"""
|
||||
import os
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
if "YII_1" in plt.style.available: plt.style.use("YII_1")
|
||||
|
||||
OUT_DIR = "./Output/"
|
||||
FILENAME_PREFIX = "poincare_sections_"
|
||||
EXTENSION = ".csv"
|
||||
|
||||
def plot_poincare_sections(filelist: list, title:str = "") -> int:
|
||||
"""
|
||||
Plot all the Poincaré sections in the file list.
|
||||
@params:
|
||||
- filelist: the list of files in the output directory, with the format
|
||||
"poincare_sections_{linear, parallel}_[1/E].csv"
|
||||
- title: title of the figure
|
||||
@returns:
|
||||
- 0.
|
||||
"""
|
||||
orderlist = np.argsort([(int(file
|
||||
.replace(FILENAME_PREFIX, "")
|
||||
.replace(EXTENSION, "")
|
||||
.replace("linear_", "")
|
||||
.replace("parallel_", "")))
|
||||
for file in filelist])
|
||||
filelist = np.array(filelist)[orderlist]
|
||||
N = len(filelist)
|
||||
#fig, axs = plt.subplot_mosaic("ABC\nDEF")
|
||||
fig1, axs1 = plt.subplot_mosaic("AB")
|
||||
fig2, axs2 = plt.subplot_mosaic("CD")
|
||||
fig3, axs3 = plt.subplot_mosaic("EF")
|
||||
|
||||
axs = list(axs1.values()) + list(axs2.values()) + list(axs3.values())
|
||||
fig1.suptitle(title)
|
||||
fig2.suptitle(title)
|
||||
fig3.suptitle(title)
|
||||
for i in range(N):
|
||||
ax = axs[i]
|
||||
filename = filelist[i]
|
||||
inv_E = (filename
|
||||
.replace(FILENAME_PREFIX, "")
|
||||
.replace(EXTENSION, "")
|
||||
.replace("linear_", "")
|
||||
.replace("parallel_", ""))
|
||||
data = np.loadtxt(OUT_DIR + filename)
|
||||
y_section = data[0]
|
||||
v_section = data[1]
|
||||
ax.scatter(y_section, v_section,
|
||||
s=.1, color="C3", marker=",", alpha=0.5,
|
||||
label="$E = 1/{}$".format(inv_E))
|
||||
ax.set_xlabel("$y$")
|
||||
ax.set_ylabel("$v$")
|
||||
ax.legend(loc="upper right")
|
||||
while i < N:
|
||||
i += 1
|
||||
axs[i].axis('off')
|
||||
if "linear" in title: kind = "linear"
|
||||
elif "parallel" in title: kind = "parallel"
|
||||
else: kind = "error"
|
||||
fig1.savefig("pcs_zoom_1_{}.pdf".format(kind))
|
||||
fig2.savefig("pcs_zoom_2_{}.pdf".format(kind))
|
||||
fig3.savefig("pcs_zoom_3_{}.pdf".format(kind))
|
||||
return 0
|
||||
|
||||
print("\033[32m"
|
||||
+ "[P]arallel or [L]inear algorithm result, or [B]oth?"
|
||||
+ "\033[0m")
|
||||
answer = input("\033[32m" + "> " + "\033[0m").upper()
|
||||
|
||||
if answer == "P":
|
||||
FILENAME_PREFIX += "parallel_"
|
||||
elif answer == "L":
|
||||
FILENAME_PREFIX += "linear_"
|
||||
|
||||
filelist = [fname for fname in os.listdir(OUT_DIR) if FILENAME_PREFIX in fname]
|
||||
|
||||
if answer in ["L", "B"]:
|
||||
filelist_linear = [fname for fname in filelist if "linear_" in fname]
|
||||
plot_poincare_sections(filelist_linear,
|
||||
title=("Poincaré Sections "
|
||||
"(results from the linear algorithm)"))
|
||||
if answer in ["P", "B"]:
|
||||
filelist_parallel = [fname for fname in filelist if "parallel_" in fname]
|
||||
plot_poincare_sections(filelist_parallel,
|
||||
title=("Poincaré Sections "
|
||||
"(results from the parallel algorithm)"))
|
||||
|
||||
plt.show()
|
||||
@@ -1,5 +1,27 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Poincaré Sections
|
||||
|
||||
Computes the Poincaré Sections
|
||||
|
||||
@ 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: 2024-11-29
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
def pcs_find(pos_x, pos_y, vel_x, vel_y):
|
||||
"""Find Poincaré sections (PCS; x = 0)
|
||||
@ params:
|
||||
- pos_x: position along the x axis
|
||||
- pos_y: position along the y axis
|
||||
- pos_x: velocity along the x axis
|
||||
- pos_y: velocity along the y axis
|
||||
@ returns: (tuple)
|
||||
- pcs_pos_y: position of the points in the PCS along the y axis
|
||||
- pcs_vel_y: velocity of the points in the PCS along the y axis
|
||||
"""
|
||||
if np.ndim(pos_x) == 1:
|
||||
pos_x = np.array([pos_x])
|
||||
pos_y = np.array([pos_y])
|
||||
@@ -25,8 +47,10 @@ def pcs_find(pos_x, pos_y, vel_x, vel_y):
|
||||
pcs_vel_y.append(v0)
|
||||
i += 1
|
||||
return pcs_pos_y, pcs_vel_y
|
||||
|
||||
def pcs_find_legacy(pos_x, pos_y, vel_x, vel_y):
|
||||
"""Depreciated legacy function that should not be used
|
||||
"""DEPRECIATED - DO NOT USE
|
||||
Depreciated legacy function that should not be used
|
||||
"""
|
||||
if np.ndim(pos_x) == 1:
|
||||
pos_x = np.array([pos_x])
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Potentials
|
||||
|
||||
Functions of the different potentials (and their derivatives for the evolution)
|
||||
|
||||
@ 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: 2024-11-29
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
|
||||
MAX_VAL = 1e3
|
||||
@@ -11,7 +23,7 @@ def kepler_potential(W_grid: np.ndarray,
|
||||
- W: Phase-space vector
|
||||
- position_only: True if W is np.array([X, Y])
|
||||
@returns:
|
||||
- V: computed potential
|
||||
- computed potential
|
||||
"""
|
||||
if position_only:
|
||||
X = W_grid[0]
|
||||
@@ -29,8 +41,11 @@ def kepler_potential(W_grid: np.ndarray,
|
||||
def hh_potential(W_grid: np.ndarray,
|
||||
position_only=False) -> np.ndarray:
|
||||
"""Computes the Hénon-Heiles potential.
|
||||
:param W: Phase-space vector
|
||||
:output V: Potential
|
||||
@params:
|
||||
- W: Phase-space vector
|
||||
- position_only: True if W is np.array([X, Y])
|
||||
@returns:
|
||||
- POT: Potential
|
||||
"""
|
||||
if position_only:
|
||||
X = W_grid[0]
|
||||
@@ -48,10 +63,12 @@ def hh_potential(W_grid: np.ndarray,
|
||||
return POT
|
||||
|
||||
def hh_evolution(t: np.ndarray, W: np.ndarray):
|
||||
"""Computes the evolution from the HH potential
|
||||
:param t: Time (not used)
|
||||
:param W: Phase space vector
|
||||
:returns dot W: Time derivative of the phase space vector
|
||||
"""Computes the evolution from the HH potential derivative
|
||||
@params
|
||||
- t: Time (not used)
|
||||
- W: Phase space vector
|
||||
&returns
|
||||
- dot W: Time derivative of the phase space vector
|
||||
"""
|
||||
X = W[0 ,0]
|
||||
Y = W[0, 1]
|
||||
|
||||
@@ -64,6 +64,8 @@ if __name__ == "__main__":
|
||||
ax.set_ylabel("$y$")
|
||||
ax.set_aspect("equal")
|
||||
|
||||
plt.savefig("evolution.png")
|
||||
|
||||
plt.show(block=True)
|
||||
|
||||
|
||||
|
||||
@@ -48,6 +48,8 @@ if __name__ == "__main__":
|
||||
ax.set_ylabel("$y$")
|
||||
ax.set_aspect("equal")
|
||||
|
||||
fig.savefig("initial_E.png")
|
||||
|
||||
plt.show(block=True)
|
||||
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ def kepler(W):
|
||||
ax.set_aspect("equal")
|
||||
ax.set_xlabel("$x$")
|
||||
ax.set_ylabel("$y$")
|
||||
|
||||
fig.savefig("pot_kepler.png")
|
||||
return 0
|
||||
|
||||
def hh(W):
|
||||
@@ -46,6 +48,8 @@ def hh(W):
|
||||
ax.set_aspect("equal")
|
||||
ax.set_xlabel("$x$")
|
||||
ax.set_ylabel("$y$")
|
||||
|
||||
fig.savefig("pot_hh.png")
|
||||
return 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user