pub fn calc_rd(depth: f64) -> f64 {
match depth {
z if z <= 9.15 => 1.0 - 0.00765 * z,
z if z > 9.15 && z < 23.0 => 1.174 - 0.0267 * z,
z if (23.0..30.0).contains(&z) => 0.744 - 0.008 * z,
_ => 0.5,
}
}
pub fn calc_csr(pga: f64, normal_stress: f64, rd: f64) -> f64 {
0.65 * pga * normal_stress * rd
}
pub fn calc_msf(mw: f64) -> f64 {
10.0_f64.powf(2.24) / mw.powf(2.56)
}
#[cfg(test)]
mod tests {
use approx::assert_abs_diff_eq;
use super::*;
#[test]
fn test_calc_rd_shallow_depth() {
let depth = 5.0;
let expected = 1.0 - 0.00765 * depth;
let result = calc_rd(depth);
assert_abs_diff_eq!(result, expected, epsilon = 1e-6);
}
#[test]
fn test_calc_rd_transition_depth_9_15() {
let depth = 9.15;
let expected = 1.0 - 0.00765 * depth;
let result = calc_rd(depth);
assert_abs_diff_eq!(result, expected, epsilon = 1e-6);
}
#[test]
fn test_calc_rd_intermediate_depth() {
let depth = 15.0;
let expected = 1.174 - 0.0267 * depth;
let result = calc_rd(depth);
assert_abs_diff_eq!(result, expected, epsilon = 1e-6);
}
#[test]
fn test_calc_rd_range_23_to_30() {
let depth = 25.0;
let expected = 0.744 - 0.008 * depth;
let result = calc_rd(depth);
assert_abs_diff_eq!(result, expected, epsilon = 1e-6);
}
#[test]
fn test_calc_rd_exact_30() {
let depth = 30.0;
let expected = 0.5;
let result = calc_rd(depth);
assert_abs_diff_eq!(result, expected, epsilon = 1e-6);
}
#[test]
fn test_calc_rd_greater_than_30() {
let depth = 35.0;
let expected = 0.5;
let result = calc_rd(depth);
assert_abs_diff_eq!(result, expected, epsilon = 1e-6);
}
#[test]
fn test_calc_csr() {
let pga = 0.3; let normal_stress = 10.0; let rd = 0.9;
let expected = 0.65 * pga * normal_stress * rd;
let result = calc_csr(pga, normal_stress, rd);
assert_abs_diff_eq!(result, expected, epsilon = 1e-6);
}
#[test]
fn test_calc_msf_typical_magnitude() {
let mw: f64 = 7.5;
let expected = 10.0_f64.powf(2.24) / mw.powf(2.56);
let result = calc_msf(mw);
assert_abs_diff_eq!(result, expected, epsilon = 1e-6);
}
}