Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Treat HP campaign args same as HP discount args #151

Merged
merged 6 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions k8s/job.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,32 @@ local job(name, args_excl_output) = {
'extended_boiler_upgrade_scheme',
'--intervention',
'heat_pump_campaign',
'--campaign-target-heat-pump-awareness',
'0.8',
'--heat-pump-awareness-campaign-date',
'2028-01-01',
'--campaign-target-heat-pump-awareness-date',
charlotte-avery marked this conversation as resolved.
Show resolved Hide resolved
'2028-01-01:0.5',
'--campaign-target-heat-pump-awareness-date',
'2034-01-01:0.75',
'--intervention',
'gas_oil_boiler_ban',
'--gas-oil-boiler-ban-date',
'2035-01-01',
'--gas-oil-boiler-ban-announce-date',
'2025-01-01',
'--heat-pump-awareness',
'0.25',
'--price-gbp-per-kwh-gas',
'0.0682',
'--price-gbp-per-kwh-electricity',
'0.182',
'--heat-pump-installer-count',
'10000000000'
]),
job('01b-%s-max-policy-extended-bus' % std.extVar('SHORT_SHA'), [
'--intervention',
'extended_boiler_upgrade_scheme',
'--intervention',
'heat_pump_campaign',
'--campaign-target-heat-pump-awareness-date',
'2028-01-01:0.75',
'--intervention',
'gas_oil_boiler_ban',
'--gas-oil-boiler-ban-date',
Expand Down
55 changes: 41 additions & 14 deletions simulation/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,30 +179,58 @@ def check_string_is_isoformat_datetime(string) -> str:
parser.add_argument("--price-gbp-per-kwh-oil", type=float, default=0.068)

parser.add_argument(
"--heat-pump-awareness-campaign-date",
default=datetime.datetime(2028, 1, 1),
type=convert_to_datetime,
)

parser.add_argument(
"--campaign-target-heat-pump-awareness",
default=0.8,
type=float_between_0_and_1,
"--campaign-target-heat-pump-awareness-date",
action="append",
type=map_string_to_datetime_float_tuple,
help="A factor by which heat pump awareness will increase by a specified date.",
metavar="YYYY-MM-DD:heat_pump_awareness",
)

return parser.parse_args(args)


def check_parsed_target_heat_pump_awareness(
campaigns: dict, initial_awareness: float
) -> bool:
"""Determine whether target heat pump awareness increases over the model horizon

Args:
campaigns (dict): modelled heat pump awareness campaigns
initial_awareness (float): initial (t=0) heat pump awareness

Returns:
bool: True if target awareness values are set to increase over model horizon
"""

campaigns_date_ordered = sorted(campaigns)
_, awareness_factors = zip(*campaigns_date_ordered)
awareness_factors = list(awareness_factors)
awareness_factors.insert(0, initial_awareness)

increasing_awareness = all(
[
awareness_factors[i - 1] < awareness_factors[i]
for i in range(1, len(awareness_factors))
]
)
return increasing_awareness


def validate_args(args):
if args.gas_oil_boiler_ban_announce_date > args.gas_oil_boiler_ban_date:
raise ValueError(
f"Boiler ban announcement date must be on or before ban date, got gas_oil_boiler_ban_date:{args.gas_oil_boiler_ban_date}, gas_oil_boiler_ban_announce_date:{args.gas_oil_boiler_ban_announce_date}"
)

if args.campaign_target_heat_pump_awareness < args.heat_pump_awareness:
raise ValueError(
f"Campaign target awareness must be greater than or equal to the population heat pump awareness, got campaign_target_heat_pump_awareness:{args.campaign_target_heat_pump_awareness}, heat_pump_awareness:{args.heat_pump_awareness}"
if args.campaign_target_heat_pump_awareness_date is not None:
# Check that target awareness inputs increase over the model horizon
increasing_awareness = check_parsed_target_heat_pump_awareness(
args.campaign_target_heat_pump_awareness_date, args.heat_pump_awareness
)
if not increasing_awareness:
raise ValueError(
f"Campaign target awareness must be greater than or equal to the population heat pump awareness, got campaign_target_heat_pump_awareness:{args.campaign_target_heat_pump_awareness_date}, heat_pump_awareness:{args.heat_pump_awareness}"
)


if __name__ == "__main__":
Expand Down Expand Up @@ -243,8 +271,7 @@ def validate_args(args):
args.heat_pump_installer_count,
args.heat_pump_installer_annual_growth_rate,
ENGLAND_WALES_ANNUAL_NEW_BUILDS if args.include_new_builds else None,
args.campaign_target_heat_pump_awareness,
args.heat_pump_awareness_campaign_date,
args.campaign_target_heat_pump_awareness_date,
)

with smart_open.open(args.history_file, "w") as file:
Expand Down
1 change: 0 additions & 1 deletion simulation/agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,6 @@ def proba_of_becoming_heat_pump_aware_required_to_reach_campaign_target(
def update_heat_pump_awareness(self, model) -> None:
if (
InterventionType.HEAT_PUMP_CAMPAIGN in model.interventions
and model.current_datetime >= model.heat_pump_awareness_campaign_date
and model.heat_pump_awareness_at_timestep
< model.campaign_target_heat_pump_awareness
and not self.is_heat_pump_aware
Expand Down
22 changes: 11 additions & 11 deletions simulation/costs.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,20 +157,20 @@

# Grant cap is set to £250M for 2024-’25, SOURCE: https://www.gov.uk/government/publications/boiler-upgrade-scheme-budget-increase-and-approval-to-over-allocate-vouchers/approval-to-increase-the-budget-and-over-allocate-vouchers-for-the-boiler-upgrade-scheme-november-2024
# Grant cap is set to £1.54B for 2025-’28, SOURCE: https://www.gov.uk/government/news/families-business-and-industry-to-get-energy-efficiency-support
# Assume limited spend of £515M per annum during 2025-’28, unless the grant was underspent in year in which case the underspent amount gets carried forward to the future years
# Assume £515M PA grant will be extended to 2035.
# Assume limited spend of per annum during 2025-’28, unless the grant was underspent in year in which case the underspent amount gets carried forward to the future years
# Assume grant will be extended to 2035.
BOILER_UPGRADE_SCHEME_GRANT_CAP = {
2024: 250_000_000,
2025: 765_000_000,
2026: 1280_000_000,
2025: 545_000_000,
2026: 1025_000_000,
2027: 1795_000_000,
2028: 2310_000_000,
2029: 2825_000_000,
2030: 3340_000_000,
2031: 3855_000_000,
2032: 4370_000_000,
2033: 4885_000_000,
2034: 5400_000_000,
2028: 2565_000_000,
2029: 3335_000_000,
2030: 4105_000_000,
2031: 4875_000_000,
2032: 5645_000_000,
2033: 6415_000_000,
2034: 7185_000_000,
}


Expand Down
38 changes: 30 additions & 8 deletions simulation/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ def __init__(
heat_pump_installer_annual_growth_rate: float,
annual_new_builds: Optional[Dict[int, int]],
heat_pump_awareness: float,
campaign_target_heat_pump_awareness: float,
heat_pump_awareness_campaign_date: datetime.datetime,
heat_pump_awareness_campaign_schedule: Optional[
List[Tuple[datetime.datetime, float]]
],
population_heat_pump_awareness: List[bool],
):
self.start_datetime = start_datetime
Expand Down Expand Up @@ -79,8 +80,11 @@ def __init__(
self.heat_pump_installations_at_current_step = 0
self.annual_new_builds = annual_new_builds
self.heat_pump_awareness = heat_pump_awareness
self.campaign_target_heat_pump_awareness = campaign_target_heat_pump_awareness
self.heat_pump_awareness_campaign_date = heat_pump_awareness_campaign_date
self.heat_pump_awareness_campaign_schedule = (
sorted(heat_pump_awareness_campaign_schedule)
if heat_pump_awareness_campaign_schedule
else None
)

self.population_heat_pump_awareness = population_heat_pump_awareness
self.num_households_heat_pump_aware = sum(population_heat_pump_awareness)
Expand Down Expand Up @@ -211,6 +215,24 @@ def heat_pump_awareness_at_timestep(self) -> float:
+ self.num_households_switching_to_heat_pump_aware
) / self.household_count

@property
def campaign_target_heat_pump_awareness(self) -> float:

if self.heat_pump_awareness_campaign_schedule:

step_dates, awareness_factors = zip(
*self.heat_pump_awareness_campaign_schedule
)

index = bisect(step_dates, self.current_datetime)
current_date_precedes_first_campaign_date = index == 0

if current_date_precedes_first_campaign_date:
return self.heat_pump_awareness
return awareness_factors[index - 1]

return self.heat_pump_awareness

def increment_timestep(self):
self.current_datetime += self.step_interval
self.boiler_upgrade_scheme_cumulative_spend_gbp += (
Expand Down Expand Up @@ -282,8 +304,9 @@ def create_and_run_simulation(
heat_pump_installer_count: int,
heat_pump_installer_annual_growth_rate: float,
annual_new_builds: Dict[int, int],
campaign_target_heat_pump_awareness: float,
heat_pump_awareness_campaign_date: datetime.datetime,
heat_pump_awareness_campaign_schedule: Optional[
List[Tuple[datetime.datetime, float]]
],
):

population_heat_pump_awareness = [
Expand All @@ -308,8 +331,7 @@ def create_and_run_simulation(
heat_pump_installer_annual_growth_rate=heat_pump_installer_annual_growth_rate,
annual_new_builds=annual_new_builds,
heat_pump_awareness=heat_pump_awareness,
campaign_target_heat_pump_awareness=campaign_target_heat_pump_awareness,
heat_pump_awareness_campaign_date=heat_pump_awareness_campaign_date,
heat_pump_awareness_campaign_schedule=heat_pump_awareness_campaign_schedule,
population_heat_pump_awareness=population_heat_pump_awareness,
)

Expand Down
3 changes: 1 addition & 2 deletions simulation/tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ def model_factory(**model_attributes):
"heat_pump_installer_annual_growth_rate": 0,
"annual_new_builds": None,
"heat_pump_awareness": 0.5,
"campaign_target_heat_pump_awareness": 0.8,
"heat_pump_awareness_campaign_date": datetime.datetime(2028, 1, 1),
"heat_pump_awareness_campaign_schedule": None,
"population_heat_pump_awareness": [],
}

Expand Down
11 changes: 7 additions & 4 deletions simulation/tests/test_agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -705,8 +705,10 @@ def test_heat_pump_awareness_updated_after_successful_campaign(
start_datetime=datetime.datetime(2025, 1, 1),
step_interval=relativedelta(months=1),
interventions=[InterventionType.HEAT_PUMP_CAMPAIGN],
heat_pump_awareness_campaign_date=datetime.datetime(2025, 3, 1),
campaign_target_heat_pump_awareness=1.0,
heat_pump_awareness=0.0,
heat_pump_awareness_campaign_schedule=[
(datetime.datetime(2025, 3, 1), 1.0)
],
)
agent = household_factory(is_heat_pump_aware=False)
model.add_agents([agent])
Expand Down Expand Up @@ -751,9 +753,10 @@ def test_heat_pump_awareness_does_not_increase_when_campaign_target_is_same_as_c
start_datetime=datetime.datetime(2025, 1, 1),
step_interval=relativedelta(months=1),
interventions=[InterventionType.HEAT_PUMP_CAMPAIGN],
heat_pump_awareness_campaign_date=datetime.datetime(2025, 2, 1),
heat_pump_awareness_campaign_schedule=[
(datetime.datetime(2025, 2, 1), 0.0)
],
heat_pump_awareness=0.0,
campaign_target_heat_pump_awareness=0.0,
population_heat_pump_awareness=[False],
)
agent = household_factory(is_heat_pump_aware=False)
Expand Down
16 changes: 13 additions & 3 deletions simulation/tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@

import simulation.__main__
from abm import read_jsonlines
from simulation.__main__ import parse_args, validate_args
from simulation.__main__ import (
check_parsed_target_heat_pump_awareness,
parse_args,
validate_args,
)
from simulation.constants import InterventionType


Expand Down Expand Up @@ -299,11 +303,17 @@ def test_campaign_target_less_than_heat_pump_awareness_raises_value_error(
args = parse_args(
[
*mandatory_local_args,
"--campaign-target-heat-pump-awareness",
"0.1",
"--campaign-target-heat-pump-awareness-date",
"2024-03-01:0.1",
"--heat-pump-awareness",
"0.5",
]
)

increasing_awareness = check_parsed_target_heat_pump_awareness(
args.campaign_target_heat_pump_awareness_date, args.heat_pump_awareness
)
assert not increasing_awareness

with pytest.raises(ValueError):
validate_args(args)
35 changes: 33 additions & 2 deletions simulation/tests/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,36 @@ def test_model_installs_heat_pumps_in_existing_builds_when_there_is_capacity(sel
assert 0 < capacity_new_build < capacity_existing_build
assert model.has_heat_pump_installation_capacity

def test_heat_pump_awareness_campaign_is_intial_awareness_if_no_campaign_schedule_passed(
self,
):

model = model_factory(heat_pump_awareness_campaign_schedule=None)

assert model.campaign_target_heat_pump_awareness == model.heat_pump_awareness

def test_heat_pump_awareness_changes_when_crosses_campaign_schedule_date(
self,
):

model = model_factory(
start_datetime=datetime.datetime(2024, 2, 1),
heat_pump_awareness=0.25,
heat_pump_awareness_campaign_schedule=[
(datetime.datetime(2024, 2, 2), 0.5),
(datetime.datetime(2024, 2, 3), 0.7),
],
step_interval=datetime.timedelta(minutes=1440),
)

assert model.campaign_target_heat_pump_awareness == 0.25

model.increment_timestep()
assert model.campaign_target_heat_pump_awareness == 0.5

model.increment_timestep()
assert model.campaign_target_heat_pump_awareness == 0.7


class test_household_agents:

Expand Down Expand Up @@ -344,9 +374,10 @@ def test_all_household_agents_become_heat_pump_aware_with_100_per_cent_campaign_
start_datetime=datetime.datetime(2025, 1, 1),
step_interval=relativedelta(months=1),
interventions=[InterventionType.HEAT_PUMP_CAMPAIGN],
heat_pump_awareness_campaign_date=datetime.datetime(2025, 2, 1),
heat_pump_awareness=0.0,
campaign_target_heat_pump_awareness=campaign_target_heat_pump_awareness,
heat_pump_awareness_campaign_schedule=[
(datetime.datetime(2025, 2, 1), campaign_target_heat_pump_awareness)
],
population_heat_pump_awareness=population_heat_pump_awareness,
)
model.add_agents([household_agents])
Expand Down
Loading