1"""Which lines get a wall: `Session._build_line_walls` against the drawing.
3The wall model itself is held in ``test_wall.py``. This holds the build: a line
4the drawing itemised into segments is solved as a ``segmented`` pipe whose bore
5and length live in its segments, not in ``p`` (``_SUPERSEDED_BY_SEGMENTS``).
6Reading only ``p["bore"]`` left every such line bare, which on the LE4 (3)
7stand -- every line itemised -- made the default-on fitting heat a silent
8no-op in Hotbench and Layer X alike.
11from __future__
import annotations
14from pathlib
import Path
15from types
import SimpleNamespace
24HERE = Path(__file__).resolve().parent
25LE4 = HERE /
"fixtures" /
"le4_rocket_and_gse.json"
33BEND_MM = 29.923670025442775
36def _measured(value: float, unit: str) -> dict[str, object]:
37 return {
"value": value,
"unit": unit,
"source":
"measured"}
40def _drawing(segmented: bool, **line: dict[str, object]) -> dict[str, object]:
41 params: dict[str, object] = {
42 "length":
_measured((TUBE_MM + 3 * BEND_MM) / 1000.0,
"m"),
47 data: dict[str, object] = {
"lineType":
"pipe",
"params": params}
55 "lengthBasis":
"tube",
57 {
"id": f
"fit_{i}",
"kind":
"bend",
"count": 1,
"lengthMm": BEND_MM}
70 "fluidType":
"nitrogen",
77 {
"id":
"n2",
"type":
"VENT",
"data": {
"label":
"V-01"}},
79 "edges": [{
"id":
"L1",
"source":
"n1",
"target":
"n2",
"data": data}],
83def _walls(doc: dict[str, object]) -> dict[str, Any]:
84 """`_build_line_walls` on the drawing's network, nothing else of a session."""
85 built = build_network(read_diagram(doc))
86 stub: Any = SimpleNamespace(model=SimpleNamespace(built=built))
87 Session._build_line_walls(stub)
88 return dict(stub.walls)
92 """The same run, itemised or not, carries the same metal and the same area."""
95 assert set(plain) == {
"L1"}
96 assert set(itemised) == {
"L1"},
"the itemised run was left bare"
97 a, b = plain[
"L1"], itemised[
"L1"]
98 assert b.bore == pytest.approx(a.bore, rel=1e-12)
99 assert b.mass == pytest.approx(a.mass, rel=1e-12)
102 assert b.area == pytest.approx(a.area, rel=1e-3)
106 """Worked by hand: three 1/2 in.-class unions scaled to a 10.922 mm bore."""
108 bore = BORE_MM / 1000.0
109 assert wall.mass == pytest.approx(fitting_metal(3, bore))
110 assert wall.mass == pytest.approx(3 * 0.113 * (10.922 / 10.92) ** 2, rel=1e-9)
111 run = (TUBE_MM + 3 * BEND_MM) / 1000.0
112 assert wall.area == pytest.approx(math.pi * bore * run, rel=1e-12)
117 plain =
_walls(
_drawing(segmented=
False, wall_thickness=thickness))[
"L1"]
118 itemised =
_walls(
_drawing(segmented=
True, wall_thickness=thickness))[
"L1"]
119 assert itemised.mass > fitting_metal(3, BORE_MM / 1000.0)
120 assert itemised.mass == pytest.approx(plain.mass, rel=1e-3)
125 edge: Any = doc[
"edges"]
126 edge[0][
"data"][
"segments"][0].pop(
"bore")
127 edge[0][
"data"][
"params"].pop(
"bore")
132 """The shipped LE4 drawing: every pressurant run is itemised."""
135 built = build_network(read_diagram(json.loads(LE4.read_text()), name=
"LE4"))
136 stub: Any = SimpleNamespace(model=SimpleNamespace(built=built))
137 Session._build_line_walls(stub)
138 for line
in (
"node_2-junc_49",
"junc_49-junc_48",
"node_38-node_36"):
139 assert line
in stub.walls, (line, sorted(stub.walls))
141 assert "node_15-node_38" not in stub.walls
None test_a_drawn_wall_thickness_adds_the_tube_on_every_segment()
dict[str, object] _measured(float value, str unit)
None test_the_le4_press_lines_get_their_walls()
None test_a_one_segment_line_gets_the_darcy_pipes_wall()
None test_the_metal_is_the_counted_fittings_at_the_segment_bore()
dict[str, Any] _walls(dict[str, object] doc)
None test_an_itemised_run_with_no_bore_anywhere_stays_bare()
dict[str, object] _drawing(bool segmented, **dict[str, object] line)