From 2c3eb17b9622fadc8e5675a6724bcd0c4bc6bd85 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Thu, 28 May 2026 15:18:16 +0000 Subject: [PATCH] =?UTF-8?q?Slice=20S0380.33:=20round=20synthesized=20PV=20?= =?UTF-8?q?kWp=20to=202=20d.p.=20per=20RdSAP10=20=C2=A715=20=E2=80=94=20cl?= =?UTF-8?q?oses=20cert=206835=20+0.015=20SAP=20residual?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RdSAP10 §15 p.66 (Rounding of data): "kWp for photovoltaics, etc.: 2 d.p." Cert 6835 lodges Photovoltaic Supply as "Proportion of roof area = 40" (no explicit kWp). Per RdSAP10 §11.1 b) p.60 the cascade synthesizes kWp = 0.12 × PV area where PV area is roof_area / cos(35°). For cert 6835: PV area = 36.9 × 0.40 / cos(35°) = 18.0186 m^2 kWp unrounded = 0.12 x 18.0186 = 2.16224 kWp at 2 d.p. = 2.16 (matches worksheet "Cells Peak = 2.16") SAP 10.2 §M1 EPV = 0.8 x kWp x S x ZPV. With the 0.0022 kWp delta the cascade was overstating PV generation by 1.5448 kWh/yr, adding -0.20 GBP to (252) total PV credit, dropping (255) total energy cost by 0.20, lowering ECF and raising SAP by +0.015. Cohort-2 distribution after S0380.31..S0380.33: 35 exact + 3 <=0.07 (was 34 + 4 at S0380.32 HEAD). Cert 6835: +0.014534 -> -4.3e-5. Co-Authored-By: Claude Opus 4.7 --- .../sap10_calculator/rdsap/cert_to_inputs.py | 8 ++++++- .../rdsap/tests/test_cert_to_inputs.py | 23 +++++++++++-------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/domain/sap10_calculator/rdsap/cert_to_inputs.py b/domain/sap10_calculator/rdsap/cert_to_inputs.py index e3fafb7f..df04c3b6 100644 --- a/domain/sap10_calculator/rdsap/cert_to_inputs.py +++ b/domain/sap10_calculator/rdsap/cert_to_inputs.py @@ -883,7 +883,13 @@ def _synthesize_pv_arrays_from_percent_roof_area( if is_pitched: bp_pv_area /= cos_factor pv_area_m2 += bp_pv_area - kwp = _PV_PEAK_POWER_KWP_PER_M2 * pv_area_m2 + # RdSAP10 §15 p.66: "kWp for photovoltaics, etc.: 2 d.p." — round + # before the EPV cascade so it matches the worksheet's "Cells Peak" + # column (cert 6835: cascade 0.12 × 36.9 × 0.40 / cos(35°) = 2.16224 + # → 2.16, matching worksheet "Cells Peak = 2.16"). The 0.0022 kWp + # delta otherwise feeds straight into (233) PV generation as a + # +1.5 kWh/yr over-credit and a +0.015 SAP residual. + kwp = _round_half_up(_PV_PEAK_POWER_KWP_PER_M2 * pv_area_m2, 2) if kwp <= 0: return None return [ diff --git a/domain/sap10_calculator/rdsap/tests/test_cert_to_inputs.py b/domain/sap10_calculator/rdsap/tests/test_cert_to_inputs.py index 3fbe3a95..6307bb9f 100644 --- a/domain/sap10_calculator/rdsap/tests/test_cert_to_inputs.py +++ b/domain/sap10_calculator/rdsap/tests/test_cert_to_inputs.py @@ -481,10 +481,14 @@ def test_pv_generation_synthesizes_array_from_percent_roof_area_per_rdsap_11_1() Cohort-2 cert 6835 (Semi-Detached bungalow, single storey, TFA 36.9 m², pitched roof) lodges only "Proportion of roof area = 40" — the - cascade must synthesize a 2.16 kWp array (= 36.9 × 0.40 / cos(35°) - × 0.12) and route the generation through the Appendix M cost - cascade. Verified against the worksheet's "Cells Peak = 2.16, - Orientation = South, Elevation = 30°, Overshading = Modest" line. + cascade must synthesize the array and route the generation through + the Appendix M cost cascade. Worksheet (cert 6835 dr87-0001-000624) + lodges "Cells Peak = 2.16, Orientation = South, Elevation = 30°, + Overshading = Modest" and worksheet (233) PV generation = 1492.3348 + kWh/yr. Per RdSAP10 §15 p.66 "kWp for photovoltaics, etc.: 2 d.p." + the cascade rounds kWp before the SAP 10.2 §M1 EPV calculation — + without the round, cascade's 2.16224 kWp drives a +1.5 kWh/yr + over-credit and a +0.015 SAP residual vs the worksheet. """ from datatypes.epc.domain.epc_property_data import ( PhotovoltaicSupply, PhotovoltaicSupplyNoneOrNoDetails, @@ -513,12 +517,11 @@ def test_pv_generation_synthesizes_array_from_percent_roof_area_per_rdsap_11_1() # Act gen_kwh = cert_to_inputs(epc).pv_generation_kwh_per_yr - # Assert — kWp = 0.12 × 36.9 × 0.40 / cos(35°) = 2.1622. With S = - # ~862 kWh/m²/yr at South 30° UK-avg (Appendix U3.3) and ZPV = 0.8 - # (Modest), annual EPV = 0.8 × 2.1622 × 862 × 0.8 ≈ 1490 kWh/yr — - # within 1% of the worksheet's 1492.33 kWh/yr. - assert 1450.0 < gen_kwh < 1530.0, ( - f"expected ~1490 kWh/yr (per RdSAP §11.1 b synthesis), got {gen_kwh:.2f}" + # Assert — EPV = 0.8 × 2.16 × S(South,30°,UK-avg) × 0.8(Modest); + # the cascade rounds kWp to 2 d.p. so the result lands on the + # worksheet's 1492.3348 kWh/yr at 1e-4. + assert abs(gen_kwh - 1492.3348) <= 1e-4, ( + f"expected 1492.3348 kWh/yr (worksheet cert 6835), got {gen_kwh:.4f}" )