All libraries · tests

tests/test_decay.py

Proper-time decay of macroparticles, daughter emission, energy bookkeeping, Gamma -> 0.

53 lines · 2.3 KB · pbhgr @ 9e8e13d · raw

"""Proper-time decay of macroparticles, daughter emission, energy bookkeeping, Gamma -> 0."""
import numpy as np
from pbhgr.spherical_ev import Grid, Particles, RunConfig, Run, solve_metric
from pbhgr.initial_data import shell_family


def test_time_dilation_of_decay_in_weak_field():
    # negligible mass -> flat space; particles moving with gamma = 2 decay slower by 1/gamma
    g = Grid(r_out=200.0, K=400)
    n = 2000
    gam = 2.0
    w = np.sqrt(gam**2 - 1) * np.ones(n)
    P = Particles(np.full(n, 10.0), w, np.zeros(n), np.full(n, 1e-9), np.ones(n))
    G = 0.5
    run = Run(g, P, RunConfig(Gamma=G, t_end=4.0, cfl=0.5, emit_fraction=0.3, diag_every=1000000))
    run.run()
    N_expected = 1e-9 * np.exp(-G * 4.0 / gam)
    Xmask = run.P.m > 0
    assert np.allclose(run.P.N[Xmask], N_expected, rtol=1e-6)
    # rest-mass ledger closes: remaining + pending + decayed(emitted) = initial
    tot = run.P.N[Xmask].sum() + run.P.pending.sum() + run.ledger.decayed_rest_mass
    assert abs(tot - n * 1e-9) < 1e-12 * n
    # daughters carry the parent energy: sum N E of daughters == decayed rest mass * gamma
    E = run.P.energy()
    Ed = np.sum((run.P.N * E)[~Xmask])
    assert abs(Ed - run.ledger.decayed_rest_mass * gam) < 1e-6 * Ed


def test_adm_mass_conserved_through_decay_and_escape():
    rng = np.random.default_rng(5)
    g = Grid(r_out=30.0, K=300)
    P = shell_family(M=1.0, R=5.0, n_part=4000, rng=rng, flatness=2.0, L_rms=0.3)
    P.N *= 1.0 / solve_metric(g, P).M
    run = Run(g, P, RunConfig(Gamma=0.3, t_end=40.0, cfl=0.4, emit_fraction=0.25, diag_every=50))
    run.run()
    Mt = np.array([d["M_total"] for d in run.diag])
    assert np.max(np.abs(Mt - Mt[0])) < 3e-3          # daughters escape carrying Killing energy
    assert run.ledger.escaped_daughters > 0
    assert run.diag[-1]["n_daughters"] >= 0


def test_gamma_to_zero_limit_is_continuous():
    rng = np.random.default_rng(7)
    res = {}
    for G in (0.0, 1e-4):
        g = Grid(r_out=30.0, K=300)
        P = shell_family(M=1.0, R=5.0, n_part=3000, rng=np.random.default_rng(7), flatness=2.0, L_rms=0.3)
        P.N *= 1.0 / solve_metric(g, P).M
        run = Run(g, P, RunConfig(Gamma=G, t_end=15.0, cfl=0.4, diag_every=50, seed=1))
        run.run()
        res[G] = run.diag[-1]["max_2m_over_r"]
    assert abs(res[0.0] - res[1e-4]) < 5e-3