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

Add example 5bus case, contingency screening capability, and #128

Merged
merged 26 commits into from
Jan 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b9695fb
initial pass at 5bus example
bknueven Sep 8, 2021
b498ff3
allowing default forecastables
bknueven Sep 8, 2021
b7d9eb3
relaxing line limits
bknueven Sep 8, 2021
d83fc15
adding runner script
bknueven Sep 8, 2021
98e5e1f
correcting issue with REAL_TIME period resolution
bknueven Sep 9, 2021
2648385
Revert "relaxing line limits"
bknueven Sep 9, 2021
f761158
updating network and adding generator
bknueven Sep 9, 2021
83125f5
Merge remote-tracking branch 'upstream/main' into 5bus_case
bknueven Oct 19, 2021
14c6133
ensure reserve factor is honored even if not pre-existing
bknueven Oct 19, 2021
b64e822
first pass at enabling contingency monitoring
bknueven Oct 28, 2021
cd27dfa
Merge remote-tracking branch 'upstream/main' into 5bus_case
bknueven Oct 28, 2021
db7f120
considering more flexible thermal units
bknueven Oct 29, 2021
6121da4
Merge remote-tracking branch 'upstream/main' into 5bus_case
bknueven Nov 15, 2021
5802160
adding contingency reporting
bknueven Nov 15, 2021
722781f
updating price thresholds
bknueven Nov 16, 2021
5027a88
Merge remote-tracking branch 'upstream/main' into 5bus_case
bknueven Dec 1, 2021
f87863d
switching penalty logic to use grid-parity-exchange/Egret#259
bknueven Jan 3, 2022
8e22559
NFC: removing finished TODO
bknueven Jan 3, 2022
70cc152
Merge branch 'main' into 5bus_case
bknueven Jan 3, 2022
2e9f96e
Merge branch 'main' into 5bus_case
bknueven Jan 3, 2022
0dcbd1e
fixing names
bknueven Jan 10, 2022
4c3147f
adding python simulator script
bknueven Jan 10, 2022
0ebc525
Merge branch '5bus_case' of github.com:bknueven/Prescient into 5bus_case
bknueven Jan 10, 2022
57eacf4
more reasonable mipgap
bknueven Jan 10, 2022
99887e8
removing violation, for now
bknueven Jan 10, 2022
3af7f83
Fix spelling, update variable name
darrylmelander Jan 11, 2022
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
8,785 changes: 8,785 additions & 0 deletions examples/5bus/DAY_AHEAD_load.csv

Large diffs are not rendered by default.

8,785 changes: 8,785 additions & 0 deletions examples/5bus/DAY_AHEAD_renewables.csv

Large diffs are not rendered by default.

105,409 changes: 105,409 additions & 0 deletions examples/5bus/REAL_TIME_load.csv

Large diffs are not rendered by default.

