mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
feat(modelling): ASHP reuse case prices flush + half distribution
Slice 3 of ADR-0025 costing. When the dwelling has a reusable wet system, _distribution charges a power-flush (168) plus _REUSE_DISTRIBUTION_FRACTION (0.5) of the full radiator band -- a documented stand-in for partial radiator upsizing at ASHP flow temps, the headline uncertainty in the model. Without a wet system the full new distribution is priced. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
cf7c2e017d
commit
22612a19eb
2 changed files with 34 additions and 1 deletions
|
|
@ -63,6 +63,13 @@ _DISTRIBUTION_BY_RADIATORS: dict[int, float] = {
|
|||
}
|
||||
_MIN_RADIATORS = 4
|
||||
_MAX_RADIATORS = 12
|
||||
# Power-flush + inhibitor when reusing an existing wet system (ECOHT67).
|
||||
_DISTRIBUTION_FLUSH = 168.0
|
||||
# Fraction of a full new distribution charged when reusing an existing wet
|
||||
# system — a stand-in for partial radiator upsizing at low ASHP flow temps.
|
||||
# The headline uncertainty in the model; recalibrate against real reuse-job
|
||||
# costs / survey data (ADR-0025).
|
||||
_REUSE_DISTRIBUTION_FRACTION = 0.5
|
||||
|
||||
|
||||
class AshpExistingSystem(Enum):
|
||||
|
|
@ -133,4 +140,9 @@ class Products:
|
|||
|
||||
def _distribution(self, inputs: AshpCostInputs) -> float:
|
||||
radiators: int = max(_MIN_RADIATORS, min(_MAX_RADIATORS, inputs.radiator_count))
|
||||
return _DISTRIBUTION_BY_RADIATORS[radiators]
|
||||
full: float = _DISTRIBUTION_BY_RADIATORS[radiators]
|
||||
# An existing wet system is reused, not rebuilt: a flush plus a fraction
|
||||
# of the full distribution to cover partial radiator upsizing.
|
||||
if inputs.has_reusable_wet_system:
|
||||
return _DISTRIBUTION_FLUSH + _REUSE_DISTRIBUTION_FRACTION * full
|
||||
return full
|
||||
|
|
|
|||
|
|
@ -63,3 +63,24 @@ def test_decommission_cost_varies_by_existing_system() -> None:
|
|||
assert abs(products.ashp_bundle_cost(_large_no_reuse(AshpExistingSystem.OIL)).total - (common + 720.0)) <= 1e-9
|
||||
assert abs(products.ashp_bundle_cost(_large_no_reuse(AshpExistingSystem.LPG)).total - (common + 960.0)) <= 1e-9
|
||||
assert abs(products.ashp_bundle_cost(_large_no_reuse(AshpExistingSystem.ELECTRIC_STORAGE)).total - (common + 840.0)) <= 1e-9
|
||||
|
||||
|
||||
def test_reusable_wet_system_prices_a_flush_plus_half_the_distribution() -> None:
|
||||
# Arrange — a gas dwelling whose wet system is reusable: instead of a full
|
||||
# new distribution, the ASHP pays a power-flush plus half the radiator band
|
||||
# (a documented estimate for partial radiator upsizing — ADR-0025).
|
||||
products = Products()
|
||||
inputs = AshpCostInputs(
|
||||
existing_system=AshpExistingSystem.GAS,
|
||||
is_small_property=False,
|
||||
design_heat_loss_kw=8.0,
|
||||
radiator_count=8,
|
||||
has_reusable_wet_system=True,
|
||||
)
|
||||
|
||||
# Act
|
||||
cost: Cost = products.ashp_bundle_cost(inputs)
|
||||
|
||||
# Assert — decommission 720 + pump 9840 + cylinder 2382.60 + distribution
|
||||
# (flush 168 + 0.5 x 4152 = 2244) = 15186.60.
|
||||
assert abs(cost.total - 15186.60) <= 1e-9
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue