mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
docs: sweep stale handover, mark §3 Full, scaffold §4 slice plan
§3 close (LINE_31/33/36/37 exact for both non-RR Elmhurst worksheets) is
now landed across slices 344a9c9d..cf244762. HANDOVER_S3_CLOSE.md was
written as a mid-stream working brief; with §3 done it now creates doc
rot, so it's removed in favour of SPEC_COVERAGE.md as the single source
of truth.
SPEC_COVERAGE.md updates:
- §3 marked Full (non-RR); RR sub-area deferral noted
- §4 carries the ordered slice plan for the worksheet-driven rewrite
(xlsx rows 207–304, line refs (42)..(65))
- Hierarchy callout: the canonical SAP10.2 algorithm lives in the
repo-root xlsx, not in any handover doc
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
cf244762d5
commit
d90827446a
2 changed files with 32 additions and 156 deletions
|
|
@ -1,149 +0,0 @@
|
|||
# Handover — Close §3, then Table 11 Secondary Heating
|
||||
|
||||
**Audience:** Fresh agent continuing the deterministic SAP 10.2 calculator
|
||||
(`packages/domain/src/domain/sap/`). Read this document first, then skim
|
||||
the two key source files listed below.
|
||||
|
||||
---
|
||||
|
||||
## What we're building
|
||||
|
||||
A deterministic SAP 10.2 calculator that replicates cert-software output
|
||||
(Elmhurst, Stroma, etc.) exactly for RdSAP 10 input certs. The domain
|
||||
concept is **Calculated SAP10 Performance** — see
|
||||
`docs/adr/0009-deterministic-sap-calculator.md`. Progress is tracked in
|
||||
`docs/sap-spec/SPEC_COVERAGE.md`.
|
||||
|
||||
The workflow is strict TDD: **one failing test → minimal implementation →
|
||||
commit**. Each commit is one slice.
|
||||
|
||||
---
|
||||
|
||||
## Current state
|
||||
|
||||
### §1 Dimensions — DONE
|
||||
All 6 Elmhurst fixtures pass exactly (`test_section_1_matches_elmhurst_worksheet`).
|
||||
|
||||
### §2 Ventilation — DONE
|
||||
All 6 Elmhurst fixtures pass exactly (`test_section_2_matches_elmhurst_worksheet`).
|
||||
|
||||
### §3 Heat transmission — PARTIALLY DONE
|
||||
|
||||
What passes today:
|
||||
- **Internal invariants** (all 6 fixtures): `(33) = Σ per-element`,
|
||||
`(37) = (33) + (36)`.
|
||||
- **Exact LINE_31 + LINE_36** (non-RR fixtures 000474 and 000490 only):
|
||||
`test_section_3_non_rr_line_31_and_36_match_elmhurst_worksheet`.
|
||||
|
||||
What does NOT yet pass:
|
||||
- **Exact LINE_33** (fabric heat loss) for any fixture. This is the
|
||||
remaining §3 close task (see below).
|
||||
- **RR sub-areas** (fixtures 000487, 000480, 000477, 000516): gable/
|
||||
slope/stud-wall/flat-ceiling areas are not in `SapRoomInRoof`; these
|
||||
fixtures are **formally deferred** — see gap notes in
|
||||
`test_section_3_partial_match_against_elmhurst_worksheet`.
|
||||
|
||||
---
|
||||
|
||||
## Task A — Close LINE_33 for non-RR fixtures (investigation slice)
|
||||
|
||||
**Goal:** assert exact LINE_33 and LINE_37 for 000474 and 000490.
|
||||
|
||||
### The diagnostic gap
|
||||
|
||||
Running `heat_transmission_from_cert(epc, window_total_area_m2=0, door_count=actual)` on
|
||||
000474 gives `fabric = 193.83 W/K`. The Elmhurst `LINE_33 = 209.11 W/K`.
|
||||
The gap is +15.28 W/K — and it cannot be explained by window area alone,
|
||||
because `u_wall (1.5) > u_window_eff (1.33)`, so adding windows would
|
||||
*decrease* fabric heat loss, not increase it.
|
||||
|
||||
The gap is therefore in one or more of the other elements. Most likely
|
||||
culprits, in priority order:
|
||||
|
||||
1. **Floor construction missing from fixture.**
|
||||
`SapFloorDimension.floor_construction` is `None` in all Elmhurst
|
||||
fixture files (field not set). Our `u_floor` fallback may not match
|
||||
the Elmhurst value. The 000490 fixture comment records the expected
|
||||
U-values explicitly: *"suspended timber ground floor on main (U=0.71),
|
||||
exposed timber floor on Extension 1 (U=1.20)"*. Set the correct
|
||||
`floor_construction` and `floor_insulation` codes on each
|
||||
`SapFloorDimension` and see if the gap closes.
|
||||
|
||||
2. **Roof construction / insulation thickness missing from fixture.**
|
||||
Similarly, `roof_insulation_thickness` may not be set on the building
|
||||
parts. The Elmhurst cert will have a specific roof type and insulation
|
||||
depth that drives a specific `u_roof`.
|
||||
|
||||
3. **Wall insulation re-check.** All fixtures use `wall_insulation_type=4`
|
||||
(`_WALL_INSULATION_NONE`), giving `u_wall = 1.5` for cavity age B.
|
||||
Confirm this matches the actual Elmhurst worksheet row.
|
||||
|
||||
### How to proceed
|
||||
|
||||
1. Read the EPC API field encoding for `floor_construction` and
|
||||
`floor_insulation` in `datatypes/epc/domain/epc_property_data.py`
|
||||
and `packages/domain/src/domain/ml/rdsap_uvalues.py` (the `u_floor`
|
||||
function + its construction constants).
|
||||
2. Look up the actual floor type for 000474 and 000490 from the PDF
|
||||
(ask the user — PDFs were supplied manually; not stored in repo).
|
||||
3. Set `floor_construction` + `floor_insulation` + `floor_insulation_thickness`
|
||||
on the `SapFloorDimension` objects in the fixture files.
|
||||
4. Re-run the debug calc (`r0.fabric` with `window_area=0`) and check
|
||||
whether the gap collapses.
|
||||
5. Once floor/roof are resolved, back-calculate window area:
|
||||
`A_w = (LINE_33 - r0.fabric) / (window_u_eff - u_wall)`.
|
||||
If the gap is now ≤ the window contribution, this formula should give
|
||||
a physically plausible positive area (5–15 m² for a 2-storey terrace).
|
||||
6. Add `WINDOW_TOTAL_AREA_M2: float` and `WINDOW_AVG_U_VALUE: float = 1.4`
|
||||
constants to each non-RR fixture file.
|
||||
7. Write a new parametrised test asserting exact LINE_33 and LINE_37 for
|
||||
000474 and 000490. Commit as one slice.
|
||||
|
||||
---
|
||||
|
||||
## Task B — Table 11 Secondary Heating (highest-MAE-impact gap)
|
||||
|
||||
Per `SPEC_COVERAGE.md`, this is the **next priority after §3**.
|
||||
|
||||
Most boiler-main certs allocate ~10 % of space heating to a secondary
|
||||
system (electric room heater or similar). We currently model 0 %. This
|
||||
causes a systematic bias on the large majority of boiler certs.
|
||||
|
||||
**SAP 10.2 Table 11** gives the secondary fraction keyed on main-heating
|
||||
type. **RdSAP 10 Appendix A** identifies the heating type from cert codes.
|
||||
|
||||
Starting point: `packages/domain/src/domain/sap/calculator.py` (entry
|
||||
point) and `packages/domain/src/domain/sap/rdsap/cert_to_inputs.py`
|
||||
(cert→inputs adapter). The `SapInputs` struct carries `main_heating_*`
|
||||
fields — see how space heating demand is calculated and where a secondary
|
||||
fraction would hook in.
|
||||
|
||||
---
|
||||
|
||||
## Key files to read
|
||||
|
||||
| File | Why |
|
||||
|---|---|
|
||||
| `packages/domain/src/domain/sap/worksheet/heat_transmission.py` | §3 implementation — `heat_transmission_from_cert` |
|
||||
| `packages/domain/src/domain/sap/worksheet/tests/test_heat_transmission.py` | all §3 tests including the partial Elmhurst conformance test |
|
||||
| `packages/domain/src/domain/sap/worksheet/tests/_elmhurst_worksheet_000474.py` | non-RR fixture to close |
|
||||
| `packages/domain/src/domain/sap/worksheet/tests/_elmhurst_worksheet_000490.py` | non-RR fixture to close |
|
||||
| `packages/domain/src/domain/ml/rdsap_uvalues.py` | all U-value lookups — `u_floor`, `u_wall`, `u_roof` |
|
||||
| `docs/sap-spec/SPEC_COVERAGE.md` | overall progress tracker |
|
||||
| `docs/adr/0009-deterministic-sap-calculator.md` | scope + architectural decisions |
|
||||
|
||||
Spec PDFs are at `docs/sap-spec/` — SAP 10.2 (March 2025), SAP 10.3
|
||||
(Jan 2026), RdSAP 10 (June 2025).
|
||||
|
||||
The canonical reference Excel worksheet is at the repo root:
|
||||
`2026-05-19-17-18 RdSap10Worksheet.xlsx`. A loader for it is at
|
||||
`packages/domain/src/domain/sap/worksheet/tests/_xlsx_loader.py`.
|
||||
|
||||
---
|
||||
|
||||
## Test suite
|
||||
|
||||
```
|
||||
python -m pytest packages/domain/src/domain/sap/worksheet/tests/ -q
|
||||
# Should show 122 passed
|
||||
```
|
||||
|
|
@ -2,16 +2,18 @@
|
|||
|
||||
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-18 after S-B19.
|
||||
Updated 2026-05-20 after §3 close (slices `344a9c9d`…`cf244762`).
|
||||
|
||||
The canonical SAP10.2 algorithm lives in [`2026-05-19-17-18 RdSap10Worksheet.xlsx`](../../2026-05-19-17-18%20RdSap10Worksheet.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 §§1–13 (the SAP worksheet)
|
||||
|
||||
| § | Topic | Module | Status | Notes / gaps |
|
||||
|---|---|---|---|---|
|
||||
| 1 | Dimensions | `worksheet/dimensions.py` | **Full** | Porches, conservatories, RIR deferred per ADR-0009 |
|
||||
| 2 | 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 | Heat transmission | `worksheet/heat_transmission.py` | Partial | DwellingExposure for flats ✓, but uses global y-factor (Table R2 per-junction deferred); no roof-light separate U-value |
|
||||
| 4 | Hot water + Appendix J | uses `domain.ml.demand.predicted_hot_water_kwh` | Partial | Instantaneous-system flag ✓; no shower/bath count adjustments, no FGHRS/WWHRS, no PV-diverter |
|
||||
| § | xlsx rows | Topic | Module | Status | Notes / gaps |
|
||||
|---|---|---|---|---|---|
|
||||
| 1 | 1–120 (approx) | Dimensions | `worksheet/dimensions.py` | **Full** | Porches, conservatories, RIR deferred per ADR-0009 |
|
||||
| 2 | 121–206 (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 | 121–207 | 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 | 207–304 | Hot water + Appendix J | uses `domain.ml.demand.predicted_hot_water_kwh` | Partial (legacy) | **Worksheet-driven rewrite in progress** — see slice plan below. Instantaneous-system flag ✓; no shower/bath count adjustments, no FGHRS/WWHRS, no PV-diverter |
|
||||
| 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 |
|
||||
|
|
@ -58,3 +60,26 @@ Updated 2026-05-18 after S-B19.
|
|||
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 — current focus (xlsx rows 207–304)
|
||||
|
||||
Line refs to implement in order (one TDD slice each):
|
||||
|
||||
| Line ref | Description | xlsx row |
|
||||
|---|---|---|
|
||||
| (42) | Assumed occupancy N from Appendix J formula | 209 |
|
||||
| (42a)m | Hot water — mixer showers, monthly | 215 |
|
||||
| (42b)m | Hot water — baths, monthly | 218 |
|
||||
| (42c)m | Hot water — other uses, monthly | 221 |
|
||||
| (43) | Annual average hot water (litres/day) | 223 |
|
||||
| (44)m | Daily hot water usage, monthly | 226 |
|
||||
| (45)m | Energy content of hot water, monthly | 229 |
|
||||
| (46)m | Distribution loss = 0.15 × (45)m | 236 |
|
||||
| (47)–(56) | Storage volume + water storage / HIU loss path | 238–263 |
|
||||
| (57) | Dedicated solar storage adjustment | (after 263) |
|
||||
| (58)–(61) | Primary loss + combi loss | — |
|
||||
| (62)m | Total monthly water heat requirement | — |
|
||||
| (63a)–(63d) | WWHRS / PV-diverter / Solar / FGHRS reductions | — |
|
||||
| (64)m | Output from water heater | — |
|
||||
| (64a)m | Electric-shower energy | — |
|
||||
| (65)m | Heat gains from water heating | — |
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue