mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-12 13:29:04 +00:00
The orchestrator threads the dwelling design heat loss into ASHP sizing 🟥
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
b25e7bb7f9
commit
cb91954bb4
2 changed files with 61 additions and 0 deletions
|
|
@ -264,6 +264,7 @@ def _candidate_recommendations(
|
|||
planning_restrictions: PlanningRestrictions,
|
||||
solar_potential: Optional[SolarPotential],
|
||||
considered_measures: Optional[frozenset[MeasureType]],
|
||||
design_heat_loss_kw: Optional[float] = None,
|
||||
) -> list[Recommendation]:
|
||||
"""Run the applicable Recommendation Generators; keep the ones that apply.
|
||||
Solid-wall insulation, glazing, heating and solar are additionally gated by
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
"""The ModellingOrchestrator threads the dwelling's SAP design heat loss into
|
||||
the heating Recommendation Generator so the ASHP is sized to the dwelling
|
||||
(ADR-0049), mirroring how planning_restrictions and the solar potential are
|
||||
threaded. Tests the candidate-wiring seam directly; the end-to-end run-through-
|
||||
repos path is covered by the DB integration tests.
|
||||
"""
|
||||
|
||||
from datatypes.epc.domain.epc_property_data import EpcPropertyData
|
||||
from domain.geospatial.planning_restrictions import PlanningRestrictions
|
||||
from domain.modelling.measure_type import MeasureType
|
||||
from domain.modelling.product import Product
|
||||
from domain.modelling.recommendation import Recommendation
|
||||
from orchestration.modelling_orchestrator import (
|
||||
_candidate_recommendations, # pyright: ignore[reportPrivateUsage]
|
||||
)
|
||||
from repositories.product.product_repository import ProductRepository
|
||||
from tests.domain.modelling._elmhurst_recommendation import (
|
||||
parse_recommendation_summary,
|
||||
)
|
||||
|
||||
|
||||
class _StubProducts(ProductRepository):
|
||||
def get(self, measure_type: str) -> Product:
|
||||
return Product(
|
||||
measure_type=measure_type,
|
||||
unit_cost_per_m2=0.0,
|
||||
contingency_rate=0.15,
|
||||
id=909,
|
||||
)
|
||||
|
||||
|
||||
def _ashp_eligible_house() -> EpcPropertyData:
|
||||
epc = parse_recommendation_summary(
|
||||
"ashp_from_system_boiler_with_cylinder_001431_before.pdf"
|
||||
)
|
||||
epc.property_type = "House"
|
||||
return epc
|
||||
|
||||
|
||||
def test_candidate_recommendations_sizes_the_ashp_to_the_threaded_design_heat_loss() -> (
|
||||
None
|
||||
):
|
||||
# Arrange — an ASHP-eligible house and a high (17.5 kW) design heat loss.
|
||||
epc = _ashp_eligible_house()
|
||||
|
||||
# Act
|
||||
recommendations: list[Recommendation] = _candidate_recommendations(
|
||||
epc, _StubProducts(), PlanningRestrictions(), None, None, design_heat_loss_kw=17.5
|
||||
)
|
||||
|
||||
# Assert — the ASHP is sized to the load (capped 12 kW aroTHERM plus 110281),
|
||||
# not the fixed 5 kW / floor-area-proxy unit.
|
||||
heating = next(r for r in recommendations if r.surface == "Heating & Hot Water")
|
||||
ashp = next(
|
||||
o
|
||||
for o in heating.options
|
||||
if o.measure_type == MeasureType.AIR_SOURCE_HEAT_PUMP
|
||||
)
|
||||
assert ashp.overlay.heating is not None
|
||||
assert ashp.overlay.heating.main_heating_index_number == 110281
|
||||
Loading…
Add table
Reference in a new issue