hpr_design/finish.rs
1//! Surface finishes: the roughness height that limits a surface's skin friction.
2//!
3//! The named finishes are the rows of Barrowman 1967 Table 4-1 ("Approximate Surface Roughness
4//! Heights of Physical Surfaces", p. 46, after Hoerner, *Fluid-Dynamic Drag*, 1965, p. 5-3).
5//! Niskanen 2009 Table 3.2 (p. 44) reprints ten of its fifteen rows with the same heights. Any
6//! other roughness is a [`Finish::Custom`] height. See `docs/physics/aero.md`.
7
8use serde::{Deserialize, Serialize};
9
10use crate::error::DesignError;
11use crate::shapes::check_dimension;
12
13/// A surface finish, by its roughness height `R_s`.
14#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
15#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
16#[non_exhaustive]
17pub enum Finish {
18 /// A mirror-like surface, 0 µm (Barrowman Table 4-1).
19 Mirror {},
20 /// Average glass, 0.1 µm.
21 AverageGlass {},
22 /// A finished and polished surface, 0.5 µm.
23 Polished {},
24 /// An aircraft-type sheet-metal surface, 2 µm (Barrowman Table 4-1 only).
25 SheetMetal {},
26 /// An optimum paint-sprayed surface, 5 µm.
27 OptimumPaint {},
28 /// Planed wooden boards, 15 µm.
29 PlanedWood {},
30 /// Paint in aircraft mass production, 20 µm. The default.
31 MassProductionPaint {},
32 /// Bare steel plating, 50 µm (Barrowman Table 4-1 only).
33 BareSteel {},
34 /// A smooth cement surface, 50 µm.
35 SmoothCement {},
36 /// A surface with an asphalt-type coating, 100 µm (Barrowman Table 4-1 only).
37 AsphaltCoating {},
38 /// A dip-galvanized metal surface, 150 µm.
39 DipGalvanized {},
40 /// Incorrectly sprayed aircraft paint, 200 µm.
41 PoorPaint {},
42 /// The natural surface of cast iron, 250 µm (Barrowman Table 4-1 only).
43 CastIron {},
44 /// Raw wooden boards, 500 µm.
45 RawWood {},
46 /// An average concrete surface, 1000 µm.
47 Concrete {},
48 /// A given roughness height.
49 Custom {
50 /// Roughness height, m.
51 roughness_m: f64,
52 },
53}
54
55impl Default for Finish {
56 fn default() -> Self {
57 Finish::MassProductionPaint {}
58 }
59}
60
61impl Finish {
62 /// Every named finish, smoothest first.
63 pub const NAMED: &'static [Finish] = &[
64 Finish::Mirror {},
65 Finish::AverageGlass {},
66 Finish::Polished {},
67 Finish::SheetMetal {},
68 Finish::OptimumPaint {},
69 Finish::PlanedWood {},
70 Finish::MassProductionPaint {},
71 Finish::BareSteel {},
72 Finish::SmoothCement {},
73 Finish::AsphaltCoating {},
74 Finish::DipGalvanized {},
75 Finish::PoorPaint {},
76 Finish::CastIron {},
77 Finish::RawWood {},
78 Finish::Concrete {},
79 ];
80
81 /// Roughness height `R_s`, m.
82 ///
83 /// # Errors
84 ///
85 /// [`DesignError::Domain`] for a custom height that is negative or not finite.
86 pub fn roughness_m(&self) -> Result<f64, DesignError> {
87 const MICRON: f64 = 1e-6;
88 Ok(match *self {
89 Finish::Mirror {} => 0.0,
90 Finish::AverageGlass {} => 0.1 * MICRON,
91 Finish::Polished {} => 0.5 * MICRON,
92 Finish::SheetMetal {} => 2.0 * MICRON,
93 Finish::OptimumPaint {} => 5.0 * MICRON,
94 Finish::PlanedWood {} => 15.0 * MICRON,
95 Finish::MassProductionPaint {} => 20.0 * MICRON,
96 Finish::BareSteel {} | Finish::SmoothCement {} => 50.0 * MICRON,
97 Finish::AsphaltCoating {} => 100.0 * MICRON,
98 Finish::DipGalvanized {} => 150.0 * MICRON,
99 Finish::PoorPaint {} => 200.0 * MICRON,
100 Finish::CastIron {} => 250.0 * MICRON,
101 Finish::RawWood {} => 500.0 * MICRON,
102 Finish::Concrete {} => 1000.0 * MICRON,
103 Finish::Custom { roughness_m } => {
104 check_dimension("roughness height", roughness_m, true)?;
105 roughness_m
106 }
107 })
108 }
109}