From 16cdf6019701db20d972e0dd0b7d4d4942bd5b8c Mon Sep 17 00:00:00 2001 From: Chad Baker Date: Thu, 2 Jan 2025 13:54:13 -0700 Subject: [PATCH 1/5] pyo3=0.20 --- rust/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 539539e1..f1b9f9b6 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -17,7 +17,7 @@ codegen-units = 1 # optimize connection between modules [workspace.dependencies] anyhow = "1.0.57" ndarray = { version = "0.15.4", features = ["serde"] } -pyo3 = "0.19" +pyo3 = "0.20" pyo3-log = "*" serde = "1.0.143" serde_json = "1.0.83" From 97c89afe04e93ffe6d139dadd4c81fc7b1e263fb Mon Sep 17 00:00:00 2001 From: Chad Baker Date: Thu, 2 Jan 2025 16:54:50 -0700 Subject: [PATCH 2/5] pyo3=0.21 --- rust/Cargo.toml | 2 +- rust/fastsim-cli/src/bin/fastsim-cli.rs | 4 +- .../src/add_pyo3_api/mod.rs | 59 +++++++++++-------- rust/fastsim-core/src/cycle.rs | 47 +++++++++++---- rust/fastsim-core/src/macros.rs | 36 ----------- rust/fastsim-core/src/simdrivelabel.rs | 45 ++++++++------ rust/fastsim-py/src/lib.rs | 2 +- 7 files changed, 98 insertions(+), 97 deletions(-) diff --git a/rust/Cargo.toml b/rust/Cargo.toml index f1b9f9b6..489be18e 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -17,7 +17,7 @@ codegen-units = 1 # optimize connection between modules [workspace.dependencies] anyhow = "1.0.57" ndarray = { version = "0.15.4", features = ["serde"] } -pyo3 = "0.20" +pyo3 = "0.21" pyo3-log = "*" serde = "1.0.143" serde_json = "1.0.83" diff --git a/rust/fastsim-cli/src/bin/fastsim-cli.rs b/rust/fastsim-cli/src/bin/fastsim-cli.rs index 687c1176..4a3686bb 100644 --- a/rust/fastsim-cli/src/bin/fastsim-cli.rs +++ b/rust/fastsim-cli/src/bin/fastsim-cli.rs @@ -367,11 +367,11 @@ struct ArrayObject { /// Takes a vector of floats and transforms it into an object representation /// used by the ndarray library. -fn array_to_object_representation(xs: &Vec) -> ArrayObject { +fn array_to_object_representation(xs: &[f64]) -> ArrayObject { ArrayObject { v: 1, dim: vec![xs.len()], - data: xs.clone(), + data: xs.to_vec().clone(), } } diff --git a/rust/fastsim-core/fastsim-proc-macros/src/add_pyo3_api/mod.rs b/rust/fastsim-core/fastsim-proc-macros/src/add_pyo3_api/mod.rs index c444a260..f8899414 100644 --- a/rust/fastsim-core/fastsim-proc-macros/src/add_pyo3_api/mod.rs +++ b/rust/fastsim-core/fastsim-proc-macros/src/add_pyo3_api/mod.rs @@ -204,7 +204,7 @@ pub fn add_pyo3_api(attr: TokenStream, item: TokenStream) -> TokenStream { py_impl_block.extend::(quote! { pub fn copy(&self) -> Self {self.clone()} pub fn __copy__(&self) -> Self {self.clone()} - pub fn __deepcopy__(&self, _memo: &PyDict) -> Self {self.clone()} + pub fn __deepcopy__(&self, _memo: &Bound) -> Self {self.clone()} /// Read (deserialize) an object from a resource file packaged with the `fastsim-core` crate /// @@ -215,8 +215,11 @@ pub fn add_pyo3_api(attr: TokenStream, item: TokenStream) -> TokenStream { #[cfg(feature = "resources")] #[staticmethod] #[pyo3(name = "from_resource")] - pub fn from_resource_py(filepath: &PyAny, skip_init: Option) -> PyResult { - Self::from_resource(PathBuf::extract(filepath)?, skip_init.unwrap_or_default()).map_err(|e| PyIOError::new_err(format!("{:?}", e))) + pub fn from_resource_py(filepath: &Bound, skip_init: Option) -> PyResult { + Self::from_resource( + PathBuf::extract_bound(filepath)?, + skip_init.unwrap_or_default() + ).map_err(|e| PyIOError::new_err(format!("{:?}", e))) } /// Write (serialize) an object to a file. @@ -228,8 +231,10 @@ pub fn add_pyo3_api(attr: TokenStream, item: TokenStream) -> TokenStream { /// * `filepath`: `str | pathlib.Path` - The filepath at which to write the object /// #[pyo3(name = "to_file")] - pub fn to_file_py(&self, filepath: &PyAny) -> PyResult<()> { - self.to_file(PathBuf::extract(filepath)?).map_err(|e| PyIOError::new_err(format!("{:?}", e))) + pub fn to_file_py(&self, filepath: &Bound) -> PyResult<()> { + self.to_file( + PathBuf::extract_bound(filepath)? + ).map_err(|e| PyIOError::new_err(format!("{:?}", e))) } /// Read (deserialize) an object from a file. @@ -241,8 +246,12 @@ pub fn add_pyo3_api(attr: TokenStream, item: TokenStream) -> TokenStream { /// #[staticmethod] #[pyo3(name = "from_file")] - pub fn from_file_py(filepath: &PyAny, skip_init: Option) -> PyResult { - Self::from_file(PathBuf::extract(filepath)?, skip_init.unwrap_or_default()).map_err(|e| PyIOError::new_err(format!("{:?}", e))) + pub fn from_file_py(filepath: &Bound, skip_init: Option) -> PyResult { + Self::from_file( + PathBuf::extract_bound(filepath)?, + skip_init.unwrap_or_default() + ) + .map_err(|e| PyIOError::new_err(format!("{:?}", e))) } /// Write (serialize) an object into a string @@ -305,25 +314,25 @@ pub fn add_pyo3_api(attr: TokenStream, item: TokenStream) -> TokenStream { Self::from_yaml(yaml_str, skip_init.unwrap_or_default()).map_err(|e| PyIOError::new_err(format!("{:?}", e))) } - /// Write (serialize) an object to bincode-encoded `bytes` - #[cfg(feature = "bincode")] - #[pyo3(name = "to_bincode")] - pub fn to_bincode_py<'py>(&self, py: Python<'py>) -> PyResult<&'py PyBytes> { - PyResult::Ok(PyBytes::new(py, &self.to_bincode()?)).map_err(|e| PyIOError::new_err(format!("{:?}", e))) - } + // /// Write (serialize) an object to bincode-encoded `bytes` + // #[cfg(feature = "bincode")] + // #[pyo3(name = "to_bincode")] + // pub fn to_bincode_py<'py>(&self, py: Python<'py>) -> PyResult<&'py PyBytes> { + // PyResult::Ok(PyBytes::new(py, &self.to_bincode()?)).map_err(|e| PyIOError::new_err(format!("{:?}", e))) + // } - /// Read (deserialize) an object from bincode-encoded `bytes` - /// - /// # Arguments - /// - /// * `encoded`: `bytes` - Encoded bytes to deserialize from - /// - #[cfg(feature = "bincode")] - #[staticmethod] - #[pyo3(name = "from_bincode")] - pub fn from_bincode_py(encoded: &PyBytes, skip_init: Option) -> PyResult { - Self::from_bincode(encoded.as_bytes(), skip_init.unwrap_or_default()).map_err(|e| PyIOError::new_err(format!("{:?}", e))) - } + // /// Read (deserialize) an object from bincode-encoded `bytes` + // /// + // /// # Arguments + // /// + // /// * `encoded`: `bytes` - Encoded bytes to deserialize from + // /// + // #[cfg(feature = "bincode")] + // #[staticmethod] + // #[pyo3(name = "from_bincode")] + // pub fn from_bincode_py(encoded: &PyBytes, skip_init: Option) -> PyResult { + // Self::from_bincode(encoded.as_bytes(), skip_init.unwrap_or_default()).map_err(|e| PyIOError::new_err(format!("{:?}", e))) + // } }); let impl_block = quote! { diff --git a/rust/fastsim-core/src/cycle.rs b/rust/fastsim-core/src/cycle.rs index ccc4531a..b8114432 100644 --- a/rust/fastsim-core/src/cycle.rs +++ b/rust/fastsim-core/src/cycle.rs @@ -355,7 +355,7 @@ pub fn extend_cycle( #[cfg(feature = "pyo3")] #[allow(unused)] -pub fn register(_py: Python<'_>, m: &PyModule) -> anyhow::Result<()> { +pub fn register(_py: Python<'_>, m: &Bound) -> anyhow::Result<()> { m.add_function(wrap_pyfunction!(calc_constant_jerk_trajectory, m)?)?; m.add_function(wrap_pyfunction!(accel_for_constant_jerk, m)?)?; m.add_function(wrap_pyfunction!(speed_for_constant_jerk, m)?)?; @@ -487,8 +487,8 @@ impl RustCycleCache { #[staticmethod] #[pyo3(name = "from_csv")] - pub fn from_csv_py(filepath: &PyAny, skip_init: Option) -> anyhow::Result { - Self::from_csv_file(PathBuf::extract(filepath)?, skip_init.unwrap_or_default()) + pub fn from_csv_py(filepath: &Bound, skip_init: Option) -> anyhow::Result { + Self::from_csv_file(PathBuf::extract_bound(filepath)?, skip_init.unwrap_or_default()) } pub fn to_rust(&self) -> Self { @@ -496,23 +496,44 @@ impl RustCycleCache { } #[staticmethod] - pub fn from_dict(dict: &PyDict, skip_init: Option) -> anyhow::Result { - let time_s = Array::from_vec(PyAny::get_item(dict, "time_s")?.extract()?); + pub fn from_dict(dict: &Bound, skip_init: Option) -> PyResult { + let time_s = Array::from_vec(dict.get_item("time_s")?.with_context(|| format_dbg!())?.extract()?); let cyc_len = time_s.len(); let mut cyc = Self { time_s, - mps: Array::from_vec(PyAny::get_item(dict, "mps")?.extract()?), - grade: if let Ok(value) = PyAny::get_item(dict, "grade") { - Array::from_vec(value.extract()?) + mps: Array::from_vec(dict.get_item("mps")?.with_context(|| format_dbg!())?.extract()?), + grade: if let Ok(Some(item_res)) = dict.get_item("grade") { + if let Ok(grade) = item_res.extract() { + Array::from_vec(grade) + } else { + Array::default(cyc_len) + } } else { Array::default(cyc_len) }, - road_type: if let Ok(value) = PyAny::get_item(dict, "road_type") { - Array::from_vec(value.extract()?) + road_type: if let Ok(Some(item_res)) = dict.get_item("road_type") { + if let Ok(road_type) = item_res.extract() { + Array::from_vec(road_type) + } else { + Array::default(cyc_len) + } } else { Array::default(cyc_len) }, - name: PyAny::get_item(dict, "name").and_then(String::extract).unwrap_or_default(), + // name: PyAny::get_item(dict, "name").and_then(String::extract).unwrap_or_default(), + name: if let Ok(Some(item_res)) = dict.get_item("name") { + if let Ok(name) = item_res.extract() { + if let Ok(name_str) = String::extract(name) { + name_str + } else { + Default::default() + } + } else { + Default::default() + } + } else { + Default::default() + }, orphaned: false, }; if !skip_init.unwrap_or_default() { @@ -521,8 +542,8 @@ impl RustCycleCache { Ok(cyc) } - pub fn to_dict<'py>(&self, py: Python<'py>) -> anyhow::Result<&'py PyDict> { - let dict = PyDict::new(py); + pub fn to_dict<'py>(&self, py: Python<'py>) -> anyhow::Result> { + let dict = PyDict::new_bound(py); dict.set_item("time_s", self.time_s.to_vec())?; dict.set_item("mps", self.mps.to_vec())?; dict.set_item("grade", self.grade.to_vec())?; diff --git a/rust/fastsim-core/src/macros.rs b/rust/fastsim-core/src/macros.rs index ff4f41a1..25bd1862 100644 --- a/rust/fastsim-core/src/macros.rs +++ b/rust/fastsim-core/src/macros.rs @@ -1,39 +1,3 @@ -/// Given pairs of arbitrary keys and values, prints "key: value" to python intepreter. -/// Given str, prints str. -/// Using this will break `cargo test` but work with `maturin develop`. -#[macro_export] -macro_rules! print_to_py { - ( $( $x:expr, $y:expr ),* ) => { - { - pyo3::Python::with_gil(|py| { - let locals = pyo3::types::PyDict::new(py); - $( - locals.set_item($x, $y).unwrap(); - py.run( - &format!("print(f\"{}: {{{}:.3g}}\")", $x, $x), - None, - Some(locals), - ) - .expect(&format!("printing `{}` failed", $x)); - )* - }); - }; - }; - ( $x:expr ) => { - { - // use pyo3::py_run; - pyo3::Python::with_gil(|py| { - py.run( - &format!("print({})", $x), - None, - None, - ) - .expect(&format!("printing `{}` failed", $x)); - }); - }; - } -} - #[macro_export] macro_rules! check_orphaned_and_set { ($struct_self: ident, $field: ident, $value: expr) => { diff --git a/rust/fastsim-core/src/simdrivelabel.rs b/rust/fastsim-core/src/simdrivelabel.rs index 41976907..263d82d8 100644 --- a/rust/fastsim-core/src/simdrivelabel.rs +++ b/rust/fastsim-core/src/simdrivelabel.rs @@ -394,11 +394,22 @@ pub fn get_label_fe_py( full_detail: Option, verbose: Option, ) -> anyhow::Result<(LabelFe, Option>)> { - let result = - get_label_fe(veh, full_detail, verbose)?; + let result = get_label_fe(veh, full_detail, verbose)?; Ok(result) } +/// PHEV-specific function for label fe. +/// +/// # Arguments +/// - `veh` : vehicle::RustVehicle +/// - `sd` : RustSimDrive objects to use for label fe calculations +/// - `long_params` : Struct for longparams.json values +/// - `adj_params`: Adjusted coefficients from longparams.json +/// - `sim_params` : RustSimDriveParams +/// - `props` : RustPhysicalProperties +/// +/// # Returns +/// label fuel economy values for PHEV as a struct. pub fn get_label_fe_phev( veh: &vehicle::RustVehicle, sd: &mut HashMap<&str, RustSimDrive>, @@ -407,18 +418,6 @@ pub fn get_label_fe_phev( sim_params: &RustSimDriveParams, props: &RustPhysicalProperties, ) -> anyhow::Result { - // PHEV-specific function for label fe. - // - // Arguments: - // ---------- - // veh : vehicle::RustVehicle - // sd : RustSimDrive objects to use for label fe calculations - // long_params : Struct for longparams.json values - // adj_params: Adjusted coefficients from longparams.json - // sim_params : RustSimDriveParams - // props : RustPhysicalProperties - // - // Returns label fuel economy values for PHEV as a struct. let mut phev_calcs = LabelFePHEV { regen_soc_buffer: min( ((0.5 * veh.veh_kg * ((60. * (1. / MPH_PER_MPS)).powi(2))) @@ -698,21 +697,29 @@ pub fn get_label_fe_phev( #[cfg(feature = "pyo3")] #[pyfunction(name = "get_label_fe_phev")] - /// pyo3 version of [get_label_fe_phev] pub fn get_label_fe_phev_py( veh: &vehicle::RustVehicle, - sd: HashMap<&str, RustSimDrive>, + sd_dict: Bound, adj_params: AdjCoef, long_params: RustLongParams, sim_params: &RustSimDriveParams, props: RustPhysicalProperties, ) -> anyhow::Result { - let mut sd_mut = HashMap::new(); - for (key, value) in sd { - sd_mut.insert(key, value); + let mut sd_mut: HashMap = HashMap::new(); + for (key, value) in sd_dict.keys().into_iter().zip(sd_dict.values().into_iter()) { + let key_extracted = key + .extract::() + .with_context(|| format!("{}\nFailed to extract key", format_dbg!()))?; + let value_extracted = value + .extract() + .with_context(|| format!("{}\nFailed to extract value", format_dbg!()))?; + sd_mut.insert(key_extracted, value_extracted); } + let mut sd_mut = + HashMap::from_iter(sd_mut.iter().map(|item| (item.0.as_str(), item.1.clone()))); + get_label_fe_phev( veh, &mut sd_mut, diff --git a/rust/fastsim-py/src/lib.rs b/rust/fastsim-py/src/lib.rs index a440af59..0046ac09 100644 --- a/rust/fastsim-py/src/lib.rs +++ b/rust/fastsim-py/src/lib.rs @@ -12,7 +12,7 @@ use pyo3imports::*; /// Function for adding Rust structs as Python Classes #[pymodule] -fn fastsimrust(py: Python, m: &PyModule) -> PyResult<()> { +fn fastsimrust(py: Python, m: &Bound) -> PyResult<()> { #[cfg(feature = "logging")] pyo3_log::init(); m.add_class::()?; From bf60c11921f31b3012b275d8191b0ecfef461e50 Mon Sep 17 00:00:00 2001 From: Chad Baker Date: Thu, 2 Jan 2025 17:27:46 -0700 Subject: [PATCH 3/5] pyo3=0.22.4 --- rust/Cargo.toml | 2 +- .../src/add_pyo3_api/mod.rs | 5 +++ rust/fastsim-core/src/cycle.rs | 14 ++----- rust/fastsim-core/src/simdrive.rs | 4 ++ .../src/simdrive/simdrive_iter.rs | 1 + rust/fastsim-core/src/simdrivelabel.rs | 1 + rust/fastsim-core/src/thermal.rs | 11 ++++++ rust/fastsim-core/src/vehicle_import.rs | 38 ++++++++++++++++++- rust/fastsim-core/src/vehicle_utils.rs | 11 ++++++ 9 files changed, 75 insertions(+), 12 deletions(-) diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 489be18e..8823a5a7 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -17,7 +17,7 @@ codegen-units = 1 # optimize connection between modules [workspace.dependencies] anyhow = "1.0.57" ndarray = { version = "0.15.4", features = ["serde"] } -pyo3 = "0.21" +pyo3 = "0.22.4" pyo3-log = "*" serde = "1.0.143" serde_json = "1.0.83" diff --git a/rust/fastsim-core/fastsim-proc-macros/src/add_pyo3_api/mod.rs b/rust/fastsim-core/fastsim-proc-macros/src/add_pyo3_api/mod.rs index f8899414..b6519add 100644 --- a/rust/fastsim-core/fastsim-proc-macros/src/add_pyo3_api/mod.rs +++ b/rust/fastsim-core/fastsim-proc-macros/src/add_pyo3_api/mod.rs @@ -215,6 +215,7 @@ pub fn add_pyo3_api(attr: TokenStream, item: TokenStream) -> TokenStream { #[cfg(feature = "resources")] #[staticmethod] #[pyo3(name = "from_resource")] + #[pyo3(signature = (filepath, skip_init=None))] pub fn from_resource_py(filepath: &Bound, skip_init: Option) -> PyResult { Self::from_resource( PathBuf::extract_bound(filepath)?, @@ -246,6 +247,7 @@ pub fn add_pyo3_api(attr: TokenStream, item: TokenStream) -> TokenStream { /// #[staticmethod] #[pyo3(name = "from_file")] + #[pyo3(signature = (filepath, skip_init=None))] pub fn from_file_py(filepath: &Bound, skip_init: Option) -> PyResult { Self::from_file( PathBuf::extract_bound(filepath)?, @@ -274,6 +276,7 @@ pub fn add_pyo3_api(attr: TokenStream, item: TokenStream) -> TokenStream { /// #[staticmethod] #[pyo3(name = "from_str")] + #[pyo3(signature = (contents, format, skip_init=None))] pub fn from_str_py(contents: &str, format: &str, skip_init: Option) -> PyResult { Self::from_str(contents, format, skip_init.unwrap_or_default()).map_err(|e| PyIOError::new_err(format!("{:?}", e))) } @@ -292,6 +295,7 @@ pub fn add_pyo3_api(attr: TokenStream, item: TokenStream) -> TokenStream { /// #[staticmethod] #[pyo3(name = "from_json")] + #[pyo3(signature = (json_str, skip_init=None))] pub fn from_json_py(json_str: &str, skip_init: Option) -> PyResult { Self::from_json(json_str, skip_init.unwrap_or_default()).map_err(|e| PyIOError::new_err(format!("{:?}", e))) } @@ -310,6 +314,7 @@ pub fn add_pyo3_api(attr: TokenStream, item: TokenStream) -> TokenStream { /// #[staticmethod] #[pyo3(name = "from_yaml")] + #[pyo3(signature = (yaml_str, skip_init=None))] pub fn from_yaml_py(yaml_str: &str, skip_init: Option) -> PyResult { Self::from_yaml(yaml_str, skip_init.unwrap_or_default()).map_err(|e| PyIOError::new_err(format!("{:?}", e))) } diff --git a/rust/fastsim-core/src/cycle.rs b/rust/fastsim-core/src/cycle.rs index b8114432..678bd906 100644 --- a/rust/fastsim-core/src/cycle.rs +++ b/rust/fastsim-core/src/cycle.rs @@ -487,6 +487,7 @@ impl RustCycleCache { #[staticmethod] #[pyo3(name = "from_csv")] + #[pyo3(signature = (filepath, skip_init=None))] pub fn from_csv_py(filepath: &Bound, skip_init: Option) -> anyhow::Result { Self::from_csv_file(PathBuf::extract_bound(filepath)?, skip_init.unwrap_or_default()) } @@ -496,6 +497,7 @@ impl RustCycleCache { } #[staticmethod] + #[pyo3(signature = (dict, skip_init=None))] pub fn from_dict(dict: &Bound, skip_init: Option) -> PyResult { let time_s = Array::from_vec(dict.get_item("time_s")?.with_context(|| format_dbg!())?.extract()?); let cyc_len = time_s.len(); @@ -520,17 +522,8 @@ impl RustCycleCache { } else { Array::default(cyc_len) }, - // name: PyAny::get_item(dict, "name").and_then(String::extract).unwrap_or_default(), name: if let Ok(Some(item_res)) = dict.get_item("name") { - if let Ok(name) = item_res.extract() { - if let Ok(name_str) = String::extract(name) { - name_str - } else { - Default::default() - } - } else { - Default::default() - } + String::extract_bound(&item_res).unwrap_or_default() } else { Default::default() }, @@ -569,6 +562,7 @@ impl RustCycleCache { } #[pyo3(name = "modify_with_braking_trajectory")] + #[pyo3(signature = (brake_accel_m_per_s2, idx, dts_m=None))] pub fn modify_with_braking_trajectory_py( &mut self, brake_accel_m_per_s2: f64, diff --git a/rust/fastsim-core/src/simdrive.rs b/rust/fastsim-core/src/simdrive.rs index 26fcf0b6..ef8fef82 100644 --- a/rust/fastsim-core/src/simdrive.rs +++ b/rust/fastsim-core/src/simdrive.rs @@ -198,6 +198,7 @@ impl Default for RustSimDriveParams { } #[pyo3(name = "sim_drive")] + #[pyo3(signature = (init_soc=None, aux_in_kw_override=None))] /// Initialize and run sim_drive_walk as appropriate for vehicle attribute vehPtType. /// Arguments /// ------------ @@ -213,6 +214,7 @@ impl Default for RustSimDriveParams { self.sim_drive(init_soc, aux_in_kw_override) } + #[pyo3(signature = (init_soc, aux_in_kw_override=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 @@ -233,6 +235,7 @@ impl Default for RustSimDriveParams { self.walk(init_soc, aux_in_kw_override) } + #[pyo3(signature = (by_microtrip=None, extend_fraction=None, blend_factor=None, min_target_speed_m_per_s=None))] /// 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 @@ -257,6 +260,7 @@ impl Default for RustSimDriveParams { } #[pyo3(name = "init_for_step")] + #[pyo3(signature = (init_soc, aux_in_kw_override=None))] /// This is a specialty method which should be called prior to using /// sim_drive_step in a loop. /// Arguments diff --git a/rust/fastsim-core/src/simdrive/simdrive_iter.rs b/rust/fastsim-core/src/simdrive/simdrive_iter.rs index 98c5e88a..7b8e08ea 100644 --- a/rust/fastsim-core/src/simdrive/simdrive_iter.rs +++ b/rust/fastsim-core/src/simdrive/simdrive_iter.rs @@ -11,6 +11,7 @@ use rayon::prelude::*; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] #[add_pyo3_api( #[pyo3(name = "sim_drive")] + #[pyo3(signature = (parallelize=None))] /// Calls `sim_drive` method for each simdrive instance in vec. /// # Arguments: /// * parallelize: whether to parallelize `sim_drive` calls, defaults to `true` diff --git a/rust/fastsim-core/src/simdrivelabel.rs b/rust/fastsim-core/src/simdrivelabel.rs index 263d82d8..ea019e04 100644 --- a/rust/fastsim-core/src/simdrivelabel.rs +++ b/rust/fastsim-core/src/simdrivelabel.rs @@ -388,6 +388,7 @@ pub fn get_label_fe( #[cfg(feature = "pyo3")] #[pyfunction(name = "get_label_fe")] +#[pyo3(signature = (veh, full_detail=None, verbose=None))] /// pyo3 version of [get_label_fe] pub fn get_label_fe_py( veh: &vehicle::RustVehicle, diff --git a/rust/fastsim-core/src/thermal.rs b/rust/fastsim-core/src/thermal.rs index 794d04fe..c27e6801 100644 --- a/rust/fastsim-core/src/thermal.rs +++ b/rust/fastsim-core/src/thermal.rs @@ -14,6 +14,7 @@ use crate::vehicle_thermal::*; #[add_pyo3_api( /// method for instantiating SimDriveHot #[new] + #[pyo3(signature = (cyc, veh, vehthrm, init_state=None, amb_te_deg_c=None))] pub fn __new__( cyc: cycle::RustCycle, veh: vehicle::RustVehicle, @@ -30,6 +31,7 @@ use crate::vehicle_thermal::*; Ok(self.gap_to_lead_vehicle_m().to_vec()) } #[pyo3(name = "sim_drive")] + #[pyo3(signature = (init_soc=None, aux_in_kw_override=None))] /// Initialize and run sim_drive_walk as appropriate for vehicle attribute vehPtType. /// Arguments /// ------------ @@ -45,6 +47,7 @@ use crate::vehicle_thermal::*; self.sim_drive(init_soc, aux_in_kw_override) } + #[pyo3(signature = (init_soc, aux_in_kw_override=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 @@ -66,6 +69,7 @@ use crate::vehicle_thermal::*; } #[pyo3(name = "init_for_step")] + #[pyo3(signature = (init_soc, aux_in_kw_override=None))] /// This is a specialty method which should be called prior to using /// sim_drive_step in a loop. /// Arguments @@ -983,6 +987,13 @@ impl SimDriveHot { #[add_pyo3_api( #[new] + #[pyo3(signature = ( + amb_te_deg_c=None, + fc_te_deg_c_init=None, + cab_te_deg_c_init=None, + exhport_te_deg_c_init=None, + cat_te_deg_c_init=None, + ))] pub fn __new__( amb_te_deg_c: Option, fc_te_deg_c_init: Option, diff --git a/rust/fastsim-core/src/vehicle_import.rs b/rust/fastsim-core/src/vehicle_import.rs index dd8da853..18d907b0 100644 --- a/rust/fastsim-core/src/vehicle_import.rs +++ b/rust/fastsim-core/src/vehicle_import.rs @@ -286,6 +286,13 @@ pub struct VehicleDataEPA { impl SerdeAPI for VehicleDataEPA {} #[cfg_attr(feature = "pyo3", pyfunction)] +#[pyo3(signature = ( + year, + make, + model, + cache_url=None, + data_dir=None, +))] /// Gets options from fueleconomy.gov for the given vehicle year, make, and model /// /// Arguments: @@ -335,6 +342,12 @@ pub fn get_options_for_year_make_model( } #[cfg_attr(feature = "pyo3", pyfunction)] +#[pyo3(signature = ( + id, + year, + cache_url=None, + data_dir=None, +))] pub fn get_vehicle_data_for_id( id: i32, year: &str, @@ -720,6 +733,15 @@ fn match_epatest_with_fegov( #[derive(Default, PartialEq, Clone, Debug, Deserialize, Serialize)] #[add_pyo3_api( #[new] + #[pyo3(signature = ( + vehicle_width_in, + vehicle_height_in, + fuel_tank_gal, + ess_max_kwh, + mc_max_kw, + ess_max_kw, + fc_max_kw=None + ))] pub fn __new__( vehicle_width_in: f64, vehicle_height_in: f64, @@ -753,6 +775,13 @@ pub struct OtherVehicleInputs { impl SerdeAPI for OtherVehicleInputs {} #[cfg_attr(feature = "pyo3", pyfunction)] +#[pyo3(signature = ( + vehicle_id, + year, + other_inputs, + cache_url=None, + data_dir=None, +))] /// Creates RustVehicle for the given vehicle using data from fueleconomy.gov and EPA databases /// The created RustVehicle is also written as a yaml file /// @@ -1287,7 +1316,14 @@ fn load_fegov_data_for_given_years>( Ok(data) } #[cfg_attr(feature = "pyo3", pyfunction)] - +#[pyo3(signature = ( + year, + make, + model, + other_inputs, + cache_url=None, + data_dir=None, +))] /// Import All Vehicles for the given Year, Make, and Model and supplied other inputs pub fn import_all_vehicles( year: u32, diff --git a/rust/fastsim-core/src/vehicle_utils.rs b/rust/fastsim-core/src/vehicle_utils.rs index 0bdf4081..ad3615c2 100644 --- a/rust/fastsim-core/src/vehicle_utils.rs +++ b/rust/fastsim-core/src/vehicle_utils.rs @@ -27,6 +27,17 @@ pub const NETWORK_TEST_DISABLE_ENV_VAR_NAME: &str = "FASTSIM_DISABLE_NETWORK_TES #[cfg_attr(feature = "pyo3", pyfunction)] #[allow(clippy::too_many_arguments)] #[cfg(feature = "default")] +#[pyo3(signature = ( + veh, + a_lbf, + b_lbf__mph, + c_lbf__mph2, + custom_rho=None, + custom_rho_temp_degC=None, + custom_rho_elevation_m=None, + simdrive_optimize=None, + _show_plots=None, +))] pub fn abc_to_drag_coeffs( veh: &mut RustVehicle, a_lbf: f64, From 4517f3f981205333342e277247faf09b115f9af9 Mon Sep 17 00:00:00 2001 From: Chad Baker Date: Fri, 3 Jan 2025 09:33:46 -0700 Subject: [PATCH 4/5] rust-version = 1.83 for better warnings --- rust/Cargo.toml | 1 + rust/fastsim-cli/Cargo.toml | 1 + rust/fastsim-core/Cargo.toml | 1 + rust/fastsim-py/Cargo.toml | 1 + 4 files changed, 4 insertions(+) diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 8823a5a7..05ee09c7 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,5 +1,6 @@ [workspace] resolver = "2" +package.rust-version = "1.83" members = [ "fastsim-cli", # command line app diff --git a/rust/fastsim-cli/Cargo.toml b/rust/fastsim-cli/Cargo.toml index 37ead798..79043bd4 100644 --- a/rust/fastsim-cli/Cargo.toml +++ b/rust/fastsim-cli/Cargo.toml @@ -2,6 +2,7 @@ name = "fastsim-cli" version = "0.1.0" edition = "2021" +rust-version.workspace = true license = "Apache-2.0" authors = ["NREL/MTES/CIMS/MBAP Group "] description = "CLI app for FASTSim models for vehicle energy usage simulation" diff --git a/rust/fastsim-core/Cargo.toml b/rust/fastsim-core/Cargo.toml index b8639323..5293fc30 100644 --- a/rust/fastsim-core/Cargo.toml +++ b/rust/fastsim-core/Cargo.toml @@ -2,6 +2,7 @@ name = "fastsim-core" version = "0.1.7" edition = "2021" +rust-version.workspace = true license = "Apache-2.0" authors = ["NREL/MTES/CIMS/MBAP Group "] description = "Core FASTSim models for vehicle energy usage simulation" diff --git a/rust/fastsim-py/Cargo.toml b/rust/fastsim-py/Cargo.toml index c067a7da..74d553f3 100644 --- a/rust/fastsim-py/Cargo.toml +++ b/rust/fastsim-py/Cargo.toml @@ -2,6 +2,7 @@ name = "fastsim-py" version = "0.1.0" edition = "2021" +rust-version.workspace = true license = "Apache-2.0" authors = ["NREL/MTES/CIMS/MBAP Group "] description = "Python API for FASTSim models for vehicle energy usage simulation" From 708ee6ab5932ba513828550119fa831e08caec21 Mon Sep 17 00:00:00 2001 From: Chad Baker Date: Fri, 3 Jan 2025 09:34:12 -0700 Subject: [PATCH 5/5] pyo3 = 0.23.3, latest release --- rust/Cargo.toml | 2 +- rust/fastsim-core/src/cycle.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 05ee09c7..c99ffb22 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -18,7 +18,7 @@ codegen-units = 1 # optimize connection between modules [workspace.dependencies] anyhow = "1.0.57" ndarray = { version = "0.15.4", features = ["serde"] } -pyo3 = "0.22.4" +pyo3 = "0.23.3" pyo3-log = "*" serde = "1.0.143" serde_json = "1.0.83" diff --git a/rust/fastsim-core/src/cycle.rs b/rust/fastsim-core/src/cycle.rs index 678bd906..51ba3b58 100644 --- a/rust/fastsim-core/src/cycle.rs +++ b/rust/fastsim-core/src/cycle.rs @@ -536,7 +536,7 @@ impl RustCycleCache { } pub fn to_dict<'py>(&self, py: Python<'py>) -> anyhow::Result> { - let dict = PyDict::new_bound(py); + let dict = PyDict::new(py); dict.set_item("time_s", self.time_s.to_vec())?; dict.set_item("mps", self.mps.to_vec())?; dict.set_item("grade", self.grade.to_vec())?;