diff --git a/app/plot_functions.py b/app/plot_functions.py index 78f9ae2c..6f3d657c 100644 --- a/app/plot_functions.py +++ b/app/plot_functions.py @@ -616,7 +616,12 @@ 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, @@ -624,7 +629,7 @@ def create_profile_figure_generation(df_sel: pd.DataFrame) -> go.Figure: component="Wind onshore", parameter="Power", fill=True, - color="blue", + color="#1E78C2", ) add_trace_to_figure( df_sel, @@ -632,13 +637,13 @@ def create_profile_figure_generation(df_sel: pd.DataFrame) -> go.Figure: 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) diff --git a/app/tab_optimization.py b/app/tab_optimization.py index b2ab2873..a96e3140 100644 --- a/app/tab_optimization.py +++ b/app/tab_optimization.py @@ -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 @@ -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"), @@ -108,8 +109,8 @@ 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"] @@ -117,23 +118,23 @@ def calc_aggregate_statistics( 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)"] = ( @@ -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"] @@ -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", @@ -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( [ @@ -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() diff --git a/md/info_optimization_results.md b/md/info_optimization_results.md index c1d8f52f..823c10a9 100644 --- a/md/info_optimization_results.md +++ b/md/info_optimization_results.md @@ -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.