add methanol techs for master to branch
This commit is contained in:
parent
98a9d2795f
commit
d142717563
@ -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
|
||||
|
@ -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"
|
||||
),
|
||||
|
@ -141,6 +141,13 @@ 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.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"]
|
||||
|
||||
@ -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,7 +3075,8 @@ 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,
|
||||
@ -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 @@ if __name__ == "__main__":
|
||||
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 @@ if __name__ == "__main__":
|
||||
if options["ammonia"]:
|
||||
add_ammonia(n, costs)
|
||||
|
||||
if options["methanol"]:
|
||||
add_methanol(n, costs)
|
||||
|
||||
if options["industry"]:
|
||||
add_industry(n, costs)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user