altrios_core/train/resistance/method/
strap.rs1use 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!())? .with_context(|| "{}\nExpected `Some`.")? * 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}