Skip to content

Commit

Permalink
Replace bioenergy and MSW stores with generators (#1373)
Browse files Browse the repository at this point in the history
* replace bioenergy stores with generators

* fix values to ensure feasibility

* represent other bioenergy and msw sources as generators

* fix spatial variable for biogas

* fix virtual msw transport bug

* make operational limit for msw work

* fix bioliquids potential resolution

* improve virtual msw transport

* add release note
  • Loading branch information
cpschau authored Nov 4, 2024
1 parent acf089f commit 52b8179
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 58 deletions.
2 changes: 2 additions & 0 deletions doc/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Upcoming Release
================
* Bugfix: Duplicates in build_transmission_projects were caught, but not removed from the network. This is now fixed.

* Replaced the Store representation of biogenic carriers (solid biomass, biogas, bioliquids, MSW) in ``prepare_sector_network`` with the extended Generator component that uses the ``e_sum_min`` and ``e_sum_max`` attributes to enforce minimum usage and limit maximum potential, respectively.

* Added option to reduce central heating forward temperatures by annual percentage (see rule :mod:`build_central_heating_temperature_profiles`). This makes COP profiles and heat pump efficiencies planning-horizon-dependent. Myopic and perfect foresight modes were adjusted accordingly to update COPs of existing heat pumps in preceding years to adjusted temperatures.

* Rearranged workflow to cluster the electricity network before calculating
Expand Down
104 changes: 46 additions & 58 deletions scripts/prepare_sector_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -2528,6 +2528,9 @@ def add_biomass(n, costs):
unsustainable_solid_biomass_potentials_spatial = biomass_potentials[
"unsustainable solid biomass"
].rename(index=lambda x: x + " unsustainable solid biomass")
unsustainable_liquid_biofuel_potentials_spatial = biomass_potentials[
"unsustainable bioliquids"
].rename(index=lambda x: x + " unsustainable bioliquids")

else:
solid_biomass_potentials_spatial = biomass_potentials["solid biomass"].sum()
Expand All @@ -2537,12 +2540,6 @@ def add_biomass(n, costs):
unsustainable_solid_biomass_potentials_spatial = biomass_potentials[
"unsustainable solid biomass"
].sum()

if options["regional_oil_demand"]:
unsustainable_liquid_biofuel_potentials_spatial = biomass_potentials[
"unsustainable bioliquids"
].rename(index=lambda x: x + " unsustainable bioliquids")
else:
unsustainable_liquid_biofuel_potentials_spatial = biomass_potentials[
"unsustainable bioliquids"
].sum()
Expand Down Expand Up @@ -2572,18 +2569,15 @@ def add_biomass(n, costs):
carrier="municipal solid waste",
)

e_max_pu = pd.DataFrame(1, index=n.snapshots, columns=spatial.msw.nodes)
e_max_pu.iloc[-1] = 0

n.add(
"Store",
"Generator",
spatial.msw.nodes,
bus=spatial.msw.nodes,
carrier="municipal solid waste",
e_nom=msw_biomass_potentials_spatial,
p_nom=msw_biomass_potentials_spatial,
marginal_cost=0, # costs.at["municipal solid waste", "fuel"],
e_max_pu=e_max_pu,
e_initial=msw_biomass_potentials_spatial,
e_sum_min=msw_biomass_potentials_spatial,
e_sum_max=msw_biomass_potentials_spatial,
)

n.add(
Expand All @@ -2603,23 +2597,25 @@ def add_biomass(n, costs):
)

n.add(
"Store",
"Generator",
spatial.gas.biogas,
bus=spatial.gas.biogas,
carrier="biogas",
e_nom=biogas_potentials_spatial,
p_nom=biogas_potentials_spatial,
marginal_cost=costs.at["biogas", "fuel"],
e_initial=biogas_potentials_spatial,
e_sum_min=0,
e_sum_max=biogas_potentials_spatial,
)

n.add(
"Store",
"Generator",
spatial.biomass.nodes,
bus=spatial.biomass.nodes,
carrier="solid biomass",
e_nom=solid_biomass_potentials_spatial,
p_nom=solid_biomass_potentials_spatial,
marginal_cost=costs.at["solid biomass", "fuel"],
e_initial=solid_biomass_potentials_spatial,
e_sum_min=0,
e_sum_max=solid_biomass_potentials_spatial,
)

if options["solid_biomass_import"].get("enable", False):
Expand Down Expand Up @@ -2671,38 +2667,29 @@ def add_biomass(n, costs):
)

if biomass_potentials.filter(like="unsustainable").sum().sum() > 0:
# Create timeseries to force usage of unsustainable potentials
e_max_pu = pd.DataFrame(1, index=n.snapshots, columns=spatial.gas.biogas)
e_max_pu.iloc[-1] = 0

n.add(
"Store",
"Generator",
spatial.gas.biogas,
suffix=" unsustainable",
bus=spatial.gas.biogas,
carrier="unsustainable biogas",
e_nom=unsustainable_biogas_potentials_spatial,
p_nom=unsustainable_biogas_potentials_spatial,
p_nom_extendable=False,
marginal_cost=costs.at["biogas", "fuel"],
e_initial=unsustainable_biogas_potentials_spatial,
e_nom_extendable=False,
e_max_pu=e_max_pu,
)

e_max_pu = pd.DataFrame(
1, index=n.snapshots, columns=spatial.biomass.nodes_unsustainable
e_sum_min=unsustainable_biogas_potentials_spatial,
e_sum_max=unsustainable_biogas_potentials_spatial,
)
e_max_pu.iloc[-1] = 0

n.add(
"Store",
"Generator",
spatial.biomass.nodes_unsustainable,
bus=spatial.biomass.nodes,
carrier="unsustainable solid biomass",
e_nom=unsustainable_solid_biomass_potentials_spatial,
p_nom=unsustainable_solid_biomass_potentials_spatial,
p_nom_extendable=False,
marginal_cost=costs.at["fuelwood", "fuel"],
e_initial=unsustainable_solid_biomass_potentials_spatial,
e_nom_extendable=False,
e_max_pu=e_max_pu,
e_sum_min=unsustainable_solid_biomass_potentials_spatial,
e_sum_max=unsustainable_solid_biomass_potentials_spatial,
)

n.add(
Expand All @@ -2713,21 +2700,16 @@ def add_biomass(n, costs):
unit="MWh_LHV",
)

e_max_pu = pd.DataFrame(
1, index=n.snapshots, columns=spatial.biomass.bioliquids
)
e_max_pu.iloc[-1] = 0

n.add(
"Store",
"Generator",
spatial.biomass.bioliquids,
bus=spatial.biomass.bioliquids,
carrier="unsustainable bioliquids",
e_nom=unsustainable_liquid_biofuel_potentials_spatial,
p_nom=unsustainable_liquid_biofuel_potentials_spatial,
p_nom_extendable=False,
marginal_cost=costs.at["biodiesel crops", "fuel"],
e_initial=unsustainable_liquid_biofuel_potentials_spatial,
e_nom_extendable=False,
e_max_pu=e_max_pu,
e_sum_min=unsustainable_liquid_biofuel_potentials_spatial,
e_sum_max=unsustainable_liquid_biofuel_potentials_spatial,
)

add_carrier_buses(n, "oil")
Expand Down Expand Up @@ -2848,6 +2830,7 @@ def add_biomass(n, costs):
n.add(
"Generator",
spatial.biomass.nodes,
suffix=" transported",
bus=spatial.biomass.nodes,
carrier="solid biomass",
p_nom=10000,
Expand All @@ -2866,6 +2849,7 @@ def add_biomass(n, costs):
n.add(
"Generator",
spatial.biomass.nodes_unsustainable,
suffix=" transported",
bus=spatial.biomass.nodes,
carrier="unsustainable solid biomass",
p_nom=10000,
Expand All @@ -2877,14 +2861,11 @@ def add_biomass(n, costs):
)
* average_distance,
)
# Set last snapshot of e_max_pu for unsustainable solid biomass to 1 to make operational limit work
unsus_stores_idx = n.stores.query(
"carrier == 'unsustainable solid biomass'"
).index
unsus_stores_idx = unsus_stores_idx.intersection(
n.stores_t.e_max_pu.columns
)
n.stores_t.e_max_pu.loc[n.snapshots[-1], unsus_stores_idx] = 1
# Set e_sum_min to 0 to allow for the faux biomass transport
n.generators.loc[
n.generators.carrier == "unsustainable solid biomass", "e_sum_min"
] = 0

n.add(
"GlobalConstraint",
"unsustainable biomass limit",
Expand All @@ -2899,17 +2880,24 @@ def add_biomass(n, costs):
n.add(
"Generator",
spatial.msw.nodes,
suffix=" transported",
bus=spatial.msw.nodes,
carrier="municipal solid waste",
p_nom=10000,
marginal_cost=0 # costs.at["municipal solid waste", "fuel"]
+ bus_transport_costs * average_distance,
+ bus_transport_costs.rename(
dict(zip(spatial.biomass.nodes, spatial.msw.nodes))
)
* average_distance,
)
n.generators.loc[
n.generators.carrier == "municipal solid waste", "e_sum_min"
] = 0
n.add(
"GlobalConstraint",
"msw limit",
carrier_attribute="municipal solid waste",
sense="<=",
sense="==",
constant=biomass_potentials["municipal solid waste"].sum(),
type="operational_limit",
)
Expand Down

0 comments on commit 52b8179

Please sign in to comment.