Skip to content

Commit

Permalink
Merge pull request #273 from bknueven/reserves_price_stacking
Browse files Browse the repository at this point in the history
Reserves price stacking
  • Loading branch information
bknueven authored Apr 13, 2022
2 parents 42eb712 + f1e09b1 commit 828bd72
Show file tree
Hide file tree
Showing 15 changed files with 41 additions and 23 deletions.
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

0 comments on commit 828bd72

Please sign in to comment.