safe transport demand in unit kinetic energy
This commit is contained in:
parent
986c7be48e
commit
b70aa59dce
@ -19,13 +19,16 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
def build_nodal_transport_data(fn, pop_layout):
|
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)
|
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 = transport_data.loc[pop_layout.ct].fillna(0.0)
|
||||||
nodal_transport_data.index = pop_layout.index
|
nodal_transport_data.index = pop_layout.index
|
||||||
nodal_transport_data["number cars"] = (
|
nodal_transport_data["number cars"] = (
|
||||||
pop_layout["fraction"] * 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.loc[
|
||||||
nodal_transport_data["average fuel efficiency"] == 0.0,
|
nodal_transport_data["average fuel efficiency"] == 0.0,
|
||||||
"average fuel efficiency",
|
"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):
|
def build_transport_demand(traffic_fn, airtemp_fn, nodes, nodal_transport_data):
|
||||||
## Get overall demand curve for all vehicles
|
"""
|
||||||
|
returns transport demand per bus in unit kinetic energy.
|
||||||
traffic = pd.read_csv(traffic_fn, skiprows=2, usecols=["count"]).squeeze("columns")
|
"""
|
||||||
|
# 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(
|
transport_shape = generate_periodic_profiles(
|
||||||
dt_index=snapshots,
|
dt_index=snapshots,
|
||||||
nodes=nodes,
|
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()
|
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
|
# get heating demand for correction to demand time series
|
||||||
temperature = xr.open_dataarray(airtemp_fn).to_pandas()
|
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"],
|
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
|
# 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()
|
ice_correction = (transport_shape * (1 + dd_ICE)).sum() / transport_shape.sum()
|
||||||
|
|
||||||
energy_totals_transport = (
|
energy_totals_transport = (
|
||||||
@ -87,8 +77,7 @@ def build_transport_demand(traffic_fn, airtemp_fn, nodes, nodal_transport_data):
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
(transport_shape.multiply(energy_totals_transport) * 1e6 * nyears)
|
(transport_shape.multiply(energy_totals_transport) * 1e6 * nyears)
|
||||||
.divide(efficiency_gain * ice_correction)
|
.divide(nodal_transport_data["average fuel efficiency"] * ice_correction)
|
||||||
.multiply(1 + dd_EV)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -125,11 +114,14 @@ def bev_availability_profile(fn, snapshots, nodes, options):
|
|||||||
"""
|
"""
|
||||||
Derive plugged-in availability for passenger electric vehicles.
|
Derive plugged-in availability for passenger electric vehicles.
|
||||||
"""
|
"""
|
||||||
|
# car count in typical week
|
||||||
traffic = pd.read_csv(fn, skiprows=2, usecols=["count"]).squeeze("columns")
|
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"]
|
avail_max = options["bev_avail_max"]
|
||||||
|
# average share plugged-in availability for passenger electric vehicles
|
||||||
avail_mean = options["bev_avail_mean"]
|
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()) / (
|
avail = avail_max - (avail_max - avail_mean) * (traffic - traffic.min()) / (
|
||||||
traffic.mean() - 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):
|
def bev_dsm_profile(snapshots, nodes, options):
|
||||||
dsm_week = np.zeros((24 * 7,))
|
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[
|
dsm_week[(np.arange(0, 7, 1) * 24 + options["bev_dsm_restriction_time"])] = options[
|
||||||
"bev_dsm_restriction_value"
|
"bev_dsm_restriction_value"
|
||||||
]
|
]
|
||||||
@ -160,7 +154,7 @@ def bev_dsm_profile(snapshots, nodes, options):
|
|||||||
weekly_profile=dsm_week,
|
weekly_profile=dsm_week,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#%%
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if "snakemake" not in globals():
|
if "snakemake" not in globals():
|
||||||
from _helpers import mock_snakemake
|
from _helpers import mock_snakemake
|
||||||
@ -168,7 +162,7 @@ if __name__ == "__main__":
|
|||||||
snakemake = mock_snakemake(
|
snakemake = mock_snakemake(
|
||||||
"build_transport_demand",
|
"build_transport_demand",
|
||||||
simpl="",
|
simpl="",
|
||||||
clusters=48,
|
clusters=37,
|
||||||
)
|
)
|
||||||
configure_logging(snakemake)
|
configure_logging(snakemake)
|
||||||
set_scenario_config(snakemake)
|
set_scenario_config(snakemake)
|
||||||
|
Loading…
Reference in New Issue
Block a user