Skip to content

Commit

Permalink
updating branch to keep up to date with main fastsim-2 branch
Browse files Browse the repository at this point in the history
  • Loading branch information
robinsteuteville committed Jul 26, 2024
2 parents 24f69cb + f363a6c commit 09ca705
Show file tree
Hide file tree
Showing 15 changed files with 294 additions and 199 deletions.
1 change: 1 addition & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ jobs:
test:
runs-on: ubuntu-latest


strategy:
fail-fast: true
matrix:
Expand Down
52 changes: 6 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,12 @@ Developers might want to install the code in place so that FASTSim files can be

## Usage

To see and run examples, navigate to `./python/fastsim/demos` and run the various *demo.py files to see fastsim use cases. There are other examples in fastsim/tests.
To see and run examples, download the FASTSim demo files using the following code (with your Python environment activated and FASTSim installed):
```python
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

Expand Down Expand Up @@ -105,51 +110,6 @@ ach = achieved value
in = component input
out = component output

## Known Issues

Rust versions of classes have limited Language Server Protocol integration, and we are actively working on fixing this.

## 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.

## Contributors

Chad Baker -- <[email protected]>
Expand Down
2 changes: 2 additions & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@
- [Documentation](./fastsim-doc.md)
- [Python](./python-doc.md)
- [Rust](./rust-doc.md)
- [Developers](./developers.md)
- [Calibration/Validation](./cal_and_val.md)
- [How to Update This Book](./how-to-update.md)
- [Release Notes](./release-notes.md)
11 changes: 11 additions & 0 deletions docs/src/developers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# 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.
4 changes: 3 additions & 1 deletion docs/src/fastsim-doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@

## [Python](./python-doc.md)

## [Rust](./rust-doc.md)
## [Rust](./rust-doc.md)

## [Developers](./developers.md)
6 changes: 3 additions & 3 deletions docs/src/how-to-update.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Run the following in the repository root directory:

## Publishing
1. Update `book.toml` or files in `docs/src/`
1. Make sure the docs look good locally by running the steps in [Serving Locally](#serving-locally)
1. Commit files and push to `main` branch
1. Make sure the docs look good locally by running the steps in [Serving Locally](#serving-locally).
1. Commit files and push to `fastsim-2` branch

After that, a GitHub action will build the book and publish it.
After that, a GitHub action will build the book and publish it.
41 changes: 41 additions & 0 deletions docs/src/release-notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
## 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.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ classifiers = [
dependencies = [
"pandas>=1",
"matplotlib>=3.3",
"numpy>=1.18",
"numpy==1.24",
"scipy",
"seaborn>=0.10",
"typing_extensions",
Expand Down
13 changes: 9 additions & 4 deletions python/fastsim/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import sys
import logging
import traceback
from typing import Dict

from fastsim import parameters as params
from fastsim import utils
Expand All @@ -21,11 +22,15 @@ def package_root() -> Path:
return Path(__file__).parent


DEFAULT_LOGGING_CONFIG = dict(
format = "%(asctime)s.%(msecs)03d | %(filename)s:%(lineno)s | %(levelname)s: %(message)s",
datefmt = "%Y-%m-%d %H:%M:%S",
)



# Set up logging
logging.basicConfig(
format="%(asctime)s.%(msecs)03d | %(filename)s:%(lineno)s | %(levelname)s: %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
logging.basicConfig(**DEFAULT_LOGGING_CONFIG)
logger = logging.getLogger(__name__)

from pkg_resources import get_distribution
Expand Down
173 changes: 88 additions & 85 deletions python/fastsim/demos/demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -482,92 +482,94 @@ def get_sim_drive_vec(
# Includes example of how to load cycle from dict

# %%
veh = fsim.vehicle.Vehicle.from_vehdb(1) # load vehicle model
output = {}

results_df = pd.DataFrame()
t_start = time.perf_counter()
for trp in list(drive_cycs_df.nrel_trip_id.unique()):
pnts = drive_cycs_df[drive_cycs_df['nrel_trip_id'] == trp].copy()
pnts['time_local'] = pd.to_datetime(pnts['timestamp'])

cyc = {}
cyc['cycGrade'] = np.zeros(len(pnts))
cyc['mps'] = np.array(
pnts['speed_mph'] / fsim.params.MPH_PER_MPS) # MPH to MPS conversion
cyc['time_s'] = np.array(
np.cumsum(
(pnts['time_local'] -
pnts['time_local'].shift()).fillna(pd.Timedelta(seconds=0)).astype('timedelta64[s]')
with fsim.utils.suppress_logging():
veh = fsim.vehicle.Vehicle.from_vehdb(1) # load vehicle model
output = {}

results_df = pd.DataFrame()
t_start = time.perf_counter()
for trp in list(drive_cycs_df.nrel_trip_id.unique()):
pnts = drive_cycs_df[drive_cycs_df['nrel_trip_id'] == trp].copy()
pnts['time_local'] = pd.to_datetime(pnts['timestamp'])

cyc = {}
cyc['cycGrade'] = np.zeros(len(pnts))
cyc['mps'] = np.array(
pnts['speed_mph'] / fsim.params.MPH_PER_MPS) # MPH to MPS conversion
cyc['time_s'] = np.array(
np.cumsum(
(pnts['time_local'] -
pnts['time_local'].shift()).fillna(pd.Timedelta(seconds=0)).astype('timedelta64[s]')
)
)
)
cyc['road_type'] = np.zeros(len(pnts))
# example of loading cycle from dict
cyc = fsim.cycle.Cycle.from_dict(cyc)

sim_drive = fsim.simdrive.SimDrive(cyc, veh)
sim_drive.sim_drive()

output['nrel_trip_id'] = trp
output['distance_mi'] = sum(sim_drive.dist_mi)
duration_sec = sim_drive.cyc.time_s[-1] - sim_drive.cyc.time_s[0]
output['avg_speed_mph'] = sum(
sim_drive.dist_mi) / (duration_sec / 3600.0)
#results_df = results_df.append(output, ignore_index=True)
results_df = pd.concat([results_df,pd.DataFrame(output,index=[0])],ignore_index=True)
output['mpgge'] = sim_drive.mpgge

t_end = time.perf_counter()
cyc['road_type'] = np.zeros(len(pnts))
# example of loading cycle from dict
cyc = fsim.cycle.Cycle.from_dict(cyc)

sim_drive = fsim.simdrive.SimDrive(cyc, veh)
sim_drive.sim_drive()

output['nrel_trip_id'] = trp
output['distance_mi'] = sum(sim_drive.dist_mi)
duration_sec = sim_drive.cyc.time_s[-1] - sim_drive.cyc.time_s[0]
output['avg_speed_mph'] = sum(
sim_drive.dist_mi) / (duration_sec / 3600.0)
#results_df = results_df.append(output, ignore_index=True)
results_df = pd.concat([results_df,pd.DataFrame(output,index=[0])],ignore_index=True)
output['mpgge'] = sim_drive.mpgge

t_end = time.perf_counter()

# results_df = results_df.astype(float)
# results_df = results_df.astype(float)

print(f'Simulations Complete. Total runtime = {t_end - t_start:.2f} s')
print(' Average time per cycle = {:.2f} s'.format((
t_end - t_start) / len(drive_cycs_df.nrel_trip_id.unique())))
print(f'Simulations Complete. Total runtime = {t_end - t_start:.2f} s')
print(' Average time per cycle = {:.2f} s'.format((
t_end - t_start) / len(drive_cycs_df.nrel_trip_id.unique())))

# %% ... and the Rust version
veh = fsim.vehicle.Vehicle.from_vehdb(1).to_rust() # load vehicle model
output = {}

rust_results_df = pd.DataFrame()
t_start = time.perf_counter()
for trp in list(drive_cycs_df.nrel_trip_id.unique()):
pnts = drive_cycs_df[drive_cycs_df['nrel_trip_id'] == trp].copy()
pnts['time_local'] = pd.to_datetime(pnts['timestamp'])

cyc = {}
cyc['cycGrade'] = np.zeros(len(pnts))
cyc['mps'] = np.array(
pnts['speed_mph'] / fsim.params.MPH_PER_MPS) # MPH to MPS conversion
cyc['time_s'] = np.array(
np.cumsum(
(pnts['time_local'] -
pnts['time_local'].shift()).fillna(pd.Timedelta(seconds=0)).astype('timedelta64[s]')
with fsim.utils.suppress_logging():
veh = fsim.vehicle.Vehicle.from_vehdb(1).to_rust() # load vehicle model
output = {}

rust_results_df = pd.DataFrame()
t_start = time.perf_counter()
for trp in list(drive_cycs_df.nrel_trip_id.unique()):
pnts = drive_cycs_df[drive_cycs_df['nrel_trip_id'] == trp].copy()
pnts['time_local'] = pd.to_datetime(pnts['timestamp'])

cyc = {}
cyc['cycGrade'] = np.zeros(len(pnts))
cyc['mps'] = np.array(
pnts['speed_mph'] / fsim.params.MPH_PER_MPS) # MPH to MPS conversion
cyc['time_s'] = np.array(
np.cumsum(
(pnts['time_local'] -
pnts['time_local'].shift()).fillna(pd.Timedelta(seconds=0)).astype('timedelta64[s]')
)
)
)
cyc['road_type'] = np.zeros(len(pnts))
# example of loading cycle from dict
cyc = fsim.cycle.Cycle.from_dict(cyc).to_rust()

sim_drive = fsim.simdrive.RustSimDrive(cyc, veh)
sim_drive.sim_drive()

output['nrel_trip_id'] = trp
output['distance_mi'] = sum(sim_drive.dist_mi)
duration_sec = sim_drive.cyc.time_s[-1] - sim_drive.cyc.time_s[0]
output['avg_speed_mph'] = sum(
sim_drive.dist_mi) / (duration_sec / 3600.0)
rust_results_df = pd.concat([results_df, pd.DataFrame(output,index=[0])], ignore_index=True)
#rust_results_df = results_df.append(output, ignore_index=True)
output['mpgge'] = sim_drive.mpgge

t_end = time.perf_counter()
cyc['road_type'] = np.zeros(len(pnts))
# example of loading cycle from dict
cyc = fsim.cycle.Cycle.from_dict(cyc).to_rust()

sim_drive = fsim.simdrive.RustSimDrive(cyc, veh)
sim_drive.sim_drive()

output['nrel_trip_id'] = trp
output['distance_mi'] = sum(sim_drive.dist_mi)
duration_sec = sim_drive.cyc.time_s[-1] - sim_drive.cyc.time_s[0]
output['avg_speed_mph'] = sum(
sim_drive.dist_mi) / (duration_sec / 3600.0)
rust_results_df = pd.concat([results_df, pd.DataFrame(output,index=[0])], ignore_index=True)
#rust_results_df = results_df.append(output, ignore_index=True)
output['mpgge'] = sim_drive.mpgge

t_end = time.perf_counter()

# results_df = results_df.astype(float)
# results_df = results_df.astype(float)

print(f'Simulations Complete. Total runtime = {t_end - t_start:.2f} s')
print(' Average time per cycle = {:.2f} s'.format((
t_end - t_start) / len(drive_cycs_df.nrel_trip_id.unique())))
print(f'Simulations Complete. Total runtime = {t_end - t_start:.2f} s')
print(' Average time per cycle = {:.2f} s'.format((
t_end - t_start) / len(drive_cycs_df.nrel_trip_id.unique())))

# %% [markdown]
# ### Results
Expand Down Expand Up @@ -889,12 +891,13 @@ def get_sim_drive_vec(
# values.

# %%
if "default" in fsim.fastsimrust.enabled_features():
from fastsim.fastsimrust import abc_to_drag_coeffs
test_veh = fsim.vehicle.Vehicle.from_vehdb(5, to_rust=True).to_rust()
(drag_coef, wheel_rr_coef) = abc_to_drag_coeffs(test_veh, 25.91, 0.1943, 0.01796, simdrive_optimize=True)

print(f'Drag Coefficient: {drag_coef:.3g}')
print(f'Wheel Rolling Resistance Coefficient: {wheel_rr_coef:.3g}')
with fsim.utils.suppress_logging():
if "default" in fsim.fastsimrust.enabled_features():
from fastsim.fastsimrust import abc_to_drag_coeffs
test_veh = fsim.vehicle.Vehicle.from_vehdb(5, to_rust=True).to_rust()
(drag_coef, wheel_rr_coef) = abc_to_drag_coeffs(test_veh, 25.91, 0.1943, 0.01796, simdrive_optimize=True)

print(f'Drag Coefficient: {drag_coef:.3g}')
print(f'Wheel Rolling Resistance Coefficient: {wheel_rr_coef:.3g}')

# %%
Loading

0 comments on commit 09ca705

Please sign in to comment.