14 print(
"\n=== Testing Layer 2a Pointwise MR Check ===")
16 config_mock = MagicMock(spec=PintleEngineConfig)
17 config_mock.ablative_cooling =
None
18 config_mock.graphite_insert =
None
25 mr_spike = np.full(20, target_of)
26 mr_spike[10] = target_of * 1.3
29 "F": np.full(20, 1000.0),
30 "mdot_O": np.full(20, 1.0),
31 "mdot_F": np.full(20, 0.5),
33 "chugging_stability_margin": np.full(20, 1.0)
36 with patch(
"engine.optimizer.layers.layer2_pressure.PintleEngineRunner")
as MockRunner:
37 runner_instance = MockRunner.return_value
38 runner_instance.evaluate_arrays_with_time.return_value = mock_results
42 lox_min, fuel_min, summary, success = run_layer2a_minimum_pressures(
43 optimized_config=config_mock,
44 initial_lox_pressure_pa=3e6,
45 initial_fuel_pressure_pa=2e6,
47 target_apogee_m=1000.0,
48 rocket_dry_mass_kg=100.0,
49 max_lox_tank_capacity_kg=50.0,
50 max_fuel_tank_capacity_kg=50.0,
51 target_burn_time=10.0,
53 optimal_of_ratio=target_of
57 print(
"PASS: run_layer2a_minimum_pressures correctly rejected spiked MR.")
59 print(
"FAIL: run_layer2a_minimum_pressures accepted spiked MR despite 30% spike.")
62 print(
"\n=== Testing Layer 2 Objective Weighted MR Penalty ===")
64 config_mock = MagicMock(spec=PintleEngineConfig)
65 config_mock.ablative_cooling =
None
66 config_mock.graphite_insert =
None
71 mr_flat = np.full(20, target_of * 1.1)
76 mr_spiked = np.full(20, target_of)
77 mr_spiked[10] = target_of * 1.2
82 mr_very_spiked = np.full(20, target_of)
83 mr_very_spiked[10] = target_of * 1.4
85 with patch(
"engine.optimizer.layers.layer2_pressure.PintleEngineRunner")
as MockRunner:
86 runner_instance = MockRunner.return_value
90 runner_instance.evaluate_arrays_with_time.return_value = {
91 "F": np.full(20, 1000.0),
92 "mdot_O": np.full(20, 1.0),
93 "mdot_F": np.full(20, 0.5),
95 "chugging_stability_margin": np.full(20, 1.0),
96 "Pc": np.full(20, 2.5e6),
97 "press_tank": MagicMock()
99 runner_instance.evaluate.return_value = {
"Pc": 3e6}
102 def capture_obj(it, obj, best):
107 x = np.array([0.1, 0.9, 0.3, 1.0, 0.3] * 8)
110 optimized_config=config_mock,
111 initial_lox_pressure_pa=3e6,
112 initial_fuel_pressure_pa=2e6,
114 target_apogee_m=1000.0,
115 rocket_dry_mass_kg=100.0,
116 max_lox_tank_capacity_kg=100.0,
117 max_fuel_tank_capacity_kg=100.0,
118 target_burn_time=10.0,
121 optimal_of_ratio=target_of,
122 objective_callback=capture_obj,
126 return objs[0]
if objs
else 1e9
128 print(
"Calculating objective for flat MR (10% error everywhere)...")
129 obj_flat = get_obj(mr_flat)
130 print(f
"Flat Objective: {obj_flat:.2f}")
132 print(
"Calculating objective for spiked MR (20% max, 1% mean error)...")
133 obj_spiked = get_obj(mr_spiked)
134 print(f
"Spiked Objective: {obj_spiked:.2f}")
136 print(
"Calculating objective for very spiked MR (40% max, 2% mean error)...")
137 obj_very_spiked = get_obj(mr_very_spiked)
138 print(f
"Very Spiked Objective: {obj_very_spiked:.2f}")
145 if obj_very_spiked > obj_spiked:
146 print(
"PASS: Objective correctly penalizes larger spikes more heavily.")
148 print(
"FAIL: Objective did not penalize larger spike correctly.")