Skip to content

Commit b8aa8cd

Browse files
committed
Add num_sim_days as input arg
This change allows more flexibility when creating input files.
1 parent 5cd50b3 commit b8aa8cd

File tree

5 files changed

+33
-17
lines changed

5 files changed

+33
-17
lines changed

scripts/run_quickstart.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def main():
1212
input_folder = "..//model_library"
1313
output_folder = "..//temptemp"
1414

15-
model_name = "solar_ess"
15+
model_name = "dummy"
1616
model_year = 2016
1717

1818
# Simulation parameters

src/pownet/core/data_processor.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,9 +285,10 @@ def _create_derate_factors(
285285
else:
286286
return
287287

288+
num_hrs_in_year = 8760
288289
temp_df = pd.DataFrame(
289290
derate_factor,
290-
index=range(0, 8760), # Consider making 8760 a constant or parameter
291+
index=range(0, num_hrs_in_year),
291292
columns=units,
292293
)
293294
setattr(

src/pownet/core/input.py

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ def __init__(
2020
model_name: str,
2121
year: int,
2222
sim_horizon: int,
23+
num_sim_days: int = 365,
2324
use_spin_var: bool = True,
2425
dc_opf: str = "kirchhoff",
2526
spin_reserve_factor: float = 0.15,
@@ -36,6 +37,10 @@ def __init__(
3637
self.model_dir: str = os.path.join(input_folder, model_name)
3738
self.year: int = year
3839
self.sim_horizon: int = sim_horizon
40+
41+
self.num_sim_days: int = num_sim_days
42+
self.num_sim_hours: int = num_sim_days * 24
43+
3944
self.use_spin_var: bool = use_spin_var
4045

4146
# The timestamp is used to create a unique folder for the model
@@ -433,9 +438,11 @@ def _load_contract_costs(self):
433438
"contract_cost.csv", header_levels=0
434439
)
435440

436-
# Check that the contract costs timeseries is of length 8760
437-
if len(contract_costs_df) not in [0, 8760]:
438-
raise ValueError("PowNet: Marginal cost timeseries must be of length 8760.")
441+
# Check that the contract costs timeseries is of length num_sim_hours
442+
if len(contract_costs_df) not in [0, self.num_sim_hours]:
443+
raise ValueError(
444+
f"PowNet: Marginal cost timeseries must be of length {self.num_sim_hours}."
445+
)
439446

440447
self.contract_costs = {
441448
(col, idx): value
@@ -517,7 +524,7 @@ def _create_timeseries_of_edges(self, data: list, column_name: str) -> pd.DataFr
517524
columns=[column_name],
518525
).T
519526
# Repeat values for every hour of the year
520-
df = df.loc[df.index.repeat(365 * 24)].reset_index(drop=True)
527+
df = df.loc[df.index.repeat(self.num_sim_hours)].reset_index(drop=True)
521528
df.index += 1
522529
return df
523530

@@ -699,7 +706,7 @@ def load_data(self):
699706
#################
700707
if self.spin_reserve_mw is not None:
701708
self.spin_requirement = pd.Series(
702-
self.spin_reserve_mw, index=range(1, 8761)
709+
self.spin_reserve_mw, index=range(1, self.num_sim_hours + 1)
703710
)
704711
else:
705712
self.spin_requirement = self.demand.sum(axis=1) * self.spin_reserve_factor
@@ -782,8 +789,10 @@ def check_data(self):
782789
# Timeseries have the correct length
783790
##################################
784791

785-
if len(self.demand) != 8760:
786-
raise ValueError("PowNet: Demand timeseries must be of length 8760.")
792+
if len(self.demand) != self.num_sim_hours:
793+
raise ValueError(
794+
f"PowNet: Demand timeseries must be of length {self.num_sim_hours} but got {len(self.demand)}."
795+
)
787796

788797
attrs_to_check = [
789798
"solar_capacity",
@@ -795,12 +804,14 @@ def check_data(self):
795804
]
796805
for attr in attrs_to_check:
797806
temp_df = getattr(self, attr)
798-
if (not temp_df.empty) and (len(temp_df) != 8760):
799-
raise ValueError(f"PowNet: {attr} must be of length 8760.")
807+
if (not temp_df.empty) and (len(temp_df) != self.num_sim_hours):
808+
raise ValueError(
809+
f"PowNet: {attr} must be of length {self.num_sim_hours} but got {len(temp_df)}."
810+
)
800811

801-
if len(self.daily_hydro_capacity) not in [0, 365]:
812+
if len(self.daily_hydro_capacity) not in [0, self.num_sim_days]:
802813
raise ValueError(
803-
"PowNet: Daily hydropower timeseries must be of length 365."
814+
f"PowNet: Daily hydropower timeseries must be of length {self.num_sim_days}."
804815
)
805816

806817
##################################
@@ -941,6 +952,7 @@ def print_summary(self):
941952
942953
---- Modeling parameters ----
943954
{'Simulation horizon':<25} = {self.sim_horizon} hours
955+
{'Number of simulation days':<25} = {self.num_sim_days}
944956
{'Use spin variable':<25} = {self.use_spin_var}
945957
{'Power flow':<25} = {self.dc_opf}
946958
{'Spin reserve factor:':<25} = {self.spin_reserve_factor if self.spin_reserve_mw is None else 'Use an absolute value in MW.'}

src/pownet/core/simulation.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ def run(
7575
self,
7676
sim_horizon: int,
7777
steps_to_run: int,
78+
num_sim_days: int = 365,
7879
to_process_inputs: bool = True,
7980
solver: str = "gurobi",
8081
log_to_console: bool = True,
@@ -101,7 +102,7 @@ def run(
101102
"""
102103

103104
if steps_to_run is None:
104-
steps_to_run = 365 - (sim_horizon // 24 - 1)
105+
steps_to_run = num_sim_days - (sim_horizon // 24 - 1)
105106

106107
# To create files with "pownet_" prefix
107108
if to_process_inputs:
@@ -118,6 +119,7 @@ def run(
118119
model_name=self.model_name,
119120
year=self.model_year,
120121
sim_horizon=sim_horizon,
122+
num_sim_days=num_sim_days,
121123
use_spin_var=self.use_spin_var,
122124
dc_opf=self.dc_opf,
123125
spin_reserve_factor=self.spin_reserve_factor,
@@ -130,6 +132,7 @@ def run(
130132
)
131133
# Produce an error if the data is not making sense
132134
self.inputs.load_and_check_data()
135+
self.inputs.print_summary()
133136

134137
####################### Simulation
135138
self.system_record = SystemRecord(self.inputs)

src/pownet/data_utils.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@
1212
from .folder_utils import get_database_dir
1313

1414

15-
def get_dates(year):
15+
def get_dates(year, num_days=365):
1616
"""Return a dataframe of dates for the given year. The dataframe will have
1717
365 rows, one for each day of the year. The columns are 'date' and 'hour'.
1818
Exclude 29th February.
1919
"""
2020
# Create dates to concatenate with the new dataframes
2121
dates = pd.DataFrame(
22-
{"date": pd.date_range(start=str(year), periods=366, freq="D")}
22+
{"date": pd.date_range(start=str(year), periods=num_days + 1, freq="D")}
2323
)
2424
# Remove 29th Feb because we do not deal with them
2525
dates = dates.loc[dates.date.dt.strftime("%m-%d") != "02-29"]
@@ -28,7 +28,7 @@ def get_dates(year):
2828

2929
# In case we need three columns: date, hour, and day
3030
dates = dates.loc[dates.index.repeat(24)]
31-
dates["hour"] = np.tile(range(1, 25), 365)
31+
dates["hour"] = np.tile(range(1, 25), num_days)
3232
dates = dates.reset_index(drop=True)
3333
return dates
3434

0 commit comments

Comments
 (0)