validate P3M timestep convergence for baseline linear-in-scale-factor steps
This commit is contained in:
parent
13e6c3b32d
commit
a38f1b2585
7 changed files with 89782 additions and 1889 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -25,7 +25,12 @@ from pysbmy.fft import FourierGrid
|
|||
|
||||
from wip3m import *
|
||||
from wip3m.tools import get_k_max, generate_sim_params, generate_white_noise_Field, run_simulation
|
||||
from wip3m.params import params_planck_kmax_missing, cosmo_small_to_full_dict, z2a, BASELINE_SEEDPHASE
|
||||
from wip3m.params import (
|
||||
params_planck_kmax_missing,
|
||||
cosmo_small_to_full_dict,
|
||||
z2a,
|
||||
BASELINE_SEEDPHASE,
|
||||
)
|
||||
from wip3m.plot_utils import *
|
||||
|
||||
from wip3m.logger import getCustomLogger, INDENT, UNINDENT
|
||||
|
@ -37,34 +42,48 @@ output_path = OUTPUT_PATH
|
|||
|
||||
from argparse import ArgumentParser
|
||||
|
||||
parser = ArgumentParser(
|
||||
description="Run convergence tests towards implementing P3M gravity."
|
||||
)
|
||||
parser = ArgumentParser(description="Run convergence tests towards implementing P3M gravity.")
|
||||
|
||||
parser.add_argument("--run_id", type=str, help="Simulation run identifier.")
|
||||
parser.add_argument("--L", type=float, default=32.0, help="Box size in Mpc/h.")
|
||||
parser.add_argument("--N", type=int, default=128, help="Density grid size per dimension.")
|
||||
parser.add_argument("--Np", type=int, default=32, help="Number of particles per dimension.")
|
||||
parser.add_argument("--Npm", type=int, default=64, help="PM mesh resolution per dimension.")
|
||||
parser.add_argument("--n_Tiles", type=int, default=8, help="Number of tiles per dimension for short-range PP.")
|
||||
parser.add_argument(
|
||||
"--n_Tiles", type=int, default=8, help="Number of tiles per dimension for short-range PP."
|
||||
)
|
||||
|
||||
# Timestep settings per method
|
||||
for scheme in ["pmref", "pm1", "pm2", "cola", "spm", "p3m1", "p3m2", "p3m3"]:
|
||||
parser.add_argument(f"--nsteps_{scheme}", type=int, default={
|
||||
"pmref": 200, "pm1": 100, "pm2": 20,
|
||||
"cola": 10, "spm": 200,
|
||||
"p3m1": 200, "p3m2": 100, "p3m3": 20
|
||||
}[scheme], help=f"Number of timesteps for {scheme.upper()}.")
|
||||
parser.add_argument(f"--tsd_{scheme}", type=int, default=0,
|
||||
help=f"TimeStepDistribution ID for {scheme.upper()}.")
|
||||
parser.add_argument(
|
||||
f"--nsteps_{scheme}",
|
||||
type=int,
|
||||
default={
|
||||
"pmref": 200,
|
||||
"pm1": 100,
|
||||
"pm2": 20,
|
||||
"cola": 10,
|
||||
"spm": 200,
|
||||
"p3m1": 200,
|
||||
"p3m2": 100,
|
||||
"p3m3": 20,
|
||||
}[scheme],
|
||||
help=f"Number of timesteps for {scheme.upper()}.",
|
||||
)
|
||||
parser.add_argument(
|
||||
f"--tsd_{scheme}",
|
||||
type=int,
|
||||
default=0,
|
||||
help=f"TimeStepDistribution ID for {scheme.upper()}.",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
go_beyond_Nyquist_ss = True # for the summary statistics
|
||||
force = True
|
||||
force_hard = True
|
||||
force = False
|
||||
force_hard = False
|
||||
|
||||
run_id = args.run_id
|
||||
L = args.L
|
||||
|
@ -104,14 +123,13 @@ if __name__ == "__main__":
|
|||
logger.info(f"Number of timesteps for P3M2: {nsteps_p3m2}")
|
||||
logger.info(f"Number of timesteps for P3M3: {nsteps_p3m3}")
|
||||
INDENT()
|
||||
|
||||
|
||||
corner = -L / 2.0
|
||||
RedshiftLPT = 19.0
|
||||
RedshiftFCs = 0.0
|
||||
ai = z2a(RedshiftLPT)
|
||||
af = z2a(RedshiftFCs)
|
||||
k_max = get_k_max(L, N) # k_max in h/Mpc
|
||||
print(f"k_max = {k_max}")
|
||||
cosmo = params_planck_kmax_missing.copy()
|
||||
cosmo["k_max"] = k_max
|
||||
|
||||
|
@ -120,6 +138,7 @@ if __name__ == "__main__":
|
|||
logdir = simdir + "logs/"
|
||||
if force_hard:
|
||||
import shutil
|
||||
|
||||
if Path(simdir).exists():
|
||||
shutil.rmtree(simdir)
|
||||
if Path(wd).exists():
|
||||
|
@ -143,6 +162,22 @@ if __name__ == "__main__":
|
|||
"n_Tiles": n_Tiles,
|
||||
"RedshiftLPT": RedshiftLPT,
|
||||
"RedshiftFCs": RedshiftFCs,
|
||||
"nsteps_pmref": nsteps_pmref,
|
||||
"nsteps_pm1": nsteps_pm1,
|
||||
"nsteps_pm2": nsteps_pm2,
|
||||
"nsteps_cola": nsteps_cola,
|
||||
"nsteps_spm": nsteps_spm,
|
||||
"nsteps_p3m1": nsteps_p3m1,
|
||||
"nsteps_p3m2": nsteps_p3m2,
|
||||
"nsteps_p3m3": nsteps_p3m3,
|
||||
"tsd_pmref": tsd_pmref,
|
||||
"tsd_pm1": tsd_pm1,
|
||||
"tsd_pm2": tsd_pm2,
|
||||
"tsd_cola": tsd_cola,
|
||||
"tsd_spm": tsd_spm,
|
||||
"tsd_p3m1": tsd_p3m1,
|
||||
"tsd_p3m2": tsd_p3m2,
|
||||
"tsd_p3m3": tsd_p3m3,
|
||||
}
|
||||
with open(wd + "sim_params.txt", "w") as f:
|
||||
f.write(f"{sim_params}\n")
|
||||
|
@ -247,7 +282,9 @@ if __name__ == "__main__":
|
|||
("p3m3", p3m3_params),
|
||||
]
|
||||
for name, params in all_sim_params:
|
||||
logger.info(f"Generating parameters for {name.upper()} with nsteps = {params['nsteps']}...")
|
||||
logger.info(
|
||||
f"Generating parameters for {name.upper()} with nsteps = {params['nsteps']}..."
|
||||
)
|
||||
file_ext = f"{name}_nsteps{params['nsteps']}"
|
||||
generate_sim_params(params, ICs_path, wd, simdir, file_ext, force)
|
||||
logger.info(f"Generating parameters for {name.upper()} done.")
|
||||
|
@ -324,4 +361,4 @@ if __name__ == "__main__":
|
|||
raise RuntimeError("Failed.") from e
|
||||
finally:
|
||||
UNINDENT()
|
||||
logger.info("Running convergence tests done.")
|
||||
logger.info("Running convergence tests done.")
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
/Users/hoellinger/Library/CloudStorage/Dropbox/travail/these/science/code/PUBLIC/selfisys_public/src/selfisys/utils/plot_params.py
|
75
src/wip3m/plot_params.py
Normal file
75
src/wip3m/plot_params.py
Normal file
|
@ -0,0 +1,75 @@
|
|||
#!/usr/bin/env python3
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (C) 2025 Tristan Hoellinger
|
||||
# Distributed under the GNU General Public License v3.0 (GPLv3).
|
||||
# See the LICENSE file in the root directory for details.
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
__author__ = "Tristan Hoellinger"
|
||||
__version__ = "0.1.0"
|
||||
__date__ = "2025"
|
||||
__license__ = "GPLv3"
|
||||
|
||||
"""Plotting parameters and custom colormaps for the WIP-P3M package."""
|
||||
|
||||
|
||||
# Global font sizes
|
||||
GLOBAL_FS = 18
|
||||
GLOBAL_FS_LARGE = 20
|
||||
GLOBAL_FS_XLARGE = 22
|
||||
GLOBAL_FS_SMALL = 16
|
||||
GLOBAL_FS_TINY = 14
|
||||
COLOUR_LIST = ["C{}".format(i) for i in range(10)]
|
||||
|
||||
|
||||
def reset_plotting():
|
||||
import matplotlib as mpl
|
||||
|
||||
mpl.rcParams.update(mpl.rcParamsDefault)
|
||||
|
||||
|
||||
def setup_plotting():
|
||||
"""
|
||||
Configure Matplotlib plotting settings for consistent appearance.
|
||||
"""
|
||||
import matplotlib.pyplot as plt
|
||||
import importlib.resources
|
||||
|
||||
with importlib.resources.open_text("wip3m", "preamble.tex") as f:
|
||||
preamble = f.read()
|
||||
|
||||
# Dictionary with rcParams settings
|
||||
rcparams = {
|
||||
"font.family": "serif",
|
||||
"font.size": GLOBAL_FS, # Base font size
|
||||
"axes.titlesize": GLOBAL_FS_XLARGE,
|
||||
"axes.labelsize": GLOBAL_FS_LARGE,
|
||||
"axes.linewidth": 1.0,
|
||||
"xtick.labelsize": GLOBAL_FS_SMALL,
|
||||
"ytick.labelsize": GLOBAL_FS_SMALL,
|
||||
"xtick.major.width": 1.2,
|
||||
"ytick.major.width": 1.2,
|
||||
"xtick.minor.width": 1.0,
|
||||
"ytick.minor.width": 1.0,
|
||||
"xtick.direction": "in",
|
||||
"ytick.direction": "in",
|
||||
"xtick.major.pad": 5,
|
||||
"xtick.minor.pad": 5,
|
||||
"ytick.major.pad": 5,
|
||||
"ytick.minor.pad": 5,
|
||||
"legend.fontsize": GLOBAL_FS_SMALL,
|
||||
"legend.title_fontsize": GLOBAL_FS_LARGE,
|
||||
"figure.titlesize": GLOBAL_FS_XLARGE,
|
||||
"figure.dpi": 300,
|
||||
"grid.color": "gray",
|
||||
"grid.linestyle": "dotted",
|
||||
"grid.linewidth": 0.6,
|
||||
"lines.linewidth": 2,
|
||||
"lines.markersize": 8,
|
||||
"text.usetex": True,
|
||||
"text.latex.preamble": preamble,
|
||||
}
|
||||
|
||||
# Update rcParams
|
||||
plt.rcParams.update(rcparams)
|
450
src/wip3m/plots_convergence_baseline_ts_parser.py
Normal file
450
src/wip3m/plots_convergence_baseline_ts_parser.py
Normal file
|
@ -0,0 +1,450 @@
|
|||
#!/usr/bin/env python3
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (C) 2025 Tristan Hoellinger
|
||||
# Distributed under the GNU General Public License v3.0 (GPLv3).
|
||||
# See the LICENSE file in the root directory for details.
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
__author__ = "Tristan Hoellinger"
|
||||
__version__ = "0.1.0"
|
||||
__date__ = "2025"
|
||||
__license__ = "GPLv3"
|
||||
|
||||
"""Plot results of time step convergence tests."""
|
||||
|
||||
# pyright: reportWildcardImportFromLibrary=false
|
||||
from pathlib import Path
|
||||
import numpy as np
|
||||
|
||||
from pysbmy.fft import read_FourierGrid
|
||||
from pysbmy.field import read_field
|
||||
from pysbmy.correlations import get_autocorrelation
|
||||
|
||||
from wip3m import *
|
||||
from wip3m.tools import none_bool_str
|
||||
from wip3m.plot_utils import *
|
||||
|
||||
from wip3m.logger import getCustomLogger, INDENT, UNINDENT
|
||||
|
||||
logger = getCustomLogger(__name__)
|
||||
|
||||
workdir = ROOT_PATH + "results/"
|
||||
output_path = OUTPUT_PATH
|
||||
|
||||
from argparse import ArgumentParser
|
||||
|
||||
parser = ArgumentParser(description="Plot convergence results for WIP3M.")
|
||||
parser.add_argument(
|
||||
"--run_id",
|
||||
type=str,
|
||||
help="Run ID to use for plotting.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--outdir_suffix",
|
||||
type=str,
|
||||
default="plots",
|
||||
help="Suffix to append to the output directory.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--ref",
|
||||
type=str,
|
||||
default="P3M1",
|
||||
choices=["P3M1", "PMref"],
|
||||
help="Reference field for power spectrum comparison.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--lpt",
|
||||
type=none_bool_str,
|
||||
default=False,
|
||||
help="Whether to compute and plot the LPT power spectrum.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--cola",
|
||||
type=none_bool_str,
|
||||
default=True,
|
||||
help="Whether to compute and plot the COLA power spectrum.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--plot_fields",
|
||||
type=none_bool_str,
|
||||
default=False,
|
||||
help="Whether to plot the fields or not.",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
run_id = args.run_id
|
||||
outdir_suffix = args.outdir_suffix
|
||||
ref = args.ref
|
||||
lpt = args.lpt
|
||||
cola = args.cola
|
||||
plot_fields = args.plot_fields
|
||||
|
||||
if not run_id:
|
||||
raise ValueError("Please provide a run ID using the --run_id argument.")
|
||||
|
||||
simdir = output_path + run_id + "/"
|
||||
outdir = simdir + outdir_suffix + "/"
|
||||
input_ss_file = simdir + "input_ss_k_grid.h5"
|
||||
wd = workdir + run_id + "/"
|
||||
|
||||
Path(outdir).mkdir(parents=True, exist_ok=True)
|
||||
|
||||
if __name__ == "__main__":
|
||||
logger.info(f"Plotting convergence results for run ID: {run_id}")
|
||||
logger.info(f"Output directory: {outdir}")
|
||||
|
||||
logger.info(f"Reading simulation parameters from {wd}sim_params.txt...")
|
||||
with open(wd + "sim_params.txt", "r") as f:
|
||||
sim_params = eval(f.read())
|
||||
L = sim_params["L"] # Box size in Mpc/h
|
||||
N = sim_params["N"] # Density grid size
|
||||
Np = sim_params["Np"] # Number of dark matter particles per spatial dimension
|
||||
Npm = sim_params["Npm"] # PM grid size
|
||||
nsteps_pmref = sim_params["nsteps_pmref"]
|
||||
nsteps_pm1 = sim_params["nsteps_pm1"]
|
||||
nsteps_pm2 = sim_params["nsteps_pm2"]
|
||||
nsteps_cola = sim_params["nsteps_cola"]
|
||||
nsteps_spm = sim_params["nsteps_spm"]
|
||||
nsteps_p3m1 = sim_params["nsteps_p3m1"]
|
||||
nsteps_p3m2 = sim_params["nsteps_p3m2"]
|
||||
nsteps_p3m3 = sim_params["nsteps_p3m3"]
|
||||
logger.info(f"Reading simulation parameters from {wd}sim_params.txt done.")
|
||||
|
||||
if plot_fields:
|
||||
logger.info(f"Loading fields from {simdir}...")
|
||||
INDENT()
|
||||
slice_ijk = (N // 2, slice(None), slice(None))
|
||||
DELTA_LPT = read_field(simdir + "lpt_density.h5").data[slice_ijk]
|
||||
DELTA_PMREF = read_field(simdir + f"pmref_nsteps{nsteps_pmref}_final_density_pm.h5").data[
|
||||
slice_ijk
|
||||
]
|
||||
DELTA_PM1 = read_field(simdir + f"pm1_nsteps{nsteps_pm1}_final_density_pm.h5").data[
|
||||
slice_ijk
|
||||
]
|
||||
DELTA_PM2 = read_field(simdir + f"pm2_nsteps{nsteps_pm2}_final_density_pm.h5").data[
|
||||
slice_ijk
|
||||
]
|
||||
DELTA_COLA = read_field(simdir + f"cola_nsteps{nsteps_cola}_final_density_cola.h5").data[
|
||||
slice_ijk
|
||||
]
|
||||
DELTA_SPM = read_field(simdir + f"spm_nsteps{nsteps_spm}_final_density_spm.h5").data[
|
||||
slice_ijk
|
||||
]
|
||||
DELTA_P3M1 = read_field(simdir + f"p3m1_nsteps{nsteps_p3m1}_final_density_p3m.h5").data[
|
||||
slice_ijk
|
||||
]
|
||||
DELTA_P3M2 = read_field(simdir + f"p3m2_nsteps{nsteps_p3m2}_final_density_p3m.h5").data[
|
||||
slice_ijk
|
||||
]
|
||||
DELTA_P3M3 = read_field(simdir + f"p3m3_nsteps{nsteps_p3m3}_final_density_p3m.h5").data[
|
||||
slice_ijk
|
||||
]
|
||||
UNINDENT()
|
||||
logger.info(f"Loading fields from {simdir} done.")
|
||||
|
||||
diff_pm1_pmref = DELTA_PM1 - DELTA_PMREF
|
||||
diff_pm2_pmref = DELTA_PM2 - DELTA_PMREF
|
||||
diff_p3m1_pmref = DELTA_P3M1 - DELTA_PMREF
|
||||
diff_p3m2_pm1 = DELTA_P3M2 - DELTA_PM1
|
||||
diff_p3m3_pm2 = DELTA_P3M3 - DELTA_PM2
|
||||
diff_p3m1_spm = DELTA_P3M1 - DELTA_SPM
|
||||
|
||||
fields = [
|
||||
"pmref",
|
||||
"pm1",
|
||||
"pm2",
|
||||
"p3m1",
|
||||
"p3m2",
|
||||
"p3m3",
|
||||
"diff_p3m1_spm",
|
||||
"diff_pm1_pmref",
|
||||
"diff_pm2_pmref",
|
||||
"diff_p3m1_pmref",
|
||||
"diff_p3m2_pm1",
|
||||
"diff_p3m3_pm2",
|
||||
] # fields to plot
|
||||
ncols = 6 # Max panels per row
|
||||
|
||||
figname = "_".join(fields)
|
||||
slices_dict = {
|
||||
"lpt": DELTA_LPT,
|
||||
"cola": DELTA_COLA,
|
||||
"pmref": DELTA_PMREF,
|
||||
"pm1": DELTA_PM1,
|
||||
"pm2": DELTA_PM2,
|
||||
"spm": DELTA_SPM,
|
||||
"p3m1": DELTA_P3M1,
|
||||
"p3m2": DELTA_P3M2,
|
||||
"p3m3": DELTA_P3M3,
|
||||
"diff_pm1_pmref": diff_pm1_pmref,
|
||||
"diff_pm2_pmref": diff_pm2_pmref,
|
||||
"diff_p3m1_pmref": diff_p3m1_pmref,
|
||||
"diff_p3m2_pm1": diff_p3m2_pm1,
|
||||
"diff_p3m3_pm2": diff_p3m3_pm2,
|
||||
"diff_p3m1_spm": diff_p3m1_spm,
|
||||
}
|
||||
titles_dict = {
|
||||
"lpt": "LPT",
|
||||
"pmref": f"PMref $n_\\mathrm{{steps}}={nsteps_pmref}$",
|
||||
"pm1": f"PM1 $n_\\mathrm{{steps}}={nsteps_pm1}$",
|
||||
"pm2": f"PM2 $n_\\mathrm{{steps}}={nsteps_pm2}$",
|
||||
"cola": f"COLA $n_\\mathrm{{steps}}={nsteps_cola}$",
|
||||
"spm": f"sPM $n_\\mathrm{{steps}}={nsteps_spm}$",
|
||||
"p3m1": f"P3M1 $n_\\mathrm{{steps}}={nsteps_p3m1}$",
|
||||
"p3m2": f"P3M2 $n_\\mathrm{{steps}}={nsteps_p3m2}$",
|
||||
"p3m3": f"P3M3 $n_\\mathrm{{steps}}={nsteps_p3m3}$",
|
||||
"diff_pm1_pmref": r"$\delta_{\rm PM1}-\delta_{\rm PMref}$",
|
||||
"diff_pm2_pmref": r"$\delta_{\rm PM2}-\delta_{\rm PMref}$",
|
||||
"diff_p3m1_pmref": r"$\delta_{\rm P3M1}-\delta_{\rm PMref}$",
|
||||
"diff_p3m2_pm1": r"$\delta_{\rm P3M2}-\delta_{\rm PM1}$",
|
||||
"diff_p3m3_pm2": r"$\delta_{\rm P3M3}-\delta_{\rm PM2}$",
|
||||
"diff_p3m1_spm": r"$\delta_{\rm P3M1}-\delta_{\rm sPM}$",
|
||||
}
|
||||
|
||||
logger.info(f"Plotting fields: {fields}...")
|
||||
npanels = len(fields)
|
||||
nrows = np.ceil(npanels / ncols).astype(int)
|
||||
|
||||
fig, axs = plt.subplots(
|
||||
nrows=nrows, ncols=ncols, figsize=(3 * ncols, 4.6 * nrows), sharey=True
|
||||
)
|
||||
|
||||
axs = axs.flatten()
|
||||
ims = []
|
||||
|
||||
for i, key in enumerate(fields):
|
||||
ax = axs[i]
|
||||
data = slices_dict[key]
|
||||
title = titles_dict[key]
|
||||
|
||||
if key.startswith("diff"):
|
||||
norm = TwoSlopeNorm(
|
||||
vmin=-np.log(1 + np.abs(np.min(data))),
|
||||
vcenter=0,
|
||||
vmax=np.log10(1 + np.abs(np.max(data))),
|
||||
)
|
||||
im = ax.imshow(np.sign(data) * np.log(1 + np.abs(data)), cmap="RdBu_r", norm=norm)
|
||||
else:
|
||||
im = ax.imshow(np.log10(2 + data), cmap=cmap)
|
||||
|
||||
ims.append((im, key))
|
||||
ax.set_title(title, fontsize=fs_titles)
|
||||
for spine in ax.spines.values():
|
||||
spine.set_visible(False)
|
||||
|
||||
# Hide unused axes
|
||||
for i in range(npanels, len(axs)):
|
||||
axs[i].axis("off")
|
||||
|
||||
# Shared axes labels
|
||||
for i, ax in enumerate(axs[:npanels]):
|
||||
if i % ncols == 0:
|
||||
ax.set_yticks([0, N // 2, N])
|
||||
ax.set_yticklabels([f"{-L/2:.0f}", "0", f"{L/2:.0f}"], fontsize=fs)
|
||||
ax.set_ylabel(r"Mpc/$h$", size=GLOBAL_FS_SMALL)
|
||||
|
||||
ax.set_xticks([0, N // 2, N])
|
||||
ax.set_xticklabels([f"{-L/2:.0f}", "0", f"{L/2:.0f}"], fontsize=fs)
|
||||
ax.set_xlabel(r"Mpc/$h$", size=GLOBAL_FS_SMALL)
|
||||
|
||||
# Colorbars
|
||||
for ax, (im, key) in zip(axs[:npanels], ims):
|
||||
divider = make_axes_locatable(ax)
|
||||
cax = divider.append_axes("bottom", size="5%", pad=0.6)
|
||||
cb = fig.colorbar(im, cax=cax, orientation="horizontal")
|
||||
if key.startswith("diff"):
|
||||
cb.set_label(
|
||||
r"$\textrm{sgn}\left(\Delta\delta\right)\log_{10}(1 + |\Delta\delta|)$",
|
||||
fontsize=fs,
|
||||
)
|
||||
else:
|
||||
cb.set_label(r"$\log_{10}(2 + \delta)$", fontsize=fs)
|
||||
cb.ax.tick_params(labelsize=fs)
|
||||
cax.xaxis.set_ticks_position("bottom")
|
||||
cax.xaxis.set_label_position("bottom")
|
||||
|
||||
fig.savefig(outdir + f"{figname}.png", bbox_inches="tight", dpi=300, transparent=True)
|
||||
fig.savefig(outdir + f"{figname}.pdf", bbox_inches="tight", dpi=300)
|
||||
plt.close(fig)
|
||||
logger.info(f"Plotting fields done. Saved to {outdir}{figname}.png and {figname}.pdf")
|
||||
|
||||
logger.info("Computing and plotting power spectra...")
|
||||
INDENT()
|
||||
logger.info("Loading Fourier grid...")
|
||||
G = read_FourierGrid(input_ss_file)
|
||||
logger.info("Loading Fourier grid done.")
|
||||
|
||||
# Exit here with "0" for debugging purposes:
|
||||
exit(0)
|
||||
|
||||
k = G.k_modes
|
||||
AliasingCorr = False
|
||||
|
||||
logger.info("Computing power spectra...")
|
||||
DELTA = read_field(simdir + "initial_density.h5")
|
||||
Pk_INI, _ = get_autocorrelation(DELTA, G, AliasingCorr)
|
||||
|
||||
if lpt:
|
||||
DELTA = read_field(simdir + "lpt_density.h5")
|
||||
Pk_LPT, _ = get_autocorrelation(DELTA, G, AliasingCorr)
|
||||
|
||||
DELTA = read_field(simdir + f"pmref_nsteps{nsteps_pmref}_final_density_pm.h5")
|
||||
Pk_PMref, _ = get_autocorrelation(DELTA, G, AliasingCorr)
|
||||
|
||||
DELTA = read_field(simdir + f"pm1_nsteps{nsteps_pm1}_final_density_pm.h5")
|
||||
Pk_PM1, _ = get_autocorrelation(DELTA, G, AliasingCorr)
|
||||
|
||||
DELTA = read_field(simdir + f"pm2_nsteps{nsteps_pm2}_final_density_pm.h5")
|
||||
Pk_PM2, _ = get_autocorrelation(DELTA, G, AliasingCorr)
|
||||
|
||||
if cola:
|
||||
DELTA = read_field(simdir + f"cola_nsteps{nsteps_cola}_final_density_cola.h5")
|
||||
Pk_COLA, _ = get_autocorrelation(DELTA, G, AliasingCorr)
|
||||
|
||||
DELTA = read_field(simdir + f"spm_nsteps{nsteps_spm}_final_density_spm.h5")
|
||||
Pk_sPM, _ = get_autocorrelation(DELTA, G, AliasingCorr)
|
||||
|
||||
DELTA = read_field(simdir + f"p3m1_nsteps{nsteps_p3m1}_final_density_p3m.h5")
|
||||
Pk_P3M1, _ = get_autocorrelation(DELTA, G, AliasingCorr)
|
||||
|
||||
DELTA = read_field(simdir + f"p3m2_nsteps{nsteps_p3m2}_final_density_p3m.h5")
|
||||
Pk_P3M2, _ = get_autocorrelation(DELTA, G, AliasingCorr)
|
||||
|
||||
DELTA = read_field(simdir + f"p3m3_nsteps{nsteps_p3m3}_final_density_p3m.h5")
|
||||
Pk_P3M3, _ = get_autocorrelation(DELTA, G, AliasingCorr)
|
||||
logger.info("Computing power spectra done.")
|
||||
|
||||
if ref == "P3M1":
|
||||
nsteps_reference = nsteps_p3m1
|
||||
Pk_ref = Pk_P3M1
|
||||
label_ref = f"Ref (P3M, $n_\\mathrm{{steps}}={nsteps_reference}$)"
|
||||
elif ref == "PMref":
|
||||
nsteps_reference = nsteps_pm1
|
||||
Pk_ref = Pk_PMref
|
||||
label_ref = f"Ref (PM, $n_\\mathrm{{steps}}={nsteps_reference}$)"
|
||||
else:
|
||||
raise ValueError("Invalid reference field. Choose 'P3M1' or 'PMref'.")
|
||||
|
||||
logger.info(f"Plotting power spectra...")
|
||||
INDENT()
|
||||
fig, ax = plt.subplots(figsize=(7, 4))
|
||||
|
||||
ax.set_xscale("log")
|
||||
k = G.k_modes
|
||||
kmin, kmax = k.min(), k.max()
|
||||
logger.info(f"kmin = {kmin:.2e}, kmax = {kmax:.2e}")
|
||||
log_pad = 0.02
|
||||
log_k_min = np.log10(kmin)
|
||||
log_k_max = np.log10(kmax)
|
||||
log_range = log_k_max - log_k_min
|
||||
xlim_min = 10 ** (log_k_min - log_pad * log_range)
|
||||
xlim_max = 10 ** (log_k_max + log_pad * log_range)
|
||||
|
||||
plt.xlim(xlim_min, xlim_max)
|
||||
# ax.set_ylim([0.2, 1.8])
|
||||
dark_grey_bnd = 0.01
|
||||
medium_grey_bnd = 0.05
|
||||
light_grey_bnd = 0.1
|
||||
|
||||
ax.plot([kmin, kmax], [1, 1], color="black", linestyle="-", label=label_ref)
|
||||
if lpt:
|
||||
ax.plot(k, Pk_LPT / Pk_ref, label="2LPT", linestyle="--")
|
||||
fields_to_plot = [
|
||||
("PMref", Pk_PMref),
|
||||
("PM1", Pk_PM1),
|
||||
("PM2", Pk_PM2),
|
||||
("sPM", Pk_sPM),
|
||||
("P3M1", Pk_P3M1),
|
||||
("P3M2", Pk_P3M2),
|
||||
("P3M3", Pk_P3M3),
|
||||
]
|
||||
if cola:
|
||||
fields_to_plot.append(("COLA", Pk_COLA))
|
||||
# Remove the field corresponding to the reference:
|
||||
fields_to_plot = [(field_name, Pk) for field_name, Pk in fields_to_plot if field_name != ref]
|
||||
for field_name, Pk in fields_to_plot:
|
||||
label = f"{field_name}, $n_\\mathrm{{steps}}={eval(f'nsteps_{field_name.lower()}')}$"
|
||||
if field_name in ["PMref", "P3M1"]:
|
||||
linestyle = "-"
|
||||
zorder = 1
|
||||
else:
|
||||
linestyle = "--"
|
||||
zorder = 2
|
||||
ax.plot(k, Pk / Pk_ref, label=label, linestyle=linestyle)
|
||||
|
||||
ax.axhspan(1 - dark_grey_bnd, 1 + dark_grey_bnd, color="grey", alpha=0.3)
|
||||
ax.axhspan(1 - medium_grey_bnd, 1 + medium_grey_bnd, color="grey", alpha=0.2)
|
||||
ax.axhspan(1 - light_grey_bnd, 1 + light_grey_bnd, color="grey", alpha=0.1)
|
||||
|
||||
for i in range(1, len(k)):
|
||||
ax.axvline(k[i], color="black", linestyle=":", linewidth=1, alpha=0.1, zorder=0)
|
||||
ax.yaxis.set_major_locator(plt.MaxNLocator(6))
|
||||
ax.yaxis.get_major_ticks()[0].label1.set_visible(False)
|
||||
ax.set_xlabel("$k$ [$h/\\mathrm{Mpc}$]", fontsize=fs)
|
||||
ax.set_ylabel("$P(k)/P_\\mathrm{ref}(k)$", fontsize=fs)
|
||||
ax.tick_params(which="both", direction="in")
|
||||
ax.tick_params(axis="both", which="major", labelsize=fs)
|
||||
ax.tick_params(axis="both", which="minor", labelsize=fs)
|
||||
|
||||
# Characteristic vertical reference scales
|
||||
nyquist = np.pi * N / L
|
||||
nyquist_PM = np.pi * Npm / L
|
||||
epsilon = 0.03 * L / Np
|
||||
particle_length = 2 * epsilon
|
||||
xs = 1.25 * L / Npm
|
||||
xr = 4.5 * xs
|
||||
particle_wavenumber = 2 * np.pi / particle_length # Too large to be shown
|
||||
xs_inv = 2 * np.pi / xs
|
||||
xr_inv = 2 * np.pi / xr
|
||||
line1 = ax.axvline(
|
||||
x=nyquist, color="black", linestyle="--", lw=2, label="Nyquist (density grid)", zorder=0
|
||||
)
|
||||
line1 = ax.axvline(
|
||||
x=nyquist_PM, color="black", linestyle="-", lw=1, label="Nyquist (PM grid)", zorder=0
|
||||
)
|
||||
line3 = ax.axvline(
|
||||
x=xs_inv, color="gray", linestyle="-.", lw=2, label=r"Split wavenumber $x_s$", zorder=0
|
||||
)
|
||||
line4 = ax.axvline(
|
||||
x=xr_inv, color="gray", linestyle=":", lw=2, label=r"Short-range reach $x_r$", zorder=0
|
||||
)
|
||||
|
||||
logger.info(f"Nyquist (density grid): {nyquist:.2f} h/Mpc")
|
||||
logger.info(f"Nyquist (PM grid): {nyquist_PM:.2f} h/Mpc")
|
||||
logger.info(f"Particle wavenumber: {particle_wavenumber:.2f} h/Mpc")
|
||||
logger.info(f"Split wavenumber: {xs_inv:.2f} h/Mpc")
|
||||
logger.info(f"Short-range reach: {xr_inv:.2f} h/Mpc")
|
||||
|
||||
handles, labels = plt.gca().get_legend_handles_labels()
|
||||
# empty_patch = mpatches.Patch(color="none", label="")
|
||||
# handles = [empty_patch, *handles]
|
||||
# labels = ["", *labels]
|
||||
plt.legend(
|
||||
handles,
|
||||
labels,
|
||||
loc="upper center",
|
||||
ncol=2,
|
||||
bbox_to_anchor=(0.5, -0.2),
|
||||
fontsize=fs,
|
||||
frameon=False,
|
||||
)
|
||||
fig.savefig(
|
||||
outdir + "power_spectra.png",
|
||||
bbox_inches="tight",
|
||||
dpi=300,
|
||||
transparent=True,
|
||||
)
|
||||
fig.savefig(
|
||||
outdir + "power_spectra.pdf",
|
||||
bbox_inches="tight",
|
||||
dpi=300,
|
||||
)
|
||||
plt.close(fig)
|
||||
UNINDENT()
|
||||
logger.info(
|
||||
f"Power spectra plotted and saved to {outdir}power_spectra.png and power_spectra.pdf"
|
||||
)
|
||||
UNINDENT()
|
||||
logger.info("Computing and plotting power spectra done.")
|
||||
logger.info("All plots completed successfully.")
|
|
@ -1,43 +1,139 @@
|
|||
#!/bin/bash
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (C) 2025 Tristan Hoellinger
|
||||
# Distributed under the GNU General Public License v3.0 (GPLv3).
|
||||
# See the LICENSE file in the root directory for details.
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# ----------------------------------------------------------------------
|
||||
#SBATCH --job-name=cappel_L1024_Np512
|
||||
#SBATCH -o /data70/hoellinger/WIP3M/cappel_L1024_Np512/log.log
|
||||
#SBATCH -e /data70/hoellinger/WIP3M/cappel_L1024_Np512/err.err
|
||||
#SBATCH --exclusive
|
||||
#SBATCH -N 1 # Number of nodes (value or min-max)
|
||||
#SBATCH -n 128 # The number of tasks (i.e. cores) per node
|
||||
#SBATCH --time=24:00:00
|
||||
|
||||
# Author: Tristan Hoellinger
|
||||
# Version: 0.1
|
||||
# Date: 2025
|
||||
# License: GPLv3
|
||||
##SBATCH --exclusive
|
||||
##SBATCH --mem=64G # Memory pool for all cores (see also --mem-per-cpu)
|
||||
##SBATCH --array=0-10 # Size of the array
|
||||
##SBATCH --constraint=i1 # Constraint e.g. specific node
|
||||
|
||||
eval "$(conda shell.bash hook)"
|
||||
conda activate p3m
|
||||
|
||||
export OMP_NUM_THREADS=128
|
||||
|
||||
export OMP_NUM_THREADS=8
|
||||
python $WIP3M_ROOT_PATH"src/wip3m/convergence_baseline_ts_parser.py" \
|
||||
--run_id ts1/ \
|
||||
--L 64 \
|
||||
--N 64 \
|
||||
--Np 64 \
|
||||
--Npm 3600 \
|
||||
--n_Tiles 32 \
|
||||
--run_id cappel_L1024_Np512 \
|
||||
--L 1024 \
|
||||
--N 1024 \
|
||||
--Np 512 \
|
||||
--Npm 1024 \
|
||||
--n_Tiles 128 \
|
||||
--nsteps_pmref 200 \
|
||||
--nsteps_pm1 100 \
|
||||
--nsteps_pm2 20 \
|
||||
--nsteps_cola 10 \
|
||||
--nsteps_spm 200 \
|
||||
--nsteps_p3m1 200 \
|
||||
--nsteps_p3m2 100 \
|
||||
--nsteps_p3m3 20 \
|
||||
--tsd_pmref 0 \
|
||||
--tsd_pm1 0 \
|
||||
--tsd_pm2 0 \
|
||||
--tsd_cola 0 \
|
||||
--tsd_spm 0 \
|
||||
--tsd_p3m1 0 \
|
||||
--tsd_p3m2 0 \
|
||||
--tsd_p3m3 0
|
||||
--nsteps_pm2 50 \
|
||||
--nsteps_cola 20 \
|
||||
--nsteps_spm 400 \
|
||||
--nsteps_p3m1 400 \
|
||||
--nsteps_p3m2 300 \
|
||||
--nsteps_p3m3 200
|
||||
|
||||
# python $WIP3M_ROOT_PATH"src/wip3m/convergence_baseline_ts_parser.py" \
|
||||
# --run_id cappel_Np512 \
|
||||
# --L 512 \
|
||||
# --N 1024 \
|
||||
# --Np 512 \
|
||||
# --Npm 1024 \
|
||||
# --n_Tiles 128 \
|
||||
# --nsteps_pmref 200 \
|
||||
# --nsteps_pm1 100 \
|
||||
# --nsteps_pm2 50 \
|
||||
# --nsteps_cola 20 \
|
||||
# --nsteps_spm 400 \
|
||||
# --nsteps_p3m1 400 \
|
||||
# --nsteps_p3m2 300 \
|
||||
# --nsteps_p3m3 200
|
||||
|
||||
# python $WIP3M_ROOT_PATH"src/wip3m/convergence_baseline_ts_parser.py" \
|
||||
# --run_id cappel_loga_Np512 \
|
||||
# --L 512 \
|
||||
# --N 1024 \
|
||||
# --Np 512 \
|
||||
# --Npm 1024 \
|
||||
# --n_Tiles 128 \
|
||||
# --nsteps_pmref 200 \
|
||||
# --nsteps_pm1 100 \
|
||||
# --nsteps_pm2 50 \
|
||||
# --nsteps_cola 20 \
|
||||
# --nsteps_spm 400 \
|
||||
# --nsteps_p3m1 400 \
|
||||
# --nsteps_p3m2 300 \
|
||||
# --nsteps_p3m3 200 \
|
||||
# --tsd_pmref 1 \
|
||||
# --tsd_pm1 1 \
|
||||
# --tsd_pm2 1 \
|
||||
# --tsd_cola 1 \
|
||||
# --tsd_spm 1 \
|
||||
# --tsd_p3m1 1 \
|
||||
# --tsd_p3m2 1 \
|
||||
# --tsd_p3m3 1
|
||||
|
||||
# python $WIP3M_ROOT_PATH"src/wip3m/convergence_baseline_ts_parser.py" \
|
||||
# --run_id brabois_Np512_L1024 \
|
||||
# --L 1024 \
|
||||
# --N 1024 \
|
||||
# --Np 512 \
|
||||
# --Npm 1024 \
|
||||
# --n_Tiles 128 \
|
||||
# --nsteps_pmref 100 \
|
||||
# --nsteps_pm1 50 \
|
||||
# --nsteps_pm2 20 \
|
||||
# --nsteps_cola 20 \
|
||||
# --nsteps_spm 200 \
|
||||
# --nsteps_p3m1 200 \
|
||||
# --nsteps_p3m2 100 \
|
||||
# --nsteps_p3m3 50
|
||||
|
||||
# python $WIP3M_ROOT_PATH"src/wip3m/convergence_baseline_ts_parser.py" \
|
||||
# --run_id brabois_Np512 \
|
||||
# --L 512 \
|
||||
# --N 1024 \
|
||||
# --Np 512 \
|
||||
# --Npm 1024 \
|
||||
# --n_Tiles 128 \
|
||||
# --nsteps_pmref 100 \
|
||||
# --nsteps_pm1 50 \
|
||||
# --nsteps_pm2 20 \
|
||||
# --nsteps_cola 20 \
|
||||
# --nsteps_spm 200 \
|
||||
# --nsteps_p3m1 200 \
|
||||
# --nsteps_p3m2 100 \
|
||||
# --nsteps_p3m3 50
|
||||
|
||||
# python $WIP3M_ROOT_PATH"src/wip3m/convergence_baseline_ts_parser.py" \
|
||||
# --run_id brabois_Np256 \
|
||||
# --L 512 \
|
||||
# --N 512 \
|
||||
# --Np 256 \
|
||||
# --Npm 512 \
|
||||
# --n_Tiles 64 \
|
||||
# --nsteps_pmref 200 \
|
||||
# --nsteps_pm1 100 \
|
||||
# --nsteps_pm2 50 \
|
||||
# --nsteps_cola 20 \
|
||||
# --nsteps_spm 400 \
|
||||
# --nsteps_p3m1 400 \
|
||||
# --nsteps_p3m2 300 \
|
||||
# --nsteps_p3m3 200
|
||||
|
||||
# python $WIP3M_ROOT_PATH"src/wip3m/convergence_baseline_ts_parser.py" \
|
||||
# --run_id brabois_Np256_fine \
|
||||
# --L 512 \
|
||||
# --N 1024 \
|
||||
# --Np 256 \
|
||||
# --Npm 512 \
|
||||
# --n_Tiles 64 \
|
||||
# --nsteps_pmref 200 \
|
||||
# --nsteps_pm1 100 \
|
||||
# --nsteps_pm2 50 \
|
||||
# --nsteps_cola 20 \
|
||||
# --nsteps_spm 400 \
|
||||
# --nsteps_p3m1 400 \
|
||||
# --nsteps_p3m2 300 \
|
||||
# --nsteps_p3m3 200
|
||||
|
||||
exit 0
|
24
submit/plots_convergence_baseline_ts.sh
Normal file
24
submit/plots_convergence_baseline_ts.sh
Normal file
|
@ -0,0 +1,24 @@
|
|||
#!/bin/bash
|
||||
#SBATCH --job-name=cappel_L1024_Np512
|
||||
#SBATCH -o /data70/hoellinger/WIP3M/cappel_L1024_Np512/plots.log
|
||||
#SBATCH --exclusive
|
||||
#SBATCH -N 1 # Number of nodes (value or min-max)
|
||||
#SBATCH -n 128 # The number of tasks (i.e. cores) per node
|
||||
#SBATCH --time=2:00:00
|
||||
|
||||
##SBATCH --exclusive
|
||||
##SBATCH --mem=64G # Memory pool for all cores (see also --mem-per-cpu)
|
||||
##SBATCH --array=0-10 # Size of the array
|
||||
##SBATCH --constraint=i1 # Constraint e.g. specific node
|
||||
|
||||
conda activate p3m
|
||||
|
||||
export OMP_NUM_THREADS=64
|
||||
|
||||
python $WIP3M_ROOT_PATH"src/wip3m/plots_convergence_baseline_ts_parser.py" \
|
||||
--run_id cappel_L1024_Np512 \
|
||||
--outdir_suffix plots \
|
||||
--lpt True \
|
||||
--cola False
|
||||
|
||||
exit 0
|
Loading…
Add table
Add a link
Reference in a new issue