#!/usr/bin/env python3
"""Measure wall time per RK4 step and peak RSS vs particle number / grid size, then extrapolate
the Stage-A workload to see where this VPS stops being sufficient."""
import json, os, resource, subprocess, sys, time
import numpy as np
def probe(n_part, K, steps=10):
code = f"""
import numpy as np, time, resource, json
from pbhgr.spherical_ev import Grid, RunConfig, Run, solve_metric
from pbhgr.initial_data import shell_family
rng = np.random.default_rng(0)
g = Grid(r_out=30.0, K={K})
P = shell_family(1.0, 5.0, {n_part}, rng, flatness=2.0, L_rms=0.3)
P.N *= 1.0/solve_metric(g, P).M
run = Run(g, P, RunConfig(Gamma=0.2, t_end=1e9, cfl=0.4, diag_every=10**9, max_steps={steps}))
t0=time.time(); run.run(); dt=(time.time()-t0)/{steps}
print(json.dumps(dict(n_part={n_part}, K={K}, s_per_step=dt, peak_rss_MB=resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024)))
"""
out = subprocess.run([sys.executable, "-c", code], capture_output=True, text=True)
if out.returncode != 0:
err = out.stderr.strip().splitlines()[-1][:200] if out.stderr.strip() else f"killed (signal/OOM), returncode {out.returncode}"
return dict(n_part=n_part, K=K, error=err)
return json.loads(out.stdout.strip().splitlines()[-1])
rows = []
for n_part, K in [(2e4, 400), (1e5, 400), (1e5, 4000), (1e6, 4000), (3e6, 4000), (1e7, 10000), (2e7, 10000)]:
r = probe(int(n_part), K, steps=5 if n_part >= 1e6 else 10)
rows.append(r); print(r, flush=True)
json.dump(rows, open("runs/resource_probe.json", "w"), indent=1)