Skip to content

Commit ae3c330

Browse files
committed
Add unit commitment extension
Signed-off-by: Davey Elder <iandavidelder@gmail.com>
1 parent 5e448e7 commit ae3c330

17 files changed

Lines changed: 1410 additions & 15 deletions

File tree

temoa/_internal/table_data_puller.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,11 @@ def poll_flow_results(model: TemoaModel, epsilon: float = 1e-5) -> dict[FI, dict
246246
continue
247247
res[fi][FlowType.OUT] = flow
248248

249+
if 'unit_commitment' in model.enabled_extensions:
250+
import temoa.extensions.unit_commitment.core.data_puller as uc
251+
252+
uc.poll_startup_input_results(model, res, epsilon)
253+
249254
return res
250255

251256

@@ -494,6 +499,10 @@ def poll_cost_results(
494499
import temoa.extensions.economies_of_scale.core.data_puller as eos
495500

496501
eos.poll_costs(model, exchange_costs, entries, p_0_true, epsilon)
502+
if 'unit_commitment' in model.enabled_extensions:
503+
import temoa.extensions.unit_commitment.core.data_puller as uc
504+
505+
uc.poll_startup_cost_results(model, exchange_costs, entries, p_0_true, epsilon)
497506

498507
exchange_entries = exchange_costs.get_entries()
499508
return entries, exchange_entries
@@ -558,6 +567,11 @@ def poll_emissions(
558567
* model.emission_activity[r, e, i, t, v, o]
559568
)
560569

570+
if 'unit_commitment' in model.enabled_extensions:
571+
from temoa.extensions.unit_commitment.core import data_puller as uc
572+
573+
uc.poll_emission_results(model, flows)
574+
561575
# gather costs
562576
ud_costs: dict[tuple[Region, Period, Technology, Vintage], float] = defaultdict(float)
563577
d_costs: dict[tuple[Region, Period, Technology, Vintage], float] = defaultdict(float)

temoa/_internal/table_writer.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,16 @@ def write_capacity_tables(self, model: TemoaModel, iteration: int | None = None)
483483
cap_data = poll_capacity_results(model=model, epsilon=self.output_threshold_capacity)
484484
self._insert_capacity_results(cap_data=cap_data, iteration=iteration)
485485

486+
if 'unit_commitment' in model.enabled_extensions:
487+
import temoa.extensions.unit_commitment.core.data_puller as uc_puller
488+
489+
uc_puller.write_uc_results(
490+
model=model,
491+
writer=self,
492+
iteration=iteration,
493+
epsilon=self.output_threshold_capacity,
494+
)
495+
486496
def _insert_capacity_results(self, cap_data: CapData, iteration: int | None) -> None:
487497
if self.tech_sectors is None:
488498
raise RuntimeError('tech sectors not available... code error')

temoa/components/commodities.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,11 @@ def commodity_balance_constraint(
425425
for s_o in model.process_outputs_by_input[r, p, s_t, s_v, c]
426426
)
427427

428+
if 'unit_commitment' in model.enabled_extensions:
429+
from temoa.extensions.unit_commitment.components import startup
430+
431+
consumed += startup.uc_startup_input_rpsdc(model, r, p, s, d, c)
432+
428433
if (r, p, c) in model.capacity_consumption_techs:
429434
# Consumed by building capacity
430435
# Assume evenly distributed over a year
@@ -573,6 +578,11 @@ def annual_commodity_balance_constraint(
573578
for s_o in model.process_outputs_by_input[r, p, s_t, s_v, c]
574579
)
575580

581+
if 'unit_commitment' in model.enabled_extensions:
582+
from temoa.extensions.unit_commitment.components import startup
583+
584+
consumed += startup.uc_startup_input_rpc(model, r, p, c)
585+
576586
if (r, p, c) in model.capacity_consumption_techs:
577587
# Consumed by building capacity
578588
# Assume evenly distributed over a year

temoa/components/limits.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,11 @@ def limit_emission_constraint(
795795
if (reg, p, S_t, S_v) in model.process_inputs
796796
)
797797

798+
if 'unit_commitment' in model.enabled_extensions:
799+
from temoa.extensions.unit_commitment.components import startup
800+
801+
process_emissions += startup.uc_startup_emissions_rpe(model, regions, p, e)
802+
798803
embodied_emissions = quicksum(
799804
model.v_new_capacity[reg, t, v]
800805
* value(model.emission_embodied[reg, e, t, v])

temoa/components/time.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,9 +336,8 @@ def create_time_season_to_sequential(model: TemoaModel) -> None:
336336
f'No data in time_season_sequential but time_sequencing parameter set to '
337337
f'{model.time_sequencing.first()} and inter-season features used. '
338338
'time_season_sequential must be filled for this type of time sequencing if '
339-
'seasonal storage or inter-season constraints like ramp_up/ramp_down are used. '
340-
'Check '
341-
'the config file.'
339+
'seasonal storage or inter-season constraints like ramp_up/ramp_down or'
340+
'unit_commitment are used. Check the config file.'
342341
)
343342
logger.error(msg)
344343
raise ValueError(msg)

temoa/core/model.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -831,10 +831,15 @@ def __init__(
831831

832832
self.progress_marker_4 = BuildAction(['Starting to build Constraints'], rule=progress_check)
833833

834-
# Declare constraints to calculate derived decision variables
835-
self.capacity_constraint = Constraint(
836-
self.capacity_constraint_rpsdtv, rule=capacity.capacity_constraint
837-
)
834+
if 'unit_commitment' in self.enabled_extensions:
835+
# Hijack the capacity constraint and load params for other injections
836+
import temoa.extensions.unit_commitment.core.model as uc
837+
838+
uc.register_early_components(self)
839+
else:
840+
self.capacity_constraint = Constraint(
841+
self.capacity_constraint_rpsdtv, rule=capacity.capacity_constraint
842+
)
838843

839844
self.capacity_annual_constraint_rptv = Set(
840845
dimen=4, initialize=capacity.capacity_annual_constraint_indices
@@ -962,12 +967,13 @@ def __init__(
962967
self.ramp_down_constraint_rpsdtv = Set(
963968
dimen=6, initialize=operations.ramp_down_constraint_indices
964969
)
965-
self.ramp_down_constraint = Constraint(
966-
self.ramp_down_constraint_rpsdtv, rule=operations.ramp_down_constraint
967-
)
968-
self.ramp_up_constraint = Constraint(
969-
self.ramp_up_constraint_rpsdtv, rule=operations.ramp_up_constraint
970-
)
970+
if 'unit_commitment' not in self.enabled_extensions:
971+
self.ramp_down_constraint = Constraint(
972+
self.ramp_down_constraint_rpsdtv, rule=operations.ramp_down_constraint
973+
)
974+
self.ramp_up_constraint = Constraint(
975+
self.ramp_up_constraint_rpsdtv, rule=operations.ramp_up_constraint
976+
)
971977

972978
self.reserve_margin_rpsd = Set(dimen=4, initialize=reserves.reserve_margin_indices)
973979
self.validate_reserve_margin = BuildAction(rule=validate_reserve_margin)

temoa/extensions/framework.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,14 @@ def get_known_extension_specs() -> dict[str, ExtensionSpec]:
5959
from temoa.extensions.discrete_capacity.extension import DISCRETE_CAPACITY_EXTENSION
6060
from temoa.extensions.economies_of_scale.extension import EOS_EXTENSION
6161
from temoa.extensions.growth_rates.extension import GROWTH_RATES_EXTENSION
62-
63-
specs = [GROWTH_RATES_EXTENSION, DISCRETE_CAPACITY_EXTENSION, EOS_EXTENSION]
62+
from temoa.extensions.unit_commitment.extension import UNIT_COMMITMENT_EXTENSION
63+
64+
specs = [
65+
GROWTH_RATES_EXTENSION,
66+
DISCRETE_CAPACITY_EXTENSION,
67+
EOS_EXTENSION,
68+
UNIT_COMMITMENT_EXTENSION,
69+
]
6470
return {spec.extension_id: spec for spec in specs}
6571

6672

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from temoa.extensions.unit_commitment.extension import UNIT_COMMITMENT_EXTENSION
2+
3+
__all__ = ['UNIT_COMMITMENT_EXTENSION']

temoa/extensions/unit_commitment/components/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)