42 target = Path(sys.argv[1]).resolve()
43 cfg_path = Path(sys.argv[2]).resolve()
44 out_path = Path(sys.argv[3]).resolve()
46 sys.path.insert(0, str(target))
50 config = load_config(str(cfg_path))
51 runner = PintleEngineRunner(config)
54 p_lox0 = float(getattr(config.lox_tank,
"initial_pressure_psi", 700.0))
55 p_fuel0 = float(getattr(config.fuel_tank,
"initial_pressure_psi", 600.0))
58 for scale
in (1.0, 0.9, 1.1):
59 P_O, P_F = p_lox0 * scale * psi, p_fuel0 * scale * psi
60 res = runner.evaluate(P_tank_O=P_O, P_tank_F=P_F)
61 diag = res.get(
"diagnostics", {})
or {}
63 "P_tank_O_psi": p_lox0 * scale,
64 "P_tank_F_psi": p_fuel0 * scale,
65 "outputs": {k:
_to_jsonable(res.get(k))
for k
in ANCHOR_FIELDS},
66 "diagnostics": {k:
_to_jsonable(diag.get(k))
for k
in DIAG_FIELDS},
69 "state": (res.get(
"stability_results")
or {}).get(
"stability_state"),
70 "score":
_to_jsonable((res.get(
"stability_results")
or {}).get(
"stability_score")),
76 "target_tree": str(target),
77 "config": str(cfg_path),
78 "fuel": str(config.fluids[
"fuel"].name),
79 "oxidizer": str(config.fluids[
"oxidizer"].name),
80 "injector_type": str(config.injector.type),
81 "equivalence_fields": {
"outputs": ANCHOR_FIELDS,
"diagnostics": DIAG_FIELDS},
82 "note":
"stability_ref is informational only — NOT part of anchor equivalence",
86 out_path.parent.mkdir(parents=
True, exist_ok=
True)
87 out_path.write_text(json.dumps(fixture, indent=2))
88 print(f
"wrote {out_path}")
91 print(f
" scale point: Pc={o['Pc']:.0f} Pa F={o['F']:.1f} N MR={o['MR']:.4f} Isp={o['Isp']:.2f}")