#[must_use]
#[inline]
pub fn blasius_thickness(x: f64, reynolds_x: f64) -> f64 {
if reynolds_x <= 0.0 {
return 0.0;
}
5.0 * x / reynolds_x.sqrt()
}
#[must_use]
#[inline]
pub fn turbulent_thickness(x: f64, reynolds_x: f64) -> f64 {
if reynolds_x <= 0.0 {
return 0.0;
}
0.37 * x / reynolds_x.powf(0.2)
}
pub const TRANSITION_REYNOLDS: f64 = 500_000.0;
#[must_use]
#[inline]
pub fn is_turbulent(reynolds: f64) -> bool {
reynolds > TRANSITION_REYNOLDS
}
#[must_use]
#[inline]
pub fn skin_friction_laminar(reynolds_x: f64) -> f64 {
if reynolds_x <= 0.0 {
return 0.0;
}
0.664 / reynolds_x.sqrt()
}
#[must_use]
#[inline]
pub fn skin_friction_turbulent(reynolds_x: f64) -> f64 {
if reynolds_x <= 0.0 {
return 0.0;
}
0.027 / reynolds_x.powf(1.0 / 7.0)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn blasius_basic() {
let delta = blasius_thickness(1.0, 100_000.0);
assert!(
(delta - 0.0158).abs() < 0.001,
"Blasius thickness should be ~0.016m, got {delta}"
);
}
#[test]
fn turbulent_thicker_than_laminar() {
let re = 1_000_000.0;
let lam = blasius_thickness(1.0, re);
let turb = turbulent_thickness(1.0, re);
assert!(
turb > lam,
"turbulent BL should be thicker than laminar at same Re"
);
}
#[test]
fn transition_check() {
assert!(!is_turbulent(100_000.0));
assert!(is_turbulent(1_000_000.0));
}
#[test]
fn skin_friction_laminar_decreases_with_re() {
let cf_low = skin_friction_laminar(10_000.0);
let cf_high = skin_friction_laminar(1_000_000.0);
assert!(cf_high < cf_low);
}
#[test]
fn turbulent_friction_higher_than_laminar() {
let re = 1_000_000.0;
let cf_lam = skin_friction_laminar(re);
let cf_turb = skin_friction_turbulent(re);
assert!(cf_turb > cf_lam, "turbulent friction should be higher");
}
#[test]
fn zero_reynolds_safe() {
assert_eq!(blasius_thickness(1.0, 0.0), 0.0);
assert_eq!(turbulent_thickness(1.0, 0.0), 0.0);
assert_eq!(skin_friction_laminar(0.0), 0.0);
}
#[test]
fn negative_reynolds_safe() {
assert_eq!(blasius_thickness(1.0, -1.0), 0.0);
assert_eq!(turbulent_thickness(1.0, -1.0), 0.0);
assert_eq!(skin_friction_laminar(-1.0), 0.0);
assert_eq!(skin_friction_turbulent(-1.0), 0.0);
}
#[test]
fn skin_friction_turbulent_zero_reynolds() {
assert_eq!(skin_friction_turbulent(0.0), 0.0);
}
#[test]
fn blasius_thickness_scales_with_x() {
let re = 500_000.0;
let d1 = blasius_thickness(1.0, re);
let d2 = blasius_thickness(2.0, re);
assert!(
(d2 / d1 - 2.0).abs() < 1e-10,
"Blasius thickness should scale linearly with x"
);
}
#[test]
fn turbulent_thickness_at_transition() {
let re = TRANSITION_REYNOLDS;
let lam = blasius_thickness(1.0, re);
let turb = turbulent_thickness(1.0, re);
assert!(
turb > lam,
"turbulent should be thicker even at transition point"
);
}
#[test]
fn skin_friction_known_values() {
let cf = skin_friction_laminar(1_000_000.0);
assert!(
(cf - 6.64e-4).abs() < 1e-5,
"Cf_lam at Re=1M should be ~6.64e-4, got {cf}"
);
}
#[test]
fn is_turbulent_at_boundary() {
assert!(
!is_turbulent(TRANSITION_REYNOLDS),
"exactly at transition should be laminar"
);
assert!(is_turbulent(TRANSITION_REYNOLDS + 1.0));
}
}