Skip to content

Commit

Permalink
Merge pull request #73 from PyPSA/biomass-transport
Browse files Browse the repository at this point in the history
Biomass transport
  • Loading branch information
fneum authored Sep 28, 2021
2 parents ec04d79 + 385779f commit 7d0ff39
Show file tree
Hide file tree
Showing 6 changed files with 259 additions and 37 deletions.
25 changes: 22 additions & 3 deletions Snakefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@

from snakemake.remote.HTTP import RemoteProvider as HTTPRemoteProvider
HTTP = HTTPRemoteProvider()

configfile: "config.yaml"


Expand Down Expand Up @@ -180,6 +183,21 @@ rule build_biomass_potentials:
script: 'scripts/build_biomass_potentials.py'


if config["sector"]["biomass_transport"]:
rule build_biomass_transport_costs:
input:
transport_cost_data=HTTP.remote("publications.jrc.ec.europa.eu/repository/bitstream/JRC98626/biomass potentials in europe_web rev.pdf", keep_local=True)
output:
biomass_transport_costs="resources/biomass_transport_costs.csv",
threads: 1
resources: mem_mb=1000
benchmark: "benchmarks/build_biomass_transport_costs"
script: 'scripts/build_biomass_transport_costs.py'
build_biomass_transport_costs_output = rules.build_biomass_transport_costs.output
else:
build_biomass_transport_costs_output = {}


rule build_ammonia_production:
input:
usgs="data/myb1-2017-nitro.xls"
Expand Down Expand Up @@ -321,8 +339,8 @@ rule prepare_sector_network:
energy_totals_name='resources/energy_totals.csv',
co2_totals_name='resources/co2_totals.csv',
transport_name='resources/transport_data.csv',
traffic_data_KFZ = "data/emobility/KFZ__count",
traffic_data_Pkw = "data/emobility/Pkw__count",
traffic_data_KFZ="data/emobility/KFZ__count",
traffic_data_Pkw="data/emobility/Pkw__count",
biomass_potentials='resources/biomass_potentials.csv',
heat_profile="data/heat_load_profile_BDEW.csv",
costs=CDIR + "costs_{planning_horizons}.csv",
Expand Down Expand Up @@ -352,7 +370,8 @@ rule prepare_sector_network:
solar_thermal_total="resources/solar_thermal_total_elec_s{simpl}_{clusters}.nc",
solar_thermal_urban="resources/solar_thermal_urban_elec_s{simpl}_{clusters}.nc",
solar_thermal_rural="resources/solar_thermal_rural_elec_s{simpl}_{clusters}.nc",
**build_retro_cost_output
**build_retro_cost_output,
**build_biomass_transport_costs_output
output: RDIR + '/prenetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc'
threads: 1
resources: mem_mb=2000
Expand Down
3 changes: 2 additions & 1 deletion config.default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ sector:
electricity_grid_connection: true # only applies to onshore wind and utility PV
gas_distribution_grid: true
gas_distribution_grid_cost_factor: 1.0 #multiplies cost in data/costs.csv
biomass_transport: false # biomass transport between nodes
conventional_generation: # generator : carrier
OCGT: gas

Expand Down Expand Up @@ -275,7 +276,6 @@ industry:
hotmaps_locate_missing: false
reference_year: 2015


costs:
lifetime: 25 #default lifetime
# From a Lion Hirth paper, also reflects average of Noothout et al 2016
Expand Down Expand Up @@ -509,5 +509,6 @@ plotting:
shipping oil: "#6495ED"
shipping oil emissions: "#6495ED"
electricity distribution grid: '#333333'
solid biomass transport: green
H2 for industry: "#222222"
H2 for shipping: "#6495ED"
6 changes: 6 additions & 0 deletions doc/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ Future release
* The share of shipping transformed into hydrogen fuel cell can be now defined for different years in the ``config.yaml`` file. The carbon emission from the remaining share is treated as a negative load on the atmospheric carbon dioxide bus, just like aviation and land transport emissions.
* The transformation of the Steel and Aluminium production can be now defined for different years in the ``config.yaml`` file.
* Include the option to alter the maximum energy capacity of a store via the ``carrier+factor`` in the ``{sector_opts}`` wildcard. This can be useful for sensitivity analyses. Example: ``co2 stored+e2`` multiplies the ``e_nom_max`` by factor 2. In this example, ``e_nom_max`` represents the CO2 sequestration potential in Europe.
* Add option to regionally disaggregate biomass potential to individual nodes
(currently given per country, then distributed by population density within)
and allow the transport of solid biomass.
The transport costs are determined based on the `JRC-EU-Times Bioenergy report <http://dx.doi.org/10.2790/01017>`_
in the new optional rule ``build_biomass_transport_costs``.
Biomass transport can be activated with the setting ``sector: biomass_transport: true``.
* Compatibility with ``xarray`` version 0.19.

PyPSA-Eur-Sec 0.5.0 (21st May 2021)
Expand Down
6 changes: 4 additions & 2 deletions doc/spatial_resolution.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ Hydrogen network: nodal.
Methane network: single node for Europe, since future demand is so
low and no bottlenecks are expected.

Solid biomass: single node for Europe, until transport costs can be
incorporated.
Solid biomass: choice between single node for Europe and nodal where biomass
potential is regionally disaggregated (currently given per country,
then distributed by population density within)
and transport of solid biomass is possible.

CO2: single node for Europe, but a transport and storage cost is added for
sequestered CO2. Optionally: nodal, with CO2 transport via pipelines.
Expand Down
90 changes: 90 additions & 0 deletions scripts/build_biomass_transport_costs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
"""
Reads biomass transport costs for different countries of the JRC report
"The JRC-EU-TIMES model.
Bioenergy potentials
for EU and neighbouring countries."
(2015)
converts them from units 'EUR per km/ton' -> 'EUR/ (km MWh)'
assuming as an approximation energy content of wood pellets
@author: bw0928
"""

import pandas as pd
import tabula as tbl

ENERGY_CONTENT = 4.8 # unit MWh/t (wood pellets)

def get_countries():

pandas_options = dict(
skiprows=range(6),
header=None,
index_col=0
)

return tbl.read_pdf(
str(snakemake.input.transport_cost_data),
pages="145",
multiple_tables=False,
pandas_options=pandas_options
)[0].index


def get_cost_per_tkm(page, countries):

pandas_options = dict(
skiprows=range(6),
header=0,
sep=' |,',
engine='python',
index_col=False,
)

sc = tbl.read_pdf(
str(snakemake.input.transport_cost_data),
pages=page,
multiple_tables=False,
pandas_options=pandas_options
)[0]
sc.index = countries
sc.columns = sc.columns.str.replace("€", "EUR")

return sc


def build_biomass_transport_costs():

countries = get_countries()

sc1 = get_cost_per_tkm(146, countries)
sc2 = get_cost_per_tkm(147, countries)

# take mean of both supply chains
to_concat = [sc1["EUR/km/ton"], sc2["EUR/km/ton"]]
transport_costs = pd.concat(to_concat, axis=1).mean(axis=1)

# convert tonnes to MWh
transport_costs /= ENERGY_CONTENT
transport_costs.name = "EUR/km/MWh"

# rename country names
to_rename = {
"UK": "GB",
"XK": "KO",
"EL": "GR"
}
transport_costs.rename(to_rename, inplace=True)

# add missing Norway with data from Sweden
transport_costs["NO"] = transport_costs["SE"]

transport_costs.to_csv(snakemake.output[0])


if __name__ == "__main__":

build_biomass_transport_costs()
Loading

0 comments on commit 7d0ff39

Please sign in to comment.