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

PhantomData in structs to prevent outside instantiation #172

Merged
merged 4 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 fastsim-core/src/air_properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ lazy_static! {

)]
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, HistoryMethods)]
#[non_exhaustive]
pub struct Air {}
impl Init for Air {}
impl SerdeAPI for Air {}
Expand Down
2 changes: 2 additions & 0 deletions fastsim-core/src/drive_cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use fastsim_2::cycle::RustCycle as Cycle2;
}
)]
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)]
#[non_exhaustive]
/// Container
pub struct Cycle {
/// Name of cycle (can be left empty)
Expand Down Expand Up @@ -402,6 +403,7 @@ impl Cycle {

#[fastsim_api]
#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Clone)]
#[non_exhaustive]
/// Element of `Cycle`. Used for vec-like operations.
pub struct CycleElement {
/// simulation time \[s\]
Expand Down
21 changes: 8 additions & 13 deletions fastsim-core/src/simdrive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::prelude::*;

#[fastsim_api]
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, HistoryMethods)]
#[non_exhaustive]
/// Solver parameters
pub struct SimParams {
pub ach_speed_max_iter: u32,
Expand Down Expand Up @@ -39,11 +40,11 @@ impl Default for SimParams {
#[fastsim_api(
#[new]
fn __new__(veh: Vehicle, cyc: Cycle, sim_params: Option<SimParams>) -> anyhow::Result<Self> {
Ok(SimDrive{
Ok(SimDrive::new(
veh,
cyc,
sim_params: sim_params.unwrap_or_default(),
})
sim_params,
))
}

/// Run vehicle simulation once
Expand All @@ -67,6 +68,7 @@ impl Default for SimParams {

)]
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, HistoryMethods)]
#[non_exhaustive]
pub struct SimDrive {
#[has_state]
pub veh: Vehicle,
Expand Down Expand Up @@ -474,6 +476,7 @@ pwr deficit: {} kW
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, HistoryMethods)]
#[non_exhaustive]
pub struct TraceMissTolerance {
tol_dist: si::Length,
tol_dist_frac: si::Ratio,
Expand Down Expand Up @@ -520,11 +523,7 @@ mod tests {
fn test_sim_drive_conv() {
let _veh = mock_conv_veh();
let _cyc = Cycle::from_resource("udds.csv", false).unwrap();
let mut sd = SimDrive {
veh: _veh,
cyc: _cyc,
sim_params: Default::default(),
};
let mut sd = SimDrive::new(_veh, _cyc, Default::default());
sd.walk().unwrap();
assert!(sd.veh.state.i == sd.cyc.len());
assert!(sd.veh.fc().unwrap().state.energy_fuel > si::Energy::ZERO);
Expand All @@ -535,11 +534,7 @@ mod tests {
fn test_sim_drive_hev() {
let _veh = mock_hev();
let _cyc = Cycle::from_resource("udds.csv", false).unwrap();
let mut sd = SimDrive {
veh: _veh,
cyc: _cyc,
sim_params: Default::default(),
};
let mut sd = SimDrive::new(_veh, _cyc, Default::default());
sd.walk().unwrap();
assert!(sd.veh.state.i == sd.cyc.len());
assert!(sd.veh.fc().unwrap().state.energy_fuel > si::Energy::ZERO);
Expand Down
1 change: 1 addition & 0 deletions fastsim-core/src/vehicle/bev.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::*;

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, HistoryMethods)]
#[non_exhaustive]
/// Battery electric vehicle
pub struct BatteryElectricVehicle {
#[has_state]
Expand Down
1 change: 1 addition & 0 deletions fastsim-core/src/vehicle/cabin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ impl SerdeAPI for CabinOption {}

#[fastsim_api]
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, HistoryMethods)]
#[non_exhaustive]
/// Basic single thermal capacitance cabin thermal model, including HVAC
/// system and controls
pub struct SingleCapacitanceCabin {
Expand Down
1 change: 1 addition & 0 deletions fastsim-core/src/vehicle/chassis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ impl Init for DriveTypes {}

#[fastsim_api]
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize, HistoryMethods)]
#[non_exhaustive]
/// Struct for simulating vehicle
pub struct Chassis {
/// Aerodynamic drag coefficient
Expand Down
1 change: 1 addition & 0 deletions fastsim-core/src/vehicle/conv.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::*;

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, HistoryMethods)]
#[non_exhaustive]
/// Conventional vehicle with only a FuelConverter as a power source
pub struct ConventionalVehicle {
pub fs: FuelStorage,
Expand Down
5 changes: 5 additions & 0 deletions fastsim-core/src/vehicle/hev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::{vehicle_model::VehicleState, *};
use crate::prelude::ElectricMachineState;

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, HistoryMethods)]
#[non_exhaustive]
/// Hybrid vehicle with both engine and reversible energy storage (aka battery)
/// This type of vehicle is not likely to be widely prevalent due to modularity of consists.
pub struct HybridElectricVehicle {
Expand Down Expand Up @@ -288,6 +289,7 @@ impl Mass for HybridElectricVehicle {

#[fastsim_api]
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
#[non_exhaustive]
pub struct FCOnCauses(Vec<FCOnCause>);
impl Init for FCOnCauses {}
impl SerdeAPI for FCOnCauses {}
Expand All @@ -309,6 +311,7 @@ impl FCOnCauses {
// TODO: figure out why this is not turning in the dataframe but is in teh pydict
#[fastsim_api]
#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, HistoryVec, SetCumulative)]
#[non_exhaustive]
pub struct HEVState {
/// time step index
pub i: usize,
Expand Down Expand Up @@ -381,6 +384,7 @@ impl fmt::Display for FCOnCause {

/// Options for controlling simulation behavior
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[non_exhaustive]
pub struct HEVSimulationParams {
/// [ReversibleEnergyStorage] per [FuelConverter]
pub res_per_fuel_lim: si::Ratio,
Expand Down Expand Up @@ -555,6 +559,7 @@ impl HEVPowertrainControls {
/// Container for static controls parameters. See [Self::init] for default
/// values.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Default)]
#[non_exhaustive]
pub struct RESGreedyWithDynamicBuffers {
/// RES energy delta from minimum SOC corresponding to kinetic energy of
/// vehicle at this speed that triggers ramp down in RES discharge.
Expand Down
29 changes: 17 additions & 12 deletions fastsim-core/src/vehicle/powertrain/electric_machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ use crate::pyo3::*;
// }
)]
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, HistoryMethods)]
#[non_exhaustive]
/// Struct for modeling electric machines. This lumps performance and efficiency of motor and power
/// electronics.
pub struct ElectricMachine {
Expand Down Expand Up @@ -142,10 +143,12 @@ impl ElectricMachine {
.eff_interp_at_max_input
.as_ref()
.map(|interpolator| {
interpolator.interpolate(&[abs_checked_x_val(
(pwr_in_fwd_lim / self.pwr_out_max).get::<si::ratio>(),
interpolator.x().map_err(|e| anyhow!(e))?,
)?]).map_err(|e| anyhow!(e))
interpolator
.interpolate(&[abs_checked_x_val(
(pwr_in_fwd_lim / self.pwr_out_max).get::<si::ratio>(),
interpolator.x().map_err(|e| anyhow!(e))?,
)?])
.map_err(|e| anyhow!(e))
})
.ok_or(anyhow!(
"eff_interp_bwd is None, which should never be the case at this point."
Expand All @@ -162,10 +165,12 @@ impl ElectricMachine {
.eff_interp_at_max_input
.as_ref()
.map(|interpolator| {
interpolator.interpolate(&[abs_checked_x_val(
(pwr_in_bwd_lim / self.pwr_out_max).get::<si::ratio>(),
interpolator.x().map_err(|e| anyhow!(e))?,
)?]).map_err(|e| anyhow!(e))
interpolator
.interpolate(&[abs_checked_x_val(
(pwr_in_bwd_lim / self.pwr_out_max).get::<si::ratio>(),
interpolator.x().map_err(|e| anyhow!(e))?,
)?])
.map_err(|e| anyhow!(e))
})
.ok_or(anyhow!(
"eff_interp_bwd is None, which should never be the case at this point."
Expand Down Expand Up @@ -328,9 +333,7 @@ impl Init for ElectricMachine {
self.eff_interp_fwd.strategy()?.to_owned(),
self.eff_interp_fwd.extrapolate()?.to_owned(),
)?;
self.eff_interp_at_max_input = Some(Interpolator::Interp1D(
eff_interp_at_max_input,
));
self.eff_interp_at_max_input = Some(Interpolator::Interp1D(eff_interp_at_max_input));
}
Ok(())
}
Expand Down Expand Up @@ -447,7 +450,8 @@ impl ElectricMachine {
.ok_or(anyhow!(
"eff_interp_bwd is None, which should never be the case at this point."
))?
.f_x()?.to_owned();
.f_x()?
.to_owned();
match &mut self.eff_interp_at_max_input {
Some(Interpolator::Interp1D(interp1d)) => {
// let old_interp = interp1d;
Expand Down Expand Up @@ -628,6 +632,7 @@ impl ElectricMachine {
#[derive(
Clone, Copy, Debug, Default, Deserialize, Serialize, PartialEq, HistoryVec, SetCumulative,
)]
#[non_exhaustive]
pub struct ElectricMachineState {
/// time step index
pub i: usize,
Expand Down
7 changes: 3 additions & 4 deletions fastsim-core/src/vehicle/powertrain/fuel_converter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ use super::*;
}
)]
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, HistoryMethods)]
#[non_exhaustive]
/// Struct for modeling Fuel Converter (e.g. engine, fuel cell.)
pub struct FuelConverter {
/// [Self] Thermal plant, including thermal management controls
Expand Down Expand Up @@ -87,10 +88,6 @@ pub struct FuelConverter {
#[serde(default)]
#[serde(skip_serializing_if = "FuelConverterStateHistoryVec::is_empty")]
pub history: FuelConverterStateHistoryVec,
#[serde(skip)]
// phantom private field to prevent direct instantiation in other modules
#[api(skip_get, skip_set)]
pub(in super::super) _phantom: PhantomData<()>,
}

impl SetCumulative for FuelConverter {
Expand Down Expand Up @@ -339,6 +336,7 @@ impl FuelConverter {
#[derive(
Clone, Copy, Debug, Default, Deserialize, Serialize, PartialEq, HistoryVec, SetCumulative,
)]
#[non_exhaustive]
pub struct FuelConverterState {
/// time step index
pub i: usize,
Expand Down Expand Up @@ -395,6 +393,7 @@ impl SerdeAPI for FuelConverterThermalOption {}

#[fastsim_api]
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, HistoryMethods)]
#[non_exhaustive]
/// Struct for modeling Fuel Converter (e.g. engine, fuel cell.)
pub struct FuelConverterThermal {
/// [FuelConverter] thermal capacitance
Expand Down
1 change: 1 addition & 0 deletions fastsim-core/src/vehicle/powertrain/fuel_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use super::*;
// }
)]
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)]
#[non_exhaustive]
pub struct FuelStorage {
/// max power output
pub pwr_out_max: si::Power,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ const TOL: f64 = 1e-3;
}
)]
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, HistoryMethods)]
#[non_exhaustive]
/// Struct for modeling technology-naive Reversible Energy Storage (e.g. battery, flywheel).
pub struct ReversibleEnergyStorage {
/// ReversibleEnergyStorage mass
Expand Down Expand Up @@ -568,6 +569,7 @@ pub enum SpecificEnergySideEffect {

#[fastsim_api]
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, HistoryVec, SetCumulative)]
#[non_exhaustive]
// component limits
/// ReversibleEnergyStorage state variables
pub struct ReversibleEnergyStorageState {
Expand Down
2 changes: 2 additions & 0 deletions fastsim-core/src/vehicle/powertrain/transmission.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::*;

#[fastsim_api]
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, HistoryMethods)]
#[non_exhaustive]
pub struct Transmission {
/// Transmission mass
#[serde(default)]
Expand Down Expand Up @@ -86,6 +87,7 @@ impl Mass for Transmission {

#[fastsim_api]
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, HistoryVec, SetCumulative)]
#[non_exhaustive]
pub struct TransmissionState {
/// time step index
pub i: usize,
Expand Down
20 changes: 5 additions & 15 deletions fastsim-core/src/vehicle/vehicle_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ impl Init for AuxSource {}
}
)]
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize, HistoryMethods)]
#[non_exhaustive]
/// Struct for simulating vehicle
pub struct Vehicle {
/// Vehicle name
Expand Down Expand Up @@ -438,6 +439,7 @@ impl Vehicle {
/// Vehicle state for current time step
#[fastsim_api]
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, HistoryVec, SetCumulative)]
#[non_exhaustive]
pub struct VehicleState {
/// time step index
pub i: usize,
Expand Down Expand Up @@ -613,11 +615,7 @@ pub(crate) mod tests {
fn test_to_fastsim2_conv() {
let veh = mock_conv_veh();
let cyc = crate::drive_cycle::Cycle::from_resource("udds.csv", false).unwrap();
let sd = crate::simdrive::SimDrive {
veh,
cyc,
sim_params: Default::default(),
};
let sd = crate::simdrive::SimDrive::new(veh, cyc, Default::default());
let mut sd2 = sd.to_fastsim2().unwrap();
sd2.sim_drive(None, None).unwrap();
}
Expand All @@ -627,11 +625,7 @@ pub(crate) mod tests {
fn test_to_fastsim2_hev() {
let veh = mock_hev();
let cyc = crate::drive_cycle::Cycle::from_resource("udds.csv", false).unwrap();
let sd = crate::simdrive::SimDrive {
veh,
cyc,
sim_params: Default::default(),
};
let sd = crate::simdrive::SimDrive::new(veh, cyc, Default::default());
let mut sd2 = sd.to_fastsim2().unwrap();
sd2.sim_drive(None, None).unwrap();
}
Expand All @@ -641,11 +635,7 @@ pub(crate) mod tests {
fn test_to_fastsim2_bev() {
let veh = mock_bev();
let cyc = crate::drive_cycle::Cycle::from_resource("udds.csv", false).unwrap();
let sd = crate::simdrive::SimDrive {
veh,
cyc,
sim_params: Default::default(),
};
let sd = crate::simdrive::SimDrive::new(veh, cyc, Default::default());
let mut sd2 = sd.to_fastsim2().unwrap();
sd2.sim_drive(None, None).unwrap();
}
Expand Down
2 changes: 0 additions & 2 deletions fastsim-core/src/vehicle/vehicle_model/fastsim2_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ impl TryFrom<&fastsim_2::vehicle::RustVehicle> for PowertrainType {
pwr_idle_fuel: si::Power::ZERO,
save_interval: Some(1),
history: Default::default(),
_phantom: PhantomData,
};
fc.init()?;
fc.set_mass(None, MassSideEffect::None)
Expand Down Expand Up @@ -148,7 +147,6 @@ impl TryFrom<&fastsim_2::vehicle::RustVehicle> for PowertrainType {
pwr_idle_fuel: si::Power::ZERO,
save_interval: Some(1),
history: Default::default(),
_phantom: PhantomData,
};
fc.init()?;
fc.set_mass(None, MassSideEffect::None)
Expand Down
Loading