Merge pull request #737 from PyPSA/wildcard-opts-config
Add wildcards option in config (full backward compatibility)
This commit is contained in:
commit
f6fbd00787
@ -59,6 +59,9 @@ snapshots:
|
||||
start: "2013-01-01"
|
||||
end: "2014-01-01"
|
||||
inclusive: 'left'
|
||||
resolution: false
|
||||
segmentation: false
|
||||
#representative: false
|
||||
|
||||
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#enable
|
||||
enable:
|
||||
@ -74,6 +77,7 @@ enable:
|
||||
retrieve_natura_raster: true
|
||||
custom_busmap: false
|
||||
|
||||
|
||||
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#co2-budget
|
||||
co2_budget:
|
||||
2020: 0.701
|
||||
@ -87,7 +91,9 @@ co2_budget:
|
||||
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#electricity
|
||||
electricity:
|
||||
voltages: [220., 300., 380., 500., 750.]
|
||||
gaslimit_enable: false
|
||||
gaslimit: false
|
||||
co2limit_enable: false
|
||||
co2limit: 7.75e+7
|
||||
co2base: 1.487e+9
|
||||
agg_p_nom_limits: data/agg_p_nom_minmax.csv
|
||||
@ -124,6 +130,10 @@ electricity:
|
||||
Onshore: [onwind]
|
||||
PV: [solar]
|
||||
|
||||
autarky:
|
||||
enable: false
|
||||
by_country: false
|
||||
|
||||
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#atlite
|
||||
atlite:
|
||||
default_cutout: europe-2013-era5
|
||||
@ -618,7 +628,9 @@ costs:
|
||||
battery: 0.
|
||||
battery inverter: 0.
|
||||
emission_prices:
|
||||
enable: false
|
||||
co2: 0.
|
||||
co2_monthly_prices: false
|
||||
|
||||
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#clustering
|
||||
clustering:
|
||||
@ -660,6 +672,12 @@ solving:
|
||||
linearized_unit_commitment: true
|
||||
horizon: 365
|
||||
|
||||
constraints:
|
||||
CCL: false
|
||||
EQ: false
|
||||
BAU: false
|
||||
SAFE: false
|
||||
|
||||
solver:
|
||||
name: gurobi
|
||||
options: gurobi-default
|
||||
|
@ -1,9 +1,11 @@
|
||||
,Unit,Values,Description
|
||||
year,--,"YYYY; e.g. '2030'","Year for which to retrieve cost assumptions of ``resources/costs.csv``."
|
||||
version,--,"vX.X.X; e.g. 'v0.5.0'","Version of ``technology-data`` repository to use."
|
||||
rooftop_share,--,float,"Share of rooftop PV when calculating capital cost of solar (joint rooftop and utility-scale PV)."
|
||||
fill_values,--,float,"Default values if not specified for a technology in ``resources/costs.csv``."
|
||||
capital_cost,EUR/MW,"Keys should be in the 'technology' column of ``resources/costs.csv``. Values can be any float.","For the given technologies, assumptions about their capital investment costs are set to the corresponding value. Optional; overwrites cost assumptions from ``resources/costs.csv``."
|
||||
marginal_cost,EUR/MWh,"Keys should be in the 'technology' column of ``resources/costs.csv``. Values can be any float.","For the given technologies, assumptions about their marginal operating costs are set to the corresponding value. Optional; overwrites cost assumptions from ``resources/costs.csv``."
|
||||
emission_prices,,,"Specify exogenous prices for emission types listed in ``network.carriers`` to marginal costs."
|
||||
-- co2,EUR/t,float,"Exogenous price of carbon-dioxide added to the marginal costs of fossil-fuelled generators according to their carbon intensity. Added through the keyword ``Ep`` in the ``{opts}`` wildcard only in the rule :mod:`prepare_network``."
|
||||
,Unit,Values,Description
|
||||
year,--,YYYY; e.g. '2030',Year for which to retrieve cost assumptions of ``resources/costs.csv``.
|
||||
version,--,vX.X.X; e.g. 'v0.5.0',Version of ``technology-data`` repository to use.
|
||||
rooftop_share,--,float,Share of rooftop PV when calculating capital cost of solar (joint rooftop and utility-scale PV).
|
||||
fill_values,--,float,Default values if not specified for a technology in ``resources/costs.csv``.
|
||||
capital_cost,EUR/MW,Keys should be in the 'technology' column of ``resources/costs.csv``. Values can be any float.,"For the given technologies, assumptions about their capital investment costs are set to the corresponding value. Optional; overwrites cost assumptions from ``resources/costs.csv``."
|
||||
marginal_cost,EUR/MWh,Keys should be in the 'technology' column of ``resources/costs.csv``. Values can be any float.,"For the given technologies, assumptions about their marginal operating costs are set to the corresponding value. Optional; overwrites cost assumptions from ``resources/costs.csv``."
|
||||
emission_prices,,,Specify exogenous prices for emission types listed in ``network.carriers`` to marginal costs.
|
||||
-- enable,bool,true or false,Add cost for a carbon-dioxide price configured in ``costs: emission_prices: co2`` to ``marginal_cost`` of generators (other emission types listed in ``network.carriers`` possible as well)
|
||||
-- co2,EUR/t,float,Exogenous price of carbon-dioxide added to the marginal costs of fossil-fuelled generators according to their carbon intensity. Added through the keyword ``Ep`` in the ``{opts}`` wildcard only in the rule :mod:`prepare_network``.
|
||||
-- co2_monthly_price,bool,true or false,Add monthly cost for a carbon-dioxide price based on historical values built by the rule ``build_monthly_prices``
|
||||
|
|
@ -1,6 +1,8 @@
|
||||
,Unit,Values,Description
|
||||
voltages,kV,"Any subset of {220., 300., 380.}",Voltage levels to consider
|
||||
gaslimit_enable,bool,true or false,Add an overall absolute gas limit configured in ``electricity: gaslimit``.
|
||||
gaslimit,MWhth,float or false,Global gas usage limit
|
||||
co2limit_enable,bool,true or false,Add an overall absolute carbon-dioxide emissions limit configured in ``electricity: co2limit``.
|
||||
co2limit,:math:`t_{CO_2-eq}/a`,float,Cap on total annual system carbon dioxide emissions
|
||||
co2base,:math:`t_{CO_2-eq}/a`,float,Reference value of total annual system carbon dioxide emissions if relative emission reduction target is specified in ``{opts}`` wildcard.
|
||||
agg_p_nom_limits,file,path,Reference to ``.csv`` file specifying per carrier generator nominal capacity constraints for individual countries if ``'CCL'`` is in ``{opts}`` wildcard. Defaults to ``data/agg_p_nom_minmax.csv``.
|
||||
@ -34,3 +36,6 @@ estimate_renewable_capacities,,,
|
||||
-- -- Offshore,--,"Any subset of {offwind-ac, offwind-dc}","List of PyPSA-Eur carriers that is considered as (IRENA, OPSD) onshore technology."
|
||||
-- -- Offshore,--,{onwind},"List of PyPSA-Eur carriers that is considered as (IRENA, OPSD) offshore technology."
|
||||
-- -- PV,--,{solar},"List of PyPSA-Eur carriers that is considered as (IRENA, OPSD) PV technology."
|
||||
autarky,,,
|
||||
-- enable,bool,true or false,Require each node to be autarkic by removing all lines and links.
|
||||
-- by_country,bool,true or false,Require each country to be autarkic by removing all cross-border lines and links. ``electricity: autarky`` must be enabled.
|
||||
|
|
@ -1,13 +1,13 @@
|
||||
Trigger, Description, Definition, Status
|
||||
``nH``; i.e. ``2H``-``6H``, Resample the time-resolution by averaging over every ``n`` snapshots, ``prepare_network``: `average_every_nhours() <https://github.com/PyPSA/pypsa-eur/blob/6b964540ed39d44079cdabddee8333f486d0cd63/scripts/prepare_network.py#L110>`_ and its `caller <https://github.com/PyPSA/pypsa-eur/blob/6b964540ed39d44079cdabddee8333f486d0cd63/scripts/prepare_network.py#L146>`__), In active use
|
||||
``nSEG``; e.g. ``4380SEG``, "Apply time series segmentation with `tsam <https://tsam.readthedocs.io/en/latest/index.html>`_ package to ``n`` adjacent snapshots of varying lengths based on capacity factors of varying renewables, hydro inflow and load.", ``prepare_network``: apply_time_segmentation(), In active use
|
||||
``Co2L``, Add an overall absolute carbon-dioxide emissions limit configured in ``electricity: co2limit``. If a float is appended an overall emission limit relative to the emission level given in ``electricity: co2base`` is added (e.g. ``Co2L0.05`` limits emissisions to 5% of what is given in ``electricity: co2base``), ``prepare_network``: `add_co2limit() <https://github.com/PyPSA/pypsa-eur/blob/6b964540ed39d44079cdabddee8333f486d0cd63/scripts/prepare_network.py#L19>`_ and its `caller <https://github.com/PyPSA/pypsa-eur/blob/6b964540ed39d44079cdabddee8333f486d0cd63/scripts/prepare_network.py#L154>`__, In active use
|
||||
``Ep``, Add cost for a carbon-dioxide price configured in ``costs: emission_prices: co2`` to ``marginal_cost`` of generators (other emission types listed in ``network.carriers`` possible as well), ``prepare_network``: `add_emission_prices() <https://github.com/PyPSA/pypsa-eur/blob/6b964540ed39d44079cdabddee8333f486d0cd63/scripts/prepare_network.py#L24>`_ and its `caller <https://github.com/PyPSA/pypsa-eur/blob/6b964540ed39d44079cdabddee8333f486d0cd63/scripts/prepare_network.py#L158>`__, In active use
|
||||
``Ept``, Add monthly cost for a carbon-dioxide price based on historical values built by the rule ``build_monthly_prices``, In active use
|
||||
``CCL``, Add minimum and maximum levels of generator nominal capacity per carrier for individual countries. These can be specified in the file linked at ``electricity: agg_p_nom_limits`` in the configuration. File defaults to ``data/agg_p_nom_minmax.csv``., ``solve_network``, In active use
|
||||
``EQ``, "Require each country or node to on average produce a minimal share of its total consumption itself. Example: ``EQ0.5c`` demands each country to produce on average at least 50% of its consumption; ``EQ0.5`` demands each node to produce on average at least 50% of its consumption.", ``solve_network``, In active use
|
||||
``ATK``, "Require each node to be autarkic. Example: ``ATK`` removes all lines and links. ``ATKc`` removes all cross-border lines and links.", ``prepare_network``, In active use
|
||||
``BAU``, Add a per-``carrier`` minimal overall capacity; i.e. at least ``40GW`` of ``OCGT`` in Europe; configured in ``electricity: BAU_mincapacities``, ``solve_network``: `add_opts_constraints() <https://github.com/PyPSA/pypsa-eur/blob/6b964540ed39d44079cdabddee8333f486d0cd63/scripts/solve_network.py#L66>`__, Untested
|
||||
``SAFE``, Add a capacity reserve margin of a certain fraction above the peak demand to which renewable generators and storage do *not* contribute. Ignores network., ``solve_network`` `add_opts_constraints() <https://github.com/PyPSA/pypsa-eur/blob/6b964540ed39d44079cdabddee8333f486d0cd63/scripts/solve_network.py#L73>`__, Untested
|
||||
``carrier+{c|p|m}factor``,"Alter the capital cost (``c``), installable potential (``p``) or marginal costs (``m``) of a carrier by a factor. Example: ``solar+c0.5`` reduces the capital cost of solar to 50\% of original values.", ``prepare_network``, In active use
|
||||
``CH4L``,"Add an overall absolute gas limit. If configured in ``electricity: gaslimit`` it is given in MWh thermal, if a float is appended, the overall gaslimit is assumed to be given in TWh thermal (e.g. ``CH4L200`` limits gas dispatch to 200 TWh termal)", ``prepare_network``: ``add_gaslimit()``, In active use
|
||||
Trigger, Description, Definition, Status
|
||||
``nH``; i.e. ``2H``-``6H``, Resample the time-resolution by averaging over every ``n`` snapshots, ``prepare_network``: `average_every_nhours() <https://github.com/PyPSA/pypsa-eur/blob/6b964540ed39d44079cdabddee8333f486d0cd63/scripts/prepare_network.py#L110>`_ and its `caller <https://github.com/PyPSA/pypsa-eur/blob/6b964540ed39d44079cdabddee8333f486d0cd63/scripts/prepare_network.py#L146>`__), In active use
|
||||
``nSEG``; e.g. ``4380SEG``,"Apply time series segmentation with `tsam <https://tsam.readthedocs.io/en/latest/index.html>`_ package to ``n`` adjacent snapshots of varying lengths based on capacity factors of varying renewables, hydro inflow and load.", ``prepare_network``: apply_time_segmentation(), In active use
|
||||
``Co2L``,Add an overall absolute carbon-dioxide emissions limit configured in ``electricity: co2limit``. If a float is appended an overall emission limit relative to the emission level given in ``electricity: co2base`` is added (e.g. ``Co2L0.05`` limits emissisions to 5% of what is given in ``electricity: co2base``), ``prepare_network``: `add_co2limit() <https://github.com/PyPSA/pypsa-eur/blob/6b964540ed39d44079cdabddee8333f486d0cd63/scripts/prepare_network.py#L19>`_ and its `caller <https://github.com/PyPSA/pypsa-eur/blob/6b964540ed39d44079cdabddee8333f486d0cd63/scripts/prepare_network.py#L154>`__, In active use
|
||||
``Ep``,Add cost for a carbon-dioxide price configured in ``costs: emission_prices: co2`` to ``marginal_cost`` of generators (other emission types listed in ``network.carriers`` possible as well), ``prepare_network``: `add_emission_prices() <https://github.com/PyPSA/pypsa-eur/blob/6b964540ed39d44079cdabddee8333f486d0cd63/scripts/prepare_network.py#L24>`_ and its `caller <https://github.com/PyPSA/pypsa-eur/blob/6b964540ed39d44079cdabddee8333f486d0cd63/scripts/prepare_network.py#L158>`__, In active use
|
||||
``Ept``,Add monthly cost for a carbon-dioxide price based on historical values built by the rule ``build_monthly_prices``, In active use,
|
||||
``CCL``,Add minimum and maximum levels of generator nominal capacity per carrier for individual countries. These can be specified in the file linked at ``electricity: agg_p_nom_limits`` in the configuration. File defaults to ``data/agg_p_nom_minmax.csv``., ``solve_network``, In active use
|
||||
``EQ``,Require each country or node to on average produce a minimal share of its total consumption itself. Example: ``EQ0.5c`` demands each country to produce on average at least 50% of its consumption; ``EQ0.5`` demands each node to produce on average at least 50% of its consumption., ``solve_network``, In active use
|
||||
``ATK``,Require each node to be autarkic. Example: ``ATK`` removes all lines and links. ``ATKc`` removes all cross-border lines and links., ``prepare_network``, In active use
|
||||
``BAU``,Add a per-``carrier`` minimal overall capacity; i.e. at least ``40GW`` of ``OCGT`` in Europe; configured in ``electricity: BAU_mincapacities``, ``solve_network``: `add_opts_constraints() <https://github.com/PyPSA/pypsa-eur/blob/6b964540ed39d44079cdabddee8333f486d0cd63/scripts/solve_network.py#L66>`__, Untested
|
||||
``SAFE``,Add a capacity reserve margin of a certain fraction above the peak demand to which renewable generators and storage do *not* contribute. Ignores network., ``solve_network`` `add_opts_constraints() <https://github.com/PyPSA/pypsa-eur/blob/6b964540ed39d44079cdabddee8333f486d0cd63/scripts/solve_network.py#L73>`__, Untested
|
||||
``carrier+{c|p|m}factor``,"Alter the capital cost (``c``), installable potential (``p``) or marginal costs (``m``) of a carrier by a factor. Example: ``solar+c0.5`` reduces the capital cost of solar to 50\% of original values.", ``prepare_network``, In active use
|
||||
``CH4L``,"Add an overall absolute gas limit. If configured in ``electricity: gaslimit`` it is given in MWh thermal, if a float is appended, the overall gaslimit is assumed to be given in TWh thermal (e.g. ``CH4L200`` limits gas dispatch to 200 TWh termal)", ``prepare_network``: ``add_gaslimit()``, In active use
|
||||
|
Can't render this file because it has a wrong number of fields in line 6.
|
@ -1,4 +1,6 @@
|
||||
,Unit,Values,Description
|
||||
start,--,"str or datetime-like; e.g. YYYY-MM-DD","Left bound of date range"
|
||||
end,--,"str or datetime-like; e.g. YYYY-MM-DD","Right bound of date range"
|
||||
inclusive,--,"One of {'neither', 'both', ‘left’, ‘right’}","Make the time interval closed to the ``left``, ``right``, or both sides ``both`` or neither side ``None``."
|
||||
,Unit,Values,Description
|
||||
start,--,str or datetime-like; e.g. YYYY-MM-DD,Left bound of date range
|
||||
end,--,str or datetime-like; e.g. YYYY-MM-DD,Right bound of date range
|
||||
inclusive,--,"One of {'neither', 'both', ‘left’, ‘right’}","Make the time interval closed to the ``left``, ``right``, or both sides ``both`` or neither side ``None``."
|
||||
resolution ,--,"{false,``nH``; i.e. ``2H``-``6H``}",Resample the time-resolution by averaging over every ``n`` snapshots
|
||||
segmentation,--,"{false,``n``; e.g. ``4380``}","Apply time series segmentation with `tsam <https://tsam.readthedocs.io/en/latest/index.html>`_ package to ``n`` adjacent snapshots of varying lengths based on capacity factors of varying renewables, hydro inflow and load."
|
||||
|
|
@ -13,6 +13,11 @@ options,,,
|
||||
-- transmission_losses,int,[0-9],"Add piecewise linear approximation of transmission losses based on n tangents. Defaults to 0, which means losses are ignored."
|
||||
-- linearized_unit_commitment,bool,"{'true','false'}",Whether to optimise using the linearized unit commitment formulation.
|
||||
-- horizon,--,int,Number of snapshots to consider in each iteration. Defaults to 100.
|
||||
constraints ,,,
|
||||
-- CCL,bool,"{'true','false'}",Add minimum and maximum levels of generator nominal capacity per carrier for individual countries. These can be specified in the file linked at ``electricity: agg_p_nom_limits`` in the configuration. File defaults to ``data/agg_p_nom_minmax.csv``.
|
||||
-- EQ,bool/string,"{'false',`n(c| )``; i.e. ``0.5``-``0.7c``}",Require each country or node to on average produce a minimal share of its total consumption itself. Example: ``EQ0.5c`` demands each country to produce on average at least 50% of its consumption; ``EQ0.5`` demands each node to produce on average at least 50% of its consumption.
|
||||
-- BAU,bool,"{'true','false'}",Add a per-``carrier`` minimal overall capacity; i.e. at least ``40GW`` of ``OCGT`` in Europe; configured in ``electricity: BAU_mincapacities``
|
||||
-- SAFE,bool,"{'true','false'}",Add a capacity reserve margin of a certain fraction above the peak demand to which renewable generators and storage do *not* contribute. Ignores network.
|
||||
solver,,,
|
||||
-- name,--,"One of {'gurobi', 'cplex', 'cbc', 'glpk', 'ipopt'}; potentially more possible",Solver to use for optimisation problems in the workflow; e.g. clustering and linear optimal power flow.
|
||||
-- options,--,Key listed under ``solver_options``.,Link to specific parameter settings.
|
||||
|
|
@ -10,6 +10,11 @@ Release Notes
|
||||
Upcoming Release
|
||||
================
|
||||
|
||||
* More wildcard options now have a corresponding config entry. If the wildcard
|
||||
is given, then its value is used. If the wildcard is not given but the options
|
||||
in config are enabled, then the value from config is used. If neither is
|
||||
given, the options are skipped.
|
||||
|
||||
* Distinguish between stored and sequestered CO2. Stored CO2 is stored
|
||||
overground in tanks and can be used for CCU (e.g. methanolisation).
|
||||
Sequestered CO2 is stored underground and can no longer be used for CCU. This
|
||||
|
@ -20,7 +20,7 @@ if config["enable"].get("prepare_links_p_nom", False):
|
||||
|
||||
rule build_electricity_demand:
|
||||
params:
|
||||
snapshots=config["snapshots"],
|
||||
snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]},
|
||||
countries=config["countries"],
|
||||
load=config["load"],
|
||||
input:
|
||||
@ -61,7 +61,7 @@ rule build_powerplants:
|
||||
rule base_network:
|
||||
params:
|
||||
countries=config["countries"],
|
||||
snapshots=config["snapshots"],
|
||||
snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]},
|
||||
lines=config["lines"],
|
||||
links=config["links"],
|
||||
transformers=config["transformers"],
|
||||
@ -144,7 +144,7 @@ if config["enable"].get("build_cutout", False):
|
||||
|
||||
rule build_cutout:
|
||||
params:
|
||||
snapshots=config["snapshots"],
|
||||
snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]},
|
||||
cutouts=config["atlite"]["cutouts"],
|
||||
input:
|
||||
regions_onshore=RESOURCES + "regions_onshore.geojson",
|
||||
@ -258,6 +258,7 @@ else:
|
||||
|
||||
rule build_renewable_profiles:
|
||||
params:
|
||||
snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]},
|
||||
renewable=config["renewable"],
|
||||
input:
|
||||
**opt,
|
||||
@ -354,6 +355,8 @@ rule build_hydro_profile:
|
||||
if config["lines"]["dynamic_line_rating"]["activate"]:
|
||||
|
||||
rule build_line_rating:
|
||||
params:
|
||||
snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]},
|
||||
input:
|
||||
base_network=RESOURCES + "networks/base.nc",
|
||||
cutout="cutouts/"
|
||||
@ -531,13 +534,20 @@ rule add_extra_components:
|
||||
|
||||
rule prepare_network:
|
||||
params:
|
||||
snapshots={
|
||||
"resolution": config["snapshots"].get("resolution", False),
|
||||
"segmentation": config["snapshots"].get("segmentation", False),
|
||||
},
|
||||
links=config["links"],
|
||||
lines=config["lines"],
|
||||
co2base=config["electricity"]["co2base"],
|
||||
co2limit_enable=config["electricity"].get("co2limit_enable", False),
|
||||
co2limit=config["electricity"]["co2limit"],
|
||||
gaslimit_enable=config["electricity"].get("gaslimit_enable", False),
|
||||
gaslimit=config["electricity"].get("gaslimit"),
|
||||
max_hours=config["electricity"]["max_hours"],
|
||||
costs=config["costs"],
|
||||
autarky=config["electricity"].get("autarky", {}),
|
||||
input:
|
||||
RESOURCES + "networks/elec_s{simpl}_{clusters}_ec.nc",
|
||||
tech_costs=COSTS,
|
||||
|
@ -125,7 +125,7 @@ rule cluster_gas_network:
|
||||
|
||||
rule build_heat_demands:
|
||||
params:
|
||||
snapshots=config["snapshots"],
|
||||
snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]},
|
||||
input:
|
||||
pop_layout=RESOURCES + "pop_layout_{scope}.nc",
|
||||
regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson",
|
||||
@ -147,7 +147,7 @@ rule build_heat_demands:
|
||||
|
||||
rule build_temperature_profiles:
|
||||
params:
|
||||
snapshots=config["snapshots"],
|
||||
snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]},
|
||||
input:
|
||||
pop_layout=RESOURCES + "pop_layout_{scope}.nc",
|
||||
regions_onshore=RESOURCES + "regions_onshore_elec_s{simpl}_{clusters}.geojson",
|
||||
@ -199,7 +199,7 @@ rule build_cop_profiles:
|
||||
|
||||
rule build_solar_thermal_profiles:
|
||||
params:
|
||||
snapshots=config["snapshots"],
|
||||
snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]},
|
||||
solar_thermal=config["solar_thermal"],
|
||||
input:
|
||||
pop_layout=RESOURCES + "pop_layout_{scope}.nc",
|
||||
@ -662,7 +662,7 @@ rule build_shipping_demand:
|
||||
|
||||
rule build_transport_demand:
|
||||
params:
|
||||
snapshots=config["snapshots"],
|
||||
snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]},
|
||||
sector=config["sector"],
|
||||
input:
|
||||
clustered_pop_layout=RESOURCES + "pop_layout_elec_s{simpl}_{clusters}.csv",
|
||||
|
@ -85,7 +85,7 @@ rule make_summary:
|
||||
params:
|
||||
foresight=config["foresight"],
|
||||
costs=config["costs"],
|
||||
snapshots=config["snapshots"],
|
||||
snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]},
|
||||
scenario=config["scenario"],
|
||||
RDIR=RDIR,
|
||||
input:
|
||||
|
@ -17,7 +17,7 @@ rule build_electricity_production:
|
||||
The data is used for validation of the optimization results.
|
||||
"""
|
||||
params:
|
||||
snapshots=config["snapshots"],
|
||||
snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]},
|
||||
countries=config["countries"],
|
||||
output:
|
||||
RESOURCES + "historical_electricity_production.csv",
|
||||
@ -35,7 +35,7 @@ rule build_cross_border_flows:
|
||||
The data is used for validation of the optimization results.
|
||||
"""
|
||||
params:
|
||||
snapshots=config["snapshots"],
|
||||
snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]},
|
||||
countries=config["countries"],
|
||||
input:
|
||||
network=RESOURCES + "networks/base.nc",
|
||||
@ -55,7 +55,7 @@ rule build_electricity_prices:
|
||||
The data is used for validation of the optimization results.
|
||||
"""
|
||||
params:
|
||||
snapshots=config["snapshots"],
|
||||
snapshots={k: config["snapshots"][k] for k in ["start", "end", "inclusive"]},
|
||||
countries=config["countries"],
|
||||
output:
|
||||
RESOURCES + "historical_electricity_prices.csv",
|
||||
|
@ -7,6 +7,7 @@ import contextlib
|
||||
import hashlib
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import urllib
|
||||
from pathlib import Path
|
||||
|
||||
@ -23,6 +24,35 @@ logger = logging.getLogger(__name__)
|
||||
REGION_COLS = ["geometry", "name", "x", "y", "country"]
|
||||
|
||||
|
||||
def get_opt(opts, expr, flags=None):
|
||||
"""
|
||||
Return the first option matching the regular expression.
|
||||
|
||||
The regular expression is case-insensitive by default.
|
||||
"""
|
||||
if flags is None:
|
||||
flags = re.IGNORECASE
|
||||
for o in opts:
|
||||
match = re.match(expr, o, flags=flags)
|
||||
if match:
|
||||
return match.group(0)
|
||||
return None
|
||||
|
||||
|
||||
def find_opt(opts, expr):
|
||||
"""
|
||||
Return if available the float after the expression.
|
||||
"""
|
||||
for o in opts:
|
||||
if expr in o:
|
||||
m = re.findall("[0-9]*\.?[0-9]+$", o)
|
||||
if len(m) > 0:
|
||||
return True, float(m[0])
|
||||
else:
|
||||
return True, None
|
||||
return False, None
|
||||
|
||||
|
||||
# Define a context manager to temporarily mute print statements
|
||||
@contextlib.contextmanager
|
||||
def mute_print():
|
||||
|
@ -725,11 +725,12 @@ def base_network(
|
||||
transformers = _set_electrical_parameters_transformers(transformers, config)
|
||||
links = _set_electrical_parameters_links(links, config, links_p_nom)
|
||||
converters = _set_electrical_parameters_converters(converters, config)
|
||||
snapshots = snakemake.params.snapshots
|
||||
|
||||
n = pypsa.Network()
|
||||
n.name = "PyPSA-Eur"
|
||||
|
||||
n.set_snapshots(pd.date_range(freq="h", **config["snapshots"]))
|
||||
n.set_snapshots(pd.date_range(freq="h", **snapshots))
|
||||
n.madd("Carrier", ["AC", "DC"])
|
||||
|
||||
n.import_components_from_dataframe(buses, "Bus")
|
||||
|
@ -146,8 +146,10 @@ if __name__ == "__main__":
|
||||
)
|
||||
configure_logging(snakemake)
|
||||
|
||||
snapshots = snakemake.params.snapshots
|
||||
|
||||
n = pypsa.Network(snakemake.input.base_network)
|
||||
time = pd.date_range(freq="h", **snakemake.config["snapshots"])
|
||||
time = pd.date_range(freq="h", **snapshots)
|
||||
cutout = atlite.Cutout(snakemake.input.cutout).sel(time=time)
|
||||
|
||||
da = calculate_line_rating(n, cutout)
|
||||
|
@ -210,6 +210,7 @@ if __name__ == "__main__":
|
||||
resource = params["resource"] # pv panel params / wind turbine params
|
||||
correction_factor = params.get("correction_factor", 1.0)
|
||||
capacity_per_sqkm = params["capacity_per_sqkm"]
|
||||
snapshots = snakemake.params.snapshots
|
||||
|
||||
if correction_factor != 1.0:
|
||||
logger.info(f"correction_factor is set as {correction_factor}")
|
||||
@ -219,7 +220,7 @@ if __name__ == "__main__":
|
||||
else:
|
||||
client = None
|
||||
|
||||
sns = pd.date_range(freq="h", **snakemake.config["snapshots"])
|
||||
sns = pd.date_range(freq="h", **snapshots)
|
||||
cutout = atlite.Cutout(snakemake.input.cutout).sel(time=sns)
|
||||
regions = gpd.read_file(snakemake.input.regions)
|
||||
assert not regions.empty, (
|
||||
|
@ -63,7 +63,7 @@ import re
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import pypsa
|
||||
from _helpers import configure_logging
|
||||
from _helpers import configure_logging, find_opt, get_opt
|
||||
from add_electricity import load_costs, update_transmission_costs
|
||||
from pypsa.descriptors import expand_series
|
||||
|
||||
@ -296,42 +296,42 @@ if __name__ == "__main__":
|
||||
|
||||
set_line_s_max_pu(n, snakemake.params.lines["s_max_pu"])
|
||||
|
||||
for o in opts:
|
||||
m = re.match(r"^\d+h$", o, re.IGNORECASE)
|
||||
if m is not None:
|
||||
n = average_every_nhours(n, m.group(0))
|
||||
break
|
||||
# temporal averaging
|
||||
nhours_config = snakemake.params.snapshots.get("resolution", False)
|
||||
nhours_wildcard = get_opt(opts, r"^\d+h$")
|
||||
nhours = nhours_wildcard or nhours_config
|
||||
if nhours:
|
||||
n = average_every_nhours(n, nhours)
|
||||
|
||||
for o in opts:
|
||||
m = re.match(r"^\d+seg$", o, re.IGNORECASE)
|
||||
if m is not None:
|
||||
solver_name = snakemake.config["solving"]["solver"]["name"]
|
||||
n = apply_time_segmentation(n, m.group(0)[:-3], solver_name)
|
||||
break
|
||||
# segments with package tsam
|
||||
time_seg_config = snakemake.params.snapshots.get("segmentation", False)
|
||||
time_seg_wildcard = get_opt(opts, r"^\d+seg$")
|
||||
time_seg = time_seg_wildcard or time_seg_config
|
||||
if time_seg:
|
||||
solver_name = snakemake.config["solving"]["solver"]["name"]
|
||||
n = apply_time_segmentation(n, time_seg.replace("seg", ""), solver_name)
|
||||
|
||||
for o in opts:
|
||||
if "Co2L" in o:
|
||||
m = re.findall("[0-9]*\.?[0-9]+$", o)
|
||||
if len(m) > 0:
|
||||
co2limit = float(m[0]) * snakemake.params.co2base
|
||||
add_co2limit(n, co2limit, Nyears)
|
||||
logger.info("Setting CO2 limit according to wildcard value.")
|
||||
else:
|
||||
add_co2limit(n, snakemake.params.co2limit, Nyears)
|
||||
logger.info("Setting CO2 limit according to config value.")
|
||||
break
|
||||
Co2L_config = snakemake.params.co2limit_enable
|
||||
Co2L_wildcard, co2limit_wildcard = find_opt(opts, "Co2L")
|
||||
if Co2L_wildcard or Co2L_config:
|
||||
if co2limit_wildcard is not None:
|
||||
co2limit = co2limit_wildcard * snakemake.params.co2base
|
||||
add_co2limit(n, co2limit, Nyears)
|
||||
logger.info("Setting CO2 limit according to wildcard value.")
|
||||
else:
|
||||
add_co2limit(n, snakemake.params.co2limit, Nyears)
|
||||
logger.info("Setting CO2 limit according to config value.")
|
||||
|
||||
for o in opts:
|
||||
if "CH4L" in o:
|
||||
m = re.findall("[0-9]*\.?[0-9]+$", o)
|
||||
if len(m) > 0:
|
||||
limit = float(m[0]) * 1e6
|
||||
add_gaslimit(n, limit, Nyears)
|
||||
logger.info("Setting gas usage limit according to wildcard value.")
|
||||
else:
|
||||
add_gaslimit(n, snakemake.params.gaslimit, Nyears)
|
||||
logger.info("Setting gas usage limit according to config value.")
|
||||
break
|
||||
CH4L_config = snakemake.params.gaslimit_enable
|
||||
CH4L_wildcard, gaslimit_wildcard = find_opt(opts, "CH4L")
|
||||
if CH4L_wildcard or CH4L_config:
|
||||
if gaslimit_wildcard is not None:
|
||||
gaslimit = gaslimit_wildcard * 1e6
|
||||
add_gaslimit(n, gaslimit, Nyears)
|
||||
logger.info("Setting gas usage limit according to wildcard value.")
|
||||
else:
|
||||
add_gaslimit(n, snakemake.params.gaslimit, Nyears)
|
||||
logger.info("Setting gas usage limit according to config value.")
|
||||
|
||||
for o in opts:
|
||||
if "+" not in o:
|
||||
@ -352,21 +352,26 @@ if __name__ == "__main__":
|
||||
sel = c.df.carrier.str.contains(carrier)
|
||||
c.df.loc[sel, attr] *= factor
|
||||
|
||||
for o in opts:
|
||||
if "Ept" in o:
|
||||
logger.info(
|
||||
"Setting time dependent emission prices according spot market price"
|
||||
emission_prices = snakemake.params.costs["emission_prices"]
|
||||
Ept_config = emission_prices.get("co2_monthly_prices", False)
|
||||
Ept_wildcard = "Ept" in opts
|
||||
Ep_config = emission_prices.get("enable", False)
|
||||
Ep_wildcard, co2_wildcard = find_opt(opts, "Ep")
|
||||
|
||||
if Ept_wildcard or Ept_config:
|
||||
logger.info(
|
||||
"Setting time dependent emission prices according spot market price"
|
||||
)
|
||||
add_dynamic_emission_prices(n)
|
||||
elif Ep_wildcard or Ep_config:
|
||||
if co2_wildcard is not None:
|
||||
logger.info("Setting CO2 prices according to wildcard value.")
|
||||
add_emission_prices(n, dict(co2=co2_wildcard))
|
||||
else:
|
||||
logger.info("Setting CO2 prices according to config value.")
|
||||
add_emission_prices(
|
||||
n, dict(co2=snakemake.params.costs["emission_prices"]["co2"])
|
||||
)
|
||||
add_dynamic_emission_prices(n)
|
||||
elif "Ep" in o:
|
||||
m = re.findall("[0-9]*\.?[0-9]+$", o)
|
||||
if len(m) > 0:
|
||||
logger.info("Setting emission prices according to wildcard value.")
|
||||
add_emission_prices(n, dict(co2=float(m[0])))
|
||||
else:
|
||||
logger.info("Setting emission prices according to config value.")
|
||||
add_emission_prices(n, snakemake.params.costs["emission_prices"])
|
||||
break
|
||||
|
||||
ll_type, factor = snakemake.wildcards.ll[0], snakemake.wildcards.ll[1:]
|
||||
set_transmission_limit(n, ll_type, factor, costs, Nyears)
|
||||
@ -379,10 +384,12 @@ if __name__ == "__main__":
|
||||
p_nom_max_ext=snakemake.params.links.get("max_extension", np.inf),
|
||||
)
|
||||
|
||||
if "ATK" in opts:
|
||||
enforce_autarky(n)
|
||||
elif "ATKc" in opts:
|
||||
enforce_autarky(n, only_crossborder=True)
|
||||
autarky_config = snakemake.params.autarky
|
||||
if "ATK" in opts or autarky_config.get("enable", False):
|
||||
only_crossborder = False
|
||||
if "ATKc" in opts or autarky_config.get("by_country", False):
|
||||
only_crossborder = True
|
||||
enforce_autarky(n, only_crossborder=only_crossborder)
|
||||
|
||||
n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards)))
|
||||
n.export_to_netcdf(snakemake.output[0])
|
||||
|
@ -37,7 +37,7 @@ import pandas as pd
|
||||
import pypsa
|
||||
import xarray as xr
|
||||
from _benchmark import memory_logger
|
||||
from _helpers import configure_logging, update_config_with_sector_opts
|
||||
from _helpers import configure_logging, get_opt, update_config_with_sector_opts
|
||||
from pypsa.descriptors import get_activity_mask
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -806,18 +806,30 @@ def extra_functionality(n, snapshots):
|
||||
"""
|
||||
opts = n.opts
|
||||
config = n.config
|
||||
if "BAU" in opts and n.generators.p_nom_extendable.any():
|
||||
constraints = config["solving"].get("constraints", {})
|
||||
if (
|
||||
"BAU" in opts or constraints.get("BAU", False)
|
||||
) and n.generators.p_nom_extendable.any():
|
||||
add_BAU_constraints(n, config)
|
||||
if "SAFE" in opts and n.generators.p_nom_extendable.any():
|
||||
if (
|
||||
"SAFE" in opts or constraints.get("SAFE", False)
|
||||
) and n.generators.p_nom_extendable.any():
|
||||
add_SAFE_constraints(n, config)
|
||||
if "CCL" in opts and n.generators.p_nom_extendable.any():
|
||||
if (
|
||||
"CCL" in opts or constraints.get("CCL", False)
|
||||
) and n.generators.p_nom_extendable.any():
|
||||
add_CCL_constraints(n, config)
|
||||
|
||||
reserve = config["electricity"].get("operational_reserve", {})
|
||||
if reserve.get("activate"):
|
||||
add_operational_reserve_margin(n, snapshots, config)
|
||||
for o in opts:
|
||||
if "EQ" in o:
|
||||
add_EQ_constraints(n, o)
|
||||
|
||||
EQ_config = constraints.get("EQ", False)
|
||||
EQ_wildcard = get_opt(opts, r"^EQ+[0-9]*\.?[0-9]+(c|)")
|
||||
EQ_o = EQ_wildcard or EQ_config
|
||||
if EQ_o:
|
||||
add_EQ_constraints(n, EQ_o.replace("EQ", ""))
|
||||
|
||||
add_battery_constraints(n)
|
||||
add_lossy_bidirectional_link_constraints(n)
|
||||
add_pipe_retrofit_constraint(n)
|
||||
|
Loading…
Reference in New Issue
Block a user