From a0b8014850def6d84cff1105739911c00060613f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Tr=C3=B6ndle?= Date: Wed, 27 Feb 2019 08:05:10 +0100 Subject: [PATCH] Remove sublocations necessary for area constraints So far, there were 4 sublocations per node, so 5 nodes per location in total. This is bad for performance. The sublocations existed so that technologies can compete on the same land. But actually, only open field pv and (parts of) wind onshore are competing on the same land. So now, all other renewable technologies are restricted by power caps. The area of a location represents the land that can be used by open field pv and wind onshore. This required a second wind onshore technology, as one has a area footprint (the one competing with open field pv) whereas the other does not. The whole change removes the need for sublocations and thus removes 80% of the Calliope locations. --- .flake8 | 2 +- Snakefile | 4 ++ src/locations.py | 72 +++++++++++++++---------------- src/template/renewable-techs.yaml | 38 ++++++++++------ 4 files changed, 64 insertions(+), 52 deletions(-) diff --git a/.flake8 b/.flake8 index 070188f8..b37ae0f2 100644 --- a/.flake8 +++ b/.flake8 @@ -1,5 +1,5 @@ [flake8] max-line-length = 119 -ignore = E261 +ignore = E261, W503 exclude = Snakefile, *.smk builtins = snakemake # for using the snakemake injection in scripts diff --git a/Snakefile b/Snakefile index c4a0229f..78cc0506 100644 --- a/Snakefile +++ b/Snakefile @@ -8,6 +8,10 @@ LAND_ELIGIBILITY = "src/data/national-eligibility.csv" localrules: all, raw_load, model, clean, copy_template +onstart: + shell("mkdir -p build/logs") + + rule all: message: "Generate Euro Calliope and run tests." input: diff --git a/src/locations.py b/src/locations.py index 0c8d2223..602cab32 100644 --- a/src/locations.py +++ b/src/locations.py @@ -2,6 +2,13 @@ import jinja2 import pandas as pd +FLAT_ROOF_SHARE = 0.302 # TODO add source (own publication) +MAXIMUM_INSTALLABLE_POWER_DENSITY = { + "pv-on-tilted-roofs": 160, # [W/m^2] from (Gagnon:2016, Klauser:2016), i.e. 16% efficiency + "pv-on-flat-areas": 80, # [W/m^2] from (Gagnon:2016, Klauser:2016, Wirth:2017) # FIXME also defined in renewable-techs.yaml + "onshore-wind": 8, # [W/m^2] from (European Environment Agency, 2009) # FIXME also defined in renewable-techs.yaml + "offshore-wind": 15 # [W/m^2] from (European Environment Agency, 2009) +} TEMPLATE = """locations: {{ eligibilities.index | join(', ') }}: @@ -9,49 +16,21 @@ demand_elec: battery: hydrogen: + open_field_pv: + wind_onshore_competing: {% for country, eligibility in eligibilities.iterrows() %} - {{ country }}_pv_or_wind_farm: - available_area: {{ eligibility.eligibility_onshore_wind_and_pv_km2 }} + {{ country }}: + available_area: {{ eligibility.eligibility_onshore_wind_and_pv_km2 }} # usable by onshore wind or open field pv techs: - open_field_pv: + wind_onshore_monopoly: constraints: - resource: file=capacityfactors-open-field-pv.csv:{{ country }} - wind_onshore: - constraints: - resource: file=capacityfactors-wind-onshore.csv:{{ country }} - {{ country }}_roof_mounted_pv: - available_area: {{ eligibility.eligibility_rooftop_pv_km2 }} - techs: + energy_cap_max: {{ eligibility.eligibility_onshore_wind_monopoly_kw }} roof_mounted_pv: constraints: - resource: file=capacityfactors-rooftop-pv.csv:{{ country }} - {{ country }}_wind_offshore: - available_area: {{ eligibility.eligibility_offshore_wind_km2 }} - techs: + energy_cap_max: {{ eligibility.eligibility_rooftop_pv_kw }} wind_offshore: constraints: - resource: file=capacityfactors-wind-offshore.csv:{{ country }} - {{ country }}_wind_onshore: - available_area: {{ eligibility.eligibility_onshore_wind_km2 }} - techs: - wind_onshore: - constraints: - resource: file=capacityfactors-wind-onshore.csv:{{ country }} - {% endfor %} -links: - {% for country, _ in eligibilities.iterrows() %} - {{ country }},{{ country}}_pv_or_wind_farm: - techs: - free_transmission: - {{ country }},{{ country}}_roof_mounted_pv: - techs: - free_transmission: - {{ country }},{{ country}}_wind_offshore: - techs: - free_transmission: - {{ country }},{{ country}}_wind_onshore: - techs: - free_transmission: + energy_cap_max: {{ eligibility.eligibility_offshore_wind_kw }} {% endfor %} """ @@ -60,12 +39,31 @@ def construct_locations(path_to_land_eligibility_km2, path_to_result): """Generate a file that represents locations in Calliope.""" template = jinja2.Template(TEMPLATE) rendered = template.render( - eligibilities=pd.read_csv(path_to_land_eligibility_km2, index_col=0) + eligibilities=_from_area_to_installed_capacity( + land_eligibiligy_km2=pd.read_csv(path_to_land_eligibility_km2, index_col=0), + flat_roof_share=FLAT_ROOF_SHARE, + maximum_installable_power_density=MAXIMUM_INSTALLABLE_POWER_DENSITY + ) ) with open(path_to_result, "w") as result_file: result_file.write(rendered) +def _from_area_to_installed_capacity(land_eligibiligy_km2, flat_roof_share, + maximum_installable_power_density): + cap = land_eligibiligy_km2.copy() + factor_rooftop = ( + maximum_installable_power_density["pv-on-flat-areas"] * flat_roof_share + + maximum_installable_power_density["pv-on-tilted-roofs"] * (1 - flat_roof_share) + ) * 1000 # MW/km2 to kW/km2 + factor_onshore = maximum_installable_power_density["onshore-wind"] * 1000 # MW/km2 to kW/km2 + factor_offshore = maximum_installable_power_density["offshore-wind"] * 1000 # MW/km2 to kW/km2 + cap["eligibility_rooftop_pv_kw"] = cap["eligibility_rooftop_pv_km2"] * factor_rooftop + cap["eligibility_offshore_wind_kw"] = cap["eligibility_offshore_wind_km2"] * factor_offshore + cap["eligibility_onshore_wind_monopoly_kw"] = cap["eligibility_onshore_wind_km2"] * factor_onshore + return cap + + if __name__ == "__main__": construct_locations( path_to_land_eligibility_km2=snakemake.input.land_eligibility_km2, diff --git a/src/template/renewable-techs.yaml b/src/template/renewable-techs.yaml index a68093b6..f84affbb 100644 --- a/src/template/renewable-techs.yaml +++ b/src/template/renewable-techs.yaml @@ -5,8 +5,6 @@ tech_groups: carrier: electricity parent: supply constraints: - resource_area_per_energy_cap: 0.0000125 # [km^2/kW] from (Gagnon:2016, Klauser:2016, Wirth:2017) - resource_area_max: inf # see https://github.com/calliope-project/calliope/pull/160 energy_cap_max: inf # see https://github.com/calliope-project/calliope/issues/161 lifetime: 20 costs: @@ -19,9 +17,19 @@ tech_groups: carrier: electricity parent: supply constraints: - resource_area_max: inf # see https://github.com/calliope-project/calliope/pull/160 energy_cap_max: inf # see https://github.com/calliope-project/calliope/issues/161 lifetime: 20 + wind_onshore: + essentials: + name: Onshore wind + parent: wind + constraints: + resource: file=capacityfactors-wind-onshore.csv + resource_unit: energy_per_cap + costs: + monetary: + energy_cap: 1316.28 # EUR2016/kW from IRENA (Figure 5.2), valid for 2016 + om_annual: 49.72 # EUR2016/kW from IRENA (Table 5.1) techs: open_field_pv: @@ -29,7 +37,10 @@ techs: name: Open field PV parent: pv constraints: + # open_field_pv and wind_onshore_competing are the only technologies with area footprints + # as they are the only technologies competing on the same land. resource_area_per_energy_cap: 0.0000125 # [km^2/kW] from (Gagnon:2016, Klauser:2016, Wirth:2017) + resource_area_max: inf # see https://github.com/calliope-project/calliope/pull/160 resource: file=capacityfactors-open-field-pv.csv resource_unit: energy_per_cap roof_mounted_pv: @@ -37,27 +48,26 @@ techs: name: Roof mounted PV parent: pv constraints: - resource_area_per_energy_cap: 0.00000625 # [km^2/kW] from (Gagnon:2016, Klauser:2016) resource: file=capacityfactors-rooftop-pv.csv resource_unit: energy_per_cap - wind_onshore: + wind_onshore_monopoly: essentials: - name: Onshore wind - parent: wind + name: Onshore wind without land competition + parent: wind_onshore + wind_onshore_competing: + essentials: + name: Onshore wind competing with open field PV on land + parent: wind_onshore constraints: + # open_field_pv and wind_onshore_competing are the only technologies with area footprints + # as they are the only technologies competing on the same land. resource_area_per_energy_cap: 0.000125 # [km^2/kW] from (European Environment Agency, 2009) - resource: file=capacityfactors-wind-onshore.csv - resource_unit: energy_per_cap - costs: - monetary: - energy_cap: 1316.28 # EUR2016/kW from IRENA (Figure 5.2), valid for 2016 - om_annual: 49.72 # EUR2016/kW from IRENA (Table 5.1) + resource_area_max: inf # see https://github.com/calliope-project/calliope/pull/160 wind_offshore: essentials: name: Offshore wind parent: wind constraints: - resource_area_per_energy_cap: 0.000066667 # [km^2/kW] from (European Environment Agency, 2009) resource: file=capacityfactors-wind-offshore.csv resource_unit: energy_per_cap costs: