From ac0d52e1c3542fd6d4fa0ebd639905bac0578a12 Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Fri, 1 Mar 2024 18:08:28 +0100 Subject: [PATCH 01/10] Allow some plastics sequestered in landfill or built environment I.e. assume some fraction of plastics don't end up being burned or decaying into air. --- config/config.default.yaml | 1 + scripts/prepare_sector_network.py | 13 +++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 42fe5e2a..d4a8d21d 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -667,6 +667,7 @@ industry: 2040: 0.12 2045: 0.16 2050: 0.20 + HVC_environment_sequestration_fraction: 0. sector_ratios_fraction_future: 2020: 0.0 2025: 0.1 diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 432d9a82..c308f786 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -2865,7 +2865,7 @@ def add_industry(n, costs): if demand_factor != 1: logger.warning(f"Changing HVC demand by {demand_factor*100-100:+.2f}%.") - p_set_plastics = ( + p_set_naphtha = ( demand_factor * industrial_demand.loc[nodes, "naphtha"].rename( lambda x: x + " naphtha for industry" @@ -2874,7 +2874,7 @@ def add_industry(n, costs): ) if not options["regional_oil_demand"]: - p_set_plastics = p_set_plastics.sum() + p_set_naphtha = p_set_naphtha.sum() n.madd( "Bus", @@ -2889,7 +2889,7 @@ def add_industry(n, costs): spatial.oil.naphtha, bus=spatial.oil.naphtha, carrier="naphtha for industry", - p_set=p_set_plastics, + p_set=p_set_naphtha, ) # some CO2 from naphtha are process emissions from steam cracker @@ -2900,6 +2900,11 @@ def add_industry(n, costs): ) emitted_co2_per_naphtha = costs.at["oil", "CO2 intensity"] - process_co2_per_naphtha + non_sequestered = 1 - get( + snakemake.config["industry"]["HVC_environment_sequestration_fraction"], investment_year + ) + + n.madd( "Link", spatial.oil.naphtha, @@ -2909,7 +2914,7 @@ def add_industry(n, costs): bus3=spatial.co2.process_emissions, carrier="naphtha for industry", p_nom_extendable=True, - efficiency2=emitted_co2_per_naphtha, + efficiency2=emitted_co2_per_naphtha*non_sequestered, efficiency3=process_co2_per_naphtha, ) From f7dc8a7f22e3ec7f7a934acc093590504ac00591 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 1 Mar 2024 17:10:49 +0000 Subject: [PATCH 02/10] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/prepare_sector_network.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index c308f786..f88ab94a 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -2901,10 +2901,10 @@ def add_industry(n, costs): emitted_co2_per_naphtha = costs.at["oil", "CO2 intensity"] - process_co2_per_naphtha non_sequestered = 1 - get( - snakemake.config["industry"]["HVC_environment_sequestration_fraction"], investment_year + snakemake.config["industry"]["HVC_environment_sequestration_fraction"], + investment_year, ) - n.madd( "Link", spatial.oil.naphtha, @@ -2914,7 +2914,7 @@ def add_industry(n, costs): bus3=spatial.co2.process_emissions, carrier="naphtha for industry", p_nom_extendable=True, - efficiency2=emitted_co2_per_naphtha*non_sequestered, + efficiency2=emitted_co2_per_naphtha * non_sequestered, efficiency3=process_co2_per_naphtha, ) From 2055fe68efaaa73b560bd2059db36c48ede40179 Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Fri, 1 Mar 2024 18:39:15 +0100 Subject: [PATCH 03/10] add extra bus for HVC, which can either go to air or waste CHP Here we explicitly add the option to generate energy and/or capture the CO2 from HVC (i.e. plastics). NB: Since waste CHP is expensive, it's not built. --- config/config.default.yaml | 4 ++ scripts/prepare_sector_network.py | 96 +++++++++++++++++++++++++++---- 2 files changed, 88 insertions(+), 12 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index d4a8d21d..05ffb75c 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -668,6 +668,7 @@ industry: 2045: 0.16 2050: 0.20 HVC_environment_sequestration_fraction: 0. + waste_to_energy: false sector_ratios_fraction_future: 2020: 0.0 2025: 0.1 @@ -1152,3 +1153,6 @@ plotting: DC-DC: "#8a1caf" DC link: "#8a1caf" load: "#dd2e23" + waste CHP: '#e3d37d' + waste CHP CC: '#e3d3ff' + HVC to air: 'k' diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index f88ab94a..54057b71 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -2905,18 +2905,90 @@ def add_industry(n, costs): investment_year, ) - n.madd( - "Link", - spatial.oil.naphtha, - bus0=spatial.oil.nodes, - bus1=spatial.oil.naphtha, - bus2="co2 atmosphere", - bus3=spatial.co2.process_emissions, - carrier="naphtha for industry", - p_nom_extendable=True, - efficiency2=emitted_co2_per_naphtha * non_sequestered, - efficiency3=process_co2_per_naphtha, - ) + if snakemake.config["industry"]["waste_to_energy"] and options["regional_oil_demand"]: + + n.madd( + "Bus", + spatial.oil.demand_locations + " non-sequestered HVC", + location=spatial.oil.demand_locations, + carrier="non-sequestered HVC", + unit="MWh_LHV", + ) + + n.madd( + "Link", + spatial.oil.naphtha, + bus0=spatial.oil.nodes, + bus1=spatial.oil.naphtha, + bus2=spatial.oil.demand_locations + " non-sequestered HVC", + bus3=spatial.co2.process_emissions, + carrier="naphtha for industry", + p_nom_extendable=True, + efficiency2=non_sequestered*emitted_co2_per_naphtha/costs.at["oil", "CO2 intensity"], + efficiency3=process_co2_per_naphtha, + ) + + n.madd( + "Link", + spatial.oil.demand_locations + " HVC to air", + bus0=spatial.oil.demand_locations + " non-sequestered HVC", + bus1="co2 atmosphere", + carrier="HVC to air", + p_nom_extendable=True, + efficiency=costs.at["oil", "CO2 intensity"], + ) + + #TODO add heat + n.madd( + "Link", + spatial.oil.demand_locations + " waste CHP", + bus0=spatial.oil.demand_locations + " non-sequestered HVC", + bus1=spatial.oil.demand_locations, + bus2="co2 atmosphere", + carrier="waste CHP", + p_nom_extendable=True, + # p_nom=biomass_potential['municipal solid waste'] / 8760, + capital_cost=costs.at['waste CHP', 'fixed'] * costs.at['waste CHP', 'efficiency'], + marginal_cost=costs.at['waste CHP', 'VOM'], + efficiency=costs.at['waste CHP', 'efficiency'], + #efficiency4=costs.at['waste CHP', 'efficiency-heat'], + efficiency2=costs.at['oil', 'CO2 intensity'], + lifetime=costs.at['waste CHP', 'lifetime']) + + #TODO add heat + n.madd( + "Link", + spatial.oil.demand_locations + " waste CHP CC", + bus0=spatial.oil.demand_locations + " non-sequestered HVC", + bus1=spatial.oil.demand_locations, + bus2="co2 atmosphere", + bus3=spatial.co2.nodes, + carrier="waste CHP CC", + p_nom_extendable=True, + # p_nom=biomass_potential['municipal solid waste'] / 8760, + capital_cost=costs.at['waste CHP CC', 'fixed'] * costs.at['waste CHP CC', 'efficiency'], + marginal_cost=costs.at['waste CHP CC', 'VOM'], + efficiency=costs.at['waste CHP CC', 'efficiency'], + #efficiency4=costs.at['waste CHP', 'efficiency-heat'], + efficiency2=costs.at['oil', 'CO2 intensity']*(1 - options["cc_fraction"]), + efficiency3=costs.at['oil', 'CO2 intensity']*options["cc_fraction"], + lifetime=costs.at['waste CHP CC', 'lifetime']) + + + else: + + n.madd( + "Link", + spatial.oil.naphtha, + bus0=spatial.oil.nodes, + bus1=spatial.oil.naphtha, + bus2="co2 atmosphere", + bus3=spatial.co2.process_emissions, + carrier="naphtha for industry", + p_nom_extendable=True, + efficiency2=emitted_co2_per_naphtha*non_sequestered, + efficiency3=process_co2_per_naphtha, + ) # aviation demand_factor = options.get("aviation_demand_factor", 1) From 1d709913edd92fdb2569e9a5e1c0f69c9e29ac4a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 1 Mar 2024 17:42:20 +0000 Subject: [PATCH 04/10] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/prepare_sector_network.py | 48 ++++++++++++++++++------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 54057b71..a0a988a9 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -2905,7 +2905,10 @@ def add_industry(n, costs): investment_year, ) - if snakemake.config["industry"]["waste_to_energy"] and options["regional_oil_demand"]: + if ( + snakemake.config["industry"]["waste_to_energy"] + and options["regional_oil_demand"] + ): n.madd( "Bus", @@ -2913,7 +2916,7 @@ def add_industry(n, costs): location=spatial.oil.demand_locations, carrier="non-sequestered HVC", unit="MWh_LHV", - ) + ) n.madd( "Link", @@ -2924,7 +2927,9 @@ def add_industry(n, costs): bus3=spatial.co2.process_emissions, carrier="naphtha for industry", p_nom_extendable=True, - efficiency2=non_sequestered*emitted_co2_per_naphtha/costs.at["oil", "CO2 intensity"], + efficiency2=non_sequestered + * emitted_co2_per_naphtha + / costs.at["oil", "CO2 intensity"], efficiency3=process_co2_per_naphtha, ) @@ -2938,7 +2943,7 @@ def add_industry(n, costs): efficiency=costs.at["oil", "CO2 intensity"], ) - #TODO add heat + # TODO add heat n.madd( "Link", spatial.oil.demand_locations + " waste CHP", @@ -2948,14 +2953,16 @@ def add_industry(n, costs): carrier="waste CHP", p_nom_extendable=True, # p_nom=biomass_potential['municipal solid waste'] / 8760, - capital_cost=costs.at['waste CHP', 'fixed'] * costs.at['waste CHP', 'efficiency'], - marginal_cost=costs.at['waste CHP', 'VOM'], - efficiency=costs.at['waste CHP', 'efficiency'], - #efficiency4=costs.at['waste CHP', 'efficiency-heat'], - efficiency2=costs.at['oil', 'CO2 intensity'], - lifetime=costs.at['waste CHP', 'lifetime']) + capital_cost=costs.at["waste CHP", "fixed"] + * costs.at["waste CHP", "efficiency"], + marginal_cost=costs.at["waste CHP", "VOM"], + efficiency=costs.at["waste CHP", "efficiency"], + # efficiency4=costs.at['waste CHP', 'efficiency-heat'], + efficiency2=costs.at["oil", "CO2 intensity"], + lifetime=costs.at["waste CHP", "lifetime"], + ) - #TODO add heat + # TODO add heat n.madd( "Link", spatial.oil.demand_locations + " waste CHP CC", @@ -2966,14 +2973,15 @@ def add_industry(n, costs): carrier="waste CHP CC", p_nom_extendable=True, # p_nom=biomass_potential['municipal solid waste'] / 8760, - capital_cost=costs.at['waste CHP CC', 'fixed'] * costs.at['waste CHP CC', 'efficiency'], - marginal_cost=costs.at['waste CHP CC', 'VOM'], - efficiency=costs.at['waste CHP CC', 'efficiency'], - #efficiency4=costs.at['waste CHP', 'efficiency-heat'], - efficiency2=costs.at['oil', 'CO2 intensity']*(1 - options["cc_fraction"]), - efficiency3=costs.at['oil', 'CO2 intensity']*options["cc_fraction"], - lifetime=costs.at['waste CHP CC', 'lifetime']) - + capital_cost=costs.at["waste CHP CC", "fixed"] + * costs.at["waste CHP CC", "efficiency"], + marginal_cost=costs.at["waste CHP CC", "VOM"], + efficiency=costs.at["waste CHP CC", "efficiency"], + # efficiency4=costs.at['waste CHP', 'efficiency-heat'], + efficiency2=costs.at["oil", "CO2 intensity"] * (1 - options["cc_fraction"]), + efficiency3=costs.at["oil", "CO2 intensity"] * options["cc_fraction"], + lifetime=costs.at["waste CHP CC", "lifetime"], + ) else: @@ -2986,7 +2994,7 @@ def add_industry(n, costs): bus3=spatial.co2.process_emissions, carrier="naphtha for industry", p_nom_extendable=True, - efficiency2=emitted_co2_per_naphtha*non_sequestered, + efficiency2=emitted_co2_per_naphtha * non_sequestered, efficiency3=process_co2_per_naphtha, ) From afa5cc5014e04f22f7573f8141f839a772ad3d18 Mon Sep 17 00:00:00 2001 From: Michael Lindner Date: Wed, 6 Mar 2024 11:29:37 +0100 Subject: [PATCH 05/10] add heating output, correct bus ordering --- scripts/prepare_sector_network.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index a0a988a9..d2de7c71 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -2907,7 +2907,7 @@ def add_industry(n, costs): if ( snakemake.config["industry"]["waste_to_energy"] - and options["regional_oil_demand"] + and options["regional_oil_demand"] # Should warn if regional_oil_demand is not true!!? ): n.madd( @@ -2943,13 +2943,13 @@ def add_industry(n, costs): efficiency=costs.at["oil", "CO2 intensity"], ) - # TODO add heat n.madd( "Link", spatial.oil.demand_locations + " waste CHP", bus0=spatial.oil.demand_locations + " non-sequestered HVC", bus1=spatial.oil.demand_locations, - bus2="co2 atmosphere", + bus2=spatial.oil.demand_locations + "urban central heat", + bus3="co2 atmosphere", carrier="waste CHP", p_nom_extendable=True, # p_nom=biomass_potential['municipal solid waste'] / 8760, @@ -2957,19 +2957,19 @@ def add_industry(n, costs): * costs.at["waste CHP", "efficiency"], marginal_cost=costs.at["waste CHP", "VOM"], efficiency=costs.at["waste CHP", "efficiency"], - # efficiency4=costs.at['waste CHP', 'efficiency-heat'], - efficiency2=costs.at["oil", "CO2 intensity"], + efficiency2=costs.at['waste CHP', 'efficiency-heat'], + efficiency3=costs.at["oil", "CO2 intensity"], lifetime=costs.at["waste CHP", "lifetime"], ) - # TODO add heat n.madd( "Link", spatial.oil.demand_locations + " waste CHP CC", bus0=spatial.oil.demand_locations + " non-sequestered HVC", bus1=spatial.oil.demand_locations, - bus2="co2 atmosphere", - bus3=spatial.co2.nodes, + bus2=spatial.oil.demand_locations + "urban central heat", + bus3="co2 atmosphere", + bus4=spatial.co2.nodes, carrier="waste CHP CC", p_nom_extendable=True, # p_nom=biomass_potential['municipal solid waste'] / 8760, @@ -2977,9 +2977,9 @@ def add_industry(n, costs): * costs.at["waste CHP CC", "efficiency"], marginal_cost=costs.at["waste CHP CC", "VOM"], efficiency=costs.at["waste CHP CC", "efficiency"], - # efficiency4=costs.at['waste CHP', 'efficiency-heat'], - efficiency2=costs.at["oil", "CO2 intensity"] * (1 - options["cc_fraction"]), - efficiency3=costs.at["oil", "CO2 intensity"] * options["cc_fraction"], + efficiency2=costs.at["waste CHP CC", 'efficiency-heat'], + efficiency3=costs.at["oil", "CO2 intensity"] * (1 - options["cc_fraction"]), + efficiency4=costs.at["oil", "CO2 intensity"] * options["cc_fraction"], lifetime=costs.at["waste CHP CC", "lifetime"], ) From a9d0f295fb5aebe44e86522f2c0c20a133796049 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 13:41:39 +0000 Subject: [PATCH 06/10] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/make_summary.py | 49 ++++++++++++++++++------------- scripts/prepare_sector_network.py | 8 +++-- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/scripts/make_summary.py b/scripts/make_summary.py index dc1aaac1..5746697b 100644 --- a/scripts/make_summary.py +++ b/scripts/make_summary.py @@ -415,8 +415,8 @@ def calculate_supply_energy(n, label, supply_energy): def calculate_nodal_supply_energy(n, label, nodal_supply_energy): """ - Calculate the total energy supply/consumption of each component at the buses - aggregated by carrier and node. + Calculate the total energy supply/consumption of each component at the + buses aggregated by carrier and node. """ bus_carriers = n.buses.carrier.unique() @@ -432,22 +432,27 @@ def calculate_nodal_supply_energy(n, label, nodal_supply_energy): continue s = ( - pd.concat([ - ( - c.pnl.p[items] - .multiply(n.snapshot_weightings.generators, axis=0) - .sum() - .multiply(c.df.loc[items, "sign"]) - ), - c.df.loc[items][["bus", "carrier"]] - ], axis=1) + pd.concat( + [ + ( + c.pnl.p[items] + .multiply(n.snapshot_weightings.generators, axis=0) + .sum() + .multiply(c.df.loc[items, "sign"]) + ), + c.df.loc[items][["bus", "carrier"]], + ], + axis=1, + ) .groupby(by=["bus", "carrier"]) .sum()[0] ) s = pd.concat([s], keys=[c.list_name]) s = pd.concat([s], keys=[i]) - nodal_supply_energy = nodal_supply_energy.reindex(s.index.union(nodal_supply_energy.index)) + nodal_supply_energy = nodal_supply_energy.reindex( + s.index.union(nodal_supply_energy.index) + ) nodal_supply_energy.loc[s.index, label] = s for c in n.iterate_components(n.branch_components): @@ -458,14 +463,18 @@ def calculate_nodal_supply_energy(n, label, nodal_supply_energy): continue s = ( - pd.concat([ - ( - (-1) * c.pnl["p" + end][items] - .multiply(n.snapshot_weightings.generators, axis=0) - .sum() - ), - c.df.loc[items][["bus0", "carrier"]] - ], axis=1) + pd.concat( + [ + ( + (-1) + * c.pnl["p" + end][items] + .multiply(n.snapshot_weightings.generators, axis=0) + .sum() + ), + c.df.loc[items][["bus0", "carrier"]], + ], + axis=1, + ) .groupby(by=["bus0", "carrier"]) .sum()[0] ) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index d2de7c71..c210c6da 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -2907,7 +2907,9 @@ def add_industry(n, costs): if ( snakemake.config["industry"]["waste_to_energy"] - and options["regional_oil_demand"] # Should warn if regional_oil_demand is not true!!? + and options[ + "regional_oil_demand" + ] # Should warn if regional_oil_demand is not true!!? ): n.madd( @@ -2957,7 +2959,7 @@ def add_industry(n, costs): * costs.at["waste CHP", "efficiency"], marginal_cost=costs.at["waste CHP", "VOM"], efficiency=costs.at["waste CHP", "efficiency"], - efficiency2=costs.at['waste CHP', 'efficiency-heat'], + efficiency2=costs.at["waste CHP", "efficiency-heat"], efficiency3=costs.at["oil", "CO2 intensity"], lifetime=costs.at["waste CHP", "lifetime"], ) @@ -2977,7 +2979,7 @@ def add_industry(n, costs): * costs.at["waste CHP CC", "efficiency"], marginal_cost=costs.at["waste CHP CC", "VOM"], efficiency=costs.at["waste CHP CC", "efficiency"], - efficiency2=costs.at["waste CHP CC", 'efficiency-heat'], + efficiency2=costs.at["waste CHP CC", "efficiency-heat"], efficiency3=costs.at["oil", "CO2 intensity"] * (1 - options["cc_fraction"]), efficiency4=costs.at["oil", "CO2 intensity"] * options["cc_fraction"], lifetime=costs.at["waste CHP CC", "lifetime"], From 649e277c7d8fd90e89e81be0957598de0909ca64 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 13 May 2024 17:13:16 +0200 Subject: [PATCH 07/10] make waste-to-energy work without regional_oil_demand --- config/config.default.yaml | 1 + scripts/prepare_sector_network.py | 100 +++++++++++++++--------------- 2 files changed, 51 insertions(+), 50 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 05ffb75c..8b7ee474 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -669,6 +669,7 @@ industry: 2050: 0.20 HVC_environment_sequestration_fraction: 0. waste_to_energy: false + waste_to_energy_cc: false sector_ratios_fraction_future: 2020: 0.0 2025: 0.1 diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index d2de7c71..86c79026 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -906,8 +906,6 @@ def add_ammonia(n, costs): nodes = pop_layout.index - cf_industry = snakemake.params.industry - n.add("Carrier", "NH3") n.madd( @@ -2901,18 +2899,17 @@ def add_industry(n, costs): emitted_co2_per_naphtha = costs.at["oil", "CO2 intensity"] - process_co2_per_naphtha non_sequestered = 1 - get( - snakemake.config["industry"]["HVC_environment_sequestration_fraction"], + cf_industry["HVC_environment_sequestration_fraction"], investment_year, ) - if ( - snakemake.config["industry"]["waste_to_energy"] - and options["regional_oil_demand"] # Should warn if regional_oil_demand is not true!!? - ): + if cf_industry["waste_to_energy"] or cf_industry["waste_to_energy_cc"]: + + non_sequestered_hvc_locations = pd.Index(spatial.oil.demand_locations) + " non-sequestered HVC" n.madd( "Bus", - spatial.oil.demand_locations + " non-sequestered HVC", + non_sequestered_hvc_locations, location=spatial.oil.demand_locations, carrier="non-sequestered HVC", unit="MWh_LHV", @@ -2923,7 +2920,7 @@ def add_industry(n, costs): spatial.oil.naphtha, bus0=spatial.oil.nodes, bus1=spatial.oil.naphtha, - bus2=spatial.oil.demand_locations + " non-sequestered HVC", + bus2=non_sequestered_hvc_locations, bus3=spatial.co2.process_emissions, carrier="naphtha for industry", p_nom_extendable=True, @@ -2935,53 +2932,56 @@ def add_industry(n, costs): n.madd( "Link", - spatial.oil.demand_locations + " HVC to air", - bus0=spatial.oil.demand_locations + " non-sequestered HVC", + spatial.oil.demand_locations, + suffix=" HVC to air", + bus0=non_sequestered_hvc_locations, bus1="co2 atmosphere", carrier="HVC to air", p_nom_extendable=True, efficiency=costs.at["oil", "CO2 intensity"], ) - n.madd( - "Link", - spatial.oil.demand_locations + " waste CHP", - bus0=spatial.oil.demand_locations + " non-sequestered HVC", - bus1=spatial.oil.demand_locations, - bus2=spatial.oil.demand_locations + "urban central heat", - bus3="co2 atmosphere", - carrier="waste CHP", - p_nom_extendable=True, - # p_nom=biomass_potential['municipal solid waste'] / 8760, - capital_cost=costs.at["waste CHP", "fixed"] - * costs.at["waste CHP", "efficiency"], - marginal_cost=costs.at["waste CHP", "VOM"], - efficiency=costs.at["waste CHP", "efficiency"], - efficiency2=costs.at['waste CHP', 'efficiency-heat'], - efficiency3=costs.at["oil", "CO2 intensity"], - lifetime=costs.at["waste CHP", "lifetime"], - ) + if cf_industry["waste_to_energy"]: - n.madd( - "Link", - spatial.oil.demand_locations + " waste CHP CC", - bus0=spatial.oil.demand_locations + " non-sequestered HVC", - bus1=spatial.oil.demand_locations, - bus2=spatial.oil.demand_locations + "urban central heat", - bus3="co2 atmosphere", - bus4=spatial.co2.nodes, - carrier="waste CHP CC", - p_nom_extendable=True, - # p_nom=biomass_potential['municipal solid waste'] / 8760, - capital_cost=costs.at["waste CHP CC", "fixed"] - * costs.at["waste CHP CC", "efficiency"], - marginal_cost=costs.at["waste CHP CC", "VOM"], - efficiency=costs.at["waste CHP CC", "efficiency"], - efficiency2=costs.at["waste CHP CC", 'efficiency-heat'], - efficiency3=costs.at["oil", "CO2 intensity"] * (1 - options["cc_fraction"]), - efficiency4=costs.at["oil", "CO2 intensity"] * options["cc_fraction"], - lifetime=costs.at["waste CHP CC", "lifetime"], - ) + n.madd( + "Link", + spatial.nodes + " waste CHP", + bus0=non_sequestered_hvc_locations, + bus1=spatial.nodes, + bus2=spatial.nodes + " urban central heat", + bus3="co2 atmosphere", + carrier="waste CHP", + p_nom_extendable=True, + capital_cost=costs.at["waste CHP", "fixed"] + * costs.at["waste CHP", "efficiency"], + marginal_cost=costs.at["waste CHP", "VOM"], + efficiency=costs.at["waste CHP", "efficiency"], + efficiency2=costs.at['waste CHP', 'efficiency-heat'], + efficiency3=costs.at["oil", "CO2 intensity"], + lifetime=costs.at["waste CHP", "lifetime"], + ) + + if cf_industry["waste_to_energy_cc"]: + + n.madd( + "Link", + spatial.nodes + " waste CHP CC", + bus0=non_sequestered_hvc_locations, + bus1=spatial.nodes, + bus2=spatial.nodes + " urban central heat", + bus3="co2 atmosphere", + bus4=spatial.co2.nodes, + carrier="waste CHP CC", + p_nom_extendable=True, + capital_cost=costs.at["waste CHP CC", "fixed"] + * costs.at["waste CHP CC", "efficiency"], + marginal_cost=costs.at["waste CHP CC", "VOM"], + efficiency=costs.at["waste CHP CC", "efficiency"], + efficiency2=costs.at["waste CHP CC", 'efficiency-heat'], + efficiency3=costs.at["oil", "CO2 intensity"] * (1 - options["cc_fraction"]), + efficiency4=costs.at["oil", "CO2 intensity"] * options["cc_fraction"], + lifetime=costs.at["waste CHP CC", "lifetime"], + ) else: @@ -3207,7 +3207,6 @@ def add_waste_heat(n): # TODO options? logger.info("Add possibility to use industrial waste heat in district heating") - cf_industry = snakemake.params.industry # AC buses with district heating urban_central = n.buses.index[n.buses.carrier == "urban central heat"] @@ -3672,6 +3671,7 @@ if __name__ == "__main__": update_config_from_wildcards(snakemake.config, snakemake.wildcards) options = snakemake.params.sector + cf_industry = snakemake.params.industry investment_year = int(snakemake.wildcards.planning_horizons[-4:]) From b529ab1d3c97ee5e30c753baa37ef83987c68e68 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 15:14:33 +0000 Subject: [PATCH 08/10] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- scripts/prepare_sector_network.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 86c79026..89d5cd7d 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -2905,7 +2905,9 @@ def add_industry(n, costs): if cf_industry["waste_to_energy"] or cf_industry["waste_to_energy_cc"]: - non_sequestered_hvc_locations = pd.Index(spatial.oil.demand_locations) + " non-sequestered HVC" + non_sequestered_hvc_locations = ( + pd.Index(spatial.oil.demand_locations) + " non-sequestered HVC" + ) n.madd( "Bus", @@ -2956,7 +2958,7 @@ def add_industry(n, costs): * costs.at["waste CHP", "efficiency"], marginal_cost=costs.at["waste CHP", "VOM"], efficiency=costs.at["waste CHP", "efficiency"], - efficiency2=costs.at['waste CHP', 'efficiency-heat'], + efficiency2=costs.at["waste CHP", "efficiency-heat"], efficiency3=costs.at["oil", "CO2 intensity"], lifetime=costs.at["waste CHP", "lifetime"], ) @@ -2977,8 +2979,9 @@ def add_industry(n, costs): * costs.at["waste CHP CC", "efficiency"], marginal_cost=costs.at["waste CHP CC", "VOM"], efficiency=costs.at["waste CHP CC", "efficiency"], - efficiency2=costs.at["waste CHP CC", 'efficiency-heat'], - efficiency3=costs.at["oil", "CO2 intensity"] * (1 - options["cc_fraction"]), + efficiency2=costs.at["waste CHP CC", "efficiency-heat"], + efficiency3=costs.at["oil", "CO2 intensity"] + * (1 - options["cc_fraction"]), efficiency4=costs.at["oil", "CO2 intensity"] * options["cc_fraction"], lifetime=costs.at["waste CHP CC", "lifetime"], ) From 49ca5a456437aabf5a6d62b28b21bf500a876223 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 13 May 2024 17:23:15 +0200 Subject: [PATCH 09/10] add release notes [no ci] --- doc/configtables/industry.csv | 3 +++ doc/release_notes.rst | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/doc/configtables/industry.csv b/doc/configtables/industry.csv index d1b560ed..cee06c97 100644 --- a/doc/configtables/industry.csv +++ b/doc/configtables/industry.csv @@ -16,6 +16,9 @@ petrochemical_process _emissions,MtCO2/a,float,The emission of petrochemical pro HVC_primary_fraction,--,float,The fraction of high value chemicals (HVC) produced via primary route HVC_mechanical_recycling _fraction,--,float,The fraction of high value chemicals (HVC) produced using mechanical recycling HVC_chemical_recycling _fraction,--,float,The fraction of high value chemicals (HVC) produced using chemical recycling +HVC_environment_sequestration_fraction,--,float,The fraction of high value chemicals (HVC) put into landfill resulting in additional carbon sequestration. The default value is 0. +waste_to_energy,--,bool,Switch to enable expansion of waste to energy CHPs for conversion of plastics. Default is false. +waste_to_energy_cc,--,bool,Switch to enable expansion of waste to energy CHPs for conversion of plastics with carbon capture. Default is false. ,,, sector_ratios_fraction_future,--,Dictionary with planning horizons as keys.,The fraction of total progress in fuel and process switching achieved in the industry sector. basic_chemicals_without_NH3_production_today,Mt/a,float,"The amount of basic chemicals produced without ammonia (= 86 Mtethylene-equiv - 17 MtNH3)." diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 2f21127b..c08d0bfe 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,6 +10,16 @@ Release Notes Upcoming Release ================ +* Added option ``industry: HVC_environment_sequestration_fraction:`` to specify + the fraction of carbon contained plastics that is permanently sequestered in + landfill. The default assumption is that all carbon contained in plastics is + eventually released to the atmosphere. + +* Added option for building waste-to-energy plants with and without carbon + capture to consume non-recycled and non-sequestered plastics. The config + settings are ``industry: waste_to_energy:`` and ``industry: + waste_to_energy_cc``. This does not include municipal solid waste. + * Bump minimum ``powerplantmatching`` version to v0.5.15. * Add floating wind technology for water depths below 60m From a9333458b316690d5c28da2e98e5972687e06dc0 Mon Sep 17 00:00:00 2001 From: Fabian Neumann Date: Mon, 13 May 2024 17:40:10 +0200 Subject: [PATCH 10/10] handle potentially diverging spatial resolutions of HVC --- config/test/config.overnight.yaml | 5 +++++ scripts/prepare_sector_network.py | 9 +++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/config/test/config.overnight.yaml b/config/test/config.overnight.yaml index 09342ae9..813211be 100644 --- a/config/test/config.overnight.yaml +++ b/config/test/config.overnight.yaml @@ -70,6 +70,11 @@ sector: gas_network: true H2_retrofit: true +industry: + HVC_environment_sequestration_fraction: 0.5 + waste_to_energy: true + waste_to_energy_cc: true + solving: solver: name: glpk diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 89d5cd7d..d35af1c9 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -2943,12 +2943,17 @@ def add_industry(n, costs): efficiency=costs.at["oil", "CO2 intensity"], ) + if len(non_sequestered_hvc_locations) == 1: + waste_source = non_sequestered_hvc_locations[0] + else: + waste_source = non_sequestered_hvc_locations + if cf_industry["waste_to_energy"]: n.madd( "Link", spatial.nodes + " waste CHP", - bus0=non_sequestered_hvc_locations, + bus0=waste_source, bus1=spatial.nodes, bus2=spatial.nodes + " urban central heat", bus3="co2 atmosphere", @@ -2968,7 +2973,7 @@ def add_industry(n, costs): n.madd( "Link", spatial.nodes + " waste CHP CC", - bus0=non_sequestered_hvc_locations, + bus0=waste_source, bus1=spatial.nodes, bus2=spatial.nodes + " urban central heat", bus3="co2 atmosphere",