STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
test_layerx_feed_gaps.py
Go to the documentation of this file.
1"""A verdict that rests on a gap in the drawing says so up front (W14, known open).
2
3Since 2026-10-03 the chug margin is graded on the drawing's own feed lines, and the line losses are
4the drawing's. LE4 (3) draws its LOX path as direct connections (no line at all) and gives its fuel
5tank line a 0 mm bore: the graded margin is 1.004 (warn) against 1.21 on EngineDesign's own
6feed_system, and the flown burn depletes the other tank first. Preflight said nothing on the pad,
7and the flags sat inside ``diagnostics.stability.flags``. Preflight now warns, per side, and the
8graded chug limit names the gaps in its hint. The drawing itself is pid-designer's to fix.
9"""
10
11from __future__ import annotations
12
13import copy
14from dataclasses import replace
15from pathlib import Path
16
17import pytest
18
19pytest.importorskip("feedtwin", reason="lib/feedtwin is not installed")
20
21from engine.layerx import DrawingStore, LayerXSettings, prepare # noqa: E402
22from engine.layerx.diag.limits import grade # noqa: E402
23from engine.layerx.sources import shipped_drawings_dir # noqa: E402
24from engine.pipeline.io import load_config # noqa: E402
25
26GN2 = "copv_study_gn2"
27CFG = Path(__file__).resolve().parent / "fixtures" / "ethalox_6500N_doublet_cad_2026-09-28.yaml"
28needs_drawing = pytest.mark.skipif(not (shipped_drawings_dir() / f"{GN2}.json").is_file(),
29 reason="feed-twin's shipped drawings are not next to this checkout")
30
31
32@needs_drawing
34 config = load_config(str(CFG))
35 drawing = {d.name: d for d in DrawingStore(None).list()}[GN2]
36 settings = dict(replay=False, engine_model="native", tank_pressure_psia=600.0)
37 whole = prepare(config, None, drawing, LayerXSettings(drawing_id=drawing.id, **settings))
38 assert whole.ok and not any(c.key == "feed_lines" for c in whole.checks)
39
40 payload = copy.deepcopy(drawing.payload)
41 for e in payload["edges"]:
42 if e["id"] == "l_fu1":
43 e["data"]["params"]["bore"]["value"] = 0.0 # as LE4 (3)'s fuel tank line is drawn
44 gap = replace(drawing, id=drawing.id + "-gap", payload=payload)
45 prep = prepare(config, None, gap, LayerXSettings(drawing_id=gap.id, **settings))
46 check = next(c for c in prep.checks if c.key == "feed_lines")
47 assert check.status == "warn"
48 assert check.detail.startswith("Fuel: l_fu1 has no usable length or bore")
49 assert "LOX" not in check.detail
50
51
52def _result():
53 t = [-0.05, 0.0, 0.05, 0.10]
54 side = {"tank_psia": [578.0] * 4, "stiffness": [0.0, 0.0, 0.3, 0.3], "liquid_kg": [5.0] * 4}
55 block = {"t0_psia": 578.0, "min_psia": 570.0, "stiffness_min": 0.3, "peak_psia": 578.0, "loaded_kg": 5.0,
56 "residual_kg": 0.0}
57 return {"series": {"t": t, "dt": [0.05] * 4, "firing": [False, False, True, True], "converged": [True] * 4,
58 "copv_psia": [1500.0] * 4, "ox": dict(side), "fuel": dict(side)},
59 "summary": {"depleted_side": "oxidiser", "burn_time_s": 0.1, "copv_end_psia": 1500.0, "copv_t0_psia": 4500.0,
60 "ox": dict(block), "fuel": dict(block), "failed_steps": 0, "t0_settled": True, "steps": 4},
61 "events": [], "converged": True,
62 "provenance": {"derived": {"roles": {"oxidiser": "OXT", "fuel": "FUT"}, "ambient_pa": 101325.0}},
63 "diagnostics": {"stability": {
64 "basis": "drawing", "worst": {"t": 0.05, "index": 2, "margin": 1.004},
65 "settled_min": {"t": 0.10, "index": 3, "margin": 1.004}, "start_window_s": 0.05,
66 "flags": ["oxidiser: OM-R: no length on the drawing, so its body's inertance is not counted",
67 "fuel: node_15-node_38: no usable length/bore; left out of the inertance",
68 "oxidiser: the drawing declares no line on the path; the config's inertance is kept"]}}}
69
70
72 chug = next(e for e in grade(_result()) if e["key"] == "chug_margin")
73 assert chug["grade"] == "warn" and chug["value"] == 1.004
74 assert "It rests on gaps in the drawing: fuel: node_15-node_38: no usable length/bore" in chug["hint"]
75 assert "oxidiser: the drawing declares no line on the path" in chug["hint"]
76 assert len(chug["drawing_gaps"]) == 2 # the valve-body note is not a gap in the line