File size: 4,798 Bytes
78ff8fc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import streamlit as st
import math

st.set_page_config(page_title="Geotech Engineering Solver", layout="wide")
st.title("🧱 Geotechnical Engineering Solver")
st.markdown("Built using **American Standards** (ASTM, NAVFAC, Terzaghi, Meyerhof, Coduto).")

# Tabs for modules
tabs = st.tabs([
    "Phase Relationships",
    "Soil Classification (USCS)",
    "Bearing Capacity (Terzaghi & Meyerhof)",
])

# Constants
WATER_DENSITY = 1.0  # g/cm³


# PHASE RELATIONSHIPS TAB
with tabs[0]:
    st.header("Phase Relationships")
    st.markdown("Enter known values. Leave unknowns blank.")

    col1, col2 = st.columns(2)
    with col1:
        rho_wet = st.number_input("Wet Density (g/cm³)", step=0.01, format="%.3f")
        w = st.number_input("Moisture Content (as decimal, e.g. 0.12)", step=0.01, format="%.3f")
        Gs = st.number_input("Specific Gravity Gs", step=0.01, format="%.3f")
    with col2:
        rho_dry = st.number_input("Dry Density (g/cm³)", step=0.01, format="%.3f")
        e = st.number_input("Void Ratio", step=0.01, format="%.3f")
        S = st.number_input("Degree of Saturation (decimal)", step=0.01, format="%.3f")

    if st.button("Calculate Phase Relationships"):
        results = {}

        if rho_dry == 0 and rho_wet and w:
            rho_dry = rho_wet / (1 + w)
            results["Dry Density"] = f"{rho_dry:.3f} g/cm³"

        if e == 0 and Gs and rho_dry:
            e = (Gs * WATER_DENSITY / rho_dry) - 1
            results["Void Ratio"] = f"{e:.3f}"

        if e and not S and Gs and w:
            S = (w * Gs) / e
            results["Degree of Saturation"] = f"{S*100:.2f} %"

        if e:
            n = e / (1 + e)
            results["Porosity"] = f"{n*100:.2f} %"
        if e and S:
            Av = (e / (1 + e)) * (1 - S)
            results["Air Voids"] = f"{Av*100:.2f} %"

        st.subheader("Results:")
        if results:
            for k, v in results.items():
                st.success(f"{k}: {v}")
        else:
            st.warning("Not enough data to compute results.")

# SOIL CLASSIFICATION TAB
with tabs[1]:
    st.header("Soil Classification (USCS)")
    st.markdown("Based on **ASTM D2487 - Unified Soil Classification System**.")

    gravel = st.number_input("Gravel (%)", 0.0, 100.0, step=0.1)
    sand = st.number_input("Sand (%)", 0.0, 100.0, step=0.1)
    fines = st.number_input("Fines (Silt + Clay) (%)", 0.0, 100.0, step=0.1)
    LL = st.number_input("Liquid Limit (LL)", 0.0, 100.0)
    PL = st.number_input("Plastic Limit (PL)", 0.0, 100.0)

    if st.button("Classify Soil"):
        if fines > 50:
            PI = LL - PL
            if PI > 7 and LL > 50:
                soil_type = "CH (Fat Clay)"
            elif PI > 7 and LL <= 50:
                soil_type = "CL (Lean Clay)"
            elif PI <= 7 and LL <= 50:
                soil_type = "ML (Silt)"
            else:
                soil_type = "MH (Elastic Silt)"
        elif fines <= 50:
            if fines > 12:
                soil_type = "SM or SC (Silty/Clayey Sand)"
            elif sand > gravel:
                soil_type = "SP or SW (Poorly or Well Graded Sand)"
            else:
                soil_type = "GP or GW (Poorly or Well Graded Gravel)"
        else:
            soil_type = "Unclassified"

        st.success(f"USCS Soil Classification: **{soil_type}**")

# BEARING CAPACITY TAB
with tabs[2]:
    st.header("Bearing Capacity (Terzaghi & Meyerhof)")
    st.markdown("Formulas from **Terzaghi (1943)** and **Meyerhof (1951)** for shallow foundations.")

    φ = st.number_input("φ (Friction Angle, degrees)", 0.0, 45.0, step=0.1)
    c = st.number_input("Cohesion (kPa)", step=1.0)
    gamma = st.number_input("Soil Unit Weight (kN/m³)", 10.0, 30.0, step=0.1)
    B = st.number_input("Footing Width B (m)", step=0.1)
    D = st.number_input("Depth of Foundation D (m)", step=0.1)
    shape = st.selectbox("Footing Shape", ["Strip", "Square", "Circular"])

    if st.button("Compute Bearing Capacity"):
        φ_rad = math.radians(φ)

        Nq = math.exp(math.pi * math.tan(φ_rad)) * (math.tan(math.radians(45) + φ_rad / 2) ** 2)
        Nc = (Nq - 1) / math.tan(φ_rad) if φ > 0 else 5.14
        Nγ = 2 * (Nq + 1) * math.tan(φ_rad)

        if shape == "Strip":
            sc = sq = sγ = 1
        elif shape == "Square":
            sc = 1.3
            sq = 1.2
            sγ = 0.8
        elif shape == "Circular":
            sc = 1.3
            sq = 1.2
            sγ = 0.6

        q_ult = c * Nc * sc + gamma * D * Nq * sq + 0.5 * gamma * B * Nγ * sγ
        FS = 3
        q_allow = q_ult / FS

        st.subheader("Results")
        st.success(f"Ultimate Bearing Capacity q_ult = {q_ult:.2f} kPa")
        st.info(f"Allowable Bearing Capacity (FS={FS}) = {q_allow:.2f} kPa")