All libraries · scripts

scripts/pm3d_shelltest.py

Lagrangian-shell test of the PM code against the exact LTB solution (spherical Yoo profile, mu = 0.1).

28 lines · 1.7 KB · pbhgr @ 9e8e13d · raw

"""Lagrangian-shell test of the PM code against the exact LTB solution (spherical Yoo profile, mu = 0.1).
Usage: python3 pm3d_shelltest.py N Np smooth a_end"""
import sys, numpy as np; sys.path.insert(0, '.')
from pbhgr.pm3d import PM3D, H_I, T_I
from pbhgr.profiles import profile_table
from pbhgr.ltb import LTBGaussian
N, Np, smooth, a_end = int(sys.argv[1]), int(sys.argv[2]), float(sys.argv[3]), float(sys.argv[4])
mu = 0.1; L = LTBGaussian(mu); rm = L.r_m; tC0 = L.tC(1e-6)
pm = PM3D(N, 6 * rm, Np, smooth=smooth).make_ic(mu, profile_table("yoo")["spline"])
shells = [(0.05, 0.1), (0.1, 0.15), (0.15, 0.2), (0.25, 0.3), (0.4, 0.5)]
sel = [(pm.r_ell_q >= lo * rm) & (pm.r_ell_q < hi * rm) for lo, hi in shells]
print(f"N={N} Np={Np} smooth={smooth}: shells (r_q/r_m) " + ", ".join(f"{lo}-{hi} ({s.sum()} p)" for (lo, hi), s in zip(shells, sel)))
print("t/tC0  | PM mean comoving radius / initial, per shell   ||  LTB R/(a e^zeta r) per shell")
a = 1.0
for a_t in np.array([200, 400, 600, 800, 1000, 1150, 1300]):
    if a_t > a_end: break
    while a < a_t:
        da = min(0.02 * a, a_t - a); a, _ = pm.step(a, da)
    t = T_I * a**1.5
    c = pm.L / 2
    pmv, ltbv = [], []
    for (lo, hi), s in zip(shells, sel):
        rel = (pm.x[s] - c + pm.L / 2) % pm.L - pm.L / 2
        r = np.sqrt((rel**2).sum(1)); pmv.append(r.mean() / pm.r_ell_q[s].mean())
        rq = 0.5 * (lo + hi) * rm
        ltbv.append(L.R(t, rq) / (a * rq * np.exp(L.zeta(rq))) if t < L.tC(rq) else 0.0)   # LTB areal radius R = a e^zeta r (1 - ...): compare per unit Lagrangian q
    print(f"{t/tC0:5.3f}  | " + " ".join(f"{v:6.3f}" for v in pmv) + "   ||  " + " ".join(f"{v:6.3f}" for v in ltbv), flush=True)