Skip to content

Commit 2e36a83

Browse files
committed
Fix bug where 0 flow meant no constraint
1 parent 0570633 commit 2e36a83

File tree

2 files changed

+83
-57
lines changed

2 files changed

+83
-57
lines changed

switch_model/generators/core/dispatch.py

Lines changed: 81 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -729,16 +729,24 @@ def graph_total_dispatch(tools):
729729

730730
tools.bar_label()
731731

732+
732733
@graph(
733734
"energy_balance",
734735
title="Energy Balance For Every Month",
735736
supports_multi_scenario=True,
736-
is_long=True
737+
is_long=True,
737738
)
738739
def energy_balance(tools):
739740
# Get dispatch dataframe
740-
cols = ["timestamp", "gen_tech", "gen_energy_source", "DispatchGen_MW", "scenario_name", "scenario_index",
741-
"Curtailment_MW"]
741+
cols = [
742+
"timestamp",
743+
"gen_tech",
744+
"gen_energy_source",
745+
"DispatchGen_MW",
746+
"scenario_name",
747+
"scenario_index",
748+
"Curtailment_MW",
749+
]
742750
df = tools.get_dataframe("dispatch.csv", drop_scenario_info=False)[cols]
743751
df = tools.transform.gen_type(df)
744752

@@ -749,11 +757,16 @@ def energy_balance(tools):
749757
# Sum dispatch across all the projects of the same type and timepoint
750758
key_columns = ["timestamp", "gen_type", "scenario_name", "scenario_index"]
751759
df = df.groupby(key_columns, as_index=False).sum()
752-
df = df.melt(id_vars=key_columns, value_vars=["Dispatch", "Dispatch Limit"], var_name="Type")
760+
df = df.melt(
761+
id_vars=key_columns, value_vars=["Dispatch", "Dispatch Limit"], var_name="Type"
762+
)
753763
df = df.rename({"gen_type": "Source"}, axis=1)
754764

755-
discharge = df[(df["Source"] == "Storage") & (df["Type"] == "Dispatch")].drop(["Source", "Type"], axis=1).rename(
756-
{"value": "discharge"}, axis=1)
765+
discharge = (
766+
df[(df["Source"] == "Storage") & (df["Type"] == "Dispatch")]
767+
.drop(["Source", "Type"], axis=1)
768+
.rename({"value": "discharge"}, axis=1)
769+
)
757770

758771
# Get load dataframe
759772
load = tools.get_dataframe("load_balance.csv", drop_scenario_info=False)
@@ -764,23 +777,21 @@ def energy_balance(tools):
764777
load = load.groupby(key_columns, as_index=False).sum()
765778

766779
# Subtract storage dispatch from generation and add it to the storage charge to get net flow
767-
load = load.merge(
768-
discharge,
769-
how="left",
770-
on=key_columns,
771-
validate="one_to_one"
772-
)
780+
load = load.merge(discharge, how="left", on=key_columns, validate="one_to_one")
773781
load["ZoneTotalCentralDispatch"] -= load["discharge"]
774782
load["StorageNetCharge"] += load["discharge"]
775783
load = load.drop("discharge", axis=1)
776784

777785
# Rename and convert from wide to long format
778-
load = load.rename({
779-
"ZoneTotalCentralDispatch": "Total Generation (excl. storage discharge)",
780-
"TXPowerNet": "Transmission Losses",
781-
"StorageNetCharge": "Storage Net Flow",
782-
"zone_demand_mw": "Demand",
783-
}, axis=1).sort_index(axis=1)
786+
load = load.rename(
787+
{
788+
"ZoneTotalCentralDispatch": "Total Generation (excl. storage discharge)",
789+
"TXPowerNet": "Transmission Losses",
790+
"StorageNetCharge": "Storage Net Flow",
791+
"zone_demand_mw": "Demand",
792+
},
793+
axis=1,
794+
).sort_index(axis=1)
784795
load = load.melt(id_vars=key_columns, var_name="Source")
785796
load["Type"] = "Dispatch"
786797

@@ -796,26 +807,34 @@ def energy_balance(tools):
796807
FREQUENCY = "1W"
797808

798809
def groupby_time(df):
799-
return df.groupby([
800-
"scenario_name",
801-
"period",
802-
"Source",
803-
"Type",
804-
tools.pd.Grouper(key="datetime", freq=FREQUENCY, origin="start")
805-
])["value"]
810+
return df.groupby(
811+
[
812+
"scenario_name",
813+
"period",
814+
"Source",
815+
"Type",
816+
tools.pd.Grouper(key="datetime", freq=FREQUENCY, origin="start"),
817+
]
818+
)["value"]
806819

807820
df = groupby_time(df).sum().reset_index()
808821

809822
# Get the state of charge data
810-
soc = tools.get_dataframe("StateOfCharge.csv", dtype={"STORAGE_GEN_TPS_1": str}, drop_scenario_info=False)
811-
soc = soc.rename({"STORAGE_GEN_TPS_2": "timepoint", "StateOfCharge": "value"}, axis=1)
823+
soc = tools.get_dataframe(
824+
"StateOfCharge.csv", dtype={"STORAGE_GEN_TPS_1": str}, drop_scenario_info=False
825+
)
826+
soc = soc.rename(
827+
{"STORAGE_GEN_TPS_2": "timepoint", "StateOfCharge": "value"}, axis=1
828+
)
812829
# Sum over all the projects that are in the same scenario with the same timepoint
813830
soc = soc.groupby(["timepoint", "scenario_name"], as_index=False).sum()
814831
soc["Source"] = "State Of Charge"
815832
soc["value"] /= 1e6 # Convert to TWh
816833

