9import sys, copy, json, argparse
17 ap = argparse.ArgumentParser()
18 ap.add_argument(
'--config', required=
True)
19 ap.add_argument(
'--out', default=
'', help=
'summary JSON path; default alongside the config')
20 ap.add_argument(
'--label', default=
'')
23 a.out = str(Path(a.config).with_suffix(
'.layer1.json'))
24 cfg = load_config(a.config)
25 req = cfg.design_requirements.model_dump()
27 pcfg = {
"mode":
"optimizer_controlled",
28 "max_lox_pressure_psi": float(req[
"max_lox_tank_pressure_psi"]),
29 "max_fuel_pressure_psi": float(req[
"max_fuel_tank_pressure_psi"])}
30 opt_cfg, results = run_layer1_optimization(
31 config_obj=copy.deepcopy(cfg), runner=runner, requirements=req,
32 target_burn_time=float(req.get(
"target_burn_time", 6.0)),
33 tolerances={
"thrust": 0.10,
"apogee": 0.15}, pressure_config=pcfg)
34 perf = results.get(
"performance")
or {}
35 ci = results.get(
"convergence_info")
or {}
37 "label": a.label,
"config": a.config,
38 "failure_reasons": list(perf.get(
"failure_reasons")
or []),
39 "gates": {k: v
for k, v
in perf.items()
if k.endswith(
"_check_passed")
or k.endswith(
"_gate_passed")},
40 "MR": perf.get(
"MR"),
"F": perf.get(
"F"),
"Pc_psi": (perf.get(
"Pc")
or 0)/6894.757,
41 "Isp": perf.get(
"Isp"),
"Lstar": perf.get(
"layer1_geometry_Lstar_config_m"),
42 "CR": perf.get(
"layer1_geometry_Ac_over_At"),
"eta_cstar": perf.get(
"eta_cstar"),
43 "R": perf.get(
"momentum_ratio_R"),
"n_F": perf.get(
"momentum_ratio_n_elements_F"),
44 "n_O": perf.get(
"momentum_ratio_n_elements_O"),
45 "imp_angle": perf.get(
"impingement_angle_deg_effective"),
46 "smd_um": perf.get(
"effective_smd_microns"),
47 "D_over_Dt": (ci.get(
"best_objective_breakdown")
or {}).get(
"chamber_D_over_Dt"),
48 "Isp_merit": (ci.get(
"best_objective_breakdown")
or {}).get(
"Isp_merit_s"),
49 "isp_penalty": (ci.get(
"best_objective_breakdown")
or {}).get(
"isp_penalty"),
50 "chamber_mass_kg": (ci.get(
"best_objective_breakdown")
or {}).get(
"chamber_mass_kg"),
51 "L_engine_m": (ci.get(
"best_objective_breakdown")
or {}).get(
"L_engine_m"),
52 "angle_O": perf.get(
"impingement_angle_O_deg"),
"angle_F": perf.get(
"impingement_angle_F_deg"),
53 "best_objective": ci.get(
"best_objective"),
54 "valid": perf.get(
"pressure_candidate_valid"),
56 "validation_tank_pressure_scale": perf.get(
"layer1_validation_tank_pressure_scale"),
57 "validation_replay_ok": perf.get(
"validation_replay_ok"),
58 "warnings": list(perf.get(
"layer1_warnings")
or []),
59 "final_rebuild_diag": results.get(
"final_rebuild_diag"),
60 "breakdown": ci.get(
"best_objective_breakdown"),
63 g = opt_cfg.injector.geometry
64 out[
"angle_O"] = float(g.oxidizer.impingement_angle)
65 out[
"angle_F"] = float(g.fuel.impingement_angle)
66 except AttributeError:
72 _yaml.safe_dump(config_to_dict(opt_cfg),
73 open(a.out.replace(
'.json',
'_config.yaml'),
'w'),
74 sort_keys=
False, default_flow_style=
False)
75 json.dump(out, open(a.out,
'w'), indent=1, default=str)
76 print(
"RESULT " + json.dumps({k: v
for k, v
in out.items()
77 if k
not in (
"breakdown",
"final_rebuild_diag")}, default=str))