use crate::{
models::{foundation::Foundation, loads::Loads, soil_profile::SoilProfile},
validation::{validate_field, ValidationError},
};
use serde::{Deserialize, Serialize};
use std::f64::consts::PI;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HorizontalSlidingResult {
pub rth: f64,
pub ptv: f64,
pub rpk_x: f64,
pub rpk_y: f64,
pub rpt_x: f64,
pub rpt_y: f64,
pub sum_x: f64,
pub sum_y: f64,
pub is_safe_x: bool,
pub is_safe_y: bool,
pub ac: f64,
pub vth_x: f64,
pub vth_y: f64,
}
pub fn validate_input(
soil_profile: &SoilProfile,
foundation: &Foundation,
loads: &Loads,
foundation_pressure: f64,
) -> Result<(), ValidationError> {
soil_profile.validate(&[
"thickness",
"dry_unit_weight",
"saturated_unit_weight",
"c_prime",
"cu",
"phi_prime",
"phi_u",
])?;
foundation.validate(&[
"foundation_depth",
"foundation_width",
"foundation_length",
"surface_friction_coefficient",
])?;
loads.validate(&["horizontal_load_x", "horizontal_load_y"])?;
validate_field(
"foundation_pressure",
Some(foundation_pressure),
Some(0.0),
None,
"loads",
)?;
Ok(())
}
fn get_soil_params(soil_profile: &SoilProfile, df: f64) -> (f64, f64, f64) {
let layer = soil_profile.get_layer_at_depth(df);
let c_prime = layer.c_prime.unwrap();
let cu = layer.cu.unwrap();
let phi_prime = layer.phi_prime.unwrap();
let phi_u = layer.phi_u.unwrap();
let dry_unit_weight = layer.dry_unit_weight.unwrap();
let saturated_unit_weight = layer.saturated_unit_weight.unwrap();
let (selected_unit_weight, selected_cohesion, selected_phi) =
if soil_profile.ground_water_level.unwrap() <= df {
(saturated_unit_weight - 1.0, cu, phi_u)
} else {
(dry_unit_weight, c_prime, phi_prime)
};
(selected_cohesion, selected_phi, selected_unit_weight)
}
pub fn calc_horizontal_sliding(
soil_profile: &SoilProfile,
foundation: &Foundation,
loads: &Loads,
foundation_pressure: f64,
) -> Result<HorizontalSlidingResult, ValidationError> {
validate_input(soil_profile, foundation, loads, foundation_pressure)?;
let df = foundation.foundation_depth.unwrap();
let b = foundation.foundation_width.unwrap();
let l = foundation.foundation_length.unwrap();
let vx = loads.horizontal_load_x.unwrap();
let vy = loads.horizontal_load_y.unwrap();
let surface_friction = foundation.surface_friction_coefficient.unwrap();
let ptv = foundation_pressure * b * l;
let (cohesion, phi, unit_weight) = get_soil_params(soil_profile, df);
let kp = (f64::tan((45.0 + phi / 2.0) * PI / 180.0)).powi(2);
let rth = if soil_profile.ground_water_level.unwrap() > df {
ptv * surface_friction / 1.1
} else {
l * b * cohesion / 1.1
};
let rpk_x = b * 0.5 * df.powi(2) * unit_weight * kp;
let rpk_y = l * 0.5 * df.powi(2) * unit_weight * kp;
let rpt_x = rpk_x / 1.4;
let rpt_y = rpk_y / 1.4;
let sum_x = rth + 0.3 * rpt_x;
let sum_y = rth + 0.3 * rpt_y;
Ok(HorizontalSlidingResult {
rth,
ptv,
rpk_x,
rpk_y,
rpt_x,
rpt_y,
sum_x,
sum_y,
is_safe_x: vx <= sum_x,
is_safe_y: vy <= sum_y,
ac: l * b,
vth_x: vx,
vth_y: vy,
})
}