soilrust/bearing_capacity/
point_load_test.rs

1use serde::Serialize;
2
3use crate::{
4    models::{foundation::Foundation, point_load_test::PointLoadTest},
5    validation::{validate_field, ValidationError},
6};
7
8/// Represents the bearing capacity result for a given soil and foundation setup.
9#[derive(Debug, Serialize)]
10pub struct Output {
11    /// Is50 value in MPa.
12    pub is50: f64,
13
14    /// Uniaxial compressive strength (UCS) in MPa.
15    pub ucs: f64,
16
17    /// Generalized value of C.
18    pub c: f64,
19
20    /// Equivalent core diameter in mm.
21    pub d: f64,
22
23    /// Allowable bearing capacity in ton/m2.
24    pub allowable_bearing_capacity: f64,
25
26    /// The pressure exerted by the foundation in ton/m2.
27    pub qmax: f64,
28
29    /// Indicates the depth at which the bearing capacity is calculated in meters.
30    pub df: f64,
31
32    /// Indicates whether the bearing capacity is safe.
33    pub is_safe: bool,
34
35    /// Safety factor used in the design.
36    pub safety_factor: f64,
37}
38
39pub fn validate_input(
40    point_load_test: &PointLoadTest,
41    foundation: &Foundation,
42    foundation_pressure: f64,
43    safety_factor: f64,
44) -> Result<(), ValidationError> {
45    point_load_test.validate(&["is50", "d"])?;
46    foundation.validate(&["foundation_depth"])?;
47    validate_field(
48        "foundation_pressure",
49        Some(foundation_pressure),
50        Some(0.0),
51        None,
52        "loads",
53    )?;
54    validate_field(
55        "safety_factor",
56        Some(safety_factor),
57        Some(1.),
58        None,
59        "safety_factor",
60    )?;
61    Ok(())
62}
63/// Calculates the generalized size correction factor `C` based on the given equivalent core diameter `D`.
64///
65/// This follows the standard chart provided by ASTM and ISRM guidelines for point load tests, interpolating intermediate values.
66///
67/// # Arguments
68/// * `d` - Sample diameter in millimeters (mm).
69///
70/// # Returns
71/// * `f64` - The generalized correction factor `C`.
72pub fn get_generalized_c_value(d: f64) -> f64 {
73    // Diameter (mm) to C values mapping
74    let diameters = [
75        (20., 17.5),
76        (30., 19.),
77        (40., 21.),
78        (50., 23.),
79        (54., 24.),
80        (60., 24.5),
81    ];
82
83    if d <= diameters[0].0 {
84        return diameters[0].1;
85    }
86
87    if d >= diameters.last().unwrap().0 {
88        return diameters.last().unwrap().1;
89    }
90
91    // Interpolate intermediate values
92    for i in 0..diameters.len() - 1 {
93        let (d_lower, c_lower) = diameters[i];
94        let (d_upper, c_upper) = diameters[i + 1];
95
96        if d >= d_lower && d <= d_upper {
97            let fraction = (d - d_lower) / (d_upper - d_lower);
98            return c_lower + fraction * (c_upper - c_lower);
99        }
100    }
101    unreachable!()
102}
103
104/// Calculates the bearing capacity of a foundation based on point load test results.
105///
106/// # Arguments
107/// * `point_load_test` - The point load test data.
108/// * `df` - Depth at which to calculate the bearing capacity.
109/// * `foundation_pressure` - The pressure exerted by the foundation.
110/// * `safety_factor` - The safety factor for the design.
111///
112/// # Returns
113/// * `Output` - The bearing capacity result containing various parameters.
114pub fn calc_bearing_capacity(
115    point_load_test: PointLoadTest,
116    foundation: Foundation,
117    foundation_pressure: f64,
118    safety_factor: f64,
119) -> Result<Output, ValidationError> {
120    validate_input(
121        &point_load_test,
122        &foundation,
123        foundation_pressure,
124        safety_factor,
125    )?;
126    let df = foundation.foundation_depth.unwrap();
127    let point_load_test_exp = point_load_test.get_idealized_exp("idealized".to_string());
128    const MPA_TO_TON: f64 = 101.97162; // Conversion factor from MPa to ton/m2
129    let sample = point_load_test_exp.get_sample_at_depth(df);
130
131    let is50 = sample.is50.unwrap();
132    let d = sample.d.unwrap();
133    let c = get_generalized_c_value(d);
134
135    let ucs = is50 * c * MPA_TO_TON;
136
137    let allowable_bearing_capacity = ucs / safety_factor;
138    let is_safe = allowable_bearing_capacity >= foundation_pressure;
139
140    Ok(Output {
141        is50,
142        ucs,
143        c,
144        d,
145        allowable_bearing_capacity,
146        is_safe,
147        safety_factor,
148        qmax: foundation_pressure,
149        df,
150    })
151}