use crate::{
models::{foundation::Foundation, masw::Masw, soil_profile::SoilProfile},
validation::ValidationError,
};
use serde::Serialize;
#[derive(Debug, Serialize)]
pub struct Output {
pub vs: f64,
pub unit_weight: f64,
pub qmax: f64,
pub allowable_bearing_capacity: f64,
pub is_safe: bool,
pub safety_factor: f64,
}
pub fn validate_input(
masw: &Masw,
soil_profile: &SoilProfile,
foundation: &Foundation,
) -> Result<(), ValidationError> {
masw.validate(&["thickness", "vs"])?;
soil_profile.validate(&["thickness", "dry_unit_weight", "saturated_unit_weight"])?;
foundation.validate(&["foundation_depth"])?;
Ok(())
}
fn get_unit_weight(df: f64, soil_profile: SoilProfile) -> f64 {
let layer = soil_profile.get_layer_at_depth(df);
let gwt = soil_profile.ground_water_level.unwrap();
let mut unit_weight = layer.dry_unit_weight.unwrap();
if gwt <= df {
unit_weight = layer.saturated_unit_weight.unwrap();
}
unit_weight
}
pub fn calc_bearing_capacity(
soil_profile: SoilProfile,
masw: &mut Masw,
foundation: Foundation,
foundation_pressure: f64,
) -> Result<Output, ValidationError> {
validate_input(masw, &soil_profile, &foundation)?;
let df = foundation.foundation_depth.unwrap();
let masw_exp = masw.get_idealized_exp("idealized".to_string());
let masw_layer = masw_exp.get_layer_at_depth(df);
let vs = masw_layer.vs.unwrap();
let unit_weight = get_unit_weight(df, soil_profile);
let (safety_factor, bearing_capacity): (f64, f64) = match vs {
vs if vs < 750.0 => {
let sf = 4.0;
let q = 0.025 * unit_weight * vs;
(sf, q)
}
vs if vs < 4000.0 => {
let sf = 4.6 - vs * 8.0e-4;
let q = 0.1 * unit_weight * vs / sf;
(sf, q)
}
_ => {
let sf = 1.4;
let q = 0.071 * unit_weight * vs;
(sf, q)
}
};
Ok(Output {
vs,
unit_weight,
allowable_bearing_capacity: bearing_capacity,
is_safe: bearing_capacity >= foundation_pressure,
safety_factor,
qmax: foundation_pressure,
})
}