#[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq)]
enum FlowRegime {
Laminar, Transitional, Turbulent, }
fn calculate_reynolds_number(
velocity_mps: f64,
diameter_m: f64,
air_density_kg_m3: f64,
temperature_k: f64,
) -> f64 {
let mu = calculate_air_viscosity(temperature_k);
air_density_kg_m3 * velocity_mps * diameter_m / mu
}
fn calculate_air_viscosity(temperature_k: f64) -> f64 {
const T0: f64 = 273.15; const MU0: f64 = 1.716e-5; const S: f64 = 110.4;
MU0 * (T0 + S) / (temperature_k + S) * (temperature_k / T0).powf(1.5)
}
#[allow(dead_code)]
fn get_flow_regime(reynolds_number: f64) -> FlowRegime {
if reynolds_number < 2000.0 {
FlowRegime::Laminar
} else if reynolds_number < 5e5 {
FlowRegime::Transitional
} else {
FlowRegime::Turbulent
}
}
fn reynolds_drag_correction(reynolds_number: f64, mach: f64, _base_cd: f64) -> f64 {
if mach >= 1.0 {
return 1.0;
}
const RE_REF: f64 = 1e6;
if reynolds_number >= RE_REF {
return 1.0;
}
if reynolds_number < 1000.0 {
let correction = 24.0 / reynolds_number + 1.0;
correction.min(5.0)
} else if reynolds_number < 1e4 {
let n = -0.4;
(reynolds_number / RE_REF).powf(n)
} else if reynolds_number < 1e5 {
let n = -0.2;
(reynolds_number / RE_REF).powf(n)
} else {
let n = -0.1;
(reynolds_number / RE_REF).powf(n)
}
}
fn calculate_corrected_drag(
velocity_mps: f64,
diameter_m: f64,
air_density_kg_m3: f64,
temperature_k: f64,
mach: f64,
base_cd: f64,
) -> (f64, f64) {
let re = calculate_reynolds_number(velocity_mps, diameter_m, air_density_kg_m3, temperature_k);
let correction = reynolds_drag_correction(re, mach, base_cd);
let corrected_cd = base_cd * correction;
(corrected_cd, re)
}
pub fn apply_reynolds_correction(
base_cd: f64,
velocity_mps: f64,
diameter_inches: f64,
air_density_kg_m3: f64,
temperature_c: f64,
mach: f64,
) -> f64 {
let diameter_m = diameter_inches * 0.0254; let temperature_k = temperature_c + 273.15;
if velocity_mps > 1000.0 || mach > 3.0 {
return base_cd;
}
let (corrected_cd, _) = calculate_corrected_drag(
velocity_mps,
diameter_m,
air_density_kg_m3,
temperature_k,
mach,
base_cd,
);
corrected_cd
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_air_viscosity() {
let mu = calculate_air_viscosity(288.15);
assert!((mu - 1.789e-5).abs() < 1e-7);
}
#[test]
fn test_reynolds_number() {
let re = calculate_reynolds_number(100.0, 0.00782, 1.225, 288.15);
assert!(re > 5e4 && re < 6e4);
}
#[test]
fn test_flow_regime() {
assert_eq!(get_flow_regime(1000.0), FlowRegime::Laminar);
assert_eq!(get_flow_regime(1e5), FlowRegime::Transitional);
assert_eq!(get_flow_regime(1e6), FlowRegime::Turbulent);
}
#[test]
fn test_reynolds_correction() {
let correction = reynolds_drag_correction(1e5, 1.5, 0.5);
assert_eq!(correction, 1.0);
let correction = reynolds_drag_correction(1e4, 0.5, 0.5);
assert!(correction > 1.0);
let correction = reynolds_drag_correction(100.0, 0.1, 0.5);
assert!(correction > 1.0);
assert!(correction <= 5.0); }
}