use crate::{
models::{foundation::Foundation, soil_profile::SoilProfile},
validation::{validate_field, ValidationError},
};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SwellingPotentialData {
pub layer_center: f64,
pub effective_stress: f64,
pub delta_stress: f64,
pub swelling_pressure: f64,
pub is_safe: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SwellingPotentialResult {
pub data: Vec<SwellingPotentialData>,
pub net_foundation_pressure: f64,
}
pub fn validate_input(
soil_profile: &SoilProfile,
foundation: &Foundation,
foundation_pressure: f64,
) -> Result<(), ValidationError> {
soil_profile.validate(&[
"thickness",
"dry_unit_weight",
"saturated_unit_weight",
"water_content",
"liquid_limit",
"plastic_limit",
])?;
foundation.validate(&["foundation_depth", "foundation_width", "foundation_length"])?;
validate_field(
"foundation_pressure",
Some(foundation_pressure),
Some(0.0),
None,
"loads",
)?;
Ok(())
}
pub fn calc_swelling_potential(
soil_profile: &mut SoilProfile,
foundation: &Foundation,
foundation_pressure: f64,
) -> Result<SwellingPotentialResult, ValidationError> {
validate_input(soil_profile, foundation, foundation_pressure)?;
soil_profile.calc_layer_depths();
let df = foundation.foundation_depth.unwrap();
let width = foundation.foundation_width.unwrap();
let length = foundation.foundation_length.unwrap();
let net_foundation_pressure = foundation_pressure - soil_profile.calc_normal_stress(df);
let vertical_load = net_foundation_pressure * width * length;
let mut data = Vec::new();
for layer in soil_profile.layers.iter() {
let z = layer.center.unwrap();
let mut effective_stress = 0.;
let mut delta_stress = 0.;
if z >= df {
effective_stress = soil_profile.calc_effective_stress(z);
delta_stress = vertical_load / ((width + z - df) * (length + z - df));
}
let swelling_pressure = if let Some(plastic_limit) = layer.plastic_limit {
let water_content = layer.water_content.unwrap();
let liquid_limit = layer.liquid_limit.unwrap();
let dry_unit_weight = layer.dry_unit_weight.unwrap();
-3.08 * water_content
+ 102.5 * dry_unit_weight
+ 0.635 * liquid_limit
+ 4.24 * plastic_limit
- 220.8
} else {
0.0
};
let is_safe = swelling_pressure <= (effective_stress + delta_stress);
data.push(SwellingPotentialData {
layer_center: layer.center.unwrap(),
effective_stress,
delta_stress,
swelling_pressure,
is_safe,
});
}
Ok(SwellingPotentialResult {
data,
net_foundation_pressure,
})
}