diff --git a/.gitignore b/.gitignore index 95ba5524..21062dd3 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ # # SPDX-License-Identifier: CC0-1.0 +master + .snakemake* .ipynb_checkpoints __pycache__ diff --git a/config/config.default.yaml b/config/config.default.yaml index 497971dc..e1fce90f 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -417,7 +417,6 @@ sector: bev_availability: 0.5 bev_energy: 0.05 bev_charge_efficiency: 0.9 - bev_plug_to_wheel_efficiency: 0.2 bev_charge_rate: 0.011 bev_avail_max: 0.95 bev_avail_mean: 0.8 diff --git a/doc/configtables/sector.csv b/doc/configtables/sector.csv index 58ccd9bf..703652b5 100644 --- a/doc/configtables/sector.csv +++ b/doc/configtables/sector.csv @@ -24,7 +24,6 @@ bev_dsm,--,"{true, false}",Add the option for battery electric vehicles (BEV) to 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_charge_efficiency,--,float,Battery electric vehicles (BEV) charge and discharge efficiency -bev_plug_to_wheel _efficiency,km/kWh,float,The distance battery electric vehicles (BEV) can travel in km per kWh of energy charge in battery. Base value comes from `Tesla Model S `_ bev_charge_rate,MWh,float,The power consumption for one electric vehicle (EV) in MWh. Value derived from 3-phase charger with 11 kW. bev_avail_max,--,float,The maximum share plugged-in availability for passenger electric vehicles. bev_avail_mean,--,float,The average share plugged-in availability for passenger electric vehicles. @@ -32,8 +31,9 @@ v2g,--,"{true, false}",Allows feed-in to grid from EV battery land_transport_fuel_cell _share,--,Dictionary with planning horizons as keys.,The share of vehicles that uses fuel cells in a given year 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. -transport_fuel_cell _efficiency,--,float,The H2 conversion efficiencies of fuel cells in transport -transport_internal _combustion_efficiency,--,float,The oil conversion efficiencies of internal combustion engine (ICE) in transport +transport_electric_efficiency,MWh/100km,float,The conversion efficiencies of electric vehicles in transport +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 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 agriculture_machinery _fuel_efficiency,--,float,The efficiency of electric-powered machinery in the conversion of electricity to meet agricultural needs. diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 583de9e3..0ef99f62 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -1540,7 +1540,6 @@ def get_temp_efficency( def add_EVs( n, - nodes, avail_profile, dsm_profile, p_set, @@ -1553,9 +1552,9 @@ def add_EVs( n.madd( "Bus", - nodes, + spatial.nodes, suffix=" EV battery", - location=nodes, + location=spatial.nodes, carrier="Li ion", unit="MWh_el", ) @@ -1571,7 +1570,6 @@ def add_EVs( options["EV_lower_degree_factor"], options["EV_upper_degree_factor"], ) - suffix = " land transport EV" p_shifted = (p_set + cycling_shift(p_set, 1) + cycling_shift(p_set, 2)) / 3 @@ -1579,36 +1577,28 @@ def add_EVs( efficiency *= cyclic_eff - p_nom = electric_share * p_set.div(efficiency).max() - - profile = p_set.div(efficiency) / p_set.div(efficiency).max() + profile = electric_share * p_set.div(efficiency) n.madd( - "Link", - nodes, - suffix=suffix, - bus0=nodes + " EV battery", - bus1=nodes + " land transport", + "Load", + spatial.nodes, + suffix=" land transport EV", + bus=spatial.nodes + " EV battery", carrier="land transport EV", - efficiency=efficiency, - p_min_pu=profile, - p_max_pu=profile, - p_nom=p_nom, - p_nom_extendable=False, - lifetime=1, + p_set=profile, ) p_nom = number_cars * options.get("bev_charge_rate", 0.011) * electric_share n.madd( "Link", - nodes, + spatial.nodes, suffix=" BEV charger", - bus0=nodes, - bus1=nodes + " EV battery", + bus0=spatial.nodes, + bus1=spatial.nodes + " EV battery", p_nom=p_nom, carrier="BEV charger", - p_max_pu=avail_profile[nodes], + p_max_pu=avail_profile[spatial.nodes], lifetime=1, efficiency=options.get("bev_charge_efficiency", 0.9), ) @@ -1616,13 +1606,13 @@ def add_EVs( if options["v2g"]: n.madd( "Link", - nodes, + spatial.nodes, suffix=" V2G", - bus1=nodes, - bus0=nodes + " EV battery", + bus1=spatial.nodes, + bus0=spatial.nodes + " EV battery", p_nom=p_nom, carrier="V2G", - p_max_pu=avail_profile[nodes], + p_max_pu=avail_profile[spatial.nodes], lifetime=1, efficiency=options.get("bev_charge_efficiency", 0.9), ) @@ -1637,18 +1627,18 @@ def add_EVs( n.madd( "Store", - nodes, + spatial.nodes, suffix=" battery storage", - bus=nodes + " EV battery", + bus=spatial.nodes + " EV battery", carrier="battery storage", e_cyclic=True, e_nom=e_nom, e_max_pu=1, - e_min_pu=dsm_profile[nodes], + e_min_pu=dsm_profile[spatial.nodes], ) -def add_fuel_cell_cars(n, nodes, p_set, fuel_cell_share, temperature): +def add_fuel_cell_cars(n, p_set, fuel_cell_share, temperature): car_efficiency = options["transport_fuel_cell_efficiency"] @@ -1662,29 +1652,19 @@ def add_fuel_cell_cars(n, nodes, p_set, fuel_cell_share, temperature): options["ICE_upper_degree_factor"], ) - suffix = " land transport fuel cell" - - p_nom = fuel_cell_share * p_set.div(efficiency).max() - - profile = p_set.div(efficiency) / p_set.div(efficiency).max() + profile = fuel_cell_share * p_set.div(efficiency) n.madd( - "Link", - nodes, - suffix=suffix, - bus0=spatial.h2.nodes, - bus1=nodes + " land transport", + "Load", + spatial.nodes, + suffix=" land transport fuel cell", + bus=spatial.h2.nodes, carrier="land transport fuel cell", - efficiency=efficiency, - p_nom_extendable=False, - p_nom=p_nom, - p_min_pu=profile, - p_max_pu=profile, - lifetime=1, + p_set=profile, ) -def add_ice_cars(n, nodes, p_set, ice_share, temperature): +def add_ice_cars(n, p_set, ice_share, temperature): add_carrier_buses(n, "oil") @@ -1699,32 +1679,43 @@ def add_ice_cars(n, nodes, p_set, ice_share, temperature): options["ICE_lower_degree_factor"], options["ICE_upper_degree_factor"], ) - suffix = " land transport ICE" - p_nom = ice_share * p_set.div(efficiency).max() + profile = ice_share * p_set.div(efficiency).rename( + columns=lambda x: x + " land transport oil" + ) - profile = p_set.div(efficiency) / p_set.div(efficiency).max() + if not options["regional_oil_demand"]: + profile = profile.sum(axis=1).to_frame(name="EU land transport oil") + + n.madd( + "Bus", + spatial.oil.land_transport, + location=spatial.oil.demand_locations, + carrier="land transport oil", + unit="land transport", + ) + + n.madd( + "Load", + spatial.oil.land_transport, + bus=spatial.oil.land_transport, + carrier="land transport oil", + p_set=profile, + ) n.madd( "Link", - nodes, - suffix=suffix, + spatial.oil.land_transport, bus0=spatial.oil.nodes, - bus1=nodes + " land transport", - bus2=["co2 atmosphere"], + bus1=spatial.oil.land_transport, + bus2="co2 atmosphere", carrier="land transport oil", - efficiency=efficiency, efficiency2=costs.at["oil", "CO2 intensity"], - p_nom_extendable=False, - p_nom=p_nom, - p_min_pu=profile, - p_max_pu=profile, - lifetime=1, + p_nom_extendable=True, ) def add_land_transport(n, costs): - # TODO options? logger.info("Add land transport") @@ -1751,31 +1742,7 @@ def add_land_transport(n, costs): check_land_transport_shares(shares) - nodes = spatial.nodes - - # Add load for transport demand - n.add("Carrier", "land transport demand") - - n.madd( - "Bus", - nodes, - location=nodes, - suffix=" land transport", - carrier="land transport demand", - unit="100 km", - ) - - p_set = transport[nodes] - - # add demand - n.madd( - "Load", - nodes, - suffix=" land transport", - bus=nodes + " land transport", - carrier="land transport demand", - p_set=p_set, - ) + p_set = transport[spatial.nodes] # temperature for correction factor for heating/cooling temperature = xr.open_dataarray(snakemake.input.temp_air_total).to_pandas() @@ -1783,7 +1750,6 @@ def add_land_transport(n, costs): if shares["electric"] > 0: add_EVs( n, - nodes, avail_profile, dsm_profile, p_set, @@ -1793,10 +1759,10 @@ def add_land_transport(n, costs): ) if shares["fuel_cell"] > 0: - add_fuel_cell_cars(n, nodes, p_set, shares["fuel_cell"], temperature) + add_fuel_cell_cars(n, p_set, shares["fuel_cell"], temperature) if shares["ice"] > 0: - add_ice_cars(n, nodes, p_set, shares["ice"], temperature) + add_ice_cars(n, p_set, shares["ice"], temperature) def build_heat_demand(n):