Skip to content

Commit

Permalink
Merge branch 'fastsim-2' into feature/full-feature-for-dependency-red…
Browse files Browse the repository at this point in the history
…uction

# Conflicts:
#	rust/fastsim-core/src/vehicle_utils.rs
#	rust/fastsim-py/src/lib.rs
  • Loading branch information
kylecarow committed Mar 6, 2024
2 parents 5bb62a8 + 50f4975 commit 7d6ea86
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 26 deletions.
29 changes: 29 additions & 0 deletions docs/src/cal_and_val.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,35 @@ Examples of calibration levels 0, 2, and 3 from the [FASTSim Validation Report](

![image](https://github.com/NREL/fastsim/assets/4818940/8483661f-dee4-4d59-9d69-e6d54dae0100)

## 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` and `fc_eff_type` are important high level descriptors that define the powertrain technology
- `veh_pt_type`: Vehicle powertrain type
- Parameter values:
- `Conv`: conventional (ICE, gasoline or diesel) vehicle
- `HEV`: hybrid electric vehicle
- `PHEV`: plug-in hybrid electric vehicle
- `BEV`: battery electric vehicle
- `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 ignition
- `Atkinson`: Atkinson cycle (typical for hybrids)
- `Diesel`: diesel (compression ignition)
- `H2FC`: hydrogen fuel cell (use with `veh_pt_type` set to `HEV`)
- `HD_Diesel`: heavy-duty diesel
- `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` and `wheel_rr_coef` can be calculated from dynamometer road load equation coefficients (ABCs) for vehicles tested by the US EPA using `fastsim.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](https://www.epa.gov/compliance-and-fuel-economy-data/data-cars-used-testing-fuel-economy).
- `drag_coef` is sometimes provided on specification websites and reasonable values informed by engineering judgement for `wheel_rr_coef` can be used , but when possible the ABCs and `fastsim.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 to `fastsim.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` or `mc_max_kw`, peak engine-only power should be used for `fc_max_kw` and peak electric motor-only power for `mc_max_kw`.

## Calibration Level 2 Guidelines
- Copy
[calibration_demo.py](https://github.com/NREL/fastsim/blob/fastsim-2/python/fastsim/demos/calibration_demo.py)
Expand Down
29 changes: 29 additions & 0 deletions rust/fastsim-core/src/vehicle_import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,35 @@ pub fn get_options_for_year_make_model(
.unwrap_or_else(|| vec![]))
}

#[cfg_attr(feature = "pyo3", pyfunction)]
pub fn get_vehicle_data_for_id(
id: i32,
year: &str,
cache_url: Option<String>,
data_dir: Option<String>,
) -> anyhow::Result<VehicleDataFE> {
// prep the cache for year
let y: u32 = year.trim().parse()?;
let ys: HashSet<u32> = {
let mut h = HashSet::new();
h.insert(y);
h
};
let ddpath = data_dir.and_then(|dd| Some(PathBuf::from(dd))).unwrap_or(create_project_subdir("fe_label_data")?);
let cache_url = cache_url.unwrap_or_else(get_default_cache_url);
populate_cache_for_given_years_if_needed(ddpath.as_path(), &ys, &cache_url).with_context(|| format!("Unable to load or download cache data from {cache_url}"))?;
let emissions_data = load_emissions_data_for_given_years(ddpath.as_path(), &ys)?;
let fegov_data_by_year =
load_fegov_data_for_given_years(ddpath.as_path(), &emissions_data, &ys)?;
let fegov_db = fegov_data_by_year.get(&y).context(format!("Could not get fueleconomy.gov data from year {y}"))?;
for item in fegov_db.iter() {
if item.id == id {
return Ok(item.clone())
}
}
bail!("Could not find ID in data {id}");
}

fn derive_transmission_specs(fegov: &VehicleDataFE) -> (u32, String) {
let num_gears_fe_gov: u32;
let transmission_fe_gov: String;
Expand Down
54 changes: 28 additions & 26 deletions rust/fastsim-py/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,38 +31,40 @@ fn fastsimrust(py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<thermal::ThermalState>()?;
m.add_class::<vehicle_thermal::HVACModel>()?;
m.add_class::<vehicle_import::OtherVehicleInputs>()?;
#[cfg(feature = "simdrivelabel")]
m.add_class::<simdrivelabel::LabelFe>()?;
#[cfg(feature = "simdrivelabel")]
m.add_class::<simdrivelabel::LabelFePHEV>()?;
#[cfg(feature = "simdrivelabel")]
m.add_class::<simdrivelabel::PHEVCycleCalc>()?;
m.add_class::<simdrive::simdrive_iter::SimDriveVec>()?;

cycle::register(py, m)?;

// Features
#[cfg(feature = "default")]
m.add_function(wrap_pyfunction!(vehicle_utils::abc_to_drag_coeffs, m)?)?;
#[cfg(feature = "simdrivelabel")]
m.add_function(wrap_pyfunction!(make_accel_trace_py, m)?)?;
#[cfg(feature = "simdrivelabel")]
m.add_function(wrap_pyfunction!(get_net_accel_py, m)?)?;
#[cfg(feature = "simdrivelabel")]
m.add_function(wrap_pyfunction!(get_label_fe_py, m)?)?;
#[cfg(feature = "simdrivelabel")]
m.add_function(wrap_pyfunction!(get_label_fe_phev_py, m)?)?;
#[cfg(feature = "vehicle-import")]
m.add_function(wrap_pyfunction!(
vehicle_import::get_options_for_year_make_model,
m
)?)?;
{
m.add_class::<simdrivelabel::LabelFe>()?;
m.add_class::<simdrivelabel::LabelFePHEV>()?;
m.add_class::<simdrivelabel::PHEVCycleCalc>()?;
m.add_class::<simdrive::simdrive_iter::SimDriveVec>()?;
m.add_function(wrap_pyfunction!(make_accel_trace_py, m)?)?;
m.add_function(wrap_pyfunction!(get_net_accel_py, m)?)?;
m.add_function(wrap_pyfunction!(get_label_fe_py, m)?)?;
m.add_function(wrap_pyfunction!(get_label_fe_phev_py, m)?)?;
}
#[cfg(feature = "vehicle-import")]
m.add_function(wrap_pyfunction!(
vehicle_import::vehicle_import_by_id_and_year,
m
)?)?;
#[cfg(feature = "vehicle-import")]
m.add_function(wrap_pyfunction!(vehicle_import::import_all_vehicles, m)?)?;

{
m.add_function(wrap_pyfunction!(
vehicle_import::get_options_for_year_make_model,
m
)?)?;
m.add_function(wrap_pyfunction!(
vehicle_import::get_vehicle_data_for_id,
m
)?)?;
m.add_function(wrap_pyfunction!(
vehicle_import::vehicle_import_by_id_and_year,
m
)?)?;
m.add_function(wrap_pyfunction!(vehicle_import::import_all_vehicles, m)?)?;
}
// Function to check what features are enabled from Python
m.add_function(wrap_pyfunction!(enabled_features, m)?)?;

Ok(())
Expand Down

0 comments on commit 7d6ea86

Please sign in to comment.