fastsim_core/vehicle/powertrain/
transmission.rs1use super::*;
2
3#[serde_api]
4#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, StateMethods, SetCumulative)]
5#[non_exhaustive]
6#[serde(deny_unknown_fields)]
7pub struct Transmission {
8 #[serde(default)]
10 pub(crate) mass: Option<si::Mass>,
11
12 pub eff_interp: Interpolator,
15
16 pub save_interval: Option<usize>,
18 #[serde(default)]
20 pub state: TransmissionState,
21 #[serde(default, skip_serializing_if = "TransmissionStateHistoryVec::is_empty")]
23 pub history: TransmissionStateHistoryVec,
24}
25
26impl Transmission {
27 pub fn get_pwr_in_req(&mut self, pwr_out_req: si::Power) -> anyhow::Result<si::Power> {
28 let state = &mut self.state;
29
30 state.eff.update(
31 match self.eff_interp {
32 Interpolator::Interp0D(eff) => eff * uc::R,
33 _ => unimplemented!(),
34 },
35 || format_dbg!(),
36 )?;
37 ensure!(
38 *state.eff.get_fresh(|| format_dbg!())? >= 0.0 * uc::R
39 && *state.eff.get_fresh(|| format_dbg!())? <= 1.0 * uc::R,
40 format!(
41 "{}\nTransmission efficiency ({}) must be between 0 and 1",
42 format_dbg!(
43 *state.eff.get_fresh(|| format_dbg!())? >= 0.0 * uc::R
44 && *state.eff.get_fresh(|| format_dbg!())? <= 1.0 * uc::R
45 ),
46 state.eff.get_fresh(|| format_dbg!())?.get::<si::ratio>()
47 )
48 );
49
50 state.pwr_out.update(pwr_out_req, || format_dbg!())?;
51 state.pwr_in.update(
52 if *state.pwr_out.get_fresh(|| format_dbg!())? > si::Power::ZERO {
53 *state.pwr_out.get_fresh(|| format_dbg!())?
54 / *state.eff.get_fresh(|| format_dbg!())?
55 } else {
56 *state.pwr_out.get_fresh(|| format_dbg!())?
57 * *state.eff.get_fresh(|| format_dbg!())?
58 },
59 || format_dbg!(),
60 )?;
61 state.pwr_loss.update(
62 (*state.pwr_in.get_fresh(|| format_dbg!())?
63 - *state.pwr_out.get_fresh(|| format_dbg!())?)
64 .abs(),
65 || format_dbg!(),
66 )?;
67
68 Ok(*state.pwr_in.get_fresh(|| format_dbg!())?)
69 }
70}
71impl HistoryMethods for Transmission {
72 fn save_interval(&self) -> anyhow::Result<Option<usize>> {
73 Ok(self.save_interval)
74 }
75 fn set_save_interval(&mut self, save_interval: Option<usize>) -> anyhow::Result<()> {
76 self.save_interval = save_interval;
77 Ok(())
78 }
79 fn clear(&mut self) {
80 self.history.clear()
81 }
82}
83impl SerdeAPI for Transmission {}
84impl Init for Transmission {}
85
86impl Mass for Transmission {
87 fn mass(&self) -> anyhow::Result<Option<si::Mass>> {
88 Ok(self.mass)
89 }
90
91 fn set_mass(
93 &mut self,
94 new_mass: Option<si::Mass>,
95 _side_effect: MassSideEffect,
96 ) -> anyhow::Result<()> {
97 self.mass = new_mass;
98
99 Ok(())
100 }
101
102 fn derived_mass(&self) -> anyhow::Result<Option<si::Mass>> {
104 Ok(self.mass)
105 }
106
107 fn expunge_mass_fields(&mut self) {
108 self.mass = None;
109 }
110}
111
112#[serde_api]
113#[derive(
114 Clone,
115 Default,
116 Debug,
117 Deserialize,
118 Serialize,
119 PartialEq,
120 HistoryVec,
121 StateMethods,
122 SetCumulative,
123)]
124#[non_exhaustive]
125#[serde(default)]
126#[serde(deny_unknown_fields)]
127pub struct TransmissionState {
128 pub i: TrackedState<usize>,
130
131 pub eff: TrackedState<si::Ratio>,
132
133 pub pwr_out: TrackedState<si::Power>,
134 pub pwr_in: TrackedState<si::Power>,
135 pub pwr_loss: TrackedState<si::Power>,
137
138 pub energy_out: TrackedState<si::Energy>,
139 pub energy_loss: TrackedState<si::Energy>,
140}
141
142impl Init for TransmissionState {}
143impl SerdeAPI for TransmissionState {}