mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
Slice 30: §10a fuel costs cascade pin (192/192) + electric-shower plumb
Adds `fuel_cost_section_from_cert(epc)` (delegates to `cert_to_inputs` which already wires `_fuel_cost` with full upstream context). Pins (240a)..(255) — 32 line refs × 6 fixtures = 192 cascade pins, all PASS. Three calculator changes needed for closure: 1. Electric shower (247a) — for 000487 the cert lodges 1 electric shower and the PDF reports (247a) = 79.3036 GBP (= (64a)m × std electricity price). The §4 cascade already computes electric-shower kWh via App J step 8 (slice 25d); now exposed on `WaterHeatingResult` as `electric_shower_kwh_per_yr` and plumbed into `_fuel_cost`. The instant-shower input was previously hardcoded to 0. 2. (241a/241b) main 2 + (242a/242b) secondary fractions — when a row's kWh is zero the PDF reports BOTH high/low fractions as 0 (not 1/0). `_split` in fuel_cost now zeros both fractions when kwh_per_yr <= 0. Cost columns already collapse via multiplication, so this is presentation-only. 3. (242a/242b) secondary fractions for 000474 — same pattern: when no secondary system is lodged, both fractions = 0. Adds §10a LINE_ constants to all 6 fixtures. Extracted from `sap worksheets/U985-0001-NNNNNN.txt` PDF blocks. Cascade scoreboard: 468/468 → 660/660 (§7..§10a closed). e2e SapResult: 6 remaining failures (all `co2_kg_per_yr`, await §12). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
049694e1e6
commit
74bfac049a
10 changed files with 339 additions and 7 deletions
|
|
@ -1042,6 +1042,22 @@ def fabric_energy_efficiency_from_cert(epc: EpcPropertyData) -> Optional[float]:
|
|||
)
|
||||
|
||||
|
||||
def fuel_cost_section_from_cert(
|
||||
epc: EpcPropertyData,
|
||||
) -> Optional[FuelCostResult]:
|
||||
"""SAP 10.2 §10a cert→inputs cascade for `fuel_cost`. Off-peak certs
|
||||
return the zero sentinel (Table 12a high-rate-fraction split deferred).
|
||||
For STANDARD-tariff certs returns the full (240)..(255) FuelCostResult.
|
||||
|
||||
Composes via `cert_to_inputs(epc)` — `_fuel_cost` is invoked there with
|
||||
all upstream §4/§5/§6/§7/§8/§9a values plumbed in. Returns None when
|
||||
TFA missing.
|
||||
"""
|
||||
if epc.total_floor_area_m2 is None:
|
||||
return None
|
||||
return cert_to_inputs(epc).fuel_cost
|
||||
|
||||
|
||||
def energy_requirements_section_from_cert(
|
||||
epc: EpcPropertyData,
|
||||
) -> Optional[EnergyRequirementsResult]:
|
||||
|
|
@ -1388,6 +1404,7 @@ def _fuel_cost(
|
|||
pumps_fans_kwh: float,
|
||||
lighting_kwh: float,
|
||||
cooling_kwh: float,
|
||||
electric_shower_kwh: float = 0.0,
|
||||
) -> FuelCostResult:
|
||||
"""SAP10.2 §10a fuel-cost precompute — produce a `FuelCostResult` from
|
||||
the cert + the §9a `energy_requirements_result`. RdSAP10 target per
|
||||
|
|
@ -1443,19 +1460,25 @@ def _fuel_cost(
|
|||
tariff=tariff,
|
||||
)
|
||||
|
||||
# Worksheet display convention: when a row's kWh is zero (no main 2, no
|
||||
# secondary system, etc.) the PDF reports the (high-rate fraction)
|
||||
# column as 0 rather than 1. Cost columns already collapse to 0 via
|
||||
# multiplication, so this is presentation-only.
|
||||
main_2_kwh = energy_requirements_result.main_2_fuel_kwh_per_yr
|
||||
secondary_kwh = energy_requirements_result.secondary_fuel_kwh_per_yr
|
||||
return fuel_cost(
|
||||
main_1_kwh_per_yr=energy_requirements_result.main_1_fuel_kwh_per_yr,
|
||||
main_1_high_rate_gbp_per_kwh=main_1_high_rate_gbp_per_kwh,
|
||||
main_1_low_rate_gbp_per_kwh=0.0,
|
||||
main_1_high_rate_fraction=1.0,
|
||||
main_2_kwh_per_yr=energy_requirements_result.main_2_fuel_kwh_per_yr,
|
||||
main_2_kwh_per_yr=main_2_kwh,
|
||||
main_2_high_rate_gbp_per_kwh=main_1_high_rate_gbp_per_kwh,
|
||||
main_2_low_rate_gbp_per_kwh=0.0,
|
||||
main_2_high_rate_fraction=1.0,
|
||||
secondary_kwh_per_yr=energy_requirements_result.secondary_fuel_kwh_per_yr,
|
||||
main_2_high_rate_fraction=1.0 if main_2_kwh > 0.0 else 0.0,
|
||||
secondary_kwh_per_yr=secondary_kwh,
|
||||
secondary_high_rate_gbp_per_kwh=secondary_high_rate_gbp_per_kwh,
|
||||
secondary_low_rate_gbp_per_kwh=0.0,
|
||||
secondary_high_rate_fraction=1.0,
|
||||
secondary_high_rate_fraction=1.0 if secondary_kwh > 0.0 else 0.0,
|
||||
hot_water_kwh_per_yr=hot_water_kwh,
|
||||
hot_water_high_rate_gbp_per_kwh=water_high_rate_gbp_per_kwh,
|
||||
hot_water_low_rate_gbp_per_kwh=0.0,
|
||||
|
|
@ -1464,8 +1487,8 @@ def _fuel_cost(
|
|||
lighting_kwh_per_yr=lighting_kwh,
|
||||
cooling_kwh_per_yr=cooling_kwh,
|
||||
other_uses_gbp_per_kwh=other_uses_gbp_per_kwh,
|
||||
instant_shower_kwh_per_yr=0.0,
|
||||
instant_shower_gbp_per_kwh=0.0,
|
||||
instant_shower_kwh_per_yr=electric_shower_kwh,
|
||||
instant_shower_gbp_per_kwh=other_uses_gbp_per_kwh,
|
||||
pv_generation_kwh_per_yr=_pv_generation_kwh_per_yr(epc),
|
||||
pv_export_credit_gbp_per_kwh=pv_export_credit_gbp_per_kwh,
|
||||
additional_standing_charges_gbp=standing,
|
||||
|
|
@ -1781,6 +1804,9 @@ def cert_to_inputs(
|
|||
fuel_cost=_fuel_cost(
|
||||
epc=epc,
|
||||
main=main,
|
||||
electric_shower_kwh=(
|
||||
wh_result.electric_shower_kwh_per_yr if wh_result is not None else 0.0
|
||||
),
|
||||
energy_requirements_result=energy_requirements_result,
|
||||
hot_water_kwh=hw_kwh,
|
||||
pumps_fans_kwh=pumps_fans_kwh,
|
||||
|
|
|
|||
|
|
@ -37,7 +37,20 @@ def _split(
|
|||
high_rate_fraction: float,
|
||||
) -> _OffPeakSplit:
|
||||
"""Off-peak split arithmetic shared by main 1 / main 2 / secondary /
|
||||
water-heating rows. (240c)=Q×frac×P_high, (240d)=Q×(1-frac)×P_low."""
|
||||
water-heating rows. (240c)=Q×frac×P_high, (240d)=Q×(1-frac)×P_low.
|
||||
|
||||
Worksheet display convention: when the row's kWh is zero (e.g. no main
|
||||
2 system) the PDF reports BOTH fractions as 0 rather than 1/0. Cost
|
||||
columns already collapse to 0 via the kWh×fraction multiplications,
|
||||
so this is presentation-only — the math is unaffected."""
|
||||
if kwh_per_yr <= 0.0:
|
||||
return _OffPeakSplit(
|
||||
high_rate_fraction=0.0,
|
||||
low_rate_fraction=0.0,
|
||||
high_rate_cost=0.0,
|
||||
low_rate_cost=0.0,
|
||||
total=0.0,
|
||||
)
|
||||
low_rate_fraction = 1.0 - high_rate_fraction
|
||||
high_rate_cost = kwh_per_yr * high_rate_fraction * high_rate_gbp_per_kwh
|
||||
low_rate_cost = kwh_per_yr * low_rate_fraction * low_rate_gbp_per_kwh
|
||||
|
|
|
|||
|
|
@ -450,3 +450,41 @@ LINE_213_ANNUAL_KWH: float = 0.0000
|
|||
LINE_215_M_SECONDARY_FUEL_KWH: tuple[float, ...] = (0.0,) * 12
|
||||
LINE_215_ANNUAL_KWH: float = 0.0000
|
||||
LINE_221_COOLING_FUEL_KWH: float = 0.0000
|
||||
|
||||
# ============================================================================
|
||||
# §10a Fuel costs — using Table 12 (RdSAP10 Table 32) prices
|
||||
# ============================================================================
|
||||
# STANDARD-tariff fixture — off-peak splits collapse (high_rate_fraction=1,
|
||||
# low_rate_fraction=0, high_rate_cost = total).
|
||||
LINE_240A_MAIN_1_HIGH_RATE_FRACTION: float = 1.0000
|
||||
LINE_240B_MAIN_1_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_240C_MAIN_1_HIGH_RATE_COST: float = 416.3783
|
||||
LINE_240D_MAIN_1_LOW_RATE_COST: float = 0.0000
|
||||
LINE_240E_MAIN_1_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_240_MAIN_1_TOTAL_COST: float = 416.3783
|
||||
LINE_241A_MAIN_2_HIGH_RATE_FRACTION: float = 0.0000
|
||||
LINE_241B_MAIN_2_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_241C_MAIN_2_HIGH_RATE_COST: float = 0.0000
|
||||
LINE_241D_MAIN_2_LOW_RATE_COST: float = 0.0000
|
||||
LINE_241E_MAIN_2_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_241_MAIN_2_TOTAL_COST: float = 0.0000
|
||||
LINE_242A_SECONDARY_HIGH_RATE_FRACTION: float = 0.0000
|
||||
LINE_242B_SECONDARY_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_242C_SECONDARY_HIGH_RATE_COST: float = 0.0000
|
||||
LINE_242D_SECONDARY_LOW_RATE_COST: float = 0.0000
|
||||
LINE_242E_SECONDARY_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_242_SECONDARY_TOTAL_COST: float = 0.0000
|
||||
LINE_243_WATER_HIGH_RATE_FRACTION: float = 1.0000
|
||||
LINE_244_WATER_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_245_WATER_HIGH_RATE_COST: float = 79.7539
|
||||
LINE_246_WATER_LOW_RATE_COST: float = 0.0000
|
||||
LINE_247_WATER_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_247A_INSTANT_SHOWER_COST: float = 0.0000
|
||||
LINE_248_SPACE_COOLING_COST: float = 0.0000
|
||||
LINE_249_PUMPS_FANS_COST: float = 21.1040
|
||||
LINE_250_LIGHTING_COST: float = 18.4588
|
||||
LINE_251_STANDING_CHARGES: float = 120.0000
|
||||
LINE_252_PV_CREDIT: float = 0.0000
|
||||
LINE_253_APPENDIX_Q_SAVED: float = 0.0000
|
||||
LINE_254_APPENDIX_Q_USED: float = 0.0000
|
||||
LINE_255_TOTAL_COST: float = 655.6949
|
||||
|
|
|
|||
|
|
@ -419,3 +419,39 @@ LINE_215_M_SECONDARY_FUEL_KWH: tuple[float, ...] = (
|
|||
)
|
||||
LINE_215_ANNUAL_KWH: float = 1011.1202
|
||||
LINE_221_COOLING_FUEL_KWH: float = 0.0000
|
||||
|
||||
# ============================================================================
|
||||
# §10a Fuel costs — using Table 12 (RdSAP10 Table 32) prices
|
||||
# ============================================================================
|
||||
LINE_240A_MAIN_1_HIGH_RATE_FRACTION: float = 1.0000
|
||||
LINE_240B_MAIN_1_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_240C_MAIN_1_HIGH_RATE_COST: float = 357.4298
|
||||
LINE_240D_MAIN_1_LOW_RATE_COST: float = 0.0000
|
||||
LINE_240E_MAIN_1_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_240_MAIN_1_TOTAL_COST: float = 357.4298
|
||||
LINE_241A_MAIN_2_HIGH_RATE_FRACTION: float = 0.0000
|
||||
LINE_241B_MAIN_2_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_241C_MAIN_2_HIGH_RATE_COST: float = 0.0000
|
||||
LINE_241D_MAIN_2_LOW_RATE_COST: float = 0.0000
|
||||
LINE_241E_MAIN_2_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_241_MAIN_2_TOTAL_COST: float = 0.0000
|
||||
LINE_242A_SECONDARY_HIGH_RATE_FRACTION: float = 1.0000
|
||||
LINE_242B_SECONDARY_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_242C_SECONDARY_HIGH_RATE_COST: float = 133.3668
|
||||
LINE_242D_SECONDARY_LOW_RATE_COST: float = 0.0000
|
||||
LINE_242E_SECONDARY_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_242_SECONDARY_TOTAL_COST: float = 133.3668
|
||||
LINE_243_WATER_HIGH_RATE_FRACTION: float = 1.0000
|
||||
LINE_244_WATER_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_245_WATER_HIGH_RATE_COST: float = 73.6381
|
||||
LINE_246_WATER_LOW_RATE_COST: float = 0.0000
|
||||
LINE_247_WATER_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_247A_INSTANT_SHOWER_COST: float = 0.0000
|
||||
LINE_248_SPACE_COOLING_COST: float = 0.0000
|
||||
LINE_249_PUMPS_FANS_COST: float = 21.1040
|
||||
LINE_250_LIGHTING_COST: float = 26.6010
|
||||
LINE_251_STANDING_CHARGES: float = 120.0000
|
||||
LINE_252_PV_CREDIT: float = 0.0000
|
||||
LINE_253_APPENDIX_Q_SAVED: float = 0.0000
|
||||
LINE_254_APPENDIX_Q_USED: float = 0.0000
|
||||
LINE_255_TOTAL_COST: float = 732.1396
|
||||
|
|
|
|||
|
|
@ -461,3 +461,39 @@ LINE_215_M_SECONDARY_FUEL_KWH: tuple[float, ...] = (
|
|||
)
|
||||
LINE_215_ANNUAL_KWH: float = 1239.8578
|
||||
LINE_221_COOLING_FUEL_KWH: float = 0.0000
|
||||
|
||||
# ============================================================================
|
||||
# §10a Fuel costs — using Table 12 (RdSAP10 Table 32) prices
|
||||
# ============================================================================
|
||||
LINE_240A_MAIN_1_HIGH_RATE_FRACTION: float = 1.0000
|
||||
LINE_240B_MAIN_1_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_240C_MAIN_1_HIGH_RATE_COST: float = 437.7942
|
||||
LINE_240D_MAIN_1_LOW_RATE_COST: float = 0.0000
|
||||
LINE_240E_MAIN_1_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_240_MAIN_1_TOTAL_COST: float = 437.7942
|
||||
LINE_241A_MAIN_2_HIGH_RATE_FRACTION: float = 0.0000
|
||||
LINE_241B_MAIN_2_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_241C_MAIN_2_HIGH_RATE_COST: float = 0.0000
|
||||
LINE_241D_MAIN_2_LOW_RATE_COST: float = 0.0000
|
||||
LINE_241E_MAIN_2_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_241_MAIN_2_TOTAL_COST: float = 0.0000
|
||||
LINE_242A_SECONDARY_HIGH_RATE_FRACTION: float = 1.0000
|
||||
LINE_242B_SECONDARY_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_242C_SECONDARY_HIGH_RATE_COST: float = 163.5372
|
||||
LINE_242D_SECONDARY_LOW_RATE_COST: float = 0.0000
|
||||
LINE_242E_SECONDARY_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_242_SECONDARY_TOTAL_COST: float = 163.5372
|
||||
LINE_243_WATER_HIGH_RATE_FRACTION: float = 1.0000
|
||||
LINE_244_WATER_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_245_WATER_HIGH_RATE_COST: float = 84.3426
|
||||
LINE_246_WATER_LOW_RATE_COST: float = 0.0000
|
||||
LINE_247_WATER_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_247A_INSTANT_SHOWER_COST: float = 0.0000
|
||||
LINE_248_SPACE_COOLING_COST: float = 0.0000
|
||||
LINE_249_PUMPS_FANS_COST: float = 21.1040
|
||||
LINE_250_LIGHTING_COST: float = 28.0358
|
||||
LINE_251_STANDING_CHARGES: float = 120.0000
|
||||
LINE_252_PV_CREDIT: float = 0.0000
|
||||
LINE_253_APPENDIX_Q_SAVED: float = 0.0000
|
||||
LINE_254_APPENDIX_Q_USED: float = 0.0000
|
||||
LINE_255_TOTAL_COST: float = 854.8139
|
||||
|
|
|
|||
|
|
@ -484,3 +484,40 @@ LINE_215_M_SECONDARY_FUEL_KWH: tuple[float, ...] = (
|
|||
)
|
||||
LINE_215_ANNUAL_KWH: float = 1083.4778
|
||||
LINE_221_COOLING_FUEL_KWH: float = 0.0000
|
||||
|
||||
# ============================================================================
|
||||
# §10a Fuel costs — using Table 12 (RdSAP10 Table 32) prices
|
||||
# ============================================================================
|
||||
# Has electric shower → (247a) instant-shower cost = 79.3036.
|
||||
LINE_240A_MAIN_1_HIGH_RATE_FRACTION: float = 1.0000
|
||||
LINE_240B_MAIN_1_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_240C_MAIN_1_HIGH_RATE_COST: float = 383.4409
|
||||
LINE_240D_MAIN_1_LOW_RATE_COST: float = 0.0000
|
||||
LINE_240E_MAIN_1_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_240_MAIN_1_TOTAL_COST: float = 383.4409
|
||||
LINE_241A_MAIN_2_HIGH_RATE_FRACTION: float = 0.0000
|
||||
LINE_241B_MAIN_2_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_241C_MAIN_2_HIGH_RATE_COST: float = 0.0000
|
||||
LINE_241D_MAIN_2_LOW_RATE_COST: float = 0.0000
|
||||
LINE_241E_MAIN_2_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_241_MAIN_2_TOTAL_COST: float = 0.0000
|
||||
LINE_242A_SECONDARY_HIGH_RATE_FRACTION: float = 1.0000
|
||||
LINE_242B_SECONDARY_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_242C_SECONDARY_HIGH_RATE_COST: float = 142.9107
|
||||
LINE_242D_SECONDARY_LOW_RATE_COST: float = 0.0000
|
||||
LINE_242E_SECONDARY_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_242_SECONDARY_TOTAL_COST: float = 142.9107
|
||||
LINE_243_WATER_HIGH_RATE_FRACTION: float = 1.0000
|
||||
LINE_244_WATER_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_245_WATER_HIGH_RATE_COST: float = 51.8208
|
||||
LINE_246_WATER_LOW_RATE_COST: float = 0.0000
|
||||
LINE_247_WATER_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_247A_INSTANT_SHOWER_COST: float = 79.3036
|
||||
LINE_248_SPACE_COOLING_COST: float = 0.0000
|
||||
LINE_249_PUMPS_FANS_COST: float = 21.1040
|
||||
LINE_250_LIGHTING_COST: float = 30.0318
|
||||
LINE_251_STANDING_CHARGES: float = 120.0000
|
||||
LINE_252_PV_CREDIT: float = 0.0000
|
||||
LINE_253_APPENDIX_Q_SAVED: float = 0.0000
|
||||
LINE_254_APPENDIX_Q_USED: float = 0.0000
|
||||
LINE_255_TOTAL_COST: float = 828.6119
|
||||
|
|
|
|||
|
|
@ -435,3 +435,39 @@ LINE_215_M_SECONDARY_FUEL_KWH: tuple[float, ...] = (
|
|||
)
|
||||
LINE_215_ANNUAL_KWH: float = 1118.3275
|
||||
LINE_221_COOLING_FUEL_KWH: float = 0.0000
|
||||
|
||||
# ============================================================================
|
||||
# §10a Fuel costs — using Table 12 (RdSAP10 Table 32) prices
|
||||
# ============================================================================
|
||||
LINE_240A_MAIN_1_HIGH_RATE_FRACTION: float = 1.0000
|
||||
LINE_240B_MAIN_1_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_240C_MAIN_1_HIGH_RATE_COST: float = 397.1204
|
||||
LINE_240D_MAIN_1_LOW_RATE_COST: float = 0.0000
|
||||
LINE_240E_MAIN_1_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_240_MAIN_1_TOTAL_COST: float = 397.1204
|
||||
LINE_241A_MAIN_2_HIGH_RATE_FRACTION: float = 0.0000
|
||||
LINE_241B_MAIN_2_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_241C_MAIN_2_HIGH_RATE_COST: float = 0.0000
|
||||
LINE_241D_MAIN_2_LOW_RATE_COST: float = 0.0000
|
||||
LINE_241E_MAIN_2_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_241_MAIN_2_TOTAL_COST: float = 0.0000
|
||||
LINE_242A_SECONDARY_HIGH_RATE_FRACTION: float = 1.0000
|
||||
LINE_242B_SECONDARY_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_242C_SECONDARY_HIGH_RATE_COST: float = 147.5074
|
||||
LINE_242D_SECONDARY_LOW_RATE_COST: float = 0.0000
|
||||
LINE_242E_SECONDARY_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_242_SECONDARY_TOTAL_COST: float = 147.5074
|
||||
LINE_243_WATER_HIGH_RATE_FRACTION: float = 1.0000
|
||||
LINE_244_WATER_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_245_WATER_HIGH_RATE_COST: float = 99.1998
|
||||
LINE_246_WATER_LOW_RATE_COST: float = 0.0000
|
||||
LINE_247_WATER_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_247A_INSTANT_SHOWER_COST: float = 0.0000
|
||||
LINE_248_SPACE_COOLING_COST: float = 0.0000
|
||||
LINE_249_PUMPS_FANS_COST: float = 21.1040
|
||||
LINE_250_LIGHTING_COST: float = 22.6105
|
||||
LINE_251_STANDING_CHARGES: float = 120.0000
|
||||
LINE_252_PV_CREDIT: float = 0.0000
|
||||
LINE_253_APPENDIX_Q_SAVED: float = 0.0000
|
||||
LINE_254_APPENDIX_Q_USED: float = 0.0000
|
||||
LINE_255_TOTAL_COST: float = 807.5421
|
||||
|
|
|
|||
|
|
@ -461,3 +461,39 @@ LINE_215_M_SECONDARY_FUEL_KWH: tuple[float, ...] = (
|
|||
)
|
||||
LINE_215_ANNUAL_KWH: float = 1241.0317
|
||||
LINE_221_COOLING_FUEL_KWH: float = 0.0000
|
||||
|
||||
# ============================================================================
|
||||
# §10a Fuel costs — using Table 12 (RdSAP10 Table 32) prices
|
||||
# ============================================================================
|
||||
LINE_240A_MAIN_1_HIGH_RATE_FRACTION: float = 1.0000
|
||||
LINE_240B_MAIN_1_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_240C_MAIN_1_HIGH_RATE_COST: float = 438.7033
|
||||
LINE_240D_MAIN_1_LOW_RATE_COST: float = 0.0000
|
||||
LINE_240E_MAIN_1_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_240_MAIN_1_TOTAL_COST: float = 438.7033
|
||||
LINE_241A_MAIN_2_HIGH_RATE_FRACTION: float = 0.0000
|
||||
LINE_241B_MAIN_2_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_241C_MAIN_2_HIGH_RATE_COST: float = 0.0000
|
||||
LINE_241D_MAIN_2_LOW_RATE_COST: float = 0.0000
|
||||
LINE_241E_MAIN_2_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_241_MAIN_2_TOTAL_COST: float = 0.0000
|
||||
LINE_242A_SECONDARY_HIGH_RATE_FRACTION: float = 1.0000
|
||||
LINE_242B_SECONDARY_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_242C_SECONDARY_HIGH_RATE_COST: float = 163.6921
|
||||
LINE_242D_SECONDARY_LOW_RATE_COST: float = 0.0000
|
||||
LINE_242E_SECONDARY_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_242_SECONDARY_TOTAL_COST: float = 163.6921
|
||||
LINE_243_WATER_HIGH_RATE_FRACTION: float = 1.0000
|
||||
LINE_244_WATER_LOW_RATE_FRACTION: float = 0.0000
|
||||
LINE_245_WATER_HIGH_RATE_COST: float = 86.7630
|
||||
LINE_246_WATER_LOW_RATE_COST: float = 0.0000
|
||||
LINE_247_WATER_OTHER_FUEL_COST: float = 0.0000
|
||||
LINE_247A_INSTANT_SHOWER_COST: float = 0.0000
|
||||
LINE_248_SPACE_COOLING_COST: float = 0.0000
|
||||
LINE_249_PUMPS_FANS_COST: float = 21.1040
|
||||
LINE_250_LIGHTING_COST: float = 30.4538
|
||||
LINE_251_STANDING_CHARGES: float = 120.0000
|
||||
LINE_252_PV_CREDIT: float = 0.0000
|
||||
LINE_253_APPENDIX_Q_SAVED: float = 0.0000
|
||||
LINE_254_APPENDIX_Q_USED: float = 0.0000
|
||||
LINE_255_TOTAL_COST: float = 860.7162
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ from domain.sap.rdsap.cert_to_inputs import (
|
|||
cert_to_inputs,
|
||||
energy_requirements_section_from_cert,
|
||||
fabric_energy_efficiency_from_cert,
|
||||
fuel_cost_section_from_cert,
|
||||
heat_transmission_section_from_cert,
|
||||
internal_gains_section_from_cert,
|
||||
mean_internal_temperature_section_from_cert,
|
||||
|
|
@ -780,3 +781,72 @@ def test_section_9a_scalar_line_refs_match_pdf(
|
|||
|
||||
# Assert
|
||||
_pin(actual, expected, f"§9a {fixture_attr} {fixture_name}")
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# §10a Fuel costs — LINE_240..LINE_255 (using Table 32 prices)
|
||||
# ============================================================================
|
||||
|
||||
_SECTION_10A_PINS: Final[tuple[tuple[str, str], ...]] = (
|
||||
("LINE_240A_MAIN_1_HIGH_RATE_FRACTION", "main_1_high_rate_fraction"),
|
||||
("LINE_240B_MAIN_1_LOW_RATE_FRACTION", "main_1_low_rate_fraction"),
|
||||
("LINE_240C_MAIN_1_HIGH_RATE_COST", "main_1_high_rate_cost_gbp"),
|
||||
("LINE_240D_MAIN_1_LOW_RATE_COST", "main_1_low_rate_cost_gbp"),
|
||||
("LINE_240E_MAIN_1_OTHER_FUEL_COST", "main_1_other_fuel_cost_gbp"),
|
||||
("LINE_240_MAIN_1_TOTAL_COST", "main_1_total_cost_gbp"),
|
||||
("LINE_241A_MAIN_2_HIGH_RATE_FRACTION", "main_2_high_rate_fraction"),
|
||||
("LINE_241B_MAIN_2_LOW_RATE_FRACTION", "main_2_low_rate_fraction"),
|
||||
("LINE_241C_MAIN_2_HIGH_RATE_COST", "main_2_high_rate_cost_gbp"),
|
||||
("LINE_241D_MAIN_2_LOW_RATE_COST", "main_2_low_rate_cost_gbp"),
|
||||
("LINE_241E_MAIN_2_OTHER_FUEL_COST", "main_2_other_fuel_cost_gbp"),
|
||||
("LINE_241_MAIN_2_TOTAL_COST", "main_2_total_cost_gbp"),
|
||||
("LINE_242A_SECONDARY_HIGH_RATE_FRACTION", "secondary_high_rate_fraction"),
|
||||
("LINE_242B_SECONDARY_LOW_RATE_FRACTION", "secondary_low_rate_fraction"),
|
||||
("LINE_242C_SECONDARY_HIGH_RATE_COST", "secondary_high_rate_cost_gbp"),
|
||||
("LINE_242D_SECONDARY_LOW_RATE_COST", "secondary_low_rate_cost_gbp"),
|
||||
("LINE_242E_SECONDARY_OTHER_FUEL_COST", "secondary_other_fuel_cost_gbp"),
|
||||
("LINE_242_SECONDARY_TOTAL_COST", "secondary_total_cost_gbp"),
|
||||
("LINE_243_WATER_HIGH_RATE_FRACTION", "water_high_rate_fraction"),
|
||||
("LINE_244_WATER_LOW_RATE_FRACTION", "water_low_rate_fraction"),
|
||||
("LINE_245_WATER_HIGH_RATE_COST", "water_high_rate_cost_gbp"),
|
||||
("LINE_246_WATER_LOW_RATE_COST", "water_low_rate_cost_gbp"),
|
||||
("LINE_247_WATER_OTHER_FUEL_COST", "water_other_fuel_cost_gbp"),
|
||||
("LINE_247A_INSTANT_SHOWER_COST", "instant_shower_cost_gbp"),
|
||||
("LINE_248_SPACE_COOLING_COST", "space_cooling_cost_gbp"),
|
||||
("LINE_249_PUMPS_FANS_COST", "pumps_fans_cost_gbp"),
|
||||
("LINE_250_LIGHTING_COST", "lighting_cost_gbp"),
|
||||
("LINE_251_STANDING_CHARGES", "additional_standing_charges_gbp"),
|
||||
("LINE_252_PV_CREDIT", "pv_credit_gbp"),
|
||||
("LINE_253_APPENDIX_Q_SAVED", "appendix_q_saved_gbp"),
|
||||
("LINE_254_APPENDIX_Q_USED", "appendix_q_used_gbp"),
|
||||
("LINE_255_TOTAL_COST", "total_cost_gbp"),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"fixture_name,fixture_attr,result_attr",
|
||||
[
|
||||
(fix, line, attr)
|
||||
for fix in _FIXTURES
|
||||
for line, attr in _SECTION_10A_PINS
|
||||
],
|
||||
ids=lambda x: x if isinstance(x, str) else None,
|
||||
)
|
||||
def test_section_10a_line_refs_match_pdf(
|
||||
fixture_name: str, fixture_attr: str, result_attr: str
|
||||
) -> None:
|
||||
"""§10a pins — every (240a)..(255) line ref of `_fuel_cost` matches the
|
||||
U985 PDF to abs=1e-4. STANDARD-tariff scope A (all 6 fixtures); off-
|
||||
peak splits collapse: high_rate_fraction=1, low_rate_fraction=0."""
|
||||
# Arrange
|
||||
mod = _FIXTURES[fixture_name]
|
||||
epc = mod.build_epc() # type: ignore[attr-defined]
|
||||
expected = getattr(mod, fixture_attr)
|
||||
|
||||
# Act
|
||||
fc = fuel_cost_section_from_cert(epc)
|
||||
assert fc is not None, f"{fixture_name}: fuel_cost_from_cert returned None"
|
||||
actual = getattr(fc, result_attr)
|
||||
|
||||
# Assert
|
||||
_pin(actual, expected, f"§10a {fixture_attr} {fixture_name}")
|
||||
|
|
|
|||
|
|
@ -62,7 +62,9 @@ class WaterHeatingResult:
|
|||
total_demand_monthly_kwh: tuple[float, ...]
|
||||
output_monthly_kwh: tuple[float, ...]
|
||||
heat_gains_monthly_kwh: tuple[float, ...]
|
||||
electric_shower_monthly_kwh: tuple[float, ...] # (64a)m — App J step 8
|
||||
output_kwh_per_yr: float
|
||||
electric_shower_kwh_per_yr: float # Σ (64a)m — feeds §10a (247a)
|
||||
|
||||
# Table J2 — monthly factors for hot water use (also used by Appendix J
|
||||
# equation J11 for "other uses"). Symmetric about the year midpoint.
|
||||
|
|
@ -763,5 +765,7 @@ def water_heating_from_cert(
|
|||
total_demand_monthly_kwh=total_demand,
|
||||
output_monthly_kwh=output,
|
||||
heat_gains_monthly_kwh=gains,
|
||||
electric_shower_monthly_kwh=electric_shower,
|
||||
output_kwh_per_yr=sum(output),
|
||||
electric_shower_kwh_per_yr=sum(electric_shower),
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue