Model/docs/sap-spec/SPEC_COVERAGE.md
Khalim Conn-Kowlessar 6a3552a50d docs: §4 slice progress — happy path closes both non-RR fixtures
Updates SPEC_COVERAGE.md with the 9 §4 slices landed since the last doc
sweep, and lays out the remaining work in priority order:
  1. §4 orchestrator (water_heating_from_cert)
  2. Wire calculator.py to the new worksheet module
  3. End-to-end SAP score validation against Elmhurst worksheets
  4. Cylinder + solar + renewables branches (population coverage)
  5. PCDB-backed Table 3b/3c combi loss (000474 sits here)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 16:15:18 +00:00

8.8 KiB
Raw Blame History

SAP 10.2 / RdSAP 10 Coverage Map

Tracks which sections of the SAP 10.2 specification are implemented in packages/domain/src/domain/sap/. Per ADR-0009 the calculator is built from the spec, not reverse-engineered from cert data. This doc is the worksheet-driven roadmap for what remains.

Updated 2026-05-20 after §3 close (slices 344a9c9dcf244762).

The canonical SAP10.2 algorithm lives in 2026-05-19-17-18 RdSap10Worksheet.xlsx at the repo root — each line ref (1)..(486) maps to a cell. The worksheet sub-modules under packages/domain/src/domain/sap/worksheet/ implement those line refs directly; Elmhurst worksheets validate end-to-end via tests/_elmhurst_worksheet_*.py.

Sections §§113 (the SAP worksheet)

§ xlsx rows Topic Module Status Notes / gaps
1 1120 (approx) Dimensions worksheet/dimensions.py Full Porches, conservatories, RIR deferred per ADR-0009
2 121206 (approx) Ventilation worksheet/ventilation.py Partial No mechanical ventilation (MVHR/MEV), no wind-shelter factor, no pressure-test override (worksheet lines 17-18), no AP4 override (worksheet line 19)
3 121207 Heat transmission worksheet/heat_transmission.py Full (non-RR) LINE_31/33/36/37 exact for both non-RR Elmhurst fixtures (000474, 000490). Suspended-timber + Table 20 exposed-floor routes wired. RR sub-areas (gable/slope/stud-wall) deferred until SapRoomInRoof carries them. Global y-factor (Table R2 per-junction deferred).
4 207304 Hot water + Appendix J worksheet/water_heating.py (new) + legacy domain.ml.demand.predicted_hot_water_kwh (calculator still calls this) Happy-path done — see slice progress below. Worksheet-driven module lands line refs (42)..(65) for the combi-gas-boiler population (~70% of corpus). Cylinder + solar + renewables branches deferred. Calculator.py not yet wired to new module — next step.
5 Internal gains + Appendix L worksheet/internal_gains.py Full Default occupancy + Appendix L lighting fallback
6 Solar gains + Tables 6b/6c/6d + Appendix U worksheet/solar_gains.py Partial Per-orientation/pitch ✓; Tables 6b/6c lookups ✓; Z (overshading) hardcoded to 0.77 average; roof-lights treated as vertical
7 Mean internal temperature worksheet/mean_internal_temperature.py Partial Living area fraction from Table 27 ✓ (per S-A7b); control_type from main_heating_control code ✓ (S-B5); control_temperature_adjustment_c always 0
8 Off-period temperature reduction inline in mean_internal_temperature.py Full Table 9b implemented
9 Space heating worksheet/space_heating.py Partial Single main system only — no Table 11 secondary heating allocation (10% fraction on most boilers — likely big MAE)
10 Cooling Not implemented Rare in UK dwellings; defer
11 FEE Not implemented Only for new-build; not required for ratings
12 Total energy + fuel costs calculator.py Partial Per-end-use cost split ✓; meter_type tariff routing ✓ (S-B15); PV cost credit ✓ (S-B19); standing charges not included (Table 12 note (a) says rating omits standing charge for std electricity tariff)
13 SAP rating worksheet/rating.py Full Equations 7-9 verified against SAP 10.2 §13
14 CO2 + primary energy calculator.py SapResult.co2_kg_per_yr Partial Single CO2 factor on main fuel; no per-end-use CO2 mixing; no primary energy calculation
15 Building regs n/a n/a Not relevant to ratings

Appendices

