Merge branch 'master' into auto-dl-countries
This commit is contained in:
commit
842d4b36e6
@ -65,10 +65,10 @@ The dataset consists of:
|
|||||||
(alternating current lines at and above 220kV voltage level and all high
|
(alternating current lines at and above 220kV voltage level and all high
|
||||||
voltage direct current lines) and 3803 substations.
|
voltage direct current lines) and 3803 substations.
|
||||||
- The open power plant database
|
- The open power plant database
|
||||||
[powerplantmatching](https://github.com/FRESNA/powerplantmatching).
|
[powerplantmatching](https://github.com/PyPSA/powerplantmatching).
|
||||||
- Electrical demand time series from the
|
- Electrical demand time series from the
|
||||||
[OPSD project](https://open-power-system-data.org/).
|
[OPSD project](https://open-power-system-data.org/).
|
||||||
- Renewable time series based on ERA5 and SARAH, assembled using the [atlite tool](https://github.com/FRESNA/atlite).
|
- Renewable time series based on ERA5 and SARAH, assembled using the [atlite tool](https://github.com/PyPSA/atlite).
|
||||||
- Geographical potentials for wind and solar generators based on land use (CORINE) and excluding nature reserves (Natura2000) are computed with the [atlite library](https://github.com/PyPSA/atlite).
|
- Geographical potentials for wind and solar generators based on land use (CORINE) and excluding nature reserves (Natura2000) are computed with the [atlite library](https://github.com/PyPSA/atlite).
|
||||||
|
|
||||||
A sector-coupled extension adds demand
|
A sector-coupled extension adds demand
|
||||||
|
@ -355,7 +355,6 @@ biomass:
|
|||||||
- Secondary Forestry residues - woodchips
|
- Secondary Forestry residues - woodchips
|
||||||
- Sawdust
|
- Sawdust
|
||||||
- Residues from landscape care
|
- Residues from landscape care
|
||||||
- Municipal waste
|
|
||||||
not included:
|
not included:
|
||||||
- Sugar from sugar beet
|
- Sugar from sugar beet
|
||||||
- Rape seed
|
- Rape seed
|
||||||
@ -369,6 +368,8 @@ biomass:
|
|||||||
biogas:
|
biogas:
|
||||||
- Manure solid, liquid
|
- Manure solid, liquid
|
||||||
- Sludge
|
- Sludge
|
||||||
|
municipal solid waste:
|
||||||
|
- Municipal waste
|
||||||
|
|
||||||
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#solar-thermal
|
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#solar-thermal
|
||||||
solar_thermal:
|
solar_thermal:
|
||||||
@ -409,6 +410,22 @@ sector:
|
|||||||
2045: 0.8
|
2045: 0.8
|
||||||
2050: 1.0
|
2050: 1.0
|
||||||
district_heating_loss: 0.15
|
district_heating_loss: 0.15
|
||||||
|
forward_temperature: 90 #C
|
||||||
|
return_temperature: 50 #C
|
||||||
|
heat_source_cooling: 6 #K
|
||||||
|
heat_pump_cop_approximation:
|
||||||
|
refrigerant: ammonia
|
||||||
|
heat_exchanger_pinch_point_temperature_difference: 5 #K
|
||||||
|
isentropic_compressor_efficiency: 0.8
|
||||||
|
heat_loss: 0.0
|
||||||
|
heat_pump_sources:
|
||||||
|
urban central:
|
||||||
|
- air
|
||||||
|
urban decentral:
|
||||||
|
- air
|
||||||
|
rural:
|
||||||
|
- air
|
||||||
|
- ground
|
||||||
cluster_heat_buses: true
|
cluster_heat_buses: true
|
||||||
heat_demand_cutout: default
|
heat_demand_cutout: default
|
||||||
bev_dsm_restriction_value: 0.75
|
bev_dsm_restriction_value: 0.75
|
||||||
@ -491,7 +508,7 @@ sector:
|
|||||||
aviation_demand_factor: 1.
|
aviation_demand_factor: 1.
|
||||||
HVC_demand_factor: 1.
|
HVC_demand_factor: 1.
|
||||||
time_dep_hp_cop: true
|
time_dep_hp_cop: true
|
||||||
heat_pump_sink_T: 55.
|
heat_pump_sink_T_individual_heating: 55.
|
||||||
reduce_space_heat_exogenously: true
|
reduce_space_heat_exogenously: true
|
||||||
reduce_space_heat_exogenously_factor:
|
reduce_space_heat_exogenously_factor:
|
||||||
2020: 0.10 # this results in a space heat demand reduction of 10%
|
2020: 0.10 # this results in a space heat demand reduction of 10%
|
||||||
@ -597,7 +614,9 @@ sector:
|
|||||||
conventional_generation:
|
conventional_generation:
|
||||||
OCGT: gas
|
OCGT: gas
|
||||||
biomass_to_liquid: false
|
biomass_to_liquid: false
|
||||||
|
electrobiofuels: false
|
||||||
biosng: false
|
biosng: false
|
||||||
|
municipal_solid_waste: false
|
||||||
limit_max_growth:
|
limit_max_growth:
|
||||||
enable: false
|
enable: false
|
||||||
# allowing 30% larger than max historic growth
|
# allowing 30% larger than max historic growth
|
||||||
@ -619,6 +638,12 @@ sector:
|
|||||||
max_boost: 0.25
|
max_boost: 0.25
|
||||||
var_cf: true
|
var_cf: true
|
||||||
sustainability_factor: 0.0025
|
sustainability_factor: 0.0025
|
||||||
|
solid_biomass_import:
|
||||||
|
enable: false
|
||||||
|
price: 54 #EUR/MWh
|
||||||
|
max_amount: 1390 # TWh
|
||||||
|
upstream_emissions_factor: .1 #share of solid biomass CO2 emissions at full combustion
|
||||||
|
|
||||||
|
|
||||||
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#industry
|
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#industry
|
||||||
industry:
|
industry:
|
||||||
@ -1016,6 +1041,8 @@ plotting:
|
|||||||
biogas: '#e3d37d'
|
biogas: '#e3d37d'
|
||||||
biomass: '#baa741'
|
biomass: '#baa741'
|
||||||
solid biomass: '#baa741'
|
solid biomass: '#baa741'
|
||||||
|
municipal solid waste: '#91ba41'
|
||||||
|
solid biomass import: '#d5ca8d'
|
||||||
solid biomass transport: '#baa741'
|
solid biomass transport: '#baa741'
|
||||||
solid biomass for industry: '#7a6d26'
|
solid biomass for industry: '#7a6d26'
|
||||||
solid biomass for industry CC: '#47411c'
|
solid biomass for industry CC: '#47411c'
|
||||||
@ -1029,6 +1056,7 @@ plotting:
|
|||||||
services rural biomass boiler: '#c6cf98'
|
services rural biomass boiler: '#c6cf98'
|
||||||
services urban decentral biomass boiler: '#dde5b5'
|
services urban decentral biomass boiler: '#dde5b5'
|
||||||
biomass to liquid: '#32CD32'
|
biomass to liquid: '#32CD32'
|
||||||
|
electrobiofuels: 'red'
|
||||||
BioSNG: '#123456'
|
BioSNG: '#123456'
|
||||||
# power transmission
|
# power transmission
|
||||||
lines: '#6c9459'
|
lines: '#6c9459'
|
||||||
|
@ -5,7 +5,7 @@ Cross-Channel,France - Echingen 50°41′48″N 1°38′21″E / 50.69667
|
|||||||
Volgograd-Donbass,Russia - Volzhskaya 48°49′34″N 44°40′20″E / 48.82611°N 44.67222°E,Ukraine - Mikhailovskaya 48°39′13″N 38°33′56″E / 48.65361°N 38.56556°E,475(0/475),400,750.0,1965,Merc/Thyr,Shut down in 2014,[1],44.672222222222224,48.82611111111111,38.565555555555555,48.65361111111111
|
Volgograd-Donbass,Russia - Volzhskaya 48°49′34″N 44°40′20″E / 48.82611°N 44.67222°E,Ukraine - Mikhailovskaya 48°39′13″N 38°33′56″E / 48.65361°N 38.56556°E,475(0/475),400,750.0,1965,Merc/Thyr,Shut down in 2014,[1],44.672222222222224,48.82611111111111,38.565555555555555,48.65361111111111
|
||||||
Konti-Skan 1,Denmark - Vester Hassing 57°3′46″N 10°5′24″E / 57.06278°N 10.09000°E,Sweden - Stenkullen 57°48′15″N 12°19′13″E / 57.80417°N 12.32028°E,176(87/89),250,250.0,1965,Merc,Replaced in August 2006 by modern converters using thyristors,[1],10.09,57.062777777777775,12.320277777777777,57.80416666666667
|
Konti-Skan 1,Denmark - Vester Hassing 57°3′46″N 10°5′24″E / 57.06278°N 10.09000°E,Sweden - Stenkullen 57°48′15″N 12°19′13″E / 57.80417°N 12.32028°E,176(87/89),250,250.0,1965,Merc,Replaced in August 2006 by modern converters using thyristors,[1],10.09,57.062777777777775,12.320277777777777,57.80416666666667
|
||||||
SACOI 1a,Italy - Suvereto 43°3′10″N 10°41′42″E / 43.05278°N 10.69500°E ( before 1992: Italy - San Dalmazio 43°15′43″N 10°55′05″E / 43.26194°N 10.91806°E),"France- Lucciana 42°31′40″N 9°26′59″E / 42.52778°N 9.44972°E",483(365/118),200,200.0,1965,Merc,"Replaced in 1986 by Thyr- multiterminal scheme",[1],10.695,43.05277777777778,9.449722222222222,42.52777777777778
|
SACOI 1a,Italy - Suvereto 43°3′10″N 10°41′42″E / 43.05278°N 10.69500°E ( before 1992: Italy - San Dalmazio 43°15′43″N 10°55′05″E / 43.26194°N 10.91806°E),"France- Lucciana 42°31′40″N 9°26′59″E / 42.52778°N 9.44972°E",483(365/118),200,200.0,1965,Merc,"Replaced in 1986 by Thyr- multiterminal scheme",[1],10.695,43.05277777777778,9.449722222222222,42.52777777777778
|
||||||
SACOI 1b,"France- Lucciana 42°31′40″N 9°26′59″E / 42.52778°N 9.44972°E", "Codrongianos- Italy 40°39′7″N 8°42′48″E / 40.65194°N 8.71333°E",483(365/118),200,200.0,1965,Merc,"Replaced in 1986 by Thyr- multiterminal scheme",[1],9.449722222222222,42.52777777777778,8.679351,40.65765
|
SACOI 1b,"France- Lucciana 42°31′40″N 9°26′59″E / 42.52778°N 9.44972°E","Codrongianos- Italy 40°39′7″N 8°42′48″E / 40.65194°N 8.71333°E",483(365/118),200,200.0,1965,Merc,"Replaced in 1986 by Thyr- multiterminal scheme",[1],9.449722222222222,42.52777777777778,8.679351,40.65765
|
||||||
Kingsnorth,UK - Kingsnorth 51°25′11″N 0°35′46″E / 51.41972°N 0.59611°E,UK - London-Beddington 51°22′23″N 0°7′38″W / 51.37306°N 0.12722°W,85(85/0),266,320.0,1975,Merc,Bipolar scheme Supplier: English Electric Shut down in 1987,[33],0.5961111111111111,51.41972222222222,-0.1272222222222222,51.37305555555555
|
Kingsnorth,UK - Kingsnorth 51°25′11″N 0°35′46″E / 51.41972°N 0.59611°E,UK - London-Beddington 51°22′23″N 0°7′38″W / 51.37306°N 0.12722°W,85(85/0),266,320.0,1975,Merc,Bipolar scheme Supplier: English Electric Shut down in 1987,[33],0.5961111111111111,51.41972222222222,-0.1272222222222222,51.37305555555555
|
||||||
Skagerrak 1 + 2,Denmark - Tjele 56°28′44″N 9°34′1″E / 56.47889°N 9.56694°E,Norway - Kristiansand 58°15′36″N 7°53′55″E / 58.26000°N 7.89861°E,230(130/100),250,500.0,1977,Thyr,Supplier: STK(Nexans) Control system upgrade by ABB in 2007,[34][35][36],9.566944444444445,56.47888888888889,7.898611111111111,58.26
|
Skagerrak 1 + 2,Denmark - Tjele 56°28′44″N 9°34′1″E / 56.47889°N 9.56694°E,Norway - Kristiansand 58°15′36″N 7°53′55″E / 58.26000°N 7.89861°E,230(130/100),250,500.0,1977,Thyr,Supplier: STK(Nexans) Control system upgrade by ABB in 2007,[34][35][36],9.566944444444445,56.47888888888889,7.898611111111111,58.26
|
||||||
Gotland 2,Sweden - Västervik 57°43′41″N 16°38′51″E / 57.72806°N 16.64750°E,Sweden - Yigne 57°35′13″N 18°11′44″E / 57.58694°N 18.19556°E,99.5(92.9/6.6),150,130.0,1983,Thyr,Supplier: ABB,,16.6475,57.72805555555556,18.195555555555554,57.58694444444444
|
Gotland 2,Sweden - Västervik 57°43′41″N 16°38′51″E / 57.72806°N 16.64750°E,Sweden - Yigne 57°35′13″N 18°11′44″E / 57.58694°N 18.19556°E,99.5(92.9/6.6),150,130.0,1983,Thyr,Supplier: ABB,,16.6475,57.72805555555556,18.195555555555554,57.58694444444444
|
||||||
@ -23,7 +23,7 @@ Visby-Nas,Sweden - Nas 57°05′58″N 18°14′27″E / 57.09944°N 18.24
|
|||||||
SwePol,Poland - Wierzbięcin 54°30′8″N 16°53′28″E / 54.50222°N 16.89111°E,Sweden - Stärnö 56°9′11″N 14°50′29″E / 56.15306°N 14.84139°E,245(245/0),450,600.0,2000,Thyr,Supplier: ABB,[38],16.891111111111112,54.50222222222222,14.841388888888888,56.153055555555554
|
SwePol,Poland - Wierzbięcin 54°30′8″N 16°53′28″E / 54.50222°N 16.89111°E,Sweden - Stärnö 56°9′11″N 14°50′29″E / 56.15306°N 14.84139°E,245(245/0),450,600.0,2000,Thyr,Supplier: ABB,[38],16.891111111111112,54.50222222222222,14.841388888888888,56.153055555555554
|
||||||
Tjæreborg,Denmark - Tjæreborg/Enge 55°26′52″N 8°35′34″E / 55.44778°N 8.59278°E,Denmark - Tjæreborg/Substation 55°28′07″N 8°33′36″E / 55.46861°N 8.56000°E,4.3(4.3/0),9,7.0,2000,IGBT,Interconnection to wind power generating stations,,8.592777777777778,55.44777777777778,8.56,55.46861111111111
|
Tjæreborg,Denmark - Tjæreborg/Enge 55°26′52″N 8°35′34″E / 55.44778°N 8.59278°E,Denmark - Tjæreborg/Substation 55°28′07″N 8°33′36″E / 55.46861°N 8.56000°E,4.3(4.3/0),9,7.0,2000,IGBT,Interconnection to wind power generating stations,,8.592777777777778,55.44777777777778,8.56,55.46861111111111
|
||||||
Italy-Greece,Greece - Arachthos 39°11′00″N 20°57′48″E / 39.18333°N 20.96333°E,Italy - Galatina 40°9′53″N 18°7′49″E / 40.16472°N 18.13028°E,310(200/110),400,500.0,2001,Thyr,,,20.963333333333335,39.18333333333333,18.130277777777778,40.164722222222224
|
Italy-Greece,Greece - Arachthos 39°11′00″N 20°57′48″E / 39.18333°N 20.96333°E,Italy - Galatina 40°9′53″N 18°7′49″E / 40.16472°N 18.13028°E,310(200/110),400,500.0,2001,Thyr,,,20.963333333333335,39.18333333333333,18.130277777777778,40.164722222222224
|
||||||
Moyle,UK - Auchencrosh 55°04′10″N 4°58′50″W / 55.06944°N 4.98056°W,UK - N. Ireland- Ballycronan More 54°50′34″N 5°46′11″W / 54.84278°N 5.76972°W,63.5(63.5/0),250,2501.0,2001,Thyr,"Supplier: Siemens- Nexans",[39],-4.980555555555556,55.06944444444444,-5.769722222222223,54.842777777777776
|
Moyle,UK - Auchencrosh 55°04′10″N 4°58′50″W / 55.06944°N 4.98056°W,UK - N. Ireland- Ballycronan More 54°50′34″N 5°46′11″W / 54.84278°N 5.76972°W,63.5(63.5/0),250,500.0,2001,Thyr,"Supplier: Siemens- Nexans",[39],-4.980555555555556,55.06944444444444,-5.769722222222223,54.842777777777776
|
||||||
HVDC Troll,Norway - Kollsnes 60°33′01″N 4°50′26″E / 60.55028°N 4.84056°E,Norway - Offshore platform Troll A 60°40′00″N 3°40′00″E / 60.66667°N 3.66667°E,70(70/0),60,80.0,2004,IGBT,Power supply for offshore gas compressor Supplier: ABB,[40],4.8405555555555555,60.55027777777778,3.6666666666666665,60.666666666666664
|
HVDC Troll,Norway - Kollsnes 60°33′01″N 4°50′26″E / 60.55028°N 4.84056°E,Norway - Offshore platform Troll A 60°40′00″N 3°40′00″E / 60.66667°N 3.66667°E,70(70/0),60,80.0,2004,IGBT,Power supply for offshore gas compressor Supplier: ABB,[40],4.8405555555555555,60.55027777777778,3.6666666666666665,60.666666666666664
|
||||||
Estlink,Finland - Espoo 60°12′14″N 24°33′06″E / 60.20389°N 24.55167°E,Estonia - Harku 59°23′5″N 24°33′37″E / 59.38472°N 24.56028°E,105(105/0),150,350.0,2006,IGBT,Supplier: ABB,[40],24.551666666666666,60.20388888888889,24.560277777777777,59.38472222222222
|
Estlink,Finland - Espoo 60°12′14″N 24°33′06″E / 60.20389°N 24.55167°E,Estonia - Harku 59°23′5″N 24°33′37″E / 59.38472°N 24.56028°E,105(105/0),150,350.0,2006,IGBT,Supplier: ABB,[40],24.551666666666666,60.20388888888889,24.560277777777777,59.38472222222222
|
||||||
NorNed,Netherlands - Eemshaven 53°26′4″N 6°51′57″E / 53.43444°N 6.86583°E,Norway - Feda 58°16′58″N 6°51′55″E / 58.28278°N 6.86528°E,580(580/0),450,700.0,2008,Thyr,"Supplier: ABB- Nexans",[40],6.865833333333334,53.434444444444445,6.865277777777778,58.28277777777778
|
NorNed,Netherlands - Eemshaven 53°26′4″N 6°51′57″E / 53.43444°N 6.86583°E,Norway - Feda 58°16′58″N 6°51′55″E / 58.28278°N 6.86528°E,580(580/0),450,700.0,2008,Thyr,"Supplier: ABB- Nexans",[40],6.865833333333334,53.434444444444445,6.865277777777778,58.28277777777778
|
||||||
|
|
@ -341,4 +341,6 @@ texinfo_documents = [
|
|||||||
|
|
||||||
|
|
||||||
# Example configuration for intersphinx: refer to the Python standard library.
|
# Example configuration for intersphinx: refer to the Python standard library.
|
||||||
intersphinx_mapping = {"https://docs.python.org/": None}
|
intersphinx_mapping = {
|
||||||
|
"https://docs.python.org/": ("https://docs.python.org/3", None),
|
||||||
|
}
|
||||||
|
@ -1,156 +1,174 @@
|
|||||||
,Unit,Values,Description
|
,Unit,Values,Description
|
||||||
transport,--,"{true, false}",Flag to include transport sector.
|
transport,--,"{true, false}",Flag to include transport sector.
|
||||||
heating,--,"{true, false}",Flag to include heating sector.
|
heating,--,"{true, false}",Flag to include heating sector.
|
||||||
biomass,--,"{true, false}",Flag to include biomass sector.
|
biomass,--,"{true, false}",Flag to include biomass sector.
|
||||||
industry,--,"{true, false}",Flag to include industry sector.
|
industry,--,"{true, false}",Flag to include industry sector.
|
||||||
agriculture,--,"{true, false}",Flag to include agriculture sector.
|
agriculture,--,"{true, false}",Flag to include agriculture sector.
|
||||||
fossil_fuels,--,"{true, false}","Flag to include imports of fossil fuels ( [""coal"", ""gas"", ""oil"", ""lignite""])"
|
fossil_fuels,--,"{true, false}","Flag to include imports of fossil fuels ( [""coal"", ""gas"", ""oil"", ""lignite""])"
|
||||||
district_heating,--,,`prepare_sector_network.py <https://github.com/PyPSA/pypsa-eur-sec/blob/master/scripts/prepare_sector_network.py>`_
|
district_heating,--,,`prepare_sector_network.py <https://github.com/PyPSA/pypsa-eur-sec/blob/master/scripts/prepare_sector_network.py>`_
|
||||||
-- potential,--,float,maximum fraction of urban demand which can be supplied by district heating. Ignored where below current fraction.
|
-- potential,--,float,maximum fraction of urban demand which can be supplied by district heating
|
||||||
-- progress,--,Dictionary with planning horizons as keys., Increase of today's district heating demand to potential maximum district heating share. Progress = 0 means today's district heating share. Progress = 1 means maximum fraction of urban demand is supplied by district heating
|
-- progress,--,Dictionary with planning horizons as keys., Increase of today's district heating demand to potential maximum district heating share. Progress = 0 means today's district heating share. Progress = 1 means maximum fraction of urban demand is supplied by district heating
|
||||||
-- district_heating_loss,--,float,Share increase in district heat demand in urban central due to heat losses
|
-- district_heating_loss,--,float,Share increase in district heat demand in urban central due to heat losses
|
||||||
cluster_heat_buses,--,"{true, false}",Cluster residential and service heat buses in `prepare_sector_network.py <https://github.com/PyPSA/pypsa-eur-sec/blob/master/scripts/prepare_sector_network.py>`_ to one to save memory.
|
-- forward_temperature,°C,float,Forward temperature in district heating
|
||||||
,,,
|
-- return_temperature,°C,float,Return temperature in district heating. Must be lower than forward temperature
|
||||||
bev_dsm_restriction _value,--,float,Adds a lower state of charge (SOC) limit for battery electric vehicles (BEV) to manage its own energy demand (DSM). Located in `build_transport_demand.py <https://github.com/PyPSA/pypsa-eur-sec/blob/master/scripts/build_transport_demand.py>`_. Set to 0 for no restriction on BEV DSM
|
-- heat_source_cooling,K,float,Cooling of heat source for heat pumps
|
||||||
bev_dsm_restriction _time,--,float,Time at which SOC of BEV has to be dsm_restriction_value
|
-- heat_pump_cop_approximation,,,
|
||||||
transport_heating _deadband_upper,°C,float,"The maximum temperature in the vehicle. At higher temperatures, the energy required for cooling in the vehicle increases."
|
-- -- refrigerant,--,"{ammonia, isobutane}",Heat pump refrigerant assumed for COP approximation
|
||||||
transport_heating _deadband_lower,°C,float,"The minimum temperature in the vehicle. At lower temperatures, the energy required for heating in the vehicle increases."
|
-- -- heat_exchanger_pinch_point_temperature_difference,K,float,Heat pump pinch point temperature difference in heat exchangers assumed for approximation.
|
||||||
,,,
|
-- -- isentropic_compressor_efficiency,--,float,Isentropic efficiency of heat pump compressor assumed for approximation. Must be between 0 and 1.
|
||||||
ICE_lower_degree_factor,--,float,Share increase in energy demand in internal combustion engine (ICE) for each degree difference between the cold environment and the minimum temperature.
|
-- -- heat_loss,--,float,Heat pump heat loss assumed for approximation. Must be between 0 and 1.
|
||||||
ICE_upper_degree_factor,--,float,Share increase in energy demand in internal combustion engine (ICE) for each degree difference between the hot environment and the maximum temperature.
|
-- heat_pump_sources,--,,
|
||||||
EV_lower_degree_factor,--,float,Share increase in energy demand in electric vehicles (EV) for each degree difference between the cold environment and the minimum temperature.
|
-- -- urban central,--,List of heat sources for heat pumps in urban central heating,
|
||||||
EV_upper_degree_factor,--,float,Share increase in energy demand in electric vehicles (EV) for each degree difference between the hot environment and the maximum temperature.
|
-- -- urban decentral,--,List of heat sources for heat pumps in urban decentral heating,
|
||||||
bev_dsm,--,"{true, false}",Add the option for battery electric vehicles (BEV) to participate in demand-side management (DSM)
|
-- -- rural,--,List of heat sources for heat pumps in rural heating,
|
||||||
,,,
|
cluster_heat_buses,--,"{true, false}",Cluster residential and service heat buses in `prepare_sector_network.py <https://github.com/PyPSA/pypsa-eur-sec/blob/master/scripts/prepare_sector_network.py>`_ to one to save memory.
|
||||||
bev_availability,--,float,The share for battery electric vehicles (BEV) that are able to do demand side management (DSM)
|
,,,
|
||||||
bev_energy,--,float,The average size of battery electric vehicles (BEV) in MWh
|
bev_dsm_restriction _value,--,float,Adds a lower state of charge (SOC) limit for battery electric vehicles (BEV) to manage its own energy demand (DSM). Located in `build_transport_demand.py <https://github.com/PyPSA/pypsa-eur-sec/blob/master/scripts/build_transport_demand.py>`_. Set to 0 for no restriction on BEV DSM
|
||||||
bev_charge_efficiency,--,float,Battery electric vehicles (BEV) charge and discharge efficiency
|
bev_dsm_restriction _time,--,float,Time at which SOC of BEV has to be dsm_restriction_value
|
||||||
bev_charge_rate,MWh,float,The power consumption for one electric vehicle (EV) in MWh. Value derived from 3-phase charger with 11 kW.
|
transport_heating _deadband_upper,°C,float,"The maximum temperature in the vehicle. At higher temperatures, the energy required for cooling in the vehicle increases."
|
||||||
bev_avail_max,--,float,The maximum share plugged-in availability for passenger electric vehicles.
|
transport_heating _deadband_lower,°C,float,"The minimum temperature in the vehicle. At lower temperatures, the energy required for heating in the vehicle increases."
|
||||||
bev_avail_mean,--,float,The average share plugged-in availability for passenger electric vehicles.
|
,,,
|
||||||
v2g,--,"{true, false}",Allows feed-in to grid from EV battery
|
ICE_lower_degree_factor,--,float,Share increase in energy demand in internal combustion engine (ICE) for each degree difference between the cold environment and the minimum temperature.
|
||||||
land_transport_fuel_cell _share,--,Dictionary with planning horizons as keys.,The share of vehicles that uses fuel cells in a given year
|
ICE_upper_degree_factor,--,float,Share increase in energy demand in internal combustion engine (ICE) for each degree difference between the hot environment and the maximum temperature.
|
||||||
land_transport_electric _share,--,Dictionary with planning horizons as keys.,The share of vehicles that uses electric vehicles (EV) in a given year
|
EV_lower_degree_factor,--,float,Share increase in energy demand in electric vehicles (EV) for each degree difference between the cold environment and the minimum temperature.
|
||||||
land_transport_ice _share,--,Dictionary with planning horizons as keys.,The share of vehicles that uses internal combustion engines (ICE) in a given year. What is not EV or FCEV is oil-fuelled ICE.
|
EV_upper_degree_factor,--,float,Share increase in energy demand in electric vehicles (EV) for each degree difference between the hot environment and the maximum temperature.
|
||||||
transport_electric_efficiency,MWh/100km,float,The conversion efficiencies of electric vehicles in transport
|
bev_dsm,--,"{true, false}",Add the option for battery electric vehicles (BEV) to participate in demand-side management (DSM)
|
||||||
transport_fuel_cell_efficiency,MWh/100km,float,The H2 conversion efficiencies of fuel cells in transport
|
,,,
|
||||||
transport_ice_efficiency,MWh/100km,float,The oil conversion efficiencies of internal combustion engine (ICE) in transport
|
bev_availability,--,float,The share for battery electric vehicles (BEV) that are able to do demand side management (DSM)
|
||||||
agriculture_machinery _electric_share,--,float,The share for agricultural machinery that uses electricity
|
bev_energy,--,float,The average size of battery electric vehicles (BEV) in MWh
|
||||||
agriculture_machinery _oil_share,--,float,The share for agricultural machinery that uses oil
|
bev_charge_efficiency,--,float,Battery electric vehicles (BEV) charge and discharge efficiency
|
||||||
agriculture_machinery _fuel_efficiency,--,float,The efficiency of electric-powered machinery in the conversion of electricity to meet agricultural needs.
|
bev_charge_rate,MWh,float,The power consumption for one electric vehicle (EV) in MWh. Value derived from 3-phase charger with 11 kW.
|
||||||
agriculture_machinery _electric_efficiency,--,float,The efficiency of oil-powered machinery in the conversion of oil to meet agricultural needs.
|
bev_avail_max,--,float,The maximum share plugged-in availability for passenger electric vehicles.
|
||||||
Mwh_MeOH_per_MWh_H2,LHV,float,"The energy amount of the produced methanol per energy amount of hydrogen. From `DECHEMA (2017) <https://dechema.de/dechema_media/Downloads/Positionspapiere/Technology_study_Low_carbon_energy_and_feedstock_for_the_European_chemical_industry-p-20002750.pdf>`_, page 64."
|
bev_avail_mean,--,float,The average share plugged-in availability for passenger electric vehicles.
|
||||||
MWh_MeOH_per_tCO2,LHV,float,"The energy amount of the produced methanol per ton of CO2. From `DECHEMA (2017) <https://dechema.de/dechema_media/Downloads/Positionspapiere/Technology_study_Low_carbon_energy_and_feedstock_for_the_European_chemical_industry-p-20002750.pdf>`_, page 66."
|
v2g,--,"{true, false}",Allows feed-in to grid from EV battery
|
||||||
MWh_MeOH_per_MWh_e,LHV,float,"The energy amount of the produced methanol per energy amount of electricity. From `DECHEMA (2017) <https://dechema.de/dechema_media/Downloads/Positionspapiere/Technology_study_Low_carbon_energy_and_feedstock_for_the_European_chemical_industry-p-20002750.pdf>`_, page 64."
|
land_transport_fuel_cell _share,--,Dictionary with planning horizons as keys.,The share of vehicles that uses fuel cells in a given year
|
||||||
shipping_hydrogen _liquefaction,--,"{true, false}",Whether to include liquefaction costs for hydrogen demand in shipping.
|
land_transport_electric _share,--,Dictionary with planning horizons as keys.,The share of vehicles that uses electric vehicles (EV) in a given year
|
||||||
,,,
|
land_transport_ice _share,--,Dictionary with planning horizons as keys.,The share of vehicles that uses internal combustion engines (ICE) in a given year. What is not EV or FCEV is oil-fuelled ICE.
|
||||||
shipping_hydrogen_share,--,Dictionary with planning horizons as keys.,The share of ships powered by hydrogen in a given year
|
transport_electric_efficiency,MWh/100km,float,The conversion efficiencies of electric vehicles in transport
|
||||||
shipping_methanol_share,--,Dictionary with planning horizons as keys.,The share of ships powered by methanol in a given year
|
transport_fuel_cell_efficiency,MWh/100km,float,The H2 conversion efficiencies of fuel cells in transport
|
||||||
shipping_oil_share,--,Dictionary with planning horizons as keys.,The share of ships powered by oil in a given year
|
transport_ice_efficiency,MWh/100km,float,The oil conversion efficiencies of internal combustion engine (ICE) in transport
|
||||||
shipping_methanol _efficiency,--,float,The efficiency of methanol-powered ships in the conversion of methanol to meet shipping needs (propulsion). The efficiency increase from oil can be 10-15% higher according to the `IEA <https://www.iea-amf.org/app/webroot/files/file/Annex%20Reports/AMF_Annex_56.pdf>`_
|
agriculture_machinery _electric_share,--,float,The share for agricultural machinery that uses electricity
|
||||||
,,,
|
agriculture_machinery _oil_share,--,float,The share for agricultural machinery that uses oil
|
||||||
shipping_oil_efficiency,--,float,The efficiency of oil-powered ships in the conversion of oil to meet shipping needs (propulsion). Base value derived from 2011
|
agriculture_machinery _fuel_efficiency,--,float,The efficiency of electric-powered machinery in the conversion of electricity to meet agricultural needs.
|
||||||
aviation_demand_factor,--,float,The proportion of demand for aviation compared to today's consumption
|
agriculture_machinery _electric_efficiency,--,float,The efficiency of oil-powered machinery in the conversion of oil to meet agricultural needs.
|
||||||
HVC_demand_factor,--,float,The proportion of demand for high-value chemicals compared to today's consumption
|
Mwh_MeOH_per_MWh_H2,LHV,float,"The energy amount of the produced methanol per energy amount of hydrogen. From `DECHEMA (2017) <https://dechema.de/dechema_media/Downloads/Positionspapiere/Technology_study_Low_carbon_energy_and_feedstock_for_the_European_chemical_industry-p-20002750.pdf>`_, page 64."
|
||||||
,,,
|
MWh_MeOH_per_tCO2,LHV,float,"The energy amount of the produced methanol per ton of CO2. From `DECHEMA (2017) <https://dechema.de/dechema_media/Downloads/Positionspapiere/Technology_study_Low_carbon_energy_and_feedstock_for_the_European_chemical_industry-p-20002750.pdf>`_, page 66."
|
||||||
time_dep_hp_cop,--,"{true, false}",Consider the time dependent coefficient of performance (COP) of the heat pump
|
MWh_MeOH_per_MWh_e,LHV,float,"The energy amount of the produced methanol per energy amount of electricity. From `DECHEMA (2017) <https://dechema.de/dechema_media/Downloads/Positionspapiere/Technology_study_Low_carbon_energy_and_feedstock_for_the_European_chemical_industry-p-20002750.pdf>`_, page 64."
|
||||||
heat_pump_sink_T,°C,float,The temperature heat sink used in heat pumps based on DTU / large area radiators. The value is conservatively high to cover hot water and space heating in poorly-insulated buildings
|
shipping_hydrogen _liquefaction,--,"{true, false}",Whether to include liquefaction costs for hydrogen demand in shipping.
|
||||||
reduce_space_heat _exogenously,--,"{true, false}",Influence on space heating demand by a certain factor (applied before losses in district heating).
|
,,,
|
||||||
reduce_space_heat _exogenously_factor,--,Dictionary with planning horizons as keys.,"A positive factor can mean renovation or demolition of a building. If the factor is negative, it can mean an increase in floor area, increased thermal comfort, population growth. The default factors are determined by the `Eurocalc Homes and buildings decarbonization scenario <http://tool.european-calculator.eu/app/buildings/building-types-area/?levers=1ddd4444421213bdbbbddd44444ffffff11f411111221111211l212221>`_"
|
shipping_hydrogen_share,--,Dictionary with planning horizons as keys.,The share of ships powered by hydrogen in a given year
|
||||||
retrofitting,,,
|
shipping_methanol_share,--,Dictionary with planning horizons as keys.,The share of ships powered by methanol in a given year
|
||||||
-- retro_endogen,--,"{true, false}",Add retrofitting as an endogenous system which co-optimise space heat savings.
|
shipping_oil_share,--,Dictionary with planning horizons as keys.,The share of ships powered by oil in a given year
|
||||||
-- cost_factor,--,float,Weight costs for building renovation
|
shipping_methanol _efficiency,--,float,The efficiency of methanol-powered ships in the conversion of methanol to meet shipping needs (propulsion). The efficiency increase from oil can be 10-15% higher according to the `IEA <https://www.iea-amf.org/app/webroot/files/file/Annex%20Reports/AMF_Annex_56.pdf>`_
|
||||||
-- interest_rate,--,float,The interest rate for investment in building components
|
,,,
|
||||||
-- annualise_cost,--,"{true, false}",Annualise the investment costs of retrofitting
|
shipping_oil_efficiency,--,float,The efficiency of oil-powered ships in the conversion of oil to meet shipping needs (propulsion). Base value derived from 2011
|
||||||
-- tax_weighting,--,"{true, false}",Weight the costs of retrofitting depending on taxes in countries
|
aviation_demand_factor,--,float,The proportion of demand for aviation compared to today's consumption
|
||||||
-- construction_index,--,"{true, false}",Weight the costs of retrofitting depending on labour/material costs per country
|
HVC_demand_factor,--,float,The proportion of demand for high-value chemicals compared to today's consumption
|
||||||
tes,--,"{true, false}",Add option for storing thermal energy in large water pits associated with district heating systems and individual thermal energy storage (TES)
|
,,,
|
||||||
tes_tau,,,The time constant used to calculate the decay of thermal energy in thermal energy storage (TES): 1- :math:`e^{-1/24τ}`.
|
time_dep_hp_cop,--,"{true, false}",Consider the time dependent coefficient of performance (COP) of the heat pump
|
||||||
-- decentral,days,float,The time constant in decentralized thermal energy storage (TES)
|
heat_pump_sink_T,°C,float,The temperature heat sink used in heat pumps based on DTU / large area radiators. The value is conservatively high to cover hot water and space heating in poorly-insulated buildings
|
||||||
-- central,days,float,The time constant in centralized thermal energy storage (TES)
|
reduce_space_heat _exogenously,--,"{true, false}",Influence on space heating demand by a certain factor (applied before losses in district heating).
|
||||||
boilers,--,"{true, false}",Add option for transforming gas into heat using gas boilers
|
reduce_space_heat _exogenously_factor,--,Dictionary with planning horizons as keys.,"A positive factor can mean renovation or demolition of a building. If the factor is negative, it can mean an increase in floor area, increased thermal comfort, population growth. The default factors are determined by the `Eurocalc Homes and buildings decarbonization scenario <http://tool.european-calculator.eu/app/buildings/building-types-area/?levers=1ddd4444421213bdbbbddd44444ffffff11f411111221111211l212221>`_"
|
||||||
resistive_heaters,--,"{true, false}",Add option for transforming electricity into heat using resistive heaters (independently from gas boilers)
|
retrofitting,,,
|
||||||
oil_boilers,--,"{true, false}",Add option for transforming oil into heat using boilers
|
-- retro_endogen,--,"{true, false}",Add retrofitting as an endogenous system which co-optimise space heat savings.
|
||||||
biomass_boiler,--,"{true, false}",Add option for transforming biomass into heat using boilers
|
-- cost_factor,--,float,Weight costs for building renovation
|
||||||
overdimension_individual_heating,--,float,Add option for overdimensioning individual heating systems by a certain factor. This allows them to cover heat demand peaks e.g. 10% higher than those in the data with a setting of 1.1.
|
-- interest_rate,--,float,The interest rate for investment in building components
|
||||||
chp,--,"{true, false}",Add option for using Combined Heat and Power (CHP)
|
-- annualise_cost,--,"{true, false}",Annualise the investment costs of retrofitting
|
||||||
micro_chp,--,"{true, false}",Add option for using Combined Heat and Power (CHP) for decentral areas.
|
-- tax_weighting,--,"{true, false}",Weight the costs of retrofitting depending on taxes in countries
|
||||||
solar_thermal,--,"{true, false}",Add option for using solar thermal to generate heat.
|
-- construction_index,--,"{true, false}",Weight the costs of retrofitting depending on labour/material costs per country
|
||||||
solar_cf_correction,--,float,The correction factor for the value provided by the solar thermal profile calculations
|
tes,--,"{true, false}",Add option for storing thermal energy in large water pits associated with district heating systems and individual thermal energy storage (TES)
|
||||||
marginal_cost_storage,currency/MWh ,float,The marginal cost of discharging batteries in distributed grids
|
tes_tau,,,The time constant used to calculate the decay of thermal energy in thermal energy storage (TES): 1- :math:`e^{-1/24τ}`.
|
||||||
methanation,--,"{true, false}",Add option for transforming hydrogen and CO2 into methane using methanation.
|
-- decentral,days,float,The time constant in decentralized thermal energy storage (TES)
|
||||||
coal_cc,--,"{true, false}",Add option for coal CHPs with carbon capture
|
-- central,days,float,The time constant in centralized thermal energy storage (TES)
|
||||||
dac,--,"{true, false}",Add option for Direct Air Capture (DAC)
|
boilers,--,"{true, false}",Add option for transforming gas into heat using gas boilers
|
||||||
co2_vent,--,"{true, false}",Add option for vent out CO2 from storages to the atmosphere.
|
resistive_heaters,--,"{true, false}",Add option for transforming electricity into heat using resistive heaters (independently from gas boilers)
|
||||||
allam_cycle,--,"{true, false}",Add option to include `Allam cycle gas power plants <https://en.wikipedia.org/wiki/Allam_power_cycle>`_
|
oil_boilers,--,"{true, false}",Add option for transforming oil into heat using boilers
|
||||||
hydrogen_fuel_cell,--,"{true, false}",Add option to include hydrogen fuel cell for re-electrification. Assuming OCGT technology costs
|
biomass_boiler,--,"{true, false}",Add option for transforming biomass into heat using boilers
|
||||||
hydrogen_turbine,--,"{true, false}",Add option to include hydrogen turbine for re-electrification. Assuming OCGT technology costs
|
overdimension_individual_heating,--,float,Add option for overdimensioning individual heating systems by a certain factor. This allows them to cover heat demand peaks e.g. 10% higher than those in the data with a setting of 1.1.
|
||||||
SMR,--,"{true, false}",Add option for transforming natural gas into hydrogen and CO2 using Steam Methane Reforming (SMR)
|
chp,--,"{true, false}",Add option for using Combined Heat and Power (CHP)
|
||||||
SMR CC,--,"{true, false}",Add option for transforming natural gas into hydrogen and CO2 using Steam Methane Reforming (SMR) and Carbon Capture (CC)
|
micro_chp,--,"{true, false}",Add option for using Combined Heat and Power (CHP) for decentral areas.
|
||||||
regional_methanol_demand,--,"{true, false}",Spatially resolve methanol demand. Set to true if regional CO2 constraints needed.
|
solar_thermal,--,"{true, false}",Add option for using solar thermal to generate heat.
|
||||||
regional_oil_demand,--,"{true, false}",Spatially resolve oil demand. Set to true if regional CO2 constraints needed.
|
solar_cf_correction,--,float,The correction factor for the value provided by the solar thermal profile calculations
|
||||||
regional_co2 _sequestration_potential,,,
|
marginal_cost_storage,currency/MWh ,float,The marginal cost of discharging batteries in distributed grids
|
||||||
-- enable,--,"{true, false}",Add option for regionally-resolved geological carbon dioxide sequestration potentials based on `CO2StoP <https://setis.ec.europa.eu/european-co2-storage-database_en>`_.
|
methanation,--,"{true, false}",Add option for transforming hydrogen and CO2 into methane using methanation.
|
||||||
-- attribute,--,string or list,Name (or list of names) of the attribute(s) for the sequestration potential
|
coal_cc,--,"{true, false}",Add option for coal CHPs with carbon capture
|
||||||
-- include_onshore,--,"{true, false}",Add options for including onshore sequestration potentials
|
dac,--,"{true, false}",Add option for Direct Air Capture (DAC)
|
||||||
-- min_size,Gt ,float,Any sites with lower potential than this value will be excluded
|
co2_vent,--,"{true, false}",Add option for vent out CO2 from storages to the atmosphere.
|
||||||
-- max_size,Gt ,float,The maximum sequestration potential for any one site.
|
allam_cycle,--,"{true, false}",Add option to include `Allam cycle gas power plants <https://en.wikipedia.org/wiki/Allam_power_cycle>`_
|
||||||
-- years_of_storage,years,float,The years until potential exhausted at optimised annual rate
|
hydrogen_fuel_cell,--,"{true, false}",Add option to include hydrogen fuel cell for re-electrification. Assuming OCGT technology costs
|
||||||
co2_sequestration_potential,MtCO2/a,float,The potential of sequestering CO2 in Europe per year
|
hydrogen_turbine,--,"{true, false}",Add option to include hydrogen turbine for re-electrification. Assuming OCGT technology costs
|
||||||
co2_sequestration_cost,currency/tCO2,float,The cost of sequestering a ton of CO2
|
SMR,--,"{true, false}",Add option for transforming natural gas into hydrogen and CO2 using Steam Methane Reforming (SMR)
|
||||||
co2_sequestration_lifetime,years,int,The lifetime of a CO2 sequestration site
|
SMR CC,--,"{true, false}",Add option for transforming natural gas into hydrogen and CO2 using Steam Methane Reforming (SMR) and Carbon Capture (CC)
|
||||||
co2_spatial,--,"{true, false}","Add option to spatially resolve carrier representing stored carbon dioxide. This allows for more detailed modelling of CCUTS, e.g. regarding the capturing of industrial process emissions, usage as feedstock for electrofuels, transport of carbon dioxide, and geological sequestration sites."
|
regional_methanol_demand,--,"{true, false}",Spatially resolve methanol demand. Set to true if regional CO2 constraints needed.
|
||||||
,,,
|
regional_oil_demand,--,"{true, false}",Spatially resolve oil demand. Set to true if regional CO2 constraints needed.
|
||||||
co2network,--,"{true, false}",Add option for planning a new carbon dioxide transmission network
|
regional_co2 _sequestration_potential,,,
|
||||||
co2_network_cost_factor,p.u.,float,The cost factor for the capital cost of the carbon dioxide transmission network
|
-- enable,--,"{true, false}",Add option for regionally-resolved geological carbon dioxide sequestration potentials based on `CO2StoP <https://setis.ec.europa.eu/european-co2-storage-database_en>`_.
|
||||||
,,,
|
-- attribute,--,string or list,Name (or list of names) of the attribute(s) for the sequestration potential
|
||||||
cc_fraction,--,float,The default fraction of CO2 captured with post-combustion capture
|
-- include_onshore,--,"{true, false}",Add options for including onshore sequestration potentials
|
||||||
hydrogen_underground _storage,--,"{true, false}",Add options for storing hydrogen underground. Storage potential depends regionally.
|
-- min_size,Gt ,float,Any sites with lower potential than this value will be excluded
|
||||||
hydrogen_underground _storage_locations,,"{onshore, nearshore, offshore}","The location where hydrogen underground storage can be located. Onshore, nearshore, offshore means it must be located more than 50 km away from the sea, within 50 km of the sea, or within the sea itself respectively."
|
-- max_size,Gt ,float,The maximum sequestration potential for any one site.
|
||||||
,,,
|
-- years_of_storage,years,float,The years until potential exhausted at optimised annual rate
|
||||||
ammonia,--,"{true, false, regional}","Add ammonia as a carrrier. It can be either true (copperplated NH3), false (no NH3 carrier) or ""regional"" (regionalised NH3 without network)"
|
co2_sequestration_potential,MtCO2/a,float,The potential of sequestering CO2 in Europe per year
|
||||||
min_part_load_fischer _tropsch,per unit of p_nom ,float,The minimum unit dispatch (``p_min_pu``) for the Fischer-Tropsch process
|
co2_sequestration_cost,currency/tCO2,float,The cost of sequestering a ton of CO2
|
||||||
min_part_load _methanolisation,per unit of p_nom ,float,The minimum unit dispatch (``p_min_pu``) for the methanolisation process
|
co2_sequestration_lifetime,years,int,The lifetime of a CO2 sequestration site
|
||||||
,,,
|
co2_spatial,--,"{true, false}","Add option to spatially resolve carrier representing stored carbon dioxide. This allows for more detailed modelling of CCUTS, e.g. regarding the capturing of industrial process emissions, usage as feedstock for electrofuels, transport of carbon dioxide, and geological sequestration sites."
|
||||||
use_fischer_tropsch _waste_heat,--,"{true, false}",Add option for using waste heat of Fischer Tropsch in district heating networks
|
,,,
|
||||||
use_fuel_cell_waste_heat,--,"{true, false}",Add option for using waste heat of fuel cells in district heating networks
|
co2network,--,"{true, false}",Add option for planning a new carbon dioxide transmission network
|
||||||
use_electrolysis_waste _heat,--,"{true, false}",Add option for using waste heat of electrolysis in district heating networks
|
co2_network_cost_factor,p.u.,float,The cost factor for the capital cost of the carbon dioxide transmission network
|
||||||
electricity_transmission _grid,--,"{true, false}",Switch for enabling/disabling the electricity transmission grid.
|
,,,
|
||||||
electricity_distribution _grid,--,"{true, false}",Add a simplified representation of the exchange capacity between transmission and distribution grid level through a link.
|
cc_fraction,--,float,The default fraction of CO2 captured with post-combustion capture
|
||||||
electricity_distribution _grid_cost_factor,,,Multiplies the investment cost of the electricity distribution grid
|
hydrogen_underground _storage,--,"{true, false}",Add options for storing hydrogen underground. Storage potential depends regionally.
|
||||||
,,,
|
hydrogen_underground _storage_locations,,"{onshore, nearshore, offshore}","The location where hydrogen underground storage can be located. Onshore, nearshore, offshore means it must be located more than 50 km away from the sea, within 50 km of the sea, or within the sea itself respectively."
|
||||||
electricity_grid _connection,--,"{true, false}",Add the cost of electricity grid connection for onshore wind and solar
|
,,,
|
||||||
transmission_efficiency,,,Section to specify transmission losses or compression energy demands of bidirectional links. Splits them into two capacity-linked unidirectional links.
|
ammonia,--,"{true, false, regional}","Add ammonia as a carrrier. It can be either true (copperplated NH3), false (no NH3 carrier) or ""regional"" (regionalised NH3 without network)"
|
||||||
-- {carrier},--,str,The carrier of the link.
|
min_part_load_fischer _tropsch,per unit of p_nom ,float,The minimum unit dispatch (``p_min_pu``) for the Fischer-Tropsch process
|
||||||
-- -- efficiency_static,p.u.,float,Length-independent transmission efficiency.
|
min_part_load _methanolisation,per unit of p_nom ,float,The minimum unit dispatch (``p_min_pu``) for the methanolisation process
|
||||||
-- -- efficiency_per_1000km,p.u. per 1000 km,float,Length-dependent transmission efficiency ($\eta^{\text{length}}$)
|
,,,
|
||||||
-- -- compression_per_1000km,p.u. per 1000 km,float,Length-dependent electricity demand for compression ($\eta \cdot \text{length}$) implemented as multi-link to local electricity bus.
|
use_fischer_tropsch _waste_heat,--,"{true, false}",Add option for using waste heat of Fischer Tropsch in district heating networks
|
||||||
H2_network,--,"{true, false}",Add option for new hydrogen pipelines
|
use_fuel_cell_waste_heat,--,"{true, false}",Add option for using waste heat of fuel cells in district heating networks
|
||||||
gas_network,--,"{true, false}","Add existing natural gas infrastructure, incl. LNG terminals, production and entry-points. The existing gas network is added with a lossless transport model. A length-weighted `k-edge augmentation algorithm <https://networkx.org/documentation/stable/reference/algorithms/generated/networkx.algorithms.connectivity.edge_augmentation.k_edge_augmentation.html#networkx.algorithms.connectivity.edge_augmentation.k_edge_augmentation>`_ can be run to add new candidate gas pipelines such that all regions of the model can be connected to the gas network. When activated, all the gas demands are regionally disaggregated as well."
|
use_electrolysis_waste _heat,--,"{true, false}",Add option for using waste heat of electrolysis in district heating networks
|
||||||
H2_retrofit,--,"{true, false}",Add option for retrofiting existing pipelines to transport hydrogen.
|
electricity_transmission _grid,--,"{true, false}",Switch for enabling/disabling the electricity transmission grid.
|
||||||
H2_retrofit_capacity _per_CH4,--,float,"The ratio for H2 capacity per original CH4 capacity of retrofitted pipelines. The `European Hydrogen Backbone (April, 2020) p.15 <https://gasforclimate2050.eu/wp-content/uploads/2020/07/2020_European-Hydrogen-Backbone_Report.pdf>`_ 60% of original natural gas capacity could be used in cost-optimal case as H2 capacity."
|
electricity_distribution _grid,--,"{true, false}",Add a simplified representation of the exchange capacity between transmission and distribution grid level through a link.
|
||||||
gas_network_connectivity _upgrade ,--,float,The number of desired edge connectivity (k) in the length-weighted `k-edge augmentation algorithm <https://networkx.org/documentation/stable/reference/algorithms/generated/networkx.algorithms.connectivity.edge_augmentation.k_edge_augmentation.html#networkx.algorithms.connectivity.edge_augmentation.k_edge_augmentation>`_ used for the gas network
|
electricity_distribution _grid_cost_factor,,,Multiplies the investment cost of the electricity distribution grid
|
||||||
gas_distribution_grid,--,"{true, false}",Add a gas distribution grid
|
,,,
|
||||||
gas_distribution_grid _cost_factor,,,Multiplier for the investment cost of the gas distribution grid
|
electricity_grid _connection,--,"{true, false}",Add the cost of electricity grid connection for onshore wind and solar
|
||||||
,,,
|
transmission_efficiency,,,Section to specify transmission losses or compression energy demands of bidirectional links. Splits them into two capacity-linked unidirectional links.
|
||||||
biomass_spatial,--,"{true, false}",Add option for resolving biomass demand regionally
|
-- {carrier},--,str,The carrier of the link.
|
||||||
biomass_transport,--,"{true, false}",Add option for transporting solid biomass between nodes
|
-- -- efficiency_static,p.u.,float,Length-independent transmission efficiency.
|
||||||
biogas_upgrading_cc,--,"{true, false}",Add option to capture CO2 from biomass upgrading
|
-- -- efficiency_per_1000km,p.u. per 1000 km,float,Length-dependent transmission efficiency ($\eta^{\text{length}}$)
|
||||||
conventional_generation,,,Add a more detailed description of conventional carriers. Any power generation requires the consumption of fuel from nodes representing that fuel.
|
-- -- compression_per_1000km,p.u. per 1000 km,float,Length-dependent electricity demand for compression ($\eta \cdot \text{length}$) implemented as multi-link to local electricity bus.
|
||||||
biomass_to_liquid,--,"{true, false}",Add option for transforming solid biomass into liquid fuel with the same properties as oil
|
H2_network,--,"{true, false}",Add option for new hydrogen pipelines
|
||||||
biosng,--,"{true, false}",Add option for transforming solid biomass into synthesis gas with the same properties as natural gas
|
gas_network,--,"{true, false}","Add existing natural gas infrastructure, incl. LNG terminals, production and entry-points. The existing gas network is added with a lossless transport model. A length-weighted `k-edge augmentation algorithm <https://networkx.org/documentation/stable/reference/algorithms/generated/networkx.algorithms.connectivity.edge_augmentation.k_edge_augmentation.html#networkx.algorithms.connectivity.edge_augmentation.k_edge_augmentation>`_ can be run to add new candidate gas pipelines such that all regions of the model can be connected to the gas network. When activated, all the gas demands are regionally disaggregated as well."
|
||||||
limit_max_growth,,,
|
H2_retrofit,--,"{true, false}",Add option for retrofiting existing pipelines to transport hydrogen.
|
||||||
-- enable,--,"{true, false}",Add option to limit the maximum growth of a carrier
|
H2_retrofit_capacity _per_CH4,--,float,"The ratio for H2 capacity per original CH4 capacity of retrofitted pipelines. The `European Hydrogen Backbone (April, 2020) p.15 <https://gasforclimate2050.eu/wp-content/uploads/2020/07/2020_European-Hydrogen-Backbone_Report.pdf>`_ 60% of original natural gas capacity could be used in cost-optimal case as H2 capacity."
|
||||||
-- factor,p.u.,float,The maximum growth factor of a carrier (e.g. 1.3 allows 30% larger than max historic growth)
|
gas_network_connectivity _upgrade ,--,float,The number of desired edge connectivity (k) in the length-weighted `k-edge augmentation algorithm <https://networkx.org/documentation/stable/reference/algorithms/generated/networkx.algorithms.connectivity.edge_augmentation.k_edge_augmentation.html#networkx.algorithms.connectivity.edge_augmentation.k_edge_augmentation>`_ used for the gas network
|
||||||
-- max_growth,,,
|
gas_distribution_grid,--,"{true, false}",Add a gas distribution grid
|
||||||
-- -- {carrier},GW,float,The historic maximum growth of a carrier
|
gas_distribution_grid _cost_factor,,,Multiplier for the investment cost of the gas distribution grid
|
||||||
-- max_relative_growth,,,
|
,,,
|
||||||
-- -- {carrier},p.u.,float,The historic maximum relative growth of a carrier
|
biomass_spatial,--,"{true, false}",Add option for resolving biomass demand regionally
|
||||||
,,,
|
biomass_transport,--,"{true, false}",Add option for transporting solid biomass between nodes
|
||||||
enhanced_geothermal,,,
|
biogas_upgrading_cc,--,"{true, false}",Add option to capture CO2 from biomass upgrading
|
||||||
-- enable,--,"{true, false}",Add option to include Enhanced Geothermal Systems
|
conventional_generation,,,Add a more detailed description of conventional carriers. Any power generation requires the consumption of fuel from nodes representing that fuel.
|
||||||
-- flexible,--,"{true, false}",Add option for flexible operation (see Ricks et al. 2024)
|
biomass_to_liquid,--,"{true, false}",Add option for transforming solid biomass into liquid fuel with the same properties as oil
|
||||||
-- max_hours,--,int,The maximum hours the reservoir can be charged under flexible operation
|
biosng,--,"{true, false}",Add option for transforming solid biomass into synthesis gas with the same properties as natural gas
|
||||||
-- max_boost,--,float,The maximum boost in power output under flexible operation
|
municipal_solid_waste,--,"{true, false}",Add option for municipal solid waste
|
||||||
-- var_cf,--,"{true, false}",Add option for variable capacity factor (see Ricks et al. 2024)
|
limit_max_growth,,,
|
||||||
-- sustainability_factor,--,float,Share of sourced heat that is replenished by the earth's core (see details in `build_egs_potentials.py <https://github.com/PyPSA/pypsa-eur-sec/blob/master/scripts/build_egs_potentials.py>`_)
|
-- enable,--,"{true, false}",Add option to limit the maximum growth of a carrier
|
||||||
|
-- factor,p.u.,float,The maximum growth factor of a carrier (e.g. 1.3 allows 30% larger than max historic growth)
|
||||||
|
-- max_growth,,,
|
||||||
|
-- -- {carrier},GW,float,The historic maximum growth of a carrier
|
||||||
|
-- max_relative_growth,,,
|
||||||
|
-- -- {carrier},p.u.,float,The historic maximum relative growth of a carrier
|
||||||
|
,,,
|
||||||
|
enhanced_geothermal,,,
|
||||||
|
-- enable,--,"{true, false}",Add option to include Enhanced Geothermal Systems
|
||||||
|
-- flexible,--,"{true, false}",Add option for flexible operation (see Ricks et al. 2024)
|
||||||
|
-- max_hours,--,int,The maximum hours the reservoir can be charged under flexible operation
|
||||||
|
-- max_boost,--,float,The maximum boost in power output under flexible operation
|
||||||
|
-- var_cf,--,"{true, false}",Add option for variable capacity factor (see Ricks et al. 2024)
|
||||||
|
-- sustainability_factor,--,float,Share of sourced heat that is replenished by the earth's core (see details in `build_egs_potentials.py <https://github.com/PyPSA/pypsa-eur-sec/blob/master/scripts/build_egs_potentials.py>`_)
|
||||||
|
solid_biomass_import,,,
|
||||||
|
-- enable,--,"{true, false}",Add option to include solid biomass imports
|
||||||
|
-- price,currency/MWh,float,Price for importing solid biomass
|
||||||
|
-- max_amount,Twh,float,Maximum solid biomass import potential
|
||||||
|
-- upstream_emissions_factor,p.u.,float,Upstream emissions of solid biomass imports
|
||||||
|
|
@ -242,7 +242,7 @@ Rule overview
|
|||||||
file
|
file
|
||||||
<https://pypsa-eur.readthedocs.io/en/latest/preparation/build_powerplants.html?highlight=powerplants>`__
|
<https://pypsa-eur.readthedocs.io/en/latest/preparation/build_powerplants.html?highlight=powerplants>`__
|
||||||
generated by pypsa-eur which, in turn, is based on the `powerplantmatching
|
generated by pypsa-eur which, in turn, is based on the `powerplantmatching
|
||||||
<https://github.com/FRESNA/powerplantmatching>`__ database.
|
<https://github.com/PyPSA/powerplantmatching>`__ database.
|
||||||
|
|
||||||
Existing wind and solar capacities are retrieved from `IRENA annual statistics
|
Existing wind and solar capacities are retrieved from `IRENA annual statistics
|
||||||
<https://www.irena.org/Statistics/Download-Data>`__ and distributed among the
|
<https://www.irena.org/Statistics/Download-Data>`__ and distributed among the
|
||||||
|
@ -25,7 +25,7 @@ With these and the externally extracted ENTSO-E online map topology
|
|||||||
|
|
||||||
Then the process continues by calculating conventional power plant capacities, potentials, and per-unit availability time series for variable renewable energy carriers and hydro power plants with the following rules:
|
Then the process continues by calculating conventional power plant capacities, potentials, and per-unit availability time series for variable renewable energy carriers and hydro power plants with the following rules:
|
||||||
|
|
||||||
- :mod:`build_powerplants` for today's thermal power plant capacities using `powerplantmatching <https://github.com/FRESNA/powerplantmatching>`__ allocating these to the closest substation for each powerplant,
|
- :mod:`build_powerplants` for today's thermal power plant capacities using `powerplantmatching <https://github.com/PyPSA/powerplantmatching>`__ allocating these to the closest substation for each powerplant,
|
||||||
- :mod:`build_ship_raster` for building shipping traffic density,
|
- :mod:`build_ship_raster` for building shipping traffic density,
|
||||||
- :mod:`build_renewable_profiles` for the hourly capacity factors and installation potentials constrained by land-use in each substation's Voronoi cell for PV, onshore and offshore wind, and
|
- :mod:`build_renewable_profiles` for the hourly capacity factors and installation potentials constrained by land-use in each substation's Voronoi cell for PV, onshore and offshore wind, and
|
||||||
- :mod:`build_hydro_profile` for the hourly per-unit hydro power availability time series.
|
- :mod:`build_hydro_profile` for the hourly per-unit hydro power availability time series.
|
||||||
|
@ -10,6 +10,14 @@ Release Notes
|
|||||||
Upcoming Release
|
Upcoming Release
|
||||||
================
|
================
|
||||||
|
|
||||||
|
* Changed heat pump COP approximation for central heating to be based on `Jensen et al. (2018) <https://backend.orbit.dtu.dk/ws/portalfiles/portal/151965635/MAIN_Final.pdf>`__ and a default forward temperature of 90C. This is more realistic for district heating than the previously used approximation method.
|
||||||
|
|
||||||
|
* split solid biomass potentials into solid biomass and municipal solid waste. Add option to use municipal solid waste. This option is only activated in combination with the flag ``waste_to_energy``
|
||||||
|
|
||||||
|
* Add option to import solid biomass
|
||||||
|
|
||||||
|
* Add option to produce electrobiofuels (flag ``electrobiofuels``) from solid biomass and hydrogen, as a combination of BtL and Fischer-Tropsch to make more use of the biogenic carbon
|
||||||
|
|
||||||
* Add flag ``sector: fossil_fuels`` in config to remove the option of importing fossil fuels
|
* Add flag ``sector: fossil_fuels`` in config to remove the option of importing fossil fuels
|
||||||
|
|
||||||
* Renamed the carrier of batteries in BEVs from `battery storage` to `EV battery` and the corresponding bus carrier from `Li ion` to `EV battery`. This is to avoid confusion with stationary battery storage.
|
* Renamed the carrier of batteries in BEVs from `battery storage` to `EV battery` and the corresponding bus carrier from `Li ion` to `EV battery`. This is to avoid confusion with stationary battery storage.
|
||||||
|
@ -217,13 +217,27 @@ rule build_temperature_profiles:
|
|||||||
|
|
||||||
rule build_cop_profiles:
|
rule build_cop_profiles:
|
||||||
params:
|
params:
|
||||||
heat_pump_sink_T=config_provider("sector", "heat_pump_sink_T"),
|
heat_pump_sink_T_decentral_heating=config_provider(
|
||||||
|
"sector", "heat_pump_sink_T_individual_heating"
|
||||||
|
),
|
||||||
|
forward_temperature_central_heating=config_provider(
|
||||||
|
"sector", "district_heating", "forward_temperature"
|
||||||
|
),
|
||||||
|
return_temperature_central_heating=config_provider(
|
||||||
|
"sector", "district_heating", "return_temperature"
|
||||||
|
),
|
||||||
|
heat_source_cooling_central_heating=config_provider(
|
||||||
|
"sector", "district_heating", "heat_source_cooling"
|
||||||
|
),
|
||||||
|
heat_pump_cop_approximation_central_heating=config_provider(
|
||||||
|
"sector", "district_heating", "heat_pump_cop_approximation"
|
||||||
|
),
|
||||||
|
heat_pump_sources=config_provider("sector", "heat_pump_sources"),
|
||||||
input:
|
input:
|
||||||
temp_soil_total=resources("temp_soil_total_elec_s{simpl}_{clusters}.nc"),
|
temp_soil_total=resources("temp_soil_total_elec_s{simpl}_{clusters}.nc"),
|
||||||
temp_air_total=resources("temp_air_total_elec_s{simpl}_{clusters}.nc"),
|
temp_air_total=resources("temp_air_total_elec_s{simpl}_{clusters}.nc"),
|
||||||
output:
|
output:
|
||||||
cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"),
|
cop_profiles=resources("cop_profiles_elec_s{simpl}_{clusters}.nc"),
|
||||||
cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"),
|
|
||||||
resources:
|
resources:
|
||||||
mem_mb=20000,
|
mem_mb=20000,
|
||||||
log:
|
log:
|
||||||
@ -233,7 +247,7 @@ rule build_cop_profiles:
|
|||||||
conda:
|
conda:
|
||||||
"../envs/environment.yaml"
|
"../envs/environment.yaml"
|
||||||
script:
|
script:
|
||||||
"../scripts/build_cop_profiles.py"
|
"../scripts/build_cop_profiles/run.py"
|
||||||
|
|
||||||
|
|
||||||
def solar_thermal_cutout(wildcards):
|
def solar_thermal_cutout(wildcards):
|
||||||
@ -941,6 +955,8 @@ rule prepare_sector_network:
|
|||||||
adjustments=config_provider("adjustments", "sector"),
|
adjustments=config_provider("adjustments", "sector"),
|
||||||
emissions_scope=config_provider("energy", "emissions"),
|
emissions_scope=config_provider("energy", "emissions"),
|
||||||
RDIR=RDIR,
|
RDIR=RDIR,
|
||||||
|
heat_pump_sources=config_provider("sector", "heat_pump_sources"),
|
||||||
|
heat_systems=config_provider("sector", "heat_systems"),
|
||||||
input:
|
input:
|
||||||
unpack(input_profile_offwind),
|
unpack(input_profile_offwind),
|
||||||
**rules.cluster_gas_network.output,
|
**rules.cluster_gas_network.output,
|
||||||
@ -1017,8 +1033,7 @@ rule prepare_sector_network:
|
|||||||
),
|
),
|
||||||
temp_soil_total=resources("temp_soil_total_elec_s{simpl}_{clusters}.nc"),
|
temp_soil_total=resources("temp_soil_total_elec_s{simpl}_{clusters}.nc"),
|
||||||
temp_air_total=resources("temp_air_total_elec_s{simpl}_{clusters}.nc"),
|
temp_air_total=resources("temp_air_total_elec_s{simpl}_{clusters}.nc"),
|
||||||
cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"),
|
cop_profiles=resources("cop_profiles_elec_s{simpl}_{clusters}.nc"),
|
||||||
cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"),
|
|
||||||
solar_thermal_total=lambda w: (
|
solar_thermal_total=lambda w: (
|
||||||
resources("solar_thermal_total_elec_s{simpl}_{clusters}.nc")
|
resources("solar_thermal_total_elec_s{simpl}_{clusters}.nc")
|
||||||
if config_provider("sector", "solar_thermal")(w)
|
if config_provider("sector", "solar_thermal")(w)
|
||||||
|
@ -53,6 +53,8 @@ if config["enable"]["retrieve"] and config["enable"].get("retrieve_databundle",
|
|||||||
log:
|
log:
|
||||||
"logs/retrieve_eurostat_data.log",
|
"logs/retrieve_eurostat_data.log",
|
||||||
retries: 2
|
retries: 2
|
||||||
|
conda:
|
||||||
|
"../envs/retrieve.yaml"
|
||||||
script:
|
script:
|
||||||
"../scripts/retrieve_eurostat_data.py"
|
"../scripts/retrieve_eurostat_data.py"
|
||||||
|
|
||||||
@ -62,6 +64,8 @@ if config["enable"]["retrieve"] and config["enable"].get("retrieve_databundle",
|
|||||||
log:
|
log:
|
||||||
"logs/retrieve_eurostat_household_data.log",
|
"logs/retrieve_eurostat_household_data.log",
|
||||||
retries: 2
|
retries: 2
|
||||||
|
conda:
|
||||||
|
"../envs/retrieve.yaml"
|
||||||
script:
|
script:
|
||||||
"../scripts/retrieve_eurostat_household_data.py"
|
"../scripts/retrieve_eurostat_household_data.py"
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ rule add_existing_baseyear:
|
|||||||
sector=config_provider("sector"),
|
sector=config_provider("sector"),
|
||||||
existing_capacities=config_provider("existing_capacities"),
|
existing_capacities=config_provider("existing_capacities"),
|
||||||
costs=config_provider("costs"),
|
costs=config_provider("costs"),
|
||||||
|
heat_pump_sources=config_provider("sector", "heat_pump_sources"),
|
||||||
input:
|
input:
|
||||||
network=RESULTS
|
network=RESULTS
|
||||||
+ "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc",
|
+ "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc",
|
||||||
@ -21,8 +22,7 @@ rule add_existing_baseyear:
|
|||||||
config_provider("scenario", "planning_horizons", 0)(w)
|
config_provider("scenario", "planning_horizons", 0)(w)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"),
|
cop_profiles=resources("cop_profiles_elec_s{simpl}_{clusters}.nc"),
|
||||||
cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"),
|
|
||||||
existing_heating_distribution=resources(
|
existing_heating_distribution=resources(
|
||||||
"existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv"
|
"existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv"
|
||||||
),
|
),
|
||||||
@ -69,6 +69,7 @@ rule add_brownfield:
|
|||||||
snapshots=config_provider("snapshots"),
|
snapshots=config_provider("snapshots"),
|
||||||
drop_leap_day=config_provider("enable", "drop_leap_day"),
|
drop_leap_day=config_provider("enable", "drop_leap_day"),
|
||||||
carriers=config_provider("electricity", "renewable_carriers"),
|
carriers=config_provider("electricity", "renewable_carriers"),
|
||||||
|
heat_pump_sources=config_provider("sector", "heat_pump_sources"),
|
||||||
input:
|
input:
|
||||||
unpack(input_profile_tech_brownfield),
|
unpack(input_profile_tech_brownfield),
|
||||||
simplify_busmap=resources("busmap_elec_s{simpl}.csv"),
|
simplify_busmap=resources("busmap_elec_s{simpl}.csv"),
|
||||||
@ -77,8 +78,7 @@ rule add_brownfield:
|
|||||||
+ "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc",
|
+ "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc",
|
||||||
network_p=solved_previous_horizon, #solved network at previous time step
|
network_p=solved_previous_horizon, #solved network at previous time step
|
||||||
costs=resources("costs_{planning_horizons}.csv"),
|
costs=resources("costs_{planning_horizons}.csv"),
|
||||||
cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"),
|
cop_profiles=resources("cop_profiles_elec_s{simpl}_{clusters}.nc"),
|
||||||
cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"),
|
|
||||||
output:
|
output:
|
||||||
RESULTS
|
RESULTS
|
||||||
+ "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc",
|
+ "prenetworks-brownfield/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc",
|
||||||
|
@ -7,6 +7,7 @@ rule add_existing_baseyear:
|
|||||||
sector=config_provider("sector"),
|
sector=config_provider("sector"),
|
||||||
existing_capacities=config_provider("existing_capacities"),
|
existing_capacities=config_provider("existing_capacities"),
|
||||||
costs=config_provider("costs"),
|
costs=config_provider("costs"),
|
||||||
|
heat_pump_sources=config_provider("sector", "heat_pump_sources"),
|
||||||
input:
|
input:
|
||||||
network=RESULTS
|
network=RESULTS
|
||||||
+ "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc",
|
+ "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc",
|
||||||
@ -19,8 +20,7 @@ rule add_existing_baseyear:
|
|||||||
config_provider("scenario", "planning_horizons", 0)(w)
|
config_provider("scenario", "planning_horizons", 0)(w)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
cop_soil_total=resources("cop_soil_total_elec_s{simpl}_{clusters}.nc"),
|
cop_profiles=resources("cop_profiles_elec_s{simpl}_{clusters}.nc"),
|
||||||
cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"),
|
|
||||||
existing_heating_distribution=resources(
|
existing_heating_distribution=resources(
|
||||||
"existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv"
|
"existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv"
|
||||||
),
|
),
|
||||||
|
@ -24,6 +24,10 @@ from _helpers import (
|
|||||||
from add_electricity import sanitize_carriers
|
from add_electricity import sanitize_carriers
|
||||||
from prepare_sector_network import cluster_heat_buses, define_spatial, prepare_costs
|
from prepare_sector_network import cluster_heat_buses, define_spatial, prepare_costs
|
||||||
|
|
||||||
|
from scripts.definitions.heat_sector import HeatSector
|
||||||
|
from scripts.definitions.heat_system import HeatSystem
|
||||||
|
from scripts.definitions.heat_system_type import HeatSystemType
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
cc = coco.CountryConverter()
|
cc = coco.CountryConverter()
|
||||||
idx = pd.IndexSlice
|
idx = pd.IndexSlice
|
||||||
@ -416,14 +420,14 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas
|
|||||||
|
|
||||||
|
|
||||||
def add_heating_capacities_installed_before_baseyear(
|
def add_heating_capacities_installed_before_baseyear(
|
||||||
n,
|
n: pypsa.Network,
|
||||||
baseyear,
|
baseyear: int,
|
||||||
grouping_years,
|
grouping_years: list,
|
||||||
ashp_cop,
|
cop: dict,
|
||||||
gshp_cop,
|
time_dep_hp_cop: bool,
|
||||||
time_dep_hp_cop,
|
costs: pd.DataFrame,
|
||||||
costs,
|
default_lifetime: int,
|
||||||
default_lifetime,
|
existing_heating: pd.DataFrame,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Parameters
|
Parameters
|
||||||
@ -435,141 +439,158 @@ def add_heating_capacities_installed_before_baseyear(
|
|||||||
currently assumed heating capacities split between residential and
|
currently assumed heating capacities split between residential and
|
||||||
services proportional to heating load in both 50% capacities
|
services proportional to heating load in both 50% capacities
|
||||||
in rural buses 50% in urban buses
|
in rural buses 50% in urban buses
|
||||||
|
cop: xr.DataArray
|
||||||
|
DataArray with time-dependent coefficients of performance (COPs) heat pumps. Coordinates are heat sources (see config), heat system types (see :file:`scripts/enums/HeatSystemType.py`), nodes and snapshots.
|
||||||
|
time_dep_hp_cop: bool
|
||||||
|
If True, time-dependent (dynamic) COPs are used for heat pumps
|
||||||
"""
|
"""
|
||||||
logger.debug(f"Adding heating capacities installed before {baseyear}")
|
logger.debug(f"Adding heating capacities installed before {baseyear}")
|
||||||
|
|
||||||
existing_heating = pd.read_csv(
|
for heat_system in existing_heating.columns.get_level_values(0).unique():
|
||||||
snakemake.input.existing_heating_distribution, header=[0, 1], index_col=0
|
heat_system = HeatSystem(heat_system)
|
||||||
)
|
|
||||||
|
|
||||||
for name in existing_heating.columns.get_level_values(0).unique():
|
nodes = pd.Index(
|
||||||
name_type = "central" if name == "urban central" else "decentral"
|
n.buses.location[n.buses.index.str.contains(f"{heat_system} heat")]
|
||||||
|
)
|
||||||
|
|
||||||
nodes = pd.Index(n.buses.location[n.buses.index.str.contains(f"{name} heat")])
|
if (not heat_system == HeatSystem.URBAN_CENTRAL) and options[
|
||||||
|
"electricity_distribution_grid"
|
||||||
if (name_type != "central") and options["electricity_distribution_grid"]:
|
]:
|
||||||
nodes_elec = nodes + " low voltage"
|
nodes_elec = nodes + " low voltage"
|
||||||
else:
|
else:
|
||||||
nodes_elec = nodes
|
nodes_elec = nodes
|
||||||
|
|
||||||
heat_pump_type = "air" if "urban" in name else "ground"
|
too_large_grouping_years = [
|
||||||
|
gy for gy in grouping_years if gy >= int(baseyear)
|
||||||
# Add heat pumps
|
|
||||||
costs_name = f"decentral {heat_pump_type}-sourced heat pump"
|
|
||||||
|
|
||||||
cop = {"air": ashp_cop, "ground": gshp_cop}
|
|
||||||
|
|
||||||
if time_dep_hp_cop:
|
|
||||||
efficiency = cop[heat_pump_type][nodes]
|
|
||||||
else:
|
|
||||||
efficiency = costs.at[costs_name, "efficiency"]
|
|
||||||
|
|
||||||
too_large_grouping_years = [gy for gy in grouping_years if gy >= int(baseyear)]
|
|
||||||
if too_large_grouping_years:
|
|
||||||
logger.warning(
|
|
||||||
f"Grouping years >= baseyear are ignored. Dropping {too_large_grouping_years}."
|
|
||||||
)
|
|
||||||
valid_grouping_years = pd.Series(
|
|
||||||
[
|
|
||||||
int(grouping_year)
|
|
||||||
for grouping_year in grouping_years
|
|
||||||
if int(grouping_year) + default_lifetime > int(baseyear)
|
|
||||||
and int(grouping_year) < int(baseyear)
|
|
||||||
]
|
]
|
||||||
)
|
if too_large_grouping_years:
|
||||||
|
logger.warning(
|
||||||
|
f"Grouping years >= baseyear are ignored. Dropping {too_large_grouping_years}."
|
||||||
|
)
|
||||||
|
valid_grouping_years = pd.Series(
|
||||||
|
[
|
||||||
|
int(grouping_year)
|
||||||
|
for grouping_year in grouping_years
|
||||||
|
if int(grouping_year) + default_lifetime > int(baseyear)
|
||||||
|
and int(grouping_year) < int(baseyear)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
assert valid_grouping_years.is_monotonic_increasing
|
assert valid_grouping_years.is_monotonic_increasing
|
||||||
|
|
||||||
# get number of years of each interval
|
# get number of years of each interval
|
||||||
_years = valid_grouping_years.diff()
|
_years = valid_grouping_years.diff()
|
||||||
# Fill NA from .diff() with value for the first interval
|
# Fill NA from .diff() with value for the first interval
|
||||||
_years[0] = valid_grouping_years[0] - baseyear + default_lifetime
|
_years[0] = valid_grouping_years[0] - baseyear + default_lifetime
|
||||||
# Installation is assumed to be linear for the past
|
# Installation is assumed to be linear for the past
|
||||||
ratios = _years / _years.sum()
|
ratios = _years / _years.sum()
|
||||||
|
|
||||||
for ratio, grouping_year in zip(ratios, valid_grouping_years):
|
for ratio, grouping_year in zip(ratios, valid_grouping_years):
|
||||||
|
# Add heat pumps
|
||||||
|
for heat_source in snakemake.params.heat_pump_sources[
|
||||||
|
heat_system.system_type.value
|
||||||
|
]:
|
||||||
|
costs_name = heat_system.heat_pump_costs_name(heat_source)
|
||||||
|
|
||||||
n.madd(
|
efficiency = (
|
||||||
"Link",
|
cop.sel(
|
||||||
nodes,
|
heat_system=heat_system.system_type.value,
|
||||||
suffix=f" {name} {heat_pump_type} heat pump-{grouping_year}",
|
heat_source=heat_source,
|
||||||
bus0=nodes_elec,
|
name=nodes,
|
||||||
bus1=nodes + " " + name + " heat",
|
)
|
||||||
carrier=f"{name} {heat_pump_type} heat pump",
|
.to_pandas()
|
||||||
efficiency=efficiency,
|
.reindex(index=n.snapshots)
|
||||||
capital_cost=costs.at[costs_name, "efficiency"]
|
if time_dep_hp_cop
|
||||||
* costs.at[costs_name, "fixed"],
|
else costs.at[costs_name, "efficiency"]
|
||||||
p_nom=existing_heating.loc[nodes, (name, f"{heat_pump_type} heat pump")]
|
)
|
||||||
* ratio
|
|
||||||
/ costs.at[costs_name, "efficiency"],
|
n.madd(
|
||||||
build_year=int(grouping_year),
|
"Link",
|
||||||
lifetime=costs.at[costs_name, "lifetime"],
|
nodes,
|
||||||
)
|
suffix=f" {heat_system} {heat_source} heat pump-{grouping_year}",
|
||||||
|
bus0=nodes_elec,
|
||||||
|
bus1=nodes + " " + heat_system.value + " heat",
|
||||||
|
carrier=f"{heat_system} {heat_source} heat pump",
|
||||||
|
efficiency=efficiency,
|
||||||
|
capital_cost=costs.at[costs_name, "efficiency"]
|
||||||
|
* costs.at[costs_name, "fixed"],
|
||||||
|
p_nom=existing_heating.loc[
|
||||||
|
nodes, (heat_system.value, f"{heat_source} heat pump")
|
||||||
|
]
|
||||||
|
* ratio
|
||||||
|
/ costs.at[costs_name, "efficiency"],
|
||||||
|
build_year=int(grouping_year),
|
||||||
|
lifetime=costs.at[costs_name, "lifetime"],
|
||||||
|
)
|
||||||
|
|
||||||
# add resistive heater, gas boilers and oil boilers
|
# add resistive heater, gas boilers and oil boilers
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
nodes,
|
nodes,
|
||||||
suffix=f" {name} resistive heater-{grouping_year}",
|
suffix=f" {heat_system} resistive heater-{grouping_year}",
|
||||||
bus0=nodes_elec,
|
bus0=nodes_elec,
|
||||||
bus1=nodes + " " + name + " heat",
|
bus1=nodes + " " + heat_system.value + " heat",
|
||||||
carrier=name + " resistive heater",
|
carrier=heat_system.value + " resistive heater",
|
||||||
efficiency=costs.at[f"{name_type} resistive heater", "efficiency"],
|
efficiency=costs.at[
|
||||||
|
heat_system.resistive_heater_costs_name, "efficiency"
|
||||||
|
],
|
||||||
capital_cost=(
|
capital_cost=(
|
||||||
costs.at[f"{name_type} resistive heater", "efficiency"]
|
costs.at[heat_system.resistive_heater_costs_name, "efficiency"]
|
||||||
* costs.at[f"{name_type} resistive heater", "fixed"]
|
* costs.at[heat_system.resistive_heater_costs_name, "fixed"]
|
||||||
),
|
),
|
||||||
p_nom=(
|
p_nom=(
|
||||||
existing_heating.loc[nodes, (name, "resistive heater")]
|
existing_heating.loc[nodes, (heat_system.value, "resistive heater")]
|
||||||
* ratio
|
* ratio
|
||||||
/ costs.at[f"{name_type} resistive heater", "efficiency"]
|
/ costs.at[heat_system.resistive_heater_costs_name, "efficiency"]
|
||||||
),
|
),
|
||||||
build_year=int(grouping_year),
|
build_year=int(grouping_year),
|
||||||
lifetime=costs.at[f"{name_type} resistive heater", "lifetime"],
|
lifetime=costs.at[heat_system.resistive_heater_costs_name, "lifetime"],
|
||||||
)
|
)
|
||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
nodes,
|
nodes,
|
||||||
suffix=f" {name} gas boiler-{grouping_year}",
|
suffix=f"{heat_system} gas boiler-{grouping_year}",
|
||||||
bus0="EU gas" if "EU gas" in spatial.gas.nodes else nodes + " gas",
|
bus0="EU gas" if "EU gas" in spatial.gas.nodes else nodes + " gas",
|
||||||
bus1=nodes + " " + name + " heat",
|
bus1=nodes + " " + heat_system.value + " heat",
|
||||||
bus2="co2 atmosphere",
|
bus2="co2 atmosphere",
|
||||||
carrier=name + " gas boiler",
|
carrier=heat_system.value + " gas boiler",
|
||||||
efficiency=costs.at[f"{name_type} gas boiler", "efficiency"],
|
efficiency=costs.at[heat_system.gas_boiler_costs_name, "efficiency"],
|
||||||
efficiency2=costs.at["gas", "CO2 intensity"],
|
efficiency2=costs.at["gas", "CO2 intensity"],
|
||||||
capital_cost=(
|
capital_cost=(
|
||||||
costs.at[f"{name_type} gas boiler", "efficiency"]
|
costs.at[heat_system.gas_boiler_costs_name, "efficiency"]
|
||||||
* costs.at[f"{name_type} gas boiler", "fixed"]
|
* costs.at[heat_system.gas_boiler_costs_name, "fixed"]
|
||||||
),
|
),
|
||||||
p_nom=(
|
p_nom=(
|
||||||
existing_heating.loc[nodes, (name, "gas boiler")]
|
existing_heating.loc[nodes, (heat_system.value, "gas boiler")]
|
||||||
* ratio
|
* ratio
|
||||||
/ costs.at[f"{name_type} gas boiler", "efficiency"]
|
/ costs.at[heat_system.gas_boiler_costs_name, "efficiency"]
|
||||||
),
|
),
|
||||||
build_year=int(grouping_year),
|
build_year=int(grouping_year),
|
||||||
lifetime=costs.at[f"{name_type} gas boiler", "lifetime"],
|
lifetime=costs.at[heat_system.gas_boiler_costs_name, "lifetime"],
|
||||||
)
|
)
|
||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
nodes,
|
nodes,
|
||||||
suffix=f" {name} oil boiler-{grouping_year}",
|
suffix=f" {heat_system} oil boiler-{grouping_year}",
|
||||||
bus0=spatial.oil.nodes,
|
bus0=spatial.oil.nodes,
|
||||||
bus1=nodes + " " + name + " heat",
|
bus1=nodes + " " + heat_system.value + " heat",
|
||||||
bus2="co2 atmosphere",
|
bus2="co2 atmosphere",
|
||||||
carrier=name + " oil boiler",
|
carrier=heat_system.value + " oil boiler",
|
||||||
efficiency=costs.at["decentral oil boiler", "efficiency"],
|
efficiency=costs.at[heat_system.oil_boiler_costs_name, "efficiency"],
|
||||||
efficiency2=costs.at["oil", "CO2 intensity"],
|
efficiency2=costs.at["oil", "CO2 intensity"],
|
||||||
capital_cost=costs.at["decentral oil boiler", "efficiency"]
|
capital_cost=costs.at[heat_system.oil_boiler_costs_name, "efficiency"]
|
||||||
* costs.at["decentral oil boiler", "fixed"],
|
* costs.at[heat_system.oil_boiler_costs_name, "fixed"],
|
||||||
p_nom=(
|
p_nom=(
|
||||||
existing_heating.loc[nodes, (name, "oil boiler")]
|
existing_heating.loc[nodes, (heat_system.value, "oil boiler")]
|
||||||
* ratio
|
* ratio
|
||||||
/ costs.at["decentral oil boiler", "efficiency"]
|
/ costs.at[heat_system.oil_boiler_costs_name, "efficiency"]
|
||||||
),
|
),
|
||||||
build_year=int(grouping_year),
|
build_year=int(grouping_year),
|
||||||
lifetime=costs.at[f"{name_type} gas boiler", "lifetime"],
|
lifetime=costs.at[
|
||||||
|
f"{heat_system.central_or_decentral} gas boiler", "lifetime"
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
# delete links with p_nom=nan corresponding to extra nodes in country
|
# delete links with p_nom=nan corresponding to extra nodes in country
|
||||||
@ -639,29 +660,22 @@ if __name__ == "__main__":
|
|||||||
)
|
)
|
||||||
|
|
||||||
if options["heating"]:
|
if options["heating"]:
|
||||||
time_dep_hp_cop = options["time_dep_hp_cop"]
|
|
||||||
ashp_cop = (
|
|
||||||
xr.open_dataarray(snakemake.input.cop_air_total)
|
|
||||||
.to_pandas()
|
|
||||||
.reindex(index=n.snapshots)
|
|
||||||
)
|
|
||||||
gshp_cop = (
|
|
||||||
xr.open_dataarray(snakemake.input.cop_soil_total)
|
|
||||||
.to_pandas()
|
|
||||||
.reindex(index=n.snapshots)
|
|
||||||
)
|
|
||||||
default_lifetime = snakemake.params.existing_capacities[
|
|
||||||
"default_heating_lifetime"
|
|
||||||
]
|
|
||||||
add_heating_capacities_installed_before_baseyear(
|
add_heating_capacities_installed_before_baseyear(
|
||||||
n,
|
n=n,
|
||||||
baseyear,
|
baseyear=baseyear,
|
||||||
grouping_years_heat,
|
grouping_years=grouping_years_heat,
|
||||||
ashp_cop,
|
cop=xr.open_dataarray(snakemake.input.cop_profiles),
|
||||||
gshp_cop,
|
time_dep_hp_cop=options["time_dep_hp_cop"],
|
||||||
time_dep_hp_cop,
|
costs=costs,
|
||||||
costs,
|
default_lifetime=snakemake.params.existing_capacities[
|
||||||
default_lifetime,
|
"default_heating_lifetime"
|
||||||
|
],
|
||||||
|
existing_heating=pd.read_csv(
|
||||||
|
snakemake.input.existing_heating_distribution,
|
||||||
|
header=[0, 1],
|
||||||
|
index_col=0,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
if options.get("cluster_heat_buses", False):
|
if options.get("cluster_heat_buses", False):
|
||||||
|
@ -808,7 +808,7 @@ def voronoi(points, outline, crs=4326):
|
|||||||
voronoi = gpd.GeoDataFrame(geometry=voronoi)
|
voronoi = gpd.GeoDataFrame(geometry=voronoi)
|
||||||
joined = gpd.sjoin_nearest(pts, voronoi, how="right")
|
joined = gpd.sjoin_nearest(pts, voronoi, how="right")
|
||||||
|
|
||||||
return joined.dissolve(by="Bus").squeeze()
|
return joined.dissolve(by="Bus").reindex(points.index).squeeze()
|
||||||
|
|
||||||
|
|
||||||
def build_bus_shapes(n, country_shapes, offshore_shapes, countries):
|
def build_bus_shapes(n, country_shapes, offshore_shapes, countries):
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: MIT
|
|
||||||
"""
|
|
||||||
Build coefficient of performance (COP) time series for air- or ground-sourced
|
|
||||||
heat pumps.
|
|
||||||
|
|
||||||
The COP is approximated as a quatratic function of the temperature difference between source and
|
|
||||||
sink, based on Staffell et al. 2012.
|
|
||||||
|
|
||||||
This rule is executed in ``build_sector.smk``.
|
|
||||||
|
|
||||||
Relevant Settings
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
.. code:: yaml
|
|
||||||
heat_pump_sink_T:
|
|
||||||
|
|
||||||
|
|
||||||
Inputs:
|
|
||||||
-------
|
|
||||||
- ``resources/<run_name>/temp_soil_total_elec_s<simpl>_<clusters>.nc``: Soil temperature (total) time series.
|
|
||||||
- ``resources/<run_name>/temp_air_total_elec_s<simpl>_<clusters>.nc``: Ambient air temperature (total) time series.
|
|
||||||
|
|
||||||
Outputs:
|
|
||||||
--------
|
|
||||||
- ``resources/cop_soil_total_elec_s<simpl>_<clusters>.nc``: COP (ground-sourced) time series (total).
|
|
||||||
- ``resources/cop_air_total_elec_s<simpl>_<clusters>.nc``: COP (air-sourced) time series (total).
|
|
||||||
|
|
||||||
|
|
||||||
References
|
|
||||||
----------
|
|
||||||
[1] Staffell et al., Energy & Environmental Science 11 (2012): A review of domestic heat pumps, https://doi.org/10.1039/C2EE22653G.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import xarray as xr
|
|
||||||
from _helpers import set_scenario_config
|
|
||||||
|
|
||||||
|
|
||||||
def coefficient_of_performance(delta_T, source="air"):
|
|
||||||
if source == "air":
|
|
||||||
return 6.81 - 0.121 * delta_T + 0.000630 * delta_T**2
|
|
||||||
elif source == "soil":
|
|
||||||
return 8.77 - 0.150 * delta_T + 0.000734 * delta_T**2
|
|
||||||
else:
|
|
||||||
raise NotImplementedError("'source' must be one of ['air', 'soil']")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
if "snakemake" not in globals():
|
|
||||||
from _helpers import mock_snakemake
|
|
||||||
|
|
||||||
snakemake = mock_snakemake(
|
|
||||||
"build_cop_profiles",
|
|
||||||
simpl="",
|
|
||||||
clusters=48,
|
|
||||||
)
|
|
||||||
|
|
||||||
set_scenario_config(snakemake)
|
|
||||||
|
|
||||||
for source in ["air", "soil"]:
|
|
||||||
source_T = xr.open_dataarray(snakemake.input[f"temp_{source}_total"])
|
|
||||||
|
|
||||||
delta_T = snakemake.params.heat_pump_sink_T - source_T
|
|
||||||
|
|
||||||
cop = coefficient_of_performance(delta_T, source)
|
|
||||||
|
|
||||||
cop.to_netcdf(snakemake.output[f"cop_{source}_total"])
|
|
111
scripts/build_cop_profiles/BaseCopApproximator.py
Normal file
111
scripts/build_cop_profiles/BaseCopApproximator.py
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import xarray as xr
|
||||||
|
|
||||||
|
|
||||||
|
class BaseCopApproximator(ABC):
|
||||||
|
"""
|
||||||
|
Abstract class for approximating the coefficient of performance (COP) of a
|
||||||
|
heat pump.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
----------
|
||||||
|
forward_temperature_celsius : Union[xr.DataArray, np.array]
|
||||||
|
The forward temperature in Celsius.
|
||||||
|
source_inlet_temperature_celsius : Union[xr.DataArray, np.array]
|
||||||
|
The source inlet temperature in Celsius.
|
||||||
|
|
||||||
|
Methods:
|
||||||
|
-------
|
||||||
|
__init__(self, forward_temperature_celsius, source_inlet_temperature_celsius)
|
||||||
|
Initialize CopApproximator.
|
||||||
|
approximate_cop(self)
|
||||||
|
Approximate heat pump coefficient of performance (COP).
|
||||||
|
celsius_to_kelvin(t_celsius)
|
||||||
|
Convert temperature from Celsius to Kelvin.
|
||||||
|
logarithmic_mean(t_hot, t_cold)
|
||||||
|
Calculate the logarithmic mean temperature difference.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
forward_temperature_celsius: Union[xr.DataArray, np.array],
|
||||||
|
source_inlet_temperature_celsius: Union[xr.DataArray, np.array],
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Initialize CopApproximator.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
----------
|
||||||
|
forward_temperature_celsius : Union[xr.DataArray, np.array]
|
||||||
|
The forward temperature in Celsius.
|
||||||
|
source_inlet_temperature_celsius : Union[xr.DataArray, np.array]
|
||||||
|
The source inlet temperature in Celsius.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def approximate_cop(self) -> Union[xr.DataArray, np.array]:
|
||||||
|
"""
|
||||||
|
Approximate heat pump coefficient of performance (COP).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
-------
|
||||||
|
Union[xr.DataArray, np.array]
|
||||||
|
The calculated COP values.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def celsius_to_kelvin(
|
||||||
|
t_celsius: Union[float, xr.DataArray, np.array]
|
||||||
|
) -> Union[float, xr.DataArray, np.array]:
|
||||||
|
"""
|
||||||
|
Convert temperature from Celsius to Kelvin.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
----------
|
||||||
|
t_celsius : Union[float, xr.DataArray, np.array]
|
||||||
|
Temperature in Celsius.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
-------
|
||||||
|
Union[float, xr.DataArray, np.array]
|
||||||
|
Temperature in Kelvin.
|
||||||
|
"""
|
||||||
|
if (np.asarray(t_celsius) > 200).any():
|
||||||
|
raise ValueError(
|
||||||
|
"t_celsius > 200. Are you sure you are using the right units?"
|
||||||
|
)
|
||||||
|
return t_celsius + 273.15
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def logarithmic_mean(
|
||||||
|
t_hot: Union[float, xr.DataArray, np.ndarray],
|
||||||
|
t_cold: Union[float, xr.DataArray, np.ndarray],
|
||||||
|
) -> Union[float, xr.DataArray, np.ndarray]:
|
||||||
|
"""
|
||||||
|
Calculate the logarithmic mean temperature difference.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
----------
|
||||||
|
t_hot : Union[float, xr.DataArray, np.ndarray]
|
||||||
|
Hot temperature.
|
||||||
|
t_cold : Union[float, xr.DataArray, np.ndarray]
|
||||||
|
Cold temperature.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
-------
|
||||||
|
Union[float, xr.DataArray, np.ndarray]
|
||||||
|
Logarithmic mean temperature difference.
|
||||||
|
"""
|
||||||
|
if (np.asarray(t_hot <= t_cold)).any():
|
||||||
|
raise ValueError("t_hot must be greater than t_cold")
|
||||||
|
return (t_hot - t_cold) / np.log(t_hot / t_cold)
|
392
scripts/build_cop_profiles/CentralHeatingCopApproximator.py
Normal file
392
scripts/build_cop_profiles/CentralHeatingCopApproximator.py
Normal file
@ -0,0 +1,392 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import xarray as xr
|
||||||
|
from BaseCopApproximator import BaseCopApproximator
|
||||||
|
|
||||||
|
|
||||||
|
class CentralHeatingCopApproximator(BaseCopApproximator):
|
||||||
|
"""
|
||||||
|
Approximate the coefficient of performance (COP) for a heat pump in a
|
||||||
|
central heating system (district heating).
|
||||||
|
|
||||||
|
Uses an approximation method proposed by Jensen et al. (2018) and
|
||||||
|
default parameters from Pieper et al. (2020). The method is based on
|
||||||
|
a thermodynamic heat pump model with some hard-to-know parameters
|
||||||
|
being approximated.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
----------
|
||||||
|
forward_temperature_celsius : Union[xr.DataArray, np.array]
|
||||||
|
The forward temperature in Celsius.
|
||||||
|
return_temperature_celsius : Union[xr.DataArray, np.array]
|
||||||
|
The return temperature in Celsius.
|
||||||
|
source_inlet_temperature_celsius : Union[xr.DataArray, np.array]
|
||||||
|
The source inlet temperature in Celsius.
|
||||||
|
source_outlet_temperature_celsius : Union[xr.DataArray, np.array]
|
||||||
|
The source outlet temperature in Celsius.
|
||||||
|
delta_t_pinch_point : float, optional
|
||||||
|
The pinch point temperature difference, by default 5.
|
||||||
|
isentropic_compressor_efficiency : float, optional
|
||||||
|
The isentropic compressor efficiency, by default 0.8.
|
||||||
|
heat_loss : float, optional
|
||||||
|
The heat loss, by default 0.0.
|
||||||
|
|
||||||
|
Methods:
|
||||||
|
-------
|
||||||
|
__init__(
|
||||||
|
forward_temperature_celsius: Union[xr.DataArray, np.array],
|
||||||
|
source_inlet_temperature_celsius: Union[xr.DataArray, np.array],
|
||||||
|
return_temperature_celsius: Union[xr.DataArray, np.array],
|
||||||
|
source_outlet_temperature_celsius: Union[xr.DataArray, np.array],
|
||||||
|
delta_t_pinch_point: float = 5,
|
||||||
|
isentropic_compressor_efficiency: float = 0.8,
|
||||||
|
heat_loss: float = 0.0,
|
||||||
|
) -> None:
|
||||||
|
Initializes the CentralHeatingCopApproximator object.
|
||||||
|
|
||||||
|
approximate_cop(self) -> Union[xr.DataArray, np.array]:
|
||||||
|
Calculate the coefficient of performance (COP) for the system.
|
||||||
|
|
||||||
|
_approximate_delta_t_refrigerant_source(
|
||||||
|
self, delta_t_source: Union[xr.DataArray, np.array]
|
||||||
|
) -> Union[xr.DataArray, np.array]:
|
||||||
|
Approximates the temperature difference between the refrigerant and the source.
|
||||||
|
|
||||||
|
_approximate_delta_t_refrigerant_sink(
|
||||||
|
self,
|
||||||
|
refrigerant: str = "ammonia",
|
||||||
|
a: float = {"ammonia": 0.2, "isobutane": -0.0011},
|
||||||
|
b: float = {"ammonia": 0.2, "isobutane": 0.3},
|
||||||
|
c: float = {"ammonia": 0.016, "isobutane": 2.4},
|
||||||
|
) -> Union[xr.DataArray, np.array]:
|
||||||
|
Approximates the temperature difference between the refrigerant and heat sink.
|
||||||
|
|
||||||
|
_ratio_evaporation_compression_work_approximation(
|
||||||
|
self,
|
||||||
|
refrigerant: str = "ammonia",
|
||||||
|
a: float = {"ammonia": 0.0014, "isobutane": 0.0035},
|
||||||
|
) -> Union[xr.DataArray, np.array]:
|
||||||
|
Calculate the ratio of evaporation to compression work based on approximation.
|
||||||
|
|
||||||
|
_approximate_delta_t_refrigerant_sink(
|
||||||
|
self,
|
||||||
|
refrigerant: str = "ammonia",
|
||||||
|
a: float = {"ammonia": 0.2, "isobutane": -0.0011},
|
||||||
|
b: float = {"ammonia": 0.2, "isobutane": 0.3},
|
||||||
|
c: float = {"ammonia": 0.016, "isobutane": 2.4},
|
||||||
|
) -> Union[xr.DataArray, np.array]:
|
||||||
|
Approximates the temperature difference between the refrigerant and heat sink.
|
||||||
|
|
||||||
|
_ratio_evaporation_compression_work_approximation(
|
||||||
|
self,
|
||||||
|
refrigerant: str = "ammonia",
|
||||||
|
a: float = {"ammonia": 0.0014, "isobutane": 0.0035},
|
||||||
|
) -> Union[xr.DataArray, np.array]:
|
||||||
|
Calculate the ratio of evaporation to compression work based on approximation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
forward_temperature_celsius: Union[xr.DataArray, np.array],
|
||||||
|
source_inlet_temperature_celsius: Union[xr.DataArray, np.array],
|
||||||
|
return_temperature_celsius: Union[xr.DataArray, np.array],
|
||||||
|
source_outlet_temperature_celsius: Union[xr.DataArray, np.array],
|
||||||
|
delta_t_pinch_point: float = 5,
|
||||||
|
isentropic_compressor_efficiency: float = 0.8,
|
||||||
|
heat_loss: float = 0.0,
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Initializes the CentralHeatingCopApproximator object.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
----------
|
||||||
|
forward_temperature_celsius : Union[xr.DataArray, np.array]
|
||||||
|
The forward temperature in Celsius.
|
||||||
|
return_temperature_celsius : Union[xr.DataArray, np.array]
|
||||||
|
The return temperature in Celsius.
|
||||||
|
source_inlet_temperature_celsius : Union[xr.DataArray, np.array]
|
||||||
|
The source inlet temperature in Celsius.
|
||||||
|
source_outlet_temperature_celsius : Union[xr.DataArray, np.array]
|
||||||
|
The source outlet temperature in Celsius.
|
||||||
|
delta_t_pinch_point : float, optional
|
||||||
|
The pinch point temperature difference, by default 5.
|
||||||
|
isentropic_compressor_efficiency : float, optional
|
||||||
|
The isentropic compressor efficiency, by default 0.8.
|
||||||
|
heat_loss : float, optional
|
||||||
|
The heat loss, by default 0.0.
|
||||||
|
"""
|
||||||
|
self.t_source_in_kelvin = BaseCopApproximator.celsius_to_kelvin(
|
||||||
|
source_inlet_temperature_celsius
|
||||||
|
)
|
||||||
|
self.t_sink_out_kelvin = BaseCopApproximator.celsius_to_kelvin(
|
||||||
|
forward_temperature_celsius
|
||||||
|
)
|
||||||
|
|
||||||
|
self.t_sink_in_kelvin = BaseCopApproximator.celsius_to_kelvin(
|
||||||
|
return_temperature_celsius
|
||||||
|
)
|
||||||
|
self.t_source_out = BaseCopApproximator.celsius_to_kelvin(
|
||||||
|
source_outlet_temperature_celsius
|
||||||
|
)
|
||||||
|
|
||||||
|
self.isentropic_efficiency_compressor_kelvin = isentropic_compressor_efficiency
|
||||||
|
self.heat_loss = heat_loss
|
||||||
|
self.delta_t_pinch = delta_t_pinch_point
|
||||||
|
|
||||||
|
def approximate_cop(self) -> Union[xr.DataArray, np.array]:
|
||||||
|
"""
|
||||||
|
Calculate the coefficient of performance (COP) for the system.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
--------
|
||||||
|
Union[xr.DataArray, np.array]: The calculated COP values.
|
||||||
|
"""
|
||||||
|
return (
|
||||||
|
self.ideal_lorenz_cop
|
||||||
|
* (
|
||||||
|
(
|
||||||
|
1
|
||||||
|
+ (self.delta_t_refrigerant_sink + self.delta_t_pinch)
|
||||||
|
/ self.t_sink_mean_kelvin
|
||||||
|
)
|
||||||
|
/ (
|
||||||
|
1
|
||||||
|
+ (
|
||||||
|
self.delta_t_refrigerant_sink
|
||||||
|
+ self.delta_t_refrigerant_source
|
||||||
|
+ 2 * self.delta_t_pinch
|
||||||
|
)
|
||||||
|
/ self.delta_t_lift
|
||||||
|
)
|
||||||
|
)
|
||||||
|
* self.isentropic_efficiency_compressor_kelvin
|
||||||
|
* (1 - self.ratio_evaporation_compression_work)
|
||||||
|
+ 1
|
||||||
|
- self.isentropic_efficiency_compressor_kelvin
|
||||||
|
- self.heat_loss
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def t_sink_mean_kelvin(self) -> Union[xr.DataArray, np.array]:
|
||||||
|
"""
|
||||||
|
Calculate the logarithmic mean temperature difference between the cold
|
||||||
|
and hot sinks.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Union[xr.DataArray, np.array]
|
||||||
|
The mean temperature difference.
|
||||||
|
"""
|
||||||
|
return BaseCopApproximator.logarithmic_mean(
|
||||||
|
t_cold=self.t_sink_in_kelvin, t_hot=self.t_sink_out_kelvin
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def t_source_mean_kelvin(self) -> Union[xr.DataArray, np.array]:
|
||||||
|
"""
|
||||||
|
Calculate the logarithmic mean temperature of the heat source.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Union[xr.DataArray, np.array]
|
||||||
|
The mean temperature of the heat source.
|
||||||
|
"""
|
||||||
|
return BaseCopApproximator.logarithmic_mean(
|
||||||
|
t_hot=self.t_source_in_kelvin, t_cold=self.t_source_out
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def delta_t_lift(self) -> Union[xr.DataArray, np.array]:
|
||||||
|
"""
|
||||||
|
Calculate the temperature lift as the difference between the
|
||||||
|
logarithmic sink and source temperatures.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Union[xr.DataArray, np.array]
|
||||||
|
The temperature difference between the sink and source.
|
||||||
|
"""
|
||||||
|
return self.t_sink_mean_kelvin - self.t_source_mean_kelvin
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ideal_lorenz_cop(self) -> Union[xr.DataArray, np.array]:
|
||||||
|
"""
|
||||||
|
Ideal Lorenz coefficient of performance (COP).
|
||||||
|
|
||||||
|
The ideal Lorenz COP is calculated as the ratio of the mean sink temperature
|
||||||
|
to the lift temperature difference.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
np.array
|
||||||
|
The ideal Lorenz COP.
|
||||||
|
"""
|
||||||
|
return self.t_sink_mean_kelvin / self.delta_t_lift
|
||||||
|
|
||||||
|
@property
|
||||||
|
def delta_t_refrigerant_source(self) -> Union[xr.DataArray, np.array]:
|
||||||
|
"""
|
||||||
|
Calculate the temperature difference between the refrigerant source
|
||||||
|
inlet and outlet.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Union[xr.DataArray, np.array]
|
||||||
|
The temperature difference between the refrigerant source inlet and outlet.
|
||||||
|
"""
|
||||||
|
return self._approximate_delta_t_refrigerant_source(
|
||||||
|
delta_t_source=self.t_source_in_kelvin - self.t_source_out
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def delta_t_refrigerant_sink(self) -> Union[xr.DataArray, np.array]:
|
||||||
|
"""
|
||||||
|
Temperature difference between the refrigerant and the sink based on
|
||||||
|
approximation.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Union[xr.DataArray, np.array]
|
||||||
|
The temperature difference between the refrigerant and the sink.
|
||||||
|
"""
|
||||||
|
return self._approximate_delta_t_refrigerant_sink()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ratio_evaporation_compression_work(self) -> Union[xr.DataArray, np.array]:
|
||||||
|
"""
|
||||||
|
Calculate the ratio of evaporation to compression work based on
|
||||||
|
approximation.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Union[xr.DataArray, np.array]
|
||||||
|
The calculated ratio of evaporation to compression work.
|
||||||
|
"""
|
||||||
|
return self._ratio_evaporation_compression_work_approximation()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def delta_t_sink(self) -> Union[xr.DataArray, np.array]:
|
||||||
|
"""
|
||||||
|
Calculate the temperature difference at the sink.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Union[xr.DataArray, np.array]
|
||||||
|
The temperature difference at the sink.
|
||||||
|
"""
|
||||||
|
return self.t_sink_out_kelvin - self.t_sink_in_kelvin
|
||||||
|
|
||||||
|
def _approximate_delta_t_refrigerant_source(
|
||||||
|
self, delta_t_source: Union[xr.DataArray, np.array]
|
||||||
|
) -> Union[xr.DataArray, np.array]:
|
||||||
|
"""
|
||||||
|
Approximates the temperature difference between the refrigerant and the
|
||||||
|
source.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
delta_t_source : Union[xr.DataArray, np.array]
|
||||||
|
The temperature difference for the refrigerant source.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Union[xr.DataArray, np.array]
|
||||||
|
The approximate temperature difference between the refrigerant and heat source.
|
||||||
|
"""
|
||||||
|
return delta_t_source / 2
|
||||||
|
|
||||||
|
def _approximate_delta_t_refrigerant_sink(
|
||||||
|
self,
|
||||||
|
refrigerant: str = "ammonia",
|
||||||
|
a: float = {"ammonia": 0.2, "isobutane": -0.0011},
|
||||||
|
b: float = {"ammonia": 0.2, "isobutane": 0.3},
|
||||||
|
c: float = {"ammonia": 0.016, "isobutane": 2.4},
|
||||||
|
) -> Union[xr.DataArray, np.array]:
|
||||||
|
"""
|
||||||
|
Approximates the temperature difference between the refrigerant and
|
||||||
|
heat sink.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
----------
|
||||||
|
refrigerant : str, optional
|
||||||
|
The refrigerant used in the system. Either 'isobutane' or 'ammonia. Default is 'ammonia'.
|
||||||
|
a : float, optional
|
||||||
|
Coefficient for the temperature difference between the sink and source, default is 0.2.
|
||||||
|
b : float, optional
|
||||||
|
Coefficient for the temperature difference at the sink, default is 0.2.
|
||||||
|
c : float, optional
|
||||||
|
Constant term, default is 0.016.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
-------
|
||||||
|
Union[xr.DataArray, np.array]
|
||||||
|
The approximate temperature difference between the refrigerant and heat sink.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
------
|
||||||
|
This function assumes ammonia as the refrigerant.
|
||||||
|
|
||||||
|
The approximate temperature difference at the refrigerant sink is calculated using the following formula:
|
||||||
|
a * (t_sink_out - t_source_out + 2 * delta_t_pinch) + b * delta_t_sink + c
|
||||||
|
"""
|
||||||
|
if refrigerant not in a.keys():
|
||||||
|
raise ValueError(
|
||||||
|
f"Invalid refrigerant '{refrigerant}'. Must be one of {a.keys()}"
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
a[refrigerant]
|
||||||
|
* (self.t_sink_out_kelvin - self.t_source_out + 2 * self.delta_t_pinch)
|
||||||
|
+ b[refrigerant] * self.delta_t_sink
|
||||||
|
+ c[refrigerant]
|
||||||
|
)
|
||||||
|
|
||||||
|
def _ratio_evaporation_compression_work_approximation(
|
||||||
|
self,
|
||||||
|
refrigerant: str = "ammonia",
|
||||||
|
a: float = {"ammonia": 0.0014, "isobutane": 0.0035},
|
||||||
|
b: float = {"ammonia": -0.0015, "isobutane": -0.0033},
|
||||||
|
c: float = {"ammonia": 0.039, "isobutane": 0.053},
|
||||||
|
) -> Union[xr.DataArray, np.array]:
|
||||||
|
"""
|
||||||
|
Calculate the ratio of evaporation to compression work approximation.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
----------
|
||||||
|
refrigerant : str, optional
|
||||||
|
The refrigerant used in the system. Either 'isobutane' or 'ammonia. Default is 'ammonia'.
|
||||||
|
a : float, optional
|
||||||
|
Coefficient 'a' in the approximation equation. Default is 0.0014.
|
||||||
|
b : float, optional
|
||||||
|
Coefficient 'b' in the approximation equation. Default is -0.0015.
|
||||||
|
c : float, optional
|
||||||
|
Coefficient 'c' in the approximation equation. Default is 0.039.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
-------
|
||||||
|
Union[xr.DataArray, np.array]
|
||||||
|
The approximated ratio of evaporation to compression work.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
------
|
||||||
|
This function assumes ammonia as the refrigerant.
|
||||||
|
|
||||||
|
The approximation equation used is:
|
||||||
|
ratio = a * (t_sink_out - t_source_out + 2 * delta_t_pinch) + b * delta_t_sink + c
|
||||||
|
"""
|
||||||
|
if refrigerant not in a.keys():
|
||||||
|
raise ValueError(
|
||||||
|
f"Invalid refrigerant '{refrigerant}'. Must be one of {a.keys()}"
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
a[refrigerant]
|
||||||
|
* (self.t_sink_out_kelvin - self.t_source_out + 2 * self.delta_t_pinch)
|
||||||
|
+ b[refrigerant] * self.delta_t_sink
|
||||||
|
+ c[refrigerant]
|
||||||
|
)
|
110
scripts/build_cop_profiles/DecentralHeatingCopApproximator.py
Normal file
110
scripts/build_cop_profiles/DecentralHeatingCopApproximator.py
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import xarray as xr
|
||||||
|
from BaseCopApproximator import BaseCopApproximator
|
||||||
|
|
||||||
|
|
||||||
|
class DecentralHeatingCopApproximator(BaseCopApproximator):
|
||||||
|
"""
|
||||||
|
Approximate the coefficient of performance (COP) for a heat pump in a
|
||||||
|
decentral heating system (individual/household heating).
|
||||||
|
|
||||||
|
Uses a quadratic regression on the temperature difference between the source and sink based on empirical data proposed by Staffell et al. 2012.
|
||||||
|
|
||||||
|
Attributes
|
||||||
|
----------
|
||||||
|
forward_temperature_celsius : Union[xr.DataArray, np.array]
|
||||||
|
The forward temperature in Celsius.
|
||||||
|
source_inlet_temperature_celsius : Union[xr.DataArray, np.array]
|
||||||
|
The source inlet temperature in Celsius.
|
||||||
|
source_type : str
|
||||||
|
The source of the heat pump. Must be either 'air' or 'ground'.
|
||||||
|
|
||||||
|
Methods
|
||||||
|
-------
|
||||||
|
__init__(forward_temperature_celsius, source_inlet_temperature_celsius, source_type)
|
||||||
|
Initialize the DecentralHeatingCopApproximator object.
|
||||||
|
approximate_cop()
|
||||||
|
Compute the COP values using quadratic regression for air-/ground-source heat pumps.
|
||||||
|
_approximate_cop_air_source()
|
||||||
|
Evaluate quadratic regression for an air-sourced heat pump.
|
||||||
|
_approximate_cop_ground_source()
|
||||||
|
Evaluate quadratic regression for a ground-sourced heat pump.
|
||||||
|
|
||||||
|
References
|
||||||
|
----------
|
||||||
|
[1] Staffell et al., Energy & Environmental Science 11 (2012): A review of domestic heat pumps, https://doi.org/10.1039/C2EE22653G.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
forward_temperature_celsius: Union[xr.DataArray, np.array],
|
||||||
|
source_inlet_temperature_celsius: Union[xr.DataArray, np.array],
|
||||||
|
source_type: str,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Initialize the DecentralHeatingCopApproximator object.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
forward_temperature_celsius : Union[xr.DataArray, np.array]
|
||||||
|
The forward temperature in Celsius.
|
||||||
|
source_inlet_temperature_celsius : Union[xr.DataArray, np.array]
|
||||||
|
The source inlet temperature in Celsius.
|
||||||
|
source_type : str
|
||||||
|
The source of the heat pump. Must be either 'air' or 'ground'.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.delta_t = forward_temperature_celsius - source_inlet_temperature_celsius
|
||||||
|
if source_type not in ["air", "ground"]:
|
||||||
|
raise ValueError("'source_type' must be one of ['air', 'ground']")
|
||||||
|
else:
|
||||||
|
self.source_type = source_type
|
||||||
|
|
||||||
|
def approximate_cop(self) -> Union[xr.DataArray, np.array]:
|
||||||
|
"""
|
||||||
|
Compute the COP values using quadratic regression for air-/ground-
|
||||||
|
source heat pumps.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Union[xr.DataArray, np.array]
|
||||||
|
The calculated COP values.
|
||||||
|
"""
|
||||||
|
if self.source_type == "air":
|
||||||
|
return self._approximate_cop_air_source()
|
||||||
|
elif self.source_type == "ground":
|
||||||
|
return self._approximate_cop_ground_source()
|
||||||
|
|
||||||
|
def _approximate_cop_air_source(self) -> Union[xr.DataArray, np.array]:
|
||||||
|
"""
|
||||||
|
Evaluate quadratic regression for an air-sourced heat pump.
|
||||||
|
|
||||||
|
COP = 6.81 - 0.121 * delta_T + 0.000630 * delta_T^2
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Union[xr.DataArray, np.array]
|
||||||
|
The calculated COP values.
|
||||||
|
"""
|
||||||
|
return 6.81 - 0.121 * self.delta_t + 0.000630 * self.delta_t**2
|
||||||
|
|
||||||
|
def _approximate_cop_ground_source(self) -> Union[xr.DataArray, np.array]:
|
||||||
|
"""
|
||||||
|
Evaluate quadratic regression for a ground-sourced heat pump.
|
||||||
|
|
||||||
|
COP = 8.77 - 0.150 * delta_T + 0.000734 * delta_T^2
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Union[xr.DataArray, np.array]
|
||||||
|
The calculated COP values.
|
||||||
|
"""
|
||||||
|
return 8.77 - 0.150 * self.delta_t + 0.000734 * self.delta_t**2
|
95
scripts/build_cop_profiles/run.py
Normal file
95
scripts/build_cop_profiles/run.py
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import pandas as pd
|
||||||
|
import xarray as xr
|
||||||
|
from _helpers import set_scenario_config
|
||||||
|
from CentralHeatingCopApproximator import CentralHeatingCopApproximator
|
||||||
|
from DecentralHeatingCopApproximator import DecentralHeatingCopApproximator
|
||||||
|
|
||||||
|
from scripts.definitions.heat_system_type import HeatSystemType
|
||||||
|
|
||||||
|
sys.path.append("..")
|
||||||
|
|
||||||
|
|
||||||
|
def get_cop(
|
||||||
|
heat_system_type: str,
|
||||||
|
heat_source: str,
|
||||||
|
source_inlet_temperature_celsius: xr.DataArray,
|
||||||
|
) -> xr.DataArray:
|
||||||
|
"""
|
||||||
|
Calculate the coefficient of performance (COP) for a heating system.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
heat_system_type : str
|
||||||
|
The type of heating system.
|
||||||
|
heat_source : str
|
||||||
|
The heat source used in the heating system.
|
||||||
|
source_inlet_temperature_celsius : xr.DataArray
|
||||||
|
The inlet temperature of the heat source in Celsius.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
xr.DataArray
|
||||||
|
The calculated coefficient of performance (COP) for the heating system.
|
||||||
|
"""
|
||||||
|
if HeatSystemType(heat_system_type).is_central:
|
||||||
|
return CentralHeatingCopApproximator(
|
||||||
|
forward_temperature_celsius=snakemake.params.forward_temperature_central_heating,
|
||||||
|
return_temperature_celsius=snakemake.params.return_temperature_central_heating,
|
||||||
|
source_inlet_temperature_celsius=source_inlet_temperature_celsius,
|
||||||
|
source_outlet_temperature_celsius=source_inlet_temperature_celsius
|
||||||
|
- snakemake.params.heat_source_cooling_central_heating,
|
||||||
|
).approximate_cop()
|
||||||
|
|
||||||
|
else:
|
||||||
|
return DecentralHeatingCopApproximator(
|
||||||
|
forward_temperature_celsius=snakemake.params.heat_pump_sink_T_decentral_heating,
|
||||||
|
source_inlet_temperature_celsius=source_inlet_temperature_celsius,
|
||||||
|
source_type=heat_source,
|
||||||
|
).approximate_cop()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if "snakemake" not in globals():
|
||||||
|
from _helpers import mock_snakemake
|
||||||
|
|
||||||
|
snakemake = mock_snakemake(
|
||||||
|
"build_cop_profiles",
|
||||||
|
simpl="",
|
||||||
|
clusters=48,
|
||||||
|
)
|
||||||
|
|
||||||
|
set_scenario_config(snakemake)
|
||||||
|
|
||||||
|
cop_all_system_types = []
|
||||||
|
for heat_system_type, heat_sources in snakemake.params.heat_pump_sources.items():
|
||||||
|
cop_this_system_type = []
|
||||||
|
for heat_source in heat_sources:
|
||||||
|
source_inlet_temperature_celsius = xr.open_dataarray(
|
||||||
|
snakemake.input[f"temp_{heat_source.replace('ground', 'soil')}_total"]
|
||||||
|
)
|
||||||
|
cop_da = get_cop(
|
||||||
|
heat_system_type=heat_system_type,
|
||||||
|
heat_source=heat_source,
|
||||||
|
source_inlet_temperature_celsius=source_inlet_temperature_celsius,
|
||||||
|
)
|
||||||
|
cop_this_system_type.append(cop_da)
|
||||||
|
cop_all_system_types.append(
|
||||||
|
xr.concat(
|
||||||
|
cop_this_system_type, dim=pd.Index(heat_sources, name="heat_source")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
cop_dataarray = xr.concat(
|
||||||
|
cop_all_system_types,
|
||||||
|
dim=pd.Index(snakemake.params.heat_pump_sources.keys(), name="heat_system"),
|
||||||
|
)
|
||||||
|
|
||||||
|
cop_dataarray.to_netcdf(snakemake.output.cop_profiles)
|
@ -6,7 +6,7 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
"""
|
"""
|
||||||
Retrieves conventional powerplant capacities and locations from
|
Retrieves conventional powerplant capacities and locations from
|
||||||
`powerplantmatching <https://github.com/FRESNA/powerplantmatching>`_, assigns
|
`powerplantmatching <https://github.com/PyPSA/powerplantmatching>`_, assigns
|
||||||
these to buses and creates a ``.csv`` file. It is possible to amend the
|
these to buses and creates a ``.csv`` file. It is possible to amend the
|
||||||
powerplant database with custom entries provided in
|
powerplant database with custom entries provided in
|
||||||
``data/custom_powerplants.csv``.
|
``data/custom_powerplants.csv``.
|
||||||
@ -30,17 +30,17 @@ Inputs
|
|||||||
------
|
------
|
||||||
|
|
||||||
- ``networks/base.nc``: confer :ref:`base`.
|
- ``networks/base.nc``: confer :ref:`base`.
|
||||||
- ``data/custom_powerplants.csv``: custom powerplants in the same format as `powerplantmatching <https://github.com/FRESNA/powerplantmatching>`_ provides
|
- ``data/custom_powerplants.csv``: custom powerplants in the same format as `powerplantmatching <https://github.com/PyPSA/powerplantmatching>`_ provides
|
||||||
|
|
||||||
Outputs
|
Outputs
|
||||||
-------
|
-------
|
||||||
|
|
||||||
- ``resource/powerplants.csv``: A list of conventional power plants (i.e. neither wind nor solar) with fields for name, fuel type, technology, country, capacity in MW, duration, commissioning year, retrofit year, latitude, longitude, and dam information as documented in the `powerplantmatching README <https://github.com/FRESNA/powerplantmatching/blob/master/README.md>`_; additionally it includes information on the closest substation/bus in ``networks/base.nc``.
|
- ``resource/powerplants.csv``: A list of conventional power plants (i.e. neither wind nor solar) with fields for name, fuel type, technology, country, capacity in MW, duration, commissioning year, retrofit year, latitude, longitude, and dam information as documented in the `powerplantmatching README <https://github.com/PyPSA/powerplantmatching/blob/master/README.md>`_; additionally it includes information on the closest substation/bus in ``networks/base.nc``.
|
||||||
|
|
||||||
.. image:: img/powerplantmatching.png
|
.. image:: img/powerplantmatching.png
|
||||||
:scale: 30 %
|
:scale: 30 %
|
||||||
|
|
||||||
**Source:** `powerplantmatching on GitHub <https://github.com/FRESNA/powerplantmatching>`_
|
**Source:** `powerplantmatching on GitHub <https://github.com/PyPSA/powerplantmatching>`_
|
||||||
|
|
||||||
Description
|
Description
|
||||||
-----------
|
-----------
|
||||||
|
28
scripts/definitions/heat_sector.py
Normal file
28
scripts/definitions/heat_sector.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class HeatSector(Enum):
|
||||||
|
"""
|
||||||
|
Enumeration class representing different heat sectors.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
RESIDENTIAL (str): Represents the residential heat sector.
|
||||||
|
SERVICES (str): Represents the services heat sector.
|
||||||
|
"""
|
||||||
|
|
||||||
|
RESIDENTIAL = "residential"
|
||||||
|
SERVICES = "services"
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
"""
|
||||||
|
Returns the string representation of the heat sector.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The string representation of the heat sector.
|
||||||
|
"""
|
||||||
|
return self.value
|
267
scripts/definitions/heat_system.py
Normal file
267
scripts/definitions/heat_system.py
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
from scripts.definitions.heat_sector import HeatSector
|
||||||
|
from scripts.definitions.heat_system_type import HeatSystemType
|
||||||
|
|
||||||
|
|
||||||
|
class HeatSystem(Enum):
|
||||||
|
"""
|
||||||
|
Enumeration representing different heat systems.
|
||||||
|
|
||||||
|
Attributes
|
||||||
|
----------
|
||||||
|
RESIDENTIAL_RURAL : str
|
||||||
|
Heat system for residential areas in rural locations.
|
||||||
|
SERVICES_RURAL : str
|
||||||
|
Heat system for service areas in rural locations.
|
||||||
|
RESIDENTIAL_URBAN_DECENTRAL : str
|
||||||
|
Heat system for residential areas in urban decentralized locations.
|
||||||
|
SERVICES_URBAN_DECENTRAL : str
|
||||||
|
Heat system for service areas in urban decentralized locations.
|
||||||
|
URBAN_CENTRAL : str
|
||||||
|
Heat system for urban central areas.
|
||||||
|
|
||||||
|
Methods
|
||||||
|
-------
|
||||||
|
__str__()
|
||||||
|
Returns the string representation of the heat system.
|
||||||
|
central_or_decentral()
|
||||||
|
Returns whether the heat system is central or decentralized.
|
||||||
|
system_type()
|
||||||
|
Returns the type of the heat system.
|
||||||
|
sector()
|
||||||
|
Returns the sector of the heat system.
|
||||||
|
rural()
|
||||||
|
Returns whether the heat system is for rural areas.
|
||||||
|
urban_decentral()
|
||||||
|
Returns whether the heat system is for urban decentralized areas.
|
||||||
|
urban()
|
||||||
|
Returns whether the heat system is for urban areas.
|
||||||
|
heat_demand_weighting(urban_fraction=None, dist_fraction=None)
|
||||||
|
Calculates the heat demand weighting based on urban fraction and distribution fraction.
|
||||||
|
heat_pump_costs_name(heat_source)
|
||||||
|
Generates the name for the heat pump costs based on the heat source.
|
||||||
|
"""
|
||||||
|
|
||||||
|
RESIDENTIAL_RURAL = "residential rural"
|
||||||
|
SERVICES_RURAL = "services rural"
|
||||||
|
RESIDENTIAL_URBAN_DECENTRAL = "residential urban decentral"
|
||||||
|
SERVICES_URBAN_DECENTRAL = "services urban decentral"
|
||||||
|
URBAN_CENTRAL = "urban central"
|
||||||
|
|
||||||
|
def __init__(self, *args):
|
||||||
|
super().__init__(*args)
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
"""
|
||||||
|
Returns the string representation of the heat system.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
str
|
||||||
|
The string representation of the heat system.
|
||||||
|
"""
|
||||||
|
return self.value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def central_or_decentral(self) -> str:
|
||||||
|
"""
|
||||||
|
Returns whether the heat system is central or decentralized.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
str
|
||||||
|
"central" if the heat system is central, "decentral" otherwise.
|
||||||
|
"""
|
||||||
|
if self == HeatSystem.URBAN_CENTRAL:
|
||||||
|
return "central"
|
||||||
|
else:
|
||||||
|
return "decentral"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def system_type(self) -> HeatSystemType:
|
||||||
|
"""
|
||||||
|
Returns the type of the heat system.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
str
|
||||||
|
The type of the heat system.
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
RuntimeError
|
||||||
|
If the heat system is invalid.
|
||||||
|
"""
|
||||||
|
if self == HeatSystem.URBAN_CENTRAL:
|
||||||
|
return HeatSystemType.URBAN_CENTRAL
|
||||||
|
elif (
|
||||||
|
self == HeatSystem.RESIDENTIAL_URBAN_DECENTRAL
|
||||||
|
or self == HeatSystem.SERVICES_URBAN_DECENTRAL
|
||||||
|
):
|
||||||
|
return HeatSystemType.URBAN_DECENTRAL
|
||||||
|
elif self == HeatSystem.RESIDENTIAL_RURAL or self == HeatSystem.SERVICES_RURAL:
|
||||||
|
return HeatSystemType.RURAL
|
||||||
|
else:
|
||||||
|
raise RuntimeError(f"Invalid heat system: {self}")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sector(self) -> HeatSector:
|
||||||
|
"""
|
||||||
|
Returns the sector of the heat system.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
HeatSector
|
||||||
|
The sector of the heat system.
|
||||||
|
"""
|
||||||
|
if (
|
||||||
|
self == HeatSystem.RESIDENTIAL_RURAL
|
||||||
|
or self == HeatSystem.RESIDENTIAL_URBAN_DECENTRAL
|
||||||
|
):
|
||||||
|
return HeatSector.RESIDENTIAL
|
||||||
|
elif (
|
||||||
|
self == HeatSystem.SERVICES_RURAL
|
||||||
|
or self == HeatSystem.SERVICES_URBAN_DECENTRAL
|
||||||
|
):
|
||||||
|
return HeatSector.SERVICES
|
||||||
|
else:
|
||||||
|
"tot"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_rural(self) -> bool:
|
||||||
|
"""
|
||||||
|
Returns whether the heat system is for rural areas.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
bool
|
||||||
|
True if the heat system is for rural areas, False otherwise.
|
||||||
|
"""
|
||||||
|
if self == HeatSystem.RESIDENTIAL_RURAL or self == HeatSystem.SERVICES_RURAL:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_urban_decentral(self) -> bool:
|
||||||
|
"""
|
||||||
|
Returns whether the heat system is for urban decentralized areas.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
bool
|
||||||
|
True if the heat system is for urban decentralized areas, False otherwise.
|
||||||
|
"""
|
||||||
|
if (
|
||||||
|
self == HeatSystem.RESIDENTIAL_URBAN_DECENTRAL
|
||||||
|
or self == HeatSystem.SERVICES_URBAN_DECENTRAL
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_urban(self) -> bool:
|
||||||
|
"""
|
||||||
|
Returns whether the heat system is for urban areas.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
bool True if the heat system is for urban areas, False otherwise.
|
||||||
|
"""
|
||||||
|
return not self.is_rural
|
||||||
|
|
||||||
|
def heat_demand_weighting(self, urban_fraction=None, dist_fraction=None) -> float:
|
||||||
|
"""
|
||||||
|
Calculates the heat demand weighting based on urban fraction and
|
||||||
|
distribution fraction.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
urban_fraction : float, optional
|
||||||
|
The fraction of urban heat demand.
|
||||||
|
dist_fraction : float, optional
|
||||||
|
The fraction of distributed heat demand.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
float
|
||||||
|
The heat demand weighting.
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
RuntimeError
|
||||||
|
If the heat system is invalid.
|
||||||
|
"""
|
||||||
|
if "rural" in self.value:
|
||||||
|
return 1 - urban_fraction
|
||||||
|
elif "urban central" in self.value:
|
||||||
|
return dist_fraction
|
||||||
|
elif "urban decentral" in self.value:
|
||||||
|
return urban_fraction - dist_fraction
|
||||||
|
else:
|
||||||
|
raise RuntimeError(f"Invalid heat system: {self}")
|
||||||
|
|
||||||
|
def heat_pump_costs_name(self, heat_source: str) -> str:
|
||||||
|
"""
|
||||||
|
Generates the name for the heat pump costs based on the heat source and
|
||||||
|
system.
|
||||||
|
Used to retrieve data from `technology-data <https://github.com/PyPSA/technology-data>`.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
heat_source : str
|
||||||
|
The heat source.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
str
|
||||||
|
The name for the heat pump costs.
|
||||||
|
"""
|
||||||
|
return f"{self.central_or_decentral} {heat_source}-sourced heat pump"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def resistive_heater_costs_name(self) -> str:
|
||||||
|
"""
|
||||||
|
Generates the name for the resistive heater costs based on the heat
|
||||||
|
system.
|
||||||
|
Used to retrieve data from `technology-data <https://github.com/PyPSA/technology-data>`.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
str
|
||||||
|
The name for the heater costs.
|
||||||
|
"""
|
||||||
|
return f"{self.central_or_decentral} resistive heater"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def gas_boiler_costs_name(self) -> str:
|
||||||
|
"""
|
||||||
|
Generates the name for the gas boiler costs based on the heat system.
|
||||||
|
Used to retrieve data from `technology-data <https://github.com/PyPSA/technology-data>`.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
str
|
||||||
|
The name for the gas boiler costs.
|
||||||
|
"""
|
||||||
|
return f"{self.central_or_decentral} gas boiler"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def oil_boiler_costs_name(self) -> str:
|
||||||
|
"""
|
||||||
|
Generates the name for the oil boiler costs based on the heat system.
|
||||||
|
Used to retrieve data from `technology-data <https://github.com/PyPSA/technology-data>`.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
str
|
||||||
|
The name for the oil boiler costs.
|
||||||
|
"""
|
||||||
|
return "decentral oil boiler"
|
35
scripts/definitions/heat_system_type.py
Normal file
35
scripts/definitions/heat_system_type.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class HeatSystemType(Enum):
|
||||||
|
"""
|
||||||
|
Enumeration representing different types of heat systems.
|
||||||
|
"""
|
||||||
|
|
||||||
|
URBAN_CENTRAL = "urban central"
|
||||||
|
URBAN_DECENTRAL = "urban decentral"
|
||||||
|
RURAL = "rural"
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
"""
|
||||||
|
Returns the string representation of the heat system type.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The string representation of the heat system type.
|
||||||
|
"""
|
||||||
|
return self.value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_central(self) -> bool:
|
||||||
|
"""
|
||||||
|
Returns whether the heat system type is central.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if the heat system type is central, False otherwise.
|
||||||
|
"""
|
||||||
|
return self == HeatSystemType.URBAN_CENTRAL
|
@ -37,6 +37,10 @@ from pypsa.geo import haversine_pts
|
|||||||
from pypsa.io import import_components_from_dataframe
|
from pypsa.io import import_components_from_dataframe
|
||||||
from scipy.stats import beta
|
from scipy.stats import beta
|
||||||
|
|
||||||
|
from scripts.definitions.heat_sector import HeatSector
|
||||||
|
from scripts.definitions.heat_system import HeatSystem
|
||||||
|
from scripts.definitions.heat_system_type import HeatSystemType
|
||||||
|
|
||||||
spatial = SimpleNamespace()
|
spatial = SimpleNamespace()
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -56,19 +60,25 @@ def define_spatial(nodes, options):
|
|||||||
# biomass
|
# biomass
|
||||||
|
|
||||||
spatial.biomass = SimpleNamespace()
|
spatial.biomass = SimpleNamespace()
|
||||||
|
spatial.msw = SimpleNamespace()
|
||||||
|
|
||||||
if options.get("biomass_spatial", options["biomass_transport"]):
|
if options.get("biomass_spatial", options["biomass_transport"]):
|
||||||
spatial.biomass.nodes = nodes + " solid biomass"
|
spatial.biomass.nodes = nodes + " solid biomass"
|
||||||
spatial.biomass.locations = nodes
|
spatial.biomass.locations = nodes
|
||||||
spatial.biomass.industry = nodes + " solid biomass for industry"
|
spatial.biomass.industry = nodes + " solid biomass for industry"
|
||||||
spatial.biomass.industry_cc = nodes + " solid biomass for industry CC"
|
spatial.biomass.industry_cc = nodes + " solid biomass for industry CC"
|
||||||
|
spatial.msw.nodes = nodes + " municipal solid waste"
|
||||||
|
spatial.msw.locations = nodes
|
||||||
else:
|
else:
|
||||||
spatial.biomass.nodes = ["EU solid biomass"]
|
spatial.biomass.nodes = ["EU solid biomass"]
|
||||||
spatial.biomass.locations = ["EU"]
|
spatial.biomass.locations = ["EU"]
|
||||||
spatial.biomass.industry = ["solid biomass for industry"]
|
spatial.biomass.industry = ["solid biomass for industry"]
|
||||||
spatial.biomass.industry_cc = ["solid biomass for industry CC"]
|
spatial.biomass.industry_cc = ["solid biomass for industry CC"]
|
||||||
|
spatial.msw.nodes = ["EU municipal solid waste"]
|
||||||
|
spatial.msw.locations = ["EU"]
|
||||||
|
|
||||||
spatial.biomass.df = pd.DataFrame(vars(spatial.biomass), index=nodes)
|
spatial.biomass.df = pd.DataFrame(vars(spatial.biomass), index=nodes)
|
||||||
|
spatial.msw.df = pd.DataFrame(vars(spatial.msw), index=nodes)
|
||||||
|
|
||||||
# co2
|
# co2
|
||||||
|
|
||||||
@ -1770,7 +1780,7 @@ def build_heat_demand(n):
|
|||||||
.unstack(level=1)
|
.unstack(level=1)
|
||||||
)
|
)
|
||||||
|
|
||||||
sectors = ["residential", "services"]
|
sectors = [sector.value for sector in HeatSector]
|
||||||
uses = ["water", "space"]
|
uses = ["water", "space"]
|
||||||
|
|
||||||
heat_demand = {}
|
heat_demand = {}
|
||||||
@ -1798,10 +1808,21 @@ def build_heat_demand(n):
|
|||||||
return heat_demand
|
return heat_demand
|
||||||
|
|
||||||
|
|
||||||
def add_heat(n, costs):
|
def add_heat(n: pypsa.Network, costs: pd.DataFrame, cop: xr.DataArray):
|
||||||
|
"""
|
||||||
|
Add heat sector to the network.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
n (pypsa.Network): The PyPSA network object.
|
||||||
|
costs (pd.DataFrame): DataFrame containing cost information.
|
||||||
|
cop (xr.DataArray): DataArray containing coefficient of performance (COP) values.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None
|
||||||
|
"""
|
||||||
logger.info("Add heat sector")
|
logger.info("Add heat sector")
|
||||||
|
|
||||||
sectors = ["residential", "services"]
|
sectors = [sector.value for sector in HeatSector]
|
||||||
|
|
||||||
heat_demand = build_heat_demand(n)
|
heat_demand = build_heat_demand(n)
|
||||||
|
|
||||||
@ -1820,23 +1841,6 @@ def add_heat(n, costs):
|
|||||||
for sector in sectors:
|
for sector in sectors:
|
||||||
heat_demand[sector + " space"] = (1 - dE) * heat_demand[sector + " space"]
|
heat_demand[sector + " space"] = (1 - dE) * heat_demand[sector + " space"]
|
||||||
|
|
||||||
heat_systems = [
|
|
||||||
"residential rural",
|
|
||||||
"services rural",
|
|
||||||
"residential urban decentral",
|
|
||||||
"services urban decentral",
|
|
||||||
"urban central",
|
|
||||||
]
|
|
||||||
|
|
||||||
cop = {
|
|
||||||
"air": xr.open_dataarray(snakemake.input.cop_air_total)
|
|
||||||
.to_pandas()
|
|
||||||
.reindex(index=n.snapshots),
|
|
||||||
"ground": xr.open_dataarray(snakemake.input.cop_soil_total)
|
|
||||||
.to_pandas()
|
|
||||||
.reindex(index=n.snapshots),
|
|
||||||
}
|
|
||||||
|
|
||||||
if options["solar_thermal"]:
|
if options["solar_thermal"]:
|
||||||
solar_thermal = (
|
solar_thermal = (
|
||||||
xr.open_dataarray(snakemake.input.solar_thermal_total)
|
xr.open_dataarray(snakemake.input.solar_thermal_total)
|
||||||
@ -1846,31 +1850,34 @@ def add_heat(n, costs):
|
|||||||
# 1e3 converts from W/m^2 to MW/(1000m^2) = kW/m^2
|
# 1e3 converts from W/m^2 to MW/(1000m^2) = kW/m^2
|
||||||
solar_thermal = options["solar_cf_correction"] * solar_thermal / 1e3
|
solar_thermal = options["solar_cf_correction"] * solar_thermal / 1e3
|
||||||
|
|
||||||
for name in heat_systems:
|
for (
|
||||||
name_type = "central" if name == "urban central" else "decentral"
|
heat_system
|
||||||
|
) in (
|
||||||
|
HeatSystem
|
||||||
|
): # this loops through all heat systems defined in _entities.HeatSystem
|
||||||
|
|
||||||
if name == "urban central":
|
if heat_system == HeatSystem.URBAN_CENTRAL:
|
||||||
nodes = dist_fraction.index[dist_fraction > 0]
|
nodes = dist_fraction.index[dist_fraction > 0]
|
||||||
else:
|
else:
|
||||||
nodes = pop_layout.index
|
nodes = pop_layout.index
|
||||||
|
|
||||||
n.add("Carrier", name + " heat")
|
n.add("Carrier", f"{heat_system} heat")
|
||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Bus",
|
"Bus",
|
||||||
nodes + f" {name} heat",
|
nodes + f" {heat_system.value} heat",
|
||||||
location=nodes,
|
location=nodes,
|
||||||
carrier=name + " heat",
|
carrier=f"{heat_system.value} heat",
|
||||||
unit="MWh_th",
|
unit="MWh_th",
|
||||||
)
|
)
|
||||||
|
|
||||||
if name == "urban central" and options.get("central_heat_vent"):
|
if heat_system == HeatSystem.URBAN_CENTRAL and options.get("central_heat_vent"):
|
||||||
n.madd(
|
n.madd(
|
||||||
"Generator",
|
"Generator",
|
||||||
nodes + f" {name} heat vent",
|
nodes + f" {heat_system} heat vent",
|
||||||
bus=nodes + f" {name} heat",
|
bus=nodes + f" {heat_system} heat",
|
||||||
location=nodes,
|
location=nodes,
|
||||||
carrier=name + " heat vent",
|
carrier=f"{heat_system} heat vent",
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
p_max_pu=0,
|
p_max_pu=0,
|
||||||
p_min_pu=-1,
|
p_min_pu=-1,
|
||||||
@ -1878,30 +1885,24 @@ def add_heat(n, costs):
|
|||||||
)
|
)
|
||||||
|
|
||||||
## Add heat load
|
## Add heat load
|
||||||
|
factor = heat_system.heat_demand_weighting(
|
||||||
|
urban_fraction=urban_fraction[nodes], dist_fraction=dist_fraction[nodes]
|
||||||
|
)
|
||||||
|
if not heat_system == HeatSystem.URBAN_CENTRAL:
|
||||||
|
heat_load = (
|
||||||
|
heat_demand[
|
||||||
|
[
|
||||||
|
heat_system.sector.value + " water",
|
||||||
|
heat_system.sector.value + " space",
|
||||||
|
]
|
||||||
|
]
|
||||||
|
.T.groupby(level=1)
|
||||||
|
.sum()
|
||||||
|
.T[nodes]
|
||||||
|
.multiply(factor)
|
||||||
|
)
|
||||||
|
|
||||||
for sector in sectors:
|
if heat_system == HeatSystem.URBAN_CENTRAL:
|
||||||
# heat demand weighting
|
|
||||||
if "rural" in name:
|
|
||||||
factor = 1 - urban_fraction[nodes]
|
|
||||||
elif "urban central" in name:
|
|
||||||
factor = dist_fraction[nodes]
|
|
||||||
elif "urban decentral" in name:
|
|
||||||
factor = urban_fraction[nodes] - dist_fraction[nodes]
|
|
||||||
else:
|
|
||||||
raise NotImplementedError(
|
|
||||||
f" {name} not in " f"heat systems: {heat_systems}"
|
|
||||||
)
|
|
||||||
|
|
||||||
if sector in name:
|
|
||||||
heat_load = (
|
|
||||||
heat_demand[[sector + " water", sector + " space"]]
|
|
||||||
.T.groupby(level=1)
|
|
||||||
.sum()
|
|
||||||
.T[nodes]
|
|
||||||
.multiply(factor)
|
|
||||||
)
|
|
||||||
|
|
||||||
if name == "urban central":
|
|
||||||
heat_load = (
|
heat_load = (
|
||||||
heat_demand.T.groupby(level=1)
|
heat_demand.T.groupby(level=1)
|
||||||
.sum()
|
.sum()
|
||||||
@ -1914,20 +1915,25 @@ def add_heat(n, costs):
|
|||||||
n.madd(
|
n.madd(
|
||||||
"Load",
|
"Load",
|
||||||
nodes,
|
nodes,
|
||||||
suffix=f" {name} heat",
|
suffix=f" {heat_system} heat",
|
||||||
bus=nodes + f" {name} heat",
|
bus=nodes + f" {heat_system} heat",
|
||||||
carrier=name + " heat",
|
carrier=f"{heat_system} heat",
|
||||||
p_set=heat_load,
|
p_set=heat_load,
|
||||||
)
|
)
|
||||||
|
|
||||||
## Add heat pumps
|
## Add heat pumps
|
||||||
|
for heat_source in snakemake.params.heat_pump_sources[
|
||||||
heat_pump_types = ["air"] if "urban" in name else ["ground", "air"]
|
heat_system.system_type.value
|
||||||
|
]:
|
||||||
for heat_pump_type in heat_pump_types:
|
costs_name = heat_system.heat_pump_costs_name(heat_source)
|
||||||
costs_name = f"{name_type} {heat_pump_type}-sourced heat pump"
|
|
||||||
efficiency = (
|
efficiency = (
|
||||||
cop[heat_pump_type][nodes]
|
cop.sel(
|
||||||
|
heat_system=heat_system.system_type.value,
|
||||||
|
heat_source=heat_source,
|
||||||
|
name=nodes,
|
||||||
|
)
|
||||||
|
.to_pandas()
|
||||||
|
.reindex(index=n.snapshots)
|
||||||
if options["time_dep_hp_cop"]
|
if options["time_dep_hp_cop"]
|
||||||
else costs.at[costs_name, "efficiency"]
|
else costs.at[costs_name, "efficiency"]
|
||||||
)
|
)
|
||||||
@ -1935,10 +1941,10 @@ def add_heat(n, costs):
|
|||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
nodes,
|
nodes,
|
||||||
suffix=f" {name} {heat_pump_type} heat pump",
|
suffix=f" {heat_system} {heat_source} heat pump",
|
||||||
bus0=nodes,
|
bus0=nodes,
|
||||||
bus1=nodes + f" {name} heat",
|
bus1=nodes + f" {heat_system} heat",
|
||||||
carrier=f"{name} {heat_pump_type} heat pump",
|
carrier=f"{heat_system} {heat_source} heat pump",
|
||||||
efficiency=efficiency,
|
efficiency=efficiency,
|
||||||
capital_cost=costs.at[costs_name, "efficiency"]
|
capital_cost=costs.at[costs_name, "efficiency"]
|
||||||
* costs.at[costs_name, "fixed"]
|
* costs.at[costs_name, "fixed"]
|
||||||
@ -1948,59 +1954,65 @@ def add_heat(n, costs):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if options["tes"]:
|
if options["tes"]:
|
||||||
n.add("Carrier", name + " water tanks")
|
n.add("Carrier", f"{heat_system} water tanks")
|
||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Bus",
|
"Bus",
|
||||||
nodes + f" {name} water tanks",
|
nodes + f" {heat_system} water tanks",
|
||||||
location=nodes,
|
location=nodes,
|
||||||
carrier=name + " water tanks",
|
carrier=f"{heat_system} water tanks",
|
||||||
unit="MWh_th",
|
unit="MWh_th",
|
||||||
)
|
)
|
||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
nodes + f" {name} water tanks charger",
|
nodes + f" {heat_system} water tanks charger",
|
||||||
bus0=nodes + f" {name} heat",
|
bus0=nodes + f" {heat_system} heat",
|
||||||
bus1=nodes + f" {name} water tanks",
|
bus1=nodes + f" {heat_system} water tanks",
|
||||||
efficiency=costs.at["water tank charger", "efficiency"],
|
efficiency=costs.at["water tank charger", "efficiency"],
|
||||||
carrier=name + " water tanks charger",
|
carrier=f"{heat_system} water tanks charger",
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
nodes + f" {name} water tanks discharger",
|
nodes + f" {heat_system} water tanks discharger",
|
||||||
bus0=nodes + f" {name} water tanks",
|
bus0=nodes + f" {heat_system} water tanks",
|
||||||
bus1=nodes + f" {name} heat",
|
bus1=nodes + f" {heat_system} heat",
|
||||||
carrier=name + " water tanks discharger",
|
carrier=f"{heat_system} water tanks discharger",
|
||||||
efficiency=costs.at["water tank discharger", "efficiency"],
|
efficiency=costs.at["water tank discharger", "efficiency"],
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
tes_time_constant_days = options["tes_tau"][name_type]
|
tes_time_constant_days = options["tes_tau"][
|
||||||
|
heat_system.central_or_decentral
|
||||||
|
]
|
||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Store",
|
"Store",
|
||||||
nodes + f" {name} water tanks",
|
nodes + f" {heat_system} water tanks",
|
||||||
bus=nodes + f" {name} water tanks",
|
bus=nodes + f" {heat_system} water tanks",
|
||||||
e_cyclic=True,
|
e_cyclic=True,
|
||||||
e_nom_extendable=True,
|
e_nom_extendable=True,
|
||||||
carrier=name + " water tanks",
|
carrier=f"{heat_system} water tanks",
|
||||||
standing_loss=1 - np.exp(-1 / 24 / tes_time_constant_days),
|
standing_loss=1 - np.exp(-1 / 24 / tes_time_constant_days),
|
||||||
capital_cost=costs.at[name_type + " water tank storage", "fixed"],
|
capital_cost=costs.at[
|
||||||
lifetime=costs.at[name_type + " water tank storage", "lifetime"],
|
heat_system.central_or_decentral + " water tank storage", "fixed"
|
||||||
|
],
|
||||||
|
lifetime=costs.at[
|
||||||
|
heat_system.central_or_decentral + " water tank storage", "lifetime"
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
if options["resistive_heaters"]:
|
if options["resistive_heaters"]:
|
||||||
key = f"{name_type} resistive heater"
|
key = f"{heat_system.central_or_decentral} resistive heater"
|
||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
nodes + f" {name} resistive heater",
|
nodes + f" {heat_system} resistive heater",
|
||||||
bus0=nodes,
|
bus0=nodes,
|
||||||
bus1=nodes + f" {name} heat",
|
bus1=nodes + f" {heat_system} heat",
|
||||||
carrier=name + " resistive heater",
|
carrier=f"{heat_system} resistive heater",
|
||||||
efficiency=costs.at[key, "efficiency"],
|
efficiency=costs.at[key, "efficiency"],
|
||||||
capital_cost=costs.at[key, "efficiency"]
|
capital_cost=costs.at[key, "efficiency"]
|
||||||
* costs.at[key, "fixed"]
|
* costs.at[key, "fixed"]
|
||||||
@ -2010,16 +2022,16 @@ def add_heat(n, costs):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if options["boilers"]:
|
if options["boilers"]:
|
||||||
key = f"{name_type} gas boiler"
|
key = f"{heat_system.central_or_decentral} gas boiler"
|
||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
nodes + f" {name} gas boiler",
|
nodes + f" {heat_system} gas boiler",
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
bus0=spatial.gas.df.loc[nodes, "nodes"].values,
|
bus0=spatial.gas.df.loc[nodes, "nodes"].values,
|
||||||
bus1=nodes + f" {name} heat",
|
bus1=nodes + f" {heat_system} heat",
|
||||||
bus2="co2 atmosphere",
|
bus2="co2 atmosphere",
|
||||||
carrier=name + " gas boiler",
|
carrier=f"{heat_system} gas boiler",
|
||||||
efficiency=costs.at[key, "efficiency"],
|
efficiency=costs.at[key, "efficiency"],
|
||||||
efficiency2=costs.at["gas", "CO2 intensity"],
|
efficiency2=costs.at["gas", "CO2 intensity"],
|
||||||
capital_cost=costs.at[key, "efficiency"]
|
capital_cost=costs.at[key, "efficiency"]
|
||||||
@ -2029,22 +2041,26 @@ def add_heat(n, costs):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if options["solar_thermal"]:
|
if options["solar_thermal"]:
|
||||||
n.add("Carrier", name + " solar thermal")
|
n.add("Carrier", f"{heat_system} solar thermal")
|
||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Generator",
|
"Generator",
|
||||||
nodes,
|
nodes,
|
||||||
suffix=f" {name} solar thermal collector",
|
suffix=f" {heat_system} solar thermal collector",
|
||||||
bus=nodes + f" {name} heat",
|
bus=nodes + f" {heat_system} heat",
|
||||||
carrier=name + " solar thermal",
|
carrier=f"{heat_system} solar thermal",
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
capital_cost=costs.at[name_type + " solar thermal", "fixed"]
|
capital_cost=costs.at[
|
||||||
|
heat_system.central_or_decentral + " solar thermal", "fixed"
|
||||||
|
]
|
||||||
* overdim_factor,
|
* overdim_factor,
|
||||||
p_max_pu=solar_thermal[nodes],
|
p_max_pu=solar_thermal[nodes],
|
||||||
lifetime=costs.at[name_type + " solar thermal", "lifetime"],
|
lifetime=costs.at[
|
||||||
|
heat_system.central_or_decentral + " solar thermal", "lifetime"
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
if options["chp"] and name == "urban central":
|
if options["chp"] and heat_system == HeatSystem.URBAN_CENTRAL:
|
||||||
# add gas CHP; biomass CHP is added in biomass section
|
# add gas CHP; biomass CHP is added in biomass section
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
@ -2101,16 +2117,20 @@ def add_heat(n, costs):
|
|||||||
lifetime=costs.at["central gas CHP", "lifetime"],
|
lifetime=costs.at["central gas CHP", "lifetime"],
|
||||||
)
|
)
|
||||||
|
|
||||||
if options["chp"] and options["micro_chp"] and name != "urban central":
|
if (
|
||||||
|
options["chp"]
|
||||||
|
and options["micro_chp"]
|
||||||
|
and heat_system.value != "urban central"
|
||||||
|
):
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
nodes + f" {name} micro gas CHP",
|
nodes + f" {heat_system} micro gas CHP",
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
bus0=spatial.gas.df.loc[nodes, "nodes"].values,
|
bus0=spatial.gas.df.loc[nodes, "nodes"].values,
|
||||||
bus1=nodes,
|
bus1=nodes,
|
||||||
bus2=nodes + f" {name} heat",
|
bus2=nodes + f" {heat_system} heat",
|
||||||
bus3="co2 atmosphere",
|
bus3="co2 atmosphere",
|
||||||
carrier=name + " micro gas CHP",
|
carrier=heat_system.value + " micro gas CHP",
|
||||||
efficiency=costs.at["micro CHP", "efficiency"],
|
efficiency=costs.at["micro CHP", "efficiency"],
|
||||||
efficiency2=costs.at["micro CHP", "efficiency-heat"],
|
efficiency2=costs.at["micro CHP", "efficiency-heat"],
|
||||||
efficiency3=costs.at["gas", "CO2 intensity"],
|
efficiency3=costs.at["gas", "CO2 intensity"],
|
||||||
@ -2146,7 +2166,7 @@ def add_heat(n, costs):
|
|||||||
) / heat_demand.T.groupby(level=[1]).sum().T
|
) / heat_demand.T.groupby(level=[1]).sum().T
|
||||||
|
|
||||||
for name in n.loads[
|
for name in n.loads[
|
||||||
n.loads.carrier.isin([x + " heat" for x in heat_systems])
|
n.loads.carrier.isin([x + " heat" for x in HeatSystem])
|
||||||
].index:
|
].index:
|
||||||
node = n.buses.loc[name, "location"]
|
node = n.buses.loc[name, "location"]
|
||||||
ct = pop_layout.loc[node, "ct"]
|
ct = pop_layout.loc[node, "ct"]
|
||||||
@ -2249,12 +2269,54 @@ def add_biomass(n, costs):
|
|||||||
solid_biomass_potentials_spatial = biomass_potentials["solid biomass"].rename(
|
solid_biomass_potentials_spatial = biomass_potentials["solid biomass"].rename(
|
||||||
index=lambda x: x + " solid biomass"
|
index=lambda x: x + " solid biomass"
|
||||||
)
|
)
|
||||||
|
msw_biomass_potentials_spatial = biomass_potentials[
|
||||||
|
"municipal solid waste"
|
||||||
|
].rename(index=lambda x: x + " municipal solid waste")
|
||||||
else:
|
else:
|
||||||
solid_biomass_potentials_spatial = biomass_potentials["solid biomass"].sum()
|
solid_biomass_potentials_spatial = biomass_potentials["solid biomass"].sum()
|
||||||
|
msw_biomass_potentials_spatial = biomass_potentials[
|
||||||
|
"municipal solid waste"
|
||||||
|
].sum()
|
||||||
|
|
||||||
n.add("Carrier", "biogas")
|
n.add("Carrier", "biogas")
|
||||||
n.add("Carrier", "solid biomass")
|
n.add("Carrier", "solid biomass")
|
||||||
|
|
||||||
|
if (
|
||||||
|
options["municipal_solid_waste"]
|
||||||
|
and not options["industry"]
|
||||||
|
and cf_industry["waste_to_energy"]
|
||||||
|
or cf_industry["waste_to_energy_cc"]
|
||||||
|
):
|
||||||
|
logger.warning(
|
||||||
|
"Flag municipal_solid_waste can be only used with industry "
|
||||||
|
"sector waste to energy."
|
||||||
|
"Setting municipal_solid_waste=False."
|
||||||
|
)
|
||||||
|
options["municipal_solid_waste"] = False
|
||||||
|
|
||||||
|
if options["municipal_solid_waste"]:
|
||||||
|
|
||||||
|
n.add("Carrier", "municipal solid waste")
|
||||||
|
|
||||||
|
n.madd(
|
||||||
|
"Bus",
|
||||||
|
spatial.msw.nodes,
|
||||||
|
location=spatial.msw.locations,
|
||||||
|
carrier="municipal solid waste",
|
||||||
|
)
|
||||||
|
|
||||||
|
e_max_pu = pd.Series([1] * (len(n.snapshots) - 1) + [0], index=n.snapshots)
|
||||||
|
n.madd(
|
||||||
|
"Store",
|
||||||
|
spatial.msw.nodes,
|
||||||
|
bus=spatial.msw.nodes,
|
||||||
|
carrier="municipal solid waste",
|
||||||
|
e_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,
|
||||||
|
)
|
||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Bus",
|
"Bus",
|
||||||
spatial.gas.biogas,
|
spatial.gas.biogas,
|
||||||
@ -2291,6 +2353,54 @@ def add_biomass(n, costs):
|
|||||||
e_initial=solid_biomass_potentials_spatial,
|
e_initial=solid_biomass_potentials_spatial,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if options["solid_biomass_import"].get("enable", False):
|
||||||
|
biomass_import_price = options["solid_biomass_import"]["price"]
|
||||||
|
# convert TWh in MWh
|
||||||
|
biomass_import_max_amount = options["solid_biomass_import"]["max_amount"] * 1e6
|
||||||
|
biomass_import_upstream_emissions = options["solid_biomass_import"][
|
||||||
|
"upstream_emissions_factor"
|
||||||
|
]
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
"Adding biomass import with cost %.2f EUR/MWh, a limit of %.2f TWh, and embedded emissions of %.2f%%",
|
||||||
|
biomass_import_price,
|
||||||
|
options["solid_biomass_import"]["max_amount"],
|
||||||
|
biomass_import_upstream_emissions * 100,
|
||||||
|
)
|
||||||
|
|
||||||
|
n.add("Carrier", "solid biomass import")
|
||||||
|
|
||||||
|
n.madd(
|
||||||
|
"Bus",
|
||||||
|
["EU solid biomass import"],
|
||||||
|
location="EU",
|
||||||
|
carrier="solid biomass import",
|
||||||
|
)
|
||||||
|
|
||||||
|
n.madd(
|
||||||
|
"Store",
|
||||||
|
["solid biomass import"],
|
||||||
|
bus=["EU solid biomass import"],
|
||||||
|
carrier="solid biomass import",
|
||||||
|
e_nom=biomass_import_max_amount,
|
||||||
|
marginal_cost=biomass_import_price,
|
||||||
|
e_initial=biomass_import_max_amount,
|
||||||
|
)
|
||||||
|
|
||||||
|
n.madd(
|
||||||
|
"Link",
|
||||||
|
spatial.biomass.nodes,
|
||||||
|
suffix=" solid biomass import",
|
||||||
|
bus0=["EU solid biomass import"],
|
||||||
|
bus1=spatial.biomass.nodes,
|
||||||
|
bus2="co2 atmosphere",
|
||||||
|
carrier="solid biomass import",
|
||||||
|
efficiency=1.0,
|
||||||
|
efficiency2=biomass_import_upstream_emissions
|
||||||
|
* costs.at["solid biomass", "CO2 intensity"],
|
||||||
|
p_nom_extendable=True,
|
||||||
|
)
|
||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
spatial.gas.biogas_to_gas,
|
spatial.gas.biogas_to_gas,
|
||||||
@ -2362,6 +2472,19 @@ def add_biomass(n, costs):
|
|||||||
carrier="solid biomass transport",
|
carrier="solid biomass transport",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if options["municipal_solid_waste"]:
|
||||||
|
n.madd(
|
||||||
|
"Link",
|
||||||
|
biomass_transport.index,
|
||||||
|
bus0=biomass_transport.bus0 + " municipal solid waste",
|
||||||
|
bus1=biomass_transport.bus1 + " municipal solid waste",
|
||||||
|
p_nom_extendable=False,
|
||||||
|
p_nom=5e4,
|
||||||
|
length=biomass_transport.length.values,
|
||||||
|
marginal_cost=biomass_transport.costs * biomass_transport.length.values,
|
||||||
|
carrier="municipal solid waste transport",
|
||||||
|
)
|
||||||
|
|
||||||
elif options["biomass_spatial"]:
|
elif options["biomass_spatial"]:
|
||||||
# add artificial biomass generators at nodes which include transport costs
|
# add artificial biomass generators at nodes which include transport costs
|
||||||
transport_costs = pd.read_csv(
|
transport_costs = pd.read_csv(
|
||||||
@ -2391,6 +2514,26 @@ def add_biomass(n, costs):
|
|||||||
type="operational_limit",
|
type="operational_limit",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if options["municipal_solid_waste"]:
|
||||||
|
# Add municipal solid waste
|
||||||
|
n.madd(
|
||||||
|
"Generator",
|
||||||
|
spatial.msw.nodes,
|
||||||
|
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,
|
||||||
|
)
|
||||||
|
n.add(
|
||||||
|
"GlobalConstraint",
|
||||||
|
"msw limit",
|
||||||
|
carrier_attribute="municipal solid waste",
|
||||||
|
sense="<=",
|
||||||
|
constant=biomass_potentials["municipal solid waste"].sum(),
|
||||||
|
type="operational_limit",
|
||||||
|
)
|
||||||
|
|
||||||
# AC buses with district heating
|
# AC buses with district heating
|
||||||
urban_central = n.buses.index[n.buses.carrier == "urban central heat"]
|
urban_central = n.buses.index[n.buses.carrier == "urban central heat"]
|
||||||
if not urban_central.empty and options["chp"]:
|
if not urban_central.empty and options["chp"]:
|
||||||
@ -2423,28 +2566,23 @@ def add_biomass(n, costs):
|
|||||||
bus4=spatial.co2.df.loc[urban_central, "nodes"].values,
|
bus4=spatial.co2.df.loc[urban_central, "nodes"].values,
|
||||||
carrier="urban central solid biomass CHP CC",
|
carrier="urban central solid biomass CHP CC",
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
capital_cost=costs.at[key, "fixed"] * costs.at[key, "efficiency"]
|
capital_cost=costs.at[key + " CC", "fixed"]
|
||||||
|
* costs.at[key + " CC", "efficiency"]
|
||||||
+ costs.at["biomass CHP capture", "fixed"]
|
+ costs.at["biomass CHP capture", "fixed"]
|
||||||
* costs.at["solid biomass", "CO2 intensity"],
|
* costs.at["solid biomass", "CO2 intensity"],
|
||||||
marginal_cost=costs.at[key, "VOM"],
|
marginal_cost=costs.at[key + " CC", "VOM"],
|
||||||
efficiency=costs.at[key, "efficiency"]
|
efficiency=costs.at[key + " CC", "efficiency"]
|
||||||
- costs.at["solid biomass", "CO2 intensity"]
|
- costs.at["solid biomass", "CO2 intensity"]
|
||||||
* (
|
* (
|
||||||
costs.at["biomass CHP capture", "electricity-input"]
|
costs.at["biomass CHP capture", "electricity-input"]
|
||||||
+ costs.at["biomass CHP capture", "compression-electricity-input"]
|
+ costs.at["biomass CHP capture", "compression-electricity-input"]
|
||||||
),
|
),
|
||||||
efficiency2=costs.at[key, "efficiency-heat"]
|
efficiency2=costs.at[key + " CC", "efficiency-heat"],
|
||||||
+ costs.at["solid biomass", "CO2 intensity"]
|
|
||||||
* (
|
|
||||||
costs.at["biomass CHP capture", "heat-output"]
|
|
||||||
+ costs.at["biomass CHP capture", "compression-heat-output"]
|
|
||||||
- costs.at["biomass CHP capture", "heat-input"]
|
|
||||||
),
|
|
||||||
efficiency3=-costs.at["solid biomass", "CO2 intensity"]
|
efficiency3=-costs.at["solid biomass", "CO2 intensity"]
|
||||||
* costs.at["biomass CHP capture", "capture_rate"],
|
* costs.at["biomass CHP capture", "capture_rate"],
|
||||||
efficiency4=costs.at["solid biomass", "CO2 intensity"]
|
efficiency4=costs.at["solid biomass", "CO2 intensity"]
|
||||||
* costs.at["biomass CHP capture", "capture_rate"],
|
* costs.at["biomass CHP capture", "capture_rate"],
|
||||||
lifetime=costs.at[key, "lifetime"],
|
lifetime=costs.at[key + " CC", "lifetime"],
|
||||||
)
|
)
|
||||||
|
|
||||||
if options["biomass_boiler"]:
|
if options["biomass_boiler"]:
|
||||||
@ -2486,11 +2624,12 @@ def add_biomass(n, costs):
|
|||||||
efficiency2=-costs.at["solid biomass", "CO2 intensity"]
|
efficiency2=-costs.at["solid biomass", "CO2 intensity"]
|
||||||
+ costs.at["BtL", "CO2 stored"],
|
+ costs.at["BtL", "CO2 stored"],
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
capital_cost=costs.at["BtL", "fixed"],
|
capital_cost=costs.at["BtL", "fixed"] * costs.at["BtL", "efficiency"],
|
||||||
marginal_cost=costs.at["BtL", "efficiency"] * costs.at["BtL", "VOM"],
|
marginal_cost=costs.at["BtL", "VOM"] * costs.at["BtL", "efficiency"],
|
||||||
)
|
)
|
||||||
|
|
||||||
# TODO: Update with energy penalty
|
# Assuming that acid gas removal (incl. CO2) from syngas i performed with Rectisol
|
||||||
|
# process (Methanol) and that electricity demand for this is included in the base process
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
spatial.biomass.nodes,
|
spatial.biomass.nodes,
|
||||||
@ -2506,9 +2645,46 @@ def add_biomass(n, costs):
|
|||||||
+ costs.at["BtL", "CO2 stored"] * (1 - costs.at["BtL", "capture rate"]),
|
+ costs.at["BtL", "CO2 stored"] * (1 - costs.at["BtL", "capture rate"]),
|
||||||
efficiency3=costs.at["BtL", "CO2 stored"] * costs.at["BtL", "capture rate"],
|
efficiency3=costs.at["BtL", "CO2 stored"] * costs.at["BtL", "capture rate"],
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
capital_cost=costs.at["BtL", "fixed"]
|
capital_cost=costs.at["BtL", "fixed"] * costs.at["BtL", "efficiency"]
|
||||||
+ costs.at["biomass CHP capture", "fixed"] * costs.at["BtL", "CO2 stored"],
|
+ costs.at["biomass CHP capture", "fixed"] * costs.at["BtL", "CO2 stored"],
|
||||||
marginal_cost=costs.at["BtL", "efficiency"] * costs.at["BtL", "VOM"],
|
marginal_cost=costs.at["BtL", "VOM"] * costs.at["BtL", "efficiency"],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Electrobiofuels (BtL with hydrogen addition to make more use of biogenic carbon).
|
||||||
|
# Combination of efuels and biomass to liquid, both based on Fischer-Tropsch.
|
||||||
|
# Experimental version - use with caution
|
||||||
|
if options["electrobiofuels"]:
|
||||||
|
|
||||||
|
efuel_scale_factor = costs.at["BtL", "C stored"]
|
||||||
|
name = (
|
||||||
|
pd.Index(spatial.biomass.nodes)
|
||||||
|
+ " "
|
||||||
|
+ pd.Index(spatial.h2.nodes.str.replace(" H2", ""))
|
||||||
|
)
|
||||||
|
n.madd(
|
||||||
|
"Link",
|
||||||
|
name,
|
||||||
|
suffix=" electrobiofuels",
|
||||||
|
bus0=spatial.biomass.nodes,
|
||||||
|
bus1=spatial.oil.nodes,
|
||||||
|
bus2=spatial.h2.nodes,
|
||||||
|
bus3="co2 atmosphere",
|
||||||
|
carrier="electrobiofuels",
|
||||||
|
lifetime=costs.at["electrobiofuels", "lifetime"],
|
||||||
|
efficiency=costs.at["electrobiofuels", "efficiency-biomass"],
|
||||||
|
efficiency2=-costs.at["electrobiofuels", "efficiency-hydrogen"],
|
||||||
|
efficiency3=-costs.at["solid biomass", "CO2 intensity"]
|
||||||
|
+ costs.at["BtL", "CO2 stored"]
|
||||||
|
* (1 - costs.at["Fischer-Tropsch", "capture rate"]),
|
||||||
|
p_nom_extendable=True,
|
||||||
|
capital_cost=costs.at["BtL", "fixed"] * costs.at["BtL", "efficiency"]
|
||||||
|
+ efuel_scale_factor
|
||||||
|
* costs.at["Fischer-Tropsch", "fixed"]
|
||||||
|
* costs.at["Fischer-Tropsch", "efficiency"],
|
||||||
|
marginal_cost=costs.at["BtL", "VOM"] * costs.at["BtL", "efficiency"]
|
||||||
|
+ efuel_scale_factor
|
||||||
|
* costs.at["Fischer-Tropsch", "VOM"]
|
||||||
|
* costs.at["Fischer-Tropsch", "efficiency"],
|
||||||
)
|
)
|
||||||
|
|
||||||
# BioSNG from solid biomass
|
# BioSNG from solid biomass
|
||||||
@ -2526,11 +2702,12 @@ def add_biomass(n, costs):
|
|||||||
efficiency3=-costs.at["solid biomass", "CO2 intensity"]
|
efficiency3=-costs.at["solid biomass", "CO2 intensity"]
|
||||||
+ costs.at["BioSNG", "CO2 stored"],
|
+ costs.at["BioSNG", "CO2 stored"],
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
capital_cost=costs.at["BioSNG", "fixed"],
|
capital_cost=costs.at["BioSNG", "fixed"] * costs.at["BioSNG", "efficiency"],
|
||||||
marginal_cost=costs.at["BioSNG", "efficiency"] * costs.at["BioSNG", "VOM"],
|
marginal_cost=costs.at["BioSNG", "VOM"] * costs.at["BioSNG", "efficiency"],
|
||||||
)
|
)
|
||||||
|
|
||||||
# TODO: Update with energy penalty for CC
|
# Assuming that acid gas removal (incl. CO2) from syngas i performed with Rectisol
|
||||||
|
# process (Methanol) and that electricity demand for this is included in the base process
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
spatial.biomass.nodes,
|
spatial.biomass.nodes,
|
||||||
@ -2548,10 +2725,10 @@ def add_biomass(n, costs):
|
|||||||
+ costs.at["BioSNG", "CO2 stored"]
|
+ costs.at["BioSNG", "CO2 stored"]
|
||||||
* (1 - costs.at["BioSNG", "capture rate"]),
|
* (1 - costs.at["BioSNG", "capture rate"]),
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
capital_cost=costs.at["BioSNG", "fixed"]
|
capital_cost=costs.at["BioSNG", "fixed"] * costs.at["BioSNG", "efficiency"]
|
||||||
+ costs.at["biomass CHP capture", "fixed"]
|
+ costs.at["biomass CHP capture", "fixed"]
|
||||||
* costs.at["BioSNG", "CO2 stored"],
|
* costs.at["BioSNG", "CO2 stored"],
|
||||||
marginal_cost=costs.at["BioSNG", "efficiency"] * costs.at["BioSNG", "VOM"],
|
marginal_cost=costs.at["BioSNG", "VOM"] * costs.at["BioSNG", "efficiency"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -2947,27 +3124,23 @@ def add_industry(n, costs):
|
|||||||
if options["oil_boilers"]:
|
if options["oil_boilers"]:
|
||||||
nodes = pop_layout.index
|
nodes = pop_layout.index
|
||||||
|
|
||||||
for name in [
|
for heat_system in HeatSystem:
|
||||||
"residential rural",
|
if not heat_system == HeatSystem.URBAN_CENTRAL:
|
||||||
"services rural",
|
n.madd(
|
||||||
"residential urban decentral",
|
"Link",
|
||||||
"services urban decentral",
|
nodes + f" {heat_system} oil boiler",
|
||||||
]:
|
p_nom_extendable=True,
|
||||||
n.madd(
|
bus0=spatial.oil.nodes,
|
||||||
"Link",
|
bus1=nodes + f" {heat_system} heat",
|
||||||
nodes + f" {name} oil boiler",
|
bus2="co2 atmosphere",
|
||||||
p_nom_extendable=True,
|
carrier=f"{heat_system} oil boiler",
|
||||||
bus0=spatial.oil.nodes,
|
efficiency=costs.at["decentral oil boiler", "efficiency"],
|
||||||
bus1=nodes + f" {name} heat",
|
efficiency2=costs.at["oil", "CO2 intensity"],
|
||||||
bus2="co2 atmosphere",
|
capital_cost=costs.at["decentral oil boiler", "efficiency"]
|
||||||
carrier=f"{name} oil boiler",
|
* costs.at["decentral oil boiler", "fixed"]
|
||||||
efficiency=costs.at["decentral oil boiler", "efficiency"],
|
* options["overdimension_individual_heating"],
|
||||||
efficiency2=costs.at["oil", "CO2 intensity"],
|
lifetime=costs.at["decentral oil boiler", "lifetime"],
|
||||||
capital_cost=costs.at["decentral oil boiler", "efficiency"]
|
)
|
||||||
* costs.at["decentral oil boiler", "fixed"]
|
|
||||||
* options["overdimension_individual_heating"],
|
|
||||||
lifetime=costs.at["decentral oil boiler", "lifetime"],
|
|
||||||
)
|
|
||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
@ -3062,6 +3235,17 @@ def add_industry(n, costs):
|
|||||||
efficiency3=process_co2_per_naphtha,
|
efficiency3=process_co2_per_naphtha,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if options.get("biomass", True) and options["municipal_solid_waste"]:
|
||||||
|
n.madd(
|
||||||
|
"Link",
|
||||||
|
spatial.msw.locations,
|
||||||
|
bus0=spatial.msw.nodes,
|
||||||
|
bus1=non_sequestered_hvc_locations,
|
||||||
|
carrier="municipal solid waste",
|
||||||
|
p_nom_extendable=True,
|
||||||
|
efficiency=1.0,
|
||||||
|
)
|
||||||
|
|
||||||
n.madd(
|
n.madd(
|
||||||
"Link",
|
"Link",
|
||||||
spatial.oil.demand_locations,
|
spatial.oil.demand_locations,
|
||||||
@ -3111,7 +3295,9 @@ def add_industry(n, costs):
|
|||||||
carrier="waste CHP CC",
|
carrier="waste CHP CC",
|
||||||
p_nom_extendable=True,
|
p_nom_extendable=True,
|
||||||
capital_cost=costs.at["waste CHP CC", "fixed"]
|
capital_cost=costs.at["waste CHP CC", "fixed"]
|
||||||
* costs.at["waste CHP CC", "efficiency"],
|
* costs.at["waste CHP CC", "efficiency"]
|
||||||
|
+ costs.at["biomass CHP capture", "fixed"]
|
||||||
|
* costs.at["oil", "CO2 intensity"],
|
||||||
marginal_cost=costs.at["waste CHP CC", "VOM"],
|
marginal_cost=costs.at["waste CHP CC", "VOM"],
|
||||||
efficiency=costs.at["waste CHP CC", "efficiency"],
|
efficiency=costs.at["waste CHP CC", "efficiency"],
|
||||||
efficiency2=costs.at["waste CHP CC", "efficiency-heat"],
|
efficiency2=costs.at["waste CHP CC", "efficiency-heat"],
|
||||||
@ -3952,7 +4138,7 @@ if __name__ == "__main__":
|
|||||||
"prepare_sector_network",
|
"prepare_sector_network",
|
||||||
simpl="",
|
simpl="",
|
||||||
opts="",
|
opts="",
|
||||||
clusters="1",
|
clusters="37",
|
||||||
ll="vopt",
|
ll="vopt",
|
||||||
sector_opts="",
|
sector_opts="",
|
||||||
planning_horizons="2050",
|
planning_horizons="2050",
|
||||||
@ -4010,7 +4196,7 @@ if __name__ == "__main__":
|
|||||||
add_land_transport(n, costs)
|
add_land_transport(n, costs)
|
||||||
|
|
||||||
if options["heating"]:
|
if options["heating"]:
|
||||||
add_heat(n, costs)
|
add_heat(n=n, costs=costs, cop=xr.open_dataarray(snakemake.input.cop_profiles))
|
||||||
|
|
||||||
if options["biomass"]:
|
if options["biomass"]:
|
||||||
add_biomass(n, costs)
|
add_biomass(n, costs)
|
||||||
|
Loading…
Reference in New Issue
Block a user