105,409 changes: 105,409 additions & 0 deletions examples/5bus/REAL_TIME_renewables.csv

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions examples/5bus/branch.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
UID,From Bus,To Bus,R,X,B,Cont Rating,LTE Rating,STE Rating,Tr Ratio
"branch_2_3",2,3,0.00108,0.0108,0.01852,80.0,92.0,104.0,0
"branch_1_2",1,2,0.00281,0.0281,0.00712,66.6,76.6,86.6,0
"branch_1_4",1,4,0.00304,0.0304,0.00658,66.6,76.6,86.6,0
"branch_4_10",4,10,0.00297,0.0297,0.00674,66.6,76.6,86.6,0
"branch_1_10",1,10,0.00064,0.0064,0.03126,66.6,76.6,86.6,0
"branch_3_4_0",3,4,0.00297,0.0297,0.00337,66.6,76.6,86.6,1.05
"branch_3_4_1",3,4,0.003274425,0.03274425,0.003056689,28.4,32.7,36.9,0.952380952
6 changes: 6 additions & 0 deletions examples/5bus/bus.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Bus ID,Bus Name,BaseKV,Bus Type,MW Load,MVAR Load,V Mag,V Angle,Area,Zone
1,bus1,230,PV,0,0,1,0.048935018,1,1
4,bus4,230,Ref,28.5714286,9.3907143,1,0,1,1
10,bus5,230,PV,0,0,1,0.06266308,1,1
2,bus2,230,PQ,21.4285714,7.0435714,1.04407,-0.012822061,2,1
3,bus3,230,PV,21.4285714,7.0435714,1,-0.009768957,2,1
9 changes: 9 additions & 0 deletions examples/5bus/gen.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
GEN UID,Bus ID,Unit Type,Fuel,MW Inj,MVAR Inj,V Setpoint p.u.,PMax MW,PMin MW,QMax MVAR,QMin MVAR,Min Down Time Hr,Min Up Time Hr,Ramp Rate MW/Min,Start Time Cold Hr,Start Time Warm Hr,Start Time Hot Hr,Start Heat Cold MBTU,Start Heat Warm MBTU,Start Heat Hot MBTU,Non Fuel Start Cost $,Fuel Price $/MMBTU,Output_pct_0,Output_pct_1,Output_pct_2,Output_pct_3,Output_pct_4,HR_avg_0,HR_incr_1,HR_incr_2,HR_incr_3,HR_incr_4
3_CT,3,CT,G,0,0,1,20,8,20,-20,1,1,3,,,1,,,51.75,0,0.75,0.4,0.6,0.8,1,,135722.5,97862.5,98072.5,107135,
10_STEAM,10,STEAM,C,0,0,1,76,30,76,-76,4,8,2,12,10,4,11383.41,10488.35,7355.42,0,1,0.394736842,0.596052632,0.798684211,1,,30166.66667,14402.61434,17182.46753,18283.66017,
4_CC,4,CC,G,0,0,1,100,10,55,-55,3,3,3.7,,,3,,,5665.23,0,0.5,0.4,0.6,0.8,1,,51019.54545,26818.18182,29550.90909,30308.18182,
4_STEAM,4,STEAM,O,0,0,1,12,5,12,-12,2,4,1,12,4,2,703.76,455.37,393.28,0,1.5,0.416666667,0.608333333,0.808333333,1,,179457.9999,124504.3483,125050,133643.478,
10_PV,10,PV,S,0,0,1,25.9,0,0,0,,,,,,,,,,0,,,,,,,,,,,
2_RTPV,2,RTPV,S,0,0,1,9.3,0,0,0,,,,,,,,,,0,,,,,,,,,,,
1_HYDRO,1,HYDRO,H,0,0,1,50,0,16,-10,,,,,,,,,,0,,,,,,,,,,,
4_WIND,4,WIND,W,0,0,1,120,0,0,0,,,,,,,,,,0,,,,,,,,,,,
3 changes: 3 additions & 0 deletions examples/5bus/initial_status.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
3_CT,10_STEAM,4_CC,4_STEAM
24,-24,24,-24,
14,0,40,0
1 change: 1 addition & 0 deletions examples/5bus/reserves.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Reserve Product,Requirement (MW)
7 changes: 7 additions & 0 deletions examples/5bus/simulation_objects.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Simulation_Parameters,Description,DAY_AHEAD,REAL_TIME
Periods_per_Step,the number of discrete periods represented in each simulation step,24,1
Period_Resolution,seconds per period,3600,300
Date_From,simulation beginning period,01/01/2020 0:00,12/31/2020 0:00
Date_To,simulation ending period (must account for lookahed data availability),01/01/2020 0:00,12/31/2020 0:00
Look_Ahead_Periods_per_Step,the number of look ahead periods included in each optimization step,24,2
Look_Ahead_Resolution,look-ahead period resolution,3600,300
17 changes: 17 additions & 0 deletions examples/5bus/timeseries_pointers.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Simulation,Category,Object,Parameter,Data File
DAY_AHEAD,Generator,1_HYDRO,PMin MW,DAY_AHEAD_renewables.csv
DAY_AHEAD,Generator,2_RTPV,PMin MW,DAY_AHEAD_renewables.csv
DAY_AHEAD,Generator,1_HYDRO,PMax MW,DAY_AHEAD_renewables.csv
DAY_AHEAD,Generator,2_RTPV,PMax MW,DAY_AHEAD_renewables.csv
DAY_AHEAD,Generator,10_PV,PMax MW,DAY_AHEAD_renewables.csv
DAY_AHEAD,Generator,4_WIND,PMax MW,DAY_AHEAD_renewables.csv
DAY_AHEAD,Area,1,MW Load,DAY_AHEAD_load.csv
DAY_AHEAD,Area,2,MW Load,DAY_AHEAD_load.csv
REAL_TIME,Generator,1_HYDRO,PMin MW,REAL_TIME_renewables.csv
REAL_TIME,Generator,2_RTPV,PMin MW,REAL_TIME_renewables.csv
REAL_TIME,Generator,1_HYDRO,PMax MW,REAL_TIME_renewables.csv
REAL_TIME,Generator,2_RTPV,PMax MW,REAL_TIME_renewables.csv
REAL_TIME,Generator,10_PV,PMax MW,REAL_TIME_renewables.csv
REAL_TIME,Generator,4_WIND,PMax MW,REAL_TIME_renewables.csv
REAL_TIME,Area,1,MW Load,REAL_TIME_load.csv
REAL_TIME,Area,2,MW Load,REAL_TIME_load.csv
28 changes: 28 additions & 0 deletions examples/simulate_5bus.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from prescient.simulator import Prescient

