Skip to content

Commit

Permalink
Merge branch 'fastsim-2' into remove-redundancies
Browse files Browse the repository at this point in the history
  • Loading branch information
Kyle Carow authored and Kyle Carow committed Nov 17, 2023
2 parents c4fba56 + a9ebdbb commit f162a65
Show file tree
Hide file tree
Showing 33 changed files with 715 additions and 576 deletions.
65 changes: 65 additions & 0 deletions .github/workflows/deploy-book.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: Deploy mdBook site to Pages

on:
# Runs on pushes targeting the default branch
push:
branches: ["fastsim-2"]
paths:
- "docs/**"
- ".github/workflows/deploy-book.yaml"
pull_request:
branches: ["fastsim-2"]
paths:
- "docs/**"
- ".github/workflows/deploy-book.yaml"

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write

# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false

jobs:
# Build job
build:
runs-on: [ self-hosted ]
env:
MDBOOK_VERSION: 0.4.21
steps:
- uses: actions/checkout@v3
- name: Install mdBook
run: |
curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf -y | sh
rustup update
cargo install --version ${MDBOOK_VERSION} mdbook
- name: Setup Pages
id: pages
uses: actions/configure-pages@v3
- name: Build with mdBook
working-directory: ${{runner.workspace}}/mbap-computing/docs/
run: mdbook build
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with:
path: ./docs/book

