safe transport demand in unit kinetic energy

This commit is contained in:
lisazeyen 2024-03-01 11:32:12 +01:00
parent 986c7be48e
commit b70aa59dce

View File

@ -19,13 +19,16 @@ logger = logging.getLogger(__name__)
def build_nodal_transport_data(fn, pop_layout):
# get numbers of car and fuel efficieny per country
transport_data = pd.read_csv(fn, index_col=0)
# break number of cars down to nodal level based on population density
nodal_transport_data = transport_data.loc[pop_layout.ct].fillna(0.0)
nodal_transport_data.index = pop_layout.index
nodal_transport_data["number cars"] = (
pop_layout["fraction"] * nodal_transport_data["number cars"]
)
# fill missing fuel efficiency with average data
nodal_transport_data.loc[
nodal_transport_data["average fuel efficiency"] == 0.0,
"average fuel efficiency",
@ -35,10 +38,14 @@ def build_nodal_transport_data(fn, pop_layout):
def build_transport_demand(traffic_fn, airtemp_fn, nodes, nodal_transport_data):
## Get overall demand curve for all vehicles
traffic = pd.read_csv(traffic_fn, skiprows=2, usecols=["count"]).squeeze("columns")
"""
returns transport demand per bus in unit kinetic energy.
"""
# averaged weekly counts from the year 2010-2015
traffic = pd.read_csv(traffic_fn, skiprows=2,
usecols=["count"]).squeeze("columns")
# create annual profile take account time zone + summer time
transport_shape = generate_periodic_profiles(
dt_index=snapshots,
nodes=nodes,
@ -46,15 +53,6 @@ def build_transport_demand(traffic_fn, airtemp_fn, nodes, nodal_transport_data):
)
transport_shape = transport_shape / transport_shape.sum()
# electric motors are more efficient, so alter transport demand
plug_to_wheels_eta = options["bev_plug_to_wheel_efficiency"]
battery_to_wheels_eta = plug_to_wheels_eta * options["bev_charge_efficiency"]
efficiency_gain = (
nodal_transport_data["average fuel efficiency"] / battery_to_wheels_eta
)
# get heating demand for correction to demand time series
temperature = xr.open_dataarray(airtemp_fn).to_pandas()
@ -67,16 +65,8 @@ def build_transport_demand(traffic_fn, airtemp_fn, nodes, nodal_transport_data):
options["ICE_upper_degree_factor"],
)
dd_EV = transport_degree_factor(
temperature,
options["transport_heating_deadband_lower"],
options["transport_heating_deadband_upper"],
options["EV_lower_degree_factor"],
options["EV_upper_degree_factor"],
)
# divide out the heating/cooling demand from ICE totals
# and multiply back in the heating/cooling demand for EVs
ice_correction = (transport_shape * (1 + dd_ICE)).sum() / transport_shape.sum()
energy_totals_transport = (
@ -87,8 +77,7 @@ def build_transport_demand(traffic_fn, airtemp_fn, nodes, nodal_transport_data):
return (
(transport_shape.multiply(energy_totals_transport) * 1e6 * nyears)
.divide(efficiency_gain * ice_correction)
.multiply(1 + dd_EV)
.divide(nodal_transport_data["average fuel efficiency"] * ice_correction)
)
@ -125,11 +114,14 @@ def bev_availability_profile(fn, snapshots, nodes, options):
"""
Derive plugged-in availability for passenger electric vehicles.
"""
# car count in typical week
traffic = pd.read_csv(fn, skiprows=2, usecols=["count"]).squeeze("columns")
# maximum share plugged-in availability for passenger electric vehicles
avail_max = options["bev_avail_max"]
# average share plugged-in availability for passenger electric vehicles
avail_mean = options["bev_avail_mean"]
# linear scaling, highest when traffic is lowest, decreases if traffic increases
avail = avail_max - (avail_max - avail_mean) * (traffic - traffic.min()) / (
traffic.mean() - traffic.min()
)
@ -149,7 +141,9 @@ def bev_availability_profile(fn, snapshots, nodes, options):
def bev_dsm_profile(snapshots, nodes, options):
dsm_week = np.zeros((24 * 7,))
# assuming that at a certain time ("bev_dsm_restriction_time") EVs have to
# be charged to a minimum value (defined in bev_dsm_restriction_value)
dsm_week[(np.arange(0, 7, 1) * 24 + options["bev_dsm_restriction_time"])] = options[
"bev_dsm_restriction_value"
]
@ -160,7 +154,7 @@ def bev_dsm_profile(snapshots, nodes, options):
weekly_profile=dsm_week,
)
#%%
if __name__ == "__main__":
if "snakemake" not in globals():
from _helpers import mock_snakemake
@ -168,7 +162,7 @@ if __name__ == "__main__":
snakemake = mock_snakemake(
"build_transport_demand",
simpl="",
clusters=48,
clusters=37,
)
configure_logging(snakemake)
set_scenario_config(snakemake)