# set some options
prescient_options = {
"data_path":"./5bus/",
"input_format":"rts-gmlc",
"simulate_out_of_sample":True,
"run_sced_with_persistent_forecast_errors":True,
"output_directory":"5bus_output",
"start_date":"07-10-2020",
"num_days":7,
"sced_horizon":1,
"ruc_mipgap":0.01,
"reserve_factor":0.1,
"deterministic_ruc_solver":"cbc",
"deterministic_ruc_solver_options":{"feas":"off", "DivingF":"on",},
"sced_solver":"cbc",
"sced_frequency_minutes":5,
"ruc_horizon":36,
"compute_market_settlements":True,
"monitor_all_contingencies":True,
"output_solver_logs":False,
"price_threshold":1000,
"contingency_price_threshold":100,
"reserve_price_threshold":5,
}
# run the simulator
Prescient().simulate(**prescient_options)
22 changes: 22 additions & 0 deletions examples/simulate_5bus.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
command/exec simulator.py
--data-directory=5bus
--input-format=rts-gmlc
--simulate-out-of-sample
--run-sced-with-persistent-forecast-errors
--output-directory=5bus_output
--start-date=07-10-2020
--num-days=7
--sced-horizon=1
--ruc-mipgap=0.01
--reserve-factor=0.1
--deterministic-ruc-solver=cbc
--deterministic-ruc-solver-options="feas=off DivingG=on"
--sced-solver=cbc
--sced-frequency-minutes=5
--ruc-horizon=36
--compute-market-settlements
--monitor-all-contingencies
#--output-solver-logs
--price-threshold=1000
--contingency-price-threshold=100
--reserve-price-threshold=5
18 changes: 18 additions & 0 deletions prescient/engine/data_extractors.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,20 @@ def get_max_power_available(self, sced: OperationsModel, g: G) -> float:
def get_flow_level(self, sced: OperationsModel, line: L) -> float:
pass

@abstractmethod
def get_flow_violation_level(self, sced: OperationsModel, line: L) -> float:
pass

@abstractmethod
def get_all_contingency_flow_levels(self, sced: OperationsModel) -> Dict[Tuple[L,L], float]:
"""Get the flows for the monitored contingencies."""
pass

@abstractmethod
def get_all_contingency_flow_violation_levels(self, sced: OperationsModel) -> Dict[Tuple[L,L], float]:
"""Get the flow violations for the monitored contingencies."""
pass

@abstractmethod
def get_storage_input_dispatch_level(self, sced: OperationsModel, storage: S) -> float:
pass
Expand Down Expand Up @@ -425,6 +439,10 @@ def get_all_flow_levels(self, sced: OperationsModel) -> Dict[L, float]:
return {l: self.get_flow_level(sced, l)
for l in self.get_transmission_lines(sced)}

def get_all_flow_violation_levels(self, sced: OperationsModel) -> Dict[L, float]:
return {l: self.get_flow_violation_level(sced, l)
for l in self.get_transmission_lines(sced)}

def get_all_bus_demands(self, sced: OperationsModel) -> Dict[B, float]:
return {b: self.get_bus_demand(sced, b)
for b in self.get_buses(sced)}
Expand Down
28 changes: 26 additions & 2 deletions prescient/engine/egret/data_extractors.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from typing import Iterable
from typing import Iterable, Dict, Tuple
from prescient.engine.abstract_types import *

import numpy as np
Expand Down Expand Up @@ -139,7 +139,7 @@ def get_thermal_headroom(self, sced: OperationsModel, g: G) -> float:
return val

def get_min_downtime(self, sced: OperationsModel, g: G) -> float:
return sced.data['elements']['generator'][g]['min_up_time']
return sced.data['elements']['generator'][g]['min_down_time']

def get_scaled_startup_ramp_limit(self, sced: OperationsModel, g: G) -> float:
return sced.data['elements']['generator'][g]['startup_capacity']
Expand Down Expand Up @@ -187,6 +187,30 @@ def get_generator_cost(self, sced: OperationsModel, g: G) -> float:
def get_flow_level(self, sced: OperationsModel, line: L) -> float:
return sced.data['elements']['branch'][line]['pf']['values'][0]

def get_flow_violation_level(self, sced: OperationsModel, line: L) -> float:
pf_violation = sced.data['elements']['branch'][line].get('pf_violation', 0.)
if pf_violation != 0.:
pf_violation = pf_violation['values'][0]
return pf_violation

def get_all_contingency_flow_levels(self, sced: OperationsModel) -> Dict[Tuple[L,L], float]:
contingency_dict = {}
for c_dict in sced.data['elements'].get('contingency', {}).values():
line_out = c_dict['branch_contingency']
monitored_branches = c_dict.get('monitored_branches',{'values':[{}]})
for bn, b_dict in monitored_branches['values'][0].items():
contingency_dict[line_out, bn] = b_dict['pf']
return contingency_dict

def get_all_contingency_flow_violation_levels(self, sced: OperationsModel) -> Dict[Tuple[L,L], float]:
contingency_viol = {}
for c_dict in sced.data['elements'].get('contingency', {}).values():
line_out = c_dict['branch_contingency']
monitored_branches = c_dict.get('monitored_branches',{'values':[{}]})
for bn, b_dict in monitored_branches['values'][0].items():
contingency_viol[line_out, bn] = b_dict.get('pf_violation', 0.)
return contingency_viol

def get_bus_mismatch(self, sced: OperationsModel, bus: B) -> float:
return self.get_load_mismatch(sced, bus)

Expand Down
74 changes: 64 additions & 10 deletions prescient/engine/egret/egret_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@
from egret.data.model_data import ModelData
from egret.parsers.prescient_dat_parser import get_uc_model, create_model_data_dict_params
from egret.models.unit_commitment import _time_series_dict, _preallocated_list, _solve_unit_commitment, \
_save_uc_results, create_tight_unit_commitment_model, \
_get_uc_model
_save_uc_results, create_tight_unit_commitment_model, \
_get_uc_model
from egret.model_library.transmission.tx_calc import construct_connection_graph, get_N_minus_1_branches

from prescient.util import DEFAULT_MAX_LABEL_LENGTH
from prescient.util.math_utils import round_small_values
Expand Down Expand Up @@ -146,6 +147,7 @@ def create_sced_instance(data_provider:DataProvider,
sced_data[t] = forecast[t] * forecast_error_ratio

_ensure_reserve_factor_honored(options, sced_md, range(sced_horizon))
_ensure_contingencies_monitored(options, sced_md)

# Set generator commitments & future state
for g, g_dict in sced_md.elements(element_type='generator', generator_type='thermal'):
Expand Down Expand Up @@ -368,8 +370,10 @@ def create_deterministic_ruc(options,
# Create a new model
md = data_provider.get_initial_forecast_model(options, ruc_horizon, 60)

initial_ruc = current_state is None or current_state.timestep_count == 0

# Populate the T0 data
if current_state is None or current_state.timestep_count == 0:
if initial_ruc:
data_provider.populate_initial_state_data(options, md)
else:
_copy_initial_state_into_model(options, current_state, md)
Expand Down Expand Up @@ -404,6 +408,8 @@ def create_deterministic_ruc(options,
# Ensure the reserve requirement is satisfied
_ensure_reserve_factor_honored(options, md, range(ruc_horizon))

_ensure_contingencies_monitored(options, md, initial_ruc)

return md


Expand Down Expand Up @@ -483,14 +489,12 @@ def solve_deterministic_day_ahead_pricing_problem(solver, ruc_results, options,
reserve_requirement = ('reserve_requirement' in pricing_instance.data['system'])

system = pricing_instance.data['system']
# In case of demand shortfall, the price skyrockets, so we threshold the value.
if ('load_mismatch_cost' not in system) or (system['load_mismatch_cost'] > options.price_threshold):
system['load_mismatch_cost'] = options.price_threshold

# In case of reserve shortfall, the price skyrockets, so we threshold the value.
if reserve_requirement:
if ('reserve_shortfall_cost' not in system) or (system['reserve_shortfall_cost'] > options.reserve_price_threshold):
system['reserve_shortfall_cost'] = options.reserve_price_threshold
# In case of shortfall, the price skyrockets, so we threshold the value.
for system_key, threshold_value in get_attrs_to_price_option(options):
if threshold_value is not None and ((system_key not in system) or
(system[system_key] > threshold_value)):
system[system_key] = threshold_value

ptdf_manager.mark_active(pricing_instance)
pyo_model = create_pricing_model(pricing_instance, relaxed=True,
Expand Down Expand Up @@ -675,6 +679,38 @@ def _ensure_reserve_factor_honored(options:Options, md:EgretModel, time_periods:
if reserve_reqs[t] < min_reserve:
reserve_reqs[t] = min_reserve

def _ensure_contingencies_monitored(options:Options, md:EgretModel, initial_ruc:bool = False) -> None:
''' Add contingency screening, if that option is enabled '''
if initial_ruc:
_ensure_contingencies_monitored.contingency_dicts = {}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Use of this function-local static variable makes the code not thread safe. For now that's OK, but at some point we might want to address it. create_sced_instance.shutdown_curves is another example of this.

Linked to Issue #130.


for bn, b in md.elements('branch'):
if not b.get('in_service', True):
raise RuntimeError(f"Remove branches from service by setting the `planned_outage` attribute. "
f"Branch {bn} has `in_service`:False")
for bn, b in md.elements('bus'):
if not b.get('in_service', True):
raise RuntimeError(f"Buses cannot be removed from service in Prescient")

if options.monitor_all_contingencies:
key = []
for bn, b in md.elements('branch'):
if 'planned_outage' in b:
if isinstance(b['planned_outage'], dict):
if any(b['planned_outage']['values']):
key.append(b)
elif b['planned_outage']:
key.append(b)
key = tuple(key)
if key not in _ensure_contingencies_monitored.contingency_dicts:
mapping_bus_to_idx = { k : i for i,k in enumerate(md.data['elements']['bus'].keys())}
graph = construct_connection_graph(md.data['elements']['branch'], mapping_bus_to_idx)
contingency_list = get_N_minus_1_branches(graph, md.data['elements']['branch'], mapping_bus_to_idx)
contingency_dict = { cn : {'branch_contingency':cn} for cn in contingency_list}
_ensure_contingencies_monitored.contingency_dicts[key] = contingency_dict

md.data['elements']['contingency'] = _ensure_contingencies_monitored.contingency_dicts[key]

def _copy_initial_state_into_model(options:Options,
current_state:SimulationState,
md:EgretModel):
Expand All @@ -683,3 +719,21 @@ def _copy_initial_state_into_model(options:Options,
g_dict['initial_p_output'] = current_state.get_initial_power_generated(g)
for s,s_dict in md.elements('storage'):
s_dict['initial_state_of_charge'] = current_state.get_initial_state_of_charge(s)

def get_attrs_to_price_option(options:Options):
'''
Create a map from internal attributes to various price thresholds
for the LMP SCED
'''
return {
'load_mismatch_cost' : options.price_threshold,
'contingency_flow_violation_cost' : options.contingency_price_threshold,
'transmission_flow_violation_cost' : options.transmission_price_threshold,
'interface_flow_violation_cost' : options.interface_price_threshold,
'reserve_shortfall_cost' : options.reserve_price_threshold,
'regulation_penalty_price' : options.regulation_price_threshold,
'spinning_reserve_penalty_price' : options.spinning_reserve_price_threshold,
'non_spinning_reserve_penalty_price' : options.non_spinning_reserve_price_threshold,
'supplemental_reserve_penalty_price' : options.supplemental_reserve_price_threshold,
'flexible_ramp_penalty_price' : options.flex_ramp_price_threshold,
}.items()
40 changes: 11 additions & 29 deletions prescient/engine/egret/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from egret.common.lazy_ptdf_utils import uc_instance_binary_relaxer

from prescient.engine.modeling_engine import SlackType as EngineSlackType, NetworkType as EngineNetworkType
from egret.model_library.unit_commitment.uc_utils import SlackType as EgretSlackType
from egret.model_library.unit_commitment.uc_utils import SlackType as EgretSlackType, reset_unit_commitment_penalties


_network_type_to_egret_network_constraints = {
Expand Down Expand Up @@ -259,17 +259,11 @@ def create_and_solve_lmp(self,
lmp_sced_instance = sced_instance.clone()

# In case of demand shortfall, the price skyrockets, so we threshold the value.
if 'load_mismatch_cost' not in lmp_sced_instance.data['system'] or \
lmp_sced_instance.data['system']['load_mismatch_cost'] > \
options.price_threshold:
lmp_sced_instance.data['system']['load_mismatch_cost'] = options.price_threshold

# In case of reserve shortfall, the price skyrockets, so we threshold the value.
if 'reserve_shortfall_cost' not in lmp_sced_instance.data['system'] or \
lmp_sced_instance.data['system']['reserve_shortfall_cost'] > \
options.reserve_price_threshold:
lmp_sced_instance.data['system']['reserve_shortfall_cost'] = \
options.reserve_price_threshold
system = lmp_sced_instance.data['system']
for system_key, threshold_value in self._p.get_attrs_to_price_option(options):
if threshold_value is not None and ((system_key not in system) or
(system[system_key] > threshold_value)):
system[system_key] = threshold_value

if self._last_sced_pyo_model is None:
self._ptdf_manager.mark_active(lmp_sced_instance)
Expand Down Expand Up @@ -314,23 +308,10 @@ def _transform_for_lmp(self, pyo_model, pyo_solver, lmp_sced_instance):
uc_instance_binary_relaxer(pyo_model, pyo_solver)

## reset the penalites
system = lmp_sced_instance.data['system']

update_obj = False

new_load_penalty = system['baseMVA'] * system['load_mismatch_cost']
if not math.isclose(new_load_penalty, pyo_model.LoadMismatchPenalty.value):
pyo_model.LoadMismatchPenalty.value = new_load_penalty
update_obj = True

new_reserve_penalty = system['baseMVA'] * system['reserve_shortfall_cost']
if not math.isclose(new_reserve_penalty, pyo_model.ReserveShortfallPenalty.value):
pyo_model.ReserveShortfallPenalty.value = new_reserve_penalty
update_obj = True

pyo_model.model_data = lmp_sced_instance
reset_unit_commitment_penalties(pyo_model)

if update_obj and isinstance(pyo_solver, PersistentSolver):
if isinstance(pyo_solver, PersistentSolver):
pyo_solver.set_objective(pyo_model.TotalCostObjective)

def _print_sced_info(self,
Expand Down Expand Up @@ -456,8 +437,8 @@ def _get_solver_list(name):
if not pe.SolverFactory(self._sced_solver).available():
raise RuntimeError(f"Solver {self._sced_solver} is not available to Pyomo")


def _print_persistence_warning(self, solver):
@staticmethod
def _print_persistence_warning(solver):
print(f"WARNING: Solver {solver} supports persistence, which "
"improves the performance of Prescient. Consider installing the "
f"python bindings for {solver}.")
Expand Down Expand Up @@ -487,6 +468,7 @@ def __init__(self, options: Options):
self.create_simulation_actuals = egret_plugin.create_simulation_actuals
self.solve_deterministic_day_ahead_pricing_problem = egret_plugin.solve_deterministic_day_ahead_pricing_problem
self._zero_out_costs = egret_plugin._zero_out_costs
self.get_attrs_to_price_option = egret_plugin.get_attrs_to_price_option

if options.simulator_plugin != None:
try:
Expand Down
Loading