# Deployment job
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: [ self-hosted ]
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
![FASTSim Logo](https://www.nrel.gov/transportation/assets/images/icon-fastsim.jpg)

[![Tests](https://github.com/NREL/fastsim/actions/workflows/tests.yaml/badge.svg)](https://github.com/NREL/fastsim/actions/workflows/tests.yaml) [![wheels](https://github.com/NREL/fastsim/actions/workflows/wheels.yaml/badge.svg)](https://github.com/NREL/fastsim/actions/workflows/wheels.yaml?event=release) ![Python](https://img.shields.io/badge/python-3.9%20%7C%203.10-blue) [![Documentation](https://img.shields.io/badge/documentation-custom-blue.svg)](https://nrel.github.io/fastsim/) [![GitHub](https://img.shields.io/badge/GitHub-fastsim-blue.svg)](https://github.com/NREL/fastsim)

# Description
This is the python/rust flavor of [NREL's FASTSim<sup>TM</sup>](https://www.nrel.gov/transportation/fastsim.html), 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.

Expand Down
1 change: 1 addition & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
book/
10 changes: 10 additions & 0 deletions docs/book.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[book]
authors = ["Chad Baker"]
language = "en"
multilingual = false
src = "src"
title = "FASTSim Documentation"

[output.html.fold]
enable = true
level = 0
4 changes: 4 additions & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Summary

- [Introduction](./intro.md)
- [How to Update This Book](./how-to-update.md)
15 changes: 15 additions & 0 deletions docs/src/how-to-update.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# How to Update This Markdown Book

[mdBook Documentation](https://rust-lang.github.io/mdBook/)

## Setup

1. If not already done, [install mdbook](https://rust-lang.github.io/mdBook/guide/installation.html)

## Publishing

1. Update `book.toml` or files in `docs/src/`
1. Make sure the docs look good locally: `mdbook build docs/ --open`
1. Commit files and push to `main` branch

After that, a GitHub action will build the book and publish it [here](https://pages.github.nrel.gov/MBAP/mbap-computing/)
3 changes: 3 additions & 0 deletions docs/src/intro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Introduction

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.
2 changes: 2 additions & 0 deletions rust/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Crate Architecture
[![Tests](https://github.com/NREL/fastsim/actions/workflows/tests.yaml/badge.svg)](https://github.com/NREL/fastsim/actions/workflows/tests.yaml) [![wheels](https://github.com/NREL/fastsim/actions/workflows/wheels.yaml/badge.svg)](https://github.com/NREL/fastsim/actions/workflows/wheels.yaml?event=release) ![Python](https://img.shields.io/badge/python-3.9%20%7C%203.10-blue) [![Documentation](https://img.shields.io/badge/documentation-custom-blue.svg)](https://nrel.github.io/fastsim/) [![GitHub](https://img.shields.io/badge/GitHub-fastsim-blue.svg)](https://github.com/NREL/fastsim)

FASTSim Rust crates are organized as a cargo [workspace](Cargo.toml) as follows:
1. `fastsim-core`: a pure rust lib crate with optional `pyo3` feature. This crate is intended to be used by other crates and is not in itself an app.
1. `fastsim-cli`: a wrapper around `fastsim-core` to enable a standalone CLI app for running fastsim and getting results out.
Expand Down
1 change: 1 addition & 0 deletions rust/fastsim-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ repository = "https://github.com/NREL/fastsim"

[dependencies]
fastsim-core = { path = "../fastsim-core", version = "~0" }
anyhow = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
project-root = "0.2.2"
Expand Down
111 changes: 42 additions & 69 deletions rust/fastsim-cli/src/bin/fastsim-cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,9 @@ pub fn calculate_mpgge_for_h2_diesel_ice(
fs_kwh_out_ach: &Vec<f64>,
fc_pwr_out_perc: &Vec<f64>,
h2share: &Vec<f64>,
) -> H2AndDieselResults {
assert!(fc_kw_out_ach.len() == fs_kwh_out_ach.len());
assert!(fc_pwr_out_perc.len() == h2share.len());
) -> anyhow::Result<H2AndDieselResults> {
anyhow::ensure!(fc_kw_out_ach.len() == fs_kwh_out_ach.len());
anyhow::ensure!(fc_pwr_out_perc.len() == h2share.len());
let kwh_per_gallon_diesel = 37.95;
let gge_per_kwh = 1.0 / kwh_per_gge;
let mut total_diesel_kwh = 0.0;
Expand All @@ -148,7 +148,7 @@ pub fn calculate_mpgge_for_h2_diesel_ice(
total_diesel_gals += diesel_gals;
total_diesel_gge += diesel_gge;
}
H2AndDieselResults {
Ok(H2AndDieselResults {
h2_kwh: total_h2_kwh,
h2_gge: total_h2_gge,
h2_mpgge: if total_h2_gge > 0.0 {
Expand All @@ -164,25 +164,25 @@ pub fn calculate_mpgge_for_h2_diesel_ice(
} else {
0.0
},
}
})
}

pub fn integrate_power_to_kwh(dts_s: &Vec<f64>, ps_kw: &Vec<f64>) -> Vec<f64> {
assert!(dts_s.len() == ps_kw.len());
pub fn integrate_power_to_kwh(dts_s: &Vec<f64>, ps_kw: &Vec<f64>) -> anyhow::Result<Vec<f64>> {
anyhow::ensure!(dts_s.len() == ps_kw.len());
let mut energy_kwh = Vec::<f64>::with_capacity(dts_s.len());
for idx in 0..dts_s.len() {
let dt_s = dts_s[idx];
let p_kw = ps_kw[idx];
energy_kwh.push(p_kw * dt_s / 3600.0);
}
energy_kwh
Ok(energy_kwh)
}

pub fn main() {
pub fn main() -> anyhow::Result<()> {
let fastsim_api = FastSimApi::parse();

if let Some(_cyc_json_str) = fastsim_api.cyc {
panic!("Need to implement: let cyc = RustCycle::from_json(cyc_json_str)");
anyhow::bail!("Need to implement: let cyc = RustCycle::from_json(cyc_json_str)");
}
let (is_adopt_hd, adopt_hd_string, adopt_hd_has_cycle) =
if let Some(adopt_hd_string) = &fastsim_api.adopt_hd {
Expand Down Expand Up @@ -215,26 +215,25 @@ pub fn main() {
);
println!("Drag Coefficient: {}", drag_coeff);
println!("Wheel RR Coefficient: {}", wheel_rr_coeff);
return;
return Ok(());
} else {
panic!("Need to provide coastdown test coefficients for drag and wheel rr coefficient calculation");
anyhow::bail!("Need to provide coastdown test coefficients for drag and wheel rr coefficient calculation");
}
} else {
RustCycle::from_file(&cyc_file_path)
}
} else if is_adopt_hd && adopt_hd_has_cycle {
RustCycle::from_file(&adopt_hd_string)
RustCycle::from_file(adopt_hd_string)
} else {
//TODO? use pathbuff to string, for robustness
Ok(RustCycle::new(
vec![0.0],
vec![0.0],
vec![0.0],
vec![0.0],
String::from("")
String::from(""),
))
}
.unwrap();
}?;

// TODO: put in logic here for loading vehicle for adopt-hd
// with same file format as regular adopt and same outputs retured
Expand All @@ -243,44 +242,35 @@ pub fn main() {
let mut hd_h2_diesel_ice_h2share: Option<Vec<f64>> = None;
let veh = if let Some(veh_string) = fastsim_api.veh {
if is_adopt || is_adopt_hd {
let (veh_string, pwr_out_perc, h2share) = json_rewrite(veh_string);
let (veh_string, pwr_out_perc, h2share) = json_rewrite(veh_string)?;
hd_h2_diesel_ice_h2share = h2share;
fc_pwr_out_perc = pwr_out_perc;
RustVehicle::from_json_str(&veh_string)
let mut veh = RustVehicle::from_json(&veh_string)?;
veh.set_derived()?;
Ok(veh)
} else {
RustVehicle::from_json_str(&veh_string)
let mut veh = RustVehicle::from_json(&veh_string)?;
veh.set_derived()?;
Ok(veh)
}
} else if let Some(veh_file_path) = fastsim_api.veh_file {
if is_adopt || is_adopt_hd {
let vehstring = fs::read_to_string(veh_file_path).unwrap();
let (vehstring, pwr_out_perc, h2share) = json_rewrite(vehstring);
let veh_string = fs::read_to_string(veh_file_path)?;
let (veh_string, pwr_out_perc, h2share) = json_rewrite(veh_string)?;
hd_h2_diesel_ice_h2share = h2share;
fc_pwr_out_perc = pwr_out_perc;
RustVehicle::from_json_str(&vehstring)
let mut veh = RustVehicle::from_json(&veh_string)?;
veh.set_derived()?;
Ok(veh)
} else {
RustVehicle::from_file(&veh_file_path)
}
} else {
Ok(RustVehicle::mock_vehicle())
}
.unwrap();

#[cfg(not(windows))]
macro_rules! path_separator {
() => {
"/"
};
}

#[cfg(windows)]
macro_rules! path_separator {
() => {
r#"\"#
};
}
}?;

if is_adopt {
let sdl = get_label_fe(&veh, Some(false), Some(false)).unwrap();
let sdl = get_label_fe(&veh, Some(false), Some(false))?;
let res = AdoptResults {
adjCombMpgge: sdl.0.adj_comb_mpgge,
rangeMiles: sdl.0.net_range_miles,
Expand All @@ -290,36 +280,17 @@ pub fn main() {
traceMissInMph: sdl.0.trace_miss_speed_mph,
h2AndDiesel: None,
};
println!("{}", res.to_json());
println!("{}", res.to_json()?);
} else if is_adopt_hd {
let hd_cyc_filestring = include_str!(concat!(
"..",
path_separator!(),
"..",
path_separator!(),
"..",
path_separator!(),
"..",
path_separator!(),
"python",
path_separator!(),
"fastsim",
path_separator!(),
"resources",
path_separator!(),
"cycles",
path_separator!(),
"HHDDTCruiseSmooth.csv"
));
let cyc = if adopt_hd_has_cycle {
cyc
} else {
RustCycle::from_csv_string(hd_cyc_filestring, "HHDDTCruiseSmooth".to_string()).unwrap()
RustCycle::from_resource("cycles/HHDDTCruiseSmooth.csv")?
};
let mut sim_drive = RustSimDrive::new(cyc, veh.clone());
sim_drive.sim_drive(None, None).unwrap();
sim_drive.sim_drive(None, None)?;
let mut sim_drive_accel = RustSimDrive::new(make_accel_trace(), veh.clone());
let net_accel = get_net_accel(&mut sim_drive_accel, &veh.scenario_name).unwrap();
let net_accel = get_net_accel(&mut sim_drive_accel, &veh.scenario_name)?;
let mut mpgge = sim_drive.mpgge;

let h2_diesel_results = if let Some(hd_h2_diesel_ice_h2share) = hd_h2_diesel_ice_h2share {
Expand All @@ -333,7 +304,7 @@ pub fn main() {
&sim_drive.fs_kwh_out_ach.to_vec(),
&fc_pwr_out_perc,
&hd_h2_diesel_ice_h2share,
);
)?;
mpgge = dist_mi / (r.diesel_gge + r.h2_gge);
Some(r)
} else {
Expand All @@ -358,16 +329,17 @@ pub fn main() {
traceMissInMph: sim_drive.trace_miss_speed_mps * MPH_PER_MPS,
h2AndDiesel: h2_diesel_results,
};
println!("{}", res.to_json());
println!("{}", res.to_json()?);
} else {
let mut sim_drive = RustSimDrive::new(cyc, veh);
// // this does nothing if it has already been called for the constructed `sim_drive`
sim_drive.sim_drive(None, None).unwrap();
sim_drive.sim_drive(None, None)?;
println!("{}", sim_drive.mpgge);
}
// else {
// println!("Invalid option `{}` for `--res-fmt`", res_fmt);
// }
Ok(())
}

fn translate_veh_pt_type(x: i64) -> String {
Expand Down Expand Up @@ -422,13 +394,14 @@ struct ParsedValue(Value);
impl SerdeAPI for ParsedValue {}

/// Rewrites the ADOPT JSON string to be in compliance with what FASTSim expects for JSON input.
fn json_rewrite(x: String) -> (String, Option<Vec<f64>>, Option<Vec<f64>>) {
#[allow(clippy::type_complexity)]
fn json_rewrite(x: String) -> anyhow::Result<(String, Option<Vec<f64>>, Option<Vec<f64>>)> {
let adoptstring = x;

let mut fc_pwr_out_perc: Option<Vec<f64>> = None;
let mut hd_h2_diesel_ice_h2share: Option<Vec<f64>> = None;

let mut parsed_data: Value = serde_json::from_str(&adoptstring).unwrap();
let mut parsed_data: Value = serde_json::from_str(&adoptstring)?;

let veh_pt_type_raw = &parsed_data["vehPtType"];
if veh_pt_type_raw.is_i64() {
Expand Down Expand Up @@ -520,7 +493,7 @@ fn json_rewrite(x: String) -> (String, Option<Vec<f64>>, Option<Vec<f64>>) {

parsed_data["stop_start"] = json!(false);

let adoptstring = ParsedValue(parsed_data).to_json();
let adoptstring = ParsedValue(parsed_data).to_json()?;

(adoptstring, fc_pwr_out_perc, hd_h2_diesel_ice_h2share)
Ok((adoptstring, fc_pwr_out_perc, hd_h2_diesel_ice_h2share))
}
Loading

0 comments on commit f162a65

Please sign in to comment.