Model/domain
Khalim Conn-Kowlessar 99c8c148f1 Slice S0380.65: SAP 10.2 Table 12d + Table 12a Grid 1 dual-rate CO2 factor for electric mains on off-peak
Pre-S0380.65 the cascade applied the annual-flat SAP 10.2 Table 12
code-30 CO2 factor (0.136 kg/kWh) to all electric main heating fuel,
ignoring both the Table 12d monthly variation AND the Table 12a
Grid 1 (SH) high-rate fraction. For winter-peaked heat-pump loads on
an off-peak tariff this hid ~600 kg/yr of CO2 — cert 000565 worksheet
line 261:

  Main 1 (high-rate cost)  20826.4764 kWh × 0.1581 = 3293.6388 kg
  Main 1 (low-rate cost)   13884.3176 kWh × 0.1460 = 2027.2261 kg
                           ─────────────              ────────────
  blended                  34710.7941 × 0.1533     = 5320.87 kg

Cascade impact on cert 000565:
  - co2_kg_per_yr            5823.16 → 6427.86 (Δ −624 → Δ −20)
  - main_heating_co2_factor  0.1360  → 0.1533  (matches spec line 261)
  - sap_score                29 EXACT (unchanged — CO2 doesn't enter
    the energy-rating cost factor)

Spec basis:
  - SAP 10.2 Table 12a Grid 1 (p.191): SH high-rate fraction by
    `Table12aSystem` × tariff. ASHP_OTHER + TEN_HOUR = 0.6 high
    (Slice S0380.61 already exercises this on the cost side).
  - SAP 10.2 Table 12d (p.194): monthly CO2 factors by electricity
    fuel code. 7-hour split = codes 32 (high) / 31 (low); 10-hour
    split = codes 34 (high) / 33 (low). 18-hour (38/40) and 24-hour
    (35) fall through to code-30 monthly factors in the table —
    no dual-rate split applies for those tariffs.
  - RdSAP 10 §12 page 62 (Slice S0380.60): meter_type=Dual + HP
    without PCDB record → Rule 1 → TEN_HOUR tariff.

Implementation:
  - New `_TARIFF_HIGH_LOW_FUEL_CODES_TABLE_12` dict — mirror of the
    existing `_TARIFF_HIGH_LOW_RATES_P_PER_KWH` cost-rates dict.
    Only SEVEN_HOUR + TEN_HOUR have a Table 12d split entry.
  - New `_main_heating_co2_factor_kg_per_kwh(main, tariff, monthly_kwh)`
    helper — mirror of `_space_heating_fuel_cost_gbp_per_kwh` on the
    CO2 side. Falls back to the annual `_co2_factor_kg_per_kwh` for
    non-electric mains, STANDARD tariff, mains without a Table 12a
    Grid 1 row yet (storage / direct-acting electric — TODO matches
    cost-helper coverage gap), tariffs without a Table 12d split,
    and zero-fuel degenerate cases.
  - Wire helper into `CalculatorInputs.main_heating_co2_factor_kg_per_kwh`
    using the `energy_requirements_result.main_1_fuel_monthly_kwh`
    profile already precomputed in `cert_to_inputs`.

Tests:
  - `test_dual_meter_ashp_main_heating_co2_factor_applies_table_12a
    _grid_1_split` — minimal ASHP code 224 + meter_type=1 cert
    asserts the effective factor exceeds the pre-S0380.65 annual
    flat (0.136 + 0.005) per spec.
  - `test_standard_meter_ashp_main_heating_co2_factor_falls_back_
    to_annual_table_12` — meter_type=2 (Standard) pass-through pin
    at 0.136. Locks in non-regression for non-dual-meter certs.

Test suite: 480 pass + 9 expected 000565 cascade-gap fails (was
478/9 pre-S0380.65). Pyright net-zero on both touched files
(cert_to_inputs.py 34/34; test_cert_to_inputs.py 11/11).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 16:28:47 +00:00
..
addresses standardist Address 2026-05-22 10:13:32 +00:00
data_transformation moved classifier data transformation to an easy one 2026-06-01 14:53:34 +00:00
epc pr review, move domain and orhcestration 2026-06-01 14:00:31 +00:00
sap10_calculator Slice S0380.65: SAP 10.2 Table 12d + Table 12a Grid 1 dual-rate CO2 factor for electric mains on off-peak 2026-06-01 16:28:47 +00:00
sap10_ml Slice S0380.26: RdSAP10 §5.8 dry-lining adjustment on alt walls — closes cert 7700 -0.44 → +5e-5 2026-06-01 16:28:46 +00:00
tasks added postcode splitter rewrite to ddd 2026-05-19 16:35:09 +00:00
postcode.py get rid of comments 2026-05-20 13:21:11 +00:00