Slice 7 of ADR-0025 costing: the modelling-layer interpretation half of the split. ashp_cost_inputs derives existing system (mains_gas/fuel/SAP-code), size band (floor area <= 75 m2), design heat loss (floor_area x 0.05 -- the chosen proxy over HLC, ADR updated), radiator count (habitable + 3, floor-area fallback) and reusable-wet-system flag. Catalogue math (Products) stays EPC-free. ADR-0025 updated to record the floor-area pump-sizing choice. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6.9 KiB
ASHP Bundle Costing — Composite, Dwelling-Sized
The air-source-heat-pump bundle (ADR-0024) is the first Measure Option whose cost is not a single catalogue scalar. A real ASHP retrofit ranges ~£12k–£21k depending on the existing system, pump size, and — dominantly — whether a wet distribution system already exists. The Optimiser picks least-cost-to-band, so a flat number systematically mis-ranks ASHP. We therefore compose the cost per dwelling from the real Southern Housing Group rate sheet (the HEAT PUMPS tab, line items ECOHT01–68), interpreting the dwelling to select and sum the applicable priced lines.
Decision
The ASHP bundle cost is a composite, computed per dwelling at generation time:
decommission(existing system, property size) # by system type × beds band
+ heat_pump(kW size band) # sized from heat loss
+ cylinder (fixed £2,382.60) # one cylinder per install
+ distribution: # the dominant lever
no reusable wet system → full band(n_radiators)
reusable wet system → £168 flush + 0.5 × band(n_radiators)
→ Cost(total = sum, contingency_rate = 0.25)
Products owns the catalogue math; the modelling layer owns the dwelling interpretation. A new rich domain collection over Product — Products — exposes per-measure cost methods (ashp_bundle_cost) that filter the relevant priced rows and sum them from a small typed AshpCostInputs. It stays free of EpcPropertyData and the Sap10Calculator. The dwelling→inputs interpretation (sizing, proxies, reuse detection) lives in modelling, which may depend on the calculator. ProductRepository remains the IO port; Products is the behaviour it yields. Product stays cost-only (ADR-0024 unchanged); the ECOHT rate lines land in the committed costs file as structured rows (category + qualifier), faithful to the rate sheet and the future materials table.
Dwelling interpretation rules (each a documented proxy, not a survey):
- Pump size =
floor_area × 0.05 kW/m²(design heat loss in kW), rounded up to the next install band {5, 8, 11, 15, 16} kW. The more accurateavg(HLC) × 24.2 K / 1000is deferred: the generators run before thePackageScorer, so noSapResultexists at cost time, and threading one through every generator's call site is real wiring complexity for a minor lever (the whole 5→16 kW band spans only ~£1.7k). The floor-area proxy lands the same band for most dwellings and keeps the cost interpreter free of the calculator. HLC sizing is the natural upgrade when the SAP product itself becomes dwelling-aware (which already runs the calculator). The cost product is sized to the dwelling even though the SAP product is fixed at the Vaillant aroTHERM plus 5 kW — a deliberate, documented inconsistency (see Consequences). - Existing system from
main_fuel_type+sap_main_heating_code: gas/oil/LPG/electric-storage map to their decommission lines; no system → £0; electric room/panel heaters → electric-storage line; anything else → gas line (£720) as a representative default — never a strict-raise, because raising would wrongly block ASHP eligibility for a real dwelling. - Property-size band (1–2 vs 3–4 bed, which only changes the electric-storage decommission line, a £270 swing): floor area ≤ 75 m² ⇒ 1–2 bed. Floor area is always present, unlike
habitable_rooms_count. - Reusable wet system = an existing gas/oil/LPG boiler with radiator emitters. With one, the ASHP reuses the pipework but a meaningful subset of radiators is upsized for the lower flow temperature (MCS-007, ≤ 55 °C) — so reuse is not free:
£168 flush + 0.5 × full distribution. Without one (electric/none/warm-air), a full new wet distribution is priced. - Radiator count =
clamp(habitable_rooms_count + 3, 4, 12)(RdSAP excludes kitchen/hall/bathroom from habitable rooms); fallbackfloor_area ÷ 13 m². - Cylinder = a single fixed line (£2,382.60); the cylinder-size spread on the sheet is £188 (noise).
- Extras (ECOHT53–68: socket relocation, trenching, heat meter, Hive, …) are excluded from the base composite — unpredictable from EPC data and exactly what Contingency absorbs. Controls are already inside the pump line.
Considered options
- Single fixed representative cost (the loft/glazing pattern). Rejected: those costs are genuinely ~uniform; ASHP's varies ~£12k–£21k per dwelling and the variance changes Optimiser selection. A flat number would systematically over- or under-recommend ASHP.
- Extend
Productwith a cost formula / line items. Rejected: theProduct-bloat ADR-0024 already declined; a heat pump's cost composition is not a catalogue scalar. - Inline the composition in
recommend_heating. Rejected: pulls sizing/proxy/reuse logic into the generator, which is meant to be thin detection + bundle assembly; hard to test in isolation. Products.ashp_bundle_cost(epc)doing sizing too. Rejected: inverts the layering (the priced catalogue depending on the SAP calculator and EPC). The catalogue math is kept pure and table-driven; dwelling physics stays in modelling.- Pricing reuse as a £168 power-flush only. Rejected after research: MCS reality is that existing radiators emit ~42% at 45 °C flow and a subset gets upsized, so flush-only is unrealistically optimistic.
Consequences
- A new
Productscollection +AshpCostInputs+ anashp_bundle_costmethod; the ASHP rate lines added to the committed costs file as structured rows.Product,recommend_heating's detection, and the other five generators are unchanged (they keep.get+ unit×area;Productsgrows methods per measure later — no speculative six-way refactor). - SAP/cost product-size mismatch: the cost is sized to the dwelling while the SAP simulation uses the fixed 5 kW Vaillant. Bounded and documented — the pump-band cost spread is only ~£1.7k across 5→16 kW, and the size estimate built here is exactly what a future dwelling-aware SAP product (picking the Vaillant model in the right band for both SAP and cost) would reuse. That reconciliation is deferred, not designed away.
- The 0.5 reuse-distribution fraction is the headline uncertainty — a single named constant (
_REUSE_DISTRIBUTION_FRACTION) to recalibrate when real reuse-job costs or survey data arrive. - Realistic costs (~£15k–£21k vs the £12k placeholder) make ASHP win less often; this is why the held product-swap and its 5 broken integration tests land together with this costing, against stable Optimiser behaviour rather than churning twice.
- Brand is cost-neutral (Daikin/Mitsubishi/Vaillant/Samsung/Grant priced identically), so the Vaillant SAP choice carries no cost penalty.
- All proxies (pump size, beds, radiator count, reuse fraction) are whole-dwelling estimates standing in for a survey; each is documented at its call site as such.