altrios_core/train/resistance/method/
point.rs

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