817834
# Group by time
818-
soc = tools.transform.timestamp(soc, use_timepoint=True, key_col="timepoint").astype({"period": str})
835+
soc = tools.transform.timestamp(
836+
soc, use_timepoint=True, key_col="timepoint"
837+
).astype({"period": str})
819838
soc["Type"] = "Dispatch"
820839
soc = groupby_time(soc).mean().reset_index()
821840

@@ -827,35 +846,47 @@ def groupby_time(df):
827846
# Plot
828847
# Get the colors for the lines
829848
colors = tools.get_colors()
830-
colors.update({
831-
"Transmission Losses": "brown",
832-
"Storage Net Flow": "cadetblue",
833-
"Demand": "black",
834-
"Total Generation (excl. storage discharge)": "black",
835-
"State Of Charge": "green"
836-
})
849+
colors.update(
850+
{
851+
"Transmission Losses": "brown",
852+
"Storage Net Flow": "cadetblue",
853+
"Demand": "black",
854+
"Total Generation (excl. storage discharge)": "black",
855+
"State Of Charge": "green",
856+
}
857+
)
837858

838859
# plot
839860
num_periods = df["period"].nunique()
840861
pn = tools.pn
841-
plot = pn.ggplot(df) + \
842-
pn.geom_line(pn.aes(x="day", y="value", color="Source", linetype="Type")) + \
843-
pn.facet_grid("period ~ scenario_name") + \
844-
pn.labs(y="Contribution to Energy Balance (TWh)") + \
845-
pn.scales.scale_color_manual(values=colors, aesthetics="color", na_value=colors["Other"]) + \
846-
pn.scales.scale_x_continuous(
847-
name="Month",
848-
labels=["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"],
849-
breaks=(15, 46, 76, 106, 137, 167, 198, 228, 259, 289, 319, 350),
850-
limits=(0, 366)) + \
851-
pn.scales.scale_linetype_manual(
852-
values={"Dispatch Limit": "dotted", "Dispatch": "solid"}
853-
) + \
854-
pn.theme(
855-
figure_size=(pn.options.figure_size[0] * tools.num_scenarios, pn.options.figure_size[1] * num_periods))
862+
plot = (
863+
pn.ggplot(df)
864+
+ pn.geom_line(pn.aes(x="day", y="value", color="Source", linetype="Type"))
865+
+ pn.facet_grid("period ~ scenario_name")
866+
+ pn.labs(y="Contribution to Energy Balance (TWh)")
867+
+ pn.scales.scale_color_manual(
868+
values=colors, aesthetics="color", na_value=colors["Other"]
869+
)
870+
+ pn.scales.scale_x_continuous(
871+
name="Month",
872+
labels=["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"],
873+
breaks=(15, 46, 76, 106, 137, 167, 198, 228, 259, 289, 319, 350),
874+
limits=(0, 366),
875+
)
876+
+ pn.scales.scale_linetype_manual(
877+
values={"Dispatch Limit": "dotted", "Dispatch": "solid"}
878+
)
879+
+ pn.theme(
880+
figure_size=(
881+
pn.options.figure_size[0] * tools.num_scenarios,
882+
pn.options.figure_size[1] * num_periods,
883+
)
884+
)
885+
)
856886

857887
tools.save_figure(plot.draw())
858888

889+
859890
@graph(
860891
"curtailment_per_period",
861892
title="Percent of total dispatchable capacity curtailed",

switch_model/generators/extensions/hydro_simple.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,7 @@ def define_components(mod):
171171
)
172172

173173
mod.hydro_avg_flow_mw = Param(
174-
mod.HYDRO_GEN_TS_RAW,
175-
within=NonNegativeReals,
176-
input_file="hydro_timeseries.csv",
177-
default=0.0,
174+
mod.HYDRO_GEN_TS_RAW, within=NonNegativeReals, input_file="hydro_timeseries.csv"
178175
)
179176

180177
# We use a scaling factor to improve the numerical properties
@@ -184,9 +181,7 @@ def define_components(mod):
184181
enforce_hydro_avg_flow_scaling_factor = 1e1
185182
mod.Enforce_Hydro_Avg_Flow = Constraint(
186183
mod.HYDRO_GEN_TS,
187-
rule=lambda m, g, hts: Constraint.Skip
188-
if m.hydro_avg_flow_mw[g, hts] == 0
189-
else enforce_hydro_avg_flow_scaling_factor *
184+
rule=lambda m, g, hts: enforce_hydro_avg_flow_scaling_factor *
190185
# Compute the weighted average of the dispatch
191186
sum(m.DispatchGen[g, t] * m.tp_weight[t] for t in m.TPS_IN_HTS[hts])
192187
/ sum(m.tp_weight[tp] for tp in m.TPS_IN_HTS[hts])

0 commit comments

Comments
 (0)