STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
run_layer1_impinging_8000n_followup_lox_dp.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2"""Follow-up Layer 1 starting from prior valid optimum: steer LOX dP_inj/Pc up with soft floor + W_DP_O."""
3
4from __future__ import annotations
5
6import argparse
7import copy
8import sys
9from pathlib import Path
10
11ROOT = Path(__file__).resolve().parents[1]
12sys.path.insert(0, str(ROOT))
13
14from engine.core.runner import PintleEngineRunner
15from engine.optimizer.layers.layer1_static_optimization import run_layer1_optimization
16from engine.pipeline.io import load_config
17
18
20 """Warm-start from last good follow-up (~7354 N, dP_O/Pc≈0.131, MR≈3.68).
21
22 Keeps ``A_exit = A_throat * expansion_ratio`` so ``PintleEngineRunner.evaluate`` does not abort.
23 """
24 cg = cfg.chamber_geometry
25 if cg is None:
26 raise ValueError("chamber_geometry required")
27 cg.A_throat = 0.001849
28 cg.expansion_ratio = 6.0
29 cg.A_exit = float(cg.A_throat) * float(cg.expansion_ratio)
30 cg.Lstar = 1.18811
31 cg.chamber_diameter = 0.15159999999999998
32 ox = cfg.injector.geometry.oxidizer
33 fu = cfg.injector.geometry.fuel
34 nd = 83
35 ox.n_elements = nd
36 ox.d_jet = 0.0014579
37 ox.impingement_angle = 63.70
38 ox.spacing = 0.0054755
39 fu.n_elements = nd
40 fu.d_jet = 0.0008857
41 fu.impingement_angle = 64.71
42 fu.spacing = 0.0061195
43 cfg.lox_tank.initial_pressure_psi = float(494.2608184424503)
44 cfg.fuel_tank.initial_pressure_psi = float(538.0149922949225)
45
46
47def main() -> None:
48 ap = argparse.ArgumentParser(description=__doc__)
49 ap.add_argument("--config", default=str(ROOT / "configs/impinging_lox_ch4_8000N.yaml"))
50 ap.add_argument("--max-it", type=int, default=95)
51 ap.add_argument("--restarts", type=int, default=2)
52 args = ap.parse_args()
53
54 cfg = load_config(args.config)
56
57 req = cfg.design_requirements.model_dump()
58 # LOX: hinge [0.15, 0.37] + floor at 0.15; YAML upper 0.37 preserved via model_dump.
59 req["injector_dp_ratio_O_min"] = 0.15
60 req["injector_dp_ratio_O_soft_floor"] = 0.15
61 req["W_DP_O_FLOOR"] = 9000.0
62 req["W_DP_O"] = 2500.0
63 req["injector_dp_ratio_F_min"] = 0.32
64 req["injector_dp_ratio_F_max"] = 0.57
65 req["layer1_P_O_start_psi_min"] = 490.0
66 req["layer1_P_O_start_psi_max"] = 515.0
67 req["layer1_P_F_start_psi_min"] = 535.0
68 req["layer1_P_F_start_psi_max"] = 552.0
69
70 runner = PintleEngineRunner(copy.deepcopy(cfg))
71 dr = cfg.design_requirements
72 pcfg = {
73 "mode": "optimizer_controlled",
74 "max_lox_pressure_psi": float(dr.max_lox_tank_pressure_psi),
75 "max_fuel_pressure_psi": float(dr.max_fuel_tank_pressure_psi),
76 }
77
78 opt_cfg, results = run_layer1_optimization(
79 copy.deepcopy(cfg),
80 runner,
81 req,
82 target_burn_time=float(req.get("target_burn_time", 6.0)),
83 tolerances={"thrust": 0.10, "apogee": 0.15},
84 pressure_config=pcfg,
85 layer1_smoke=False,
86 layer1_max_iterations=max(1, int(args.max_it)),
87 layer1_cma_restarts=max(1, int(args.restarts)),
88 )
89
90 perf = results.get("performance") or {}
91 ox = opt_cfg.injector.geometry.oxidizer
92 fu = opt_cfg.injector.geometry.fuel
93
94 print("\n=== Follow-up Layer 1 (warm LOX dP/Pc toward ≥0.15, prefer ≤0.37) ===")
95 print(f"req: LOX hinge [{req['injector_dp_ratio_O_min']},{req['injector_dp_ratio_O_max']}], "
96 f"W_DP_O={req['W_DP_O']}, W_DP_O_FLOOR={req['W_DP_O_FLOOR']}, "
97 f"fuel [{req['injector_dp_ratio_F_min']},{req['injector_dp_ratio_F_max']}]")
98 print()
99 print(f"thrust [N]: {perf.get('F')}")
100 print(f"MR: {perf.get('MR')}")
101 print(f"momentum_ratio_R: {perf.get('momentum_ratio_R')}")
102 print(f"dP_O/Pc: {perf.get('injector_dp_ratio_O')}")
103 print(f"dP_F/Pc: {perf.get('injector_dp_ratio_F')}")
104 print(f"P_O / P_F [psi]: {perf.get('P_O_start_psi')} / {perf.get('P_F_start_psi')}")
105 cg = opt_cfg.chamber_geometry
106 if cg is not None:
107 eps_s = float(cg.A_exit) / float(cg.A_throat) if cg.A_throat and cg.A_exit else float("nan")
108 print(
109 f"A_throat [m2] / A_exit [m2] / eps(sync check): "
110 f"{getattr(cg, 'A_throat', None)} / {getattr(cg, 'A_exit', None)} / {eps_s:.5g}"
111 )
112 print(
113 f"n_O/n_F | d_jet_O/d_jet_F [mm] | sp_O/sp_F [mm] | ang_O/ang_F [deg]: "
114 f"{int(ox.n_elements)}/{int(fu.n_elements)} | "
115 f"{ox.d_jet*1000:.4f}/{fu.d_jet*1000:.4f} | "
116 f"{ox.spacing*1000:.4f}/{fu.spacing*1000:.4f} | "
117 f"{ox.impingement_angle:.2f}/{fu.impingement_angle:.2f}"
118 )
119 print(f"pressure_candidate_valid: {perf.get('pressure_candidate_valid')}")
120
121
122if __name__ == "__main__":
123 main()
#define max(a, b)
Definition Arduino.h:43