mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
fix(uvalues): default unknown-thickness stone to §3.5 Table 3 thickness, not flat 1.7 (RdSAP 10 Table 3, PDF p.20)
When a stone wall lodges no documentary thickness, RdSAP 10 §3.5 Table 3 supplies the default thickness to feed the §5.6 formula — it does NOT fall to a flat 1.7. Table 3 stone row: A-D = 500 mm, E = 450, F-H = 420; Scotland footnote (*) adds 200 mm for bands A,B and 100 mm otherwise. This matches accredited Elmhurst: an England age-B granite/whinstone wall, as built, unknown thickness defaults to 500 mm → U = 45.315 × 500^(-0.513) = 1.87 (sandstone → 1.68). The previous flat-1.7 fallback was a setup error — Table 6 reads "According to 5.6" for bands A-D with no 1.7 entry, so the formula (not 1.7) is the spec target. The age-E footnote-(a) cap still applies on top. Adds `_table_3_stone_thickness(band, country)`. Updated the stale `..._returns_table_6_age_a_default` pin (was 1.7 → now 1.87 via Table-3) and added sandstone (1.68) + Scotland-+200mm (700 mm → 1.39) pins. Corpus: within-0.5 71.6% unchanged, SAP MAE 0.821 → 0.819, PE MAE 3.7 → 3.6. pyright not installed in this container — strict type gate not run locally. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7e187078b9
commit
54ae05d04b
2 changed files with 83 additions and 12 deletions
|
|
@ -226,6 +226,26 @@ def _u_stone_thin_wall_age_a_to_e(
|
|||
return None
|
||||
|
||||
|
||||
def _table_3_stone_thickness(band: str, country: Country) -> int:
|
||||
"""RdSAP 10 §3.5 Table 3 (PDF p.20) — default stone wall thickness (mm)
|
||||
used "only when the wall thickness could not be measured".
|
||||
|
||||
Stone row: A-D = 500, E = 450, F-H = 420, I+ = 450.
|
||||
Scotland footnote (*): add 200 mm for bands A and B, 100 mm for other
|
||||
bands. Only A-E reach this helper (the §5.6 formula gate), so the F+
|
||||
branches are defensive.
|
||||
"""
|
||||
if band in ("A", "B", "C", "D"):
|
||||
base = 500
|
||||
elif band == "E":
|
||||
base = 450
|
||||
else:
|
||||
base = 420
|
||||
if country == Country.SCT:
|
||||
base += 200 if band in ("A", "B") else 100
|
||||
return base
|
||||
|
||||
|
||||
def _u_brick_thin_wall_age_a_to_e(wall_thickness_mm: int) -> float:
|
||||
"""RdSAP 10 §5.7 Table 13 (PDF p.41) — default U-value for an
|
||||
uninsulated solid brick wall by lodged thickness, age bands A-E.
|
||||
|
|
@ -585,12 +605,22 @@ def u_wall(
|
|||
# 000565 Ext1 (granite 50 mm, age E, insulation Unknown) → min(6.09, 1.7)
|
||||
# = 1.70, matching the U985 worksheet WITHOUT a flat-table detour — the
|
||||
# age-E cap, not an insulation gate, is what produces the 1.70.
|
||||
#
|
||||
# When no documentary thickness is lodged, §3.5 Table 3 (PDF p.20) gives
|
||||
# the default thickness to feed the formula (stone A-D = 500 mm, E = 450,
|
||||
# Scotland +200/+100) — NOT a flat 1.7. This matches Elmhurst: an age-B
|
||||
# granite as-built wall with unknown thickness defaults to 500 mm →
|
||||
# 45.315 × 500^(-0.513) = 1.87 (sandstone → 1.68).
|
||||
if (
|
||||
wall_thickness_mm is not None
|
||||
and band in _STONE_AGE_A_TO_E
|
||||
band in _STONE_AGE_A_TO_E
|
||||
and construction in (WALL_STONE_GRANITE, WALL_STONE_SANDSTONE)
|
||||
):
|
||||
u0 = _u_stone_thin_wall_age_a_to_e(construction, wall_thickness_mm)
|
||||
w = (
|
||||
wall_thickness_mm
|
||||
if wall_thickness_mm is not None
|
||||
else _table_3_stone_thickness(band, ctry)
|
||||
)
|
||||
u0 = _u_stone_thin_wall_age_a_to_e(construction, w)
|
||||
if u0 is not None:
|
||||
# Footnote (a) cap is age-E only: clamp the as-built U to the
|
||||
# Table-6/7 age-E default (1.7, or 1.5 for Scotland sandstone/
|
||||
|
|
|
|||
|
|
@ -826,13 +826,14 @@ def test_u_wall_stone_granite_age_g_with_wall_thickness_ignores_5_6_formula_per_
|
|||
assert abs(result - 0.60) <= 1e-3
|
||||
|
||||
|
||||
def test_u_wall_stone_granite_age_a_without_wall_thickness_returns_table_6_age_a_default() -> None:
|
||||
# Arrange — §5.6 formula only fires when a wall thickness is
|
||||
# lodged. Without documentary wall-thickness evidence, fall back
|
||||
# to the Table 6 row (which represents typical thickness). For
|
||||
# age A stone granite without thickness, the cascade preserves
|
||||
# its existing "as-built typical" U value rather than the formula
|
||||
# extrapolation.
|
||||
def test_u_wall_stone_granite_age_a_without_wall_thickness_uses_table_3_default_500mm() -> None:
|
||||
# Arrange — when no documentary wall thickness is lodged, RdSAP 10 §3.5
|
||||
# Table 3 (PDF p.20) supplies the default stone thickness (A-D = 500 mm),
|
||||
# which feeds the §5.6 formula — NOT a flat 1.7. This matches Elmhurst:
|
||||
# an as-built granite/whinstone wall with unknown thickness defaults to
|
||||
# 500 mm → U = 45.315 × 500^(-0.513) = 1.8693. (The earlier 1.7
|
||||
# expectation was a setup error: Table 6 reads "According to 5.6" for
|
||||
# bands A-D, with no 1.7 entry.)
|
||||
|
||||
# Act
|
||||
result = u_wall(
|
||||
|
|
@ -845,8 +846,48 @@ def test_u_wall_stone_granite_age_a_without_wall_thickness_returns_table_6_age_a
|
|||
wall_thickness_mm=None,
|
||||
)
|
||||
|
||||
# Assert — _TYPICAL_STONE_UNINSULATED at age A = 1.7 (cohort default).
|
||||
assert abs(result - 1.7) <= 1e-3
|
||||
# Assert — §5.6 formula at the Table-3 default 500 mm.
|
||||
assert abs(result - 1.8693) <= 1e-3
|
||||
|
||||
|
||||
def test_u_wall_stone_sandstone_age_b_without_wall_thickness_uses_table_3_default_500mm() -> None:
|
||||
# Arrange — sandstone/limestone variant of the Table-3 default: age B,
|
||||
# unknown thickness → 500 mm → 54.876 × 500^(-0.561) = 1.6798. This is
|
||||
# the "500 mm → sandstone 1.68" Elmhurst default.
|
||||
|
||||
# Act
|
||||
result = u_wall(
|
||||
country=Country.ENG,
|
||||
age_band="B",
|
||||
construction=WALL_STONE_SANDSTONE,
|
||||
insulation_thickness_mm=None,
|
||||
insulation_present=False,
|
||||
wall_insulation_type=4,
|
||||
wall_thickness_mm=None,
|
||||
)
|
||||
|
||||
# Assert
|
||||
assert abs(result - 1.6798) <= 1e-3
|
||||
|
||||
|
||||
def test_u_wall_stone_sandstone_scotland_age_a_without_thickness_adds_200mm_per_table_3() -> None:
|
||||
# Arrange — Table 3 Scotland footnote (*): add 200 mm for bands A and B.
|
||||
# Age-A Scotland sandstone unknown thickness → 500 + 200 = 700 mm →
|
||||
# 54.876 × 700^(-0.561) = 1.3909 (< 1.7, no age-E cap at band A).
|
||||
|
||||
# Act
|
||||
result = u_wall(
|
||||
country=Country.SCT,
|
||||
age_band="A",
|
||||
construction=WALL_STONE_SANDSTONE,
|
||||
insulation_thickness_mm=None,
|
||||
insulation_present=False,
|
||||
wall_insulation_type=4,
|
||||
wall_thickness_mm=None,
|
||||
)
|
||||
|
||||
# Assert
|
||||
assert abs(result - 1.3909) <= 1e-3
|
||||
|
||||
|
||||
def test_u_wall_stone_granite_age_e_50mm_caps_at_table6_default_1_7() -> None:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue