altrios_core/train/resistance/method/
strap.rs

1use super::super::kind::*;
2use super::super::ResMethod;
3use crate::imports::*;
4use crate::track::{LinkPoint, PathResCoeff, PathTpc};
5use crate::train::TrainState;
6
7#[serde_api]
8#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
9#[cfg_attr(feature = "pyo3", pyclass(module = "altrios", subclass, eq))]
10pub struct Strap {
11    bearing: bearing::Basic,
12    rolling: rolling::Basic,
13    davis_b: davis_b::Basic,
14    aerodynamic: aerodynamic::Basic,
15    grade: path_res::Strap,
16    curve: path_res::Strap,
17}
18
19#[pyo3_api]
20impl Strap {}
21
22impl Init for Strap {}
23impl SerdeAPI for Strap {}
24
25impl Strap {
26    pub fn new(
27        bearing: bearing::Basic,
28        rolling: rolling::Basic,
29        davis_b: davis_b::Basic,
30        aerodynamic: aerodynamic::Basic,
31        grade: path_res::Strap,
32        curve: path_res::Strap,
33    ) -> Self {
34        Self {
35            bearing,
36            rolling,
37            davis_b,
38            aerodynamic,
39            grade,
40            curve,
41        }
42    }
43}
44impl ResMethod for Strap {
45    fn update_res(
46        &mut self,
47        state: &mut TrainState,
48        path_tpc: &PathTpc,
49        dir: &Dir,
50    ) -> anyhow::Result<()> {
51        state.offset_back.update_unchecked(
52            *state.offset.get_unchecked(|| format_dbg!())?
53                - *state.length.get_unchecked(|| format_dbg!())?,
54            || format_dbg!(),
55        )?;
56        state.weight_static.update_unchecked(
57            state
58                .mass()
59                .with_context(|| format_dbg!())? // extract result
60                .with_context(|| "{}\nExpected `Some`.")? // extract option
61                * uc::ACC_GRAV,
62            || format_dbg!(),
63        )?;
64        state
65            .res_bearing
66            .update_unchecked(self.bearing.calc_res(), || format_dbg!())?;
67        state
68            .res_rolling
69            .update_unchecked(self.rolling.calc_res(state)?, || format_dbg!())?;
70        state
71            .res_davis_b
72            .update_unchecked(self.davis_b.calc_res(state)?, || format_dbg!())?;
73        state
74            .res_aero
75            .update_unchecked(self.aerodynamic.calc_res(state)?, || format_dbg!())?;
76        state.res_grade.update_unchecked(
77            self.grade.calc_res(path_tpc.grades(), state, dir)?,
78            || format_dbg!(),
79        )?;
80        state.res_curve.update_unchecked(
81            self.curve.calc_res(path_tpc.curves(), state, dir)?,
82            || format_dbg!(),
83        )?;
84        state.grade_front.update_unchecked(
85            self.grade.res_coeff_front(path_tpc.grades()),
86            || format_dbg!(),
87        )?;
88        state.grade_back.update_unchecked(
89            self.grade.res_coeff_back(path_tpc.grades()),
90            || format_dbg!(),
91        )?;
92        state.elev_front.update_unchecked(
93            self.grade.res_net_front(path_tpc.grades(), state)?,
94            || format_dbg!(),
95        )?;
96        state.elev_back.update_unchecked(
97            self.grade.res_net_back(path_tpc.grades(), state)?,
98            || format_dbg!(),
99        )?;
100        Ok(())
101    }
102
103    fn fix_cache(&mut self, link_point_del: &LinkPoint) {
104        self.grade.fix_cache(link_point_del.grade_count);
105        self.curve.fix_cache(link_point_del.curve_count);
106    }
107}
108impl Valid for Strap {
109    fn valid() -> Self {
110        Self {
111            bearing: bearing::Basic::new(40.0 * 100.0 * uc::LBF),
112            rolling: rolling::Basic::new(1.5 * uc::LB / uc::TON),
113            davis_b: davis_b::Basic::new(0.03 / uc::MPH * uc::LB / uc::TON),
114            aerodynamic: aerodynamic::Basic::new(
115                5.0 * 100.0 * uc::FT2 / 10000.0 / 1.225 * uc::MPS / uc::MPH * uc::MPS / uc::MPH
116                    * uc::LBF
117                    / uc::N
118                    * 100.0,
119            ),
120            grade: path_res::Strap::new(&Vec::<PathResCoeff>::valid(), &TrainState::valid())
121                .unwrap(),
122            curve: path_res::Strap::new(&Vec::<PathResCoeff>::valid(), &TrainState::valid())
123                .unwrap(),
124        }
125    }
126}