Sompote commited on
Commit
72f959f
·
verified ·
1 Parent(s): 5aff5d9

Upload 5 files

Browse files
Files changed (5) hide show
  1. app.py +264 -0
  2. example_input.yaml +70 -0
  3. pvd_consolidation.py +762 -0
  4. requirements.txt +4 -3
  5. test_input.yaml +33 -0
app.py ADDED
@@ -0,0 +1,264 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Streamlit App for PVD Consolidation Analysis
3
+ Shows settlement vs time curve
4
+ """
5
+
6
+ import streamlit as st
7
+ import numpy as np
8
+ import matplotlib.pyplot as plt
9
+ from pvd_consolidation import PVDConsolidation, SoilLayer, PVDProperties
10
+
11
+ # Page configuration
12
+ st.set_page_config(
13
+ page_title="PVD Consolidation Analysis", page_icon="📊", layout="wide"
14
+ )
15
+
16
+ # Title
17
+ st.title("🏗️ PVD Consolidation Analysis")
18
+ st.markdown("### Settlement vs Time Calculator")
19
+
20
+ # Sidebar for inputs
21
+ st.sidebar.header("Input Parameters")
22
+
23
+ # Soil Layer Inputs
24
+ st.sidebar.subheader("Soil Properties")
25
+ n_layers = st.sidebar.number_input(
26
+ "Number of Layers", min_value=1, max_value=10, value=1
27
+ )
28
+
29
+ layers = []
30
+ for i in range(n_layers):
31
+ st.sidebar.markdown(f"**Layer {i + 1}**")
32
+ col1, col2 = st.sidebar.columns(2)
33
+
34
+ with col1:
35
+ thickness = st.number_input(
36
+ f"Thickness (m)", min_value=0.1, value=10.0, step=0.5, key=f"thick_{i}"
37
+ )
38
+ Cv = st.number_input(
39
+ f"Cv (m²/yr)", min_value=0.01, value=0.5, step=0.1, key=f"cv_{i}"
40
+ )
41
+ Ch = st.number_input(
42
+ f"Ch (m²/yr)", min_value=0.01, value=2.0, step=0.1, key=f"ch_{i}"
43
+ )
44
+ RR = st.number_input(
45
+ f"RR", min_value=0.001, value=0.05, step=0.01, format="%.3f", key=f"rr_{i}"
46
+ )
47
+
48
+ with col2:
49
+ CR = st.number_input(
50
+ f"CR", min_value=0.001, value=0.30, step=0.01, format="%.3f", key=f"cr_{i}"
51
+ )
52
+ sigma_ini = st.number_input(
53
+ f"σ'ini (kPa)", min_value=1.0, value=50.0, step=5.0, key=f"sini_{i}"
54
+ )
55
+ sigma_p = st.number_input(
56
+ f"σ'p (kPa)", min_value=1.0, value=80.0, step=5.0, key=f"sp_{i}"
57
+ )
58
+
59
+ layers.append(
60
+ SoilLayer(
61
+ thickness=thickness,
62
+ Cv=Cv,
63
+ Ch=Ch,
64
+ RR=RR,
65
+ CR=CR,
66
+ sigma_ini=sigma_ini,
67
+ sigma_p=sigma_p,
68
+ )
69
+ )
70
+
71
+ st.sidebar.markdown("---")
72
+
73
+ # PVD Properties
74
+ st.sidebar.subheader("PVD Properties")
75
+ col1, col2 = st.sidebar.columns(2)
76
+
77
+ with col1:
78
+ dw = st.number_input(
79
+ "Drain diameter dw (m)", min_value=0.01, value=0.05, step=0.01, format="%.3f"
80
+ )
81
+ ds = st.number_input(
82
+ "Smear zone ds (m)", min_value=0.01, value=0.15, step=0.01, format="%.3f"
83
+ )
84
+ De = st.number_input("Unit cell De (m)", min_value=0.1, value=1.5, step=0.1)
85
+ L_drain = st.number_input("Drain length L (m)", min_value=1.0, value=10.0, step=1.0)
86
+
87
+ with col2:
88
+ kh = st.number_input("kh (m/yr)", min_value=0.1, value=2.0, step=0.1)
89
+ ks = st.number_input("ks (m/yr)", min_value=0.1, value=1.0, step=0.1)
90
+
91
+ well_resistance = st.selectbox(
92
+ "Well Resistance", ["Negligible (qw → ∞)", "Custom qw"]
93
+ )
94
+
95
+ if well_resistance == "Custom qw":
96
+ qw = st.number_input("qw (m³/yr)", min_value=1.0, value=100.0, step=10.0)
97
+ else:
98
+ qw = 1e12 # Very large value for negligible resistance
99
+
100
+ pvd = PVDProperties(dw=dw, ds=ds, De=De, L_drain=L_drain, kh=kh, ks=ks, qw=qw)
101
+
102
+ # Analysis Parameters
103
+ st.sidebar.subheader("Analysis Parameters")
104
+ surcharge = st.sidebar.number_input(
105
+ "Surcharge (kPa)", min_value=1.0, value=100.0, step=10.0
106
+ )
107
+ t_max = st.sidebar.number_input("Max Time (years)", min_value=0.1, value=2.0, step=0.1)
108
+ dt = st.sidebar.number_input(
109
+ "Time Step (years)", min_value=0.001, value=0.01, step=0.001, format="%.3f"
110
+ )
111
+
112
+ # Run Analysis Button
113
+ if st.sidebar.button("🚀 Run Analysis", type="primary"):
114
+ with st.spinner("Calculating consolidation..."):
115
+ try:
116
+ # Create analysis
117
+ analysis = PVDConsolidation(layers, pvd, surcharge, dt)
118
+
119
+ # Calculate settlement vs time
120
+ time, settlement = analysis.settlement_vs_time(t_max=t_max, n_points=200)
121
+ settlement_mm = settlement * 1000 # Convert to mm
122
+
123
+ # Get PVD factors
124
+ Fn, Fs, Fr = analysis.calculate_pvd_factors()
125
+ F_total = Fn + Fs + Fr
126
+
127
+ # Store results in session state
128
+ st.session_state.time = time
129
+ st.session_state.settlement = settlement_mm
130
+ st.session_state.Fn = Fn
131
+ st.session_state.Fs = Fs
132
+ st.session_state.Fr = Fr
133
+ st.session_state.F_total = F_total
134
+ st.session_state.analysis_done = True
135
+
136
+ except Exception as e:
137
+ st.error(f"Error in analysis: {str(e)}")
138
+ st.session_state.analysis_done = False
139
+
140
+ # Display Results
141
+ if hasattr(st.session_state, "analysis_done") and st.session_state.analysis_done:
142
+ # Main plot - Settlement vs Time
143
+ st.subheader("Settlement vs Time")
144
+
145
+ fig, ax = plt.subplots(figsize=(12, 6))
146
+ ax.plot(st.session_state.time, st.session_state.settlement, "b-", linewidth=2.5)
147
+ ax.set_xlabel("Time (years)", fontsize=14, fontweight="bold")
148
+ ax.set_ylabel("Settlement (mm)", fontsize=14, fontweight="bold")
149
+ ax.set_title(
150
+ "PVD Consolidation - Settlement vs Time", fontsize=16, fontweight="bold"
151
+ )
152
+ ax.grid(True, alpha=0.3, linestyle="--")
153
+ ax.tick_params(labelsize=12)
154
+
155
+ # Add final settlement annotation
156
+ final_settlement = st.session_state.settlement[-1]
157
+ ax.axhline(
158
+ y=final_settlement,
159
+ color="r",
160
+ linestyle="--",
161
+ alpha=0.5,
162
+ label=f"Final Settlement = {final_settlement:.1f} mm",
163
+ )
164
+ ax.legend(fontsize=12)
165
+
166
+ st.pyplot(fig)
167
+
168
+ # Summary statistics
169
+ st.subheader("Analysis Summary")
170
+
171
+ col1, col2, col3, col4 = st.columns(4)
172
+
173
+ with col1:
174
+ st.metric("Final Settlement", f"{final_settlement:.1f} mm")
175
+
176
+ with col2:
177
+ # Find time to 90% consolidation
178
+ target_settlement = 0.9 * final_settlement
179
+ idx_90 = np.argmax(st.session_state.settlement >= target_settlement)
180
+ t_90 = (
181
+ st.session_state.time[idx_90] if idx_90 > 0 else st.session_state.time[-1]
182
+ )
183
+ st.metric("Time to 90% U", f"{t_90:.2f} years")
184
+
185
+ with col3:
186
+ # Find time to 50% consolidation
187
+ target_settlement = 0.5 * final_settlement
188
+ idx_50 = np.argmax(st.session_state.settlement >= target_settlement)
189
+ t_50 = (
190
+ st.session_state.time[idx_50] if idx_50 > 0 else st.session_state.time[-1]
191
+ )
192
+ st.metric("Time to 50% U", f"{t_50:.2f} years")
193
+
194
+ with col4:
195
+ st.metric("Total Resistance F", f"{st.session_state.F_total:.2f}")
196
+
197
+ # PVD Factors
198
+ st.subheader("PVD Influence Factors")
199
+
200
+ col1, col2, col3 = st.columns(3)
201
+
202
+ with col1:
203
+ st.metric("Geometric Factor (Fn)", f"{st.session_state.Fn:.3f}")
204
+
205
+ with col2:
206
+ st.metric("Smear Factor (Fs)", f"{st.session_state.Fs:.3f}")
207
+
208
+ with col3:
209
+ st.metric("Well Resistance (Fr)", f"{st.session_state.Fr:.3f}")
210
+
211
+ # Download data
212
+ st.subheader("Download Results")
213
+
214
+ # Prepare CSV data
215
+ csv_data = "Time (years),Settlement (mm)\n"
216
+ for t, s in zip(st.session_state.time, st.session_state.settlement):
217
+ csv_data += f"{t:.4f},{s:.2f}\n"
218
+
219
+ st.download_button(
220
+ label="📥 Download Settlement Data (CSV)",
221
+ data=csv_data,
222
+ file_name="settlement_data.csv",
223
+ mime="text/csv",
224
+ )
225
+
226
+ else:
227
+ # Initial instructions
228
+ st.info(
229
+ "👈 Configure your parameters in the sidebar and click **Run Analysis** to see results"
230
+ )
231
+
232
+ st.markdown("""
233
+ ### Instructions:
234
+
235
+ 1. **Soil Properties**: Enter the properties for each soil layer
236
+ - Thickness (m)
237
+ - Cv: Vertical coefficient of consolidation (m²/year)
238
+ - Ch: Horizontal coefficient of consolidation (m²/year)
239
+ - RR: Recompression ratio
240
+ - CR: Compression ratio
241
+ - σ'ini: Initial effective stress (kPa)
242
+ - σ'p: Preconsolidation pressure (kPa)
243
+
244
+ 2. **PVD Properties**: Configure the drain installation
245
+ - dw: Equivalent drain diameter (m)
246
+ - ds: Smear zone diameter (m)
247
+ - De: Equivalent unit cell diameter (m)
248
+ - L: Drain length (m)
249
+ - kh: Horizontal permeability (m/year)
250
+ - ks: Smear zone permeability (m/year)
251
+ - qw: Well discharge capacity (m³/year)
252
+
253
+ 3. **Analysis Parameters**:
254
+ - Surcharge: Applied load (kPa)
255
+ - Max Time: Analysis duration (years)
256
+ - Time Step: Calculation step size (years)
257
+
258
+ 4. Click **Run Analysis** to calculate and visualize results
259
+ """)
260
+
261
+ # Footer
262
+ st.sidebar.markdown("---")
263
+ st.sidebar.markdown("**PVD Consolidation Calculator**")
264
+ st.sidebar.markdown("Version 1.0")
example_input.yaml ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # PVD Consolidation Analysis Input File
2
+ # All units: m, kPa, years
3
+
4
+ # Soil layers (from top to bottom)
5
+ soil_layers:
6
+ - thickness: 5.0 # Layer thickness (m)
7
+ Cv: 0.5 # Vertical coefficient of consolidation (m²/year)
8
+ Ch: 1.5 # Horizontal coefficient of consolidation (m²/year)
9
+ RR: 0.05 # Recompression ratio
10
+ CR: 0.30 # Compression ratio
11
+ sigma_ini: 50.0 # Initial effective stress (kPa)
12
+ sigma_p: 80.0 # Preconsolidation pressure (kPa)
13
+
14
+ - thickness: 8.0
15
+ Cv: 0.3
16
+ Ch: 1.0
17
+ RR: 0.04
18
+ CR: 0.35
19
+ sigma_ini: 90.0
20
+ sigma_p: 90.0
21
+
22
+ - thickness: 7.0
23
+ Cv: 0.4
24
+ Ch: 1.2
25
+ RR: 0.045
26
+ CR: 0.32
27
+ sigma_ini: 140.0
28
+ sigma_p: 150.0
29
+
30
+ # PVD installation properties
31
+ pvd:
32
+ dw: 0.05 # Equivalent diameter of drain (m) - typically 50-100 mm
33
+ ds: 0.15 # Smear zone diameter (m) - typically 2-4 times dw
34
+ De:
35
+ 1.5 # Equivalent diameter of unit cell (m)
36
+ # For triangular pattern: De = 1.05 × S
37
+ # For square pattern: De = 1.13 × S
38
+ # where S = drain spacing
39
+ L_drain:
40
+ 20.0 # Total drain length (m)
41
+ # For two-way drainage: actual drain length
42
+ # For one-way drainage: 2 × actual drain length
43
+ kh: 2.0 # Horizontal permeability (m/year)
44
+ ks: 1.0 # Smear zone permeability (m/year) - typically 0.5-0.67 × kh
45
+ qw:
46
+ 100.0 # Well discharge capacity (m³/year)
47
+ # For negligible well resistance, use very large value (1e12)
48
+
49
+ # Analysis parameters
50
+ analysis:
51
+ surcharge: 100.0 # Applied surcharge load (kPa)
52
+ dt: 0.01 # Time step for finite difference (years)
53
+ t_max: 20.0 # Maximum time for analysis (years)
54
+ n_points: 200 # Number of points in settlement vs time curve
55
+
56
+ # Time points to check in report (years)
57
+ t_check:
58
+ - 0.1
59
+ - 0.5
60
+ - 1.0
61
+ - 2.0
62
+ - 5.0
63
+ - 10.0
64
+ - 20.0
65
+
66
+ # Times to generate consolidation profiles (years)
67
+ t_profiles:
68
+ - 0.5
69
+ - 2.0
70
+ - 10.0
pvd_consolidation.py ADDED
@@ -0,0 +1,762 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Multilayer Prefabricated Vertical Drain (PVD) Consolidation Analysis
3
+ Calculates settlement vs time using finite difference method
4
+ """
5
+
6
+ import numpy as np
7
+ import matplotlib.pyplot as plt
8
+ import yaml
9
+ import argparse
10
+ import os
11
+ from dataclasses import dataclass
12
+ from typing import List, Tuple, Dict, Any
13
+
14
+
15
+ @dataclass
16
+ class SoilLayer:
17
+ """Soil layer properties"""
18
+
19
+ thickness: float # Layer thickness (m)
20
+ Cv: float # Vertical coefficient of consolidation (m²/year)
21
+ Ch: float # Horizontal coefficient of consolidation (m²/year)
22
+ RR: float # Recompression ratio
23
+ CR: float # Compression ratio
24
+ sigma_ini: float # Initial effective stress (kPa)
25
+ sigma_p: float # Preconsolidation pressure (kPa)
26
+
27
+
28
+ @dataclass
29
+ class PVDProperties:
30
+ """PVD installation properties"""
31
+
32
+ dw: float # Equivalent diameter of drain (m)
33
+ ds: float # Smear zone diameter (m)
34
+ De: float # Equivalent diameter of unit cell (m)
35
+ L_drain: float # Total drain spacing for two-way drainage (m)
36
+ kh: float # Horizontal permeability (m/year)
37
+ ks: float # Smear zone permeability (m/year)
38
+ qw: float # Well discharge capacity (m³/year)
39
+
40
+
41
+ class PVDConsolidation:
42
+ """
43
+ Multilayer PVD consolidation analysis using finite difference method
44
+ """
45
+
46
+ def __init__(
47
+ self,
48
+ soil_layers: List[SoilLayer],
49
+ pvd: PVDProperties,
50
+ surcharge: float,
51
+ dt: float = 0.01,
52
+ ):
53
+ """
54
+ Initialize PVD consolidation analysis
55
+
56
+ Parameters:
57
+ -----------
58
+ soil_layers : List[SoilLayer]
59
+ List of soil layers from top to bottom
60
+ pvd : PVDProperties
61
+ PVD installation properties
62
+ surcharge : float
63
+ Applied surcharge load (kPa)
64
+ dt : float
65
+ Time step for finite difference (years)
66
+ """
67
+ self.layers = soil_layers
68
+ self.pvd = pvd
69
+ self.surcharge = surcharge
70
+ self.dt = dt
71
+
72
+ # Calculate total thickness
73
+ self.total_thickness = sum(layer.thickness for layer in soil_layers)
74
+
75
+ # Initialize mesh
76
+ self._setup_mesh()
77
+
78
+ def _setup_mesh(self, nodes_per_meter: int = 10):
79
+ """Setup finite difference mesh"""
80
+ self.nodes_per_meter = nodes_per_meter
81
+
82
+ # Create mesh for each layer
83
+ self.z_coords = []
84
+ self.layer_indices = []
85
+ self.Cv_profile = []
86
+ self.Ch_profile = []
87
+
88
+ z = 0
89
+ for i, layer in enumerate(self.layers):
90
+ n_nodes = max(int(layer.thickness * nodes_per_meter), 2)
91
+ z_layer = np.linspace(z, z + layer.thickness, n_nodes, endpoint=False)
92
+
93
+ self.z_coords.extend(z_layer)
94
+ self.layer_indices.extend([i] * len(z_layer))
95
+ self.Cv_profile.extend([layer.Cv] * len(z_layer))
96
+ self.Ch_profile.extend([layer.Ch] * len(z_layer))
97
+
98
+ z += layer.thickness
99
+
100
+ # Add final node
101
+ self.z_coords.append(self.total_thickness)
102
+ self.layer_indices.append(len(self.layers) - 1)
103
+ self.Cv_profile.append(self.layers[-1].Cv)
104
+ self.Ch_profile.append(self.layers[-1].Ch)
105
+
106
+ self.z_coords = np.array(self.z_coords)
107
+ self.layer_indices = np.array(self.layer_indices)
108
+ self.Cv_profile = np.array(self.Cv_profile)
109
+ self.Ch_profile = np.array(self.Ch_profile)
110
+
111
+ self.n_nodes = len(self.z_coords)
112
+ self.dz = np.diff(self.z_coords)
113
+
114
+ def calculate_pvd_factors(self) -> Tuple[float, float, float]:
115
+ """
116
+ Calculate PVD influence factors
117
+
118
+ Returns:
119
+ --------
120
+ Fn, Fs, Fr : float
121
+ Geometric, smear, and well resistance factors
122
+ """
123
+ # Geometric factor (n ratio)
124
+ n = self.pvd.De / self.pvd.dw
125
+
126
+ # Fn - Geometric factor
127
+ Fn = (n**2 / (n**2 - 1)) * np.log(n) - 3 / 4 + 1 / n**2
128
+
129
+ # Fs - Smear effect factor
130
+ s = self.pvd.ds / self.pvd.dw
131
+ Fs = ((self.pvd.kh / self.pvd.ks) - 1) * np.log(s)
132
+
133
+ # Fr - Well resistance factor
134
+ # For typical band drains: Fr = π(2L-l)l/(qw·kh) where l = L/2
135
+ # Simplified for two-way drainage
136
+ L = self.pvd.L_drain
137
+ if self.pvd.qw > 1e10: # If qw is very large, assume negligible well resistance
138
+ Fr = 0.0
139
+ else:
140
+ # Using Hansbo formula: Fr = (L²/(8·qw))·(kh)
141
+ # More typical: Fr = π·L²·kh/(8·qw) for two-way drainage
142
+ Fr = (np.pi * L**2 * self.pvd.kh) / (8 * self.pvd.qw)
143
+
144
+ return Fn, Fs, Fr
145
+
146
+ def calculate_Uh(self, t: float) -> np.ndarray:
147
+ """
148
+ Calculate degree of consolidation in horizontal direction
149
+ using finite difference method
150
+
151
+ Parameters:
152
+ -----------
153
+ t : float
154
+ Time (years)
155
+
156
+ Returns:
157
+ --------
158
+ Uh : ndarray
159
+ Degree of horizontal consolidation at each node
160
+ """
161
+ # Calculate PVD factors
162
+ Fn, Fs, Fr = self.calculate_pvd_factors()
163
+ F_total = Fn + Fs + Fr
164
+
165
+ # Initialize excess pore pressure (normalized)
166
+ u = np.ones(self.n_nodes) # Initially all excess pore pressure = surcharge
167
+ u_history = [u.copy()]
168
+
169
+ # Time stepping
170
+ n_steps = int(t / self.dt)
171
+
172
+ for step in range(n_steps):
173
+ u_new = u.copy()
174
+
175
+ # Finite difference for radial consolidation
176
+ # ∂u/∂t = Ch * [∂²u/∂r² + (1/r)(∂u/∂r)]
177
+ # Simplified for radial drainage with PVD
178
+
179
+ for i in range(1, self.n_nodes - 1):
180
+ Ch = self.Ch_profile[i]
181
+
182
+ # Radial drainage term (simplified)
183
+ # Using equivalent time factor approach
184
+ Th = Ch * self.dt / (self.pvd.De**2 / 4)
185
+
186
+ # Update excess pore pressure
187
+ decay_rate = 8 * Th / F_total
188
+ u_new[i] = u[i] * np.exp(-decay_rate)
189
+
190
+ # Boundary conditions
191
+ u_new[0] = 0 # Top drainage
192
+ u_new[-1] = 0 # Bottom drainage (if two-way)
193
+
194
+ u = u_new
195
+
196
+ if step % max(1, n_steps // 100) == 0:
197
+ u_history.append(u.copy())
198
+
199
+ # Calculate Uh (degree of consolidation)
200
+ Uh = 1 - u
201
+
202
+ return Uh
203
+
204
+ def calculate_Uv(self, t: float) -> np.ndarray:
205
+ """
206
+ Calculate degree of consolidation in vertical direction
207
+
208
+ Parameters:
209
+ -----------
210
+ t : float
211
+ Time (years)
212
+
213
+ Returns:
214
+ --------
215
+ Uv : ndarray
216
+ Degree of vertical consolidation at each node
217
+ """
218
+ Uv = np.zeros(self.n_nodes)
219
+
220
+ for i in range(self.n_nodes):
221
+ z = self.z_coords[i]
222
+ Cv = self.Cv_profile[i]
223
+ H = self.total_thickness
224
+
225
+ # Time factor
226
+ Tv = Cv * t / H**2
227
+
228
+ # Calculate Uv using Terzaghi's solution
229
+ if Tv < 0.217:
230
+ Uv[i] = np.sqrt(4 * Tv / np.pi)
231
+ else:
232
+ Uv[i] = 1 - (8 / np.pi**2) * np.exp(-(np.pi**2) * Tv / 4)
233
+
234
+ Uv[i] = min(Uv[i], 1.0)
235
+
236
+ return Uv
237
+
238
+ def calculate_total_U(self, t: float) -> np.ndarray:
239
+ """
240
+ Calculate total degree of consolidation (combined vertical and horizontal)
241
+
242
+ U = 1 - (1 - Uh)(1 - Uv)
243
+
244
+ Parameters:
245
+ -----------
246
+ t : float
247
+ Time (years)
248
+
249
+ Returns:
250
+ --------
251
+ U : ndarray
252
+ Total degree of consolidation at each node
253
+ """
254
+ Uh = self.calculate_Uh(t)
255
+ Uv = self.calculate_Uv(t)
256
+
257
+ U = 1 - (1 - Uh) * (1 - Uv)
258
+
259
+ return U
260
+
261
+ def calculate_settlement(self, t: float) -> Tuple[float, np.ndarray]:
262
+ """
263
+ Calculate total settlement at time t
264
+
265
+ Parameters:
266
+ -----------
267
+ t : float
268
+ Time (years)
269
+
270
+ Returns:
271
+ --------
272
+ total_settlement : float
273
+ Total settlement (m)
274
+ layer_settlements : ndarray
275
+ Settlement for each layer (m)
276
+ """
277
+ U = self.calculate_total_U(t)
278
+
279
+ layer_settlements = np.zeros(len(self.layers))
280
+
281
+ for i, layer in enumerate(self.layers):
282
+ # Find nodes in this layer
283
+ layer_mask = self.layer_indices == i
284
+ U_layer = np.mean(U[layer_mask])
285
+
286
+ # Calculate final settlement for this layer
287
+ sigma_final = layer.sigma_ini + self.surcharge
288
+
289
+ # Settlement components
290
+ if sigma_final <= layer.sigma_p:
291
+ # Recompression only
292
+ Sc_final = (
293
+ layer.RR * np.log10(sigma_final / layer.sigma_ini) * layer.thickness
294
+ )
295
+ else:
296
+ if layer.sigma_ini >= layer.sigma_p:
297
+ # Virgin compression only
298
+ Sc_final = (
299
+ layer.CR
300
+ * np.log10(sigma_final / layer.sigma_ini)
301
+ * layer.thickness
302
+ )
303
+ else:
304
+ # Both recompression and virgin compression
305
+ Sc_recomp = (
306
+ layer.RR
307
+ * np.log10(layer.sigma_p / layer.sigma_ini)
308
+ * layer.thickness
309
+ )
310
+ Sc_virgin = (
311
+ layer.CR
312
+ * np.log10(sigma_final / layer.sigma_p)
313
+ * layer.thickness
314
+ )
315
+ Sc_final = Sc_recomp + Sc_virgin
316
+
317
+ # Settlement at time t
318
+ layer_settlements[i] = U_layer * Sc_final
319
+
320
+ total_settlement = np.sum(layer_settlements)
321
+
322
+ return total_settlement, layer_settlements
323
+
324
+ def settlement_vs_time(
325
+ self, t_max: float, n_points: int = 100
326
+ ) -> Tuple[np.ndarray, np.ndarray]:
327
+ """
328
+ Calculate settlement vs time curve
329
+
330
+ Parameters:
331
+ -----------
332
+ t_max : float
333
+ Maximum time (years)
334
+ n_points : int
335
+ Number of time points
336
+
337
+ Returns:
338
+ --------
339
+ time : ndarray
340
+ Time array (years)
341
+ settlement : ndarray
342
+ Settlement array (m)
343
+ """
344
+ time = np.linspace(0, t_max, n_points)
345
+ settlement = np.zeros(n_points)
346
+
347
+ for i, t in enumerate(time):
348
+ if t == 0:
349
+ settlement[i] = 0
350
+ else:
351
+ settlement[i], _ = self.calculate_settlement(t)
352
+
353
+ return time, settlement
354
+
355
+ def plot_settlement_vs_time(
356
+ self, t_max: float, n_points: int = 100, save_path: str = None
357
+ ):
358
+ """
359
+ Plot settlement vs time curve
360
+
361
+ Parameters:
362
+ -----------
363
+ t_max : float
364
+ Maximum time (years)
365
+ n_points : int
366
+ Number of time points
367
+ save_path : str, optional
368
+ Path to save the plot
369
+ """
370
+ time, settlement = self.settlement_vs_time(t_max, n_points)
371
+
372
+ # Convert to mm
373
+ settlement_mm = settlement * 1000
374
+
375
+ plt.figure(figsize=(10, 6))
376
+ plt.plot(time, settlement_mm, "b-", linewidth=2)
377
+ plt.xlabel("Time (years)", fontsize=12)
378
+ plt.ylabel("Settlement (mm)", fontsize=12)
379
+ plt.title(
380
+ "Settlement vs Time - PVD Consolidation", fontsize=14, fontweight="bold"
381
+ )
382
+ plt.grid(True, alpha=0.3)
383
+ plt.tight_layout()
384
+
385
+ if save_path:
386
+ plt.savefig(save_path, dpi=300, bbox_inches="tight")
387
+
388
+ plt.show()
389
+
390
+ return time, settlement_mm
391
+
392
+ def plot_degree_of_consolidation(self, t: float, save_path: str = None):
393
+ """
394
+ Plot degree of consolidation profile at time t
395
+
396
+ Parameters:
397
+ -----------
398
+ t : float
399
+ Time (years)
400
+ save_path : str, optional
401
+ Path to save the plot
402
+ """
403
+ Uh = self.calculate_Uh(t)
404
+ Uv = self.calculate_Uv(t)
405
+ U = self.calculate_total_U(t)
406
+
407
+ fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))
408
+
409
+ # Plot 1: Degree of consolidation profiles
410
+ ax1.plot(Uh * 100, self.z_coords, "r-", linewidth=2, label="Horizontal (Uh)")
411
+ ax1.plot(Uv * 100, self.z_coords, "b-", linewidth=2, label="Vertical (Uv)")
412
+ ax1.plot(U * 100, self.z_coords, "g-", linewidth=2, label="Total (U)")
413
+ ax1.set_xlabel("Degree of Consolidation (%)", fontsize=12)
414
+ ax1.set_ylabel("Depth (m)", fontsize=12)
415
+ ax1.set_title(
416
+ f"Consolidation Profile at t = {t:.2f} years",
417
+ fontsize=12,
418
+ fontweight="bold",
419
+ )
420
+ ax1.invert_yaxis()
421
+ ax1.grid(True, alpha=0.3)
422
+ ax1.legend()
423
+
424
+ # Plot 2: Excess pore pressure
425
+ u = 1 - U
426
+ ax2.plot(u * self.surcharge, self.z_coords, "k-", linewidth=2)
427
+ ax2.set_xlabel("Excess Pore Pressure (kPa)", fontsize=12)
428
+ ax2.set_ylabel("Depth (m)", fontsize=12)
429
+ ax2.set_title(
430
+ f"Excess Pore Pressure at t = {t:.2f} years", fontsize=12, fontweight="bold"
431
+ )
432
+ ax2.invert_yaxis()
433
+ ax2.grid(True, alpha=0.3)
434
+
435
+ plt.tight_layout()
436
+
437
+ if save_path:
438
+ plt.savefig(save_path, dpi=300, bbox_inches="tight")
439
+
440
+ plt.show()
441
+
442
+ def get_summary_report(self, t_check: List[float]) -> str:
443
+ """
444
+ Generate summary report for specified time points
445
+
446
+ Parameters:
447
+ -----------
448
+ t_check : List[float]
449
+ Time points to check (years)
450
+
451
+ Returns:
452
+ --------
453
+ report : str
454
+ Summary report
455
+ """
456
+ Fn, Fs, Fr = self.calculate_pvd_factors()
457
+
458
+ report = "=" * 70 + "\n"
459
+ report += "PVD CONSOLIDATION ANALYSIS SUMMARY\n"
460
+ report += "=" * 70 + "\n\n"
461
+
462
+ report += "PVD PARAMETERS:\n"
463
+ report += f" Equivalent drain diameter (dw): {self.pvd.dw:.3f} m\n"
464
+ report += f" Smear zone diameter (ds): {self.pvd.ds:.3f} m\n"
465
+ report += f" Unit cell diameter (De): {self.pvd.De:.3f} m\n"
466
+ report += (
467
+ f" Drain spacing ratio (n = De/dw): {self.pvd.De / self.pvd.dw:.2f}\n"
468
+ )
469
+ report += f" Geometric factor (Fn): {Fn:.4f}\n"
470
+ report += f" Smear factor (Fs): {Fs:.4f}\n"
471
+ report += f" Well resistance (Fr): {Fr:.4f}\n"
472
+ report += f" Total resistance (F): {Fn + Fs + Fr:.4f}\n\n"
473
+
474
+ report += "SOIL PROFILE:\n"
475
+ for i, layer in enumerate(self.layers):
476
+ report += f" Layer {i + 1}:\n"
477
+ report += f" Thickness: {layer.thickness:.2f} m\n"
478
+ report += f" Ch: {layer.Ch:.4f} m²/year\n"
479
+ report += f" Cv: {layer.Cv:.4f} m²/year\n"
480
+ report += f" RR: {layer.RR:.4f}\n"
481
+ report += f" CR: {layer.CR:.4f}\n"
482
+ report += f" σ'ini: {layer.sigma_ini:.1f} kPa\n"
483
+ report += f" σ'p: {layer.sigma_p:.1f} kPa\n\n"
484
+
485
+ report += f"Applied surcharge: {self.surcharge:.1f} kPa\n\n"
486
+ report += "=" * 70 + "\n"
487
+ report += "SETTLEMENT vs TIME:\n"
488
+ report += "=" * 70 + "\n"
489
+ report += f"{'Time (years)':<15} {'Settlement (mm)':<20} {'U (%)':<15}\n"
490
+ report += "-" * 70 + "\n"
491
+
492
+ for t in t_check:
493
+ settlement, _ = self.calculate_settlement(t)
494
+ U = self.calculate_total_U(t)
495
+ U_avg = np.mean(U)
496
+ report += f"{t:<15.2f} {settlement * 1000:<20.2f} {U_avg * 100:<15.1f}\n"
497
+
498
+ report += "=" * 70 + "\n"
499
+
500
+ return report
501
+
502
+
503
+ def example_usage():
504
+ """Example usage of PVD consolidation analysis"""
505
+
506
+ # Define soil layers (from top to bottom)
507
+ layers = [
508
+ SoilLayer(
509
+ thickness=5.0, # 5 m thick
510
+ Cv=0.5, # 0.5 m²/year vertical consolidation
511
+ Ch=1.5, # 1.5 m²/year horizontal consolidation
512
+ RR=0.05, # Recompression ratio
513
+ CR=0.30, # Compression ratio
514
+ sigma_ini=50.0, # Initial effective stress 50 kPa
515
+ sigma_p=80.0, # Preconsolidation pressure 80 kPa
516
+ ),
517
+ SoilLayer(
518
+ thickness=8.0, # 8 m thick
519
+ Cv=0.3,
520
+ Ch=1.0,
521
+ RR=0.04,
522
+ CR=0.35,
523
+ sigma_ini=90.0,
524
+ sigma_p=90.0,
525
+ ),
526
+ SoilLayer(
527
+ thickness=7.0, # 7 m thick
528
+ Cv=0.4,
529
+ Ch=1.2,
530
+ RR=0.045,
531
+ CR=0.32,
532
+ sigma_ini=140.0,
533
+ sigma_p=150.0,
534
+ ),
535
+ ]
536
+
537
+ # Define PVD properties
538
+ pvd = PVDProperties(
539
+ dw=0.05, # 50 mm equivalent drain diameter
540
+ ds=0.15, # 150 mm smear zone diameter
541
+ De=1.5, # 1.5 m equivalent unit cell diameter (triangular spacing)
542
+ L_drain=20.0, # 20 m total drain length (two-way drainage)
543
+ kh=2.0, # 2 m/year horizontal permeability
544
+ ks=0.5, # 0.5 m/year smear zone permeability
545
+ qw=50.0, # 50 m³/year well discharge capacity
546
+ )
547
+
548
+ # Applied surcharge
549
+ surcharge = 100.0 # 100 kPa
550
+
551
+ # Create analysis object
552
+ analysis = PVDConsolidation(layers, pvd, surcharge, dt=0.01)
553
+
554
+ # Generate summary report
555
+ t_check = [0.1, 0.5, 1.0, 2.0, 5.0, 10.0, 20.0]
556
+ print(analysis.get_summary_report(t_check))
557
+
558
+ # Plot settlement vs time
559
+ print("\nGenerating settlement vs time plot...")
560
+ time, settlement = analysis.plot_settlement_vs_time(
561
+ t_max=20.0, n_points=200, save_path="settlement_vs_time.png"
562
+ )
563
+
564
+ # Plot consolidation profiles at different times
565
+ print("Generating consolidation profile plots...")
566
+ for t in [0.5, 2.0, 10.0]:
567
+ analysis.plot_degree_of_consolidation(
568
+ t, save_path=f"consolidation_profile_t{t:.1f}.png"
569
+ )
570
+
571
+ print("\nAnalysis complete!")
572
+
573
+
574
+ def load_yaml_data(yaml_file: str) -> Dict[str, Any]:
575
+ """
576
+ Load PVD analysis data from YAML file
577
+
578
+ Parameters:
579
+ -----------
580
+ yaml_file : str
581
+ Path to YAML file
582
+
583
+ Returns:
584
+ --------
585
+ data : dict
586
+ Dictionary containing analysis parameters
587
+ """
588
+ with open(yaml_file, "r") as f:
589
+ data = yaml.safe_load(f)
590
+ return data
591
+
592
+
593
+ def create_analysis_from_yaml(yaml_file: str) -> PVDConsolidation:
594
+ """
595
+ Create PVDConsolidation object from YAML file
596
+
597
+ Parameters:
598
+ -----------
599
+ yaml_file : str
600
+ Path to YAML file
601
+
602
+ Returns:
603
+ --------
604
+ analysis : PVDConsolidation
605
+ PVD consolidation analysis object
606
+ """
607
+ data = load_yaml_data(yaml_file)
608
+
609
+ # Create soil layers
610
+ layers = []
611
+ for layer_data in data["soil_layers"]:
612
+ layer = SoilLayer(
613
+ thickness=layer_data["thickness"],
614
+ Cv=layer_data["Cv"],
615
+ Ch=layer_data["Ch"],
616
+ RR=layer_data["RR"],
617
+ CR=layer_data["CR"],
618
+ sigma_ini=layer_data["sigma_ini"],
619
+ sigma_p=layer_data["sigma_p"],
620
+ )
621
+ layers.append(layer)
622
+
623
+ # Create PVD properties
624
+ pvd_data = data["pvd"]
625
+ pvd = PVDProperties(
626
+ dw=pvd_data["dw"],
627
+ ds=pvd_data["ds"],
628
+ De=pvd_data["De"],
629
+ L_drain=pvd_data["L_drain"],
630
+ kh=pvd_data["kh"],
631
+ ks=pvd_data["ks"],
632
+ qw=pvd_data["qw"],
633
+ )
634
+
635
+ # Get analysis parameters
636
+ surcharge = data["analysis"]["surcharge"]
637
+ dt = data["analysis"].get("dt", 0.01)
638
+
639
+ # Create analysis object
640
+ analysis = PVDConsolidation(layers, pvd, surcharge, dt)
641
+
642
+ return analysis, data
643
+
644
+
645
+ def run_analysis_from_yaml(yaml_file: str, output_dir: str = None):
646
+ """
647
+ Run complete PVD analysis from YAML file
648
+
649
+ Parameters:
650
+ -----------
651
+ yaml_file : str
652
+ Path to YAML input file
653
+ output_dir : str, optional
654
+ Directory to save output files
655
+ """
656
+ print(f"Loading data from: {yaml_file}")
657
+ analysis, data = create_analysis_from_yaml(yaml_file)
658
+
659
+ # Create output directory
660
+ if output_dir is None:
661
+ output_dir = os.path.dirname(yaml_file) or "."
662
+ os.makedirs(output_dir, exist_ok=True)
663
+
664
+ # Get analysis parameters
665
+ analysis_params = data["analysis"]
666
+ t_max = analysis_params.get("t_max", 20.0)
667
+ n_points = analysis_params.get("n_points", 200)
668
+ t_check = analysis_params.get("t_check", [0.1, 0.5, 1.0, 2.0, 5.0, 10.0, 20.0])
669
+ t_profiles = analysis_params.get("t_profiles", [0.5, 2.0, 10.0])
670
+
671
+ # Generate summary report
672
+ print("\n" + "=" * 70)
673
+ print("RUNNING PVD CONSOLIDATION ANALYSIS")
674
+ print("=" * 70 + "\n")
675
+
676
+ report = analysis.get_summary_report(t_check)
677
+ print(report)
678
+
679
+ # Save report to file
680
+ report_file = os.path.join(output_dir, "pvd_analysis_report.txt")
681
+ with open(report_file, "w") as f:
682
+ f.write(report)
683
+ print(f"\nReport saved to: {report_file}")
684
+
685
+ # Plot settlement vs time
686
+ print("\nGenerating settlement vs time plot...")
687
+ settlement_plot = os.path.join(output_dir, "settlement_vs_time.png")
688
+ time, settlement = analysis.plot_settlement_vs_time(
689
+ t_max=t_max, n_points=n_points, save_path=settlement_plot
690
+ )
691
+ print(f"Plot saved to: {settlement_plot}")
692
+
693
+ # Save settlement data to CSV
694
+ csv_file = os.path.join(output_dir, "settlement_data.csv")
695
+ np.savetxt(
696
+ csv_file,
697
+ np.column_stack((time, settlement * 1000)),
698
+ delimiter=",",
699
+ header="Time (years),Settlement (mm)",
700
+ comments="",
701
+ )
702
+ print(f"Data saved to: {csv_file}")
703
+
704
+ # Plot consolidation profiles at different times
705
+ print("\nGenerating consolidation profile plots...")
706
+ for t in t_profiles:
707
+ profile_plot = os.path.join(output_dir, f"consolidation_profile_t{t:.1f}y.png")
708
+ analysis.plot_degree_of_consolidation(t, save_path=profile_plot)
709
+ print(f"Profile at t={t:.1f} years saved to: {profile_plot}")
710
+
711
+ print("\n" + "=" * 70)
712
+ print("ANALYSIS COMPLETE!")
713
+ print("=" * 70)
714
+
715
+
716
+ def main():
717
+ """Main CLI interface"""
718
+ parser = argparse.ArgumentParser(
719
+ description="PVD Consolidation Analysis - Settlement vs Time Calculator",
720
+ formatter_class=argparse.RawDescriptionHelpFormatter,
721
+ epilog="""
722
+ Examples:
723
+ # Run analysis from YAML file
724
+ python pvd_consolidation.py --data input.yaml
725
+
726
+ # Specify output directory
727
+ python pvd_consolidation.py --data input.yaml --output results/
728
+
729
+ # Run example analysis
730
+ python pvd_consolidation.py --example
731
+ """,
732
+ )
733
+
734
+ parser.add_argument("--data", type=str, help="Path to YAML input file")
735
+ parser.add_argument(
736
+ "--output",
737
+ type=str,
738
+ default=None,
739
+ help="Output directory for results (default: same as input file)",
740
+ )
741
+ parser.add_argument(
742
+ "--example",
743
+ action="store_true",
744
+ help="Run example analysis with default parameters",
745
+ )
746
+
747
+ args = parser.parse_args()
748
+
749
+ if args.example:
750
+ print("Running example analysis...")
751
+ example_usage()
752
+ elif args.data:
753
+ if not os.path.exists(args.data):
754
+ print(f"Error: Input file '{args.data}' not found!")
755
+ return
756
+ run_analysis_from_yaml(args.data, args.output)
757
+ else:
758
+ parser.print_help()
759
+
760
+
761
+ if __name__ == "__main__":
762
+ main()
requirements.txt CHANGED
@@ -1,3 +1,4 @@
1
- altair
2
- pandas
3
- streamlit
 
 
1
+ numpy>=1.21.0
2
+ matplotlib>=3.4.0
3
+ pyyaml>=5.4.0
4
+ streamlit>=1.28.0
test_input.yaml ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Quick test input for PVD consolidation
2
+ soil_layers:
3
+ - thickness: 10.0
4
+ Cv: 0.5
5
+ Ch: 2.0
6
+ RR: 0.05
7
+ CR: 0.30
8
+ sigma_ini: 50.0
9
+ sigma_p: 80.0
10
+
11
+ pvd:
12
+ dw: 0.05
13
+ ds: 0.15
14
+ De: 1.5
15
+ L_drain: 10.0
16
+ kh: 2.0
17
+ ks: 1.0
18
+ qw: 1000000000000.0 # Negligible well resistance (1e12)
19
+
20
+ analysis:
21
+ surcharge: 100.0
22
+ dt: 0.005
23
+ t_max: 2.0
24
+ n_points: 50
25
+
26
+ t_check:
27
+ - 0.1
28
+ - 0.25
29
+ - 0.5
30
+ - 1.0
31
+
32
+ t_profiles:
33
+ - 0.5