diff --git a/carculator_truck/__init__.py b/carculator_truck/__init__.py index 7d2b4f3..b0fad49 100644 --- a/carculator_truck/__init__.py +++ b/carculator_truck/__init__.py @@ -22,7 +22,7 @@ ) # library version -__version__ = (0, 3, 4) +__version__ = (0, 3, 5) from pathlib import Path diff --git a/carculator_truck/data/extra_parameters.json b/carculator_truck/data/extra_parameters.json index 57a3e50..e69e093 100644 --- a/carculator_truck/data/extra_parameters.json +++ b/carculator_truck/data/extra_parameters.json @@ -263,5 +263,7 @@ "share recuperated energy", "road dust emissions", "battery cell energy density", - "battery cell mass share" + "battery cell mass share", + "total cargo mass", + "kilometers per year" ] diff --git a/carculator_truck/data/payloads.yaml b/carculator_truck/data/payloads.yaml new file mode 100644 index 0000000..c85fcb1 --- /dev/null +++ b/carculator_truck/data/payloads.yaml @@ -0,0 +1,65 @@ +# payloads and annual mileage values +# most values from +# https://www.acea.auto/files/ACEA_preliminary_CO2_baseline_heavy-duty_vehicles.pdf +# but some are from https://ec.europa.eu/clima/system/files/2017-12/sr7_lot4_final_report_en.pdf +# and some are plain interpolations +# there is no single source agreeing or giving a complete set of data for +# all truck sizes, so we have to do some guessing +--- + +payload: + Urban delivery: + 3.5t: 750 + 7.5t: 1750 + 18t: 2700 + 26t: 6300 + 32t: 8755 + 40t: 8755 + 60t: 16400 + + Regional delivery: + 3.5t: 750 + 7.5t: 1750 + 18t: 3200 + 26t: 6300 + 32t: 10300 + 40t: 10300 + 60t: 19300 + + Long haul: + 3.5t: 1125 + 7.5t: 2625 + 18t: 7400 + 26t: 13400 + 32t: 13800 + 40t: 13800 + 60t: 19300 + +annual mileage: + Urban delivery: + 3.5t: 22660 + 7.5t: 33000 + 18t: 60000 + 26t: 60000 + 32t: 60000 + 40t: 60000 + 60t: 60000 + + Regional delivery: + 3.5t: 22660 + 7.5t: 33000 + 18t: 78000 + 26t: 73000 + 32t: 68000 + 40t: 68000 + 60t: 68000 + + Long haul: + 3.5t: 22660 + 7.5t: 33000 + 18t: 98000 + 26t: 108000 + 32t: 107000 + 40t: 107000 + 60t: 107000 + diff --git a/carculator_truck/model.py b/carculator_truck/model.py index 9316dd3..ab1352c 100644 --- a/carculator_truck/model.py +++ b/carculator_truck/model.py @@ -2,6 +2,7 @@ import numpy as np import xarray as xr from prettytable import PrettyTable +import yaml from .background_systems import BackgroundSystemModel from .driving_cycles import get_standard_driving_cycle @@ -9,6 +10,9 @@ from .hot_emissions import HotEmissionsModel from .noise_emissions import NoiseEmissionsModel from .particulates_emissions import ParticulatesEmissionsModel +from . import DATA_DIR + +CARGO_MASSES = DATA_DIR / "payloads.yaml" DEFAULT_MAPPINGS = { "electric": {"BEV", "PHEV-e"}, @@ -82,45 +86,7 @@ def __init__( } } - l_pwt = [ - pt - for pt in ("BEV", "FCEV", "HEV-d", "PHEV-e") - if pt in self.array.powertrain.values - ] - - for pt in l_pwt: - - if pt in self.energy_storage["electric"]: - self.array.loc[ - dict(powertrain=pt, parameter="battery cell energy density") - ] = self.array.loc[ - dict( - powertrain=pt, - parameter=f"battery cell energy density, {self.energy_storage['electric'][pt].split('-')[0].strip()}", - ) - ] - - self.array.loc[ - dict(powertrain=pt, parameter="battery cell mass share") - ] = self.array.loc[ - dict( - powertrain=pt, - parameter=f"battery cell mass share, {self.energy_storage['electric'][pt].split('-')[0].strip()}", - ) - ] - - else: - self.array.loc[ - dict(powertrain=pt, parameter="battery cell energy density") - ] = self.array.loc[ - dict(powertrain=pt, parameter="battery cell energy density, NMC") - ] - - self.array.loc[ - dict(powertrain=pt, parameter="battery cell mass share") - ] = self.array.loc[ - dict(powertrain=pt, parameter="battery cell mass share, NMC") - ] + self.set_battery_size() target_ranges = { "Urban delivery": 150, @@ -142,91 +108,7 @@ def __init__( cycle=cycle, size=self.array.coords["size"].values ) - # default values for annual mileage correspond to a long haul use - # default values used are from Annex I, pt 2.6 of - # https://eur-lex.europa.eu/eli/reg/2019/1242/oj#d1e32-227-1 - # if a driving cycle other than "Long haul" is selected, we apply - # a reduction factor on annual mileage (from the same EU report) - # to reflect the fact that trucks used for regional or urban delivery - # drive less annually - - # we also change the payload across driving cycles - # Annex I, pt 2.6 of https://eur-lex.europa.eu/eli/reg/2019/1242/oj#d1e32-227-1 - # shows that the payload changes (decreases) from long haul (LH) use, - # to regional delivery (RD) and urban delivery (UD). - # We use such relative change (-67% for rigid trucks going from LH to RD and UD, - # and -33% for articulate trucks, going from LH to RD and UD) as correction factors - # applied on default values (which are representative of LH and taken from TRACCS for EU28). - - if self.cycle == "Regional delivery": - - if any( - s in self.array.coords["size"].values - for s in ["3.5t", "7.5t", "18t", "26t"] - ): - self.array.loc[ - dict( - parameter="total cargo mass", - size=[ - s - for s in ["3.5t", "7.5t", "18t", "26t"] - if s in self.array.coords["size"].values - ], - ) - ] *= ( - 1 - 0.67 - ) - - if any( - s in self.array.coords["size"].values for s in ["32t", "40t", "60t"] - ): - self.array.loc[ - dict( - parameter="total cargo mass", - size=[ - s - for s in ["32t", "40t", "60t"] - if s in self.array.coords["size"].values - ], - ) - ] *= ( - 1 - 0.33 - ) - - if self.cycle == "Urban delivery": - - if any( - s in self.array.coords["size"].values - for s in ["3.5t", "7.5t", "18t", "26t"] - ): - self.array.loc[ - dict( - parameter="total cargo mass", - size=[ - s - for s in ["3.5t", "7.5t", "18t", "26t"] - if s in self.array.coords["size"].values - ], - ) - ] *= ( - 1 - 0.67 - ) - - if any( - s in self.array.coords["size"].values for s in ["32t", "40t", "60t"] - ): - self.array.loc[ - dict( - parameter="total cargo mass", - size=[ - s - for s in ["32t", "40t", "60t"] - if s in self.array.coords["size"].values - ], - ) - ] *= ( - 1 - 0.33 - ) + self.set_cargo_mass_and_annual_mileage() def __call__(self, key): """ @@ -344,7 +226,6 @@ def set_all(self): self.set_hot_emissions() self.create_PHEV() self.drop_hybrid() - self.drop_hybrid() self.array.values = np.clip(self.array.values, 0, None) @@ -466,6 +347,51 @@ def set_all(self): t.add_row(row + vals.tolist()) print(t) + def set_cargo_mass_and_annual_mileage(self): + + with open( + CARGO_MASSES, "r", encoding="utf-8" + ) as stream: + payload = yaml.safe_load(stream) + + for s in self.array.coords["size"].values: + self.array.loc[dict(size=s, parameter="total cargo mass")] = payload["payload"][self.cycle][s] + self.array.loc[dict(size=s, parameter="kilometers per year")] = payload["annual mileage"][self.cycle][s] + + + def set_battery_size(self): + + l_pwt = [ + pt + for pt in ("BEV", "FCEV", "HEV-d", "PHEV-e") + if pt in self.array.powertrain.values + ] + + for pt in l_pwt: + + chemistry = "NMC" + + if pt in self.energy_storage["electric"]: + chemistry = self.energy_storage['electric'][pt].split('-')[0].strip() + + self.array.loc[ + dict(powertrain=pt, parameter="battery cell energy density") + ] = self.array.loc[ + dict( + powertrain=pt, + parameter=f"battery cell energy density, {chemistry}", + ) + ] + + self.array.loc[ + dict(powertrain=pt, parameter="battery cell mass share") + ] = self.array.loc[ + dict( + powertrain=pt, + parameter=f"battery cell mass share, {chemistry}", + ) + ] + def adjust_combustion_power_share(self): """ If the exhaust CO2 emissions exceed the targets defined in `self.emission_target`, diff --git a/dev/Input data_truck.xlsx b/dev/Input data_truck.xlsx index d898437..3de3fb0 100644 Binary files a/dev/Input data_truck.xlsx and b/dev/Input data_truck.xlsx differ diff --git a/setup.py b/setup.py index 018b812..1573f89 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,7 @@ def package_files(directory): setup( name="carculator_truck", - version="0.3.4", + version="0.3.5", packages=packages, author="Romain Sacchi ", license=open("LICENSE").read(),