1pub const GRAVITY_MM_S2: f64 = 9_806.65;
2
3#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
6pub enum ConcreteClass {
7 #[default]
8 Normal,
9 Lightweight1,
10 Lightweight2,
11}
12
13#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
15pub enum ConcreteComposition {
16 Plain,
18 #[default]
20 Rc,
21 Src,
23}
24
25pub fn concrete_unit_weight_kn_m3(fc: f64, class: ConcreteClass, comp: ConcreteComposition) -> f64 {
29 let gamma_c = match class {
30 ConcreteClass::Normal => {
31 if fc <= 36.0 {
32 23.0
33 } else if fc <= 48.0 {
34 23.5
35 } else if fc <= 120.0 {
36 24.0
37 } else {
38 24.5
39 }
40 }
41 ConcreteClass::Lightweight1 => {
42 if fc <= 27.0 {
43 19.0
44 } else {
45 20.0
46 }
47 }
48 ConcreteClass::Lightweight2 => 17.0,
49 };
50 match (class, comp) {
52 (ConcreteClass::Lightweight1, ConcreteComposition::Rc) if fc > 27.0 => 22.0,
53 (ConcreteClass::Lightweight1, ConcreteComposition::Src) if fc > 27.0 => 23.0,
54 (_, ConcreteComposition::Plain) => gamma_c,
55 (_, ConcreteComposition::Rc) => gamma_c + 1.0,
56 (_, ConcreteComposition::Src) => gamma_c + 2.0,
57 }
58}
59
60pub const STEEL_UNIT_WEIGHT_KN_M3: f64 = 77.0;
62
63pub const STEEL_UNIT_WEIGHT_TAKEOFF_T_M3: f64 = 7.85;
70
71pub mod to_internal {
72 pub fn length_m(m: f64) -> f64 {
73 m * 1_000.0
74 }
75 pub fn force_kn(kn: f64) -> f64 {
76 kn * 1_000.0
77 }
78 pub fn stiffness_kn_per_mm(kn_per_mm: f64) -> f64 {
80 kn_per_mm * 1_000.0
81 }
82 pub fn viscous_c0_kn(c0_kn: f64) -> f64 {
84 c0_kn * 1_000.0
85 }
86 pub fn line_load_kn_per_m(v: f64) -> f64 {
87 v
88 }
89 pub fn area_load_kn_per_m2(v: f64) -> f64 {
90 v / 1_000.0
91 }
92 pub fn stress_n_per_mm2(v: f64) -> f64 {
93 v
94 }
95 pub fn mass_density_g_per_cm3(v: f64) -> f64 {
96 v * 1.0e-9
97 }
98 pub fn unit_weight_kn_per_m3(v: f64) -> f64 {
99 v * 1.0e-6
100 }
101 pub fn weight_n_to_mass(w_n: f64) -> f64 {
102 w_n / super::GRAVITY_MM_S2
103 }
104 pub fn mass_density_from_unit_weight_kn_m3(v: f64) -> f64 {
107 unit_weight_kn_per_m3(v) / super::GRAVITY_MM_S2
108 }
109}
110
111pub mod to_display {
121 pub const LABEL_FORCE: &str = "kN";
123 pub const LABEL_MOMENT: &str = "kN·m";
125 pub const LABEL_LENGTH: &str = "m";
127 pub const LABEL_LENGTH_MM: &str = "mm";
129 pub const LABEL_STRESS: &str = "N/mm²";
131 pub const LABEL_AREA: &str = "cm²";
133 pub const LABEL_INERTIA: &str = "cm⁴";
135 pub const LABEL_MODULUS: &str = "cm³";
137 pub const LABEL_RADIUS: &str = "cm";
139 pub const LABEL_STIFFNESS: &str = "kN/mm";
141 pub const LABEL_AREA_LOAD: &str = "kN/m²";
143 pub const LABEL_MOMENT_PER_WIDTH: &str = "kN·m/m";
145 pub const LABEL_VISCOUS_C0: &str = "kN·(s/mm)^α";
147
148 pub fn force_kn(n: f64) -> f64 {
150 n / 1_000.0
151 }
152
153 pub fn moment_kn_m(n_mm: f64) -> f64 {
155 n_mm / 1.0e6
156 }
157
158 pub fn length_m(mm: f64) -> f64 {
160 mm / 1_000.0
161 }
162
163 pub fn stiffness_kn_per_mm(n_per_mm: f64) -> f64 {
165 n_per_mm / 1_000.0
166 }
167
168 pub fn area_load_kn_per_m2(n_per_mm2: f64) -> f64 {
170 n_per_mm2 * 1_000.0
171 }
172
173 pub fn moment_kn_m_per_m(n_mm_per_mm: f64) -> f64 {
175 n_mm_per_mm / 1_000.0
176 }
177
178 pub fn viscous_c0_kn(c0_n: f64) -> f64 {
180 c0_n / 1_000.0
181 }
182
183 pub fn area_cm2(mm2: f64) -> f64 {
185 mm2 / 1.0e2
186 }
187
188 pub fn inertia_cm4(mm4: f64) -> f64 {
190 mm4 / 1.0e4
191 }
192
193 pub fn modulus_cm3(mm3: f64) -> f64 {
195 mm3 / 1.0e3
196 }
197
198 pub fn radius_cm(mm: f64) -> f64 {
200 mm / 1.0e1
201 }
202}
203
204#[cfg(test)]
205mod tests {
206 use super::*;
207 use approx::assert_relative_eq;
208
209 #[test]
210 fn test_unit_conversions() {
211 assert_relative_eq!(to_internal::length_m(6.0), 6000.0, max_relative = 1e-12);
212 assert_relative_eq!(
213 to_internal::line_load_kn_per_m(10.0),
214 10.0,
215 max_relative = 1e-12
216 );
217 assert_relative_eq!(to_internal::force_kn(50.0), 50000.0, max_relative = 1e-12);
218 assert_relative_eq!(
219 to_internal::stiffness_kn_per_mm(10.0),
220 10000.0,
221 max_relative = 1e-12
222 );
223 assert_relative_eq!(
224 to_display::stiffness_kn_per_mm(10000.0),
225 10.0,
226 max_relative = 1e-12
227 );
228 assert_relative_eq!(
229 to_display::area_load_kn_per_m2(0.0029),
230 2.9,
231 max_relative = 1e-12
232 );
233 assert_relative_eq!(
234 to_internal::area_load_kn_per_m2(2.9),
235 0.0029,
236 max_relative = 1e-12
237 );
238 assert_relative_eq!(
239 to_display::moment_kn_m_per_m(5000.0),
240 5.0,
241 max_relative = 1e-12
242 );
243 assert_relative_eq!(to_display::viscous_c0_kn(1000.0), 1.0, max_relative = 1e-12);
244 assert_relative_eq!(
245 to_internal::viscous_c0_kn(1.0),
246 1000.0,
247 max_relative = 1e-12
248 );
249 assert_relative_eq!(
250 to_internal::stress_n_per_mm2(24.0),
251 24.0,
252 max_relative = 1e-12
253 );
254 assert_relative_eq!(
255 to_internal::mass_density_g_per_cm3(2.4),
256 2.4e-9,
257 max_relative = 1e-12
258 );
259 assert_relative_eq!(
260 to_internal::unit_weight_kn_per_m3(24.0),
261 2.4e-5,
262 max_relative = 1e-12
263 );
264 assert_relative_eq!(
265 to_internal::weight_n_to_mass(1.0e6),
266 101.971_621_297_792_82,
267 max_relative = 1e-12
268 );
269 }
270
271 #[test]
272 fn test_concrete_unit_weight_table() {
273 use ConcreteClass::*;
274 use ConcreteComposition::*;
275 assert_eq!(concrete_unit_weight_kn_m3(24.0, Normal, Plain), 23.0);
277 assert_eq!(concrete_unit_weight_kn_m3(24.0, Normal, Rc), 24.0);
278 assert_eq!(concrete_unit_weight_kn_m3(24.0, Normal, Src), 25.0);
279 assert_eq!(concrete_unit_weight_kn_m3(42.0, Normal, Rc), 24.5);
280 assert_eq!(concrete_unit_weight_kn_m3(60.0, Normal, Rc), 25.0);
281 assert_eq!(concrete_unit_weight_kn_m3(100.0, Normal, Rc), 25.0);
282 assert_eq!(concrete_unit_weight_kn_m3(150.0, Normal, Rc), 25.5);
283 assert_eq!(concrete_unit_weight_kn_m3(24.0, Lightweight1, Rc), 20.0);
285 assert_eq!(concrete_unit_weight_kn_m3(30.0, Lightweight1, Rc), 22.0);
286 assert_eq!(concrete_unit_weight_kn_m3(30.0, Lightweight1, Src), 23.0);
287 assert_eq!(concrete_unit_weight_kn_m3(21.0, Lightweight2, Rc), 18.0);
288 }
289
290 #[test]
291 fn test_mass_density_from_unit_weight() {
292 let rho = to_internal::mass_density_from_unit_weight_kn_m3(24.0);
294 assert_relative_eq!(rho, 24.0e-6 / GRAVITY_MM_S2, max_relative = 1e-12);
295 assert!((rho - 2.4473e-9).abs() / rho < 1e-3);
296 }
297}