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 3 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
35 changes: 21 additions & 14 deletions simulation/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,15 +179,11 @@ 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)
Expand All @@ -199,10 +195,22 @@ def validate_args(args):
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
campaigns = sorted(args.campaign_target_heat_pump_awareness_date)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a function that we unit test I think!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See test_campaign_target_less_than_heat_pump_awareness_raises_value_error in test_main

Copy link
Member

@shengy90 shengy90 Dec 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I mean the logic inside this if statement - it's a pretty convoluted logic that I think we should write as a function, then test that given inputs you get expected output.

e.g.

     if args.campaign_target_heat_pump_awareness_date is not None:
           x = parse_campaign_dates_and_target(arg1, arg2)
    
    # in test_main.py
     def test_parse_campaign_dates_and_target():
           test this function.

Increase maintainability of the code - if someone changes some stuff then this test will break, and they'd have to either update the tests (if break is intended) or fix the change to conform to the test etc.

_, awareness_factors = zip(*campaigns)
awareness_factors = list(awareness_factors)
awareness_factors.insert(0, args.heat_pump_awareness)
increasing_awareness = all(
[
awareness_factors[i - 1] < awareness_factors[i]
for i in range(1, len(awareness_factors))
]
)
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 +251,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
4 changes: 2 additions & 2 deletions simulation/tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,8 @@ 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",
]
Expand Down
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