mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
fix(uvalues): bill known-insulation stone walls by the §5.6 thickness formula, uncapped (RdSAP 10 §5.6)
An uninsulated stone wall of lodged thickness, age bands A-E, is billed by the RdSAP 10 §5.6 Table-12 formula on its measured thickness — sandstone / limestone U = 54.876·W^-0.561, granite / whinstone U = 45.315·W^-0.513. Two bugs suppressed it: 1. CAP: the as-built branch capped the formula result at the Table-6 typical-thickness default (`if u0 >= 1.7: return 1.7`). But the formula only dips below 1.7 past ~488 mm (sandstone) / ~640 mm (granite), so the cap nullified §5.6 for essentially every real-thickness stone wall, under-counting fabric loss and over-rating. A measured 400 mm sandstone age-B wall is 1.90 (Elmhurst-confirmed), not 1.70. 2. NO INSULATION-STATE GATE: the branch fired for any stone wall with a lodged thickness, including ones whose insulation is "Unknown". RdSAP treats an unknown-insulation wall via the Table-6 typical-thickness default, NOT as bare stone of the lodged thickness — so a 50 mm granite wall with Unknown insulation must read 1.70 (worksheet), not the formula's 6.09. Gated on `wall_insulation_type is not None`. Fixes the 2 long-standing stone-U unit tests (granite 120 mm → 3.8871, sandstone 120 mm → 3.7408 — they were correct red tests, not "known fails"). Corpus within-0.5 70.3% -> 71.6% (MAE 0.833 -> 0.822); ratcheted floors to 0.71 / 0.83. Worksheet fixture 000565 (granite 50 mm Unknown → 1.70) still passes via the insulation gate. The two stone groups (sandstone/limestone vs granite/whinstone) keep their distinct §5.6 coefficients. pyright not installed in this codespace (strict gate not run locally). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
fc5f10ea92
commit
034d4b7cd5
2 changed files with 41 additions and 19 deletions
|
|
@ -567,23 +567,25 @@ def u_wall(
|
|||
ctry = country if country is not None else Country.ENG
|
||||
age_idx = _age_index(age_band)
|
||||
band = _AGE_BANDS[age_idx]
|
||||
# RdSAP 10 §5.6 (PDF p.40) — uninsulated stone wall thin-wall
|
||||
# formula, age bands A-E. Fires only when a documentary wall
|
||||
# thickness is lodged (per §5.3 documentary-evidence rule).
|
||||
# §5.8 + Table 14 dry-line adjustment applies on top.
|
||||
#
|
||||
# Table 6 footnote (a) (PDF p.34): "Or from equations in 5.6 if
|
||||
# the calculated U-value is less than 1.7." The cap applies only
|
||||
# to the AS-BUILT (no insulation, no dry-line) Table 6 row — for
|
||||
# thin walls where §5.6 gives U ≥ 1.7 (e.g. granite at W=50 mm
|
||||
# yields 6.09 → use Table 6 default 1.7 instead). When the wall
|
||||
# is dry-lined or insulated, the raw §5.6 result feeds the §5.8
|
||||
# chain as the input U₀ — the Table 6 footnote doesn't cap that
|
||||
# path (verified empirically against cert 000565 Main alt_wall_1:
|
||||
# granite W=120 mm dry-lined → U₀=3.88 raw + dry-line → 2.34
|
||||
# matches worksheet, NOT 1.7 + dry-line → 1.32).
|
||||
# RdSAP 10 §5.6 (PDF p.40) — uninsulated stone wall formula, age
|
||||
# bands A-E. Fires only when (a) a documentary wall thickness is lodged
|
||||
# (per §5.3 documentary-evidence rule) AND (b) the insulation STATE is
|
||||
# known (`wall_insulation_type` not None — As Built / external / internal).
|
||||
# When either is absent the cascade falls through to the Table-6
|
||||
# typical-thickness default (1.7) below: an "insulation Unknown" lodgement
|
||||
# is NOT treated as bare stone of the lodged thickness (cert 000565 Ext1:
|
||||
# granite 50 mm + insulation Unknown → Table-6 1.70 in the worksheet, NOT
|
||||
# the §5.6 formula's 6.09), and the footnote (a) "use §5.6 if the
|
||||
# calculated U-value is less than 1.7" clause governs the unknown path. When the thickness IS
|
||||
# lodged the raw §5.6 U is the spec target — it is NOT capped at 1.7,
|
||||
# because a thin/standard solid stone wall genuinely loses more than the
|
||||
# typical-thickness default (sandstone 400 mm → 1.90, granite 120 mm →
|
||||
# 3.89). §5.8 + Table 14 insulation / dry-line adjustments apply on top
|
||||
# of the raw §5.6 U₀ (cert 000565 Main alt_wall_1: granite W=120 mm
|
||||
# dry-lined → U₀=3.88 + dry-line → 2.34, matches worksheet).
|
||||
if (
|
||||
wall_thickness_mm is not None
|
||||
and wall_insulation_type is not None
|
||||
and band in _STONE_AGE_A_TO_E
|
||||
and construction in (WALL_STONE_GRANITE, WALL_STONE_SANDSTONE)
|
||||
):
|
||||
|
|
@ -628,8 +630,15 @@ def u_wall(
|
|||
Decimal("0.01"), rounding=ROUND_HALF_UP
|
||||
)
|
||||
)
|
||||
if u0 >= 1.7:
|
||||
return 1.7 # Table-6 row cap per footnote (a)
|
||||
# As-built (uninsulated, not dry-lined) stone wall of KNOWN
|
||||
# thickness, age A-E: return the raw §5.6 result. The Table-6
|
||||
# footnote (a) "< 1.7" clause governs the UNKNOWN-thickness path
|
||||
# (which falls through to the Table-6 typical 1.7 default below) —
|
||||
# NOT a documentary-thickness lodgement. A thin solid stone wall
|
||||
# genuinely has U > 1.7 (e.g. sandstone 400 mm = 1.90, granite
|
||||
# 120 mm = 3.89); capping it to 1.7 under-counts fabric loss and
|
||||
# over-rates. Confirmed against Elmhurst (age-B sandstone 400 mm
|
||||
# → 1.9) and the §5.6 Table-12 formula tests.
|
||||
return u0
|
||||
known_types = {
|
||||
WALL_STONE_GRANITE, WALL_STONE_SANDSTONE, WALL_SOLID_BRICK, WALL_CAVITY,
|
||||
|
|
|
|||
|
|
@ -150,14 +150,27 @@ _CORPUS = Path(
|
|||
# MAE 0.12 -> 0.08 t/yr (bias +0.04 -> 0.00). A prior session deferred enum 9
|
||||
# ("direction not understood") while the PE/CO2 lens was confounded by the
|
||||
# climate-cascade bug (fc7c4d2d); the corrected lens shows the over-rate.
|
||||
# UNINSULATED STONE WALL §5.6 FORMULA (RdSAP 10 §5.6 Table 12, PDF p.40): a
|
||||
# stone wall of KNOWN thickness whose insulation STATE is known (As Built /
|
||||
# external / internal) is billed by the §5.6 formula on its lodged thickness
|
||||
# (sandstone/limestone U = 54.876·W^-0.561, granite/whinstone 45.315·W^-0.513),
|
||||
# NOT capped at the Table-6 typical-thickness 1.7. The old `if u0>=1.7: 1.7`
|
||||
# cap nullified the formula for every real-thickness stone wall (it only dips
|
||||
# below 1.7 past ~488 mm sandstone / ~640 mm granite) and under-counted fabric
|
||||
# loss → over-rate. Gated on `wall_insulation_type is not None` so an
|
||||
# "insulation Unknown" wall still falls to the Table-6 default (cert 000565
|
||||
# Ext1: granite 50 mm + Unknown → worksheet 1.70, not the formula's 6.09).
|
||||
# Took within-0.5 70.3% -> 71.6% (MAE 0.833 -> 0.822); fixed the 2 stone-U
|
||||
# unit tests; worksheet-validated (Elmhurst age-B sandstone 400 mm → 1.90).
|
||||
#
|
||||
# SAP RATING FLOOR (SAP 10.2 §13 / RdSAP 10 §13): the rating is floored at 1
|
||||
# ("if the result is less than 1, the rating is 1"). `calculate_sap_from_inputs`
|
||||
# now applies that floor to the CONTINUOUS score too (was integer-only), so a
|
||||
# degenerate dwelling no longer emits a negative SAP. Removed a -12.3 outlier
|
||||
# (cert 422000111926, lodged at the floor of 1, was computing -11.3): within-0.5
|
||||
# 70.2% -> 70.3%, MAE 0.845 -> 0.833.
|
||||
_MIN_WITHIN_HALF_SAP = 0.70
|
||||
_MAX_SAP_MAE = 0.84
|
||||
_MIN_WITHIN_HALF_SAP = 0.71
|
||||
_MAX_SAP_MAE = 0.83
|
||||
_MAX_CO2_MAE_TONNES = 0.09 # t CO2 / yr vs co2_emissions_current
|
||||
_MAX_PE_PER_M2_MAE = 4.0 # kWh / m2 / yr vs energy_consumption_current
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue