Skip to content

Commit

Permalink
Merge pull request #431 from agoenergy/415-add-storage-capacity-and-s…
Browse files Browse the repository at this point in the history
…torage-costs-to-optimization-results-table

415 add storage capacity and storage costs to optimization results table
  • Loading branch information
markushal authored Jun 10, 2024
2 parents 822179e + 175fbfb commit 355fb81
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 27 deletions.
15 changes: 10 additions & 5 deletions app/plot_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -616,29 +616,34 @@ def create_profile_figure_generation(df_sel: pd.DataFrame) -> go.Figure:
fig = go.Figure()

add_trace_to_figure(
df_sel, fig, component="PV tilted", parameter="Power", fill=True, color="yellow"
df_sel,
fig,
component="PV tilted",
parameter="Power",
fill=True,
color="#FFE000",
)
add_trace_to_figure(
df_sel,
fig,
component="Wind onshore",
parameter="Power",
fill=True,
color="blue",
color="#1E78C2",
)
add_trace_to_figure(
df_sel,
fig,
component="Wind offshore",
parameter="Power",
fill=True,
color="blue",
color="#0061A4",
)
add_trace_to_figure(
df_sel, fig, component="Electrolyzer", parameter="Power", color="black"
df_sel, fig, component="Electrolyzer", parameter="Power", color="#0C0C0C"
)
add_trace_to_figure(
df_sel, fig, component="Derivate production", parameter="Power", color="red"
df_sel, fig, component="Derivate production", parameter="Power", color="#408B2E"
)