Appendix Topic Status Notes
A Main + secondary heating identification Not implemented First main only; Table 11 secondary fraction missing — high-value gap
B Gas/oil boilers + boiler interlock Partial Via Table 4b in domain.ml.sap_efficiencies.seasonal_efficiency
C Community heating Not implemented Heat network certs handled by Table 4a codes 301-304 (efficiency only)
D PCDB Stubbed Per ADR-0009 grill: NoOpPcdbLookup returning None; Session C bundles a CSV PCDB extract
E Heat pumps Partial Category fallback to 2.30 for cat=4; no MCS installation factor (×1.39 GSHP); no flow temp adjustment
F Electric CPSU Not implemented Rare
G FGHRS / WWHRS / PV-diverter Not implemented Rare
H Solar water heating Partial Boolean has_solar_water_heating reduces HW by 250 kWh; no actual collector calc
J Hot water demand Partial See §4 row above
K Thermal bridging Partial Using global y per age band (per ADR-0009 grill: per-junction Table R2 deferred)
L Lighting Full Existing-dwelling fallback ✓
M PV / wind / hydro generation Partial PV ✓ (S-B19); wind / hydro / micro-CHP not implemented
N Micro-CHP Not implemented Rare
P Electric storage heaters detail Partial Identified via codes 401-409; Table 12a high-rate fractions not exact (we use 100% off-peak per cert-calibration heuristic)
Q Special features Not implemented One-off energy-use additions; rare
R Reference dwelling Not implemented Only needed for compliance, not ratings
S RdSAP procedures Separate PDF (114pp) Cert→inputs mapper in domain.sap.rdsap.cert_to_inputs ports key rules; many sections of RdSAP 10 not yet read
T Improvement measures Not relevant Recommendation engine, not rating
U Climate data Full Tables U1/U2/U3 + solar declination + Table U5 k1-k9

Prioritised gap list (by likely MAE impact)

  1. Table 11 Secondary heating allocation — most boiler-main certs allocate 10% of space heating to a secondary system (often a less-efficient room heater on a different fuel). We model 0%. Likely +1-2 SAP-point bias on affected certs.
  2. Wind-shelter factor on infiltration (§2 worksheet lines 19-21) — multiplies infiltration by 1 - 0.075 × sheltered_sides. We have no shelter input; assume 2 sheltered sides default. Net effect on infiltration ACH probably ~10%.
  3. Table 12a high-rate fraction for off-peak dwellings — we currently bill 100% of E7 space heating at the low rate. Real spec says e.g. heat pumps on 7h tariff at 80% high-rate. Affects ~5% of certs.
  4. Cylinder-loss factor cascade — currently uses simplified buckets in domain.ml.demand._STORAGE_LOSS_FACTOR. Spec has more precise interpolation rules from cylinder volume + insulation thickness.
  5. Standing charges in cost — Table 12 note (a) gives the rule for when standing charges are included (energy use vs rating). May affect bias.
  6. Per-junction thermal bridging (Table R2) — only relevant when assessor lodged junction-count data, otherwise global y is the spec answer for RdSAP-driven assessments.

Status now: 100-cert MAE 4.49, 300-cert MAE 5.45, bias near zero (±0.2). Worksheet-driven phase begins with Secondary heating Table 11 as the next slice.

§4 — slice progress (xlsx rows 207304)

Line ref Description Status Commit
(42) Assumed occupancy N from Appendix J aff678e8
(42a)m Mixer showers monthly 1dcbdb28
(42b)m Baths monthly dad7fbf3
(42c)m Other uses monthly 5cc68ab3
(43) Annual avg 702b1c6c
(44)m Daily monthly total 702b1c6c
(45)m Energy content a3c687f1
(46)m Distribution loss a3c687f1
(47)(56) Storage / HIU loss Combi zero-branch only; cylinder paths deferred
(57)m Dedicated solar storage Combi zero-branch only; solar HW deferred
(59)m Primary loss Combi zero-branch only; boiler+cylinder deferred
(61)m Combi loss Table 3a row "time-clock keep-hot" only bfba610b
(62)m Total demand bfba610b
(63a-d) WWHRS/PV/Solar/FGHRS reductions Zero-only — non-zero paths deferred feef8198
(64)m Output from water heater (with max-clamp) feef8198
(64a)m Electric shower energy Zero-only — non-zero path deferred
(65)m Heat gains 43da3ea0

Happy path closes both non-RR Elmhurst fixtures to <1e-3 kWh end-to-end on lines (42)..(65) (000474's PCDB-backed Table 3b combi loss is the one hand-lodged value).

Remaining §4 work

  1. Orchestrator water_heating_from_cert(epc, ...) that wires the leaf functions, mirroring heat_transmission_from_cert for §3.
  2. Integrate with calculator.py — replace the legacy domain.ml.demand.predicted_hot_water_kwh call.
  3. End-to-end SAP score validation against the worksheets — the real e2e test the user has been asking for.
  4. Cylinder + solar + renewables paths for full population coverage (cylinders, FGHRS, WWHRS, PV-diverter).
  5. PCDB-backed Table 3b/3c combi loss for tested boilers (000474 sits here).