diff --git a/.bumpversion.cfg b/.bumpversion.cfg
index 90e0a116..ae9a1f61 100644
--- a/.bumpversion.cfg
+++ b/.bumpversion.cfg
@@ -1,5 +1,5 @@
[bumpversion]
-current_version = 0.6.1
+current_version = 0.7.0
commit = True
tag = True
diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml
index 9a17e9ed..915edfde 100644
--- a/.github/workflows/publish.yaml
+++ b/.github/workflows/publish.yaml
@@ -23,4 +23,4 @@ jobs:
uses: docker/build-push-action@v5
with:
push: true
- tags: wingechr/ptx-boa:0.6.1
+ tags: wingechr/ptx-boa:0.7.0
diff --git a/.streamlit/config.toml b/.streamlit/config.toml
index bb33bffb..ea096d0c 100644
--- a/.streamlit/config.toml
+++ b/.streamlit/config.toml
@@ -5,6 +5,9 @@
textColor="#262730"
font="sans serif"
+[client]
+ toolbarMode = "minimal"
+
[logger]
level="INFO"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d7d8cb68..77214ffb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# CHANGELOG.md
+## 0.7.0 (2024-05-17)
+
+- for the two regions Sout Africa Kwazulu Natal and Indonesia a reduced quantile of 0.3 is
+ used to determine Wind Onshore and hybrid locations.
+- frontend changes:
+ - point maps instead of choropleth maps
+ - include selected subregion in global cost comparison
+
## 0.3.0 (2024-05-06)
- optimization of FLH data (with caching)
diff --git a/Dockerfile b/Dockerfile
index 3b1cdad4..2e31dc65 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,5 @@
FROM python:3.10-slim
-LABEL version="0.6.1"
+LABEL version="0.7.0"
RUN apt-get update
RUN apt-get install -y git
diff --git a/README.md b/README.md
index cd4e7dcb..073122d1 100644
--- a/README.md
+++ b/README.md
@@ -68,7 +68,7 @@ scp -r ptxboa2:ptx-boa_offline_optimization/optimization_cache/* .
# connect to server
ssh ptxboa
# pull latest image from dockerhub
-VERSION=0.6.1
+VERSION=0.7.0
docker pull wingechr/ptx-boa:$VERSION
# stop and delete the currently running container "app"
docker stop app
diff --git a/app/context_data.py b/app/context_data.py
index 51bf6a38..10330829 100644
--- a/app/context_data.py
+++ b/app/context_data.py
@@ -4,7 +4,7 @@
import streamlit as st
-@st.cache_data()
+@st.cache_data(show_spinner=False)
def load_context_data():
"""Import context data from excel file."""
filename = "data/context_data.xlsx"
diff --git a/app/layout_elements.py b/app/layout_elements.py
index b2ad449a..0d8ca470 100644
--- a/app/layout_elements.py
+++ b/app/layout_elements.py
@@ -25,6 +25,8 @@ def display_costs(
titlestring: str,
key_suffix: str = "",
output_unit: str | None = None,
+ default_select: int = 0,
+ default_manual_select: str | None = None,
):
"""Display costs as table and bar chart."""
if output_unit is None:
@@ -39,7 +41,7 @@ def display_costs(
with c2:
st.info("Input data has been modified. Select which data to display.")
select_data = st.radio(
- "Select data to display",
+ "Data to display",
["With Modifications", "Without Modifications", "Difference"],
horizontal=True,
key=f"select_user_modificatons_data_{key}_{key_suffix}",
@@ -53,32 +55,59 @@ def display_costs(
else:
df_res = df_costs.copy()
+ if default_manual_select is None:
+ default_manual_select = df_res.index.values
+
with c1:
+ if len(df_res) > 13:
+ select_options = [
+ "All",
+ "Manual selection",
+ "Cheapest 10",
+ ]
+ else:
+ select_options = ["All", "Manual selection"]
# select filter:
show_which_data = st.radio(
- "Select elements to display:",
- ["All", "Manual select"],
- index=0,
+ "Elements to display:",
+ select_options,
+ index=default_select,
horizontal=True,
key=f"show_which_data_{key}_{key_suffix}",
)
# apply filter:
- if show_which_data == "Manual select":
+ if show_which_data == "Manual selection":
ind_select = st.multiselect(
- "Select regions:",
+ "Select elements:",
df_res.index.values,
- default=df_res.index.values,
+ default=default_manual_select,
key=f"select_data_{key}_{key_suffix}",
+ label_visibility="collapsed",
)
df_res = df_res.loc[ind_select]
- # sort:
- sort_ascending = st.toggle(
- "Sort by total costs?",
- value=True,
- key=f"sort_data_{key}_{key_suffix}",
- )
+ if show_which_data == "Cheapest 10":
+ ind_select = (
+ df_res.sort_values(["Total"], ascending=True).iloc[:10].index.to_list()
+ )
+ # append the setting from the sidebar if not in cheapest 10
+ if (
+ st.session_state[key] not in ind_select
+ and st.session_state[key] in df_res.index
+ ):
+ ind_select.append(st.session_state[key])
+ df_res = df_res.loc[ind_select]
+ sort_ascending = False
+
+ else:
+ # sort:
+ sort_ascending = st.toggle(
+ "Sort by total costs?",
+ value=True,
+ key=f"sort_data_{key}_{key_suffix}",
+ )
+
if sort_ascending:
df_res = df_res.sort_values(["Total"], ascending=True)
@@ -95,9 +124,16 @@ def display_costs(
# add explainer for costs by supply chain comparison:
if titlestring == "Costs by supply chain":
+ if st.session_state["output_unit"] == "USD/t":
+ unit_note = (
+ "The output unit is set to USD/MWh in order to compare energy carriers"
+ " with different densities. "
+ )
+ else:
+ unit_note = ""
st.caption(
(
- "**Note**: Green Iron is not shown in this comparison "
+ f"**Note**: {unit_note}Green Iron is not shown in this comparison "
"as it is not an energy carrier."
)
)
@@ -224,12 +260,14 @@ def display_and_edit_input_data(
"electricity_generation",
"conversion_processes",
"transportation_processes",
- "reconversion_processes" "CAPEX",
+ "reconversion_processes",
+ "CAPEX",
"full load hours",
- "interest rate",
+ "WACC",
"specific_costs",
"conversion_coefficients",
"dac_and_desalination",
+ "storage",
],
scope: Literal["world", "Argentina", "Morocco", "South Africa"],
key: str,
@@ -247,7 +285,7 @@ def display_and_edit_input_data(
data_type : str
the data type which should be selected. Needs to be one of
"electricity_generation", "conversion_processes", "transportation_processes",
- "reconversion_processes", "CAPEX", "full load hours", "interest rate",
+ "reconversion_processes", "CAPEX", "full load hours", "WACC",
"specific costs", "conversion_coefficients" and "dac_and_desalination"
scope : Literal[None, "world", "Argentina", "Morocco", "South Africa"]
The regional scope. Is automatically set to None for data of
@@ -283,6 +321,7 @@ def display_and_edit_input_data(
"transportation_processes",
"reconversion_processes",
"dac_and_desalination",
+ "storage",
]:
index = "process_code"
columns = "parameter_code"
@@ -290,6 +329,27 @@ def display_and_edit_input_data(
missing_index_value = None
column_config = get_column_config()
+ if data_type == "conversion_processes":
+ custom_column_config = {
+ "CAPEX": st.column_config.NumberColumn(
+ format="%.0f USD/[unit]",
+ min_value=0,
+ help=(
+ "unit is [t] for Green iron reduction and [MW] for all other "
+ "processes."
+ ),
+ ),
+ "OPEX (fix)": st.column_config.NumberColumn(
+ format="%.0f USD/[unit]",
+ min_value=0,
+ help=(
+ "unit is [t] for Green iron reduction and [MW] for all other "
+ "processes."
+ ),
+ ),
+ }
+ column_config.update(custom_column_config)
+
if data_type == "dac_and_desalination":
index = "process_code"
columns = "parameter_code"
@@ -310,11 +370,11 @@ def display_and_edit_input_data(
),
}
- if data_type == "interest rate":
+ if data_type == "WACC":
index = "source_region_code"
columns = "parameter_code"
missing_index_name = "parameter_code"
- missing_index_value = "interest rate"
+ missing_index_value = "WACC"
column_config = {
c: st.column_config.NumberColumn(
format="%.2f %%", min_value=0, max_value=100
@@ -358,6 +418,11 @@ def display_and_edit_input_data(
missing_index_value = "conversion factors"
column_config = get_column_config()
+ if data_type == "storage":
+ column_config["OPEX (fix)"] = st.column_config.NumberColumn(
+ format="%.2f USD/kW", min_value=0
+ )
+
df = change_index_names(df)
# if editing is enabled, store modifications in session_state:
diff --git a/app/plot_functions.py b/app/plot_functions.py
index 37438623..adebe1a3 100644
--- a/app/plot_functions.py
+++ b/app/plot_functions.py
@@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
"""Functions for plotting input data and results (cost_data)."""
-import json
from pathlib import Path
from typing import Literal
+import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
@@ -11,6 +11,7 @@
import streamlit as st
from app.ptxboa_functions import (
+ change_index_names,
get_data_type_from_input_data,
remove_subregions,
select_subregions,
@@ -84,6 +85,7 @@ def plot_costs_on_map(
color_col=cost_component,
custom_data_func=_make_costs_hoverdata,
)
+
else:
fig = _choropleth_map_deep_dive_country(
api=api,
@@ -98,14 +100,14 @@ def plot_costs_on_map(
def plot_input_data_on_map(
api: PtxboaAPI,
- data_type: Literal["CAPEX", "full load hours", "interest rate"],
+ data_type: Literal["CAPEX", "full load hours", "WACC"],
color_col: Literal[
"PV tilted",
"Wind Offshore",
"Wind Onshore",
"Wind Onshore (hybrid)",
"PV tilted (hybrid)",
- "interest rate",
+ "WACC",
],
scope: Literal["world", "Argentina", "Morocco", "South Africa"] = "world",
) -> go.Figure:
@@ -115,7 +117,7 @@ def plot_input_data_on_map(
Parameters
----------
api : PtxboaAPI
- data_type : Literal["CAPEX", "full load hours", "interest rate"]
+ data_type : Literal["CAPEX", "full load hours", "WACC"]
The data type from which a parameter is plotted
color_col : Literal[ "PV tilted", "Wind Offshore", "Wind Onshore", "Wind
the parameter to plot on the map
@@ -130,10 +132,10 @@ def plot_input_data_on_map(
"""
input_data = get_data_type_from_input_data(api, data_type=data_type, scope=None)
- units = {"CAPEX": "USD/kW", "full load hours": "h/a", "interest rate": "%"}
+ units = {"CAPEX": "USD/kW", "full load hours": "h/a", "WACC": "%"}
- if data_type == "interest rate":
- assert color_col == "interest rate"
+ if data_type == "WACC":
+ assert color_col == "WACC"
custom_data_func_kwargs = {"float_precision": 2}
if data_type == "full load hours":
assert color_col in [
@@ -156,10 +158,6 @@ def plot_input_data_on_map(
custom_data_func_kwargs["data_type"] = data_type
custom_data_func_kwargs["map_variable"] = color_col
- # transform data to % for interest rate
- if data_type == "interest rate":
- input_data = input_data * 100
-
if scope == "world":
# Create a choropleth world map:
fig = _choropleth_map_world(
@@ -208,14 +206,19 @@ def _choropleth_map_world(
"""
if custom_data_func_kwargs is None:
custom_data_func_kwargs = {}
- df = remove_subregions(api=api, df=df, country_name=st.session_state["country"])
- fig = px.choropleth(
+ df = remove_subregions(
+ api=api, df=df, country_name=st.session_state["country"]
+ ).dropna(subset=color_col)
+ fig = px.scatter_geo(
locations=df.index,
locationmode="country names",
color=df[color_col],
custom_data=custom_data_func(df, **custom_data_func_kwargs),
color_continuous_scale=agora_continuous_color_scale(),
+ opacity=1,
)
+ fig.update_traces({"marker": {"size": 30}})
+ fig = _highlight_selected_region_world(fig)
return fig
@@ -230,7 +233,8 @@ def _choropleth_map_deep_dive_country(
if custom_data_func_kwargs is None:
custom_data_func_kwargs = {}
# subsetting 'df' for the selected deep dive country
- df = select_subregions(df, deep_dive_country)
+ # missing value removal necessary for wind offshore
+ df = select_subregions(df, deep_dive_country).dropna(subset=color_col)
# need to calculate custom data befor is03166 column is appended.
hover_data = custom_data_func(df, **custom_data_func_kwargs)
# get dataframe with info about iso 3166-2 codes and map them to res_costs
@@ -238,27 +242,88 @@ def _choropleth_map_deep_dive_country(
df["iso3166_code"] = df.index.map(
pd.Series(ddc_info["iso3166_code"], index=ddc_info["region_name"])
)
-
- geojson_file = (
- Path(__file__).parent.parent.resolve()
- / "data"
- / f"{deep_dive_country.lower().replace(' ', '_')}_subregions.geojson"
+ # load representative points data
+ lon_lat = pd.read_csv(
+ (
+ Path(__file__).parent.parent.resolve()
+ / "data"
+ / "subregion_representative_points.csv"
+ )
)
- with geojson_file.open("r", encoding="utf-8") as f:
- subregion_shapes = json.load(f)
+ # merge points to data
+ df = change_index_names(df, mapping={"source_region": "region"})
+ df = df.reset_index().merge(lon_lat, left_on="iso3166_code", right_on="iso_3166_2")
- fig = px.choropleth(
- locations=df["iso3166_code"],
- featureidkey="properties.iso_3166_2",
+ fig = px.scatter_geo(
+ lon=df["lon"],
+ lat=df["lat"],
color=df[color_col],
- geojson=subregion_shapes,
custom_data=hover_data,
color_continuous_scale=agora_continuous_color_scale(),
+ opacity=1,
)
+ fig.update_traces({"marker": {"size": 30}})
+
+ fig = _highlight_selected_subregion(df, fig)
+ bboxes = {
+ "Argentina": (-73.4154357571, -55.25, -53.628348965, -21.8323104794),
+ "Morocco": (-17.0204284327, 21.4207341578, -1.12455115397, 35.7599881048),
+ "South Africa": (16.3449768409, -34.8191663551, 32.830120477, -22.0913127581),
+ }
+
+ bbox = bboxes[deep_dive_country]
+ pad = 3
fig.update_geos(
- fitbounds="locations",
- visible=True,
+ center_lon=(bbox[0] + bbox[2]) / 2.0,
+ center_lat=(bbox[1] + bbox[3]) / 2.0,
+ lonaxis_range=[bbox[0] - pad, bbox[2] + pad],
+ lataxis_range=[bbox[1] - pad, bbox[3] + pad],
+ )
+ return fig
+
+
+def _highlight_selected_subregion(df, fig):
+ if st.session_state["region"] in df["region"].tolist():
+ subreg = st.session_state["region"]
+ fig.add_trace(
+ go.Scattergeo(
+ lon=df.loc[df["region"] == subreg, "lon"].tolist(),
+ lat=df.loc[df["region"] == subreg, "lat"].tolist(),
+ marker={
+ "size": 31,
+ "color": "rgba(0, 0, 0, 0)",
+ "line": {"width": 3, "color": "black"},
+ },
+ hoverinfo="skip",
+ customdata=["selected supply subregion"],
+ name="selected region",
+ showlegend=False,
+ )
+ )
+ return fig
+
+
+def _highlight_selected_region_world(fig: go.Figure) -> go.Figure:
+ if st.session_state["subregion"] is not None:
+ region = st.session_state["region"].split(" (")[0]
+ else:
+ region = st.session_state["region"]
+
+ fig.add_trace(
+ go.Scattergeo(
+ locations=[region],
+ locationmode="country names",
+ marker={
+ "size": 31,
+ "color": "rgba(0, 0, 0, 0)",
+ "line": {"width": 3, "color": "black"},
+ },
+ hoverinfo="skip",
+ customdata=["selected supply region"],
+ name="selected region",
+ showlegend=False,
+ )
)
return fig
@@ -285,10 +350,9 @@ def _set_map_layout(fig: go.Figure, colorbar_title: str) -> go.Figure:
"""
# update layout:
fig.update_geos(
- showcountries=True, # Show country borders
+ resolution=50,
+ showcountries=False, # do not show country borders
showcoastlines=True, # Show coastlines
- countrycolor="black", # Set default border color for other countries
- countrywidth=0.2, # Set border width
coastlinewidth=0.2, # coastline width
coastlinecolor="black", # coastline color
showland=True, # show land areas
@@ -313,18 +377,22 @@ def _set_map_layout(fig: go.Figure, colorbar_title: str) -> go.Figure:
def _make_inputs_hoverdata(df, data_type, map_variable, unit, float_precision):
custom_hover_data = []
- if data_type == "interest rate":
+ if data_type == "WACC":
for idx, row in df.iterrows():
hover = (
f"{idx} | {data_type}
"
- f"{row['interest rate']:.{float_precision}f} {unit}"
+ f"{row['WACC']:.{float_precision}f} {unit}"
)
custom_hover_data.append(hover)
else:
for idx, row in df.iterrows():
hover = f"{idx} | {data_type}
"
for i, v in zip(row.index, row):
- hover += f"
{i}: {v:.{float_precision}f} {unit}"
+ if np.isnan(v):
+ value = "no data"
+ else:
+ value = f"{v:.{float_precision}f} {unit}"
+ hover += f"
{i}: {value}"
if i == map_variable:
hover += " ← displayed on map"
custom_hover_data.append(hover)
@@ -332,16 +400,17 @@ def _make_inputs_hoverdata(df, data_type, map_variable, unit, float_precision):
def _make_costs_hoverdata(res_costs: pd.DataFrame) -> list[pd.Series]:
- custom_hover_data = res_costs.apply(
+ custom_hover_data = res_costs.map("{:,.1f}".format).apply(
lambda x: f"{x.name}
"
+ "
".join(
[
- f"{col}: {x[col]:.1f}" f"{st.session_state['output_unit']}"
+ f"{col}: {x[col] if x[col] != 'nan' else 'not applicable'} "
+ f"{st.session_state['output_unit'] if x[col] != 'nan' else ''}"
for col in res_costs.columns[:-1]
]
+ [
f"──────────
{res_costs.columns[-1]}: "
- f"{x[res_costs.columns[-1]]:.1f}"
+ f"{x[res_costs.columns[-1]]}"
f"{st.session_state['output_unit']}"
]
),
@@ -399,16 +468,23 @@ def create_bar_chart_costs(
# add highlight for current selection:
if current_selection is not None and current_selection in res_costs.index:
+ if (res_costs["Total"] < 0).all():
+ y = 1.2 * min(res_costs["Total"])
+ ay = 30
+ else:
+ y = 1.2 * max(res_costs["Total"])
+ ay = -30
+
fig.add_annotation(
x=current_selection,
- y=1.2 * max(res_costs["Total"]),
+ y=y,
text="current selection",
showarrow=True,
arrowhead=2,
arrowsize=1,
arrowwidth=2,
ax=0,
- ay=-30,
+ ay=ay,
)
if output_unit is None:
@@ -506,20 +582,23 @@ def add_trace_to_figure(
df_plot = df[(df["Component"] == component)]
df_plot = df_plot[(df_plot["Parameter"] == parameter)]
if fill:
- fig.add_trace(
- go.Line(
- x=df_plot["time"],
- y=df_plot["MW (MWh for SOC)"],
- name=component,
- line_color=color,
- stackgroup="one",
+ if df_plot["MW (MWh for SOC)"].sum() > 0:
+ fig.add_trace(
+ go.Scatter(
+ x=df_plot["time"],
+ y=df_plot["MW (MWh for SOC)"],
+ mode="lines",
+ name=component,
+ line_color=color,
+ stackgroup="one",
+ )
)
- )
else:
fig.add_trace(
- go.Line(
+ go.Scatter(
x=df_plot["time"],
y=df_plot["MW (MWh for SOC)"],
+ mode="lines",
name=component,
line_color=color,
)
@@ -599,7 +678,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,
@@ -607,7 +691,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,
@@ -615,13 +699,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/ptxboa_functions.py b/app/ptxboa_functions.py
index 234607bc..bf924291 100644
--- a/app/ptxboa_functions.py
+++ b/app/ptxboa_functions.py
@@ -11,7 +11,7 @@
from ptxboa.utils import is_test
-@st.cache_data
+@st.cache_data(show_spinner=False)
def calculate_results_single(
_api: PtxboaAPI,
settings: dict,
@@ -120,6 +120,19 @@ def calculate_results_list(
for parameter in parameter_list:
settings.update({parameter_to_change: parameter})
+ if parameter_to_change == "chain":
+ needs_co2 = check_if_input_is_needed(
+ api,
+ flow_code="CO2-G",
+ chain=settings["chain"],
+ scenario=settings["scenario"],
+ )
+ # if the current chain does not need CO2, set "secproc_co2" to None
+ if needs_co2:
+ settings.update({"secproc_co2": st.session_state["secproc_co2"]})
+ else:
+ settings.update({"secproc_co2": None})
+
# consider user data in optimization only for parameter set in session state
if st.session_state[parameter_to_change] == parameter:
use_user_data_for_optimize_flh = True
@@ -254,10 +267,11 @@ def get_data_type_from_input_data(
"reconversion_processes",
"CAPEX",
"full load hours",
- "interest rate",
+ "WACC",
"specific_costs",
"conversion_coefficients",
"dac_and_desalination",
+ "storage",
],
scope: Literal[None, "world", "Argentina", "Morocco", "South Africa"],
) -> pd.DataFrame:
@@ -275,7 +289,7 @@ def get_data_type_from_input_data(
data_type : str
the data type which should be selected. Needs to be one of
"electricity_generation", "conversion_processes", "transportation_processes",
- "reconversion_processes", "CAPEX", "full load hours", "interest rate",
+ "reconversion_processes", "CAPEX", "full load hours", "WACC",
"specific costs", "conversion_coefficients" and "dac_and_desalination".
scope : Literal[None, "world", "Argentina", "Morocco", "South Africa"]
The regional scope. Is automatically set to None for data of
@@ -316,6 +330,7 @@ def get_data_type_from_input_data(
"transportation_processes",
"reconversion_processes",
"dac_and_desalination",
+ "storage",
]:
scope = None
source_region_code = [""]
@@ -385,6 +400,8 @@ def get_data_type_from_input_data(
process_code = processes.loc[
processes["is_transport"] & ~processes["is_transformation"], "process_name"
].to_list()
+ # remove storage processes
+ process_code = [c for c in process_code if "storage" not in c]
if data_type == "reconversion_processes":
parameter_code = [
@@ -397,12 +414,12 @@ def get_data_type_from_input_data(
processes["is_transport"] & processes["is_transformation"], "process_name"
].to_list()
- if data_type in ["CAPEX", "interest rate"]:
+ if data_type in ["CAPEX", "WACC"]:
source_region_code = None
parameter_code = [data_type]
index = "source_region_code"
- if data_type == "interest rate":
+ if data_type == "WACC":
columns = "parameter_code"
process_code = [""]
@@ -414,6 +431,17 @@ def get_data_type_from_input_data(
"PV tilted",
]
+ if data_type == "storage":
+ parameter_code = [
+ "CAPEX",
+ "OPEX (fix)",
+ "lifetime / amortization period",
+ "efficiency",
+ ]
+ process_code = processes.loc[
+ processes["process_name"].str.contains("storage"), "process_name"
+ ].to_list()
+
df = subset_and_pivot_input_data(
input_data,
source_region_code=source_region_code,
@@ -424,13 +452,17 @@ def get_data_type_from_input_data(
values="value",
)
+ # remove electricity from specific costs
+ if data_type == "specific_costs":
+ df = df[~(df.index == "electricity")]
+
if scope == "world":
df = remove_subregions(api=api, df=df, country_name=st.session_state["country"])
if scope in ["Argentina", "Morocco", "South Africa"]:
df = select_subregions(df, scope)
- # transform data to match unit [%] for 'interest_rate' and 'efficieny'
- if data_type == "interest rate":
+ # transform data to match unit [%] for 'WACC' and 'efficieny'
+ if data_type == "WACC":
df = df * 100
if "efficiency" in df.columns:
@@ -439,7 +471,9 @@ def get_data_type_from_input_data(
return df
-def remove_subregions(api: PtxboaAPI, df: pd.DataFrame, country_name: str):
+def remove_subregions(
+ api: PtxboaAPI, df: pd.DataFrame, country_name: str, keep: str | None = None
+):
"""Remove subregions from a dataframe.
Parameters
@@ -453,6 +487,9 @@ def remove_subregions(api: PtxboaAPI, df: pd.DataFrame, country_name: str):
country_name : str
name of target country. Is removed from region list if it is also in there.
+ keep : str or None, by default None
+ can be used to keep data for a specific subregion
+
Returns
-------
pandas DataFrame with subregions removed from index.
@@ -473,6 +510,9 @@ def remove_subregions(api: PtxboaAPI, df: pd.DataFrame, country_name: str):
r for r in region_list_without_subregions if r in df.index
]
+ if keep is not None:
+ region_list_without_subregions.append(keep)
+
df = df.loc[region_list_without_subregions]
return df
@@ -554,7 +594,12 @@ def get_column_config() -> dict:
help=read_markdown_file("md/helptext_columns_lifetime.md"),
),
"levelized costs": st.column_config.NumberColumn(
- format="%.2e USD/(kW km)", min_value=0
+ format="%.2e USD/([unit] km)",
+ min_value=0,
+ help=(
+ "unit is [t] for Green iron ship (bunker fuel consumption) and [MW] "
+ "for all other processes."
+ ),
),
"losses (own fuel, transport)": st.column_config.NumberColumn(
format="%.2e fraction per km",
@@ -619,6 +664,7 @@ def change_index_names(df: pd.DataFrame, mapping: dict | None = None) -> pd.Data
"process_code": "Process",
"source_region_code": "Source region",
"region": "Source region",
+ "source_region": "Source region",
"scenario": "Scenario",
"res_gen": "RE source",
"chain": "Chain",
@@ -629,16 +675,21 @@ def change_index_names(df: pd.DataFrame, mapping: dict | None = None) -> pd.Data
return df
-def check_if_input_is_needed(api: PtxboaAPI, flow_code: str) -> bool:
+def check_if_input_is_needed(
+ api: PtxboaAPI, flow_code: str, chain: str = None, scenario: str = None
+) -> bool:
"""Check if a certain input is required by the selected process chain."""
+ if chain is None:
+ chain = st.session_state["chain"]
+ if scenario is None:
+ scenario = st.session_state["scenario"]
+
# get list of processes in selected chain:
- process_codes = (
- api.get_dimension("chain").loc[st.session_state["chain"]][:-1].to_list()
- )
+ process_codes = api.get_dimension("chain").loc[chain][:-1].to_list()
process_codes = [p for p in process_codes if p != ""]
# get list of conversion coefficients for these processes:
- df = api.get_input_data(scenario=st.session_state["scenario"], long_names=False)
+ df = api.get_input_data(scenario=scenario, long_names=False)
flow_codes = df.loc[
(df["process_code"].isin(process_codes)) & (df["parameter_code"] == "CONV"),
"flow_code",
diff --git a/app/sidebar.py b/app/sidebar.py
index 27fa4557..2a4656ff 100644
--- a/app/sidebar.py
+++ b/app/sidebar.py
@@ -7,7 +7,20 @@
from ptxboa.api import PtxboaAPI
+@st.cache_resource()
+def sidebar_logo():
+ st.image("img/agora-energiewende_logo_612x306.png")
+
+
def make_sidebar(api: PtxboaAPI):
+ st.logo(
+ image="img/transparent_10x10.png", # placeholder when sidebar is expanded
+ icon_image="img/agora-energiewende_logo_612x306.png",
+ )
+
+ with st.sidebar:
+ sidebar_logo()
+
with st.sidebar.expander("**Main settings**", expanded=True):
main_settings(api)
@@ -49,6 +62,7 @@ def main_settings(api):
index=region_list.get_loc("Morocco"), # Morocco as default
)
st.session_state["region"] = region
+ st.session_state["subregion"] = None
# If a deep dive country has been selected, add option to select subregion:
if region in ["Argentina", "Morocco", "South Africa"]:
@@ -64,6 +78,7 @@ def main_settings(api):
)
if subregion is not None:
st.session_state["region"] = subregion
+ st.session_state["subregion"] = subregion
# select demand country:
countries = api.get_dimension("country").index
@@ -91,12 +106,12 @@ def main_settings(api):
index=4, # Methane as default
)
with c2:
- ely = st.selectbox(
+ st.session_state["electrolyzer"] = st.selectbox(
"Electrolyzer type:",
[
"AEL",
"PEM",
- "SEOC",
+ "SOEC",
],
help=read_markdown_file("md/helptext_sidebar_electrolyzer_type.md"),
index=0, # AEL as default
@@ -111,7 +126,7 @@ def main_settings(api):
else:
use_reconversion = False
- st.session_state["chain"] = f"{product} ({ely})"
+ st.session_state["chain"] = f"{product} ({st.session_state['electrolyzer']})"
if use_reconversion:
st.session_state["chain"] = f"{st.session_state['chain']} + reconv. to H2"
diff --git a/app/tab_certification_schemes.py b/app/tab_certification_schemes.py
index f2f6de3e..3a84d427 100644
--- a/app/tab_certification_schemes.py
+++ b/app/tab_certification_schemes.py
@@ -75,7 +75,7 @@ def _render_scheme_info(context_data, scheme_name):
def content_certification_schemes(context_data: dict):
- with st.expander("What is this?"):
+ with st.popover("*Help*", use_container_width=True):
st.markdown(read_markdown_file("md/whatisthis_certification_schemes.md"))
helptext = "Select the certification scheme you want to know more about."
diff --git a/app/tab_costs.py b/app/tab_costs.py
index 73865393..9d579693 100644
--- a/app/tab_costs.py
+++ b/app/tab_costs.py
@@ -25,7 +25,7 @@ def content_costs(
costs_per_res_gen_without_user_changes: pd.DataFrame,
costs_per_chain_without_user_changes: pd.DataFrame,
):
- with st.expander("What is this?"):
+ with st.popover("*Help*", use_container_width=True):
st.markdown(read_markdown_file("md/whatisthis_costs.md"))
with st.container(border=True):
@@ -79,12 +79,18 @@ def content_costs(
with st.container(border=True):
display_costs(
- remove_subregions(api, costs_per_region, st.session_state["country"]),
+ remove_subregions(
+ api,
+ costs_per_region,
+ st.session_state["country"],
+ keep=st.session_state["subregion"],
+ ),
(
remove_subregions(
api,
costs_per_region_without_user_changes,
st.session_state["country"],
+ keep=st.session_state["subregion"],
)
if st.session_state["user_changes_df"] is not None
else None
@@ -116,4 +122,10 @@ def content_costs(
"chain",
"Costs by supply chain",
output_unit="USD/MWh",
+ default_select=1,
+ default_manual_select=[
+ x
+ for x in costs_per_chain.index
+ if st.session_state["electrolyzer"] in x
+ ],
)
diff --git a/app/tab_country_fact_sheets.py b/app/tab_country_fact_sheets.py
index 6ebabcc1..bde1e352 100644
--- a/app/tab_country_fact_sheets.py
+++ b/app/tab_country_fact_sheets.py
@@ -149,7 +149,7 @@ def _create_fact_sheet_supply_country(context_data: dict, api: PtxboaAPI):
def content_country_fact_sheets(context_data, api):
- with st.expander("What is this?"):
+ with st.popover("*Help*", use_container_width=True):
st.markdown(read_markdown_file("md/whatisthis_country_fact_sheets.md"))
with st.container(border=True):
_create_fact_sheet_demand_country(context_data)
diff --git a/app/tab_deep_dive_countries.py b/app/tab_deep_dive_countries.py
index 67712bf4..0fed29ce 100644
--- a/app/tab_deep_dive_countries.py
+++ b/app/tab_deep_dive_countries.py
@@ -3,7 +3,7 @@
import pandas as pd
import plotly.express as px
import streamlit as st
-from streamlit_antd_components import SegmentedItem, segmented
+import streamlit_antd_components as sac
from app.layout_elements import (
display_and_edit_input_data,
@@ -33,15 +33,15 @@ def content_deep_dive_countries(
------
None
"""
- with st.expander("What is this?"):
+ with st.popover("*Help*", use_container_width=True):
st.markdown(read_markdown_file("md/whatisthis_deep_dive_countries.md"))
st.write("Select which country to display:")
- ddc = segmented(
+ ddc = sac.buttons(
items=[
- SegmentedItem(label="Argentina"),
- SegmentedItem(label="Morocco"),
- SegmentedItem(label="South Africa"),
+ sac.ButtonsItem(label="Argentina"),
+ sac.ButtonsItem(label="Morocco"),
+ sac.ButtonsItem(label="South Africa"),
],
use_container_width=True,
)
@@ -106,7 +106,11 @@ def content_deep_dive_countries(
with c_0_1:
st.markdown("**Regional distribution**")
with c_1_1:
- fig = px.box(df)
+ fig = px.box(
+ df,
+ hover_data=[df.index],
+ hover_name="res_gen",
+ )
fig.update_layout(xaxis_title=None)
st.plotly_chart(fig, use_container_width=True)
what_is_a_boxplot()
diff --git a/app/tab_input_data.py b/app/tab_input_data.py
index b3bef0f9..efcac52f 100644
--- a/app/tab_input_data.py
+++ b/app/tab_input_data.py
@@ -21,7 +21,7 @@ def content_input_data(api: PtxboaAPI) -> None:
------
None
"""
- with st.expander("What is this?"):
+ with st.popover("*Help*", use_container_width=True):
st.markdown(read_markdown_file("md/whatisthis_input_data.md"))
with st.container(border=True):
@@ -29,7 +29,7 @@ def content_input_data(api: PtxboaAPI) -> None:
data_selection = st.radio(
"Select data type",
- ["CAPEX", "full load hours", "interest rate"],
+ ["CAPEX", "full load hours", "WACC"],
horizontal=True,
)
@@ -57,7 +57,7 @@ def content_input_data(api: PtxboaAPI) -> None:
key="input_data_map_parameter",
)
else:
- map_parameter = "interest rate"
+ map_parameter = "WACC"
fig = plot_input_data_on_map(
api=api,
data_type=data_selection,
@@ -77,11 +77,18 @@ def content_input_data(api: PtxboaAPI) -> None:
# create plot:
if data_selection == "CAPEX":
ylabel = "CAPEX (USD/kW)"
+ hover_name = "process_code"
if data_selection == "full load hours":
ylabel = "full load hours (h/a)"
- if data_selection == "interest rate":
- ylabel = "interest rate (%)"
- fig = px.box(df)
+ hover_name = "res_gen"
+ if data_selection == "WACC":
+ ylabel = "WACC (%)"
+ hover_name = "parameter_code"
+ fig = px.box(
+ df,
+ hover_data=[df.index],
+ hover_name=hover_name,
+ )
fig.update_layout(xaxis_title=None, yaxis_title=ylabel)
st.plotly_chart(fig, use_container_width=True)
what_is_a_boxplot()
@@ -96,13 +103,47 @@ def content_input_data(api: PtxboaAPI) -> None:
key="input_data_electricity_generation",
)
with st.expander("**Electrolysis and derivate production**"):
+ st.caption(
+ (
+ "The unit of CAPEX and OPEX (fix) is USD/t for Green iron "
+ "reduction and USD/MW for all other processes."
+ )
+ )
display_and_edit_input_data(
api,
data_type="conversion_processes",
scope=None,
key="input_data_conversion_processes",
)
+ with st.expander("**Storage**"):
+ st.caption(
+ (
+ "- Storage CAPEX are defined per charging power.\n"
+ "- Efficiencies are round-trip.\n"
+ "- Time-dependent losses are neglected.\n"
+ "- For electricity storage (batteries) we assume a fixed ratio of 4"
+ " MWh storage capacity per MW charging power\n"
+ " and equal charging/discharging power.\n"
+ "- For hydrogen storage (tanks) we assume storage capacity and"
+ " discharge power to be non-binding because the comporessor is by"
+ " far the most expensive component."
+ )
+ )
+ display_and_edit_input_data(
+ api,
+ data_type="storage",
+ scope=None,
+ key="input_data_storage",
+ )
+
with st.expander("**Transportation (ships and pipelines)**"):
+ st.caption(
+ (
+ "The unit of levelized costs is USD/(t km) for Green iron ship "
+ "(bunker fuel consumption) and USD/(kW km) for all other "
+ "processes."
+ )
+ )
display_and_edit_input_data(
api,
data_type="transportation_processes",
@@ -119,7 +160,7 @@ def content_input_data(api: PtxboaAPI) -> None:
key="input_data_reconversion_processes",
)
with st.expander("**Direct air capture and desalination**"):
- st.markdown(
+ st.caption(
(
"Units for CAPEX and OPEX (fix) are per kg of CO2 for "
"direct air capture and per kg of H20 for sea water "
diff --git a/app/tab_literature.py b/app/tab_literature.py
index bd137f3a..f4960691 100644
--- a/app/tab_literature.py
+++ b/app/tab_literature.py
@@ -21,7 +21,7 @@ def _is_valid_url(url: str) -> bool:
def content_literature(context_data: dict):
- with st.expander("What is this?"):
+ with st.popover("*Help*", use_container_width=True):
st.markdown(read_markdown_file("md/whatisthis_literature.md"))
st.markdown("## References")
diff --git a/app/tab_market_scanning.py b/app/tab_market_scanning.py
index 2d6abeb1..f080e936 100644
--- a/app/tab_market_scanning.py
+++ b/app/tab_market_scanning.py
@@ -6,6 +6,7 @@
from app.excel_download import prepare_and_download_df_as_excel
from app.ptxboa_functions import (
+ change_index_names,
config_number_columns,
read_markdown_file,
remove_subregions,
@@ -25,7 +26,7 @@ def content_market_scanning(api: PtxboaAPI, res_costs: pd.DataFrame, cd: dict) -
cd: dict
context data.
"""
- with st.expander("What is this?"):
+ with st.popover("*Help*", use_container_width=True):
st.markdown(read_markdown_file("md/whatisthis_market_scanning.md"))
# get input data:
@@ -77,13 +78,31 @@ def content_market_scanning(api: PtxboaAPI, res_costs: pd.DataFrame, cd: dict) -
df = df.astype(float)
# do not show subregions:
- df = remove_subregions(api, df, st.session_state["country"])
+ df = remove_subregions(
+ api, df, st.session_state["country"], keep=st.session_state["subregion"]
+ )
+
+ # if a subregion is selected, distribute country potential equally across
+ # subregions:
+ if st.session_state["subregion"] is not None:
+ region = st.session_state["region"].split(" (")[0]
+ number_of_subregions = (
+ api.get_dimension("region")["region_name"].str.startswith(region).sum() - 1
+ )
+ for par in [
+ "RE technical potential (PTX Atlas) (TWh/a)",
+ "RE technical potential (EWI) (TWh/a)",
+ ]:
+ df.at[st.session_state["subregion"], par] = (
+ df.at[region, par] / number_of_subregions
+ )
with st.container(border=True):
st.markdown(
"### Costs and transportation distances from different supply regions"
f" to {st.session_state['country']}"
)
+
c1, c2 = st.columns(2)
with c1:
# select which distance to show:
@@ -102,6 +121,7 @@ def content_market_scanning(api: PtxboaAPI, res_costs: pd.DataFrame, cd: dict) -
"RE technical potential (PTX Atlas) (TWh/a)",
"None",
],
+ help=read_markdown_file("md/helptext_technical_potential.md"),
)
# create plot:
@@ -190,8 +210,11 @@ def content_market_scanning(api: PtxboaAPI, res_costs: pd.DataFrame, cd: dict) -
df.at["USA", "h2_demand_2030"] = 10
# EU data is missing completely in context_data.xlsx:
- df.at["EU", "shipping distance"] = 1104
- df.at["EU", "pipeline distance"] = 2000
+ df.at["EU", "shipping distance"] = df.at["France", "shipping distance"]
+ try:
+ df.at["EU", "pipeline distance"] = df.at["France", "pipeline distance"]
+ except KeyError:
+ df.at["EU", "pipeline distance"] = None
df.at["EU", "h2_demand_2030"] = 20
df["h2_demand_2030"] = df["h2_demand_2030"].astype(float)
@@ -215,6 +238,7 @@ def content_market_scanning(api: PtxboaAPI, res_costs: pd.DataFrame, cd: dict) -
)
# create plot:
+ df = change_index_names(df, mapping={"target_country_code": "Target country"})
df_plot = df.copy().round(0)
# distinguish between selected region and others:
diff --git a/app/tab_optimization.py b/app/tab_optimization.py
index acf8ff4f..a2a540c6 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
@@ -17,26 +18,27 @@
def content_optimization(api: PtxboaAPI) -> None:
- with st.expander("What is this?"):
+ with st.popover("*Help*", use_container_width=True):
st.markdown(read_markdown_file("md/whatisthis_optimization.md"))
- # load netcdf file:
- try:
- n, metadata = api.get_flh_opt_network(
- scenario=st.session_state["scenario"],
- secproc_co2=st.session_state["secproc_co2"],
- secproc_water=st.session_state["secproc_water"],
- chain=st.session_state["chain"],
- res_gen=st.session_state["res_gen"],
- region=st.session_state["region"],
- country=st.session_state["country"],
- transport=st.session_state["transport"],
- ship_own_fuel=st.session_state["ship_own_fuel"],
- user_data=st.session_state["user_changes_df"],
- )
- except FileNotFoundError:
- st.error("No optimization model could be loaded")
- return
+ with st.spinner("Please wait. Running optimization model..."):
+ # load netcdf file:
+ try:
+ n, metadata = api.get_flh_opt_network(
+ scenario=st.session_state["scenario"],
+ secproc_co2=st.session_state["secproc_co2"],
+ secproc_water=st.session_state["secproc_water"],
+ chain=st.session_state["chain"],
+ res_gen=st.session_state["res_gen"],
+ region=st.session_state["region"],
+ country=st.session_state["country"],
+ transport=st.session_state["transport"],
+ ship_own_fuel=st.session_state["ship_own_fuel"],
+ user_data=st.session_state["user_changes_df"],
+ )
+ except FileNotFoundError:
+ st.error("No optimization model could be loaded")
+ return
if metadata["model_status"] == ["ok", "optimal"]:
@@ -57,8 +59,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"),
@@ -68,7 +70,7 @@ def content_optimization(api: PtxboaAPI) -> None:
with st.container(border=True):
st.subheader("Download model")
st.markdown(read_markdown_file("md/info_download_model.md"))
- download_network_as_netcdf(st.session_state["network"], "network.nc")
+ download_network_as_netcdf(n=n, filename="network.nc")
with st.expander("Debugging output"):
st.warning(
@@ -108,8 +110,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 +119,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 +145,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 +159,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 +192,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 +213,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/app/tab_sustainability.py b/app/tab_sustainability.py
index 787f4111..38244576 100644
--- a/app/tab_sustainability.py
+++ b/app/tab_sustainability.py
@@ -49,7 +49,7 @@ def _interactive_sustainability_dimension_info(context_data: dict):
def content_sustainability(context_data: dict):
- with st.expander("What is this?"):
+ with st.popover("*Help*", use_container_width=True):
st.markdown(read_markdown_file("md/whatisthis_sustainability.md"))
st.markdown("## Dimensions of sustainability")
diff --git a/app/user_data.py b/app/user_data.py
index cd2b6f20..80056a85 100644
--- a/app/user_data.py
+++ b/app/user_data.py
@@ -57,9 +57,9 @@ def register_user_changes(
# Replace the 'id' values with the corresponding index elements from df_tab
res[index] = res[index].map(lambda x: df_tab.index[x])
- # convert the interest rate from [%] to [decimals]
+ # convert the WACC from [%] to [decimals]
res["value"] = res["value"].astype(float)
- for param_code in ["interest rate", "efficiency"]:
+ for param_code in ["WACC", "efficiency"]:
res.loc[res["parameter_code"] == param_code, "value"] = (
res.loc[res["parameter_code"] == param_code, "value"] / 100
)
@@ -109,7 +109,7 @@ def _custom_unit_based_on_process_and_parameter(process, parameter, unaffected):
def _custom_unit_based_on_parameter(parameter, unaffected):
- mapping = {"efficiency": "%", "interest rate": "%"}
+ mapping = {"efficiency": "%", "WACC": "%"}
return mapping.get(parameter, unaffected)
@@ -118,8 +118,8 @@ def display_user_changes(api):
if st.session_state["user_changes_df"] is not None:
df = st.session_state["user_changes_df"].copy()
- # convert the values for 'interest rate' and 'efficiency' from [decimals] to [%]
- for param_code in ["interest rate", "efficiency"]:
+ # convert the values for 'WACC' and 'efficiency' from [decimals] to [%]
+ for param_code in ["WACC", "efficiency"]:
df.loc[df["parameter_code"] == param_code, "value"] = (
df.loc[df["parameter_code"] == param_code, "value"] * 100
)
diff --git a/app/user_data_from_file.py b/app/user_data_from_file.py
index 9600bc57..f6c6f017 100644
--- a/app/user_data_from_file.py
+++ b/app/user_data_from_file.py
@@ -182,7 +182,7 @@ def _validate_param_in_range(result):
"OPEX (fix)": (0, np.inf),
"efficiency": (0, 1),
"lifetime / amortization period": (0, np.inf),
- "interest rate": (0, 1),
+ "WACC": (0, 1),
"full load hours": (0, 8760),
"specific costs": (0, np.inf),
"losses (own fuel, transport)": (0, np.inf),
diff --git a/data/subregion_representative_points.csv b/data/subregion_representative_points.csv
new file mode 100644
index 00000000..24815252
--- /dev/null
+++ b/data/subregion_representative_points.csv
@@ -0,0 +1,46 @@
+iso_3166_2,lon,lat
+MA-11,-11.487535149205273,26.291022599999998
+MA-01,-5.434766372913305,35.2181678
+MA-02,-2.3906063870173955,33.5811814
+MA-08,-5.58317463160672,31.28770725
+MA-09,-8.157695785778756,29.7357752
+MA-10,-10.084427221839995,28.385906
+MA-06,-7.799432071783302,33.065160649999996
+MA-07,-8.306409084756796,31.806335949999998
+MA-12,-14.741994773441643,22.735386249999998
+MA-04,-6.328725938578254,34.08533075
+MA-03,-4.847581884998955,33.74727775
+MA-05,-6.280445836675398,32.4092902
+AR-E,-59.41391734740016,-32.09481027848068
+AR-A,-63.2488630052977,-24.188186947408994
+AR-Y,-66.05131162400237,-23.19339019145417
+AR-P,-60.056795466789765,-24.694332167145802
+AR-N,-54.408009579418504,-26.838980814499898
+AR-H,-60.69169607218846,-26.04543832741686
+AR-W,-57.80329050740136,-29.00667836190994
+AR-K,-67.51184361556847,-27.649319756801333
+AR-F,-66.86724287983822,-29.835207004049977
+AR-J,-68.76400612946446,-30.369850969333534
+AR-M,-68.47196659910384,-34.75436330149996
+AR-Q,-69.55620607085012,-38.61386932399996
+AR-U,-68.47608492458708,-43.999489582499905
+AR-R,-66.42178269981838,-39.78144744254544
+AR-Z,-70.40714935693845,-49.193291924999926
+AR-V,-68.09468684709897,-53.841798372999904
+AR-B,-60.113853483913914,-37.10019296649992
+AR-C,-58.44119878492826,-34.642826064273805
+AR-S,-60.97677432423949,-31.164195651608026
+AR-T,-65.39223122835818,-27.06493682212667
+AR-G,-63.37956470637425,-27.840677585851893
+AR-D,-65.95764785447187,-33.936842950791544
+AR-L,-65.8186469775226,-37.06892567313133
+AR-X,-63.68163713228595,-32.214312432772545
+ZA-NC,22.022372549742485,-28.848704728999934
+ZA-NL,30.414604596802526,-28.941989841499947
+ZA-FS,26.606093929174868,-28.668094377346847
+ZA-EC,26.5770656739886,-32.091735934615684
+ZA-LP,29.333422657090793,-23.779038391499938
+ZA-NW,25.24337419152684,-26.37090419793683
+ZA-MP,30.160392889928794,-25.74002980499995
+ZA-WC,22.14966623331297,-32.64267852138539
+ZA-GT,28.020037353796795,-26.0096414140351
diff --git a/flh_opt/_types.py b/flh_opt/_types.py
index 7b01ab04..70a338d0 100644
--- a/flh_opt/_types.py
+++ b/flh_opt/_types.py
@@ -59,6 +59,14 @@ class ProcessDerivInputData(TypedDict):
CONV: Dict[SecondaryFlowType, float]
+class SecProcessInputDataType(TypedDict):
+ # EFF: Does not use EFF parameter
+ CAPEX_A: float
+ OPEX_F: float
+ OPEX_O: float
+ CONV: Dict[SecondaryFlowType, float]
+
+
class OptInputDataType(TypedDict):
SOURCE_REGION_CODE: str
RES: List[ProcessResInputDataType]
@@ -67,6 +75,8 @@ class OptInputDataType(TypedDict):
EL_STR: ProcessStorageInputDataType
H2_STR: ProcessStorageInputDataType
SPECCOST: Dict[Literal["H2O-L"], float]
+ DAC: SecProcessInputDataType
+ DESAL: SecProcessInputDataType
class ProcessOutputResType(TypedDict):
@@ -79,6 +89,8 @@ class OptOutputDataType(TypedDict):
RES: List[ProcessOutputResType]
ELY: Dict[Literal["FLH"], float]
DERIV: Dict[Literal["FLH"], float]
+ DAC: Dict[Literal["FLH"], float]
+ DESAL: Dict[Literal["FLH"], float]
EL_STR: Dict[Literal["CAP_F"], float]
H2_STR: Dict[Literal["CAP_F"], float]
diff --git a/flh_opt/api_opt.py b/flh_opt/api_opt.py
index 9daecad7..9b0ec1fa 100644
--- a/flh_opt/api_opt.py
+++ b/flh_opt/api_opt.py
@@ -39,6 +39,44 @@ def get_profiles_and_weights(
return data, weights_and_period_ids
+def _add_link(
+ n: Network,
+ input_data: OptInputDataType,
+ name: str,
+ bus0: str,
+ bus1: str,
+ carrier: str,
+):
+ """Add link component to network."""
+ if input_data.get(name):
+
+ # default efficiency = 1 (for DAC and DESAL):
+ if not input_data[name].get("EFF"):
+ input_data[name]["EFF"] = 1
+ n.add(
+ "Link",
+ name=name,
+ bus0=bus0,
+ bus1=bus1,
+ carrier=carrier,
+ efficiency=input_data[name]["EFF"],
+ # input data is per main output,
+ # pypsa link parameters are defined per main input
+ capital_cost=(input_data[name]["CAPEX_A"] + input_data[name]["OPEX_F"])
+ / input_data[name]["EFF"],
+ marginal_cost=input_data[name]["OPEX_O"] / input_data[name]["EFF"],
+ p_nom_extendable=True,
+ )
+ # add conversion efficiencies and buses for secondary input / output
+ for i, c in enumerate(input_data[name]["CONV"].keys()):
+ n.links.at[name, f"bus{i+2}"] = c
+ # input data is per main output,
+ # pypsa link parameters are defined per main input
+ n.links.at[name, f"efficiency{i+2}"] = (
+ -input_data[name]["CONV"][c] / input_data[name]["EFF"]
+ )
+
+
def optimize(
input_data: OptInputDataType, profiles_path: str = "flh_opt/renewable_profiles"
) -> tuple[OptOutputDataType, Network]:
@@ -79,6 +117,24 @@ def optimize(
"H2O-L": -0.15
}
},
+ "H2O": {
+ "CAPEX_A": 0.07726085034488815,
+ "OPEX_F": 0.0356900588308774,
+ "OPEX_O": 0,
+ "CONV": {
+ "EL": 0.003,
+ }
+ },
+ "CO2": {
+ "CAPEX_A": 0.07726085034488815,
+ "OPEX_F": 0.0356900588308774,
+ "OPEX_O": 0,
+ "CONV": {
+ "EL": 0.4515,
+ "HEAT": 1.743,
+ "H2O-L": -1.4
+ }
+ },
"EL_STR": {
"EFF": 0.544,
"CAPEX_A": 0.385,
@@ -149,6 +205,16 @@ def optimize(
n.add("Bus", "final_product", carrier="final_product")
n.add("Carrier", "final_product")
+ # if using water desalination, add seawater supply:
+ if input_data.get("H2O"):
+ carriers_sec.append("seawater")
+ input_data["SPECCOST"]["seawater"] = 0
+
+ # if using DAC, add air supply:
+ if input_data.get("CO2"):
+ carriers_sec.append("air")
+ input_data["SPECCOST"]["air"] = 0
+
# add RE generators:
for g in input_data["RES"]:
n.add("Carrier", name=g["PROCESS_CODE"])
@@ -186,50 +252,52 @@ def optimize(
p_nom=100,
)
+ # if using water desalination, remove external water supply:
+ if input_data.get("H2O"):
+ n.remove("Generator", "H2O-L_supply")
+ n.remove("Generator", "seawater_sink")
+
+ # if using DAC, remove external CO2 supply:
+ if input_data.get("CO2"):
+ n.remove("Generator", "CO2-G_supply")
+ n.remove("Generator", "air_sink")
+
# add links:
- # TODO: account for water demand
- n.add(
- "Link",
+ _add_link(
+ n=n,
+ input_data=input_data,
name="ELY",
bus0="EL",
bus1="H2",
- bus2="H2O-L",
carrier="H2",
- efficiency=input_data["ELY"]["EFF"],
- # input data is per main output,
- # pypsa link parameters are defined per main input
- efficiency2=-input_data["ELY"]["CONV"]["H2O-L"] / input_data["ELY"]["EFF"],
- capital_cost=(input_data["ELY"]["CAPEX_A"] + input_data["ELY"]["OPEX_F"])
- / input_data["ELY"]["EFF"],
- marginal_cost=input_data["ELY"]["OPEX_O"] / input_data["ELY"]["EFF"],
- p_nom_extendable=True,
)
- if input_data.get("DERIV"):
- n.add(
- "Link",
- name="DERIV",
- bus0="H2",
- bus1="final_product",
- carrier="final_product",
- efficiency=input_data["DERIV"]["EFF"],
- # input data is per main output,
- # pypsa link parameters are defined per main input
- capital_cost=(
- input_data["DERIV"]["CAPEX_A"] + input_data["DERIV"]["OPEX_F"]
- )
- / input_data["DERIV"]["EFF"],
- marginal_cost=input_data["DERIV"]["OPEX_O"] / input_data["DERIV"]["EFF"],
- p_nom_extendable=True,
- )
- # add conversion efficiencies and buses for secondary input / output
- for i, c in enumerate(input_data["DERIV"]["CONV"].keys()):
- n.links.at["DERIV", f"bus{i+2}"] = c
- # input data is per main output,
- # pypsa link parameters are defined per main input
- n.links.at["DERIV", f"efficiency{i+2}"] = (
- -input_data["DERIV"]["CONV"][c] / input_data["DERIV"]["EFF"]
- )
+ _add_link(
+ n=n,
+ input_data=input_data,
+ name="DERIV",
+ bus0="H2",
+ bus1="final_product",
+ carrier="final_product",
+ )
+
+ _add_link(
+ n=n,
+ input_data=input_data,
+ name="H2O",
+ bus0="seawater",
+ bus1="H2O-L",
+ carrier="H2O-L",
+ )
+
+ _add_link(
+ n=n,
+ input_data=input_data,
+ name="CO2",
+ bus0="air",
+ bus1="CO2-G",
+ carrier="CO2-G",
+ )
# add loads:
if input_data.get("DERIV"):
@@ -382,9 +450,11 @@ def get_flh(n: Network, g: str, component_type: str) -> float:
)
result_data["RES"].append(d)
- # Calculate FLH for electrolyzer:
- result_data["ELY"] = {}
- result_data["ELY"]["FLH"] = get_flh(n, "ELY", "Link")
+ # Calculate FLH for ELY, DERIV, DAC and DESAL:
+ for c in ["ELY", "DERIV", "CO2", "H2O"]:
+ if input_data.get(c):
+ result_data[c] = {}
+ result_data[c]["FLH"] = get_flh(n, c, "Link")
# calculate capacity factor for storage units:
# we use charging capacity (p_nom) per final product demand
@@ -393,7 +463,5 @@ def get_flh(n: Network, g: str, component_type: str) -> float:
if input_data.get("DERIV"):
result_data["H2_STR"] = {}
result_data["H2_STR"]["CAP_F"] = n.links.at["H2_STR_in", "p_nom_opt"]
- result_data["DERIV"] = {}
- result_data["DERIV"]["FLH"] = get_flh(n, "DERIV", "Link")
return result_data, n
diff --git a/img/inout_Electrolysis.png b/img/inout_Electrolysis.png
deleted file mode 100644
index 856f7cd6..00000000
Binary files a/img/inout_Electrolysis.png and /dev/null differ
diff --git a/img/inout_General.png b/img/inout_General.png
deleted file mode 100644
index ce60983f..00000000
Binary files a/img/inout_General.png and /dev/null differ
diff --git a/img/inout_Transport.png b/img/inout_Transport.png
deleted file mode 100644
index 098cd9a2..00000000
Binary files a/img/inout_Transport.png and /dev/null differ
diff --git a/img/inout_derivate_production.png b/img/inout_derivate_production.png
index 5610194e..5f0910e9 100644
Binary files a/img/inout_derivate_production.png and b/img/inout_derivate_production.png differ
diff --git a/img/inout_electricity_generation.png b/img/inout_electricity_generation.png
index f697ffa2..6ade7f7b 100644
Binary files a/img/inout_electricity_generation.png and b/img/inout_electricity_generation.png differ
diff --git a/img/inout_electrolysis.png b/img/inout_electrolysis.png
index 856f7cd6..07bcefc8 100644
Binary files a/img/inout_electrolysis.png and b/img/inout_electrolysis.png differ
diff --git a/img/inout_general.png b/img/inout_general.png
index ce60983f..b56d2d99 100644
Binary files a/img/inout_general.png and b/img/inout_general.png differ
diff --git a/img/inout_transport.png b/img/inout_transport.png
index 098cd9a2..27fdd760 100644
Binary files a/img/inout_transport.png and b/img/inout_transport.png differ
diff --git a/img/transparent_10x10.png b/img/transparent_10x10.png
new file mode 100644
index 00000000..2f377463
Binary files /dev/null and b/img/transparent_10x10.png differ
diff --git a/md/helptext_columns_lifetime.md b/md/helptext_columns_lifetime.md
index e2d5b2ec..048f015e 100644
--- a/md/helptext_columns_lifetime.md
+++ b/md/helptext_columns_lifetime.md
@@ -1,3 +1,3 @@
-The lifetime of a process is used (in combination with the WACC / interest rate) to distribute its capital costs across time.
+The lifetime of a process is used (in combination with the WACC) to distribute its capital costs across time.
Longer lifetimes lead to lower costs per kWh delivered.
diff --git a/md/helptext_technical_potential.md b/md/helptext_technical_potential.md
new file mode 100644
index 00000000..8044dfe6
--- /dev/null
+++ b/md/helptext_technical_potential.md
@@ -0,0 +1,5 @@
+Please note that many assumptions are needed to estimate technical RE potentials. Data across sources varies significantly, and not all PtXBOA supply regions are covered by the two sources used here.
+
+If a supply region is not covered by the source, it will not show up in the diagram. Please choose "None" to show all supply regions.
+
+If you select a deep-dive country subregion as source region, it will show up in the diagram, and the potential of the country it belongs to will be divided equally across all subregions of this country.
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.
diff --git a/md/whatisthis_input_data.md b/md/whatisthis_input_data.md
index 86a41d24..6a1e2609 100644
--- a/md/whatisthis_input_data.md
+++ b/md/whatisthis_input_data.md
@@ -2,7 +2,7 @@
This tab gives you an overview of model input data that is country-specific.
-First you get an overview of data that is region specific: CAPEX, full load hours of renewables, and interest rates (WACC). For CAPEX and full load hours you can choose which source to display in map and data tables.
+First you get an overview of data that is region specific: CAPEX, full load hours of renewables, and Weighted Average Cost of Capital (WACC). For CAPEX and full load hours you can choose which source to display in map and data tables.
Next follows a list of global input data (that is not region specific). It is structured by expandable sections, each one containing a data table.
diff --git a/ptxboa/api_optimize.py b/ptxboa/api_optimize.py
index 0ce9b023..0802e608 100644
--- a/ptxboa/api_optimize.py
+++ b/ptxboa/api_optimize.py
@@ -15,7 +15,7 @@
from pypsa import Network
from flh_opt import __version__ as flh_opt_version
-from flh_opt._types import OptInputDataType, OptOutputDataType
+from flh_opt._types import OptInputDataType, OptOutputDataType, SecProcessInputDataType
from flh_opt.api_opt import optimize
from ptxboa import logger
from ptxboa.static._types import CalculateDataType
@@ -183,7 +183,7 @@ def combine_location_and_source(re_location, re_source):
class PtxOpt:
def __init__(self, profiles_path: Path, cache_dir: Path):
- self.cache_dir = cache_dir
+ self.cache_dir = Path(cache_dir) if cache_dir else None
self.profiles_hashes = ProfilesHashes(profiles_path)
self.profiles_flh = ProfilesFLH(profiles_path)
@@ -248,6 +248,10 @@ def _prepare_data(input_data: CalculateDataType) -> OptInputDataType:
"N2-G": input_data["parameter"]["SPECCOST"]["N2-G"],
"HEAT": input_data["parameter"]["SPECCOST"]["HEAT"],
},
+ "EL_STR": None,
+ "H2_STR": None,
+ "CO2": None,
+ "H2O": None,
}
for step in input_data["main_process_chain"]:
@@ -318,6 +322,24 @@ def _prepare_data(input_data: CalculateDataType) -> OptInputDataType:
"OPEX_O": step["OPEX-O"],
}
+ # data for secondary processes
+ for step, flow_code in [("H2O", "H2O-L"), ("CO2", "CO2-G")]:
+ sec_process_data = input_data["secondary_process"].get(flow_code)
+ if not sec_process_data:
+ continue
+
+ result_sec_process_data: SecProcessInputDataType = {
+ "CAPEX_A": annuity(
+ periods=sec_process_data["LIFETIME"],
+ rate=input_data["parameter"]["WACC"],
+ value=sec_process_data["CAPEX"],
+ ),
+ "OPEX_F": sec_process_data["OPEX-F"],
+ "OPEX_O": sec_process_data["OPEX-O"],
+ "CONV": sec_process_data["CONV"],
+ }
+ result[step] = result_sec_process_data
+
return result
@staticmethod
@@ -352,6 +374,13 @@ def _merge_data(input_data: CalculateDataType, opt_output_data: OptOutputDataTyp
step["FLH"] = opt_output_data["ELY"]["FLH"] * 8760
elif step["step"] == "DERIV":
step["FLH"] = opt_output_data["DERIV"]["FLH"] * 8760
+ # secondary processes
+ for step, flow_code in [("H2O", "H2O-L"), ("CO2", "CO2-G")]:
+ sec_process_data = input_data["secondary_process"].get(flow_code)
+ if not sec_process_data:
+ continue
+ sec_process_data["FLH"] = opt_output_data[step]["FLH"] * 8760
+
else:
logger.warning("Optimization not successful.")
logger.warning(f"Solver status:{opt_output_data['model_status'][0]}")
diff --git a/ptxboa/static/__init__.py b/ptxboa/static/__init__.py
index 18402fd7..b47987d1 100644
--- a/ptxboa/static/__init__.py
+++ b/ptxboa/static/__init__.py
@@ -1,807 +1,807 @@
-# -*- coding: utf-8 -*-
-"""DO NOT EDIT (created by _update_static.py)."""
-
-from typing import Literal
-
-YearType = Literal["2030", "2040"]
-YearValues = ["2030", "2040"]
-
-
-ParameterRangeType = Literal["high", "low", "medium"]
-ParameterRangeValues = ["high", "low", "medium"]
-
-
-SourceRegionCodeType = Literal[
- "ARE",
- "ARG",
- "ARG-BA",
- "ARG-CAT",
- "ARG-CBA",
- "ARG-CHA",
- "ARG-CHU",
- "ARG-COR",
- "ARG-CRB",
- "ARG-CRU",
- "ARG-EST",
- "ARG-FOR",
- "ARG-FUE",
- "ARG-JUJ",
- "ARG-LAR",
- "ARG-MEN",
- "ARG-MIS",
- "ARG-NEG",
- "ARG-NEU",
- "ARG-PAM",
- "ARG-RIO",
- "ARG-SAF",
- "ARG-SAJ",
- "ARG-SAL",
- "ARG-SAT",
- "ARG-TUC",
- "AUS",
- "BRA",
- "CHL",
- "CHN",
- "COL",
- "CRI",
- "DNK",
- "DZA",
- "EGY",
- "ESP",
- "IDN",
- "IND",
- "JOR",
- "KAZ",
- "KEN",
- "MAR",
- "MAR-BEN",
- "MAR-CAS",
- "MAR-DAK",
- "MAR-DRA",
- "MAR-FES",
- "MAR-GUE",
- "MAR-LAA",
- "MAR-LOR",
- "MAR-MAR",
- "MAR-RAB",
- "MAR-SOU",
- "MAR-TAN",
- "MEX",
- "MRT",
- "NAM",
- "NOR",
- "PER",
- "PRT",
- "RUS",
- "SAU",
- "SWE",
- "THA",
- "TUN",
- "UKR",
- "URY",
- "USA",
- "VNM",
- "ZAF",
- "ZAF-EC",
- "ZAF-FRS",
- "ZAF-GAU",
- "ZAF-KWA",
- "ZAF-LIM",
- "ZAF-MPU",
- "ZAF-NC",
- "ZAF-NW",
- "ZAF-WC",
-]
-SourceRegionCodeValues = [
- "ARE",
- "ARG",
- "ARG-BA",
- "ARG-CAT",
- "ARG-CBA",
- "ARG-CHA",
- "ARG-CHU",
- "ARG-COR",
- "ARG-CRB",
- "ARG-CRU",
- "ARG-EST",
- "ARG-FOR",
- "ARG-FUE",
- "ARG-JUJ",
- "ARG-LAR",
- "ARG-MEN",
- "ARG-MIS",
- "ARG-NEG",
- "ARG-NEU",
- "ARG-PAM",
- "ARG-RIO",
- "ARG-SAF",
- "ARG-SAJ",
- "ARG-SAL",
- "ARG-SAT",
- "ARG-TUC",
- "AUS",
- "BRA",
- "CHL",
- "CHN",
- "COL",
- "CRI",
- "DNK",
- "DZA",
- "EGY",
- "ESP",
- "IDN",
- "IND",
- "JOR",
- "KAZ",
- "KEN",
- "MAR",
- "MAR-BEN",
- "MAR-CAS",
- "MAR-DAK",
- "MAR-DRA",
- "MAR-FES",
- "MAR-GUE",
- "MAR-LAA",
- "MAR-LOR",
- "MAR-MAR",
- "MAR-RAB",
- "MAR-SOU",
- "MAR-TAN",
- "MEX",
- "MRT",
- "NAM",
- "NOR",
- "PER",
- "PRT",
- "RUS",
- "SAU",
- "SWE",
- "THA",
- "TUN",
- "UKR",
- "URY",
- "USA",
- "VNM",
- "ZAF",
- "ZAF-EC",
- "ZAF-FRS",
- "ZAF-GAU",
- "ZAF-KWA",
- "ZAF-LIM",
- "ZAF-MPU",
- "ZAF-NC",
- "ZAF-NW",
- "ZAF-WC",
-]
-
-
-TargetCountryCodeType = Literal[
- "CHN", "DEU", "ESP", "FRA", "IND", "JPN", "KOR", "NLD", "USA"
-]
-TargetCountryCodeValues = [
- "CHN",
- "DEU",
- "ESP",
- "FRA",
- "IND",
- "JPN",
- "KOR",
- "NLD",
- "USA",
-]
-
-
-SourceRegionNameType = Literal[
- "Algeria",
- "Argentina",
- "Argentina (Autonomous City of Buenos Aires)",
- "Argentina (Buenos Aires)",
- "Argentina (Catamarca)",
- "Argentina (Chaco)",
- "Argentina (Chubut)",
- "Argentina (Córdoba)",
- "Argentina (Corrientes)",
- "Argentina (Entre Ríos)",
- "Argentina (Formosa)",
- "Argentina (Jujuy)",
- "Argentina (La Pampa)",
- "Argentina (La Rioja)",
- "Argentina (Mendoza)",
- "Argentina (Misiones)",
- "Argentina (Neuquén)",
- "Argentina (Río Negro)",
- "Argentina (Salta)",
- "Argentina (San Juan)",
- "Argentina (San Luis)",
- "Argentina (Santa Cruz)",
- "Argentina (Santa Fe)",
- "Argentina (Santiago del Estero)",
- "Argentina (Tierra del Fuego, Antártida e Islas del Atlántico Sur)",
- "Argentina (Tucumán)",
- "Australia",
- "Brazil",
- "Chile",
- "China",
- "Colombia",
- "Costa Rica",
- "Denmark",
- "Egypt",
- "India",
- "Indonesia",
- "Jordan",
- "Kazakhstan",
- "Kenya",
- "Mauritania",
- "Mexico",
- "Morocco",
- "Morocco (Béni Mellal-Khénifra)",
- "Morocco (Casablanca)",
- "Morocco (Dakhla-Oued Ed-Dahab)",
- "Morocco (Drâa-Tafilalet)",
- "Morocco (Fès-Meknès)",
- "Morocco (Guelmim-Oued Noun)",
- "Morocco (L´oriental)",
- "Morocco (Laâyoune-Sakia El Hamra)",
- "Morocco (Marrakech-Safi)",
- "Morocco (Rabat-Salé-Kénitra)",
- "Morocco (Souss-Massa)",
- "Morocco (Tangier)",
- "Namibia",
- "Norway",
- "Peru",
- "Portugal",
- "Russia",
- "Saudi Arabia",
- "South Africa",
- "South Africa (East Cape)",
- "South Africa (Free State)",
- "South Africa (Gauteng)",
- "South Africa (KwaZulu-Natal)",
- "South Africa (Limpopo)",
- "South Africa (Mpumalanga)",
- "South Africa (North West)",
- "South Africa (Northern Cape)",
- "South Africa (Western Cape)",
- "Spain",
- "Sweden",
- "Thailand",
- "Tunisia",
- "Ukraine",
- "United Arab Emirates",
- "Uruguay",
- "USA",
- "Vietnam",
-]
-SourceRegionNameValues = [
- "Algeria",
- "Argentina",
- "Argentina (Autonomous City of Buenos Aires)",
- "Argentina (Buenos Aires)",
- "Argentina (Catamarca)",
- "Argentina (Chaco)",
- "Argentina (Chubut)",
- "Argentina (Córdoba)",
- "Argentina (Corrientes)",
- "Argentina (Entre Ríos)",
- "Argentina (Formosa)",
- "Argentina (Jujuy)",
- "Argentina (La Pampa)",
- "Argentina (La Rioja)",
- "Argentina (Mendoza)",
- "Argentina (Misiones)",
- "Argentina (Neuquén)",
- "Argentina (Río Negro)",
- "Argentina (Salta)",
- "Argentina (San Juan)",
- "Argentina (San Luis)",
- "Argentina (Santa Cruz)",
- "Argentina (Santa Fe)",
- "Argentina (Santiago del Estero)",
- "Argentina (Tierra del Fuego, Antártida e Islas del Atlántico Sur)",
- "Argentina (Tucumán)",
- "Australia",
- "Brazil",
- "Chile",
- "China",
- "Colombia",
- "Costa Rica",
- "Denmark",
- "Egypt",
- "India",
- "Indonesia",
- "Jordan",
- "Kazakhstan",
- "Kenya",
- "Mauritania",
- "Mexico",
- "Morocco",
- "Morocco (Béni Mellal-Khénifra)",
- "Morocco (Casablanca)",
- "Morocco (Dakhla-Oued Ed-Dahab)",
- "Morocco (Drâa-Tafilalet)",
- "Morocco (Fès-Meknès)",
- "Morocco (Guelmim-Oued Noun)",
- "Morocco (L´oriental)",
- "Morocco (Laâyoune-Sakia El Hamra)",
- "Morocco (Marrakech-Safi)",
- "Morocco (Rabat-Salé-Kénitra)",
- "Morocco (Souss-Massa)",
- "Morocco (Tangier)",
- "Namibia",
- "Norway",
- "Peru",
- "Portugal",
- "Russia",
- "Saudi Arabia",
- "South Africa",
- "South Africa (East Cape)",
- "South Africa (Free State)",
- "South Africa (Gauteng)",
- "South Africa (KwaZulu-Natal)",
- "South Africa (Limpopo)",
- "South Africa (Mpumalanga)",
- "South Africa (North West)",
- "South Africa (Northern Cape)",
- "South Africa (Western Cape)",
- "Spain",
- "Sweden",
- "Thailand",
- "Tunisia",
- "Ukraine",
- "United Arab Emirates",
- "Uruguay",
- "USA",
- "Vietnam",
-]
-
-
-TargetCountryNameType = Literal[
- "China",
- "France",
- "Germany",
- "India",
- "Japan",
- "Netherlands",
- "South Korea",
- "Spain",
- "USA",
-]
-TargetCountryNameValues = [
- "China",
- "France",
- "Germany",
- "India",
- "Japan",
- "Netherlands",
- "South Korea",
- "Spain",
- "USA",
-]
-
-
-ProcessCodeType = Literal[
- "AEL-EL",
- "ATR",
- "CH3OHREC",
- "CH3OH-S",
- "CH3OH-SB",
- "CH3OHSYN",
- "CH4-COMP",
- "CH4-LIQ",
- "CH4-P-L",
- "CH4-P-LR",
- "CH4-P-S",
- "CH4-P-SR",
- "CH4-RGAS",
- "CH4-S",
- "CH4-SB",
- "CH4SYN",
- "DAC",
- "DESAL",
- "DRI",
- "DRI-S",
- "DRI-SB",
- "EFUELSYN",
- "EL-STR",
- "EL-TRANS",
- "H2-COMP",
- "H2-LIQ",
- "H2-P-L",
- "H2-P-LR",
- "H2-P-S",
- "H2-P-SR",
- "H2-RGAS",
- "H2-S",
- "H2-SB",
- "H2-STR",
- "LOHC-CON",
- "LOHC-REC",
- "LOHC-S",
- "LOHC-SB",
- "NH3-REC",
- "NH3-S",
- "NH3-SB",
- "NH3SYN",
- "PEM-EL",
- "PV-FIX",
- "PV-TRK",
- "REGASATR",
- "RES-HYBR",
- "SOEC-EL",
- "SYN-S",
- "SYN-SB",
- "WIND-OFF",
- "WIND-ON",
-]
-ProcessCodeValues = [
- "AEL-EL",
- "ATR",
- "CH3OHREC",
- "CH3OH-S",
- "CH3OH-SB",
- "CH3OHSYN",
- "CH4-COMP",
- "CH4-LIQ",
- "CH4-P-L",
- "CH4-P-LR",
- "CH4-P-S",
- "CH4-P-SR",
- "CH4-RGAS",
- "CH4-S",
- "CH4-SB",
- "CH4SYN",
- "DAC",
- "DESAL",
- "DRI",
- "DRI-S",
- "DRI-SB",
- "EFUELSYN",
- "EL-STR",
- "EL-TRANS",
- "H2-COMP",
- "H2-LIQ",
- "H2-P-L",
- "H2-P-LR",
- "H2-P-S",
- "H2-P-SR",
- "H2-RGAS",
- "H2-S",
- "H2-SB",
- "H2-STR",
- "LOHC-CON",
- "LOHC-REC",
- "LOHC-S",
- "LOHC-SB",
- "NH3-REC",
- "NH3-S",
- "NH3-SB",
- "NH3SYN",
- "PEM-EL",
- "PV-FIX",
- "PV-TRK",
- "REGASATR",
- "RES-HYBR",
- "SOEC-EL",
- "SYN-S",
- "SYN-SB",
- "WIND-OFF",
- "WIND-ON",
-]
-
-
-FlowCodeType = Literal[
- "BFUEL-L",
- "CH3OH-L",
- "CH4-G",
- "CH4-L",
- "CHX-L",
- "CO2-G",
- "C-S",
- "DRI-S",
- "EL",
- "H2-G",
- "H2-L",
- "H2O-L",
- "HEAT",
- "LOHC-L",
- "N2-G",
- "NH3-L",
-]
-FlowCodeValues = [
- "BFUEL-L",
- "CH3OH-L",
- "CH4-G",
- "CH4-L",
- "CHX-L",
- "CO2-G",
- "C-S",
- "DRI-S",
- "EL",
- "H2-G",
- "H2-L",
- "H2O-L",
- "HEAT",
- "LOHC-L",
- "N2-G",
- "NH3-L",
-]
-
-
-ParameterCodeType = Literal[
- "CALOR",
- "CAPEX",
- "CAP-T",
- "CONV",
- "DST-S-D",
- "DST-S-DP",
- "EFF",
- "FLH",
- "LIFETIME",
- "LOSS-T",
- "OPEX-F",
- "OPEX-O",
- "OPEX-T",
- "RE-POT",
- "SEASHARE",
- "SPECCOST",
- "WACC",
-]
-ParameterCodeValues = [
- "CALOR",
- "CAPEX",
- "CAP-T",
- "CONV",
- "DST-S-D",
- "DST-S-DP",
- "EFF",
- "FLH",
- "LIFETIME",
- "LOSS-T",
- "OPEX-F",
- "OPEX-O",
- "OPEX-T",
- "RE-POT",
- "SEASHARE",
- "SPECCOST",
- "WACC",
-]
-
-
-ParameterNameType = Literal[
- "calorific values",
- "CAPEX",
- "conversion factors",
- "efficiency",
- "full load hours",
- "interest rate",
- "levelized costs",
- "lifetime / amortization period",
- "losses (own fuel, transport)",
- "OPEX (fix)",
- "OPEX (other variable)",
- "pipeline distance",
- "RE potential",
- "sea share of pipeline distance",
- "shipping distance",
- "specific costs",
- "transport capacity",
-]
-ParameterNameValues = [
- "calorific values",
- "CAPEX",
- "conversion factors",
- "efficiency",
- "full load hours",
- "interest rate",
- "levelized costs",
- "lifetime / amortization period",
- "losses (own fuel, transport)",
- "OPEX (fix)",
- "OPEX (other variable)",
- "pipeline distance",
- "RE potential",
- "sea share of pipeline distance",
- "shipping distance",
- "specific costs",
- "transport capacity",
-]
-
-
-ChainNameType = Literal[
- "Ammonia (AEL)",
- "Ammonia (AEL) + reconv. to H2",
- "Ammonia (PEM)",
- "Ammonia (PEM) + reconv. to H2",
- "Ammonia (SEOC)",
- "Ammonia (SEOC) + reconv. to H2",
- "FT e-fuels (AEL)",
- "FT e-fuels (PEM)",
- "FT e-fuels (SEOC)",
- "Green Iron (AEL)",
- "Green Iron (PEM)",
- "Green Iron (SEOC)",
- "Hydrogen (AEL)",
- "Hydrogen (PEM)",
- "Hydrogen (SEOC)",
- "LOHC (AEL)",
- "LOHC (PEM)",
- "LOHC (SEOC)",
- "Methane (AEL)",
- "Methane (AEL) + reconv. to H2",
- "Methane (PEM)",
- "Methane (PEM) + reconv. to H2",
- "Methane (SEOC)",
- "Methane (SEOC) + reconv. to H2",
- "Methanol (AEL)",
- "Methanol (PEM)",
- "Methanol (SEOC)",
-]
-ChainNameValues = [
- "Ammonia (AEL)",
- "Ammonia (AEL) + reconv. to H2",
- "Ammonia (PEM)",
- "Ammonia (PEM) + reconv. to H2",
- "Ammonia (SEOC)",
- "Ammonia (SEOC) + reconv. to H2",
- "FT e-fuels (AEL)",
- "FT e-fuels (PEM)",
- "FT e-fuels (SEOC)",
- "Green Iron (AEL)",
- "Green Iron (PEM)",
- "Green Iron (SEOC)",
- "Hydrogen (AEL)",
- "Hydrogen (PEM)",
- "Hydrogen (SEOC)",
- "LOHC (AEL)",
- "LOHC (PEM)",
- "LOHC (SEOC)",
- "Methane (AEL)",
- "Methane (AEL) + reconv. to H2",
- "Methane (PEM)",
- "Methane (PEM) + reconv. to H2",
- "Methane (SEOC)",
- "Methane (SEOC) + reconv. to H2",
- "Methanol (AEL)",
- "Methanol (PEM)",
- "Methanol (SEOC)",
-]
-
-
-ScenarioType = Literal[
- "2030 (high)",
- "2030 (low)",
- "2030 (medium)",
- "2040 (high)",
- "2040 (low)",
- "2040 (medium)",
-]
-ScenarioValues = [
- "2030 (high)",
- "2030 (low)",
- "2030 (medium)",
- "2040 (high)",
- "2040 (low)",
- "2040 (medium)",
-]
-
-
-ResultClassType = Literal[
- "Carbon",
- "Derivate production",
- "Electricity and H2 storage",
- "Electricity generation",
- "Electrolysis",
- "HEAT",
- "Transportation (Pipeline)",
- "Transportation (Ship)",
- "Water",
-]
-ResultClassValues = [
- "Carbon",
- "Derivate production",
- "Electricity and H2 storage",
- "Electricity generation",
- "Electrolysis",
- "HEAT",
- "Transportation (Pipeline)",
- "Transportation (Ship)",
- "Water",
-]
-
-
-SecProcCO2Type = Literal["Direct Air Capture"]
-SecProcCO2Values = ["Direct Air Capture"]
-
-
-SecProcH2OType = Literal["Sea Water desalination"]
-SecProcH2OValues = ["Sea Water desalination"]
-
-
-ResGenType = Literal[
- "PV tilted", "PV tracking", "Wind-PV-Hybrid", "Wind Offshore", "Wind Onshore"
-]
-ResGenValues = [
- "PV tilted",
- "PV tracking",
- "Wind-PV-Hybrid",
- "Wind Offshore",
- "Wind Onshore",
-]
-
-
-ProcessCodeResType = Literal["PV-FIX", "PV-TRK", "RES-HYBR", "WIND-OFF", "WIND-ON"]
-ProcessCodeResValues = ["PV-FIX", "PV-TRK", "RES-HYBR", "WIND-OFF", "WIND-ON"]
-
-
-DimensionType = Literal[
- "scenario",
- "chain",
- "region",
- "country",
- "transport",
- "output_unit",
- "flow",
- "process",
- "secproc_co2",
- "secproc_water",
- "res_gen",
-]
-DimensionValues = [
- "scenario",
- "chain",
- "region",
- "country",
- "transport",
- "output_unit",
- "flow",
- "process",
- "secproc_co2",
- "secproc_water",
- "res_gen",
-]
-
-
-ProcessStepType = Literal[
- "EL_STR",
- "ELY",
- "H2_STR",
- "DERIV",
- "PRE_SHP",
- "PRE_PPL",
- "POST_SHP",
- "POST_PPL",
- "SHP",
- "SHP-OWN",
- "PPLS",
- "PPL",
- "PPLX",
- "PPLR",
-]
-ProcessStepValues = [
- "EL_STR",
- "ELY",
- "H2_STR",
- "DERIV",
- "PRE_SHP",
- "PRE_PPL",
- "POST_SHP",
- "POST_PPL",
- "SHP",
- "SHP-OWN",
- "PPLS",
- "PPL",
- "PPLX",
- "PPLR",
-]
-
-
-ResultCostType = Literal["CAPEX", "OPEX", "FLOW", "LC"]
-ResultCostValues = ["CAPEX", "OPEX", "FLOW", "LC"]
-
-
-TransportType = Literal["Ship", "Pipeline"]
-TransportValues = ["Ship", "Pipeline"]
-
-
-OutputUnitType = Literal["USD/MWh", "USD/t"]
-OutputUnitValues = ["USD/MWh", "USD/t"]
+# -*- coding: utf-8 -*-
+"""DO NOT EDIT (created by _update_static.py)."""
+
+from typing import Literal
+
+YearType = Literal["2030", "2040"]
+YearValues = ["2030", "2040"]
+
+
+ParameterRangeType = Literal["high", "low", "medium"]
+ParameterRangeValues = ["high", "low", "medium"]
+
+
+SourceRegionCodeType = Literal[
+ "ARE",
+ "ARG",
+ "ARG-BA",
+ "ARG-CAT",
+ "ARG-CBA",
+ "ARG-CHA",
+ "ARG-CHU",
+ "ARG-COR",
+ "ARG-CRB",
+ "ARG-CRU",
+ "ARG-EST",
+ "ARG-FOR",
+ "ARG-FUE",
+ "ARG-JUJ",
+ "ARG-LAR",
+ "ARG-MEN",
+ "ARG-MIS",
+ "ARG-NEG",
+ "ARG-NEU",
+ "ARG-PAM",
+ "ARG-RIO",
+ "ARG-SAF",
+ "ARG-SAJ",
+ "ARG-SAL",
+ "ARG-SAT",
+ "ARG-TUC",
+ "AUS",
+ "BRA",
+ "CHL",
+ "CHN",
+ "COL",
+ "CRI",
+ "DNK",
+ "DZA",
+ "EGY",
+ "ESP",
+ "IDN",
+ "IND",
+ "JOR",
+ "KAZ",
+ "KEN",
+ "MAR",
+ "MAR-BEN",
+ "MAR-CAS",
+ "MAR-DAK",
+ "MAR-DRA",
+ "MAR-FES",
+ "MAR-GUE",
+ "MAR-LAA",
+ "MAR-LOR",
+ "MAR-MAR",
+ "MAR-RAB",
+ "MAR-SOU",
+ "MAR-TAN",
+ "MEX",
+ "MRT",
+ "NAM",
+ "NOR",
+ "PER",
+ "PRT",
+ "RUS",
+ "SAU",
+ "SWE",
+ "THA",
+ "TUN",
+ "UKR",
+ "URY",
+ "USA",
+ "VNM",
+ "ZAF",
+ "ZAF-EC",
+ "ZAF-FRS",
+ "ZAF-GAU",
+ "ZAF-KWA",
+ "ZAF-LIM",
+ "ZAF-MPU",
+ "ZAF-NC",
+ "ZAF-NW",
+ "ZAF-WC",
+]
+SourceRegionCodeValues = [
+ "ARE",
+ "ARG",
+ "ARG-BA",
+ "ARG-CAT",
+ "ARG-CBA",
+ "ARG-CHA",
+ "ARG-CHU",
+ "ARG-COR",
+ "ARG-CRB",
+ "ARG-CRU",
+ "ARG-EST",
+ "ARG-FOR",
+ "ARG-FUE",
+ "ARG-JUJ",
+ "ARG-LAR",
+ "ARG-MEN",
+ "ARG-MIS",
+ "ARG-NEG",
+ "ARG-NEU",
+ "ARG-PAM",
+ "ARG-RIO",
+ "ARG-SAF",
+ "ARG-SAJ",
+ "ARG-SAL",
+ "ARG-SAT",
+ "ARG-TUC",
+ "AUS",
+ "BRA",
+ "CHL",
+ "CHN",
+ "COL",
+ "CRI",
+ "DNK",
+ "DZA",
+ "EGY",
+ "ESP",
+ "IDN",
+ "IND",
+ "JOR",
+ "KAZ",
+ "KEN",
+ "MAR",
+ "MAR-BEN",
+ "MAR-CAS",
+ "MAR-DAK",
+ "MAR-DRA",
+ "MAR-FES",
+ "MAR-GUE",
+ "MAR-LAA",
+ "MAR-LOR",
+ "MAR-MAR",
+ "MAR-RAB",
+ "MAR-SOU",
+ "MAR-TAN",
+ "MEX",
+ "MRT",
+ "NAM",
+ "NOR",
+ "PER",
+ "PRT",
+ "RUS",
+ "SAU",
+ "SWE",
+ "THA",
+ "TUN",
+ "UKR",
+ "URY",
+ "USA",
+ "VNM",
+ "ZAF",
+ "ZAF-EC",
+ "ZAF-FRS",
+ "ZAF-GAU",
+ "ZAF-KWA",
+ "ZAF-LIM",
+ "ZAF-MPU",
+ "ZAF-NC",
+ "ZAF-NW",
+ "ZAF-WC",
+]
+
+
+TargetCountryCodeType = Literal[
+ "CHN", "DEU", "ESP", "FRA", "IND", "JPN", "KOR", "NLD", "USA"
+]
+TargetCountryCodeValues = [
+ "CHN",
+ "DEU",
+ "ESP",
+ "FRA",
+ "IND",
+ "JPN",
+ "KOR",
+ "NLD",
+ "USA",
+]
+
+
+SourceRegionNameType = Literal[
+ "Algeria",
+ "Argentina",
+ "Argentina (Autonomous City of Buenos Aires)",
+ "Argentina (Buenos Aires)",
+ "Argentina (Catamarca)",
+ "Argentina (Chaco)",
+ "Argentina (Chubut)",
+ "Argentina (Córdoba)",
+ "Argentina (Corrientes)",
+ "Argentina (Entre Ríos)",
+ "Argentina (Formosa)",
+ "Argentina (Jujuy)",
+ "Argentina (La Pampa)",
+ "Argentina (La Rioja)",
+ "Argentina (Mendoza)",
+ "Argentina (Misiones)",
+ "Argentina (Neuquén)",
+ "Argentina (Río Negro)",
+ "Argentina (Salta)",
+ "Argentina (San Juan)",
+ "Argentina (San Luis)",
+ "Argentina (Santa Cruz)",
+ "Argentina (Santa Fe)",
+ "Argentina (Santiago del Estero)",
+ "Argentina (Tierra del Fuego, Antártida e Islas del Atlántico Sur)",
+ "Argentina (Tucumán)",
+ "Australia",
+ "Brazil",
+ "Chile",
+ "China",
+ "Colombia",
+ "Costa Rica",
+ "Denmark",
+ "Egypt",
+ "India",
+ "Indonesia",
+ "Jordan",
+ "Kazakhstan",
+ "Kenya",
+ "Mauritania",
+ "Mexico",
+ "Morocco",
+ "Morocco (Béni Mellal-Khénifra)",
+ "Morocco (Casablanca)",
+ "Morocco (Dakhla-Oued Ed-Dahab)",
+ "Morocco (Drâa-Tafilalet)",
+ "Morocco (Fès-Meknès)",
+ "Morocco (Guelmim-Oued Noun)",
+ "Morocco (L´oriental)",
+ "Morocco (Laâyoune-Sakia El Hamra)",
+ "Morocco (Marrakech-Safi)",
+ "Morocco (Rabat-Salé-Kénitra)",
+ "Morocco (Souss-Massa)",
+ "Morocco (Tangier)",
+ "Namibia",
+ "Norway",
+ "Peru",
+ "Portugal",
+ "Russia",
+ "Saudi Arabia",
+ "South Africa",
+ "South Africa (East Cape)",
+ "South Africa (Free State)",
+ "South Africa (Gauteng)",
+ "South Africa (KwaZulu-Natal)",
+ "South Africa (Limpopo)",
+ "South Africa (Mpumalanga)",
+ "South Africa (North West)",
+ "South Africa (Northern Cape)",
+ "South Africa (Western Cape)",
+ "Spain",
+ "Sweden",
+ "Thailand",
+ "Tunisia",
+ "Ukraine",
+ "United Arab Emirates",
+ "Uruguay",
+ "USA",
+ "Vietnam",
+]
+SourceRegionNameValues = [
+ "Algeria",
+ "Argentina",
+ "Argentina (Autonomous City of Buenos Aires)",
+ "Argentina (Buenos Aires)",
+ "Argentina (Catamarca)",
+ "Argentina (Chaco)",
+ "Argentina (Chubut)",
+ "Argentina (Córdoba)",
+ "Argentina (Corrientes)",
+ "Argentina (Entre Ríos)",
+ "Argentina (Formosa)",
+ "Argentina (Jujuy)",
+ "Argentina (La Pampa)",
+ "Argentina (La Rioja)",
+ "Argentina (Mendoza)",
+ "Argentina (Misiones)",
+ "Argentina (Neuquén)",
+ "Argentina (Río Negro)",
+ "Argentina (Salta)",
+ "Argentina (San Juan)",
+ "Argentina (San Luis)",
+ "Argentina (Santa Cruz)",
+ "Argentina (Santa Fe)",
+ "Argentina (Santiago del Estero)",
+ "Argentina (Tierra del Fuego, Antártida e Islas del Atlántico Sur)",
+ "Argentina (Tucumán)",
+ "Australia",
+ "Brazil",
+ "Chile",
+ "China",
+ "Colombia",
+ "Costa Rica",
+ "Denmark",
+ "Egypt",
+ "India",
+ "Indonesia",
+ "Jordan",
+ "Kazakhstan",
+ "Kenya",
+ "Mauritania",
+ "Mexico",
+ "Morocco",
+ "Morocco (Béni Mellal-Khénifra)",
+ "Morocco (Casablanca)",
+ "Morocco (Dakhla-Oued Ed-Dahab)",
+ "Morocco (Drâa-Tafilalet)",
+ "Morocco (Fès-Meknès)",
+ "Morocco (Guelmim-Oued Noun)",
+ "Morocco (L´oriental)",
+ "Morocco (Laâyoune-Sakia El Hamra)",
+ "Morocco (Marrakech-Safi)",
+ "Morocco (Rabat-Salé-Kénitra)",
+ "Morocco (Souss-Massa)",
+ "Morocco (Tangier)",
+ "Namibia",
+ "Norway",
+ "Peru",
+ "Portugal",
+ "Russia",
+ "Saudi Arabia",
+ "South Africa",
+ "South Africa (East Cape)",
+ "South Africa (Free State)",
+ "South Africa (Gauteng)",
+ "South Africa (KwaZulu-Natal)",
+ "South Africa (Limpopo)",
+ "South Africa (Mpumalanga)",
+ "South Africa (North West)",
+ "South Africa (Northern Cape)",
+ "South Africa (Western Cape)",
+ "Spain",
+ "Sweden",
+ "Thailand",
+ "Tunisia",
+ "Ukraine",
+ "United Arab Emirates",
+ "Uruguay",
+ "USA",
+ "Vietnam",
+]
+
+
+TargetCountryNameType = Literal[
+ "China",
+ "France",
+ "Germany",
+ "India",
+ "Japan",
+ "Netherlands",
+ "South Korea",
+ "Spain",
+ "USA",
+]
+TargetCountryNameValues = [
+ "China",
+ "France",
+ "Germany",
+ "India",
+ "Japan",
+ "Netherlands",
+ "South Korea",
+ "Spain",
+ "USA",
+]
+
+
+ProcessCodeType = Literal[
+ "AEL-EL",
+ "ATR",
+ "CH3OHREC",
+ "CH3OH-S",
+ "CH3OH-SB",
+ "CH3OHSYN",
+ "CH4-COMP",
+ "CH4-LIQ",
+ "CH4-P-L",
+ "CH4-P-LR",
+ "CH4-P-S",
+ "CH4-P-SR",
+ "CH4-RGAS",
+ "CH4-S",
+ "CH4-SB",
+ "CH4SYN",
+ "DAC",
+ "DESAL",
+ "DRI",
+ "DRI-S",
+ "DRI-SB",
+ "EFUELSYN",
+ "EL-STR",
+ "EL-TRANS",
+ "H2-COMP",
+ "H2-LIQ",
+ "H2-P-L",
+ "H2-P-LR",
+ "H2-P-S",
+ "H2-P-SR",
+ "H2-RGAS",
+ "H2-S",
+ "H2-SB",
+ "H2-STR",
+ "LOHC-CON",
+ "LOHC-REC",
+ "LOHC-S",
+ "LOHC-SB",
+ "NH3-REC",
+ "NH3-S",
+ "NH3-SB",
+ "NH3SYN",
+ "PEM-EL",
+ "PV-FIX",
+ "PV-TRK",
+ "REGASATR",
+ "RES-HYBR",
+ "SOEC-EL",
+ "SYN-S",
+ "SYN-SB",
+ "WIND-OFF",
+ "WIND-ON",
+]
+ProcessCodeValues = [
+ "AEL-EL",
+ "ATR",
+ "CH3OHREC",
+ "CH3OH-S",
+ "CH3OH-SB",
+ "CH3OHSYN",
+ "CH4-COMP",
+ "CH4-LIQ",
+ "CH4-P-L",
+ "CH4-P-LR",
+ "CH4-P-S",
+ "CH4-P-SR",
+ "CH4-RGAS",
+ "CH4-S",
+ "CH4-SB",
+ "CH4SYN",
+ "DAC",
+ "DESAL",
+ "DRI",
+ "DRI-S",
+ "DRI-SB",
+ "EFUELSYN",
+ "EL-STR",
+ "EL-TRANS",
+ "H2-COMP",
+ "H2-LIQ",
+ "H2-P-L",
+ "H2-P-LR",
+ "H2-P-S",
+ "H2-P-SR",
+ "H2-RGAS",
+ "H2-S",
+ "H2-SB",
+ "H2-STR",
+ "LOHC-CON",
+ "LOHC-REC",
+ "LOHC-S",
+ "LOHC-SB",
+ "NH3-REC",
+ "NH3-S",
+ "NH3-SB",
+ "NH3SYN",
+ "PEM-EL",
+ "PV-FIX",
+ "PV-TRK",
+ "REGASATR",
+ "RES-HYBR",
+ "SOEC-EL",
+ "SYN-S",
+ "SYN-SB",
+ "WIND-OFF",
+ "WIND-ON",
+]
+
+
+FlowCodeType = Literal[
+ "BFUEL-L",
+ "CH3OH-L",
+ "CH4-G",
+ "CH4-L",
+ "CHX-L",
+ "CO2-G",
+ "C-S",
+ "DRI-S",
+ "EL",
+ "H2-G",
+ "H2-L",
+ "H2O-L",
+ "HEAT",
+ "LOHC-L",
+ "N2-G",
+ "NH3-L",
+]
+FlowCodeValues = [
+ "BFUEL-L",
+ "CH3OH-L",
+ "CH4-G",
+ "CH4-L",
+ "CHX-L",
+ "CO2-G",
+ "C-S",
+ "DRI-S",
+ "EL",
+ "H2-G",
+ "H2-L",
+ "H2O-L",
+ "HEAT",
+ "LOHC-L",
+ "N2-G",
+ "NH3-L",
+]
+
+
+ParameterCodeType = Literal[
+ "CALOR",
+ "CAPEX",
+ "CAP-T",
+ "CONV",
+ "DST-S-D",
+ "DST-S-DP",
+ "EFF",
+ "FLH",
+ "LIFETIME",
+ "LOSS-T",
+ "OPEX-F",
+ "OPEX-O",
+ "OPEX-T",
+ "RE-POT",
+ "SEASHARE",
+ "SPECCOST",
+ "WACC",
+]
+ParameterCodeValues = [
+ "CALOR",
+ "CAPEX",
+ "CAP-T",
+ "CONV",
+ "DST-S-D",
+ "DST-S-DP",
+ "EFF",
+ "FLH",
+ "LIFETIME",
+ "LOSS-T",
+ "OPEX-F",
+ "OPEX-O",
+ "OPEX-T",
+ "RE-POT",
+ "SEASHARE",
+ "SPECCOST",
+ "WACC",
+]
+
+
+ParameterNameType = Literal[
+ "calorific values",
+ "CAPEX",
+ "conversion factors",
+ "efficiency",
+ "full load hours",
+ "levelized costs",
+ "lifetime / amortization period",
+ "losses (own fuel, transport)",
+ "OPEX (fix)",
+ "OPEX (other variable)",
+ "pipeline distance",
+ "RE potential",
+ "sea share of pipeline distance",
+ "shipping distance",
+ "specific costs",
+ "transport capacity",
+ "WACC",
+]
+ParameterNameValues = [
+ "calorific values",
+ "CAPEX",
+ "conversion factors",
+ "efficiency",
+ "full load hours",
+ "levelized costs",
+ "lifetime / amortization period",
+ "losses (own fuel, transport)",
+ "OPEX (fix)",
+ "OPEX (other variable)",
+ "pipeline distance",
+ "RE potential",
+ "sea share of pipeline distance",
+ "shipping distance",
+ "specific costs",
+ "transport capacity",
+ "WACC",
+]
+
+
+ChainNameType = Literal[
+ "Ammonia (AEL)",
+ "Ammonia (AEL) + reconv. to H2",
+ "Ammonia (PEM)",
+ "Ammonia (PEM) + reconv. to H2",
+ "Ammonia (SOEC)",
+ "Ammonia (SOEC) + reconv. to H2",
+ "FT e-fuels (AEL)",
+ "FT e-fuels (PEM)",
+ "FT e-fuels (SOEC)",
+ "Green Iron (AEL)",
+ "Green Iron (PEM)",
+ "Green Iron (SOEC)",
+ "Hydrogen (AEL)",
+ "Hydrogen (PEM)",
+ "Hydrogen (SOEC)",
+ "LOHC (AEL)",
+ "LOHC (PEM)",
+ "LOHC (SOEC)",
+ "Methane (AEL)",
+ "Methane (AEL) + reconv. to H2",
+ "Methane (PEM)",
+ "Methane (PEM) + reconv. to H2",
+ "Methane (SOEC)",
+ "Methane (SOEC) + reconv. to H2",
+ "Methanol (AEL)",
+ "Methanol (PEM)",
+ "Methanol (SOEC)",
+]
+ChainNameValues = [
+ "Ammonia (AEL)",
+ "Ammonia (AEL) + reconv. to H2",
+ "Ammonia (PEM)",
+ "Ammonia (PEM) + reconv. to H2",
+ "Ammonia (SOEC)",
+ "Ammonia (SOEC) + reconv. to H2",
+ "FT e-fuels (AEL)",
+ "FT e-fuels (PEM)",
+ "FT e-fuels (SOEC)",
+ "Green Iron (AEL)",
+ "Green Iron (PEM)",
+ "Green Iron (SOEC)",
+ "Hydrogen (AEL)",
+ "Hydrogen (PEM)",
+ "Hydrogen (SOEC)",
+ "LOHC (AEL)",
+ "LOHC (PEM)",
+ "LOHC (SOEC)",
+ "Methane (AEL)",
+ "Methane (AEL) + reconv. to H2",
+ "Methane (PEM)",
+ "Methane (PEM) + reconv. to H2",
+ "Methane (SOEC)",
+ "Methane (SOEC) + reconv. to H2",
+ "Methanol (AEL)",
+ "Methanol (PEM)",
+ "Methanol (SOEC)",
+]
+
+
+ScenarioType = Literal[
+ "2030 (high)",
+ "2030 (low)",
+ "2030 (medium)",
+ "2040 (high)",
+ "2040 (low)",
+ "2040 (medium)",
+]
+ScenarioValues = [
+ "2030 (high)",
+ "2030 (low)",
+ "2030 (medium)",
+ "2040 (high)",
+ "2040 (low)",
+ "2040 (medium)",
+]
+
+
+ResultClassType = Literal[
+ "Carbon",
+ "Derivate production",
+ "Electricity and H2 storage",
+ "Electricity generation",
+ "Electrolysis",
+ "HEAT",
+ "Transportation (Pipeline)",
+ "Transportation (Ship)",
+ "Water",
+]
+ResultClassValues = [
+ "Carbon",
+ "Derivate production",
+ "Electricity and H2 storage",
+ "Electricity generation",
+ "Electrolysis",
+ "HEAT",
+ "Transportation (Pipeline)",
+ "Transportation (Ship)",
+ "Water",
+]
+
+
+SecProcCO2Type = Literal["Direct Air Capture"]
+SecProcCO2Values = ["Direct Air Capture"]
+
+
+SecProcH2OType = Literal["Sea Water desalination"]
+SecProcH2OValues = ["Sea Water desalination"]
+
+
+ResGenType = Literal[
+ "PV tilted", "PV tracking", "Wind-PV-Hybrid", "Wind Offshore", "Wind Onshore"
+]
+ResGenValues = [
+ "PV tilted",
+ "PV tracking",
+ "Wind-PV-Hybrid",
+ "Wind Offshore",
+ "Wind Onshore",
+]
+
+
+ProcessCodeResType = Literal["PV-FIX", "PV-TRK", "RES-HYBR", "WIND-OFF", "WIND-ON"]
+ProcessCodeResValues = ["PV-FIX", "PV-TRK", "RES-HYBR", "WIND-OFF", "WIND-ON"]
+
+
+DimensionType = Literal[
+ "scenario",
+ "chain",
+ "region",
+ "country",
+ "transport",
+ "output_unit",
+ "flow",
+ "process",
+ "secproc_co2",
+ "secproc_water",
+ "res_gen",
+]
+DimensionValues = [
+ "scenario",
+ "chain",
+ "region",
+ "country",
+ "transport",
+ "output_unit",
+ "flow",
+ "process",
+ "secproc_co2",
+ "secproc_water",
+ "res_gen",
+]
+
+
+ProcessStepType = Literal[
+ "EL_STR",
+ "ELY",
+ "H2_STR",
+ "DERIV",
+ "PRE_SHP",
+ "PRE_PPL",
+ "POST_SHP",
+ "POST_PPL",
+ "SHP",
+ "SHP-OWN",
+ "PPLS",
+ "PPL",
+ "PPLX",
+ "PPLR",
+]
+ProcessStepValues = [
+ "EL_STR",
+ "ELY",
+ "H2_STR",
+ "DERIV",
+ "PRE_SHP",
+ "PRE_PPL",
+ "POST_SHP",
+ "POST_PPL",
+ "SHP",
+ "SHP-OWN",
+ "PPLS",
+ "PPL",
+ "PPLX",
+ "PPLR",
+]
+
+
+ResultCostType = Literal["CAPEX", "OPEX", "FLOW", "LC"]
+ResultCostValues = ["CAPEX", "OPEX", "FLOW", "LC"]
+
+
+TransportType = Literal["Ship", "Pipeline"]
+TransportValues = ["Ship", "Pipeline"]
+
+
+OutputUnitType = Literal["USD/MWh", "USD/t"]
+OutputUnitValues = ["USD/MWh", "USD/t"]
diff --git a/ptxboa/static/chains.csv b/ptxboa/static/chains.csv
index 3568a97a..c07c557e 100644
--- a/ptxboa/static/chains.csv
+++ b/ptxboa/static/chains.csv
@@ -3,26 +3,26 @@ Ammonia (AEL),EL-STR,AEL-EL,H2-STR,NH3SYN,,,,,NH3-SB,NH3-S,,,,,NH3-L,False
Ammonia (AEL) + reconv. to H2,EL-STR,AEL-EL,H2-STR,NH3SYN,,,NH3-REC,NH3-REC,NH3-SB,NH3-S,,,,,H2-G,False
Ammonia (PEM),EL-STR,PEM-EL,H2-STR,NH3SYN,,,,,NH3-SB,NH3-S,,,,,NH3-L,False
Ammonia (PEM) + reconv. to H2,EL-STR,PEM-EL,H2-STR,NH3SYN,,,NH3-REC,NH3-REC,NH3-SB,NH3-S,,,,,H2-G,False
-Ammonia (SEOC),EL-STR,SOEC-EL,H2-STR,NH3SYN,,,,,NH3-SB,NH3-S,,,,,NH3-L,False
-Ammonia (SEOC) + reconv. to H2,EL-STR,SOEC-EL,H2-STR,NH3SYN,,,NH3-REC,NH3-REC,NH3-SB,NH3-S,,,,,H2-G,False
+Ammonia (SOEC),EL-STR,SOEC-EL,H2-STR,NH3SYN,,,,,NH3-SB,NH3-S,,,,,NH3-L,False
+Ammonia (SOEC) + reconv. to H2,EL-STR,SOEC-EL,H2-STR,NH3SYN,,,NH3-REC,NH3-REC,NH3-SB,NH3-S,,,,,H2-G,False
FT e-fuels (AEL),EL-STR,AEL-EL,H2-STR,EFUELSYN,,,,,SYN-SB,SYN-S,,,,,CHX-L,False
FT e-fuels (PEM),EL-STR,PEM-EL,H2-STR,EFUELSYN,,,,,SYN-SB,SYN-S,,,,,CHX-L,False
-FT e-fuels (SEOC),EL-STR,SOEC-EL,H2-STR,EFUELSYN,,,,,SYN-SB,SYN-S,,,,,CHX-L,False
+FT e-fuels (SOEC),EL-STR,SOEC-EL,H2-STR,EFUELSYN,,,,,SYN-SB,SYN-S,,,,,CHX-L,False
Green Iron (AEL),EL-STR,AEL-EL,H2-STR,DRI,,,,,DRI-SB,,,,,,DRI-S,False
Green Iron (PEM),EL-STR,PEM-EL,H2-STR,DRI,,,,,DRI-SB,,,,,,DRI-S,False
-Green Iron (SEOC),EL-STR,SOEC-EL,H2-STR,DRI,,,,,DRI-SB,,,,,,DRI-S,False
+Green Iron (SOEC),EL-STR,SOEC-EL,H2-STR,DRI,,,,,DRI-SB,,,,,,DRI-S,False
Hydrogen (AEL),EL-STR,AEL-EL,,,H2-LIQ,H2-COMP,H2-RGAS,,H2-SB,H2-S,H2-P-S,H2-P-L,H2-P-SR,H2-P-LR,H2-G,True
Hydrogen (PEM),EL-STR,PEM-EL,,,H2-LIQ,H2-COMP,H2-RGAS,,H2-SB,H2-S,H2-P-S,H2-P-L,H2-P-SR,H2-P-LR,H2-G,True
-Hydrogen (SEOC),EL-STR,SOEC-EL,,,H2-LIQ,H2-COMP,H2-RGAS,,H2-SB,H2-S,H2-P-S,H2-P-L,H2-P-SR,H2-P-LR,H2-G,True
+Hydrogen (SOEC),EL-STR,SOEC-EL,,,H2-LIQ,H2-COMP,H2-RGAS,,H2-SB,H2-S,H2-P-S,H2-P-L,H2-P-SR,H2-P-LR,H2-G,True
LOHC (AEL),EL-STR,AEL-EL,,,LOHC-CON,,LOHC-REC,,LOHC-SB,LOHC-S,,,,,H2-G,False
LOHC (PEM),EL-STR,PEM-EL,,,LOHC-CON,,LOHC-REC,,LOHC-SB,LOHC-S,,,,,H2-G,False
-LOHC (SEOC),EL-STR,SOEC-EL,,,LOHC-CON,,LOHC-REC,,LOHC-SB,LOHC-S,,,,,H2-G,False
+LOHC (SOEC),EL-STR,SOEC-EL,,,LOHC-CON,,LOHC-REC,,LOHC-SB,LOHC-S,,,,,H2-G,False
Methane (AEL),EL-STR,AEL-EL,H2-STR,CH4SYN,CH4-LIQ,CH4-COMP,CH4-RGAS,,CH4-SB,CH4-S,CH4-P-S,CH4-P-L,CH4-P-SR,CH4-P-LR,CH4-G,True
Methane (AEL) + reconv. to H2,EL-STR,AEL-EL,H2-STR,CH4SYN,CH4-LIQ,CH4-COMP,REGASATR,ATR,CH4-SB,CH4-S,CH4-P-S,CH4-P-L,CH4-P-SR,CH4-P-LR,H2-G,True
Methane (PEM),EL-STR,PEM-EL,H2-STR,CH4SYN,CH4-LIQ,CH4-COMP,CH4-RGAS,,CH4-SB,CH4-S,CH4-P-S,CH4-P-L,CH4-P-SR,CH4-P-LR,CH4-G,True
Methane (PEM) + reconv. to H2,EL-STR,PEM-EL,H2-STR,CH4SYN,CH4-LIQ,CH4-COMP,REGASATR,ATR,CH4-SB,CH4-S,CH4-P-S,CH4-P-L,CH4-P-SR,CH4-P-LR,H2-G,True
-Methane (SEOC),EL-STR,SOEC-EL,H2-STR,CH4SYN,CH4-LIQ,CH4-COMP,CH4-RGAS,,CH4-SB,CH4-S,CH4-P-S,CH4-P-L,CH4-P-SR,CH4-P-LR,CH4-G,True
-Methane (SEOC) + reconv. to H2,EL-STR,SOEC-EL,H2-STR,CH4SYN,CH4-LIQ,CH4-COMP,REGASATR,ATR,CH4-SB,CH4-S,CH4-P-S,CH4-P-L,CH4-P-SR,CH4-P-LR,H2-G,True
+Methane (SOEC),EL-STR,SOEC-EL,H2-STR,CH4SYN,CH4-LIQ,CH4-COMP,CH4-RGAS,,CH4-SB,CH4-S,CH4-P-S,CH4-P-L,CH4-P-SR,CH4-P-LR,CH4-G,True
+Methane (SOEC) + reconv. to H2,EL-STR,SOEC-EL,H2-STR,CH4SYN,CH4-LIQ,CH4-COMP,REGASATR,ATR,CH4-SB,CH4-S,CH4-P-S,CH4-P-L,CH4-P-SR,CH4-P-LR,H2-G,True
Methanol (AEL),EL-STR,AEL-EL,H2-STR,CH3OHSYN,,,,,CH3OH-SB,CH3OH-S,,,,,CH3OH-L,False
Methanol (PEM),EL-STR,PEM-EL,H2-STR,CH3OHSYN,,,,,CH3OH-SB,CH3OH-S,,,,,CH3OH-L,False
-Methanol (SEOC),EL-STR,SOEC-EL,H2-STR,CH3OHSYN,,,,,CH3OH-SB,CH3OH-S,,,,,CH3OH-L,False
+Methanol (SOEC),EL-STR,SOEC-EL,H2-STR,CH3OHSYN,,,,,CH3OH-SB,CH3OH-S,,,,,CH3OH-L,False
diff --git a/ptxboa/static/dim_parameter.csv b/ptxboa/static/dim_parameter.csv
index 435d45aa..ae170316 100644
--- a/ptxboa/static/dim_parameter.csv
+++ b/ptxboa/static/dim_parameter.csv
@@ -15,4 +15,4 @@ OPEX-T,levelized costs,USD2021/(kWh*km),False,False,True,False,True,False,False,
RE-POT,RE potential,MWel,False,False,False,True,True,True,False,False,no,no,,process_code/source_region_code
SEASHARE,sea share of pipeline distance,fraction,False,False,False,False,False,True,True,False,no,no,,source_region_code/target_country_code
SPECCOST,specific costs,various (USD2021 per flow),True,False,False,False,False,True,False,True,basic,extended,"Costs are associated with every *secondary* input. It could also be associated with secondary output (<0 for gains, >0 for costs)",flow_code/source_region_code
-WACC,interest rate,fraction,False,True,False,True,False,True,False,True,,,,source_region_code
+WACC,WACC,fraction,False,True,False,True,False,True,False,True,,,,source_region_code
diff --git a/ptxboa_streamlit.py b/ptxboa_streamlit.py
index 252c9877..144fde43 100644
--- a/ptxboa_streamlit.py
+++ b/ptxboa_streamlit.py
@@ -6,14 +6,13 @@
>>> streamlit run ptxboa_streamlit.py
"""
-__version__ = "0.6.1"
+__version__ = "0.7.0"
import logging
import pandas as pd
import streamlit as st
import streamlit_antd_components as sac
-from pypsa import Network
from app.context_data import load_context_data
from app.layout_elements import display_footer
@@ -59,9 +58,6 @@
# Set the pandas display option to format floats with 2 decimal places
pd.set_option("display.float_format", "{:.2f}".format)
-if "network" not in st.session_state:
- st.session_state["network"] = Network()
-
if "model_status" not in st.session_state:
st.session_state["model_status"] = "not yet solved"
@@ -159,49 +155,18 @@
"Market scanning",
"Input data",
"Deep-dive countries",
- "Optimization",
]:
- # calculate results over different data dimensions:
- costs_per_region = calculate_results_list(
- api, parameter_to_change="region", parameter_list=None
- )
- costs_per_scenario = calculate_results_list(
- api,
- parameter_to_change="scenario",
- parameter_list=None,
- )
- costs_per_res_gen = calculate_results_list(
- api,
- parameter_to_change="res_gen",
- # TODO: here we remove PV tracking manually, this needs to be fixed in data
- parameter_list=[
- x
- for x in api.get_dimension("res_gen").index.to_list()
- if x != "PV tracking"
- ],
- )
- costs_per_chain = calculate_results_list(
- api,
- parameter_to_change="chain",
- parameter_list=None,
- override_session_state={"output_unit": "USD/MWh"},
- )
-
- if st.session_state["user_changes_df"] is not None:
- # calculate results over different data dimensions (without user changes):
- costs_per_region_without_user_changes = calculate_results_list(
- api,
- parameter_to_change="region",
- parameter_list=None,
- apply_user_data=False,
+ with st.spinner("Please wait. Running optimization model..."):
+ # calculate results over different data dimensions:
+ costs_per_region = calculate_results_list(
+ api, parameter_to_change="region", parameter_list=None
)
- costs_per_scenario_without_user_changes = calculate_results_list(
+ costs_per_scenario = calculate_results_list(
api,
parameter_to_change="scenario",
parameter_list=None,
- apply_user_data=False,
)
- costs_per_res_gen_without_user_changes = calculate_results_list(
+ costs_per_res_gen = calculate_results_list(
api,
parameter_to_change="res_gen",
# TODO: here we remove PV tracking manually, this needs to be fixed in data
@@ -210,20 +175,51 @@
for x in api.get_dimension("res_gen").index.to_list()
if x != "PV tracking"
],
- apply_user_data=False,
)
- costs_per_chain_without_user_changes = calculate_results_list(
+ costs_per_chain = calculate_results_list(
api,
parameter_to_change="chain",
parameter_list=None,
override_session_state={"output_unit": "USD/MWh"},
- apply_user_data=False,
)
- else:
- costs_per_region_without_user_changes = None
- costs_per_scenario_without_user_changes = None
- costs_per_res_gen_without_user_changes = None
- costs_per_chain_without_user_changes = None
+
+ if st.session_state["user_changes_df"] is not None:
+ # calculate results over different data dimensions (without user changes):
+ costs_per_region_without_user_changes = calculate_results_list(
+ api,
+ parameter_to_change="region",
+ parameter_list=None,
+ apply_user_data=False,
+ )
+ costs_per_scenario_without_user_changes = calculate_results_list(
+ api,
+ parameter_to_change="scenario",
+ parameter_list=None,
+ apply_user_data=False,
+ )
+ costs_per_res_gen_without_user_changes = calculate_results_list(
+ api,
+ parameter_to_change="res_gen",
+ # TODO: here we remove PV tracking manually, needs to be fixed in data
+ parameter_list=[
+ x
+ for x in api.get_dimension("res_gen").index.to_list()
+ if x != "PV tracking"
+ ],
+ apply_user_data=False,
+ )
+ costs_per_chain_without_user_changes = calculate_results_list(
+ api,
+ parameter_to_change="chain",
+ parameter_list=None,
+ override_session_state={"output_unit": "USD/MWh"},
+ apply_user_data=False,
+ )
+ else:
+ costs_per_region_without_user_changes = None
+ costs_per_scenario_without_user_changes = None
+ costs_per_res_gen_without_user_changes = None
+ costs_per_chain_without_user_changes = None
if st.session_state[st.session_state["tab_key"]] in [
"Market scanning",
diff --git a/requirements.txt b/requirements.txt
index 8ca319e4..ed9d4df0 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,9 +1,9 @@
pandas==2.2.1
numpy==1.26.4
-streamlit
+streamlit==1.35.0
openpyxl==3.1.2
-plotly==5.19.0
+plotly==5.22.0
streamlit-antd-components
XlsxWriter==3.2.0
pypsa==0.27
-highspy==1.5.3
+highspy==1.7.1
diff --git a/tests/test_api.py b/tests/test_api.py
index d469af8a..172dc44d 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -121,7 +121,7 @@ def test_example_api_call_2_ship_own_fuel(self):
settings = {
"region": "Argentina (Chaco)",
"country": "Japan",
- "chain": "Methanol (SEOC)",
+ "chain": "Methanol (SOEC)",
"res_gen": "Wind Onshore",
"scenario": "2040 (high)",
"secproc_co2": "Specific costs",
diff --git a/tests/test_api_data.py b/tests/test_api_data.py
index 1214077a..d6b6ca4d 100644
--- a/tests/test_api_data.py
+++ b/tests/test_api_data.py
@@ -21,7 +21,7 @@ def user_data_01():
("Argentina", "PV tilted", 2000, "full load hours", None),
("Costa Rica", "Wind-PV-Hybrid", 2000, "full load hours", None),
("Australia", "Wind Onshore", 4000, "full load hours", None),
- ("Costa Rica", None, 0.12, "interest rate", None),
+ ("Costa Rica", None, 0.12, "WACC", None),
],
columns=[
"source_region_code",
diff --git a/tests/test_opt.py b/tests/test_opt.py
index 98e64f74..4d75726d 100644
--- a/tests/test_opt.py
+++ b/tests/test_opt.py
@@ -13,7 +13,7 @@
from app.tab_optimization import calc_aggregate_statistics
from flh_opt.api_opt import get_profiles_and_weights, optimize
from ptxboa import DEFAULT_CACHE_DIR
-from ptxboa.api import PtxboaAPI
+from ptxboa.api import DataHandler, PtxboaAPI
logging.basicConfig(level=logging.INFO)
@@ -64,7 +64,6 @@ def test_optimize_export_to_netcdf(call_optimize):
n.export_to_netcdf(f"{export_dir}/{input_data['id']}.nc")
-@pytest.mark.xfail()
def test_optimize_expected_objective_value(call_optimize):
"""Test for expected objective value."""
[res, n, input_data] = call_optimize
@@ -136,6 +135,32 @@ def test_issue_312_fix_fhl_optimization_errors(api, chain):
assert len(res) > 0
+@pytest.mark.parametrize("chain", ["Methane (AEL)", "Hydrogen (AEL)", "LOHC (AEL)"])
+def test_issue_403_fix_no_heat_demand_for_methane_production(api, chain):
+ """See https://github.com/agoenergy/ptx-boa/issues/403.
+
+ Heat costs should be zero for Methane and Hydrogen, and >0 for LOHC.
+ """
+ settings = {
+ "region": "Morocco",
+ "country": "Germany",
+ "chain": chain,
+ "res_gen": "PV tilted",
+ "scenario": "2040 (medium)",
+ "secproc_co2": "Specific costs",
+ "secproc_water": "Specific costs",
+ "transport": "Pipeline",
+ "ship_own_fuel": False,
+ "output_unit": "USD/t",
+ }
+ res = api.calculate(**settings, optimize_flh=True)
+ df = res[0]
+ if chain != "LOHC (AEL)":
+ assert sum(df["process_type"] == "Heat") == 0
+ else:
+ assert df.loc[df["process_type"] == "Heat", "values"].values[0] > 0
+
+
# expected to fail because of pypsa bug https://github.com/PyPSA/PyPSA/issues/866
@pytest.mark.xfail()
@pytest.mark.filterwarnings("always")
@@ -193,3 +218,99 @@ def network(api) -> pypsa.Network:
def test_calc_aggregate_statistics(network):
res = calc_aggregate_statistics(network)
assert isinstance(res, pd.DataFrame)
+
+
+def test_prepare_data_for_optimize_incl_sec_proc():
+ """Data for optimization should include data for secondary processes."""
+ settings = {
+ "region": "Morocco",
+ "country": "Germany",
+ "chain": "Methane (AEL)",
+ "res_gen": "PV tilted",
+ "scenario": "2040 (medium)",
+ "secproc_co2": "Direct Air Capture",
+ "secproc_water": "Sea Water desalination",
+ "transport": "Pipeline",
+ "ship_own_fuel": False,
+ "user_data": None,
+ }
+ secondary_processes = {
+ "H2O-L": (
+ DataHandler.get_dimensions_parameter_code(
+ "secproc_water", settings["secproc_water"]
+ )
+ if settings["secproc_water"]
+ else None
+ ),
+ "CO2-G": (
+ DataHandler.get_dimensions_parameter_code(
+ "secproc_co2", settings["secproc_co2"]
+ )
+ if settings["secproc_co2"]
+ else None
+ ),
+ }
+ chain_name = settings["chain"]
+ process_code_res = DataHandler.get_dimensions_parameter_code(
+ "res_gen", settings["res_gen"]
+ )
+ source_region_code = DataHandler.get_dimensions_parameter_code(
+ "region", settings["region"]
+ )
+ target_country_code = DataHandler.get_dimensions_parameter_code(
+ "country", settings["country"]
+ )
+ use_ship = settings["transport"] == "Ship"
+ ship_own_fuel = settings["ship_own_fuel"]
+
+ with TemporaryDirectory() as cache_dir:
+ data_handler = DataHandler(
+ scenario=settings["scenario"],
+ cache_dir=cache_dir,
+ data_dir=ptxdata_dir_static,
+ )
+
+ # prepare data in the same way as in PtxboaAPI.calculate():
+ data = data_handler._get_calculation_data(
+ secondary_processes=secondary_processes,
+ chain_name=chain_name,
+ process_code_res=process_code_res,
+ source_region_code=source_region_code,
+ target_country_code=target_country_code,
+ use_ship=use_ship,
+ ship_own_fuel=ship_own_fuel,
+ use_user_data=False,
+ )
+
+ # prepare data same way as in PtxOpt.get_data()
+ opt_input_data = data_handler.optimizer._prepare_data(data)
+
+ # check that some values exist
+ assert opt_input_data["H2O"]["CAPEX_A"]
+ assert opt_input_data["H2O"]["CONV"]
+ assert opt_input_data["CO2"]["CAPEX_A"]
+ assert opt_input_data["CO2"]["CONV"]
+
+ # actually call optimizer as in PtxOpt.get_data()
+ opt_output_data, _network = optimize(
+ opt_input_data,
+ profiles_path=data_handler.optimizer.profiles_hashes.profiles_path,
+ )
+
+ # check that some values exist
+ assert opt_output_data["H2O"]["FLH"]
+ assert opt_output_data["CO2"]["FLH"]
+
+ # do the same using the proper api call
+
+ data = data_handler.get_calculation_data(
+ secondary_processes=secondary_processes,
+ chain_name=chain_name,
+ process_code_res=process_code_res,
+ source_region_code=source_region_code,
+ target_country_code=target_country_code,
+ use_ship=use_ship,
+ ship_own_fuel=ship_own_fuel,
+ optimize_flh=True,
+ use_user_data_for_optimize_flh=False,
+ )
diff --git a/tests/test_optimize_settings.json b/tests/test_optimize_settings.json
index 8748f49c..84d3f0b3 100644
--- a/tests/test_optimize_settings.json
+++ b/tests/test_optimize_settings.json
@@ -1,215 +1,315 @@
[
- {
- "id": "H2, PV",
- "input_data": {
- "SOURCE_REGION_CODE": "ARG",
- "RES": [
- {
- "CAPEX_A": 30,
- "OPEX_F": 1,
- "OPEX_O": 0.001,
- "PROCESS_CODE": "PV-FIX"
- }
- ],
- "ELY": {
- "EFF": 0.75,
- "CAPEX_A": 25,
- "OPEX_F": 10,
- "OPEX_O": 0,
- "CONV": {
- "H2O-L": 0.3
- }
- },
- "DERIV": null,
- "EL_STR": {
- "EFF": 0.9,
- "CAPEX_A": 50,
- "OPEX_F": 0,
- "OPEX_O": 0
- },
- "H2_STR": {
- "EFF": 0.9,
- "CAPEX_A": 5,
- "OPEX_F": 0,
- "OPEX_O": 0
- },
- "SPECCOST": {
- "H2O-L": 0.001,
- "CO2-G": 0.04,
- "HEAT": 0.05
- }
+ {
+ "id": "H2, PV",
+ "input_data": {
+ "SOURCE_REGION_CODE": "ARG",
+ "RES": [
+ {
+ "CAPEX_A": 30,
+ "OPEX_F": 1,
+ "OPEX_O": 0.001,
+ "PROCESS_CODE": "PV-FIX"
+ }
+ ],
+ "ELY": {
+ "EFF": 0.75,
+ "CAPEX_A": 25,
+ "OPEX_F": 10,
+ "OPEX_O": 0,
+ "CONV": {
+ "H2O-L": 0.3
+ }
+ },
+ "DERIV": null,
+ "EL_STR": {
+ "EFF": 0.9,
+ "CAPEX_A": 50,
+ "OPEX_F": 0,
+ "OPEX_O": 0
+ },
+ "H2_STR": {
+ "EFF": 0.9,
+ "CAPEX_A": 5,
+ "OPEX_F": 0,
+ "OPEX_O": 0
+ },
+ "SPECCOST": {
+ "H2O-L": 0.001,
+ "CO2-G": 0.04,
+ "HEAT": 0.05
+ }
+ },
+ "expected_output": {
+ "RES": [
+ {
+ "PROCESS_CODE": "PV-FIX",
+ "FLH": 0.10209904130397318,
+ "SHARE_FACTOR": 1.0
+ }
+ ],
+ "ELY": {
+ "FLH": 0.36068215977942414
+ },
+ "EL_STR": {
+ "CAP_F": 121.50878141391004
+ },
+ "H2_STR": {
+ "CAP_F": 348.33524817139295
+ }
+ },
+ "expected_ojective_value": 424.8982813167353
+ },
+ {
+ "id": "CH4, hybrid, with DAC and DESAL",
+ "input_data": {
+ "SOURCE_REGION_CODE": "ARG",
+ "RES": [
+ {
+ "CAPEX_A": 30,
+ "OPEX_F": 1,
+ "OPEX_O": 0.001,
+ "PROCESS_CODE": "PV-FIX"
},
- "expected_output": {
- "RES": [
- {
- "PROCESS_CODE": "PV-FIX",
- "FLH": 0.10209904130397318,
- "SHARE_FACTOR": 1.0
- }
- ],
- "ELY": {
- "FLH": 0.36068215977942414
- },
- "EL_STR": {
- "CAP_F": 121.50878141391004
- },
- "H2_STR": {
- "CAP_F": 348.33524817139295
- }
+ {
+ "CAPEX_A": 80,
+ "OPEX_F": 1,
+ "OPEX_O": 0.002,
+ "PROCESS_CODE": "WIND-ON"
+ }
+ ],
+ "ELY": {
+ "EFF": 0.75,
+ "CAPEX_A": 25,
+ "OPEX_F": 10,
+ "OPEX_O": 0,
+ "CONV": {
+ "H2O-L": 0.3
+ }
+ },
+ "DERIV": {
+ "EFF": 0.8,
+ "CAPEX_A": 30,
+ "OPEX_F": 20,
+ "OPEX_O": 0,
+ "PROCESS_CODE": "CH4SYN",
+ "CONV": {
+ "CO2-G": 0.2,
+ "HEAT": -0.2,
+ "H2O-L": -0.15
+ }
+ },
+ "H2O": {
+ "CAPEX_A": 0.07726085034488815,
+ "OPEX_F": 0.0356900588308774,
+ "OPEX_O": 0,
+ "CONV": {
+ "EL": 0.003
+ }
+ },
+ "CO2": {
+ "CAPEX_A": 0.07726085034488815,
+ "OPEX_F": 0.0356900588308774,
+ "OPEX_O": 0,
+ "CONV": {
+ "EL": 0.4515,
+ "HEAT": 1.743,
+ "H2O-L": -1.4
+ }
+ },
+ "EL_STR": {
+ "EFF": 0.9,
+ "CAPEX_A": 50,
+ "OPEX_F": 0,
+ "OPEX_O": 0
+ },
+ "H2_STR": {
+ "EFF": 0.9,
+ "CAPEX_A": 5,
+ "OPEX_F": 0,
+ "OPEX_O": 0
+ },
+ "SPECCOST": {
+ "H2O-L": 0.001,
+ "CO2-G": 0.04,
+ "HEAT": 0.05
+ }
+ },
+ "expected_output": {
+ "RES": [
+ {
+ "PROCESS_CODE": "PV-FIX",
+ "FLH": 0,
+ "SHARE_FACTOR": -0.0
},
- "expected_ojective_value": 2480.8292413355575
+ {
+ "PROCESS_CODE": "WIND-ON",
+ "FLH": 0.345701024478453,
+ "SHARE_FACTOR": 1.0
+ }
+ ],
+ "ELY": {
+ "FLH": 0.5124598171364299
+ },
+ "EL_STR": {
+ "CAP_F": -0.0
+ },
+ "H2_STR": {
+ "CAP_F": 122.44991931269928
+ }
},
- {
- "id": "CH4, hybrid",
- "input_data": {
- "SOURCE_REGION_CODE": "ARG",
- "RES": [
- {
- "CAPEX_A": 30,
- "OPEX_F": 1,
- "OPEX_O": 0.001,
- "PROCESS_CODE": "PV-FIX"
- },
- {
- "CAPEX_A": 80,
- "OPEX_F": 1,
- "OPEX_O": 0.002,
- "PROCESS_CODE": "WIND-ON"
- }
- ],
- "ELY": {
- "EFF": 0.75,
- "CAPEX_A": 25,
- "OPEX_F": 10,
- "OPEX_O": 0,
- "CONV": {
- "H2O-L": 0.3
- }
- },
- "DERIV": {
- "EFF": 0.8,
- "CAPEX_A": 30,
- "OPEX_F": 20,
- "OPEX_O": 0,
- "PROCESS_CODE": "CH4SYN",
- "CONV": {
- "CO2-G": 0.2,
- "HEAT": -0.2,
- "H2O-L": -0.15
- }
- },
- "EL_STR": {
- "EFF": 0.9,
- "CAPEX_A": 50,
- "OPEX_F": 0,
- "OPEX_O": 0
- },
- "H2_STR": {
- "EFF": 0.9,
- "CAPEX_A": 5,
- "OPEX_F": 0,
- "OPEX_O": 0
- },
- "SPECCOST": {
- "H2O-L": 0.001,
- "CO2-G": 0.04,
- "HEAT": 0.05
- }
+ "expected_ojective_value": 723.6133892869304
+ },
+ {
+ "id": "CH4, hybrid",
+ "input_data": {
+ "SOURCE_REGION_CODE": "ARG",
+ "RES": [
+ {
+ "CAPEX_A": 30,
+ "OPEX_F": 1,
+ "OPEX_O": 0.001,
+ "PROCESS_CODE": "PV-FIX"
},
- "expected_output": {
- "RES": [
- {
- "PROCESS_CODE": "PV-FIX",
- "FLH": 0,
- "SHARE_FACTOR": -0.0
- },
- {
- "PROCESS_CODE": "WIND-ON",
- "FLH": 0.345701024478453,
- "SHARE_FACTOR": 1.0
- }
- ],
- "ELY": {
- "FLH": 0.5124598171364299
- },
- "EL_STR": {
- "CAP_F": -0.0
- },
- "H2_STR": {
- "CAP_F": 122.44991931269928
- }
+ {
+ "CAPEX_A": 80,
+ "OPEX_F": 1,
+ "OPEX_O": 0.002,
+ "PROCESS_CODE": "WIND-ON"
+ }
+ ],
+ "ELY": {
+ "EFF": 0.75,
+ "CAPEX_A": 25,
+ "OPEX_F": 10,
+ "OPEX_O": 0,
+ "CONV": {
+ "H2O-L": 0.3
+ }
+ },
+ "DERIV": {
+ "EFF": 0.8,
+ "CAPEX_A": 30,
+ "OPEX_F": 20,
+ "OPEX_O": 0,
+ "PROCESS_CODE": "CH4SYN",
+ "CONV": {
+ "CO2-G": 0.2,
+ "HEAT": -0.2,
+ "H2O-L": -0.15
+ }
+ },
+ "EL_STR": {
+ "EFF": 0.9,
+ "CAPEX_A": 50,
+ "OPEX_F": 0,
+ "OPEX_O": 0
+ },
+ "H2_STR": {
+ "EFF": 0.9,
+ "CAPEX_A": 5,
+ "OPEX_F": 0,
+ "OPEX_O": 0
+ },
+ "SPECCOST": {
+ "H2O-L": 0.001,
+ "CO2-G": 0.04,
+ "HEAT": 0.05
+ }
+ },
+ "expected_output": {
+ "RES": [
+ {
+ "PROCESS_CODE": "PV-FIX",
+ "FLH": 0,
+ "SHARE_FACTOR": -0.0
},
- "expected_ojective_value": 1748.871332914744
+ {
+ "PROCESS_CODE": "WIND-ON",
+ "FLH": 0.345701024478453,
+ "SHARE_FACTOR": 1.0
+ }
+ ],
+ "ELY": {
+ "FLH": 0.5124598171364299
+ },
+ "EL_STR": {
+ "CAP_F": -0.0
+ },
+ "H2_STR": {
+ "CAP_F": 122.44991931269928
+ }
},
- {
- "id": "H2, hybrid",
- "input_data": {
- "SOURCE_REGION_CODE": "ARG",
- "RES": [
- {
- "CAPEX_A": 30,
- "OPEX_F": 1,
- "OPEX_O": 0.001,
- "PROCESS_CODE": "PV-FIX"
- },
- {
- "CAPEX_A": 80,
- "OPEX_F": 1,
- "OPEX_O": 0.002,
- "PROCESS_CODE": "WIND-ON"
- }
- ],
- "ELY": {
- "EFF": 0.75,
- "CAPEX_A": 25,
- "OPEX_F": 10,
- "OPEX_O": 0,
- "CONV": {
- "H2O-L": 0.3
- }
- },
- "DERIV": null,
- "EL_STR": {
- "EFF": 0.9,
- "CAPEX_A": 50,
- "OPEX_F": 0,
- "OPEX_O": 0
- },
- "H2_STR": {
- "EFF": 0.9,
- "CAPEX_A": 5,
- "OPEX_F": 0,
- "OPEX_O": 0
- },
- "SPECCOST": {
- "H2O-L": 0.001,
- "CO2-G": 0.04,
- "HEAT": 0.05
- }
+ "expected_ojective_value": 706.2792852401756
+ },
+ {
+ "id": "H2, hybrid",
+ "input_data": {
+ "SOURCE_REGION_CODE": "ARG",
+ "RES": [
+ {
+ "CAPEX_A": 30,
+ "OPEX_F": 1,
+ "OPEX_O": 0.001,
+ "PROCESS_CODE": "PV-FIX"
},
- "expected_output": {
- "RES": [
- {
- "PROCESS_CODE": "PV-FIX",
- "FLH": 0,
- "SHARE_FACTOR": -0.0
- },
- {
- "PROCESS_CODE": "WIND-ON",
- "FLH": 0.345701024478453,
- "SHARE_FACTOR": 1.0
- }
- ],
- "ELY": {
- "FLH": 0.5124598171364299
- },
- "EL_STR": {
- "CAP_F": -0.0
- },
- "H2_STR": {
- "CAP_F": 122.44991931269928
- }
+ {
+ "CAPEX_A": 80,
+ "OPEX_F": 1,
+ "OPEX_O": 0.002,
+ "PROCESS_CODE": "WIND-ON"
+ }
+ ],
+ "ELY": {
+ "EFF": 0.75,
+ "CAPEX_A": 25,
+ "OPEX_F": 10,
+ "OPEX_O": 0,
+ "CONV": {
+ "H2O-L": 0.3
+ }
+ },
+ "DERIV": null,
+ "EL_STR": {
+ "EFF": 0.9,
+ "CAPEX_A": 50,
+ "OPEX_F": 0,
+ "OPEX_O": 0
+ },
+ "H2_STR": {
+ "EFF": 0.9,
+ "CAPEX_A": 5,
+ "OPEX_F": 0,
+ "OPEX_O": 0
+ },
+ "SPECCOST": {
+ "H2O-L": 0.001,
+ "CO2-G": 0.04,
+ "HEAT": 0.05
+ }
+ },
+ "expected_output": {
+ "RES": [
+ {
+ "PROCESS_CODE": "PV-FIX",
+ "FLH": 0,
+ "SHARE_FACTOR": -0.0
},
- "expected_ojective_value": 1748.871332914744
- }
+ {
+ "PROCESS_CODE": "WIND-ON",
+ "FLH": 0.345701024478453,
+ "SHARE_FACTOR": 1.0
+ }
+ ],
+ "ELY": {
+ "FLH": 0.5124598171364299
+ },
+ "EL_STR": {
+ "CAP_F": -0.0
+ },
+ "H2_STR": {
+ "CAP_F": 122.44991931269928
+ }
+ },
+ "expected_ojective_value": 375.00268190093993
+ }
]
diff --git a/tests/test_user_data/non_existent_index_user_data.csv b/tests/test_user_data/non_existent_index_user_data.csv
index 6494d70b..2344946b 100644
--- a/tests/test_user_data/non_existent_index_user_data.csv
+++ b/tests/test_user_data/non_existent_index_user_data.csv
@@ -17,7 +17,7 @@ India,Ammonia Synthesis (Haber-Bosch),efficiency,0.4,
,Ammonia ship (own fuel consumption),levelized costs,100.0,
,Ammonia ship (own fuel consumption),"losses (own fuel, transport)",0.5,
,Autothermal-Reactor (Blue Hydrogen),lifetime / amortization period,40.0,
-United Arab Emirates,,interest rate,0.0001,
-Australia,,interest rate,0.9,
-Colombia,,interest rate,1.0,
+United Arab Emirates,,WACC,0.0001,
+Australia,,WACC,0.9,
+Colombia,,WACC,1.0,
,,specific costs,0.3,heat
diff --git a/tests/test_user_data/non_numeric_empty_user_data.csv b/tests/test_user_data/non_numeric_empty_user_data.csv
index 035a8834..407f218d 100644
--- a/tests/test_user_data/non_numeric_empty_user_data.csv
+++ b/tests/test_user_data/non_numeric_empty_user_data.csv
@@ -17,7 +17,7 @@ Kenya,Wind-PV-Hybrid,full load hours,,
,Ammonia ship (own fuel consumption),levelized costs,100.0,
,Ammonia ship (own fuel consumption),"losses (own fuel, transport)",0.5,
,Autothermal-Reactor (Blue Hydrogen),lifetime / amortization period,40.0,
-United Arab Emirates,,interest rate,0.0001,
-Australia,,interest rate,0.9,
-Colombia,,interest rate,1.0,
+United Arab Emirates,,WACC,0.0001,
+Australia,,WACC,0.9,
+Colombia,,WACC,1.0,
,,specific costs,0.3,heat
diff --git a/tests/test_user_data/non_numeric_nan_user_data.csv b/tests/test_user_data/non_numeric_nan_user_data.csv
index 5381877d..a99110f1 100644
--- a/tests/test_user_data/non_numeric_nan_user_data.csv
+++ b/tests/test_user_data/non_numeric_nan_user_data.csv
@@ -17,7 +17,7 @@ Kenya,Wind-PV-Hybrid,full load hours,5000.0,
,Ammonia ship (own fuel consumption),levelized costs,100.0,
,Ammonia ship (own fuel consumption),"losses (own fuel, transport)",0.5,
,Autothermal-Reactor (Blue Hydrogen),lifetime / amortization period,40.0,
-United Arab Emirates,,interest rate,0.0001,
-Australia,,interest rate,0.9,
-Colombia,,interest rate,1.0,
+United Arab Emirates,,WACC,0.0001,
+Australia,,WACC,0.9,
+Colombia,,WACC,1.0,
,,specific costs,0.3,heat
diff --git a/tests/test_user_data/non_numeric_string_user_data.csv b/tests/test_user_data/non_numeric_string_user_data.csv
index 9db72d0d..426afe9c 100644
--- a/tests/test_user_data/non_numeric_string_user_data.csv
+++ b/tests/test_user_data/non_numeric_string_user_data.csv
@@ -17,7 +17,7 @@ Kenya,Wind-PV-Hybrid,full load hours,5000.0,
,Ammonia ship (own fuel consumption),levelized costs,100.0,
,Ammonia ship (own fuel consumption),"losses (own fuel, transport)",string_entry,
,Autothermal-Reactor (Blue Hydrogen),lifetime / amortization period,40.0,
-United Arab Emirates,,interest rate,0.0001,
-Australia,,interest rate,0.9,
-Colombia,,interest rate,1.0,
+United Arab Emirates,,WACC,0.0001,
+Australia,,WACC,0.9,
+Colombia,,WACC,1.0,
,,specific costs,0.3,heat
diff --git a/tests/test_user_data/param_above_range_user_data.csv b/tests/test_user_data/param_above_range_user_data.csv
index 95b0e9fc..de4653d2 100644
--- a/tests/test_user_data/param_above_range_user_data.csv
+++ b/tests/test_user_data/param_above_range_user_data.csv
@@ -17,7 +17,7 @@ Kenya,Wind-PV-Hybrid,full load hours,5000.0,
,Ammonia ship (own fuel consumption),levelized costs,100.0,
,Ammonia ship (own fuel consumption),"losses (own fuel, transport)",0.5,
,Autothermal-Reactor (Blue Hydrogen),lifetime / amortization period,40.0,
-United Arab Emirates,,interest rate,0.0001,
-Australia,,interest rate,0.9,
-Colombia,,interest rate,1.0,
+United Arab Emirates,,WACC,0.0001,
+Australia,,WACC,0.9,
+Colombia,,WACC,1.0,
,,specific costs,0.3,heat
diff --git a/tests/test_user_data/param_below_range_user_data.csv b/tests/test_user_data/param_below_range_user_data.csv
index 081ff9b8..787944e5 100644
--- a/tests/test_user_data/param_below_range_user_data.csv
+++ b/tests/test_user_data/param_below_range_user_data.csv
@@ -17,7 +17,7 @@ Kenya,Wind-PV-Hybrid,full load hours,5000.0,
,Ammonia ship (own fuel consumption),levelized costs,100.0,
,Ammonia ship (own fuel consumption),"losses (own fuel, transport)",0.5,
,Autothermal-Reactor (Blue Hydrogen),lifetime / amortization period,40.0,
-United Arab Emirates,,interest rate,0.0001,
-Australia,,interest rate,0.9,
-Colombia,,interest rate,1.0,
+United Arab Emirates,,WACC,0.0001,
+Australia,,WACC,0.9,
+Colombia,,WACC,1.0,
,,specific costs,0.3,heat
diff --git a/tests/test_user_data/too_many_columns_user_data.csv b/tests/test_user_data/too_many_columns_user_data.csv
index fecc7e1e..1b7627c9 100644
--- a/tests/test_user_data/too_many_columns_user_data.csv
+++ b/tests/test_user_data/too_many_columns_user_data.csv
@@ -17,7 +17,7 @@ Kenya,Wind-PV-Hybrid,full load hours,5000.0,,None
,Ammonia ship (own fuel consumption),levelized costs,100.0,,None
,Ammonia ship (own fuel consumption),"losses (own fuel, transport)",0.5,,None
,Autothermal-Reactor (Blue Hydrogen),lifetime / amortization period,40.0,,None
-United Arab Emirates,,interest rate,0.0001,,None
-Australia,,interest rate,0.9,,None
-Colombia,,interest rate,1.0,,None
+United Arab Emirates,,WACC,0.0001,,None
+Australia,,WACC,0.9,,None
+Colombia,,WACC,1.0,,None
,,specific costs,0.3,heat
diff --git a/tests/test_user_data/valid_user_data.csv b/tests/test_user_data/valid_user_data.csv
index 9b723a35..dc39a98b 100644
--- a/tests/test_user_data/valid_user_data.csv
+++ b/tests/test_user_data/valid_user_data.csv
@@ -17,7 +17,7 @@ Kenya,Wind-PV-Hybrid,full load hours,5000.0,
,Ammonia ship (own fuel consumption),levelized costs,100.0,
,Ammonia ship (own fuel consumption),"losses (own fuel, transport)",0.5,
,Autothermal-Reactor (Blue Hydrogen),lifetime / amortization period,40.0,
-United Arab Emirates,,interest rate,0.0001,
-Australia,,interest rate,0.9,
-Colombia,,interest rate,1.0,
+United Arab Emirates,,WACC,0.0001,
+Australia,,WACC,0.9,
+Colombia,,WACC,1.0,
,,specific costs,0.3,heat
diff --git a/tests/test_user_data/wrong_column_name_user_data.csv b/tests/test_user_data/wrong_column_name_user_data.csv
index 92b2c253..95ba2b93 100644
--- a/tests/test_user_data/wrong_column_name_user_data.csv
+++ b/tests/test_user_data/wrong_column_name_user_data.csv
@@ -17,7 +17,7 @@ Kenya,Wind-PV-Hybrid,full load hours,5000.0,
,Ammonia ship (own fuel consumption),levelized costs,100.0,
,Ammonia ship (own fuel consumption),"losses (own fuel, transport)",0.5,
,Autothermal-Reactor (Blue Hydrogen),lifetime / amortization period,40.0,
-United Arab Emirates,,interest rate,0.0001,
-Australia,,interest rate,0.9,
-Colombia,,interest rate,1.0,
+United Arab Emirates,,WACC,0.0001,
+Australia,,WACC,0.9,
+Colombia,,WACC,1.0,
,,specific costs,0.3,heat