mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
Slice S0380.118: cohort LINE_xx pins → abs=1e-4 + §15-rounded RR test expecteds
Two changes bundled (same file, same RdSAP 10 §15 spec citation):
1. Tighten cohort cert (000474 / 000490) heat_transmission LINE_xx
pins from abs=0.01 / 0.1 → abs=1e-4 (4 pins). Pre-slice the cohort
landed at 1e-4 of the U985 PDF but the test pins were holdovers
from when the cascade was less precise. Per [[feedback-e2e-
validation-philosophy]]:
"per-component tests pin against U985 worksheet line refs at
<1e-3 tolerance ... 1e-4 since PDF lodges 4 d.p."
Probe data at HEAD post-§15:
000474 LINE_33 cascade=209.108439 ws=209.1084 Δ=+4e-5
000474 LINE_37 cascade=232.116939 ws=232.1169 Δ=+4e-5
000490 LINE_33 cascade=211.893610 ws=211.8936 Δ=+1e-5
000490 LINE_37 cascade=236.621110 ws=236.6211 Δ=+1e-5
2. Update `test_room_in_roof_simplified_type_1` and `..._type_2`
expected-value formulas to round A_RR_shell to 2 d.p. per RdSAP
10 §15 (p.66) — matching the cascade behaviour now enforced by
Slice S0380.116. The unrounded expected was 100.9156 / 71.857;
spec-correct rounded is 100.919 (39.5285 → 39.53) and 71.846
(32.2749 → 32.27). Same abs=1e-4 pin enforces both arithmetic
and rounding correctness.
New import: `_round_half_up` from heat_transmission (the same
helper the cascade uses for §15 rounding).
Net pyright change: 71 → 71. Net test change: 4 newly-tight pins,
2 newly-passing RR synthetic tests, 670 → 670 passing.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
586bb27d95
commit
412525ae6f
1 changed files with 30 additions and 16 deletions
|
|
@ -36,6 +36,7 @@ from domain.sap10_calculator.worksheet.heat_transmission import (
|
|||
heat_transmission_from_cert,
|
||||
)
|
||||
from domain.sap10_calculator.worksheet.heat_transmission import (
|
||||
_round_half_up, # pyright: ignore[reportPrivateUsage]
|
||||
_window_bp_index, # pyright: ignore[reportPrivateUsage]
|
||||
)
|
||||
|
||||
|
|
@ -1367,12 +1368,15 @@ def test_section_3_non_rr_line_31_and_36_match_elmhurst_worksheet(
|
|||
door_count=0,
|
||||
)
|
||||
|
||||
# Assert
|
||||
# Assert — per [[feedback-e2e-validation-philosophy]] cohort cert
|
||||
# LINE_xx pins ride at abs=1e-4 to match the U985 PDF's 4-d.p.
|
||||
# display precision; the cascade lands well inside that for both
|
||||
# non-RR fixtures (000474 / 000490).
|
||||
assert result.total_external_element_area_m2 == pytest.approx(
|
||||
fixture.LINE_31_TOTAL_EXTERNAL_AREA_M2, abs=0.01
|
||||
fixture.LINE_31_TOTAL_EXTERNAL_AREA_M2, abs=1e-4
|
||||
)
|
||||
assert result.thermal_bridging_w_per_k == pytest.approx(
|
||||
fixture.LINE_36_THERMAL_BRIDGING_W_PER_K, abs=0.01
|
||||
fixture.LINE_36_THERMAL_BRIDGING_W_PER_K, abs=1e-4
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -1395,12 +1399,16 @@ def test_section_3_line_33_and_line_37_match_elmhurst_worksheet_000474() -> None
|
|||
door_count=_w000474.DOOR_COUNT,
|
||||
)
|
||||
|
||||
# Assert
|
||||
# Assert — per [[feedback-e2e-validation-philosophy]] cohort cert
|
||||
# LINE_33 / LINE_37 pins ride at abs=1e-4 to match the U985 PDF's
|
||||
# 4-d.p. display precision. Pre-S0380.69 the cascade ran 0.05 W/K
|
||||
# off here; the curtain-resistance + per-storey-perimeter fixes
|
||||
# have closed those — the cascade lands at 4e-5 today.
|
||||
assert result.fabric_heat_loss_w_per_k == pytest.approx(
|
||||
_w000474.LINE_33_FABRIC_HEAT_LOSS_W_PER_K, abs=0.1
|
||||
_w000474.LINE_33_FABRIC_HEAT_LOSS_W_PER_K, abs=1e-4
|
||||
)
|
||||
assert result.total_w_per_k == pytest.approx(
|
||||
_w000474.LINE_37_TOTAL_FABRIC_HEAT_LOSS_W_PER_K, abs=0.1
|
||||
_w000474.LINE_37_TOTAL_FABRIC_HEAT_LOSS_W_PER_K, abs=1e-4
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -1425,12 +1433,14 @@ def test_section_3_line_33_and_line_37_match_elmhurst_worksheet_000490() -> None
|
|||
door_count=_w000490.DOOR_COUNT,
|
||||
)
|
||||
|
||||
# Assert
|
||||
# Assert — per [[feedback-e2e-validation-philosophy]] cohort cert
|
||||
# LINE_33 / LINE_37 pins ride at abs=1e-4 to match the U985 PDF's
|
||||
# 4-d.p. display precision. Cascade lands at 1e-5 for 000490.
|
||||
assert result.fabric_heat_loss_w_per_k == pytest.approx(
|
||||
_w000490.LINE_33_FABRIC_HEAT_LOSS_W_PER_K, abs=0.1
|
||||
_w000490.LINE_33_FABRIC_HEAT_LOSS_W_PER_K, abs=1e-4
|
||||
)
|
||||
assert result.total_w_per_k == pytest.approx(
|
||||
_w000490.LINE_37_TOTAL_FABRIC_HEAT_LOSS_W_PER_K, abs=0.1
|
||||
_w000490.LINE_37_TOTAL_FABRIC_HEAT_LOSS_W_PER_K, abs=1e-4
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -1561,10 +1571,12 @@ def test_room_in_roof_simplified_type_1_adds_a_rr_timber_framed_area_to_roof_w_p
|
|||
epc, window_total_area_m2=0.0, window_avg_u_value=None, door_count=0,
|
||||
)
|
||||
|
||||
# Assert
|
||||
a_rr = 12.5 * math.sqrt(15.0 / 1.5)
|
||||
# Assert — per RdSAP 10 §15 (p.66) "All element areas (gross) ... 2
|
||||
# d.p." the cascade rounds A_RR_shell before the (30) residual. For
|
||||
# A_RR_floor = 15 m²: 12.5 × √10 = 39.5285 → 39.53 m² (HALF_UP).
|
||||
a_rr = _round_half_up(12.5 * math.sqrt(15.0 / 1.5), 2)
|
||||
expected_roof_w_per_k = (40.0 - 15.0) * 0.40 + a_rr * 2.30
|
||||
assert result.roof_w_per_k == pytest.approx(expected_roof_w_per_k, abs=0.001)
|
||||
assert result.roof_w_per_k == pytest.approx(expected_roof_w_per_k, abs=1e-4)
|
||||
|
||||
|
||||
def test_room_in_roof_simplified_type_2_common_walls_route_to_walls_w_per_k() -> None:
|
||||
|
|
@ -1626,14 +1638,16 @@ def test_room_in_roof_simplified_type_2_common_walls_route_to_walls_w_per_k() ->
|
|||
epc, window_total_area_m2=0.0, window_avg_u_value=None, door_count=0,
|
||||
)
|
||||
|
||||
# Assert
|
||||
# Assert — per RdSAP 10 §15 (p.66) "All element areas (gross) ... 2
|
||||
# d.p." the cascade rounds A_RR_shell before the (30) residual. For
|
||||
# A_RR_floor = 10 m²: 12.5 × √(10/1.5) = 32.2749 → 32.27 m² (HALF_UP).
|
||||
a_common = 5.0 * (0.25 + 1.0)
|
||||
a_rr = 12.5 * math.sqrt(10.0 / 1.5)
|
||||
a_rr = _round_half_up(12.5 * math.sqrt(10.0 / 1.5), 2)
|
||||
a_rr_final = a_rr - a_common
|
||||
expected_walls = 60.0 * 1.5 + a_common * 1.5
|
||||
expected_roof = (40.0 - 10.0) * 0.40 + a_rr_final * 2.30
|
||||
assert result.walls_w_per_k == pytest.approx(expected_walls, abs=0.001)
|
||||
assert result.roof_w_per_k == pytest.approx(expected_roof, abs=0.001)
|
||||
assert result.walls_w_per_k == pytest.approx(expected_walls, abs=1e-4)
|
||||
assert result.roof_w_per_k == pytest.approx(expected_roof, abs=1e-4)
|
||||
|
||||
|
||||
def test_room_in_roof_detailed_per_surface_lodgement_routes_each_to_correct_line_ref() -> None:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue