Skip to content

Commit 91394f4

Browse files
committed
fix(hydro): weekly_hydro_budget_min now optional
1 parent 92bf1e6 commit 91394f4

File tree

3 files changed

+209
-149
lines changed

3 files changed

+209
-149
lines changed

scripts/run_hydrochipps.py

Lines changed: 129 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#%%
12
import os
23
from pownet.core import Simulator, DataProcessor, OutputProcessor
34

@@ -46,136 +47,137 @@
4647
output_processor = OutputProcessor()
4748
hourly_demand = output_processor.get_hourly_demand(simulator.inputs.demand)
4849

49-
## old code
50-
# #%%
51-
# import os
52-
# from datetime import datetime
53-
# from pownet.core import (
54-
# DataProcessor,
55-
# SystemInput,
56-
# ModelBuilder,
57-
# SystemRecord,
58-
# OutputProcessor,
59-
# Visualizer,
60-
# )
61-
# from pownet.data_utils import create_init_condition
62-
#
63-
# scen_path = ".\\model_library"
64-
# ##### User inputs #####
65-
# to_process_inputs = True
66-
# sim_horizon = 24*7
67-
# model_name = "cumberland"
68-
# steps_to_run = 3 # Default is None
69-
# do_plot = True
70-
# #######################
71-
#
72-
# if to_process_inputs:
73-
# data_processor = DataProcessor(
74-
# input_folder=scen_path, model_name=model_name, year=2016, frequency=50
75-
# )
76-
# data_processor.execute_data_pipeline()
77-
#
78-
# inputs = SystemInput(
79-
# input_folder=scen_path,
80-
# model_name=model_name,
81-
# year=2016,
82-
# sim_horizon=sim_horizon,
83-
# spin_reserve_factor=0,
84-
# load_shortfall_penalty_factor=1000,
85-
# load_curtail_penalty_factor=1,
86-
# spin_shortfall_penalty_factor=1000,
87-
# line_capacity_factor=1,
88-
# line_loss_factor=0
89-
# )
90-
# inputs.load_and_check_data()
91-
#
92-
#
93-
# model_builder = ModelBuilder(inputs)
94-
# record = SystemRecord(inputs)
95-
#
96-
# build_times = []
97-
# opt_times = []
98-
# objvals = []
99-
# init_conditions = create_init_condition(inputs.thermal_units) # init conditions should be empty dict if we dont have any thermal generators
100-
#
101-
# if steps_to_run is None:
102-
# steps_to_run = 10 # 365 - (sim_horizon // 24 - 1)
103-
#
104-
# start_day = 1
105-
# for step_k in range(start_day, steps_to_run):
106-
# start_time = datetime.now()
107-
# if step_k == start_day:
108-
# power_system_model = model_builder.build(
109-
# step_k=step_k,
110-
# init_conds=init_conditions,
111-
# )
112-
# else:
113-
# power_system_model = model_builder.update(
114-
# step_k=step_k,
115-
# init_conds=init_conditions,
116-
# )
117-
# build_times.append((datetime.now() - start_time).total_seconds())
118-
#
119-
# power_system_model.model.write(str(step_k) + '.lp')
120-
# power_system_model.optimize(mipgap=0.001)
121-
#
122-
# # Raise an error if the model is not feasible
123-
# if not power_system_model.check_feasible():
124-
# raise ValueError("Model is not feasible.")
125-
#
126-
# objvals.append(power_system_model.get_objval())
127-
# opt_times.append(power_system_model.get_runtime())
128-
#
129-
# record.keep(
130-
# runtime=power_system_model.get_runtime(),
131-
# objval=power_system_model.get_objval(),
132-
# solution=power_system_model.get_solution(),
133-
# lmp=power_system_model.solve_for_lmp(),
134-
# step_k=step_k,
135-
# )
136-
# init_conditions = record.get_init_conds()
137-
#
138-
# import os
50+
# old code
51+
#%%
52+
import os
53+
from datetime import datetime
54+
from pownet.core import (
55+
DataProcessor,
56+
Simulator,
57+
ModelBuilder,
58+
SystemRecord,
59+
OutputProcessor,
60+
Visualizer,
61+
)
62+
from pownet import SystemInput
63+
from pownet.data_utils import create_init_condition
64+
65+
scen_path = ".\\model_library"
66+
##### User inputs #####
67+
to_process_inputs = True
68+
sim_horizon = 24*7
69+
model_name = "cumberland"
70+
steps_to_run = 3 # Default is None
71+
do_plot = True
72+
#######################
73+
74+
if to_process_inputs:
75+
data_processor = DataProcessor(
76+
input_folder=scen_path, model_name=model_name, year=2016, frequency=50
77+
)
78+
data_processor.execute_data_pipeline()
79+
80+
inputs = SystemInput(
81+
input_folder=scen_path,
82+
model_name=model_name,
83+
year=2016,
84+
sim_horizon=sim_horizon,
85+
spin_reserve_factor=0,
86+
load_shortfall_penalty_factor=1000,
87+
load_curtail_penalty_factor=1,
88+
spin_shortfall_penalty_factor=1000,
89+
line_capacity_factor=1,
90+
line_loss_factor=0
91+
)
92+
inputs.load_and_check_data()
93+
94+
95+
model_builder = ModelBuilder(inputs)
96+
record = SystemRecord(inputs)
97+
98+
build_times = []
99+
opt_times = []
100+
objvals = []
101+
init_conditions = create_init_condition(inputs.thermal_units) # init conditions should be empty dict if we dont have any thermal generators
102+
103+
if steps_to_run is None:
104+
steps_to_run = 10 # 365 - (sim_horizon // 24 - 1)
105+
106+
start_day = 1
107+
for step_k in range(start_day, steps_to_run):
108+
start_time = datetime.now()
109+
if step_k == start_day:
110+
power_system_model = model_builder.build(
111+
step_k=step_k,
112+
init_conds=init_conditions,
113+
)
114+
else:
115+
power_system_model = model_builder.update(
116+
step_k=step_k,
117+
init_conds=init_conditions,
118+
)
119+
build_times.append((datetime.now() - start_time).total_seconds())
120+
121+
# power_system_model.model.write(str(step_k) + '.lp')
122+
power_system_model.optimize(mipgap=0.001)
123+
124+
# Raise an error if the model is not feasible
125+
if not power_system_model.check_feasible():
126+
raise ValueError("Model is not feasible.")
127+
128+
objvals.append(power_system_model.get_objval())
129+
opt_times.append(power_system_model.get_runtime())
130+
131+
record.keep(
132+
runtime=power_system_model.get_runtime(),
133+
objval=power_system_model.get_objval(),
134+
solution=power_system_model.get_solution(),
135+
lmp=power_system_model.solve_for_lmp(),
136+
step_k=step_k,
137+
)
138+
init_conditions = record.get_init_conds()
139+
140+
import os
141+
output_folder = ".//outputs"
142+
if not os.path.exists(output_folder):
143+
os.makedirs(output_folder)
144+
record.write_simulation_results(output_folder)
145+
146+
147+
139148
# output_folder = ".//outputs"
140149
# if not os.path.exists(output_folder):
141150
# os.makedirs(output_folder)
142-
# record.write_simulation_results(output_folder)
143-
#
144-
#
145-
#
146-
# # output_folder = ".//outputs"
147-
# # if not os.path.exists(output_folder):
148-
# # os.makedirs(output_folder)
149-
# # results.write_results(output_folder)
150-
#
151-
# import pandas as pd
152-
# # Process the results
153-
# output_processor = OutputProcessor()
154-
# output_processor.load(inputs=inputs)
155-
# # output_processor = OutputProcessor(inputs)
156-
# node_var_df = record.get_node_variables()
157-
# output_processor.get_hourly_generation(node_var_df)
158-
# # output_processor.load_from_dataframe(node_var_df)
159-
#
160-
# output_processor.get_thermal_unit_hourly_dispatch(node_var_df)
161-
# a = output_processor.get_unit_hourly_generation(node_var_df)
162-
# # Visualize the results
163-
# if do_plot:
164-
# visualizer = Visualizer(inputs.model_id)
165-
# if steps_to_run <= 7:
166-
# visualizer.plot_fuelmix_bar(
167-
# dispatch=output_processor.get_hourly_generation(node_var_df),
168-
# demand=output_processor.get_hourly_demand(inputs.demand),
169-
# )
170-
# visualizer.plot_lmp(record.lmp_df)
171-
# else:
172-
# visualizer = Visualizer(inputs.model_id)
173-
# visualizer.plot_fuelmix_area(
174-
# dispatch=output_processor.get_daily_dispatch(),
175-
# demand=output_processor.get_daily_demand(),
176-
# )
177-
#
178-
#
151+
# results.write_results(output_folder)
152+
153+
import pandas as pd
154+
# Process the results
155+
output_processor = OutputProcessor()
156+
output_processor.load(inputs=inputs)
157+
# output_processor = OutputProcessor(inputs)
158+
node_var_df = record.get_node_variables()
159+
output_processor.get_hourly_generation(node_var_df)
160+
# output_processor.load_from_dataframe(node_var_df)
161+
162+
output_processor.get_thermal_unit_hourly_dispatch(node_var_df)
163+
a = output_processor.get_unit_hourly_generation(node_var_df)
164+
# Visualize the results
165+
if do_plot:
166+
visualizer = Visualizer(inputs.model_id)
167+
if steps_to_run <= 7:
168+
visualizer.plot_fuelmix_bar(
169+
dispatch=output_processor.get_hourly_generation(node_var_df),
170+
demand=output_processor.get_hourly_demand(inputs.demand),
171+
)
172+
visualizer.plot_lmp(record.lmp_df)
173+
else:
174+
visualizer = Visualizer(inputs.model_id)
175+
visualizer.plot_fuelmix_area(
176+
dispatch=output_processor.get_daily_dispatch(),
177+
demand=output_processor.get_daily_demand(),
178+
)
179+
180+
179181
# # Save other modeling statistics
180182
# import os
181183
# from pownet.folder_utils import get_output_dir

src/pownet/builder/hydro.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,17 +168,26 @@ def add_constraints(self, step_k: int, init_conds: dict, **kwargs) -> None:
168168
hydro_capacity=self.inputs.daily_hydro_capacity,
169169
)
170170

171-
# Weekly lower and upper bounds
171+
# Weekly upper bounds
172172
self.c_hydro_limit_weekly = nondispatch_constr.add_c_hydro_limit_weekly(
173173
model=self.model,
174174
phydro=self.phydro,
175175
step_k=step_k,
176176
sim_horizon=self.inputs.sim_horizon,
177177
hydro_units=self.inputs.weekly_hydro_unit_node.keys(),
178178
hydro_capacity=self.inputs.weekly_hydro_capacity,
179-
hydro_capacity_min=self.inputs.hydro_min_capacity,
180179
)
181180

181+
if not self.inputs.hydro_min_capacity.empty:
182+
self.c_hydro_limit_weekly_lb = nondispatch_constr.add_c_hydro_limit_weekly_lb(
183+
model=self.model,
184+
phydro=self.phydro,
185+
step_k=step_k,
186+
sim_horizon=self.inputs.sim_horizon,
187+
hydro_units=self.inputs.weekly_hydro_unit_node.keys(),
188+
hydro_capacity_min=self.inputs.hydro_min_capacity,
189+
)
190+
182191
if self.inputs.use_nondispatch_status_var:
183192
self.c_link_hydro_pu = nondispatch_constr.add_c_link_unit_pu(
184193
model=self.model,
@@ -227,9 +236,20 @@ def update_constraints(self, step_k: int, init_conds: dict, **kwargs) -> None:
227236
sim_horizon=self.inputs.sim_horizon,
228237
hydro_units=self.inputs.weekly_hydro_unit_node.keys(),
229238
hydro_capacity=self.inputs.weekly_hydro_capacity,
230-
hydro_capacity_min=self.inputs.hydro_min_capacity,
239+
# hydro_capacity_min=self.inputs.hydro_min_capacity,
231240
)
232241

242+
if not self.inputs.hydro_min_capacity.empty:
243+
self.model.remove(self.c_hydro_limit_weekly_lb)
244+
self.c_hydro_limit_weekly_lb = nondispatch_constr.add_c_hydro_limit_weekly_lb(
245+
model=self.model,
246+
phydro=self.phydro,
247+
step_k=step_k,
248+
sim_horizon=self.inputs.sim_horizon,
249+
hydro_units=self.inputs.weekly_hydro_unit_node.keys(),
250+
hydro_capacity_min=self.inputs.hydro_min_capacity,
251+
)
252+
233253
def update_daily_hydropower_capacity(
234254
self, step_k: int, new_capacity: dict[tuple[str, int], float]
235255
) -> None:

0 commit comments

Comments
 (0)