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

Reserves price stacking #273

Merged
merged 4 commits into from
Apr 13, 2022
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
14 changes: 4 additions & 10 deletions egret/model_library/unit_commitment/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -634,10 +634,9 @@ def enforce_zonal_reg_dn_requirement_rule(m, rz, t):
m.ZonalRegulationDnShortfall[rz,t] >= m.ZonalRegulationDnRequirement[rz,t]
model.EnforceZonalRegulationDnRequirements = Constraint(model.RegulationZones, model.TimePeriods, rule=enforce_zonal_reg_dn_requirement_rule)

## NOTE: making sure not to double count the shortfall
def system_reg_up_provided(m,t):
return sum(m.RegulationReserveUp[g,t] for g in m.AGC_Generators) + \
m.SystemRegulationUpShortfall[t] + sum(m.ZonalRegulationUpShortfall[rz,t] for rz in m.RegulationZones)
m.SystemRegulationUpShortfall[t]
model.SystemRegulationUpProvided = Expression(model.TimePeriods, rule=system_reg_up_provided)

def enforce_system_regulation_up_requirement_rule(m, t):
Expand All @@ -646,7 +645,7 @@ def enforce_system_regulation_up_requirement_rule(m, t):

def enforce_system_regulation_dn_requirement_rule(m, t):
return sum(m.RegulationReserveDn[g,t] for g in m.AGC_Generators) + \
m.SystemRegulationDnShortfall[t] + sum(m.ZonalRegulationDnShortfall[rz,t] for rz in m.RegulationZones) \
m.SystemRegulationDnShortfall[t] \
>= m.SystemRegulationDnRequirement[t]
model.EnforceSystemRegulationDnRequirement = Constraint(model.TimePeriods, rule=enforce_system_regulation_dn_requirement_rule)

Expand Down Expand Up @@ -737,7 +736,6 @@ def enforce_zonal_spinning_reserve_requirement(m, rz, t):

def system_spinning_reserve_provided(m,t):
return sum(m.SpinningReserveDispatched[g,t] for g in m.ThermalGenerators) \
+ sum(m.ZonalSpinningReserveShortfall[rz,t] for rz in m.SpinningReserveZones) \
+ m.SystemSpinningReserveShortfall[t]
model.SystemSpinningReserveProvided = Expression(model.TimePeriods, rule=system_spinning_reserve_provided)

Expand Down Expand Up @@ -835,7 +833,6 @@ def enforce_zonal_non_spinning_reserve_rule(m, rz, t):

def nspin_reserves_provided(m,t):
return sum(m.NonSpinningReserveDispatched[g,t] for g in m.NonSpinGenerators) \
+ sum(m.ZonalNonSpinningReserveShortfall[rz,t] for rz in m.NonSpinReserveZones) \
+ m.SystemNonSpinningReserveShortfall[t]
model.SystemNonSpinningReserveProvided = Expression(model.TimePeriods, rule=nspin_reserves_provided)

Expand Down Expand Up @@ -958,7 +955,7 @@ def enforce_zonal_supplemental_reserve_requirement_rule(m, rz, t):
return m.SupplementalZonalReservesProvided[rz,t] \
+ (m.NonSpinningZonalReservesProvided[rz,t] if nspin else 0.) \
+ (m.ZonalSpinningReserveProvided[rz,t] if spin else 0.) \
+ (m.ZonalRegulationUpRequirement[rz,t] if reg_up else 0.) \
+ (m.ZonalRegulationUpProvided[rz,t] if reg_up else 0.) \
>= m.ZonalSupplementalReserveRequirement[rz,t] \
+ (m.ZonalNonSpinningReserveRequirement[rz,t] if nspin else 0.) \
+ (m.ZonalSpinningReserveRequirement[rz,t] if spin else 0.)\
Expand All @@ -967,15 +964,14 @@ def enforce_zonal_supplemental_reserve_requirement_rule(m, rz, t):

def operational_reserves_provided(m,t):
return sum(m.SupplementalReserveDispatched[g,t] for g in m.ThermalGenerators) \
+ sum(m.ZonalSupplementalReserveShortfall[rz,t] for rz in m.SupplementalReserveZones) \
+ m.SystemSupplementalReserveShortfall[t]
model.SystemSupplementalReserveProvided = Expression(model.TimePeriods, rule=operational_reserves_provided)

def enforce_system_supplemental_reserve_requirement(m, t):
return m.SystemSupplementalReserveProvided[t] \
+ (m.SystemNonSpinningReserveProvided[t] if nspin_reserves else 0.) \
+ (m.SystemSpinningReserveProvided[t] if spin_reserves else 0.) \
+ (m.SystemRegulationUpRequirement[t] if regup_reserves else 0.)\
+ (m.SystemRegulationUpProvided[t] if regup_reserves else 0.)\
>= m.SystemSupplementalReserveRequirement[t] \
+ (m.SystemNonSpinningReserveRequirement[t] if nspin_reserves else 0.) \
+ (m.SystemSpinningReserveRequirement[t] if spin_reserves else 0.)\
Expand Down Expand Up @@ -1063,14 +1059,12 @@ def zonal_flex_dn_requirement_rule(m, rz, t):

def system_flex_up_requirement_rule(m, t):
return sum(m.FlexUpProvided[g,t] for g in m.ThermalGenerators) \
+ sum(m.ZonalFlexUpShortfall[rz,t] for rz in m.FlexRampZones) \
+ m.SystemFlexUpShortfall[t] \
>= m.SystemFlexUpRequirement[t]
model.SystemFlexUpRequirementConstr = Constraint(model.TimePeriods, rule=system_flex_up_requirement_rule)

def system_flex_dn_requirement_rule(m, t):
return sum(m.FlexDnProvided[g,t] for g in m.ThermalGenerators) \
+ sum(m.ZonalFlexDnShortfall[rz,t] for rz in m.FlexRampZones) \
+ m.SystemFlexDnShortfall[t] \
>= m.SystemFlexDnRequirement[t]
model.SystemFlexDnRequirementConstr = Constraint(model.TimePeriods, rule=system_flex_dn_requirement_rule)
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

24 changes: 24 additions & 0 deletions egret/models/unit_commitment.py
Original file line number Diff line number Diff line change
Expand Up @@ -1560,6 +1560,30 @@ def _populate_system_reserves(sys_dict):

_populate_system_reserves(md.data['system'])

if relaxed:
_reserve_stacking = { # NOTE: need to maintain this order to avoid double-counting
'regulation_up_price' : ('spinning_reserve_price', 'non_spinning_reserve_price', 'supplemental_reserve_price'),
'spinning_reserve_price' : ('non_spinning_reserve_price', 'supplemental_reserve_price'),
'non_spinning_reserve_price' : ('supplemental_reserve_price',),
}

def _stack_reserves_zones(elements_dict):
for e_dict in elements_dict.values():
_stack_reserves(e_dict)

def _stack_reserves(e_dict):
for price_name, stack in _reserve_stacking.items():
if price_name in e_dict:
vals = e_dict[price_name]['values']
for stacked_name in stack:
if stacked_name in e_dict:
for idx, v in enumerate(e_dict[stacked_name]['values']):
vals[idx] += v

_stack_reserves_zones(areas)
_stack_reserves_zones(zones)
_stack_reserves(md.data['system'])

if fs:
fuel_supplies = dict(md.elements(element_type='fuel_supply'))
for f, f_dict in fuel_supplies.items():
Expand Down