Skip to content

Commit 72b126d

Browse files
committed
Create state of charge plot
1 parent 3919b35 commit 72b126d

File tree

2 files changed

+69
-19
lines changed

2 files changed

+69
-19
lines changed

papers/Martin_Staadecker_Value_of_LDES_and_Factors/LDES_paper_graphs/Figure Costs.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,3 +182,15 @@
182182
ax.set_title("B. Estimated LMP by region")
183183
# %%
184184
fig.tight_layout()
185+
186+
# %% night time vs day time
187+
df = daily_lmp.divide(daily_lmp["Noon"], axis=0) * 100 - 100
188+
df.min()
189+
df.max()
190+
# %% average drop in daily duals
191+
df = daily_lmp.mean(axis=1)
192+
df / df.iloc[0] - 1
193+
# daily_lmp / daily_lmp.iloc[0] - 1
194+
# %% night time drop
195+
df = daily_lmp[["Midnight", "8pm", "4am"]].mean(axis=1)
196+
(1 - df.loc[3] / df.iloc[0]) * 100 / ((3 - 1.94) * 10)

papers/Martin_Staadecker_Value_of_LDES_and_Factors/LDES_paper_graphs/Figure impact of LDES on grid.py

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
# %% GET TOOLS
22

33
# Imports
4+
import matplotlib.gridspec
45
import matplotlib.pyplot as plt
56
import pandas as pd
7+
from matplotlib import cm
68
from matplotlib.ticker import PercentFormatter
9+
from matplotlib.colors import Normalize
710

811
from papers.Martin_Staadecker_Value_of_LDES_and_Factors.LDES_paper_graphs.util import (
912
set_style,
1013
get_set_e_scenarios,
1114
)
1215
from switch_model.tools.graph.main import GraphTools
1316

14-
1517
# Prepare graph tools
1618
tools = GraphTools(scenarios=get_set_e_scenarios())
1719
tools.pre_graphing(multi_scenario=True)
@@ -21,10 +23,10 @@
2123
plt.close()
2224
fig = plt.figure()
2325
fig.set_size_inches(12, 12)
24-
ax1 = fig.add_subplot(2, 2, 1)
25-
ax2 = fig.add_subplot(2, 2, 2)
26-
ax3 = fig.add_subplot(2, 2, 3)
27-
ax4 = fig.add_subplot(2, 2, 4)
26+
gs = matplotlib.gridspec.GridSpec(2, 2, figure=fig)
27+
ax1 = fig.add_subplot(gs[0, 0])
28+
ax2 = fig.add_subplot(gs[0, 1])
29+
ax3 = fig.add_subplot(gs[1, :])
2830

2931
# %% IMPACT ON TX AND GEN
3032

@@ -131,11 +133,58 @@
131133
ax.set_xlabel("WECC-wide storage capacity (TWh)")
132134
ax.set_title("A. Impact of LDES on curtailment")
133135
ax.tick_params(top=False, bottom=False, right=False, left=False)
134-
# %%
135-
plt.subplots_adjust(
136-
hspace=0.2, wspace=0.25, left=0.07, right=0.97, top=0.95, bottom=0.07
136+
# %% State of charge
137+
ax = ax3
138+
ax.clear()
139+
140+
freq = "1D"
141+
142+
state_of_charge = tools.get_dataframe("StateOfCharge.csv")
143+
state_of_charge = state_of_charge.rename(
144+
{"STORAGE_GEN_TPS_2": "timepoint", "StateOfCharge": "value"}, axis=1
145+
)
146+
state_of_charge = state_of_charge.groupby(
147+
["scenario_name", "timepoint"], as_index=False
148+
).value.sum()
149+
state_of_charge.value *= 1e-6 # Convert from MWh to TWh
150+
state_of_charge = tools.transform.timestamp(state_of_charge, use_timepoint=True)
151+
state_of_charge = state_of_charge.set_index("datetime")
152+
state_of_charge = state_of_charge.groupby("scenario_name").resample(freq).value.mean()
153+
state_of_charge = state_of_charge.unstack("scenario_name").rename_axis(
154+
"Storage Capacity (TWh)", axis=1
137155
)
138156

157+
demand = tools.get_dataframe("loads.csv", from_inputs=True).rename(
158+
{"TIMEPOINT": "timepoint", "zone_demand_mw": "value"}, axis=1
159+
)
160+
demand = demand[demand.scenario_name == 1.94]
161+
demand = demand.groupby("timepoint", as_index=False).value.sum()
162+
demand = tools.transform.timestamp(demand, use_timepoint=True)
163+
demand = demand.set_index("datetime")["value"]
164+
demand = demand.resample(freq).mean()
165+
demand = demand * 60 / demand.max()
166+
167+
state_of_charge.plot(
168+
ax=ax,
169+
cmap="viridis",
170+
ylabel="WECC-wide stored energy (TWh, 24h mean)",
171+
xlabel="Time of year",
172+
legend=False,
173+
)
174+
plt.colorbar(
175+
cm.ScalarMappable(norm=Normalize(1.94, 64), cmap="viridis"),
176+
ax=ax,
177+
label="Storage Capacity (TWh)",
178+
fraction=0.1,
179+
)
180+
181+
lines = ax.plot(demand, c="dimgray", linestyle="--", alpha=0.5)
182+
ax.legend(lines, ["Demand"])
183+
184+
ax.set_title("C. State of charge throughout the year")
185+
# %%
186+
plt.tight_layout()
187+
139188
# %% CALCULATIONS
140189
cap_total = cap["Solar"] + cap["Wind"]
141190
1 - (cap_total / cap_total.iloc[0])
@@ -153,14 +202,3 @@
153202
# %% transmission
154203
tx / tx.iloc[0] * 100
155204
(3 - 1.94) * 1000 / ((1 - tx.loc[3] / tx.iloc[0]) * 100)
156-
# %% night time vs day time
157-
df = daily_lmp.divide(daily_lmp["Noon"], axis=0) * 100 - 100
158-
df.min()
159-
df.max()
160-
# %% average drop in daily duals
161-
df = daily_lmp.mean(axis=1)
162-
df / df.iloc[0] - 1
163-
# daily_lmp / daily_lmp.iloc[0] - 1
164-
# %% night time drop
165-
df = daily_lmp[["Midnight", "8pm", "4am"]].mean(axis=1)
166-
(1 - df.loc[3] / df.iloc[0]) * 100 / ((3 - 1.94) * 10)

0 commit comments

Comments
 (0)