From d1427175638cd926dfbc6bbb6fc9357670b94663 Mon Sep 17 00:00:00 2001
From: Philipp Glaum
Date: Mon, 29 Jul 2024 14:49:57 +0200
Subject: [PATCH 01/14] add methanol techs for master to branch
---
config/config.default.yaml | 31 +-
rules/build_sector.smk | 3 +
scripts/prepare_sector_network.py | 459 ++++++++++++++++++++++++++++--
3 files changed, 461 insertions(+), 32 deletions(-)
diff --git a/config/config.default.yaml b/config/config.default.yaml
index 0af347341..a31abd3d8 100644
--- a/config/config.default.yaml
+++ b/config/config.default.yaml
@@ -541,7 +541,6 @@ sector:
hydrogen_turbine: false
SMR: true
SMR_cc: true
- regional_methanol_demand: false
regional_oil_demand: false
regional_coal_demand: false
regional_co2_sequestration_potential:
@@ -567,6 +566,21 @@ sector:
# - onshore # more than 50 km from sea
- nearshore # within 50 km of sea
# - offshore
+ methanol: false # if industry is modelled, methanol is still added even if false
+ methanol_spatial: false # if true demand is also regional even if regional demand is set to false, since methanol is regionally resolved
+ regional_methanol_demand: false
+ methanol_transport: false
+ methanol_reforming: false
+ methanol_reforming_cc: false
+ methanol_to_kerosene: false
+ methanol_to_olefins: false
+ methanol_to_power:
+ ccgt: false
+ ccgt_cc: false
+ ocgt: false
+ allam: false
+ biomass_to_methanol: false
+ biomass_to_methanol_cc: false
ammonia: false
min_part_load_fischer_tropsch: 0.5
min_part_load_methanolisation: 0.3
@@ -1157,8 +1171,19 @@ plotting:
liquid: '#25c49a'
kerosene for aviation: '#a1ffe6'
naphtha for industry: '#57ebc4'
- methanolisation: '#83d6d5'
- methanol: '#468c8b'
+ methanol-to-kerosene: '#C98468'
+ methanol-to-olefins/aromatics: '#FFA07A'
+ Methanol steam reforming: '#FFBF00'
+ Methanol steam reforming CC: '#A2EA8A'
+ methanolisation: '#00FFBF'
+ biomass-to-methanol: #EAD28A
+ biomass-to-methanol CC: #EADBAD
+ allam methanol: '#B98F76'
+ CCGT methanol: '#B98F76'
+ CCGT methanol CC: '#B98F76'
+ OCGT methanol: '#B98F76'
+ methanol: '#FF7B00'
+ methanol transport: '#FF7B00'
shipping methanol: '#468c8b'
industry methanol: '#468c8b'
# co2
diff --git a/rules/build_sector.smk b/rules/build_sector.smk
index 6614b163a..276f61e50 100644
--- a/rules/build_sector.smk
+++ b/rules/build_sector.smk
@@ -1020,6 +1020,9 @@ rule prepare_sector_network:
hourly_heat_demand_total=resources(
"hourly_heat_demand_total_elec_s{simpl}_{clusters}.nc"
),
+ industrial_production=resources(
+ "industrial_production_elec_s{simpl}_{clusters}_{planning_horizons}.csv"
+ ),
district_heat_share=resources(
"district_heat_share_elec_s{simpl}_{clusters}_{planning_horizons}.csv"
),
diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py
index 8cfa62a42..2288354de 100644
--- a/scripts/prepare_sector_network.py
+++ b/scripts/prepare_sector_network.py
@@ -141,17 +141,24 @@ def define_spatial(nodes, options):
spatial.methanol = SimpleNamespace()
- spatial.methanol.nodes = ["EU methanol"]
- spatial.methanol.locations = ["EU"]
-
- if options["regional_methanol_demand"]:
+ if options.get("methanol_spatial", False):
+ spatial.methanol.nodes = nodes + " methanol"
+ spatial.methanol.locations = nodes
spatial.methanol.demand_locations = nodes
spatial.methanol.industry = nodes + " industry methanol"
spatial.methanol.shipping = nodes + " shipping methanol"
else:
- spatial.methanol.demand_locations = ["EU"]
- spatial.methanol.shipping = ["EU shipping methanol"]
- spatial.methanol.industry = ["EU industry methanol"]
+ spatial.methanol.nodes = ["EU methanol"]
+ spatial.methanol.locations = ["EU"]
+
+ if options["regional_methanol_demand"]:
+ spatial.methanol.demand_locations = nodes
+ spatial.methanol.industry = nodes + " industry methanol"
+ spatial.methanol.shipping = nodes + " shipping methanol"
+ else:
+ spatial.methanol.demand_locations = ["EU"]
+ spatial.methanol.shipping = ["EU shipping methanol"]
+ spatial.methanol.industry = ["EU industry methanol"]
# oil
spatial.oil = SimpleNamespace()
@@ -762,6 +769,331 @@ def add_allam(n, costs):
)
+def add_biomass_to_methanol(n, costs):
+
+ if len(spatial.biomass.nodes) <= 1 and len(spatial.methanol.nodes) > 1:
+ link_names = nodes + " " + spatial.biomass.nodes
+ else:
+ link_names = spatial.biomass.nodes
+
+ n.madd(
+ "Link",
+ link_names,
+ suffix=" biomass-to-methanol",
+ bus0=spatial.biomass.nodes,
+ bus1=spatial.methanol.nodes,
+ bus2="co2 atmosphere",
+ carrier="biomass-to-methanol",
+ lifetime=costs.at["biomass-to-methanol", "lifetime"],
+ efficiency=costs.at["biomass-to-methanol", "efficiency"],
+ efficiency2=-costs.at["solid biomass", "CO2 intensity"]
+ + costs.at["biomass-to-methanol", "CO2 stored"],
+ p_nom_extendable=True,
+ capital_cost=costs.at["biomass-to-methanol", "fixed"]
+ / costs.at["biomass-to-methanol", "efficiency"],
+ marginal_cost=costs.loc["biomass-to-methanol", "VOM"]
+ / costs.at["biomass-to-methanol", "efficiency"],
+ )
+
+
+def add_biomass_to_methanol_cc(n, costs):
+
+ if len(spatial.biomass.nodes) <= 1 and len(spatial.methanol.nodes) > 1:
+ link_names = nodes + " " + spatial.biomass.nodes
+ else:
+ link_names = spatial.biomass.nodes
+
+ n.madd(
+ "Link",
+ link_names,
+ suffix=" biomass-to-methanol CC",
+ bus0=spatial.biomass.nodes,
+ bus1=spatial.methanol.nodes,
+ bus2="co2 atmosphere",
+ bus3=spatial.co2.nodes,
+ carrier="biomass-to-methanol CC",
+ lifetime=costs.at["biomass-to-methanol", "lifetime"],
+ efficiency=costs.at["biomass-to-methanol", "efficiency"],
+ efficiency2=-costs.at["solid biomass", "CO2 intensity"]
+ + costs.at["biomass-to-methanol", "CO2 stored"]
+ * (1 - costs.at["biomass-to-methanol", "capture rate"]),
+ efficiency3=costs.at["biomass-to-methanol", "CO2 stored"]
+ * costs.at["biomass-to-methanol", "capture rate"],
+ p_nom_extendable=True,
+ capital_cost=costs.at["biomass-to-methanol", "fixed"]
+ / costs.at["biomass-to-methanol", "efficiency"]
+ + costs.at["biomass CHP capture", "fixed"]
+ * costs.at["biomass-to-methanol", "CO2 stored"],
+ marginal_cost=costs.loc["biomass-to-methanol", "VOM"]
+ / costs.at["biomass-to-methanol", "efficiency"],
+ )
+
+
+def add_methanol_to_power(n, costs, types={}):
+ # TODO: add costs to technology-data
+
+ nodes = pop_layout.index
+
+ if types["allam"]:
+ logger.info("Adding Allam cycle methanol power plants.")
+
+ n.madd(
+ "Link",
+ nodes,
+ suffix=" allam methanol",
+ bus0=spatial.methanol.nodes,
+ bus1=nodes,
+ bus2=spatial.co2.df.loc[nodes, "nodes"].values,
+ bus3="co2 atmosphere",
+ carrier="allam methanol",
+ p_nom_extendable=True,
+ capital_cost=0.59
+ * 1.832e6
+ * calculate_annuity(25, 0.07), # efficiency * EUR/MW * annuity
+ marginal_cost=2,
+ efficiency=0.59,
+ efficiency2=0.98 * costs.at["methanolisation", "carbondioxide-input"],
+ efficiency3=0.02 * costs.at["methanolisation", "carbondioxide-input"],
+ lifetime=25,
+ )
+
+ if types["ccgt"]:
+ logger.info("Adding methanol CCGT power plants.")
+
+ # efficiency * EUR/MW * (annuity + FOM)
+ capital_cost = 0.58 * 916e3 * (calculate_annuity(25, 0.07) + 0.035)
+
+ n.madd(
+ "Link",
+ nodes,
+ suffix=" CCGT methanol",
+ bus0=spatial.methanol.nodes,
+ bus1=nodes,
+ bus2="co2 atmosphere",
+ carrier="CCGT methanol",
+ p_nom_extendable=True,
+ capital_cost=capital_cost,
+ marginal_cost=2,
+ efficiency=0.58,
+ efficiency2=costs.at["methanolisation", "carbondioxide-input"],
+ lifetime=25,
+ )
+
+ if types["ccgt_cc"]:
+ logger.info(
+ "Adding methanol CCGT power plants with post-combustion carbon capture."
+ )
+
+ # TODO consider efficiency changes / energy inputs for CC
+
+ # efficiency * EUR/MW * (annuity + FOM)
+ capital_cost = 0.58 * 916e3 * (calculate_annuity(25, 0.07) + 0.035)
+
+ capital_cost_cc = (
+ capital_cost
+ + costs.at["cement capture", "fixed"]
+ * costs.at["methanolisation", "carbondioxide-input"]
+ )
+
+ n.madd(
+ "Link",
+ nodes,
+ suffix=" CCGT methanol CC",
+ bus0=spatial.methanol.nodes,
+ bus1=nodes,
+ bus2=spatial.co2.df.loc[nodes, "nodes"].values,
+ bus3="co2 atmosphere",
+ carrier="CCGT methanol CC",
+ p_nom_extendable=True,
+ capital_cost=capital_cost_cc,
+ marginal_cost=2,
+ efficiency=0.58,
+ efficiency2=costs.at["cement capture", "capture_rate"]
+ * costs.at["methanolisation", "carbondioxide-input"],
+ efficiency3=(1 - costs.at["cement capture", "capture_rate"])
+ * costs.at["methanolisation", "carbondioxide-input"],
+ lifetime=25,
+ )
+
+ if types["ocgt"]:
+ logger.info("Adding methanol OCGT power plants.")
+
+ n.madd(
+ "Link",
+ nodes,
+ suffix=" OCGT methanol",
+ bus0=spatial.methanol.nodes,
+ bus1=nodes,
+ bus2="co2 atmosphere",
+ carrier="OCGT methanol",
+ p_nom_extendable=True,
+ capital_cost=0.35
+ * 458e3
+ * (
+ calculate_annuity(25, 0.07) + 0.035
+ ), # efficiency * EUR/MW * (annuity + FOM)
+ marginal_cost=2,
+ efficiency=0.35,
+ efficiency2=costs.at["methanolisation", "carbondioxide-input"],
+ lifetime=25,
+ )
+
+
+def add_methanol_to_olefins(n, costs):
+ nodes = pop_layout.index
+ nhours = n.snapshot_weightings.generators.sum()
+ nyears = nhours / 8760
+
+ tech = "methanol-to-olefins/aromatics"
+
+ logger.info(f"Adding {tech}.")
+
+ demand_factor = options["HVC_demand_factor"]
+
+ industrial_production = (
+ pd.read_csv(snakemake.input.industrial_production, index_col=0)
+ * 1e3
+ * nyears # kt/a -> t/a
+ )
+
+ p_nom_max = (
+ demand_factor
+ * industrial_production.loc[nodes, "HVC"]
+ / nhours
+ * costs.at[tech, "methanol-input"]
+ )
+
+ co2_release = (
+ costs.at[tech, "carbondioxide-output"] / costs.at[tech, "methanol-input"]
+ + costs.at["methanolisation", "carbondioxide-input"]
+ )
+
+ n.madd(
+ "Link",
+ spatial.methanol.locations,
+ suffix=f" {tech}",
+ carrier=tech,
+ capital_cost=costs.at[tech, "fixed"] / costs.at[tech, "methanol-input"],
+ marginal_cost=costs.at[tech, "VOM"] / costs.at[tech, "methanol-input"],
+ p_nom_extendable=True,
+ bus0=spatial.methanol.nodes,
+ bus1=spatial.oil.naphtha,
+ bus2=nodes,
+ bus3="co2 atmosphere",
+ p_min_pu=1,
+ p_nom_max=p_nom_max.values,
+ efficiency=1 / costs.at[tech, "methanol-input"],
+ efficiency2=-costs.at[tech, "electricity-input"]
+ / costs.at[tech, "methanol-input"],
+ efficiency3=co2_release,
+ )
+
+
+def add_methanol_to_kerosene(n, costs):
+ nodes = pop_layout.index
+ nhours = n.snapshot_weightings.generators.sum()
+ nyears = nhours / 8760
+
+ demand_factor = options["aviation_demand_factor"]
+
+ tech = "methanol-to-kerosene"
+
+ logger.info(f"Adding {tech}.")
+
+ all_aviation = ["total international aviation", "total domestic aviation"]
+
+ p_nom_max = (
+ demand_factor
+ * pop_weighted_energy_totals.loc[nodes, all_aviation].sum(axis=1)
+ * 1e6
+ / nhours
+ * costs.at[tech, "methanol-input"]
+ )
+
+ # cost data available at https://www.concawe.eu/wp-content/uploads/Rpt_22-17.pdf table 94
+
+ n.madd(
+ "Link",
+ spatial.methanol.locations,
+ suffix=f" {tech}",
+ carrier=tech,
+ # capital_cost= ,
+ bus0=spatial.methanol.nodes,
+ bus1=spatial.oil.kerosene,
+ bus2=spatial.h2.nodes,
+ efficiency=costs.at[tech, "methanol-input"],
+ efficiency2=-costs.at[tech, "hydrogen-input"]
+ / costs.at[tech, "methanol-input"],
+ p_nom_extendable=True,
+ p_min_pu=1,
+ p_nom_max=p_nom_max.values,
+ )
+
+
+def add_methanol_reforming(n, costs):
+ logger.info("Adding methanol steam reforming.")
+
+ nodes = pop_layout.index
+
+ tech = "Methanol steam reforming"
+
+ capital_cost = costs.at[tech, "fixed"] / costs.at[tech, "methanol-input"]
+
+ n.madd(
+ "Link",
+ spatial.methanol.locations,
+ suffix=f" {tech}",
+ bus0=spatial.methanol.nodes,
+ bus1=spatial.h2.nodes,
+ bus2="co2 atmosphere",
+ p_nom_extendable=True,
+ capital_cost=capital_cost,
+ efficiency=1 / costs.at[tech, "methanol-input"],
+ efficiency2=costs.at["methanolisation", "carbondioxide-input"],
+ carrier=tech,
+ lifetime=costs.at[tech, "lifetime"],
+ )
+
+
+def add_methanol_reforming_cc(n, costs):
+ logger.info("Adding methanol steam reforming with carbon capture.")
+
+ nodes = pop_layout.index
+
+ tech = "Methanol steam reforming"
+
+ # TODO: heat release and electricity demand for process and carbon capture
+ # but the energy demands for carbon capture have not yet been added for other CC processes
+ # 10.1016/j.rser.2020.110171: 0.129 kWh_e/kWh_H2, -0.09 kWh_heat/kWh_H2
+
+ capital_cost = costs.at[tech, "fixed"] / costs.at[tech, "methanol-input"]
+
+ capital_cost_cc = (
+ capital_cost
+ + costs.at["cement capture", "fixed"]
+ * costs.at["methanolisation", "carbondioxide-input"]
+ )
+
+ n.madd(
+ "Link",
+ nodes,
+ suffix=f" {tech} CC",
+ bus0=spatial.methanol.nodes,
+ bus1=spatial.h2.nodes,
+ bus2="co2 atmosphere",
+ bus3=spatial.co2.nodes,
+ p_nom_extendable=True,
+ capital_cost=capital_cost_cc,
+ efficiency=1 / costs.at[tech, "methanol-input"],
+ efficiency2=(1 - costs.at["cement capture", "capture_rate"])
+ * costs.at["methanolisation", "carbondioxide-input"],
+ efficiency3=costs.at["cement capture", "capture_rate"]
+ * costs.at["methanolisation", "carbondioxide-input"],
+ carrier=f"{tech} CC",
+ lifetime=costs.at[tech, "lifetime"],
+ )
+
+
def add_dac(n, costs):
heat_carriers = ["urban central heat", "services urban decentral heat"]
heat_buses = n.buses.index[n.buses.carrier.isin(heat_carriers)]
@@ -2226,6 +2558,64 @@ def add_heat(n, costs):
)
+def add_methanol(n, costs):
+ logger.info("Add methanol")
+
+ n.add("Carrier", "methanol")
+
+ n.madd(
+ "Bus",
+ spatial.methanol.nodes,
+ location=spatial.methanol.locations,
+ carrier="methanol",
+ unit="MWh_LHV",
+ )
+
+ n.madd(
+ "Store",
+ spatial.methanol.nodes,
+ suffix=" Store",
+ bus=spatial.methanol.nodes,
+ e_nom_extendable=True,
+ e_cyclic=True,
+ carrier="methanol",
+ capital_cost=0.02,
+ )
+
+ if options["methanol_transport"]:
+ methanol_transport = create_network_topology(
+ n, "methanol transport ", bidirectional=True
+ )
+ n.madd(
+ "Link",
+ methanol_transport.index,
+ bus0=methanol_transport.bus0 + " methanol",
+ bus1=methanol_transport.bus1 + " methanol",
+ p_nom_extendable=False,
+ p_nom=5e4,
+ length=methanol_transport.length.values,
+ marginal_cost=0.027
+ * methanol_transport.length.values, # assuming 0.15€/ton-km and 0.183t/1000MWhMeOH
+ carrier="methanol transport",
+ )
+
+ if "biomass" in n.buses.carrier.unique():
+ if options["biomass_to_methanol"]:
+ add_biomass_to_methanol(n, costs)
+
+ if options["biomass_to_methanol"]:
+ add_biomass_to_methanol_cc(n, costs)
+
+ if options["methanol_to_power"]:
+ add_methanol_to_power(n, costs, types=options["methanol_to_power"])
+
+ if options["methanol_reforming"]:
+ add_methanol_reforming(n, costs)
+
+ if options["methanol_reforming_cc"]:
+ add_methanol_reforming_cc(n, costs)
+
+
def add_biomass(n, costs):
logger.info("Add biomass")
@@ -2685,25 +3075,26 @@ def add_industry(n, costs):
)
# methanol for industry
+ # add methanol nodes if not already added
+ if "methanol" not in n.buses.carrier.unique():
+ n.madd(
+ "Bus",
+ spatial.methanol.nodes,
+ carrier="methanol",
+ location=spatial.methanol.locations,
+ unit="MWh_LHV",
+ )
- n.madd(
- "Bus",
- spatial.methanol.nodes,
- carrier="methanol",
- location=spatial.methanol.locations,
- unit="MWh_LHV",
- )
-
- n.madd(
- "Store",
- spatial.methanol.nodes,
- suffix=" Store",
- bus=spatial.methanol.nodes,
- e_nom_extendable=True,
- e_cyclic=True,
- carrier="methanol",
- capital_cost=0.02,
- )
+ n.madd(
+ "Store",
+ spatial.methanol.nodes,
+ suffix=" Store",
+ bus=spatial.methanol.nodes,
+ e_nom_extendable=True,
+ e_cyclic=True,
+ carrier="methanol",
+ capital_cost=0.02,
+ )
n.madd(
"Bus",
@@ -2718,7 +3109,7 @@ def add_industry(n, costs):
/ nhours
)
- if not options["regional_methanol_demand"]:
+ if not options["regional_methanol_demand"] or not options["methanol_spatial"]:
p_set_methanol = p_set_methanol.sum()
n.madd(
@@ -2840,7 +3231,7 @@ def add_industry(n, costs):
* efficiency
)
- if not options["regional_methanol_demand"]:
+ if not options["regional_methanol_demand"] or not options["methanol_spatial"]:
p_set_methanol_shipping = p_set_methanol_shipping.sum()
n.madd(
@@ -3129,6 +3520,9 @@ def add_industry(n, costs):
efficiency3=process_co2_per_naphtha,
)
+ if options["methanol_to_olefins"]:
+ add_methanol_to_olefins(n, costs)
+
# aviation
demand_factor = options.get("aviation_demand_factor", 1)
if demand_factor != 1:
@@ -3173,6 +3567,9 @@ def add_industry(n, costs):
efficiency2=costs.at["oil", "CO2 intensity"],
)
+ if options["methanol_to_kerosene"]:
+ add_methanol_to_kerosene(n, costs)
+
# TODO simplify bus expression
n.madd(
"Load",
@@ -3947,9 +4344,10 @@ def add_enhanced_geothermal(n, egs_potentials, egs_overlap, costs):
simpl="",
opts="",
clusters="37",
- ll="v1.0",
- sector_opts="730H-T-H-B-I-A-dist1",
+ ll="vopt",
+ sector_opts="",
planning_horizons="2050",
+ run="enable_all",
)
configure_logging(snakemake)
@@ -4012,6 +4410,9 @@ def add_enhanced_geothermal(n, egs_potentials, egs_overlap, costs):
if options["ammonia"]:
add_ammonia(n, costs)
+ if options["methanol"]:
+ add_methanol(n, costs)
+
if options["industry"]:
add_industry(n, costs)
From acb0a8d7af0c452c44d9823692a583ba281b74fd Mon Sep 17 00:00:00 2001
From: Philipp Glaum
Date: Mon, 5 Aug 2024 10:08:04 +0200
Subject: [PATCH 02/14] get methanol to kerosene cost form technology data
---
scripts/prepare_sector_network.py | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py
index 245d6bc4d..898496d0b 100644
--- a/scripts/prepare_sector_network.py
+++ b/scripts/prepare_sector_network.py
@@ -1011,15 +1011,14 @@ def add_methanol_to_kerosene(n, costs):
* costs.at[tech, "methanol-input"]
)
- # cost data available at https://www.concawe.eu/wp-content/uploads/Rpt_22-17.pdf table 94
+ capital_cost = costs.at[tech, "fixed"] / costs.at[tech, "methanol-input"]
n.madd(
"Link",
spatial.methanol.locations,
suffix=f" {tech}",
carrier=tech,
- # capital_cost= ,
- bus0=spatial.methanol.nodes,
+ capital_cost=capital_cost,
bus1=spatial.oil.kerosene,
bus2=spatial.h2.nodes,
efficiency=costs.at[tech, "methanol-input"],
From 975716250ad3c133b105b3d0b34822478fdea8b2 Mon Sep 17 00:00:00 2001
From: Philipp Glaum
Date: Mon, 5 Aug 2024 12:00:15 +0200
Subject: [PATCH 03/14] add bus0 for methanol-to-kerosene process
---
scripts/prepare_sector_network.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py
index 989bc4f95..581074f2c 100644
--- a/scripts/prepare_sector_network.py
+++ b/scripts/prepare_sector_network.py
@@ -1022,6 +1022,7 @@ def add_methanol_to_kerosene(n, costs):
suffix=f" {tech}",
carrier=tech,
capital_cost=capital_cost,
+ bus0=spatial.methanol.nodes,
bus1=spatial.oil.kerosene,
bus2=spatial.h2.nodes,
efficiency=costs.at[tech, "methanol-input"],
From b298d58d61e4e5002a97fe4382ae86d11c2ae60a Mon Sep 17 00:00:00 2001
From: Philipp Glaum
Date: Mon, 5 Aug 2024 13:27:43 +0200
Subject: [PATCH 04/14] fix missing biomass-to-methanol due to wrong if
statement
---
scripts/prepare_sector_network.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py
index 581074f2c..5d61821cf 100644
--- a/scripts/prepare_sector_network.py
+++ b/scripts/prepare_sector_network.py
@@ -2605,7 +2605,7 @@ def add_methanol(n, costs):
carrier="methanol transport",
)
- if "biomass" in n.buses.carrier.unique():
+ if n.buses.carrier.str.contains("biomass").any():
if options["biomass_to_methanol"]:
add_biomass_to_methanol(n, costs)
From 280e8d6d01237a79a1befd4c1df19db6bfa440c4 Mon Sep 17 00:00:00 2001
From: Philipp Glaum
Date: Mon, 5 Aug 2024 13:40:05 +0200
Subject: [PATCH 05/14] use correct colorcode for biomass-to-methanol
---
config/config.default.yaml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/config/config.default.yaml b/config/config.default.yaml
index 10d166146..6ba8039e6 100644
--- a/config/config.default.yaml
+++ b/config/config.default.yaml
@@ -1183,8 +1183,8 @@ plotting:
Methanol steam reforming: '#FFBF00'
Methanol steam reforming CC: '#A2EA8A'
methanolisation: '#00FFBF'
- biomass-to-methanol: #EAD28A
- biomass-to-methanol CC: #EADBAD
+ biomass-to-methanol: '#EAD28A'
+ biomass-to-methanol CC: '#EADBAD'
allam methanol: '#B98F76'
CCGT methanol: '#B98F76'
CCGT methanol CC: '#B98F76'
From 5c577b62906bbbf163013d62c18197cc34e43f79 Mon Sep 17 00:00:00 2001
From: Philipp Glaum
Date: Mon, 12 Aug 2024 10:38:01 +0200
Subject: [PATCH 06/14] remove methanol transport because it has no impact
---
config/config.default.yaml | 4 +---
scripts/prepare_sector_network.py | 38 ++++++-------------------------
2 files changed, 8 insertions(+), 34 deletions(-)
diff --git a/config/config.default.yaml b/config/config.default.yaml
index 83371c379..f4a70c244 100644
--- a/config/config.default.yaml
+++ b/config/config.default.yaml
@@ -590,10 +590,8 @@ sector:
# - onshore # more than 50 km from sea
- nearshore # within 50 km of sea
# - offshore
- methanol: false # if industry is modelled, methanol is still added even if false
- methanol_spatial: false # if true demand is also regional even if regional demand is set to false, since methanol is regionally resolved
regional_methanol_demand: false
- methanol_transport: false
+ methanol: false
methanol_reforming: false
methanol_reforming_cc: false
methanol_to_kerosene: false
diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py
index bb850c3a3..eb16ac946 100644
--- a/scripts/prepare_sector_network.py
+++ b/scripts/prepare_sector_network.py
@@ -153,24 +153,17 @@ def define_spatial(nodes, options):
spatial.methanol = SimpleNamespace()
- if options.get("methanol_spatial", False):
- spatial.methanol.nodes = nodes + " methanol"
- spatial.methanol.locations = nodes
+ spatial.methanol.nodes = ["EU methanol"]
+ spatial.methanol.locations = ["EU"]
+
+ if options["regional_methanol_demand"]:
spatial.methanol.demand_locations = nodes
spatial.methanol.industry = nodes + " industry methanol"
spatial.methanol.shipping = nodes + " shipping methanol"
else:
- spatial.methanol.nodes = ["EU methanol"]
- spatial.methanol.locations = ["EU"]
-
- if options["regional_methanol_demand"]:
- spatial.methanol.demand_locations = nodes
- spatial.methanol.industry = nodes + " industry methanol"
- spatial.methanol.shipping = nodes + " shipping methanol"
- else:
- spatial.methanol.demand_locations = ["EU"]
- spatial.methanol.shipping = ["EU shipping methanol"]
- spatial.methanol.industry = ["EU industry methanol"]
+ spatial.methanol.demand_locations = ["EU"]
+ spatial.methanol.shipping = ["EU shipping methanol"]
+ spatial.methanol.industry = ["EU industry methanol"]
# oil
spatial.oil = SimpleNamespace()
@@ -2610,23 +2603,6 @@ def add_methanol(n, costs):
capital_cost=0.02,
)
- if options["methanol_transport"]:
- methanol_transport = create_network_topology(
- n, "methanol transport ", bidirectional=True
- )
- n.madd(
- "Link",
- methanol_transport.index,
- bus0=methanol_transport.bus0 + " methanol",
- bus1=methanol_transport.bus1 + " methanol",
- p_nom_extendable=False,
- p_nom=5e4,
- length=methanol_transport.length.values,
- marginal_cost=0.027
- * methanol_transport.length.values, # assuming 0.15€/ton-km and 0.183t/1000MWhMeOH
- carrier="methanol transport",
- )
-
if n.buses.carrier.str.contains("biomass").any():
if options["biomass_to_methanol"]:
add_biomass_to_methanol(n, costs)
From d14ced2549f8f0669fdba420906250da661c751d Mon Sep 17 00:00:00 2001
From: Philipp Glaum
Date: Mon, 12 Aug 2024 10:43:13 +0200
Subject: [PATCH 07/14] cleanup
---
scripts/prepare_sector_network.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py
index eb16ac946..ca3634a84 100644
--- a/scripts/prepare_sector_network.py
+++ b/scripts/prepare_sector_network.py
@@ -3367,7 +3367,7 @@ def add_industry(n, costs):
/ nhours
)
- if not options["regional_methanol_demand"] or not options["methanol_spatial"]:
+ if not options["regional_methanol_demand"]:
p_set_methanol = p_set_methanol.sum()
n.madd(
@@ -3490,7 +3490,7 @@ def add_industry(n, costs):
* efficiency
)
- if not options["regional_methanol_demand"] or not options["methanol_spatial"]:
+ if not options["regional_methanol_demand"]:
p_set_methanol_shipping = p_set_methanol_shipping.sum()
n.madd(
From 560929a2a8dbf3b0d7bdfc9a43d020b6a1193dd3 Mon Sep 17 00:00:00 2001
From: Philipp Glaum
Date: Mon, 12 Aug 2024 10:55:32 +0200
Subject: [PATCH 08/14] add release note
---
doc/release_notes.rst | 1 +
1 file changed, 1 insertion(+)
diff --git a/doc/release_notes.rst b/doc/release_notes.rst
index 7404e2ef4..9d059e7a4 100644
--- a/doc/release_notes.rst
+++ b/doc/release_notes.rst
@@ -9,6 +9,7 @@ Release Notes
Upcoming Release
================
+* Add technology options for methanol, like electricity production from methanol, biomass to methanol, methanol to kerosene, ...
* Added unsustainable biomass potentials for solid, gaseous, and liquid biomass. The potentials can be phased-out and/or
substituted by the phase-in of sustainable biomass types using the config parameters
From aa91c7b2461e85e9c6ce9df826af3688b69f44a9 Mon Sep 17 00:00:00 2001
From: Philipp Glaum
Date: Mon, 12 Aug 2024 11:11:05 +0200
Subject: [PATCH 09/14] add documentation for configuration
---
config/config.default.yaml | 2 +-
doc/configtables/sector.csv | 13 ++++++++++++-
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/config/config.default.yaml b/config/config.default.yaml
index f4a70c244..8f9e6d7ad 100644
--- a/config/config.default.yaml
+++ b/config/config.default.yaml
@@ -590,8 +590,8 @@ sector:
# - onshore # more than 50 km from sea
- nearshore # within 50 km of sea
# - offshore
- regional_methanol_demand: false
methanol: false
+ regional_methanol_demand: false
methanol_reforming: false
methanol_reforming_cc: false
methanol_to_kerosene: false
diff --git a/doc/configtables/sector.csv b/doc/configtables/sector.csv
index e0deb8ca9..b9dd22f08 100644
--- a/doc/configtables/sector.csv
+++ b/doc/configtables/sector.csv
@@ -99,7 +99,6 @@ hydrogen_fuel_cell,--,"{true, false}",Add option to include hydrogen fuel cell f
hydrogen_turbine,--,"{true, false}",Add option to include hydrogen turbine for re-electrification. Assuming OCGT technology costs
SMR,--,"{true, false}",Add option for transforming natural gas into hydrogen and CO2 using Steam Methane Reforming (SMR)
SMR CC,--,"{true, false}",Add option for transforming natural gas into hydrogen and CO2 using Steam Methane Reforming (SMR) and Carbon Capture (CC)
-regional_methanol_demand,--,"{true, false}",Spatially resolve methanol demand. Set to true if regional CO2 constraints needed.
regional_oil_demand,--,"{true, false}",Spatially resolve oil demand. Set to true if regional CO2 constraints needed.
regional_co2 _sequestration_potential,,,
-- enable,--,"{true, false}",Add option for regionally-resolved geological carbon dioxide sequestration potentials based on `CO2StoP `_.
@@ -120,6 +119,18 @@ cc_fraction,--,float,The default fraction of CO2 captured with post-combustion c
hydrogen_underground _storage,--,"{true, false}",Add options for storing hydrogen underground. Storage potential depends regionally.
hydrogen_underground _storage_locations,,"{onshore, nearshore, offshore}","The location where hydrogen underground storage can be located. Onshore, nearshore, offshore means it must be located more than 50 km away from the sea, within 50 km of the sea, or within the sea itself respectively."
,,,
+methanol, --,"{true, false}", Add methanol as carrrier and add enables methnol technologies
+regional_methanol_demand,--,"{true, false}",Spatially resolve methanol demand. Set to true if regional CO2 constraints needed.
+methanol_reforming,--,"{true, false}", Add methanol reforming
+methanol_reforming_cc,--,"{true, false}", Add methanol reforming with carbon capture
+methanol_to_kerosene,--,"{true, false}", Add methanol to kerosene
+methanol_to_olefins,--,"{true, false}", Add methanol to olefins
+methanol_to_power,--,--, Add different methanol to power technologies
+-- ccgt,--,"{true, false}", Add combined cycle gas turbine (CCGT) technology using methanol
+-- ccgt_cc,--,"{true, false}", Add combined cycle gas turbine (CCGT) technology using methanol with carbon capture
+-- ocgt,--,"{true, false}", Add open cycle gas turbine (OCGT) technology using methanol
+-- allam,--,"{true, false}", Add Allam cycle gas power plants using methanol
+,,,
ammonia,--,"{true, false, regional}","Add ammonia as a carrrier. It can be either true (copperplated NH3), false (no NH3 carrier) or ""regional"" (regionalised NH3 without network)"
min_part_load_fischer _tropsch,per unit of p_nom ,float,The minimum unit dispatch (``p_min_pu``) for the Fischer-Tropsch process
min_part_load _methanolisation,per unit of p_nom ,float,The minimum unit dispatch (``p_min_pu``) for the methanolisation process
From a76cb299641bad65046c1ad56cf37236fa25cacd Mon Sep 17 00:00:00 2001
From: Philipp Glaum
Date: Mon, 12 Aug 2024 11:26:18 +0200
Subject: [PATCH 10/14] fix spelling mistake
---
doc/configtables/sector.csv | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/doc/configtables/sector.csv b/doc/configtables/sector.csv
index b9dd22f08..c50bf6091 100644
--- a/doc/configtables/sector.csv
+++ b/doc/configtables/sector.csv
@@ -119,16 +119,16 @@ cc_fraction,--,float,The default fraction of CO2 captured with post-combustion c
hydrogen_underground _storage,--,"{true, false}",Add options for storing hydrogen underground. Storage potential depends regionally.
hydrogen_underground _storage_locations,,"{onshore, nearshore, offshore}","The location where hydrogen underground storage can be located. Onshore, nearshore, offshore means it must be located more than 50 km away from the sea, within 50 km of the sea, or within the sea itself respectively."
,,,
-methanol, --,"{true, false}", Add methanol as carrrier and add enables methnol technologies
+methanol, --,"{true, false}", Add methanol as carrrier and add enabled methnol technologies
regional_methanol_demand,--,"{true, false}",Spatially resolve methanol demand. Set to true if regional CO2 constraints needed.
methanol_reforming,--,"{true, false}", Add methanol reforming
methanol_reforming_cc,--,"{true, false}", Add methanol reforming with carbon capture
methanol_to_kerosene,--,"{true, false}", Add methanol to kerosene
methanol_to_olefins,--,"{true, false}", Add methanol to olefins
methanol_to_power,--,--, Add different methanol to power technologies
--- ccgt,--,"{true, false}", Add combined cycle gas turbine (CCGT) technology using methanol
--- ccgt_cc,--,"{true, false}", Add combined cycle gas turbine (CCGT) technology using methanol with carbon capture
--- ocgt,--,"{true, false}", Add open cycle gas turbine (OCGT) technology using methanol
+-- ccgt,--,"{true, false}", Add combined cycle gas turbine (CCGT) using methanol
+-- ccgt_cc,--,"{true, false}", Add combined cycle gas turbine (CCGT) with carbon capture using methanol
+-- ocgt,--,"{true, false}", Add open cycle gas turbine (OCGT) using methanol
-- allam,--,"{true, false}", Add Allam cycle gas power plants using methanol
,,,
ammonia,--,"{true, false, regional}","Add ammonia as a carrrier. It can be either true (copperplated NH3), false (no NH3 carrier) or ""regional"" (regionalised NH3 without network)"
From 25f6c014e72e491df399977992aaf74ae0215dcf Mon Sep 17 00:00:00 2001
From: Philipp Glaum
Date: Mon, 26 Aug 2024 15:15:02 +0200
Subject: [PATCH 11/14] adress review comments
---
config/config.default.yaml | 26 ++++-----
doc/configtables/sector.csv | 26 ++++-----
scripts/prepare_sector_network.py | 96 ++++++++++---------------------
3 files changed, 57 insertions(+), 91 deletions(-)
diff --git a/config/config.default.yaml b/config/config.default.yaml
index f3f4f2384..eeff81912 100644
--- a/config/config.default.yaml
+++ b/config/config.default.yaml
@@ -631,19 +631,19 @@ sector:
# - onshore # more than 50 km from sea
- nearshore # within 50 km of sea
# - offshore
- methanol: false
- regional_methanol_demand: false
- methanol_reforming: false
- methanol_reforming_cc: false
- methanol_to_kerosene: false
- methanol_to_olefins: false
- methanol_to_power:
- ccgt: false
- ccgt_cc: false
- ocgt: false
- allam: false
- biomass_to_methanol: false
- biomass_to_methanol_cc: false
+ methanol:
+ regional_methanol_demand: false
+ methanol_reforming: false
+ methanol_reforming_cc: false
+ methanol_to_kerosene: false
+ methanol_to_olefins: false
+ methanol_to_power:
+ ccgt: false
+ ccgt_cc: false
+ ocgt: false
+ allam: false
+ biomass_to_methanol: false
+ biomass_to_methanol_cc: false
ammonia: false
min_part_load_fischer_tropsch: 0.5
min_part_load_methanolisation: 0.3
diff --git a/doc/configtables/sector.csv b/doc/configtables/sector.csv
index c554e5e9a..916bce09f 100644
--- a/doc/configtables/sector.csv
+++ b/doc/configtables/sector.csv
@@ -89,7 +89,7 @@ chp,--,"{true, false}",Add option for using Combined Heat and Power (CHP)
micro_chp,--,"{true, false}",Add option for using Combined Heat and Power (CHP) for decentral areas.
solar_thermal,--,"{true, false}",Add option for using solar thermal to generate heat.
solar_cf_correction,--,float,The correction factor for the value provided by the solar thermal profile calculations
-marginal_cost_storage,currency/MWh ,float,The marginal cost of discharging batteries in distributed grids
+marginal_cost_storage,"currency/MWh ",float,The marginal cost of discharging batteries in distributed grids
methanation,--,"{true, false}",Add option for transforming hydrogen and CO2 into methane using methanation.
coal_cc,--,"{true, false}",Add option for coal CHPs with carbon capture
dac,--,"{true, false}",Add option for Direct Air Capture (DAC)
@@ -119,17 +119,17 @@ cc_fraction,--,float,The default fraction of CO2 captured with post-combustion c
hydrogen_underground _storage,--,"{true, false}",Add options for storing hydrogen underground. Storage potential depends regionally.
hydrogen_underground _storage_locations,,"{onshore, nearshore, offshore}","The location where hydrogen underground storage can be located. Onshore, nearshore, offshore means it must be located more than 50 km away from the sea, within 50 km of the sea, or within the sea itself respectively."
,,,
-methanol, --,"{true, false}", Add methanol as carrrier and add enabled methnol technologies
-regional_methanol_demand,--,"{true, false}",Spatially resolve methanol demand. Set to true if regional CO2 constraints needed.
-methanol_reforming,--,"{true, false}", Add methanol reforming
-methanol_reforming_cc,--,"{true, false}", Add methanol reforming with carbon capture
-methanol_to_kerosene,--,"{true, false}", Add methanol to kerosene
-methanol_to_olefins,--,"{true, false}", Add methanol to olefins
-methanol_to_power,--,--, Add different methanol to power technologies
--- ccgt,--,"{true, false}", Add combined cycle gas turbine (CCGT) using methanol
--- ccgt_cc,--,"{true, false}", Add combined cycle gas turbine (CCGT) with carbon capture using methanol
--- ocgt,--,"{true, false}", Add open cycle gas turbine (OCGT) using methanol
--- allam,--,"{true, false}", Add Allam cycle gas power plants using methanol
+methanol,--,--,Add methanol as carrrier and add enabled methnol technologies
+-- regional_methanol_demand,--,"{true, false}",Spatially resolve methanol demand. Set to true if regional CO2 constraints needed.
+-- methanol_reforming,--,"{true, false}"," Add methanol reforming"
+-- methanol_reforming_cc,--,"{true, false}"," Add methanol reforming with carbon capture"
+-- methanol_to_kerosene,--,"{true, false}"," Add methanol to kerosene"
+-- methanol_to_olefins,--,"{true, false}"," Add methanol to olefins"
+-- methanol_to_power,--,--," Add different methanol to power technologies"
+-- -- ccgt,--,"{true, false}"," Add combined cycle gas turbine (CCGT) using methanol"
+-- -- ccgt_cc,--,"{true, false}"," Add combined cycle gas turbine (CCGT) with carbon capture using methanol"
+-- -- ocgt,--,"{true, false}"," Add open cycle gas turbine (OCGT) using methanol"
+-- -- allam,--,"{true, false}"," Add Allam cycle gas power plants using methanol"
,,,
ammonia,--,"{true, false, regional}","Add ammonia as a carrrier. It can be either true (copperplated NH3), false (no NH3 carrier) or ""regional"" (regionalised NH3 without network)"
min_part_load_fischer _tropsch,per unit of p_nom ,float,The minimum unit dispatch (``p_min_pu``) for the Fischer-Tropsch process
@@ -152,7 +152,7 @@ H2_network,--,"{true, false}",Add option for new hydrogen pipelines
gas_network,--,"{true, false}","Add existing natural gas infrastructure, incl. LNG terminals, production and entry-points. The existing gas network is added with a lossless transport model. A length-weighted `k-edge augmentation algorithm `_ can be run to add new candidate gas pipelines such that all regions of the model can be connected to the gas network. When activated, all the gas demands are regionally disaggregated as well."
H2_retrofit,--,"{true, false}",Add option for retrofiting existing pipelines to transport hydrogen.
H2_retrofit_capacity _per_CH4,--,float,"The ratio for H2 capacity per original CH4 capacity of retrofitted pipelines. The `European Hydrogen Backbone (April, 2020) p.15 `_ 60% of original natural gas capacity could be used in cost-optimal case as H2 capacity."
-gas_network_connectivity _upgrade ,--,float,The number of desired edge connectivity (k) in the length-weighted `k-edge augmentation algorithm `_ used for the gas network
+"gas_network_connectivity _upgrade ",--,float,The number of desired edge connectivity (k) in the length-weighted `k-edge augmentation algorithm `_ used for the gas network
gas_distribution_grid,--,"{true, false}",Add a gas distribution grid
gas_distribution_grid _cost_factor,,,Multiplier for the investment cost of the gas distribution grid
,,,
diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py
index 4bbced7e4..27a5e2e79 100644
--- a/scripts/prepare_sector_network.py
+++ b/scripts/prepare_sector_network.py
@@ -155,7 +155,7 @@ def define_spatial(nodes, options):
spatial.methanol.nodes = ["EU methanol"]
spatial.methanol.locations = ["EU"]
- if options["regional_methanol_demand"]:
+ if options["methanol"]["regional_methanol_demand"]:
spatial.methanol.demand_locations = nodes
spatial.methanol.industry = nodes + " industry methanol"
spatial.methanol.shipping = nodes + " shipping methanol"
@@ -779,14 +779,9 @@ def add_allam(n, costs):
def add_biomass_to_methanol(n, costs):
- if len(spatial.biomass.nodes) <= 1 and len(spatial.methanol.nodes) > 1:
- link_names = nodes + " " + spatial.biomass.nodes
- else:
- link_names = spatial.biomass.nodes
-
n.madd(
"Link",
- link_names,
+ spatial.biomass.nodes,
suffix=" biomass-to-methanol",
bus0=spatial.biomass.nodes,
bus1=spatial.methanol.nodes,
@@ -806,14 +801,9 @@ def add_biomass_to_methanol(n, costs):
def add_biomass_to_methanol_cc(n, costs):
- if len(spatial.biomass.nodes) <= 1 and len(spatial.methanol.nodes) > 1:
- link_names = nodes + " " + spatial.biomass.nodes
- else:
- link_names = spatial.biomass.nodes
-
n.madd(
"Link",
- link_names,
+ spatial.biomass.nodes,
suffix=" biomass-to-methanol CC",
bus0=spatial.biomass.nodes,
bus1=spatial.methanol.nodes,
@@ -869,7 +859,7 @@ def add_methanol_to_power(n, costs, types={}):
logger.info("Adding methanol CCGT power plants.")
# efficiency * EUR/MW * (annuity + FOM)
- capital_cost = 0.58 * 916e3 * (calculate_annuity(25, 0.07) + 0.035)
+ capital_cost = costs.at["CCGT", "efficiency"] * costs.at["CCGT", "fixed"]
n.madd(
"Link",
@@ -882,9 +872,9 @@ def add_methanol_to_power(n, costs, types={}):
p_nom_extendable=True,
capital_cost=capital_cost,
marginal_cost=2,
- efficiency=0.58,
+ efficiency=costs.at["CCGT", "efficiency"],
efficiency2=costs.at["methanolisation", "carbondioxide-input"],
- lifetime=25,
+ lifetime=costs.at["CCGT", "lifetime"],
)
if types["ccgt_cc"]:
@@ -895,7 +885,7 @@ def add_methanol_to_power(n, costs, types={}):
# TODO consider efficiency changes / energy inputs for CC
# efficiency * EUR/MW * (annuity + FOM)
- capital_cost = 0.58 * 916e3 * (calculate_annuity(25, 0.07) + 0.035)
+ capital_cost = costs.at["CCGT", "efficiency"] * costs.at["CCGT", "fixed"]
capital_cost_cc = (
capital_cost
@@ -915,12 +905,12 @@ def add_methanol_to_power(n, costs, types={}):
p_nom_extendable=True,
capital_cost=capital_cost_cc,
marginal_cost=2,
- efficiency=0.58,
+ efficiency=costs.at["CCGT", "efficiency"],
efficiency2=costs.at["cement capture", "capture_rate"]
* costs.at["methanolisation", "carbondioxide-input"],
efficiency3=(1 - costs.at["cement capture", "capture_rate"])
* costs.at["methanolisation", "carbondioxide-input"],
- lifetime=25,
+ lifetime=costs.at["CCGT", "lifetime"],
)
if types["ocgt"]:
@@ -935,15 +925,11 @@ def add_methanol_to_power(n, costs, types={}):
bus2="co2 atmosphere",
carrier="OCGT methanol",
p_nom_extendable=True,
- capital_cost=0.35
- * 458e3
- * (
- calculate_annuity(25, 0.07) + 0.035
- ), # efficiency * EUR/MW * (annuity + FOM)
+ capital_cost=costs.at["OCGT", "fixed"] * costs.at["OCGT", "efficiency"],
marginal_cost=2,
- efficiency=0.35,
+ efficiency=costs.at["OCGT", "efficiency"],
efficiency2=costs.at["methanolisation", "carbondioxide-input"],
- lifetime=25,
+ lifetime=costs.at["OCGT", "lifetime"],
)
@@ -978,7 +964,7 @@ def add_methanol_to_olefins(n, costs):
n.madd(
"Link",
- spatial.methanol.locations,
+ nodes,
suffix=f" {tech}",
carrier=tech,
capital_cost=costs.at[tech, "fixed"] / costs.at[tech, "methanol-input"],
@@ -1000,7 +986,6 @@ def add_methanol_to_olefins(n, costs):
def add_methanol_to_kerosene(n, costs):
nodes = pop_layout.index
nhours = n.snapshot_weightings.generators.sum()
- nyears = nhours / 8760
demand_factor = options["aviation_demand_factor"]
@@ -1022,7 +1007,7 @@ def add_methanol_to_kerosene(n, costs):
n.madd(
"Link",
- spatial.methanol.locations,
+ spatial.h2.locations,
suffix=f" {tech}",
carrier=tech,
capital_cost=capital_cost,
@@ -1041,15 +1026,13 @@ def add_methanol_to_kerosene(n, costs):
def add_methanol_reforming(n, costs):
logger.info("Adding methanol steam reforming.")
- nodes = pop_layout.index
-
tech = "Methanol steam reforming"
capital_cost = costs.at[tech, "fixed"] / costs.at[tech, "methanol-input"]
n.madd(
"Link",
- spatial.methanol.locations,
+ spatial.h2.locations,
suffix=f" {tech}",
bus0=spatial.methanol.nodes,
bus1=spatial.h2.nodes,
@@ -1066,8 +1049,6 @@ def add_methanol_reforming(n, costs):
def add_methanol_reforming_cc(n, costs):
logger.info("Adding methanol steam reforming with carbon capture.")
- nodes = pop_layout.index
-
tech = "Methanol steam reforming"
# TODO: heat release and electricity demand for process and carbon capture
@@ -1084,7 +1065,7 @@ def add_methanol_reforming_cc(n, costs):
n.madd(
"Link",
- nodes,
+ spatial.h2.locations,
suffix=f" {tech} CC",
bus0=spatial.methanol.nodes,
bus1=spatial.h2.nodes,
@@ -2579,43 +2560,28 @@ def add_heat(n: pypsa.Network, costs: pd.DataFrame, cop: xr.DataArray):
def add_methanol(n, costs):
- logger.info("Add methanol")
- n.add("Carrier", "methanol")
-
- n.madd(
- "Bus",
- spatial.methanol.nodes,
- location=spatial.methanol.locations,
- carrier="methanol",
- unit="MWh_LHV",
- )
+ methanol_options = options["methanol"]
+ if not any(methanol_options.values()):
+ return
- n.madd(
- "Store",
- spatial.methanol.nodes,
- suffix=" Store",
- bus=spatial.methanol.nodes,
- e_nom_extendable=True,
- e_cyclic=True,
- carrier="methanol",
- capital_cost=0.02,
- )
+ logger.info("Add methanol")
+ add_carrier_buses(n, "methanol")
if n.buses.carrier.str.contains("biomass").any():
- if options["biomass_to_methanol"]:
+ if methanol_options["biomass_to_methanol"]:
add_biomass_to_methanol(n, costs)
- if options["biomass_to_methanol"]:
+ if methanol_options["biomass_to_methanol"]:
add_biomass_to_methanol_cc(n, costs)
- if options["methanol_to_power"]:
- add_methanol_to_power(n, costs, types=options["methanol_to_power"])
+ if methanol_options["methanol_to_power"]:
+ add_methanol_to_power(n, costs, types=methanol_options["methanol_to_power"])
- if options["methanol_reforming"]:
+ if methanol_options["methanol_reforming"]:
add_methanol_reforming(n, costs)
- if options["methanol_reforming_cc"]:
+ if methanol_options["methanol_reforming_cc"]:
add_methanol_reforming_cc(n, costs)
@@ -3398,7 +3364,7 @@ def add_industry(n, costs):
/ nhours
)
- if not options["regional_methanol_demand"]:
+ if not options["methanol"]["regional_methanol_demand"]:
p_set_methanol = p_set_methanol.sum()
n.madd(
@@ -3521,7 +3487,7 @@ def add_industry(n, costs):
* efficiency
)
- if not options["regional_methanol_demand"]:
+ if not options["methanol"]["regional_methanol_demand"]:
p_set_methanol_shipping = p_set_methanol_shipping.sum()
n.madd(
@@ -3819,7 +3785,7 @@ def add_industry(n, costs):
efficiency3=process_co2_per_naphtha,
)
- if options["methanol_to_olefins"]:
+ if options["methanol"]["methanol_to_olefins"]:
add_methanol_to_olefins(n, costs)
# aviation
@@ -3866,7 +3832,7 @@ def add_industry(n, costs):
efficiency2=costs.at["oil", "CO2 intensity"],
)
- if options["methanol_to_kerosene"]:
+ if options["methanol"]["methanol_to_kerosene"]:
add_methanol_to_kerosene(n, costs)
# TODO simplify bus expression
From cae63a3578de797406370c5d6eb73e85f0f75b1b Mon Sep 17 00:00:00 2001
From: Philipp Glaum
Date: Fri, 30 Aug 2024 16:47:46 +0200
Subject: [PATCH 12/14] prepare_sector_network: get tech data for allam cycle
from data base
---
config/config.default.yaml | 2 +-
scripts/prepare_sector_network.py | 20 +++++++++-----------
2 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/config/config.default.yaml b/config/config.default.yaml
index 42b069d6b..4060729d4 100644
--- a/config/config.default.yaml
+++ b/config/config.default.yaml
@@ -815,7 +815,7 @@ industry:
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#costs
costs:
year: 2030
- version: v0.9.1
+ version: v0.9.2
social_discountrate: 0.02
fill_values:
FOM: 0
diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py
index 5f3936457..2bb63e893 100644
--- a/scripts/prepare_sector_network.py
+++ b/scripts/prepare_sector_network.py
@@ -786,11 +786,11 @@ def add_allam(n, costs):
carrier="allam",
p_nom_extendable=True,
# TODO: add costs to technology-data
- capital_cost=0.6 * 1.5e6 * 0.1, # efficiency * EUR/MW * annuity
- marginal_cost=2,
- efficiency=0.6,
+ capital_cost=costs.at["allam", "fixed"] * costs.at["allam", "efficiency"],
+ marginal_cost=costs.at["allam", "VOM"] * costs.at["allam", "efficiency"],
+ efficiency=costs.at["allam", "efficiency"],
efficiency2=costs.at["gas", "CO2 intensity"],
- lifetime=30.0,
+ lifetime=costs.at["allam", "lifetime"],
)
@@ -862,11 +862,9 @@ def add_methanol_to_power(n, costs, types={}):
bus3="co2 atmosphere",
carrier="allam methanol",
p_nom_extendable=True,
- capital_cost=0.59
- * 1.832e6
- * calculate_annuity(25, 0.07), # efficiency * EUR/MW * annuity
- marginal_cost=2,
- efficiency=0.59,
+ capital_cost=costs.at["allam", "fixed"] * costs.at["allam", "efficiency"],
+ marginal_cost=costs.at["allam", "VOM"] * costs.at["allam", "efficiency"],
+ efficiency=costs.at["allam", "efficiency"],
efficiency2=0.98 * costs.at["methanolisation", "carbondioxide-input"],
efficiency3=0.02 * costs.at["methanolisation", "carbondioxide-input"],
lifetime=25,
@@ -921,7 +919,7 @@ def add_methanol_to_power(n, costs, types={}):
carrier="CCGT methanol CC",
p_nom_extendable=True,
capital_cost=capital_cost_cc,
- marginal_cost=2,
+ marginal_cost=costs.at["CCGT", "VOM"] * costs.at["CCGT", "VOM"],
efficiency=costs.at["CCGT", "efficiency"],
efficiency2=costs.at["cement capture", "capture_rate"]
* costs.at["methanolisation", "carbondioxide-input"],
@@ -943,7 +941,7 @@ def add_methanol_to_power(n, costs, types={}):
carrier="OCGT methanol",
p_nom_extendable=True,
capital_cost=costs.at["OCGT", "fixed"] * costs.at["OCGT", "efficiency"],
- marginal_cost=2,
+ marginal_cost=costs.at["OCGT", "VOM"] * costs.at["OCGT", "efficiency"],
efficiency=costs.at["OCGT", "efficiency"],
efficiency2=costs.at["methanolisation", "carbondioxide-input"],
lifetime=costs.at["OCGT", "lifetime"],
From 51c5e39e2d51dafd25c51072e09d4fa47ce6c8c1 Mon Sep 17 00:00:00 2001
From: Philipp Glaum
Date: Fri, 30 Aug 2024 16:54:55 +0200
Subject: [PATCH 13/14] cleanup
---
scripts/prepare_sector_network.py | 20 --------------------
1 file changed, 20 deletions(-)
diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py
index 2bb63e893..e1c6fd7c6 100644
--- a/scripts/prepare_sector_network.py
+++ b/scripts/prepare_sector_network.py
@@ -3356,26 +3356,6 @@ def add_industry(n, costs):
)
# methanol for industry
- # add methanol nodes if not already added
- if "methanol" not in n.buses.carrier.unique():
- n.madd(
- "Bus",
- spatial.methanol.nodes,
- carrier="methanol",
- location=spatial.methanol.locations,
- unit="MWh_LHV",
- )
-
- n.madd(
- "Store",
- spatial.methanol.nodes,
- suffix=" Store",
- bus=spatial.methanol.nodes,
- e_nom_extendable=True,
- e_cyclic=True,
- carrier="methanol",
- capital_cost=0.02,
- )
n.madd(
"Bus",
From 6cb68b191a738e45e6ff05640ea6704d6409e291 Mon Sep 17 00:00:00 2001
From: Philipp Glaum
Date: Wed, 11 Sep 2024 09:32:42 +0200
Subject: [PATCH 14/14] address Lisa's comments
---
scripts/prepare_sector_network.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py
index e310c8b19..452fbf1b3 100755
--- a/scripts/prepare_sector_network.py
+++ b/scripts/prepare_sector_network.py
@@ -919,7 +919,7 @@ def add_methanol_to_power(n, costs, types={}):
carrier="CCGT methanol",
p_nom_extendable=True,
capital_cost=capital_cost,
- marginal_cost=2,
+ marginal_cost=costs.at["CCGT", "VOM"],
efficiency=costs.at["CCGT", "efficiency"],
efficiency2=costs.at["methanolisation", "carbondioxide-input"],
lifetime=costs.at["CCGT", "lifetime"],
@@ -952,7 +952,7 @@ def add_methanol_to_power(n, costs, types={}):
carrier="CCGT methanol CC",
p_nom_extendable=True,
capital_cost=capital_cost_cc,
- marginal_cost=costs.at["CCGT", "VOM"] * costs.at["CCGT", "VOM"],
+ marginal_cost=costs.at["CCGT", "VOM"],
efficiency=costs.at["CCGT", "efficiency"],
efficiency2=costs.at["cement capture", "capture_rate"]
* costs.at["methanolisation", "carbondioxide-input"],
@@ -982,7 +982,7 @@ def add_methanol_to_power(n, costs, types={}):
def add_methanol_to_olefins(n, costs):
- nodes = pop_layout.index
+ nodes = spatial.nodes
nhours = n.snapshot_weightings.generators.sum()
nyears = nhours / 8760
@@ -2617,7 +2617,7 @@ def add_methanol(n, costs):
logger.info("Add methanol")
add_carrier_buses(n, "methanol")
- if n.buses.carrier.str.contains("biomass").any():
+ if options["biomass"]:
if methanol_options["biomass_to_methanol"]:
add_biomass_to_methanol(n, costs)