add_vertical_lines(fig)
Expand Down
63 changes: 42 additions & 21 deletions app/tab_optimization.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
"""Content of optimization tab."""
import numpy as np
import pandas as pd
import pypsa
import streamlit as st
Expand Down Expand Up @@ -57,8 +58,8 @@ def content_optimization(api: PtxboaAPI) -> None:
res,
use_container_width=True,
column_config={
"Capacity (kW)": st.column_config.NumberColumn(format="%.1f"),
"Output (kWh/a)": st.column_config.NumberColumn(format="%.0f"),
"Capacity (MW)": st.column_config.NumberColumn(format="%.1f"),
"Output (MWh/a)": st.column_config.NumberColumn(format="%.0f"),
"Full load hours (h)": st.column_config.NumberColumn(format="%.0f"),
"Curtailment (%)": st.column_config.NumberColumn(format="%.1f %%"),
"Cost (USD/MWh)": st.column_config.NumberColumn(format="%.1f"),
Expand Down Expand Up @@ -108,32 +109,32 @@ def calc_aggregate_statistics(
"WIND-OFF",
]:
if g in n.generators.index:
res.at[g, "Capacity (kW)"] = n.generators.at[g, "p_nom_opt"]
res.at[g, "Output (kWh/a)"] = (
res.at[g, "Capacity (MW)"] = n.generators.at[g, "p_nom_opt"]
res.at[g, "Output (MWh/a)"] = (
n.generators_t["p"][g] * n.snapshot_weightings["generators"]
).sum()
res.at[g, "CAPEX (USD/kW)"] = n.generators.at[g, "capital_cost"]
res.at[g, "OPEX (USD/kWh)"] = n.generators.at[g, "marginal_cost"]
res.at[g, "Full load hours before curtailment (h)"] = (
n.generators_t["p_max_pu"][g] * n.snapshot_weightings["generators"]
).sum()
res.at[g, "Curtailment (kWh/a)"] = (
res.at[g, "Capacity (kW)"]
res.at[g, "Curtailment (MWh/a)"] = (
res.at[g, "Capacity (MW)"]
* res.at[g, "Full load hours before curtailment (h)"]
- res.at[g, "Output (kWh/a)"]
- res.at[g, "Output (MWh/a)"]
)
res.at[g, "Curtailment (%)"] = (
100
* res.at[g, "Curtailment (kWh/a)"]
/ (res.at[g, "Output (kWh/a)"] + res.at[g, "Curtailment (kWh/a)"])
* res.at[g, "Curtailment (MWh/a)"]
/ (res.at[g, "Output (MWh/a)"] + res.at[g, "Curtailment (MWh/a)"])
)

for g in ["ELY", "DERIV", "H2_STR_in"]:
if g in n.links.index:
res.at[g, "Capacity (kW)"] = (
res.at[g, "Capacity (MW)"] = (
n.links.at[g, "p_nom_opt"] * n.links.at[g, "efficiency"]
)
res.at[g, "Output (kWh/a)"] = (
res.at[g, "Output (MWh/a)"] = (
-n.links_t["p1"][g] * n.snapshot_weightings["generators"]
).sum()
res.at[g, "CAPEX (USD/kW)"] = (
Expand All @@ -143,8 +144,8 @@ def calc_aggregate_statistics(

for g in ["EL_STR"]:
if g in n.storage_units.index:
res.at[g, "Capacity (kW)"] = n.storage_units.at[g, "p_nom_opt"]
res.at[g, "Output (kWh/a)"] = (
res.at[g, "Capacity (MW)"] = n.storage_units.at[g, "p_nom_opt"]
res.at[g, "Output (MWh/a)"] = (
n.storage_units_t["p_dispatch"][g] * n.snapshot_weightings["generators"]
).sum()
res.at[g, "CAPEX (USD/kW)"] = n.storage_units.at[g, "capital_cost"]
Expand All @@ -157,25 +158,23 @@ def calc_aggregate_statistics(
"N2-G_supply",
]:
if g in n.generators.index:
res.at[g, "Output (kWh/a)"] = (
res.at[g, "Output (MWh/a)"] = (
n.generators_t["p"][g] * n.snapshot_weightings["generators"]
).sum()
res.at[g, "OPEX (USD/kWh)"] = n.generators.at[g, "marginal_cost"]

res = res.fillna(0)

res["Full load hours (h)"] = res["Output (kWh/a)"] / res["Capacity (kW)"]
res["Full load hours (h)"] = res["Output (MWh/a)"] / res["Capacity (MW)"]
res["Cost (USD/MWh)"] = (
(
res["Capacity (kW)"] * res["CAPEX (USD/kW)"]
+ res["Output (kWh/a)"] * res["OPEX (USD/kWh)"]
res["Capacity (MW)"] * res["CAPEX (USD/kW)"]
+ res["Output (MWh/a)"] * res["OPEX (USD/kWh)"]
)
/ 8760
* 1000
)

res["Output (MWh/a)"] = res["Output (kWh/a)"] / 1000

# rename components:
rename_list = {
"PV-FIX": "PV tilted",
Expand All @@ -192,16 +191,19 @@ def calc_aggregate_statistics(

# drop unwanted columns:
if not include_debugging_output:

# filter columns:
res = res[
[
"Capacity (kW)",
"Output (kWh/a)",
"Capacity (MW)",
"Output (MWh/a)",
"Full load hours (h)",
"Curtailment (%)",
"Cost (USD/MWh)",
]
]

# filter rows:
res = res[
res.index.isin(
[
Expand All @@ -210,10 +212,29 @@ def calc_aggregate_statistics(
"Wind offshore",
"Electrolyzer",
"Derivate production",
"Electricity storage",
"H2 storage",
]
)
]

# remove unwanted entries:
for i in ["Electricity storage", "H2 storage"]:
for c in [
"Output (MWh/a)",
"Full load hours (h)",
"Curtailment (%)",
]:
if i in res.index:
res.at[i, c] = np.nan

for i in [
"Electrolyzer",
"Derivate production",
]:
if i in res.index:
res.at[i, "Curtailment (%)"] = np.nan

# calculate total costs:
res.at["Total", "Cost (USD/MWh)"] = res["Cost (USD/MWh)"].sum()

Expand Down
2 changes: 1 addition & 1 deletion md/info_optimization_results.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
This table shows aggregated results of the optimization:

- the installed generation, electrolyzer and derivate production capacities and their annual output that are required to produce 8760kWh of final product per year
- the installed generation, electrolyzer and derivate production capacities and their annual output that are required to produce 8760 MWh of final product per year
- the realized full load hours of said components
- the curtailment of renewable generation
- the costs per MWh of final product.
Expand Down

0 comments on commit 355fb81

Please sign in to comment.