FASTSim
Description
This is the python/rust flavor of NREL's FASTSimTM, which is based on the original Excel implementation. Effort will be made to keep the core methodology between this software and the Excel flavor in line with one another.
All classes and methods are self-documented.
Installation
Python
Set up and activate a python environment (compatible with Python 3.8 - 3.10; we recommend Python 3.10) with the following steps.
Anaconda
- Create:
conda create -n fastsim python=3.10
- Activate:
conda activate fastsim
venv
There is some variation based on your Operating System:
-
PowerShell (windows):
- Create:
python -m venv fastsim-venv
-- name is user decision - Activate:
fastsim-venv/Scripts/Activate.ps1
- Create:
-
Bash (i.e. unix/linux/mac):
- Create:
python -m venv fastsim-venv
-- name is user decision - Activate:
source fastsim-venv/bin/activate
- Create:
-
Command Prompt (windows):
- Create:
python -m venv fastsim-venv
-- name is user decision - Activate:
fastsim-venv/Scripts/activate.bat
- Create:
FASTSim
Via PyPI
In an active Python environment created above, run pip install fastsim
.
Building from Scratch
Developers might want to install the code in place so that FASTSim files can be editable (the -e
flag for pip provides this behavior). This option can be handy since FASTSim will be installed in place from the installation location and any updates will be propagated each time FASTSim is freshly imported. To do this, you'll need to have the Rust toolchain installed.
- Option 1: run
sh build_and_test.sh
in root folder. - Option 2:
- Run
pip install -e ".[dev]"
Optional testing steps: - Run
cd rust/ && cargo test
- Run
pytest -v python/fastsim/tests/
- Run
Usage
To see and run examples, download the FASTSim demo files using the following code (with your Python environment activated and FASTSim installed):
from fastsim import utils
utils.copy_demo_files()
This code downloads demo files into a specified local directory (if no directory is specified, it will create a \demos
folder in the current working directory). WARNING: If you download the demo files to a location where files of the same name already exist, the original files will be overwritten.
Adding FASTSim as a Dependency in Rust
Via GitHub
Add this line:
fastsim-core = { git = "https://github.com/NREL/fastsim/", branch = "fastsim-2" }
to your Cargo.toml file, modifying the branch
key as appropriate.
Via Cargo
FASTSim is available as a Rust crate, which can be added to your dependencies via the following command:
cargo add fastsim-core
List of Abbreviations
cur = current time step
prev = previous time step
cyc = drive cycle
secs = seconds
mps = meters per second
mph = miles per hour
kw = kilowatts, unit of power
kwh = kilowatt-hour, unit of energy
kg = kilograms, unit of mass
max = maximum
min = minimum
avg = average
fs = fuel storage (eg. gasoline/diesel tank, pressurized hydrogen tank)
fc = fuel converter (eg. internal combustion engine, fuel cell)
mc = electric motor/generator and controller
ess = energy storage system (eg. high voltage traction battery)
chg = charging of a component
dis = discharging of a component
lim = limit of a component
regen = associated with regenerative braking
des = desired value
ach = achieved value
in = component input
out = component output
Contributors
Chad Baker -- Chad.Baker@nrel.gov
Aaron Brooker -- Aaron.Brooker@nrel.gov
Kyle Carow -- Kyle.Carow@nrel.gov
Robin Steuteville -- Robin.Steuteville@nrel.gov
Jeffrey Gonder -- Jeff.Gonder@nrel.gov
Jacob Holden -- Jacob.Holden@nrel.gov
Jinghu Hu -- Jinghu.Hu@nrel.gov
Jason Lustbader -- Jason.Lustbader@nrel.gov
Sean Lopp -- sean@rstudio.com
Matthew Moniot -- Matthew.Moniot@nrel.gov
Grant Payne -- Grant.Payne@nrel.gov
Laurie Ramroth -- lramroth@ford.com
Eric Wood -- Eric.Wood@nrel.gov
About this book
This is the overall FASTSim documentation. We're working toward making this a fully integrated document that includes both the Python API and Rust core documentation for the fastsim-2
branch and eventually also for the fastsim-3
branch.
Documentation
Python
Rust
Developers
Table of Contents
- fastsim
- fastsim.calibration
- fastsim.resample
- fastsim.cycle
- CycleCache
- Cycle
- LegacyCycle
- cyc_equal
- to_microtrips
- make_cycle
- equals
- concat
- resample
- clip_by_times
- accelerations
- peak_acceleration
- peak_deceleration
- calc_constant_jerk_trajectory
- accel_for_constant_jerk
- speed_for_constant_jerk
- dist_for_constant_jerk
- detect_passing
- average_step_speeds
- average_step_speed_at
- trapz_step_distances
- trapz_step_start_distance
- trapz_distance_for_step
- trapz_distance_over_range
- extend_cycle
- create_dist_and_target_speeds_by_microtrip
- copy_cycle
- fastsim.simdrivelabel
- fastsim.vehicle
- fastsim.tests.test_soc_correction
- fastsim.tests.test_utils
- fastsim.tests.test_logging
- fastsim.tests.test_auxiliaries
- fastsim.tests.test_eco_cruise
- fastsim.tests.test_coasting
- make_coasting_plot
- make_dvdd_plot
- TestCoasting
- test_cycle_reported_distance_traveled_m
- test_cycle_modifications_with_constant_jerk
- test_that_cycle_modifications_work_as_expected
- test_that_we_can_coast
- test_eco_approach_modeling
- test_consistency_of_constant_jerk_trajectory
- test_that_final_speed_of_cycle_modification_matches_trajectory_calcs
- test_that_cycle_distance_reported_is_correct
- test_brake_trajectory
- test_logic_to_enter_eco_approach_automatically
- test_that_coasting_works_going_uphill
- test_that_coasting_logic_works_going_uphill
- test_that_coasting_logic_works_going_downhill
- test_that_coasting_works_with_multiple_stops_and_grades
- fastsim.tests.test_vehicle
- fastsim.tests.test_copy
- fastsim.tests.test_simdrivelabel
- fastsim.tests.test_simdrive_sweep
- fastsim.tests.test_cycle
- calc_distance_traveled_m
- dicts_are_equal
- TestCycle
- test_monotonicity
- test_load_dict
- test_that_udds_has_18_microtrips
- test_roundtrip_of_microtrip_and_concat
- test_roundtrip_of_microtrip_and_concat_using_keep_name_arg
- test_set_from_dict_for_a_microtrip
- test_duration_of_concatenated_cycles_is_the_sum_of_the_components
- test_cycle_equality
- test_that_cycle_resampling_works_as_expected
- test_resampling_and_concatenating_cycles
- test_resampling_with_hold_keys
- test_that_resampling_preserves_total_distance_traveled_using_rate_keys
- test_clip_by_times
- test_get_accelerations
- test_that_copy_creates_idential_structures
- test_make_cycle
- test_key_conversion
- test_get_grade_by_distance
- test_dt_s_vs_dt_s_at_i
- test_trapz_step_start_distance
- test_that_cycle_cache_interp_grade_substitutes_for_average_grade_over_range
- test_that_trapz_step_start_distance_equals_cache_trapz_distances
- test_average_grade_over_range_with_and_without_cache
- fastsim.tests.test_vs_excel
- fastsim.tests.test_resources
- fastsim.tests.test_rust
- fastsim.tests
- fastsim.tests.test_cav_sweep
- fastsim.tests.test_following
- fastsim.tests.test_simdrive
- fastsim.utils.utilities
- fastsim.utils.vehicle_import_preproc
- fastsim.utils
- fastsim.auxiliaries
- fastsim.simdrive
- fastsim.vehicle_base
- fastsim.inspect_utils
- fastsim.parameters
- fastsim.demos.vehicle_import_demo
- fastsim.demos.cav_sweep
- fastsim.demos.fusion_thermal_cal_post
- fastsim.demos.demo_eu_vehicle_wltp
- fastsim.demos.accel_demo
- fastsim.demos.fusion_thermal_cal
- fastsim.demos.calibration_demo
- fastsim.demos.stop_start_demo
- fastsim.demos.wltc_calibration
- fastsim.demos.timing_demo
- fastsim.demos.demo
- fastsim.demos.time_dilation_demo
- fastsim.demos.test_demos
- fastsim.demos.cav_demo
- fastsim.demos.demo_abc_drag_coef_conv
- fastsim.demos.2017_Ford_F150_thermal_val
- fastsim.demos
- fastsim.demos.fusion_thermal_demo
fastsim
Package containing modules for running FASTSim. For example usage, see
package_root
def package_root() -> Path
Returns the package root directory.
resources_root
def resources_root() -> Path
Returns the resources root directory.
fastsim.calibration
get_error_val
def get_error_val(model: npt.NDArray[np.float64],
test: npt.NDArray[np.float64],
time_steps: npt.NDArray[np.float64]) -> float
Returns time-averaged error for model and test signal.
Arguments:
model
npt.NDArray[np.float64] - array of values for signal from modeltest
npt.NDArray[np.float64] - array of values for signal from test datatime_steps
npt.NDArray[np.float64] - array (or scalar for constant) of values for model time steps [s]
Returns:
float
- integral of absolute value of difference between model and test per time
ModelObjectives Objects
@dataclass
class ModelObjectives(object)
Class for calculating eco-driving objectives
get_errors
def get_errors(
sim_drives: Dict[str, fsr.RustSimDrive | fsr.SimDriveHot],
return_mods: bool = False,
plot: bool = False,
plot_save_dir: Optional[str] = None,
plot_perc_err: bool = False,
show: bool = False,
fontsize: float = 12,
plotly: bool = False
) -> Union[
Dict[str, Dict[str, float]],
# or if return_mods is True
Tuple[Dict[str, fsim.simdrive.SimDrive], Dict[str, Dict[str, float]]]]
Calculate model errors w.r.t. test data for each element in dfs/models for each objective.
Arguments:
sim_drives
Dict[str, fsr.RustSimDrive | fsr.SimDriveHot] - dictionary with user-defined keys and SimDrive or SimDriveHot instancesreturn_mods
bool, optional - if true, also returns dict of solved models. Defaults to False.plot
bool, optional - if true, plots objectives using matplotlib.pyplot. Defaults to False.plot_save_dir
Optional[str], optional - directory in which to save plots. If None, plots are not saved. Defaults to None.plot_perc_err
bool, optional - whether to include % error axes in plots. Defaults to False.show
bool, optional - whether to show matplotlib.pyplot plots. Defaults to False.fontsize
float, optional - plot font size. Defaults to 12.plotly
bool, optional - whether to generate plotly plots, which can be opened manually in a browser window. Defaults to False.
Returns:
Objectives and optionally solved models
update_params
def update_params(xs: List[Any])
Updates model parameters based on x
, which must match length of self.params
get_parser
def get_parser(
def_description: str = "Program for calibrating fastsim models.",
def_p: int = 4,
def_n_max_gen: int = 500,
def_pop_size: int = 12,
def_save_path: Optional[str] = "pymoo_res") -> argparse.ArgumentParser
Generate parser for optimization hyper params and misc. other params
Arguments:
def_p
int, optional - default number of processes. Defaults to 4.def_n_max_gen
int, optional - max allowed generations. Defaults to 500.def_pop_size
int, optional - default population size. Defaults to 12.def_save_path
str, optional - default save path. Defaults topymoo_res
.
Returns:
argparse.ArgumentParser
- description
fastsim.resample
resample
def resample(df: pd.DataFrame,
dt_new: Optional[float] = 1.0,
time_col: Optional[str] = "Time[s]",
rate_vars: Optional[Tuple[str]] = [],
hold_vars: Optional[Tuple[str]] = []) -> pd.DataFrame
Resamples dataframe df
.
Arguments:
- df: dataframe to resample
- dt_new: new time step size, default 1.0 s
- time_col: column for time in s
- rate_vars: list of variables that represent rates that need to be time averaged
- hold_vars: vars that need zero-order hold from previous nearest time step (e.g. quantized variables like current gear)
fastsim.cycle
Module containing classes and methods for cycle data.
CycleCache Objects
class CycleCache()
interp_grade
def interp_grade(dist: float)
Interpolate the single-point grade at the given distance. Assumes that the grade at i applies from sample point (i-1, i]
interp_elevation
def interp_elevation(dist: float)
Interpolate the elevation at the given distance
Cycle Objects
@dataclass
class Cycle(object)
Object for containing time, speed, road grade, and road charging vectors
for drive cycle. Instantiate with the from_file
or from_dict
method.
from_file
@classmethod
def from_file(cls, filename: str) -> Self
Load cycle from filename (str).
Can be absolute or relative path. If relative, looks in working dir first
and then in fastsim/resources/cycles
.
File must contain columns for:
-- cycSecs
or time_s
-- cycMps
or mps
-- cycGrade
or grade
(optional)
-- cycRoadType
or road_type
(optional)
from_dict
@classmethod
def from_dict(cls, cyc_dict: dict) -> Self
Load cycle from dict, which must contain keys for:
-- cycSecs
or time_s
-- cycMps
or mps
-- cycGrade
or grade
(optional)
-- cycRoadType
or road_type
(optional)
get_numba_cyc
def get_numba_cyc()
Deprecated.
build_cache
def build_cache() -> CycleCache
Calculates a dataclass containing expensive-to-calculate items. The data created can persist between calls and optionally be passed into methods that can use it which will result in a performance enhancement. RETURN: CycleCache
dt_s_at_i
def dt_s_at_i(i: int) -> float
Calculate the time-step duration for time-step i
.
Returns: the time-step duration in seconds
delta_elev_m
@property
def delta_elev_m() -> np.ndarray
Cumulative elevation change w.r.t. to initial
__len__
def __len__() -> int
return cycle length
to_dict
def to_dict() -> Dict[str, np.ndarray]
Returns cycle as dict rather than class instance.
reset_orphaned
def reset_orphaned()
Dummy method for flexibility between Rust/Python version interfaces
copy
def copy() -> Self
Return a copy of this Cycle instance.
average_grade_over_range
def average_grade_over_range(distance_start_m,
delta_distance_m,
cache: Optional[CycleCache] = None)
Returns the average grade over the given range of distances
- distance_start_m: non-negative-number, the distance at start of evaluation area (m)
- delta_distance_m: non-negative-number, the distance traveled from distance_start_m (m) RETURN: number, the average grade (rise over run) over the given distance range Note: grade is assumed to be constant from just after the previous sample point until the current sample point. That is, grade[i] applies over the range of distances, d, from (d[i - 1], d[i]]
calc_distance_to_next_stop_from
def calc_distance_to_next_stop_from(distance_m: float,
cache: Optional[CycleCache] = None
) -> float
Calculate the distance to next stop from distance_m
- distance_m: non-negative-number, the current distance from start (m) RETURN: returns the distance to the next stop from distance_m NOTE: distance may be negative if we're beyond the last stop
modify_by_const_jerk_trajectory
def modify_by_const_jerk_trajectory(idx, n, jerk_m__s3, accel0_m__s2)
Modifies the cycle using the given constant-jerk trajectory parameters
- idx: non-negative integer, the point in the cycle to initiate modification (note: THIS point is modified since trajectory should be calculated from idx-1)
- jerk_m__s3: number, the "Jerk" associated with the trajectory (m/s3)
- accel0_m__s2: number, the initial acceleration (m/s2) NOTE:
- modifies cyc in place to hit any critical rendezvous_points by a trajectory adjustment
- CAUTION: NOT ROBUST AGAINST VARIABLE DURATION TIME-STEPS RETURN: Number, final modified speed (m/s)
modify_with_braking_trajectory
def modify_with_braking_trajectory(brake_accel_m__s2: float,
idx: int,
dts_m: Optional[float] = None) -> tuple
Add a braking trajectory that would cover the same distance as the given constant brake deceleration
- brake_accel_m__s2: negative number, the braking acceleration (m/s2)
- idx: non-negative integer, the index where to initiate the stop trajectory, start of the step (i in FASTSim)
- dts_m: None | float: if given, this is the desired distance-to-stop in meters. If not given, it is calculated based on braking deceleration. RETURN: (non-negative-number, positive-integer)
- the final speed of the modified trajectory (m/s)
- the number of time-steps required to complete the braking maneuver NOTE:
- modifies the cycle in place for the braking trajectory
LegacyCycle Objects
class LegacyCycle(object)
Implementation of Cycle with legacy keys.
__init__
def __init__(cycle: Cycle)
Given cycle, returns legacy cycle.
cyc_equal
def cyc_equal(a: Cycle, b: Cycle) -> bool
Return True if a and b are equal
to_microtrips
def to_microtrips(cycle, stop_speed_m__s=1e-6, keep_name=False)
Split a cycle into an array of microtrips with one microtrip being a start to subsequent stop plus any idle (stopped time).
Arguments:
cycle
- drive cycle converted to dictionary by cycle.to_dict()stop_speed_m__s
- speed at which vehicle is considered stopped for trip separationkeep_name
- (optional) bool, if True and cycle contains "name", adds that name to all microtrips
make_cycle
def make_cycle(ts, vs, gs=None, rs=None) -> dict
(Array Num) (Array Num) (Array Num)? -> Dict Create a cycle from times, speeds, and grades. If grades is not specified, it is set to zero.
Arguments:
ts
- array of times [s]vs
- array of vehicle speeds [mps]gs
- array of gradesrs
- array of road types (charging or not)
equals
def equals(c1, c2) -> bool
Dict Dict -> Bool Returns true if the two cycles are equal, false otherwise
Arguments:
c1
- cycle as dictionary from to_dict()c2
- cycle as dictionary from to_dict()
concat
def concat(cycles, name=None)
Concatenates cycles together one after another into a single dictionary (Array Dict) String -> Dict
Arguments:
cycles
- (Array Dict)name
- (optional) string or None, if a string, adds the "name" key to the output
resample
def resample(cycle: Dict[str, Any],
new_dt: Optional[float] = None,
start_time: Optional[float] = None,
end_time: Optional[float] = None,
hold_keys: Optional[Set[str]] = None,
hold_keys_next: Optional[Set[str]] = None,
rate_keys: Optional[Set[str]] = None)
Cycle new_dt=?Real start_time=?Real end_time=?Real -> Cycle Resample a cycle with a new delta time from start time to end time.
- cycle: Dict with keys 'time_s': numpy.array Real giving the elapsed time
- new_dt: Real, optional the new delta time of the sampling. Defaults to the difference between the first two times of the cycle passed in
- start_time: Real, optional the start time of the sample. Defaults to 0.0 seconds
- end_time: Real, optional the end time of the cycle. Defaults to the last time of the passed in cycle.
- hold_keys: None or (Set String), if specified, yields values that should be interpolated step-wise, holding their value until an explicit change (i.e., NOT interpolated)
- hold_keys_next: None or (Set String), similar to hold_keys but yields values that should be interpolated step-wise, taking the NEXT value as the value (vs hold_keys which uses the previous)
- rate_keys: None or (Set String), if specified, yields values that maintain the interpolated value of the given rate. So, for example, if a speed, will set the speed such that the distance traveled is consistent. Note: using rate keys for mps may result in non-zero starting and ending speeds Resamples all non-time metrics by the new sample time.
clip_by_times
def clip_by_times(cycle, t_end, t_start=0)
Cycle Number Number -> Cycle INPUT:
- cycle: Dict, a legitimate driving cycle
- t_start: Number, time to start
- t_end: Number, time to end RETURNS: Dict, the cycle with fields snipped to times >= t_start and <= t_end Clip the cycle to the given times and return
accelerations
def accelerations(cycle)
Cycle -> Real Return the acceleration of the given cycle INPUTS:
- cycle: Dict, a legitimate driving cycle OUTPUTS: Real, the maximum acceleration
peak_acceleration
def peak_acceleration(cycle)
Cycle -> Real Return the maximum acceleration of the given cycle INPUTS:
- cycle: Dict, a legitimate driving cycle OUTPUTS: Real, the maximum acceleration
peak_deceleration
def peak_deceleration(cycle)
Cycle -> Real Return the minimum acceleration (maximum deceleration) of the given cycle INPUTS:
- cycle: Dict, a legitimate driving cycle OUTPUTS: Real, the maximum acceleration
calc_constant_jerk_trajectory
def calc_constant_jerk_trajectory(n: int, D0: float, v0: float, Dr: float,
vr: float, dt: float) -> tuple
Num Num Num Num Num Int -> (Tuple 'jerk_m__s3': Num, 'accel_m__s2': Num) INPUTS:
- n: Int, number of time-steps away from rendezvous
- D0: Num, distance of simulated vehicle (m/s)
- v0: Num, speed of simulated vehicle (m/s)
- Dr: Num, distance of rendezvous point (m)
- vr: Num, speed of rendezvous point (m/s)
- dt: Num, step duration (s) RETURNS: (Tuple 'jerk_m__s3': Num, 'accel_m__s2': Num) Returns the constant jerk and acceleration for initial time step.
accel_for_constant_jerk
def accel_for_constant_jerk(n, a0, k, dt)
Calculate the acceleration n timesteps away INPUTS:
- n: Int, number of times steps away to calculate
- a0: Num, initial acceleration (m/s2)
- k: Num, constant jerk (m/s3)
- dt: Num, time-step duration in seconds NOTE:
- this is the constant acceleration over the time-step from sample n to sample n+1 RETURN: Num, the acceleration n timesteps away (m/s2)
speed_for_constant_jerk
def speed_for_constant_jerk(n, v0, a0, k, dt)
Int Num Num Num Num -> Num Calculate speed (m/s) n timesteps away INPUTS:
- n: Int, numer of timesteps away to calculate
- v0: Num, initial speed (m/s)
- a0: Num, initial acceleration (m/s2)
- k: Num, constant jerk
- dt: Num, duration of a timestep (s) NOTE:
- this is the speed at sample n
- if n == 0, speed is v0
- if n == 1, speed is v0 + a0*dt, etc. RETURN: Num, the speed n timesteps away (m/s)
dist_for_constant_jerk
def dist_for_constant_jerk(n, d0, v0, a0, k, dt)
Calculate distance (m) after n timesteps INPUTS:
- n: Int, numer of timesteps away to calculate
- d0: Num, initial distance (m)
- v0: Num, initial speed (m/s)
- a0: Num, initial acceleration (m/s2)
- k: Num, constant jerk
- dt: Num, duration of a timestep (s) NOTE:
- this is the distance traveled from start (i.e., n=0) measured at sample point n RETURN: Num, the distance at n timesteps away (m)
detect_passing
def detect_passing(cyc: Cycle,
cyc0: Cycle,
i: int,
dist_tol_m: float = 0.1) -> PassingInfo
Reports back information of the first point where cyc passes cyc0, starting at step i until the next stop of cyc.
- cyc: fastsim.Cycle, the proposed cycle of the vehicle under simulation
- cyc0: fastsim.Cycle, the reference/lead vehicle/shadow cycle to compare with
- i: int, the time-step index to consider
- dist_tol_m: float, the distance tolerance away from lead vehicle to be seen as "deviated" from the reference/shadow trace (m) RETURNS: PassingInfo
average_step_speeds
def average_step_speeds(cyc: Cycle) -> np.ndarray
Calculate the average speed per each step in m/s
average_step_speed_at
def average_step_speed_at(cyc: Cycle, i: int) -> float
Calculate the average step speed at step i in m/s (i.e., from sample point i-1 to i)
trapz_step_distances
def trapz_step_distances(cyc: Cycle) -> np.ndarray
Sum of the distance traveled over each step using trapezoidal integration
trapz_step_start_distance
def trapz_step_start_distance(cyc: Cycle, i: int) -> float
The distance traveled from start at the beginning of step i (i.e., distance traveled up to sample point i-1) Distance is in meters.
trapz_distance_for_step
def trapz_distance_for_step(cyc: Cycle, i: int) -> float
The distance traveled during step i in meters (i.e., from sample point i-1 to i)
trapz_distance_over_range
def trapz_distance_over_range(cyc: Cycle, i_start: int, i_end: int) -> float
Calculate the distance from step i_start to the start of step i_end (i.e., distance from sample point i_start-1 to i_end-1)
extend_cycle
def extend_cycle(cyc: Cycle,
absolute_time_s: float = 0.0,
time_fraction: float = 0.0,
use_rust: bool = False) -> Cycle
- cyc: fastsim.cycle.Cycle
- absolute_time_s: float, the seconds to extend
- time_fraction: float, the fraction of the original cycle time to add on
- use_rust: bool, if True, return a RustCycle instance, else a normal Python Cycle RETURNS: fastsim.cycle.Cycle (or fastsimrust.RustCycle), the new cycle with stopped time appended NOTE: additional time is rounded to the nearest second
create_dist_and_target_speeds_by_microtrip
def create_dist_and_target_speeds_by_microtrip(
cyc: Cycle,
blend_factor: float = 0.0,
min_target_speed_mps: float = 8.0) -> list
Create distance and target speeds by microtrip This helper function splits a cycle up into microtrips and returns a list of 2-tuples of: (distance from start in meters, target speed in meters/second)
- cyc: the cycle to operate on
- blend_factor: float, from 0 to 1 if 0, use average speed of the microtrip if 1, use average speed while moving (i.e., no stopped time) else something in between
- min_target_speed_mps: float, the minimum target speed allowed (m/s) RETURN: list of 2-tuple of (float, float) representing the distance of start of each microtrip and target speed for that microtrip NOTE: target speed per microtrip is not allowed to be below min_target_speed_mps
copy_cycle
def copy_cycle(
cyc: Cycle,
return_type: str = None,
deep: bool = True
) -> Dict[str, np.ndarray] | Cycle | LegacyCycle | RustCycle
Returns copy of Cycle.
Arguments:
cyc
- instantianed Cycle or CycleJit return_type:default
- infer from type of cyc'dict'
- dict'python'
- Cycle'legacy'
- LegacyCycle'rust'
- RustCycledeep
- if True, uses deepcopy on everything
fastsim.simdrivelabel
Module containing classes and methods for calculating label fuel economy.
get_label_fe
def get_label_fe(veh: vehicle.Vehicle,
full_detail: bool = False,
verbose: bool = False,
chg_eff: float = None,
use_rust=False)
Generates label fuel economy (FE) values for a provided vehicle.
Arguments:
veh : vehicle.Vehicle() full_detail : boolean, default False If True, sim_drive objects for each cycle are also returned. verbose : boolean, default false If true, print out key results chg_eff : float between 0 and 1 Override for chg_eff -- currently not functional
-
use_rust
- bool, if True, use rust version of classes, else PythonReturns label fuel economy values as a dict and (optionally) simdrive.SimDriveClassic objects.
fastsim.vehicle
Module containing classes and methods for for loading vehicle data.
clean_data
def clean_data(raw_data)
Cleans up data formatting. Argument:
raw_data: cell of vehicle dataframe
Output: clean_data: cleaned up data
Vehicle Objects
@dataclass
class Vehicle(object)
Class for loading and contaning vehicle attributes
See from_vehdb
, from_file
, and from_dict
methods for usage instructions.
from_vehdb
@classmethod
def from_vehdb(cls,
vnum: int,
veh_file: str = None,
to_rust: bool = False) -> Self
Load vehicle vnum
from default vehdb or veh_file
.
Arguments:
vnum
- vehicle numberveh_file
- path to vehicle database fileto_rust
- if True, convert to rust-compatible vehicle
from_file
@classmethod
def from_file(cls,
filename: str,
vnum: int = None,
to_rust: bool = False) -> Self
Loads vehicle from file filename
(str). Looks in working dir and then
fastsim/resources/vehdb, which also contains numerous examples of vehicle csv files.
vnum
is needed for multi-vehicle files.
Arguments:
filename
- path to vehicle database filevnum
- vehicle numberto_rust
- if True, convert to rust-compatible vehicle
from_df
@classmethod
def from_df(cls,
vehdf: pd.DataFrame,
vnum: int,
veh_file: Path,
to_rust: bool = False) -> Self
Given vehdf, generates dict to feed to from_dict
.
Arguments:
vehdf
- pandas dataframe of vehicle attributesvnum
- vehicle numberveh_file
- path to vehicle database fileto_rust
- if True, convert to rust-compatible vehicle
from_dict
@classmethod
def from_dict(cls, veh_dict: dict, to_rust: bool = False) -> Self
Load vehicle from dict with snake_case key names.
Arguments:
veh_dict
- dict of vehicle attributesto_rust
- if True, convert to rust-compatible vehicle
__post_init__
def __post_init__(converted_to_rust: bool = False)
Sets derived parameters.
Arguments:
fc_peak_eff_override
- float (0, 1) or -1, if provided and not -1, overrides engine peak efficiency with proportional scaling. Default of -1 has no effect.mc_peak_eff_override
- float (0, 1) or -1, if provided and not -1, overrides motor peak efficiency with proportional scaling. Default of -1 has no effect.
set_derived
def set_derived()
Sets derived parameters.
Arguments:
fc_peak_eff_override
- float (0, 1) or -1, if provided and not -1, overrides engine peak efficiency with proportional scaling. Default of -1 has no effect.mc_peak_eff_override
- float (0, 1) or -1, if provided and not -1, overrides motor peak efficiency with proportional scaling. Default of -1 has no effect.
set_veh_mass
def set_veh_mass()
Calculate total vehicle mass. Sum up component masses if positive real number is not specified for self.veh_override_kg
veh_type_selection
@property
def veh_type_selection() -> str
Copying veh_pt_type to additional key to be consistent with Excel version but not used in Python version
get_mcPeakEff
def get_mcPeakEff() -> float
Return np.max(self.mc_eff_array)
set_mcPeakEff
def set_mcPeakEff(new_peak)
Set motor peak efficiency EVERYWHERE.
Arguments:
new_peak
- float, new peak motor efficiency in decimal form
get_fcPeakEff
def get_fcPeakEff() -> float
Return np.max(self.fc_eff_array)
set_fcPeakEff
def set_fcPeakEff(new_peak)
Set fc peak efficiency EVERWHERE.
Arguments:
new_peak
- float, new peak fc efficiency in decimal form
get_numba_veh
def get_numba_veh()
Deprecated.
to_rust
def to_rust() -> RustVehicle
Return a Rust version of the vehicle
reset_orphaned
def reset_orphaned()
Dummy method for flexibility between Rust/Python version interfaces
LegacyVehicle Objects
class LegacyVehicle(object)
Implementation of Vehicle with legacy keys.
__init__
def __init__(vehicle: Vehicle)
Given cycle, returns legacy cycle.
to_native_type
def to_native_type(value)
Attempts to map from numpy and other types to python native for better yaml (de-)serialization
copy_vehicle
def copy_vehicle(
veh: Vehicle,
return_type: str = None,
deep: bool = True
) -> Dict[str, np.ndarray] | Vehicle | LegacyVehicle | RustVehicle
Returns copy of Vehicle.
Arguments:
veh
- instantiated Vehicle or RustVehicle return_type:'dict'
- dict'vehicle'
- Vehicle'legacy'
- LegacyVehicle'rust'
- RustVehicle
veh_equal
def veh_equal(veh1: Vehicle, veh2: Vehicle, full_out: bool = False) -> bool
Given veh1 and veh2, which can be Vehicle and/or RustVehicle instances, return True if equal.
Arguments:
fastsim.tests.test_soc_correction
Tests an HEV correction methodology versus other techniques
TestSocCorrection Objects
class TestSocCorrection(unittest.TestCase)
test_that_soc_correction_method_works
def test_that_soc_correction_method_works()
Test using an SOC equivalency method versus other techniques
fastsim.tests.test_utils
fastsim.tests.test_logging
fastsim.tests.test_auxiliaries
fastsim.tests.test_eco_cruise
Test the eco-cruise feature in FASTSim
fastsim.tests.test_coasting
Tests that check the drive cycle modification functionality.
make_coasting_plot
def make_coasting_plot(
cyc0: fastsim.cycle.Cycle,
cyc: fastsim.cycle.Cycle,
use_mph: bool = False,
title: Optional[str] = None,
save_file: Optional[str] = None,
do_show: bool = False,
verbose: bool = False,
gap_offset_m: float = 0.0,
coast_brake_start_speed_m_per_s: Optional[float] = None)
- cyc0: Cycle, the reference cycle (the "shadow trace" or "lead vehicle")
- cyc: Cycle, the actual cycle driven
- use_mph: Bool, if True, plot in miles per hour, else m/s
- title: None or string, if string, set the title
- save_file: (Or None string), if specified, save the file to disk
- do_show: Bool, whether to show the file or not
- verbose: Bool, if True, prints out
- gap_offset_m: number, an offset to apply to the gap metrics (m)
- coast_brake_start_speed_m_per_s: None | number, if supplied, plots the coast-start speed (m/s) RETURN: None
- saves creates the given file and shows it
make_dvdd_plot
def make_dvdd_plot(cyc: fastsim.cycle.Cycle,
coast_to_break_speed_m__s: Union[float, None] = None,
use_mph: bool = False,
save_file: Union[None, str] = None,
do_show: bool = False,
curve_fit: bool = True,
additional_xs: Union[None, List[float]] = None,
additional_ys: Union[None, List[float]] = None)
Create a change in speed (dv) by change in distance (dd) plot
TestCoasting Objects
class TestCoasting(unittest.TestCase)
test_cycle_reported_distance_traveled_m
def test_cycle_reported_distance_traveled_m()
test_cycle_modifications_with_constant_jerk
def test_cycle_modifications_with_constant_jerk()
test_that_cycle_modifications_work_as_expected
def test_that_cycle_modifications_work_as_expected()
test_that_we_can_coast
def test_that_we_can_coast()
Test the standard interface to Eco-Approach for 'free coasting'
test_eco_approach_modeling
def test_eco_approach_modeling()
Test a simplified model of eco-approach
test_consistency_of_constant_jerk_trajectory
def test_consistency_of_constant_jerk_trajectory()
Confirm that acceleration, speed, and distances are as expected for constant jerk trajectory
test_that_final_speed_of_cycle_modification_matches_trajectory_calcs
def test_that_final_speed_of_cycle_modification_matches_trajectory_calcs()
test_that_cycle_distance_reported_is_correct
def test_that_cycle_distance_reported_is_correct()
Test the reported distances via cycDistMeters
test_brake_trajectory
def test_brake_trajectory()
test_logic_to_enter_eco_approach_automatically
def test_logic_to_enter_eco_approach_automatically()
Test that we can auto-enter eco-approach
test_that_coasting_works_going_uphill
def test_that_coasting_works_going_uphill()
Test coasting logic while hill climbing
test_that_coasting_logic_works_going_uphill
def test_that_coasting_logic_works_going_uphill()
When going uphill, we want to ensure we can still hit our coasting target
test_that_coasting_logic_works_going_downhill
def test_that_coasting_logic_works_going_downhill()
When going downhill, ensure we can still hit our coasting target
test_that_coasting_works_with_multiple_stops_and_grades
def test_that_coasting_works_with_multiple_stops_and_grades()
Ensure coasting hits distance target with multiple stops and both uphill/downhill
fastsim.tests.test_vehicle
Test suite for cycle instantiation and manipulation.
TestVehicle Objects
class TestVehicle(unittest.TestCase)
test_equal
def test_equal()
Verify that a copied Vehicle and original are equal.
test_properties
def test_properties()
Verify that some of the property variables are working as expected.
test_fc_efficiency_override
def test_fc_efficiency_override()
Verify that we can scale FC
test_set_derived_init
def test_set_derived_init()
Verify that we can set derived parameters or not on init.
fastsim.tests.test_copy
Test various copy utilities
TestCopy Objects
class TestCopy(unittest.TestCase)
test_copy_cycle
def test_copy_cycle()
Test that cycle_copy works as expected
test_copy_physical_properties
def test_copy_physical_properties()
Test that copy_physical_properties works as expected
test_copy_vehicle
def test_copy_vehicle()
Test that vehicle_copy works as expected
test_copy_sim_params
def test_copy_sim_params()
Test that copy_sim_params works as expected
test_copy_sim_drive
def test_copy_sim_drive()
Test that copy_sim_drive works as expected
fastsim.tests.test_simdrivelabel
fastsim.tests.test_simdrive_sweep
Test script that saves results from 26 vehicles currently in master branch of FASTSim as of 17 December 2019 for 3 standard cycles. From command line, pass True (default if left blank) or False argument to use JIT compilation or not, respectively.
main
def main(err_tol=1e-4, verbose=True, use_rust=False)
Runs test test for 26 vehicles and 3 cycles. Test compares cumulative positive and negative energy values to a benchmark from earlier.
Arguments:
err_tol : error tolerance default of 1e-4 was selected to prevent minor errors from showing. As of 31 December 2020, a recent python update caused errors that are smaller than this and therefore ok to neglect.
verbose
- if True, prints progressuse_rust
- Boolean, if True, use Rust version of classes, else python version
Returns:
df_err : pandas datafram, fractional errors df : pandas dataframe, new values df0 : pandas dataframe, original benchmark values
col_for_max_error
- string or None, the column name of the column having max absolute errormax_abs_err
- number or None, the maximum absolute error if it exists
TestSimDriveSweep Objects
class TestSimDriveSweep(unittest.TestCase)
test_sweep
def test_sweep()
Compares results against benchmark.
fastsim.tests.test_cycle
Test suite for cycle instantiation and manipulation.
calc_distance_traveled_m
def calc_distance_traveled_m(cyc, up_to=None)
Calculate the distance traveled in meters
- cyc: a cycle dictionary
- up_to: None or a positive number indicating a time in seconds. Will calculate the distance up-to that given time RETURN: Number, the distance traveled in meters
dicts_are_equal
def dicts_are_equal(d1, d2, d1_name=None, d2_name=None)
Checks if dictionaries are equal
- d1: dict
- d2: dict
- d1_name: None or string, the name used for dict 1 in messaging
- d2_name: None or string, the name used for dict 1 in messaging RETURN: (boolean, (Array string)), Returns (True, []) if the dictionaries are equal; otherwise, returns (False, [... list of issues here])
TestCycle Objects
class TestCycle(unittest.TestCase)
test_monotonicity
def test_monotonicity()
checks that time is monotonically increasing
test_load_dict
def test_load_dict()
checks that conversion from dict works
test_that_udds_has_18_microtrips
def test_that_udds_has_18_microtrips()
Check that the number of microtrips equals expected
test_roundtrip_of_microtrip_and_concat
def test_roundtrip_of_microtrip_and_concat()
A cycle split into microtrips and concatenated back together should equal the original
test_roundtrip_of_microtrip_and_concat_using_keep_name_arg
def test_roundtrip_of_microtrip_and_concat_using_keep_name_arg()
A cycle split into microtrips and concatenated back together should equal the original
test_set_from_dict_for_a_microtrip
def test_set_from_dict_for_a_microtrip()
Test splitting into microtrips and setting is as expected
test_duration_of_concatenated_cycles_is_the_sum_of_the_components
def test_duration_of_concatenated_cycles_is_the_sum_of_the_components()
Test that two cycles concatenated have the same duration as the sum of the constituents
test_cycle_equality
def test_cycle_equality()
Test structural equality of driving cycles
test_that_cycle_resampling_works_as_expected
def test_that_cycle_resampling_works_as_expected()
Test resampling the values of a cycle
test_resampling_and_concatenating_cycles
def test_resampling_and_concatenating_cycles()
Test that concatenating cycles at different sampling rates works as expected
test_resampling_with_hold_keys
def test_resampling_with_hold_keys()
Test that 'hold_keys' works with resampling
test_that_resampling_preserves_total_distance_traveled_using_rate_keys
def test_that_resampling_preserves_total_distance_traveled_using_rate_keys()
Distance traveled before and after resampling should be the same when rate_keys are used
test_clip_by_times
def test_clip_by_times()
Test that clipping by times works as expected
test_get_accelerations
def test_get_accelerations()
Test getting and processing accelerations
test_that_copy_creates_idential_structures
def test_that_copy_creates_idential_structures()
Checks that copy methods produce identical cycles
test_make_cycle
def test_make_cycle()
Check that make_cycle works as expected
test_key_conversion
def test_key_conversion()
check that legacy keys can still be generated
test_get_grade_by_distance
def test_get_grade_by_distance()
check that we can lookup grade by distance
test_dt_s_vs_dt_s_at_i
def test_dt_s_vs_dt_s_at_i()
Test that dt_s_at_i is a true replacement for dt_s[i]
test_trapz_step_start_distance
def test_trapz_step_start_distance()
Test the implementation of trapz_step_start_distance
test_that_cycle_cache_interp_grade_substitutes_for_average_grade_over_range
def test_that_cycle_cache_interp_grade_substitutes_for_average_grade_over_range(
)
Ensure that CycleCache.interp_grade actually predicts the same values as Cycle.average_grade_over_range(d, 0.0, cache=None|CycleCache) with and without using CycleCache
test_that_trapz_step_start_distance_equals_cache_trapz_distances
def test_that_trapz_step_start_distance_equals_cache_trapz_distances()
Test that cycle.trapz_step_start_distance(self.cyc0, i) == self._cyc0_cache.trapz_distances_m[i-1]
test_average_grade_over_range_with_and_without_cache
def test_average_grade_over_range_with_and_without_cache()
Ensure that CycleCache usage only speeds things up; doesn't change values...
fastsim.tests.test_vs_excel
Module for comparing python results with Excel by running all the vehicles in both Excel (uses archived results if Excel version not available) and Python FASTSim for both UDDS and HWFET cycles.
run
def run(vehicles=np.arange(1, 27), verbose=True, use_rust=False)
Runs python fastsim through 26 vehicles and returns list of dictionaries containing scenario descriptions.
Arguments:
verbose : Boolean if True, print progress
use_rust
- Boolean, if True, use Rust versions of classes
run_excel
def run_excel(
vehicles=np.arange(1, 28), prev_res_path=PREV_RES_PATH,
rerun_excel=False)
Runs excel fastsim through 26 vehicles and returns list of dictionaries containing scenario descriptions.
Arguments:
prev_res_path : path (str) to prevous results in pickle (*.p) file rerun_excel : (Boolean) if True, re-runs Excel FASTSim, which must be open
compare
def compare(res_python, res_excel, err_tol=0.001, verbose=True)
Finds common vehicle names in both excel and python (hypothetically all of them, but there may be discrepancies) and then compares fuel economy results. Arguments: results from run_python and run_excel Returns dict of comparsion results.
Arguments:
res_python : output of run_python res_excel : output of run_excel err_tol : (float) error tolerance, default=1e-3 verbose : Boolean if True, print progress
main
def main(err_tol=0.001,
prev_res_path=PREV_RES_PATH,
rerun_excel=False,
verbose=False)
Function for running both python and excel and then comparing
Arguments:
err_tol : (float) error tolerance, default=1e-3 prev_res_path : path (str) to prevous results in pickle (*.p) file rerun_excel : (Boolean) if True, re-runs Excel FASTSim, which must be open verbose : Boolean if True, print progress
TestExcel Objects
class TestExcel(unittest.TestCase)
test_vs_excel
def test_vs_excel()
Compares results against archived Excel results.
fastsim.tests.test_resources
Test getting resource lists via Rust API
TestListResources Objects
class TestListResources(unittest.TestCase)
test_list_resources_for_cycle
def test_list_resources_for_cycle()
check if list_resources works for RustCycle
test_list_resources_for_vehicles
def test_list_resources_for_vehicles()
check if list_resources works for RustVehicle
fastsim.tests.test_rust
Tests using the Rust versions of SimDrive, Cycle, and Vehicle
TestRust Objects
class TestRust(unittest.TestCase)
test_discrepancies
def test_discrepancies(veh_type="ALL", use_dict=True, cyc_name="udds")
Function for testing for Rust/Python discrepancies, both in the vehicle database CSV as well as the individual model files. Uses test_vehicle_for_discrepancies as backend.
Arguments:
veh_type
- type of vehicle to test for discrepancies can be "CONV", "HEV", "PHEV", "BEV", or "ALL"use_dict
- if True, use small cyc_dict to speed up test if false, default to UDDScyc_name
- name of cycle from database to use if use_dict == False
test_vehicle_for_discrepancies
def test_vehicle_for_discrepancies(vnum=1,
veh_filename=None,
cyc_dict=None,
cyc_name="udds")
Test for finding discrepancies between Rust and Python for single vehicle.
Arguments:
vnum
- vehicle database number, optional, default option without any argumentsveh_filename
- vehicle filename from vehdb folder, optionalcyc_dict
- cycle dictionary for custom cycle, optionalcyc_name
- cycle name from cycle database, optional
test_fueling_prediction_for_multiple_vehicle
def test_fueling_prediction_for_multiple_vehicle()
This test assures that Rust and Python agree on at least one example of all permutations of veh_pt_type and fc_eff_type.
fastsim.tests
Package containing tests for FASTSim.
run_functional_tests
def run_functional_tests()
Runs all functional tests.
fastsim.tests.test_cav_sweep
Test fastsim/demos/cav_sweep.py for regressions
fastsim.tests.test_following
Tests that check the drive cycle modification functionality.
TestFollowing Objects
class TestFollowing(unittest.TestCase)
test_that_we_have_a_gap_between_us_and_the_lead_vehicle
def test_that_we_have_a_gap_between_us_and_the_lead_vehicle()
A positive gap should exist between us and the lead vehicle
test_that_the_gap_changes_over_the_cycle
def test_that_the_gap_changes_over_the_cycle()
Ensure that our gap calculation is doing something
test_that_following_works_over_parameter_sweep
def test_that_following_works_over_parameter_sweep()
We're going to sweep through all of the parameters and see how it goes
test_that_we_can_use_the_idm
def test_that_we_can_use_the_idm()
Tests use of the IDM model for following
test_sweeping_idm_parameters
def test_sweeping_idm_parameters()
Tests use of the IDM model for following
test_distance_based_grade_on_following
def test_distance_based_grade_on_following()
Tests use of the IDM model for following
fastsim.tests.test_simdrive
Test suite for simdrive instantiation and usage.
TestSimDriveClassic Objects
class TestSimDriveClassic(unittest.TestCase)
Tests for fastsim.simdrive.SimDriveClassic methods
test_sim_drive_step
def test_sim_drive_step()
Verify that sim_drive_step produces an expected result.
test_sim_drive_walk
def test_sim_drive_walk()
Verify that sim_drive_walk produces an expected result.
fastsim.utils.utilities
Various optional utilities that may support some applications of FASTSim.
R_air
J/(kg*K)
get_rho_air
def get_rho_air(temperature_degC, elevation_m=180)
Returns air density [kg/m**3] for given elevation and temperature. Source: https://www.grc.nasa.gov/WWW/K-12/rocket/atmosmet.html
Arguments:
temperature_degC : ambient temperature [°C] elevation_m : elevation above sea level [m]. Default 180 m is for Chicago, IL
l__100km_to_mpg
def l__100km_to_mpg(l__100km)
Given fuel economy in L/100km, returns mpg.
mpg_to_l__100km
def mpg_to_l__100km(mpg)
Given fuel economy in mpg, returns L/100km.
rollav
def rollav(x, y, width=10)
Returns x-weighted backward-looking rolling average of y. Good for resampling data that needs to preserve cumulative information.
Arguments:
x : x data
y : y data (len(y) == len(x)
must be True)
width
- rolling average width
camel_to_snake
def camel_to_snake(name)
Given camelCase, returns snake_case.
set_log_level
def set_log_level(level: str | int) -> int
Sets logging level for both Python and Rust FASTSim. The default logging level is WARNING (30). https://docs.python.org/3/library/logging.html#logging-levels
Parameters
level: str
| int
Logging level to set. str
level name or int
logging level
=========== ================
Level Numeric value
=========== ================
CRITICAL 50
ERROR 40
WARNING 30
INFO 20
DEBUG 10
NOTSET 0
Returns
int
Previous log level
disable_logging
def disable_logging() -> int
Disable FASTSim logs from being shown by setting log level to CRITICAL+1 (51).
Returns
int
Previous log level
enable_logging
def enable_logging(level: Optional[int | str] = None)
Re-enable FASTSim logging, optionally to a specified log level, otherwise to the default WARNING (30) level.
Parameters
level: str
| int
, optional
Logging level to set. str
level name or int
logging level.
See utils.set_log_level()
docstring for more details on logging levels.
suppress_logging
@contextmanager
def suppress_logging()
Disable, then re-enable FASTSim logging using a context manager. The log level is returned to its previous value. Logging is re-enabled even if the nested code throws an error.
Example:
with fastsim.utils.suppress_logging():
... # do stuff with logging suppressed
get_containers_with_path
def get_containers_with_path(struct: Any, path: str | list) -> list
Get all attributes containers from nested struct using path
to attribute.
Parameters
struct: Any
Outermost struct where first name in path
is an attribute
path: str | list
Dot-separated path, e.g. "sd.veh.drag_coef"
or ["sd", "veh", "drag_coef"]
Returns
List[Any] Ordered list of containers, from outermost to innermost
get_attr_with_path
def get_attr_with_path(struct: Any, path: str | list) -> Any
Get attribute from nested struct using path
to attribute.
Parameters
struct: Any
Outermost struct where first name in path
is an attribute
path: str | list
Dot-separated path, e.g. "sd.veh.drag_coef"
or ["sd", "veh", "drag_coef"]
Returns
Any Requested attribute
set_attr_with_path
def set_attr_with_path(struct: Any, path: str | list, value: Any) -> Any
Set attribute on nested struct using path
to attribute.
Parameters
struct: Any
Outermost struct where first name in path
is an attribute
path: str | list
Dot-separated path, e.g. "sd.veh.drag_coef"
or ["sd", "veh", "drag_coef"]
value: Any
Returns
Any
struct
with nested value set
set_attrs_with_path
def set_attrs_with_path(struct: Any, paths_and_values: Dict[str, Any]) -> Any
Set multiple attributes on nested struct using path
: value
pairs.
Parameters
struct: Any
Outermost struct where first name in path
is an attribute
paths_and_values: Dict[str | list, Any]
Mapping of dot-separated path (e.g. sd.veh.drag_coef
or ["sd", "veh", "drag_coef"]
)
to values (e.g. 0.32
)
Returns
Any
struct
with nested values set
calculate_tire_radius
def calculate_tire_radius(tire_code: str, units: str = "m")
Calculate tire radius from ISO tire code, with variable units
Unit options: "m", "cm", "mm", "ft", "in". Default is "m".
Examples:
fastsim.utils.calculate_tire_radius("P205/60R16") 0.3262 fastsim.utils.calculate_tire_radius("225/70Rx19.5G", units="in") 15.950787401574804
show_plots
def show_plots() -> bool
Returns true if plots should be displayed
do_tests
def do_tests() -> bool
Returns true if plots should be displayed
copy_demo_files
def copy_demo_files(path_for_copies: Path = Path("demos"))
Copies demo files from demos folder into specified local directory
Arguments
- -
path_for_copies
: path to copy files into (relative or absolute in)
Warning
Running this function will overwrite existing files with the same name in the specified directory, so make sure any files with changes you'd like to keep are renamed.
fastsim.utils.vehicle_import_preproc
Module for pre-processing data from fueleconomy.gov and EPA vehicle testing that is used for "vehicle import" functionality. Vehicle import allows FASTSim to import vehicles by specifying make, model, and year. See fastsim.demos.vehicle_import_demo for usage.
In order to run this pre-processing script, the data from the sources below should be placed in the "input_dir" (see the run function).
fueleconomy.gov data: https://www.fueleconomy.gov/feg/download.shtml
- vehicles.csv
- emissions.csv
EPA Test data: https://www.epa.gov/compliance-and-fuel-economy-data/data-cars-used-testing-fuel-economy
- the data for emissions by year; e.g., 20tstcar-2021-03-02.xlsx
- note: there are multiple formats in use
process_csv
def process_csv(path: Path, fn)
write_csvs_for_each_year
def write_csvs_for_each_year(output_data_dir, basename, rows_by_year, header)
sort_fueleconomygov_data_by_year
def sort_fueleconomygov_data_by_year(input_data_dir: Path,
output_data_dir: Path)
Opens up the vehicles.csv and emissions.csv and breaks them up to be by year and saves them again.
xlsx_to_csv
def xlsx_to_csv(xlsx_path, csv_path)
process_epa_test_data
def process_epa_test_data(input_dir, output_dir)
create_zip_archives_by_year
def create_zip_archives_by_year(files_dir, zip_dir)
Takes files in the files_dir that start with \d\d\d\d-*.csv and adds them to a \d\d\d\d.zip in the zip_dir
fastsim.utils
fastsim.auxiliaries
Auxiliary functions that require fastsim and provide faster access FASTSim vehicle properties.
R_air
J/(kg*K)
abc_to_drag_coeffs
def abc_to_drag_coeffs(veh: Vehicle,
a_lbf: float,
b_lbf__mph: float,
c_lbf__mph2: float,
custom_rho: bool = False,
custom_rho_temp_degC: float = 20.,
custom_rho_elevation_m: float = 180.,
simdrive_optimize: bool = True,
show_plots: bool = False,
use_rust=True) -> Tuple[float, float]
For a given vehicle and target A, B, and C coefficients; calculate and return drag and rolling resistance coefficients.
Arguments:
veh
- vehicle.Vehicle with all parameters correct except for drag and rolling resistance coefficients a_lbf, b_lbf__mph, c_lbf__mph2: coastdown coefficients for road load [lbf] vs speed [mph]custom_rho
- if True, usefastsim.utilities.get_rho_air()
to calculate the current ambient densitycustom_rho_temp_degC
- ambient temperature [degree C] forget_rho_air()
; will only be used whencustom_rho
is Truecustom_rho_elevation_m
- location elevation [degree C] forget_rho_air()
; will only be used whencustom_rho
is True; default value is elevation of Chicago, ILsimdrive_optimize
- if True, useSimDrive
to optimize the drag and rolling resistance; otherwise, directly use target A, B, C to calculate the resultsshow_plots
- if True, plots are shownuse_rust
- if True, use rust implementation of drag coefficient calculation.
drag_coeffs_to_abc
def drag_coeffs_to_abc(veh,
custom_rho: bool = False,
custom_rho_temp_degC: float = 20.,
custom_rho_elevation_m: float = 180.,
fit_with_curve: bool = False,
show_plots: bool = False) -> Tuple[float, float, float]
For a given vehicle mass, frontal area, dragCoef, and wheelRrCoef, calculate and return ABCs.
Arguments:
veh
- vehicle.Vehicle with correct drag and rolling resistancecustom_rho
- if True, usefastsim.utilities.get_rho_air()
to calculate the current ambient densitycustom_rho_temp_degC
- ambient temperature [degree C] forget_rho_air()
; will only be used whencustom_rho
is Truecustom_rho_elevation_m
- location elevation [degree C] forget_rho_air()
; will only be used whencustom_rho
is True; default value is elevation of Chicago, ILfit_with_curve
- if True, usescipy.curve_fit
to get A, B, Cs; otherwise, directly calculate A, B, Cs from given drag and rolling resistanceshow_plots
- if True, plots are shown
Returns:
a_lbf, b_lbf__mph, c_lbf__mph2: coastdown coefficients for road load [lbf] vs speed [mph]
fastsim.simdrive
Module containing classes and methods for simulating vehicle drive cycle.
SimDriveParams Objects
class SimDriveParams(object)
Class containing attributes used for configuring sim_drive. Usually the defaults are ok, and there will be no need to use this.
See comments in code for descriptions of various parameters that affect simulation behavior. If, for example, you want to suppress warning messages, use the following pastable code EXAMPLE:
import logging logging.getLogger("fastsim").setLevel(logging.DEBUG)
from_dict
@classmethod
def from_dict(cls, sdp_dict)
Create from a dictionary
__init__
def __init__()
Default values that affect simulation behavior. Can be modified after instantiation.
to_rust
def to_rust()
Change to the Rust version
reset_orphaned
def reset_orphaned()
Dummy method for flexibility between Rust/Python version interfaces
copy_sim_params
def copy_sim_params(sdp: SimDriveParams, return_type: str = None)
Returns copy of SimDriveParams.
Arguments:
sdp
- instantianed SimDriveParams or RustSimDriveParams return_type:default
- infer from type of sdp'dict'
- dict'python'
- SimDriveParams'rust'
- RustSimDriveParamsdeep
- if True, uses deepcopy on everything
sim_params_equal
def sim_params_equal(a: SimDriveParams, b: SimDriveParams) -> bool
Returns True if objects are structurally equal (i.e., equal by value), else false.
Arguments:
a
- instantiated SimDriveParams objectb
- instantiated SimDriveParams object
SimDrive Objects
class SimDrive(object)
Class containing methods for running FASTSim vehicle fuel economy simulations. This class is not compiled and will run slower for large batch runs.
Arguments:
cyc
- cycle.Cycle instanceveh
- vehicle.Vehicle instance
__init__
def __init__(cyc: cycle.Cycle, veh: vehicle.Vehicle)
Initalizes arrays, given vehicle.Vehicle() and cycle.Cycle() as arguments. sim_params is needed only if non-default behavior is desired.
gap_to_lead_vehicle_m
@property
def gap_to_lead_vehicle_m()
Provides the gap-with lead vehicle from start to finish
sim_drive
def sim_drive(init_soc: Optional[float] = None,
aux_in_kw_override: Optional[np.ndarray] = None)
Initialize and run sim_drive_walk as appropriate for vehicle attribute vehPtType. Arguments
init_soc: initial SOC for electrified vehicles.
aux_in_kw: aux_in_kw override. Array of same length as cyc.time_s.
Default of None causes veh.aux_kw to be used.
init_for_step
def init_for_step(init_soc: float,
aux_in_kw_override: Optional[np.ndarray] = None)
This is a specialty method which should be called prior to using sim_drive_step in a loop.
Arguments
init_soc: initial battery state-of-charge (SOC) for electrified vehicles
aux_in_kw: aux_in_kw override. Array of same length as cyc.time_s.
Default of None causes veh.aux_kw to be used.
sim_drive_walk
def sim_drive_walk(init_soc: float,
aux_in_kw_override: Optional[np.ndarray] = None)
Receives second-by-second cycle information, vehicle properties, and an initial state of charge and runs sim_drive_step to perform a backward facing powertrain simulation. Method 'sim_drive' runs this iteratively to achieve correct SOC initial and final conditions, as needed.
Arguments
init_soc: initial battery state-of-charge (SOC) for electrified vehicles
aux_in_kw: aux_in_kw override. Array of same length as cyc.time_s.
Default of None causes veh.aux_kw to be used.
activate_eco_cruise
def activate_eco_cruise(by_microtrip: bool = False,
extend_fraction: float = 0.1,
blend_factor: float = 0.0,
min_target_speed_m_per_s: float = 8.0)
Sets the intelligent driver model parameters for an eco-cruise driving trajectory. This is a convenience method instead of setting the sim_params.idm* parameters yourself.
- by_microtrip: bool, if True, target speed is set by microtrip, else by cycle
- extend_fraction: float, the fraction of time to extend the cycle to allow for catch-up of the following vehicle
- blend_factor: float, a value between 0 and 1; only used of by_microtrip is True, blends between microtrip average speed and microtrip average speed when moving. Must be between 0 and 1 inclusive
sim_drive_step
def sim_drive_step()
Step through 1 time step. TODO: create self.set_speed_for_target_gap(self.i): TODO: consider implementing for battery SOC dependence
solve_step
def solve_step(i)
Perform all the calculations to solve 1 time step.
set_misc_calcs
def set_misc_calcs(i)
Sets misc. calculations at time step 'i'
Arguments:
i
- index of time step
set_comp_lims
def set_comp_lims(i)
Sets component limits for time step 'i' Arguments
i: index of time step init_soc: initial SOC for electrified vehicles
set_power_calcs
def set_power_calcs(i)
Calculate power requirements to meet cycle and determine if
cycle can be met.
Arguments
i: index of time step
set_ach_speed
def set_ach_speed(i)
Calculate actual speed achieved if vehicle hardware cannot achieve trace speed. Arguments
i: index of time step
set_hybrid_cont_calcs
def set_hybrid_cont_calcs(i)
Hybrid control calculations. Arguments
i: index of time step
set_fc_forced_state
def set_fc_forced_state(i)
Calculate control variables related to engine on/off state Arguments
i: index of time step
set_hybrid_cont_decisions
def set_hybrid_cont_decisions(i)
Hybrid control decisions. Arguments
i: index of time step
set_fc_power
def set_fc_power(i)
Sets fcKwOutAch and fcKwInAch. Arguments
i: index of time step
set_post_scalars
def set_post_scalars()
Sets scalar variables that can be calculated after a cycle is run. This includes mpgge, various energy metrics, and others
to_rust
def to_rust()
Create a rust version of SimDrive
copy_sim_drive
def copy_sim_drive(sd: SimDrive,
return_type: str = None,
deep: bool = True) -> SimDrive
Returns copy of SimDriveClassic or SimDriveJit as SimDriveClassic.
Arguments:
sd
- instantiated SimDriveClassic or SimDriveJit return_type:default
- infer from type of sd'python'
- Cycle'legacy'
- LegacyCycle'rust'
- RustCycledeep
- if True, uses deepcopy on everything
sim_drive_equal
def sim_drive_equal(a: SimDrive, b: SimDrive) -> bool
run_simdrive_for_accel_test
def run_simdrive_for_accel_test(sd: SimDrive)
Initialize and run sim_drive_walk as appropriate for vehicle attribute vehPtType.
SimDrivePost Objects
class SimDrivePost(object)
Class for post-processing of SimDrive instance. Requires already-run SimDrive instance.
__init__
def __init__(sim_drive: SimDrive)
Arguments:
sim_drive
- solved sim_drive object
get_diagnostics
def get_diagnostics()
This method is to be run after runing sim_drive if diagnostic variables are needed. Diagnostic variables are returned in a dict. Diagnostic variables include:
- final integrated value of all positive powers
- final integrated value of all negative powers
- total distance traveled
- miles per gallon gasoline equivalent (mpgge)
set_battery_wear
def set_battery_wear()
Battery wear calcs
SimDriveJit
def SimDriveJit(cyc_jit, veh_jit)
deprecated
estimate_soc_corrected_fuel_kJ
def estimate_soc_corrected_fuel_kJ(sd: SimDrive) -> float
- sd: SimDriveClassic, the simdrive instance after simulation RETURN: number, the kJ of fuel corrected for SOC imbalance
fastsim.vehicle_base
Boiler plate stuff needed for vehicle.py
fastsim.inspect_utils
Utilities to assist with object introspection.
isprop
def isprop(attr) -> bool
Checks if instance attribute is a property.
isfunc
def isfunc(attr) -> bool
Checks if instance attribute is method.
get_attrs
def get_attrs(instance)
Given an instantiated object, returns attributes that are not:
-- callable
-- special (i.e. start with __
)
-- properties
fastsim.parameters
Global constants representing unit conversions that shourd never change, physical properties that should rarely change, and vehicle model parameters that can be modified by advanced users.
PhysicalProperties Objects
class PhysicalProperties(object)
Container class for physical constants that could change under certain special circumstances (e.g. high altitude or extreme weather)
copy_physical_properties
def copy_physical_properties(p: PhysicalProperties,
return_type: str = None,
deep: bool = True)
Returns copy of PhysicalProperties.
Arguments:
p
- instantianed PhysicalProperties or RustPhysicalProperties return_type:default
- infer from type of p'dict'
- dict'python'
- PhysicalProperties'legacy'
- LegacyPhysicalProperties -- NOT IMPLEMENTED YET; is it needed?'rust'
- RustPhysicalPropertiesdeep
- if True, uses deepcopy on everything
physical_properties_equal
def physical_properties_equal(a: PhysicalProperties,
b: PhysicalProperties) -> bool
Return True if the physical properties are equal by value
fc_perc_out_array
hardcoded ***
chg_eff
charger efficiency for PEVs, this should probably not be hard coded long term
fastsim.demos.vehicle_import_demo
Vehicle Import Demonstration This module demonstrates the vehicle import API
other_inputs
None -> calculate from EPA data
fastsim.demos.cav_sweep
ABSOLUTE_EXTENDED_TIME_S
180.0
make_debug_plot
def make_debug_plot(sd: fastsim.simdrive.SimDrive,
save_file: Optional[str] = None,
do_show: bool = False)
load_cycle
def load_cycle(cyc_name: str, use_rust: bool = False) -> fastsim.cycle.Cycle
Load the given cycle and return
main
def main(cycle_name=None,
powertrain=None,
do_show=None,
use_rust=False,
verbose=True,
save_dir=None,
maneuver=None)
fastsim.demos.fusion_thermal_cal_post
save_path
seems to be best
fastsim.demos.demo_eu_vehicle_wltp
fastsim.demos.accel_demo
create_accel_cyc
def create_accel_cyc(length_in_seconds=300, spd_mph=89.48, grade=0.0, hz=10)
Create a synthetic Drive Cycle for acceleration targeting. Defaults to a 15 second acceleration cycle. Should be adjusted based on target acceleration time and initial vehicle acceleration time, so that time isn't wasted on cycles that are needlessly long.
spd_mph @ 89.48 FASTSim XL version mph default speed for acceleration cycles grade @ 0 and hz @ 10 also matches XL version settings
main
def main()
Arguments:
fastsim.demos.fusion_thermal_cal
lhv_fuel_btu_per_lbm
from "2012FordFusionV6Overview V5.pdf"
fastsim.demos.calibration_demo
Script for demonstrating how to calibrate a vehicle model. See FASTSim Calibration/Validation documentation for more info on how to use this.
lhv_fuel_btu_per_lbm
from "2012FordFusionV6Overview V5.pdf"
load_data
def load_data() -> Dict[str, pd.DataFrame]
Loads dyno test data from csv files 61811011, 61811012, 61811013, and 61811014 downloaded from https://www.anl.gov/taps/d3-2018-toyota-camry-xle
Returns:
Dict[str, pd.DataFrame]: dictionary of dataframes
get_cal_and_val_objs
def get_cal_and_val_objs(dfs: Dict[str, pd.DataFrame] = load_data()) -> Tuple[
fsim.cal.ModelObjectives, fsim.cal.ModelObjectives, List[Tuple[
float, float]]]
Returns objects to be used by PyMOO optimizer
Arguments:
dfs
Dict[str, pd.DataFrame] - output ofload_data
Returns:
Tuple[fsim.cal.ModelObjectives, fsim.cal.ModelObjectives, List[Tuple[float, float]]]: description
fastsim.demos.stop_start_demo
fastsim.demos.wltc_calibration
WILLANS_FACTOR
gCO2/MJ
E10_HEAT_VALUE
kWh/L
fastsim.demos.timing_demo
fastsim.demos.demo
v2
should not have derived params
data_path
path to drive cycles
veh
load vehicle using name
fastsim.demos.time_dilation_demo
fastsim.demos.test_demos
fastsim.demos.cav_demo
fastsim.demos.demo_abc_drag_coef_conv
fastsim.demos.2017_Ford_F150_thermal_val
lhv_fuel_btu_per_lbm
from "2012FordFusionV6Overview V5.pdf"
fastsim.demos
fastsim.demos.fusion_thermal_demo
Rust Documentation
How to compile/test Rust code
cargo build
cargo build
will not compile when run in /rust
due to problems compiling /rust/fastsim-py
.
cargo build
should compile when run in the /rust/fastsim-core
.
cargo test
cargo test
should compile when run in /rust because there are no tests in /rust/fastsim-py
.
build_and_test.sh
Running sh build_and_test.sh
from the root fastsim directory compile/tests the Rust code, and tests the Python code. It should compile without errors.
Calibration and Validation of Vehicle Models
FASTSim powertrain models can have varying levels of calibration and resolution based on available calibration and validation data. In the simplest (US) cases, the only available validation data for a powertrain model is the EPA "window sticker" energy consumption rates. However, there are also situations in which detailed dynamometer or on-road data is available for a particular vehicle, enabling much more detailed model calibration. This documentation is meant to summarize these various calibration levels and the tools available to help with more detailed calibration.
Calibration/Validation Levels
Level | Calibration | Validation |
---|---|---|
0 | Vehicle is parameterized without any fitting to performance data. This is called parameterization, not calibration. | Could be none or could be validated against aggregate energy consumption data like EPA window sticker values. |
1 | Vehicle parameters are adjusted so that model results reasonably match test data for aggregate, cycle-level data (e.g. fuel usage, net SOC change). | Model results reasonably match at least some aggregate, cycle-level test data not used in any calibration process. |
2 | Vehicle parameters are adjusted so that model results reasonably match test data for time-resolved test data (e.g. instantaneous fuel usage, instantaneous cumulative fuel usage, instantaneous SOC). | Model results reasonably match at least some time-resolved test data not used in any calibration process. |
3 | Some amount of component-level thermal modeling is included and vehicle parameters are adjusted so that model results reasonably match test data for time-resolved test data (e.g. instantaneous fuel usage, instantaneous cumulative fuel usage, instantaneous SOC). | Model results reasonably match time-resolved test data not used in any calibration process that covers various temperatures and/vehcile transient thermal states. |
Examples of calibration levels 0, 2, and 3 from the FASTSim Validation Report:
Calibration Level 0 (Parameterization) Guidelines
As noted in the table above, parameterization of a new FASTSim powertrain model is performed when little or no ground truth performance data is available for a specific vehicle. One example of this is if EPA window-sticker fuel economy is the only available performance data. In this situation, it is recommended to parameterize a FASTSim powertrain model using the most reliable vehicle parameters from available information (e.g., specification websites). This helps to avoid overfitting and relies on the robustness of the FASTSim approach to capture the most important powertrain dynamics and simulate energy consumption.
- Create a new vehicle file, either from a template or an existing vehicle model (ideally of the same powertrain type)
- Enter vehicle parameters from various specification sources (note: it is recommended to document the source of specifications that are used to determine each parameter)
veh_pt_type
andfc_eff_type
are important high level descriptors that define the powertrain technologyveh_pt_type
: Vehicle powertrain type- Parameter values:
Conv
: conventional (ICE, gasoline or diesel) vehicleHEV
: hybrid electric vehiclePHEV
: plug-in hybrid electric vehicleBEV
: battery electric vehicle
- Parameter values:
fc_eff_type
: Fuel converter efficiency type- This parameter is used to retrieve the default
fc_eff_map
for a particular engine type if a custom map is not provided - Unnecessary and not used for vehicles without a fuel converter (e.g. BEVs)
- Parameter values:
SI
: spark ignitionAtkinson
: Atkinson cycle (typical for hybrids)Diesel
: diesel (compression ignition)H2FC
: hydrogen fuel cell (use withveh_pt_type
set toHEV
)HD_Diesel
: heavy-duty diesel
- This parameter is used to retrieve the default
veh_override_kg
is the simplest way to specify total vehicle mass- If not provided, the various component mass parameters will be used to calculate total vehicle mass
- If
veh_override_kg
is provided, component mass parameters are unnecessary and not used
drag_coef
andwheel_rr_coef
can be calculated from dynamometer road load equation coefficients (ABCs) for vehicles tested by the US EPA usingfastsim.auxiliaries.abc_to_drag_coeffs
. Test data, including the road load coefficients from coast-down testing, for cars tested by the US EPA is available here.drag_coef
is sometimes provided on specification websites and reasonable values informed by engineering judgement forwheel_rr_coef
can be used , but when possible the ABCs andfastsim.auxiliaries.abc_to_drag_coeffs
method should be used instead
wheel_radius_m
is often not explicitly available for a vehicle, but a tire code can be supplied tofastsim.utils.calculate_tire_radius
to calculate a radius- Note: For hybrids, 'total system power' is often provided (e.g., combined ICE and electric motor powers). This should not be used for either
fc_max_kw
ormc_max_kw
, peak engine-only power should be used forfc_max_kw
and peak electric motor-only power formc_max_kw
.
Calibration Level 2 Guidelines
- Copy calibration_demo.py to your project directory and modify as needed.
- By default, this script selects the model that minimizes the euclidean error across
all objectives, which may not be the way that you want to select your final design.
By looking at the plots that get generated in
save_path
, you can use both the time series and parallel coordinates plots to down select an appropriate design. - Because PyMOO is a multi-objective optimizer that finds a multi-dimensional Pareto surface, it will not necessarily return a single best result -- rather, it will produce a pareto-optimal set of results, and you must down select. Often, the design with minimal euclidean error will be the best design, but it's good to pick a handful of designs from the pareto set and check how they behave in the time-resolved plots that can be optionally generated by the optimization script.
- Run
python calibration_demo.py --help
to see details about how to run calibration and validation. Greater population size typically results in faster convergence at the expense of increased run time for each generation. There's no benefit in having a number of processes larger than the population size.xtol
andftol
(see CLI help) can be used to adjust when the minimization is considered converged. If the optimization is terminating whenn_max_gen
is hit, then that means it has not converged, and you may want to increasen_max_gen
. - Usually, start out with an existing vehicle model that is reasonably close to the new vehicle, and make sure to provide as many explicit parameters as possible. In some cases, a reasonable engineering judgment is appropriate.
- Resample data to 1 Hz. This is a good idea because higher frequency data will cause
fastsim to run more slowly. This can be done with
fastsim.resample.resample
. Be sure to specifyrate_vars
(e.g. fuel power flow rate [W]), which will be time averaged over the previous time step in the new frequency. - Identify test data signals and corresponding fastsim signals that need to match.
These pairs of signals will be used to construct minimization objectives. See
where
obj_names
is defined incalibration_demo.py
for an example. - See where
cycs[key]
gets assigned to see an example of constructing a Cycle from a dataframe. - Partition out calibration/validation data by specifying a tuple of regex patterns
that correspond to cycle names. See where
cal_cyc_patterns
is defined for an example. Typically, it's good to reserve about 25-33% of your data for validation. - To set parameters and corresponding ranges that the optimizer is allowed to use in
getting the model to match test data, see where
params_and_bounds
is defined below.
How to Update This Markdown Book
Setup
If not already done, install mdbook
Serving locally
Run the following in the repository root directory:
- If any python files were modified,
- Install pipx
- Install pydoc-markdown
- run
pydoc-markdown -I python/ --render-toc > docs/src/python-doc.md
. Do not modify this file manually.
- Run
mdbook serve --open docs/
Publishing
- Update
book.toml
or files indocs/src/
- Make sure the docs look good locally by running the steps in Serving Locally.
- Commit files and push to
fastsim-2
branch
After that, a GitHub action will build the book and publish it.
Release Notes
2.1.2 -- SerdeAPI revamp with many new functions, various new vehicles, calibration demo, better error propagation, demo testing
2.1.1 -- license changed to Apache 2.0, default cycle grade and road type to zero if not provided, defaults to regenerative braking parameters, optional documentation fields now generated in Rust
2.1.0 -- release and installation improvements, RustVehicle init cleanup, calibration improvements
2.0.11 - 2.0.22 -- PyPI fixes. Also, Rust version is now >100x faster than Python version.
2.0.10 -- logging fixes, proc macro reorganization, some CAVs performance fixes
2.0.9 -- support for mac ARM/RISC architecture
2.0.8 -- performance improvements
2.0.6 -- dist_v2_m
fixes and preliminary CAV functionality
2.0.5 -- added to_rust
method for cycle
2.0.4 -- exposed veh.set_veh_mass
2.0.3 -- exposed veh.__post_init__
2.0.2 -- provisioned for non-default vehdb path
2.0.1 -- bug fix
2.0.0 -- All second-by-second calculations are now implemented in both rust and python. Rust provides a ~30x speedup
1.3.1 -- fastsim.simdrive.copy_sim_drive
function can deepcopy jit to non-jit (and back) for pickling
1.2.6 -- time dilation bug fix for zero speed
1.2.4 -- bug fix changing ==
to =
1.2.3 -- veh_file
can be passed as standalone argument. fcEffType
can be anything if fcEffMap
is provided, but typing is otherwise enforced.
1.2.2 -- added checks for some conflicting vehicle parameters. Vehicle parameters fcEffType
and vehPtType
must now be str type.
1.2.1 -- improved time dilation and added test for it
1.1.7 -- get_numba_veh() and get_numba_cyc() can now be called from already jitted objects
1.1.6 -- another bug fix for numba compatibility with corresponding unit test
1.1.5 -- bug fix for numba compatibility of fcPeakEffOverride and mcPeakEffOverride
1.1.4 -- nan bug fix for fcPeakEffOverride and mcPeakEffOverride
1.1.3 -- provisioned for optional load time motor and engine peak overrides
1.1.2 -- made vehicle loading more more robust
1.1.1 -- made vehicle loading more robust
1.1.0 -- separated jitclasses into own module, made vehicle engine and motor efficiency setting more robust
1.0.4 -- bug fix with custom engine curve
1.0.3 -- bug fixes, faster testing
1.0.2 -- forced type np.float64 on vehicle mass attributes
1.0.1 -- Added vehYear
attribute to vehicle and other minor changes.
1.0.0 -- Implemented unittest package. Fixed energy audit calculations to be based on achieved speed. Updated this file. Improved documentation. Vehicle can be instantiated as dict.
0.1.5 -- Updated to be compatible with ADOPT
0.1.4 -- Bug fix: mcEffMap
is now robust to having zero as first element
0.1.3 -- Bug fix: fastsim.vehicle.Vehicle
method set_init_calcs
no longer overrides fcEffMap
.
0.1.2 -- Fixes os-dependency of xlwings by not running stuff that needs xlwings. Improvements in functional test. Refinment utomated typying of jitclass objects.
0.1.1 -- Now includes label fuel economy and/or battery kW-hr/mi values that match excel and test for benchmarking against Excel values and CPU time.