Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serde revamp and anyhowization #58

Merged
merged 24 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
dccb651
make much more use of anyhow, replacing most PyResults
Oct 18, 2023
fd113fa
remove extraneous comment
Oct 18, 2023
b25e09d
resolve fastsim-2 merge conflicts
Oct 18, 2023
021d72e
anyhowize fastsim-cli
Oct 18, 2023
d9aa2d8
change classmethods to staticmethods, no longer need PyType
Oct 19, 2023
1f2368a
anyhowize simdrivelabel and cyc_mods
Oct 19, 2023
ec6ab43
minor reorg of cycle.rs methods
Oct 19, 2023
0ab74d6
improve fastsim-cli
Oct 19, 2023
dec9471
revamp serde trait and anyhowize some misc functions
Oct 20, 2023
d0a15ae
clean up serde api to_file
Oct 20, 2023
6857a03
remove results in tests
Nov 3, 2023
22673ed
merge fastsim-2 into anyhowize-everything
Nov 3, 2023
e30636a
clean up some more anyhow calls
Nov 3, 2023
b6976f5
remove from_json_str method
Nov 3, 2023
7665bb9
from_str now calls from_yaml or from_json
Nov 3, 2023
428abee
shut annoying import warning up (it IS actually used)
Nov 3, 2023
8dd2f8d
more anyhow and result cleanup, removed some unnecessary result returns
Nov 3, 2023
9e5ec49
refactor code that clippy didn't like
Nov 3, 2023
5414653
expose from_resource to Python API
Nov 3, 2023
12d3a56
make solve_step return a Result in thermal.rs instead of unwrapping
Nov 3, 2023
2d2bc17
move to/from_file functions to other block
Nov 16, 2023
b8bdfa2
cargo fmt, to_str and from_str exposed to Python, better error messag…
Nov 17, 2023
e39c5f0
new to_file method for CSVs! also to_str works for CSVs now
Nov 17, 2023
4a73581
bin file serde working, but not for vehicles for some reason
Nov 17, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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))
}
10 changes: 4 additions & 6 deletions rust/fastsim-cli/tests/integration-tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use assert_cmd::prelude::{CommandCargoExt, OutputAssertExt};
use predicates::prelude::predicate;

#[test]
fn test_that_cli_app_produces_result() -> Result<(), Box<dyn std::error::Error>> {
let mut cmd = Command::cargo_bin("fastsim-cli")?;
fn test_that_cli_app_produces_result() {
let mut cmd = Command::cargo_bin("fastsim-cli").unwrap();
let mut cyc_file = project_root::get_project_root().unwrap();
cyc_file.push(Path::new("../python/fastsim/resources/cycles/udds.csv"));
cyc_file = cyc_file.canonicalize().unwrap();
Expand All @@ -28,17 +28,16 @@ fn test_that_cli_app_produces_result() -> Result<(), Box<dyn std::error::Error>>
cmd.assert()
.success()
.stdout(predicate::str::contains("33.8"));
Ok(())
}

#[test]
fn test_that_adopt_hd_option_works_as_expected() -> Result<(), Box<dyn std::error::Error>> {
fn test_that_adopt_hd_option_works_as_expected() {
let expected_results = vec![
("adoptstring.json", "0.245"), // 0.245 kWh/mile
("adoptstring2.json", "7.906"), // 7.906 mpgge
("adoptstring3.json", "6.882"), // 6.882 mpgge
];
let mut cmd = Command::cargo_bin("fastsim-cli")?;
let mut cmd = Command::cargo_bin("fastsim-cli").unwrap();
for (veh_file, expected_result) in expected_results.iter() {
let mut adopt_veh_file = project_root::get_project_root().unwrap();
let mut adopt_str_path = String::from("../rust/fastsim-cli/tests/assets/");
Expand All @@ -59,5 +58,4 @@ fn test_that_adopt_hd_option_works_as_expected() -> Result<(), Box<dyn std::erro
.success()
.stdout(predicate::str::contains(expected_mpg));
}
Ok(())
}
1 change: 1 addition & 0 deletions rust/fastsim-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ validator = { version = "0.16", features = ["derive"] }
lazy_static = "1.4.0"
regex = "1.7.1"
rayon = "1.7.0"
include_dir = "0.7.3"

[package.metadata]
include = [
Expand Down
4 changes: 2 additions & 2 deletions rust/fastsim-core/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ fn main() {
env::current_dir().unwrap().as_os_str().to_str().unwrap()
),
format!(
"{}/resources/udds.csv",
"{}/resources/cycles/udds.csv",
env::current_dir().unwrap().as_os_str().to_str().unwrap()
),
format!(
"{}/resources/hwfet.csv",
"{}/resources/cycles/hwfet.csv",
env::current_dir().unwrap().as_os_str().to_str().unwrap()
),
];
Expand Down
Loading