|
|
""" |
|
|
Streamlit App for PVD Consolidation Analysis |
|
|
Shows settlement vs time curve |
|
|
""" |
|
|
|
|
|
import streamlit as st |
|
|
import numpy as np |
|
|
import matplotlib.pyplot as plt |
|
|
from pvd_consolidation import PVDConsolidation, SoilLayer, PVDProperties |
|
|
|
|
|
|
|
|
st.set_page_config( |
|
|
page_title="PVD Consolidation Analysis", page_icon="📊", layout="wide" |
|
|
) |
|
|
|
|
|
|
|
|
st.title("🏗️ PVD Consolidation Analysis") |
|
|
st.markdown("### Settlement vs Time Calculator") |
|
|
|
|
|
|
|
|
st.sidebar.header("Input Parameters") |
|
|
|
|
|
|
|
|
st.sidebar.subheader("Soil Properties") |
|
|
n_layers = st.sidebar.number_input( |
|
|
"Number of Layers", min_value=1, max_value=10, value=1 |
|
|
) |
|
|
|
|
|
layers = [] |
|
|
for i in range(n_layers): |
|
|
st.sidebar.markdown(f"**Layer {i + 1}**") |
|
|
col1, col2 = st.sidebar.columns(2) |
|
|
|
|
|
with col1: |
|
|
thickness = st.number_input( |
|
|
f"Thickness (m)", min_value=0.1, value=10.0, step=0.5, key=f"thick_{i}" |
|
|
) |
|
|
Cv = st.number_input( |
|
|
f"Cv (m²/yr)", min_value=0.01, value=0.5, step=0.1, key=f"cv_{i}" |
|
|
) |
|
|
Ch = st.number_input( |
|
|
f"Ch (m²/yr)", min_value=0.01, value=2.0, step=0.1, key=f"ch_{i}" |
|
|
) |
|
|
RR = st.number_input( |
|
|
f"RR", min_value=0.001, value=0.05, step=0.01, format="%.3f", key=f"rr_{i}" |
|
|
) |
|
|
CR = st.number_input( |
|
|
f"CR", min_value=0.001, value=0.30, step=0.01, format="%.3f", key=f"cr_{i}" |
|
|
) |
|
|
|
|
|
with col2: |
|
|
sigma_ini = st.number_input( |
|
|
f"σ'ini (kPa)", min_value=1.0, value=50.0, step=5.0, key=f"sini_{i}" |
|
|
) |
|
|
sigma_p = st.number_input( |
|
|
f"σ'p (kPa)", min_value=1.0, value=80.0, step=5.0, key=f"sp_{i}" |
|
|
) |
|
|
kh = st.number_input( |
|
|
f"kh (m/yr)", min_value=0.1, value=2.0, step=0.1, key=f"kh_{i}" |
|
|
) |
|
|
ks = st.number_input( |
|
|
f"ks (m/yr)", min_value=0.1, value=1.0, step=0.1, key=f"ks_{i}" |
|
|
) |
|
|
|
|
|
layers.append( |
|
|
SoilLayer( |
|
|
thickness=thickness, |
|
|
Cv=Cv, |
|
|
Ch=Ch, |
|
|
RR=RR, |
|
|
CR=CR, |
|
|
sigma_ini=sigma_ini, |
|
|
sigma_p=sigma_p, |
|
|
kh=kh, |
|
|
ks=ks, |
|
|
) |
|
|
) |
|
|
|
|
|
st.sidebar.markdown("---") |
|
|
|
|
|
|
|
|
st.sidebar.subheader("PVD Properties") |
|
|
|
|
|
dw = st.sidebar.number_input( |
|
|
"Drain diameter dw (m)", min_value=0.01, value=0.05, step=0.01, format="%.3f" |
|
|
) |
|
|
ds = st.sidebar.number_input( |
|
|
"Smear zone ds (m)", min_value=0.01, value=0.15, step=0.01, format="%.3f" |
|
|
) |
|
|
De = st.sidebar.number_input("Unit cell De (m)", min_value=0.1, value=1.5, step=0.1) |
|
|
L_drain = st.sidebar.number_input( |
|
|
"Drain length L (m)", min_value=1.0, value=10.0, step=1.0 |
|
|
) |
|
|
|
|
|
well_resistance = st.sidebar.selectbox( |
|
|
"Well Resistance", ["Negligible (qw → ∞)", "Custom qw"] |
|
|
) |
|
|
|
|
|
if well_resistance == "Custom qw": |
|
|
qw = st.sidebar.number_input("qw (m³/yr)", min_value=1.0, value=100.0, step=10.0) |
|
|
else: |
|
|
qw = 1e12 |
|
|
|
|
|
pvd = PVDProperties(dw=dw, ds=ds, De=De, L_drain=L_drain, qw=qw) |
|
|
|
|
|
|
|
|
st.sidebar.subheader("Analysis Parameters") |
|
|
surcharge = st.sidebar.number_input( |
|
|
"Surcharge (kPa)", min_value=1.0, value=100.0, step=10.0 |
|
|
) |
|
|
t_max = st.sidebar.number_input("Max Time (years)", min_value=0.1, value=2.0, step=0.1) |
|
|
dt = st.sidebar.number_input( |
|
|
"Time Step (years)", min_value=0.001, value=0.01, step=0.001, format="%.3f" |
|
|
) |
|
|
|
|
|
|
|
|
if st.sidebar.button("🚀 Run Analysis", type="primary"): |
|
|
with st.spinner("Calculating consolidation..."): |
|
|
try: |
|
|
|
|
|
analysis = PVDConsolidation(layers, pvd, surcharge, dt) |
|
|
|
|
|
|
|
|
time, settlement = analysis.settlement_vs_time(t_max=t_max, n_points=200) |
|
|
settlement_mm = settlement * 1000 |
|
|
|
|
|
|
|
|
Fn, Fs, Fr = analysis.calculate_pvd_factors() |
|
|
F_total = Fn + Fs + Fr |
|
|
|
|
|
|
|
|
st.session_state.time = time |
|
|
st.session_state.settlement = settlement_mm |
|
|
st.session_state.Fn = Fn |
|
|
st.session_state.Fs = Fs |
|
|
st.session_state.Fr = Fr |
|
|
st.session_state.F_total = F_total |
|
|
st.session_state.analysis_done = True |
|
|
|
|
|
except Exception as e: |
|
|
st.error(f"Error in analysis: {str(e)}") |
|
|
st.session_state.analysis_done = False |
|
|
|
|
|
|
|
|
if hasattr(st.session_state, "analysis_done") and st.session_state.analysis_done: |
|
|
|
|
|
st.subheader("Settlement vs Time") |
|
|
|
|
|
fig, ax = plt.subplots(figsize=(12, 6)) |
|
|
ax.plot(st.session_state.time, st.session_state.settlement, "b-", linewidth=2.5) |
|
|
ax.set_xlabel("Time (years)", fontsize=14, fontweight="bold") |
|
|
ax.set_ylabel("Settlement (mm)", fontsize=14, fontweight="bold") |
|
|
ax.set_title( |
|
|
"PVD Consolidation - Settlement vs Time", fontsize=16, fontweight="bold" |
|
|
) |
|
|
ax.grid(True, alpha=0.3, linestyle="--") |
|
|
ax.tick_params(labelsize=12) |
|
|
|
|
|
|
|
|
ax.invert_yaxis() |
|
|
|
|
|
|
|
|
final_settlement = st.session_state.settlement[-1] |
|
|
ax.axhline( |
|
|
y=final_settlement, |
|
|
color="r", |
|
|
linestyle="--", |
|
|
alpha=0.5, |
|
|
label=f"Final Settlement = {final_settlement:.1f} mm", |
|
|
) |
|
|
ax.legend(fontsize=12) |
|
|
|
|
|
st.pyplot(fig) |
|
|
|
|
|
|
|
|
st.subheader("Analysis Summary") |
|
|
|
|
|
col1, col2, col3, col4 = st.columns(4) |
|
|
|
|
|
with col1: |
|
|
st.metric("Final Settlement", f"{final_settlement:.1f} mm") |
|
|
|
|
|
with col2: |
|
|
|
|
|
target_settlement = 0.9 * final_settlement |
|
|
idx_90 = np.argmax(st.session_state.settlement >= target_settlement) |
|
|
t_90 = ( |
|
|
st.session_state.time[idx_90] if idx_90 > 0 else st.session_state.time[-1] |
|
|
) |
|
|
st.metric("Time to 90% U", f"{t_90:.2f} years") |
|
|
|
|
|
with col3: |
|
|
|
|
|
target_settlement = 0.5 * final_settlement |
|
|
idx_50 = np.argmax(st.session_state.settlement >= target_settlement) |
|
|
t_50 = ( |
|
|
st.session_state.time[idx_50] if idx_50 > 0 else st.session_state.time[-1] |
|
|
) |
|
|
st.metric("Time to 50% U", f"{t_50:.2f} years") |
|
|
|
|
|
with col4: |
|
|
st.metric("Total Resistance F", f"{st.session_state.F_total:.2f}") |
|
|
|
|
|
|
|
|
st.subheader("PVD Influence Factors") |
|
|
|
|
|
col1, col2, col3 = st.columns(3) |
|
|
|
|
|
with col1: |
|
|
st.metric("Geometric Factor (Fn)", f"{st.session_state.Fn:.3f}") |
|
|
|
|
|
with col2: |
|
|
st.metric("Smear Factor (Fs)", f"{st.session_state.Fs:.3f}") |
|
|
|
|
|
with col3: |
|
|
st.metric("Well Resistance (Fr)", f"{st.session_state.Fr:.3f}") |
|
|
|
|
|
|
|
|
st.subheader("Download Results") |
|
|
|
|
|
|
|
|
csv_data = "Time (years),Settlement (mm)\n" |
|
|
for t, s in zip(st.session_state.time, st.session_state.settlement): |
|
|
csv_data += f"{t:.4f},{s:.2f}\n" |
|
|
|
|
|
st.download_button( |
|
|
label="📥 Download Settlement Data (CSV)", |
|
|
data=csv_data, |
|
|
file_name="settlement_data.csv", |
|
|
mime="text/csv", |
|
|
) |
|
|
|
|
|
else: |
|
|
|
|
|
st.info( |
|
|
"👈 Configure your parameters in the sidebar and click **Run Analysis** to see results" |
|
|
) |
|
|
|
|
|
st.markdown(""" |
|
|
### Instructions: |
|
|
|
|
|
1. **Soil Properties**: Enter the properties for each soil layer |
|
|
- Thickness (m) |
|
|
- Cv: Vertical coefficient of consolidation (m²/year) |
|
|
- Ch: Horizontal coefficient of consolidation (m²/year) |
|
|
- RR: Recompression ratio |
|
|
- CR: Compression ratio |
|
|
- σ'ini: Initial effective stress (kPa) |
|
|
- σ'p: Preconsolidation pressure (kPa) |
|
|
|
|
|
2. **PVD Properties**: Configure the drain installation |
|
|
- dw: Equivalent drain diameter (m) |
|
|
- ds: Smear zone diameter (m) |
|
|
- De: Equivalent unit cell diameter (m) |
|
|
- L: Drain length (m) |
|
|
- kh: Horizontal permeability (m/year) |
|
|
- ks: Smear zone permeability (m/year) |
|
|
- qw: Well discharge capacity (m³/year) |
|
|
|
|
|
3. **Analysis Parameters**: |
|
|
- Surcharge: Applied load (kPa) |
|
|
- Max Time: Analysis duration (years) |
|
|
- Time Step: Calculation step size (years) |
|
|
|
|
|
4. Click **Run Analysis** to calculate and visualize results |
|
|
""") |
|
|
|
|
|
|
|
|
st.sidebar.markdown("---") |
|
|
st.sidebar.markdown("**PVD Consolidation Calculator**") |
|
|
st.sidebar.markdown("Version 1.0") |
|
|
|