STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
test_ambient_isa.py
Go to the documentation of this file.
1"""The site ambient is the 1976 standard atmosphere, as its docstring always said it was.
2
3``compute_ambient_pressure_from_elevation`` was an isothermal exponential with T held at 288.15 K:
494 069.7 Pa at the LE4 site's 626.67 m against ISA's 94 020.4 Pa, 1.25 % high at 3 km.
5"""
6
7from __future__ import annotations
8
9import pytest
10
11from engine.core.runner import compute_ambient_pressure_from_elevation as ambient
12
13R0 = 6356766.0 # m, the 1976 standard's Earth radius for geopotential altitude
14
15
16def _isa_troposphere_by_hand(h: float) -> float:
17 """p = p0 (T/T0)^(g0 M0 / (R* L)): U.S. Standard Atmosphere 1976, eq. 33a, lowest layer."""
18 H = R0 * h / (R0 + h) # geopotential altitude
19 T0, L, g0, M0, Rs = 288.15, -0.0065, 9.80665, 0.0289644, 8.31432
20 return 101325.0 * ((T0 + L * H) / T0) ** (-g0 * M0 / (Rs * L))
21
22
23@pytest.mark.parametrize("h", [0.0, 626.67, 1400.0, 3000.0, 10000.0])
25 assert ambient(h) == pytest.approx(_isa_troposphere_by_hand(h), rel=1e-6)
26
27
29 assert ambient(626.67) == pytest.approx(94020.4, abs=0.1)
30
31
33 """Layer 1 runs every evaluation at, and targets as its exit pressure, the site ambient.
34
35 It kept its own isothermal exponential after the solver moved to the standard: 94 069.7 Pa at
36 the LE4 site against the 94 020.4 Pa forward mode, the Time-Series tab and Layer X evaluate at.
37 """
38 from types import SimpleNamespace
39
40 from engine.optimizer.layers.layer1_static_optimization import _layer1_site_ambient_pa
41
42 def cfg(elevation):
43 return SimpleNamespace(environment=SimpleNamespace(elevation=elevation))
44
45 assert _layer1_site_ambient_pa(cfg(626.67)) == ambient(626.67)
46 assert _layer1_site_ambient_pa(cfg(3000.0)) == ambient(3000.0)
47 # no site: sea level, as the runner falls back
48 assert _layer1_site_ambient_pa(cfg(None)) == 101325.0
49 assert _layer1_site_ambient_pa(SimpleNamespace(environment=None)) == 101325.0
50
51
53 """No module computes a second barometric formula beside the solver's: the isothermal one Layer 1
54 and the optimizer carried (dry air's molar mass, 0.0289644 kg/mol, in code) is how they drifted."""
55 import re
56 from pathlib import Path
57
58 root = Path(__file__).resolve().parents[1]
59 found = []
60 for sub in ("engine", "backend", "ui", "copv"):
61 for path in (root / sub).rglob("*.py"):
62 for n, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
63 if re.search(r"0\.0289644\b", line.split("#", 1)[0]):
64 found.append(f"{path.relative_to(root)}:{n}")
65 assert not found, f"a second site-atmosphere formula: {found}; call compute_ambient_pressure_from_elevation"
66
test_layer1_designs_at_the_solvers_ambient()
float _isa_troposphere_by_hand(float h)
test_matches_the_1976_standard_by_hand(h)