STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
test_time_varying_ambient.py
Go to the documentation of this file.
1"""The time-varying solver must fire the nozzle into the same sky as the steady solve.
2
3Found while integrating a flat dome-regulated burn: ``evaluate_arrays_with_time`` reported
46344.1 N at t=0 where ``evaluate()`` reported 6405.5 N for the same tank pressures and the
5same geometry. Pc, mdot, O/F and c* agreed to four figures -- only thrust differed, by exactly
6``(101325 - P_a(site)) * A_exit`` = 61.35 N. ``TimeVaryingCoupledSolver.solve_time_step``
7hardcoded ``Pa = 101325.0`` while the steady path derives ambient from
8``environment.elevation``. Every time-series thrust, impulse and burn-time number was low by
9the site's altitude, and the two paths disagreed about the same engine.
10
11At t=0 nothing has receded yet, so the two paths evaluate identical geometry and must agree.
12"""
13import copy
14import os
15import sys
16
17import numpy as np
18import pytest
19
20sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
21
22from engine.core.runner import PintleEngineRunner, compute_ambient_pressure_from_elevation # noqa: E402
23from engine.pipeline.io import load_config # noqa: E402
24
25# A shipped config, not a golden one: tests/golden/ is gitignored, so a test
26# that leaned on it errored on every machine but the one it was written on,
27# CI included. What the test needs is the coupled ablative path on an ethalox
28# engine, and the 180 lb point ships with exactly that.
29_CFG = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "configs", "ethalox_180lb_8to1.yaml")
30_PSI = 6894.757
31
32
33@pytest.fixture(scope="module")
34def cfg():
35 c = load_config(_CFG)
36 # Put the pad somewhere with real altitude so a sea-level default is visibly wrong:
37 # 626.67 m is the elevation the shipped ethalox configs declare (94.07 kPa, 7.2 % below 1 atm).
38 c.environment.elevation = 626.67
39 assert c.ablative_cooling is not None and c.ablative_cooling.enabled
40 assert getattr(c.ablative_cooling, "track_geometry_evolution", False), \
41 "fixture must exercise the coupled time-varying path"
42 return c
43
44
46 P_O = cfg.lox_tank.initial_pressure_psi * _PSI
47 P_F = cfg.fuel_tank.initial_pressure_psi * _PSI
48
49 steady = PintleEngineRunner(copy.deepcopy(cfg)).evaluate(P_O, P_F, silent=True)
50
51 t = np.array([0.0, 0.05])
52 tv = PintleEngineRunner(copy.deepcopy(cfg)).evaluate_arrays_with_time(
53 t, np.array([P_O, P_O]), np.array([P_F, P_F]), use_coupled_solver=True)
54
55 # Same geometry, same chamber state -> the two paths must agree on thrust at t=0.
56 # Chamber quantities are the control: they agreed before the fix, so if THEY move the
57 # test is measuring something else.
58 assert abs(float(tv["Pc"][0]) / float(steady["Pc"]) - 1.0) < 1e-3
59 assert abs(float(tv["mdot_total"][0]) / float(steady["mdot_total"]) - 1.0) < 1e-3
60
61 F_tv = float(tv["F"][0])
62 F_st = float(steady["F"])
63 # The bug was a fixed Pa*Ae offset; require agreement well inside that offset.
64 Ae = float(cfg.chamber_geometry.A_exit)
65 offset_if_sea_level = (101325.0 - compute_ambient_pressure_from_elevation(626.67)) * Ae
66 assert abs(F_tv - F_st) < 0.1 * offset_if_sea_level, (
67 f"t=0 thrust disagrees: time-varying {F_tv:.2f} N vs steady {F_st:.2f} N "
68 f"(a sea-level ambient would put them {offset_if_sea_level:.2f} N apart)")
69
70
72 """Passing P_ambient must override the site elevation in both paths alike."""
73 P_O = cfg.lox_tank.initial_pressure_psi * _PSI
74 P_F = cfg.fuel_tank.initial_pressure_psi * _PSI
75 Pa = 60000.0 # well above the pad, well away from either default
76 steady = PintleEngineRunner(copy.deepcopy(cfg)).evaluate(P_O, P_F, P_ambient=Pa, silent=True)
77 t = np.array([0.0, 0.05])
78 tv = PintleEngineRunner(copy.deepcopy(cfg)).evaluate_arrays_with_time(
79 t, np.array([P_O, P_O]), np.array([P_F, P_F]), P_ambient=Pa, use_coupled_solver=True)
80 assert abs(float(tv["F"][0]) - float(steady["F"])) < 0.5