geolysis 0.9.0__py3-none-any.whl → 0.10.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- geolysis/__init__.py +3 -3
- geolysis/bearing_capacity/abc/__init__.py +21 -0
- geolysis/bearing_capacity/abc/_cohl/__init__.py +109 -0
- geolysis/bearing_capacity/abc/{cohl → _cohl}/_core.py +19 -8
- geolysis/bearing_capacity/abc/_cohl/bowles_abc.py +103 -0
- geolysis/bearing_capacity/abc/_cohl/meyerhof_abc.py +100 -0
- geolysis/bearing_capacity/abc/_cohl/terzaghi_abc.py +143 -0
- geolysis/bearing_capacity/ubc/__init__.py +107 -128
- geolysis/bearing_capacity/ubc/_core.py +65 -52
- geolysis/bearing_capacity/ubc/_hansen_ubc.py +271 -0
- geolysis/bearing_capacity/ubc/_terzaghi_ubc.py +178 -0
- geolysis/bearing_capacity/ubc/_vesic_ubc.py +253 -0
- geolysis/foundation.py +146 -136
- geolysis/soil_classifier.py +379 -283
- geolysis/spt.py +323 -257
- geolysis/{utils/__init__.py → utils.py} +44 -33
- geolysis-0.10.0.dist-info/METADATA +181 -0
- geolysis-0.10.0.dist-info/RECORD +22 -0
- {geolysis-0.9.0.dist-info → geolysis-0.10.0.dist-info}/WHEEL +1 -1
- geolysis/bearing_capacity/abc/cohl/__init__.py +0 -137
- geolysis/bearing_capacity/abc/cohl/bowles_abc.py +0 -96
- geolysis/bearing_capacity/abc/cohl/meyerhof_abc.py +0 -96
- geolysis/bearing_capacity/abc/cohl/terzaghi_abc.py +0 -131
- geolysis/bearing_capacity/ubc/hansen_ubc.py +0 -287
- geolysis/bearing_capacity/ubc/terzaghi_ubc.py +0 -246
- geolysis/bearing_capacity/ubc/vesic_ubc.py +0 -293
- geolysis/utils/exceptions.py +0 -65
- geolysis/utils/validators.py +0 -119
- geolysis-0.9.0.dist-info/METADATA +0 -206
- geolysis-0.9.0.dist-info/RECORD +0 -24
- {geolysis-0.9.0.dist-info → geolysis-0.10.0.dist-info}/licenses/LICENSE.txt +0 -0
- {geolysis-0.9.0.dist-info → geolysis-0.10.0.dist-info}/top_level.txt +0 -0
geolysis/spt.py
CHANGED
@@ -1,69 +1,103 @@
|
|
1
|
-
"""This module provides classes for performing Standard Penetration Test (SPT)
|
2
|
-
corrections, including energy, overburden pressure, and dilatancy corrections,
|
3
|
-
as well as calculating design N-values.
|
4
|
-
"""
|
5
1
|
import enum
|
6
2
|
from abc import abstractmethod
|
7
|
-
from typing import
|
8
|
-
|
9
|
-
from
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
3
|
+
from typing import Annotated, Final, Sequence
|
4
|
+
|
5
|
+
from func_validator import (
|
6
|
+
validate_func_args,
|
7
|
+
MustBeBetween,
|
8
|
+
MustBePositive,
|
9
|
+
MustBeMemberOf,
|
10
|
+
MustBeNonNegative,
|
11
|
+
MustBeGreaterThanOrEqual,
|
12
|
+
MustHaveLengthGreaterThan,
|
13
|
+
MustHaveValuesBetween,
|
14
|
+
)
|
15
|
+
|
16
|
+
from .utils import AbstractStrEnum, isclose, log10, mean, round_, sqrt
|
17
|
+
|
18
|
+
__all__ = [
|
19
|
+
"SPT",
|
20
|
+
"HammerType",
|
21
|
+
"SamplerType",
|
22
|
+
"EnergyCorrection",
|
23
|
+
"GibbsHoltzOPC",
|
24
|
+
"BazaraaPeckOPC",
|
25
|
+
"PeckOPC",
|
26
|
+
"LiaoWhitmanOPC",
|
27
|
+
"SkemptonOPC",
|
28
|
+
"DilatancyCorrection",
|
29
|
+
"OPCType",
|
30
|
+
"create_overburden_pressure_correction",
|
31
|
+
]
|
32
|
+
|
33
|
+
|
34
|
+
class SPTDesignMethod(AbstractStrEnum):
|
35
|
+
"""Enumeration of Standard Penetration Test (SPT) design methods.
|
36
|
+
|
37
|
+
Each member represents a different method for interpreting SPT
|
38
|
+
results in geotechnical design calculations.
|
39
|
+
"""
|
40
|
+
|
41
|
+
MINIMUM = "min"
|
42
|
+
"""Use the minimum SPT value."""
|
43
|
+
|
44
|
+
AVERAGE = "avg"
|
45
|
+
"""Use the average SPT value."""
|
46
|
+
|
47
|
+
WEIGHTED = "wgt"
|
48
|
+
"""Use the weighted SPT value."""
|
49
|
+
|
50
|
+
|
51
|
+
class SPT:
|
27
52
|
"""SPT Design Calculations.
|
28
53
|
|
29
|
-
Due to uncertainty in field procedure in standard penetration test
|
30
|
-
to consider all the N-value in the influence zone of a
|
31
|
-
was suggested to calculate the design N-value
|
32
|
-
calculating the allowable bearing capacity
|
33
|
-
than using a particular N-value. All
|
34
|
-
|
35
|
-
N-value from the base.
|
54
|
+
Due to uncertainty in field procedure in standard penetration test
|
55
|
+
and also to consider all the N-value in the influence zone of a
|
56
|
+
foundation, a method was suggested to calculate the design N-value
|
57
|
+
which should be used in calculating the allowable bearing capacity
|
58
|
+
of shallow foundation rather than using a particular N-value. All
|
59
|
+
the N-value from the influence zone is taken under consideration by
|
60
|
+
giving the highest weightage to the closest N-value from the base.
|
36
61
|
"""
|
37
62
|
|
38
|
-
def __init__(
|
39
|
-
|
63
|
+
def __init__(
|
64
|
+
self,
|
65
|
+
corrected_spt_n_values: Sequence[float],
|
66
|
+
method: SPTDesignMethod.WEIGHTED = "wgt",
|
67
|
+
):
|
40
68
|
"""
|
41
69
|
:param corrected_spt_n_values: Corrected SPT N-values within the
|
42
70
|
foundation influence zone.
|
43
|
-
:type corrected_spt_n_values: Sequence[float]
|
44
71
|
"""
|
45
72
|
self.corrected_spt_n_values = corrected_spt_n_values
|
46
73
|
self.method = method
|
47
74
|
|
48
75
|
@property
|
49
76
|
def corrected_spt_n_values(self) -> Sequence[float]:
|
50
|
-
"""
|
77
|
+
"""
|
78
|
+
Corrected SPT N-values within the foundation influence zone.
|
79
|
+
"""
|
51
80
|
return self._corrected_spt_n_values
|
52
81
|
|
53
82
|
@corrected_spt_n_values.setter
|
54
|
-
@
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
83
|
+
@validate_func_args
|
84
|
+
def corrected_spt_n_values(
|
85
|
+
self,
|
86
|
+
corrected_spt_n_values: Annotated[
|
87
|
+
Sequence[float],
|
88
|
+
MustHaveLengthGreaterThan(1),
|
89
|
+
MustHaveValuesBetween(min_value=1.0, max_value=100.0),
|
90
|
+
],
|
91
|
+
) -> None:
|
92
|
+
self._corrected_spt_n_values = corrected_spt_n_values
|
59
93
|
|
60
94
|
@property
|
61
95
|
def method(self):
|
62
96
|
return self._method
|
63
97
|
|
64
98
|
@method.setter
|
65
|
-
@
|
66
|
-
def method(self, val: str)
|
99
|
+
@validate_func_args
|
100
|
+
def method(self, val: Annotated[str, MustBeMemberOf(SPTDesignMethod)]):
|
67
101
|
self._method = val
|
68
102
|
|
69
103
|
@staticmethod
|
@@ -89,97 +123,121 @@ class SPTNDesign:
|
|
89
123
|
|
90
124
|
@round_(ndigits=1)
|
91
125
|
def n_design(self):
|
92
|
-
r"""Calculates the SPT N-design within the foundation influence
|
126
|
+
r"""Calculates the SPT N-design within the foundation influence
|
127
|
+
zone.
|
93
128
|
|
94
|
-
If
|
95
|
-
influence zone as the SPT N-design value. This
|
96
|
-
by
|
129
|
+
If `method="min"`, it returns the minimum N-value within the
|
130
|
+
foundation influence zone as the SPT N-design value. This
|
131
|
+
approach was suggested by `Terzaghi & Peck (1948)`.
|
97
132
|
|
98
|
-
if
|
99
|
-
influence zone as the SPT N-design value.
|
100
|
-
|
101
|
-
if ``method="wgt"``, it returns the weighted average N-value within the
|
133
|
+
if `method="avg"`, it returns the average N-value within the
|
102
134
|
foundation influence zone as the SPT N-design value.
|
103
135
|
|
104
|
-
|
136
|
+
if `method="wgt"`, it returns the weighted average N-value
|
137
|
+
within the foundation influence zone as the SPT N-design value.
|
105
138
|
|
106
|
-
.. math::
|
107
139
|
|
108
|
-
|
109
|
-
|
140
|
+
$$
|
141
|
+
N_{design} = \dfrac{\sum_{i=1}^{n} \frac{N_i}{i^2}}
|
142
|
+
{\sum_{i=1}^{n}\frac{1}{i^2}}
|
143
|
+
$$
|
110
144
|
"""
|
111
145
|
if self.method == "min":
|
112
|
-
|
146
|
+
_n_design = self._min_spt_n_design
|
113
147
|
elif self.method == "avg":
|
114
|
-
|
115
|
-
else:
|
116
|
-
|
148
|
+
_n_design = self._avg_spt_n_design
|
149
|
+
else:
|
150
|
+
_n_design = self._wgt_spt_n_design
|
117
151
|
|
152
|
+
return _n_design(self.corrected_spt_n_values)
|
153
|
+
|
154
|
+
|
155
|
+
class HammerType(AbstractStrEnum):
|
156
|
+
"""Enumeration of hammer types used in geotechnical testing.
|
157
|
+
|
158
|
+
Each member represents a different type of hammer used for
|
159
|
+
Standard Penetration Test (SPT) or other soil testing methods.
|
160
|
+
"""
|
118
161
|
|
119
|
-
@enum_repr
|
120
|
-
class HammerType(enum.StrEnum):
|
121
|
-
"""Enumeration of hammer types."""
|
122
162
|
AUTOMATIC = enum.auto()
|
163
|
+
"""Automatic hammer."""
|
164
|
+
|
123
165
|
DONUT_1 = enum.auto()
|
166
|
+
"""Donut-type hammer, variant 1."""
|
167
|
+
|
124
168
|
DONUT_2 = enum.auto()
|
169
|
+
"""Donut-type hammer, variant 2."""
|
170
|
+
|
125
171
|
SAFETY = enum.auto()
|
172
|
+
"""Safety hammer."""
|
173
|
+
|
126
174
|
DROP = enum.auto()
|
175
|
+
"""Drop hammer."""
|
176
|
+
|
127
177
|
PIN = enum.auto()
|
178
|
+
"""Pin-type hammer."""
|
179
|
+
|
128
180
|
|
181
|
+
class SamplerType(AbstractStrEnum):
|
182
|
+
"""Enumeration of soil sampler types.
|
183
|
+
|
184
|
+
Each member represents a different type of sampler used in
|
185
|
+
Standard Penetration Tests (SPT) or other geotechnical sampling
|
186
|
+
methods.
|
187
|
+
"""
|
129
188
|
|
130
|
-
@enum_repr
|
131
|
-
class SamplerType(enum.StrEnum):
|
132
|
-
"""Enumeration of sampler types."""
|
133
189
|
STANDARD = enum.auto()
|
190
|
+
"""Standard sampler."""
|
191
|
+
|
134
192
|
NON_STANDARD = enum.auto()
|
193
|
+
"""Non-standard sampler."""
|
135
194
|
|
136
195
|
|
137
196
|
class EnergyCorrection:
|
138
197
|
r"""SPT N-value standardized for field procedures.
|
139
198
|
|
140
|
-
On the basis of field observations, it appears reasonable to
|
141
|
-
the field SPT N-value as a function of the input driving
|
142
|
-
dissipation around the sampler around the surrounding
|
143
|
-
in testing procedures may be at least partially
|
144
|
-
the measured N-value to
|
145
|
-
transferred to the tip of the
|
199
|
+
On the basis of field observations, it appears reasonable to
|
200
|
+
standardize the field SPT N-value as a function of the input driving
|
201
|
+
energy and its dissipation around the sampler around the surrounding
|
202
|
+
soil. The variations in testing procedures may be at least partially
|
203
|
+
compensated by converting the measured N-value to $N_{60}$
|
204
|
+
assuming 60% hammer energy being transferred to the tip of the
|
205
|
+
standard split spoon.
|
146
206
|
"""
|
147
207
|
|
148
|
-
_HAMMER_EFFICIENCY_FACTORS = {
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
208
|
+
_HAMMER_EFFICIENCY_FACTORS = {
|
209
|
+
HammerType.AUTOMATIC: 0.70,
|
210
|
+
HammerType.DONUT_1: 0.60,
|
211
|
+
HammerType.DONUT_2: 0.50,
|
212
|
+
HammerType.SAFETY: 0.55,
|
213
|
+
HammerType.DROP: 0.45,
|
214
|
+
HammerType.PIN: 0.45,
|
215
|
+
}
|
216
|
+
|
217
|
+
_SAMPLER_CORRECTION_FACTORS = {
|
218
|
+
SamplerType.STANDARD: 1.00,
|
219
|
+
SamplerType.NON_STANDARD: 1.20,
|
220
|
+
}
|
221
|
+
|
222
|
+
def __init__(
|
223
|
+
self,
|
224
|
+
recorded_spt_n_value: int,
|
225
|
+
*,
|
226
|
+
energy_percentage=0.6,
|
227
|
+
borehole_diameter=65.0,
|
228
|
+
rod_length=3.0,
|
229
|
+
hammer_type=HammerType.DONUT_1,
|
230
|
+
sampler_type=SamplerType.STANDARD,
|
231
|
+
):
|
164
232
|
"""
|
165
233
|
:param recorded_spt_n_value: Recorded SPT N-value from field.
|
166
|
-
:type recorded_spt_n_value: int
|
167
|
-
|
168
|
-
:param energy_percentage: Energy percentage reaching the tip of the
|
169
|
-
sampler, defaults to 0.6
|
170
|
-
:type energy_percentage: float, optional
|
171
|
-
|
172
|
-
:param borehole_diameter: Borehole diameter (mm), defaults to 65.0.
|
173
|
-
:type borehole_diameter: float, optional
|
174
234
|
|
175
|
-
:param
|
176
|
-
|
177
|
-
|
178
|
-
:param
|
179
|
-
:
|
180
|
-
|
181
|
-
:param sampler_type: Sampler type, defaults to :py:enum:mem:`~SamplerType.STANDARD`
|
182
|
-
:type sampler_type: SamplerType, optional
|
235
|
+
:param energy_percentage: Energy percentage reaching the tip of
|
236
|
+
the sampler.
|
237
|
+
:param borehole_diameter: Borehole diameter (mm).
|
238
|
+
:param rod_length: Length of SPT rod, defaults to 3.0 (m).
|
239
|
+
:param hammer_type: Hammer type.
|
240
|
+
:param sampler_type: Sampler type.
|
183
241
|
"""
|
184
242
|
self.recorded_spt_n_value = int(recorded_spt_n_value)
|
185
243
|
self.energy_percentage = energy_percentage
|
@@ -194,9 +252,11 @@ class EnergyCorrection:
|
|
194
252
|
return self._recorded_spt_value
|
195
253
|
|
196
254
|
@recorded_spt_n_value.setter
|
197
|
-
@
|
198
|
-
|
199
|
-
|
255
|
+
@validate_func_args
|
256
|
+
def recorded_spt_n_value(
|
257
|
+
self,
|
258
|
+
val: Annotated[int, MustBeBetween(min_value=0, max_value=100)]
|
259
|
+
) -> None:
|
200
260
|
self._recorded_spt_value = val
|
201
261
|
|
202
262
|
@property
|
@@ -205,9 +265,11 @@ class EnergyCorrection:
|
|
205
265
|
return self._energy_percentage
|
206
266
|
|
207
267
|
@energy_percentage.setter
|
208
|
-
@
|
209
|
-
|
210
|
-
|
268
|
+
@validate_func_args
|
269
|
+
def energy_percentage(
|
270
|
+
self,
|
271
|
+
val: Annotated[float, MustBeBetween(min_value=0.0, max_value=1.0)]
|
272
|
+
) -> None:
|
211
273
|
self._energy_percentage = val
|
212
274
|
|
213
275
|
@property
|
@@ -216,9 +278,11 @@ class EnergyCorrection:
|
|
216
278
|
return self._borehole_diameter
|
217
279
|
|
218
280
|
@borehole_diameter.setter
|
219
|
-
@
|
220
|
-
|
221
|
-
|
281
|
+
@validate_func_args
|
282
|
+
def borehole_diameter(
|
283
|
+
self, val: Annotated[
|
284
|
+
float, MustBeBetween(min_value=65.0, max_value=200.0)]
|
285
|
+
) -> None:
|
222
286
|
self._borehole_diameter = val
|
223
287
|
|
224
288
|
@property
|
@@ -227,8 +291,8 @@ class EnergyCorrection:
|
|
227
291
|
return self._rod_length
|
228
292
|
|
229
293
|
@rod_length.setter
|
230
|
-
@
|
231
|
-
def rod_length(self, val: float)
|
294
|
+
@validate_func_args
|
295
|
+
def rod_length(self, val: Annotated[float, MustBePositive]):
|
232
296
|
self._rod_length = val
|
233
297
|
|
234
298
|
@property
|
@@ -236,17 +300,21 @@ class EnergyCorrection:
|
|
236
300
|
return self._hammer_type
|
237
301
|
|
238
302
|
@hammer_type.setter
|
239
|
-
@
|
240
|
-
def hammer_type(
|
241
|
-
|
303
|
+
@validate_func_args
|
304
|
+
def hammer_type(
|
305
|
+
self,
|
306
|
+
hammer_type: Annotated[HammerType, MustBeMemberOf(HammerType)]
|
307
|
+
):
|
308
|
+
self._hammer_type = hammer_type
|
242
309
|
|
243
310
|
@property
|
244
311
|
def sampler_type(self) -> SamplerType:
|
245
312
|
return self._sampler_type
|
246
313
|
|
247
314
|
@sampler_type.setter
|
248
|
-
@
|
249
|
-
def sampler_type(self,
|
315
|
+
@validate_func_args
|
316
|
+
def sampler_type(self,
|
317
|
+
val: Annotated[SamplerType, MustBeMemberOf(SamplerType)]):
|
250
318
|
self._sampler_type = val
|
251
319
|
|
252
320
|
@property
|
@@ -286,18 +354,19 @@ class EnergyCorrection:
|
|
286
354
|
def correction(self) -> float:
|
287
355
|
r"""Energy correction factor.
|
288
356
|
|
289
|
-
|
290
|
-
|
291
|
-
|
357
|
+
$$
|
358
|
+
N_{ENERGY} = \dfrac{E_H \cdot C_B \cdot C_S
|
359
|
+
\cdot C_R \cdot N}{ENERGY}
|
360
|
+
$$
|
292
361
|
|
293
|
-
|
294
|
-
|
295
|
-
``ENERGY``: 0.6, 0.55, etc
|
362
|
+
`ENERGY`: 0.6, 0.55, etc
|
296
363
|
"""
|
297
|
-
numerator = (
|
298
|
-
|
299
|
-
|
300
|
-
|
364
|
+
numerator = (
|
365
|
+
self.hammer_efficiency
|
366
|
+
* self.borehole_diameter_correction
|
367
|
+
* self.sampler_correction
|
368
|
+
* self.rod_length_correction
|
369
|
+
)
|
301
370
|
return numerator / self.energy_percentage
|
302
371
|
|
303
372
|
@round_(ndigits=1)
|
@@ -309,41 +378,52 @@ class EnergyCorrection:
|
|
309
378
|
class OPC:
|
310
379
|
"""Base class for Overburden Pressure Correction (OPC)."""
|
311
380
|
|
312
|
-
def __init__(self, std_spt_n_value: float, eop: float)
|
381
|
+
def __init__(self, std_spt_n_value: float, eop: float):
|
313
382
|
"""
|
314
|
-
:param std_spt_n_value: SPT N-value standardized for field
|
315
|
-
|
316
|
-
|
317
|
-
:param eop: Effective overburden pressure (:math:`kPa`).
|
318
|
-
:type eop: float
|
383
|
+
:param std_spt_n_value: SPT N-value standardized for field
|
384
|
+
procedures.
|
385
|
+
:param eop: Effective overburden pressure ($kPa$).
|
319
386
|
"""
|
320
387
|
self.std_spt_n_value = std_spt_n_value
|
321
388
|
self.eop = eop
|
322
389
|
|
390
|
+
@property
|
391
|
+
def eop(self) -> float:
|
392
|
+
"""Effective overburden pressure ($kPa$)."""
|
393
|
+
return self._eop
|
394
|
+
|
395
|
+
@eop.setter
|
396
|
+
@validate_func_args
|
397
|
+
def eop(self, val: Annotated[float, MustBeNonNegative]):
|
398
|
+
"""Effective overburden pressure ($kPa$)."""
|
399
|
+
self._eop = val
|
400
|
+
|
323
401
|
@property
|
324
402
|
def std_spt_n_value(self) -> float:
|
325
403
|
"""SPT N-value standardized for field procedures."""
|
326
404
|
return self._std_spt_n_value
|
327
405
|
|
328
406
|
@std_spt_n_value.setter
|
329
|
-
@
|
330
|
-
|
331
|
-
|
407
|
+
@validate_func_args
|
408
|
+
def std_spt_n_value(
|
409
|
+
self, val: Annotated[
|
410
|
+
float, MustBeBetween(min_value=0.0, max_value=100.0)]
|
411
|
+
):
|
332
412
|
self._std_spt_n_value = val
|
333
413
|
|
334
414
|
@round_(ndigits=1)
|
335
415
|
def corrected_spt_n_value(self) -> float:
|
336
416
|
r"""Corrected SPT N-value.
|
337
417
|
|
338
|
-
|
339
|
-
|
340
|
-
|
418
|
+
$$
|
419
|
+
(N_1)_{60} = C_N \cdot N_{60}
|
420
|
+
$$
|
341
421
|
|
342
|
-
|
422
|
+
!!! note
|
343
423
|
|
344
|
-
|
345
|
-
|
346
|
-
|
424
|
+
`60` is used in this case to represent `60%` hammer
|
425
|
+
efficiency and can be any percentage of hammer efficiency
|
426
|
+
e.g. $N_{55}$ for `55%` hammer efficiency.
|
347
427
|
"""
|
348
428
|
corrected_spt = self.correction() * self.std_spt_n_value
|
349
429
|
# Corrected SPT should not be more
|
@@ -356,67 +436,61 @@ class OPC:
|
|
356
436
|
|
357
437
|
|
358
438
|
class GibbsHoltzOPC(OPC):
|
359
|
-
"""Overburden Pressure Correction according to
|
439
|
+
"""Overburden Pressure Correction according to
|
440
|
+
`Gibbs & Holtz (1957)`.
|
441
|
+
"""
|
360
442
|
|
361
443
|
@property
|
362
444
|
def eop(self) -> float:
|
363
|
-
"""Effective overburden pressure (
|
445
|
+
"""Effective overburden pressure ($kPa$)."""
|
364
446
|
return self._eop
|
365
447
|
|
366
448
|
@eop.setter
|
367
|
-
@
|
368
|
-
|
369
|
-
|
449
|
+
@validate_func_args
|
450
|
+
def eop(self, val: Annotated[
|
451
|
+
float, MustBeBetween(min_value=0.0, max_value=280.0)]):
|
370
452
|
self._eop = val
|
371
453
|
|
372
454
|
def correction(self) -> float:
|
373
455
|
r"""SPT Correction.
|
374
456
|
|
375
|
-
|
376
|
-
|
377
|
-
|
457
|
+
$$
|
458
|
+
C_N = \dfrac{350}{\sigma_o + 70} \, \sigma_o \le 280kN/m^2
|
459
|
+
$$
|
378
460
|
|
379
|
-
|
380
|
-
|
381
|
-
divided by 2.0 to obtain the design value used in finding the
|
382
|
-
capacity of the soil.
|
461
|
+
$\frac{N_c}{N_{60}}$ should lie between 0.45 and 2.0, if
|
462
|
+
$\frac{N_c}{N_{60}}$ is greater than 2.0, :math:`N_c` should be
|
463
|
+
divided by 2.0 to obtain the design value used in finding the
|
464
|
+
bearing capacity of the soil.
|
383
465
|
"""
|
384
466
|
corr = 350.0 / (self.eop + 70.0)
|
385
467
|
return corr / 2.0 if corr > 2.0 else corr
|
386
468
|
|
387
469
|
|
388
470
|
class BazaraaPeckOPC(OPC):
|
389
|
-
"""Overburden Pressure Correction according to
|
390
|
-
also by
|
471
|
+
"""Overburden Pressure Correction according to `Bazaraa (1967)`, and
|
472
|
+
also by `Peck and Bazaraa (1969)`.
|
391
473
|
"""
|
392
474
|
|
393
475
|
#: Maximum effective overburden pressure (:math:`kPa`).
|
394
476
|
STD_PRESSURE: Final = 71.8
|
395
477
|
|
396
|
-
@property
|
397
|
-
def eop(self) -> float:
|
398
|
-
"""Effective overburden pressure (:math:`kPa`)."""
|
399
|
-
return self._eop
|
400
|
-
|
401
|
-
@eop.setter
|
402
|
-
@validators.ge(0.0)
|
403
|
-
def eop(self, val: float) -> None:
|
404
|
-
"""Effective overburden pressure (:math:`kPa`)."""
|
405
|
-
self._eop = val
|
406
|
-
|
407
478
|
def correction(self) -> float:
|
408
479
|
r"""SPT Correction.
|
409
480
|
|
410
|
-
|
411
|
-
|
412
|
-
|
481
|
+
$$
|
482
|
+
C_N = \dfrac{4}{1 + 0.0418 \cdot \sigma_o}, \,
|
483
|
+
\sigma_o \lt 71.8kN/m^2
|
484
|
+
$$
|
413
485
|
|
414
|
-
|
486
|
+
$$
|
487
|
+
C_N = \dfrac{4}{3.25 + 0.0104 \cdot \sigma_o},
|
488
|
+
\, \sigma_o \gt 71.8kN/m^2
|
489
|
+
$$
|
415
490
|
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
C_N &= 1 \, , \, \sigma_o = 71.8kN/m^2
|
491
|
+
$$
|
492
|
+
C_N = 1 \, , \, \sigma_o = 71.8kN/m^2
|
493
|
+
$$
|
420
494
|
"""
|
421
495
|
if isclose(self.eop, self.STD_PRESSURE, rel_tol=0.01):
|
422
496
|
corr = 1.0
|
@@ -428,165 +502,157 @@ class BazaraaPeckOPC(OPC):
|
|
428
502
|
|
429
503
|
|
430
504
|
class PeckOPC(OPC):
|
431
|
-
"""Overburden Pressure Correction according to
|
505
|
+
"""Overburden Pressure Correction according to
|
506
|
+
`Peck et al. (1974)`.
|
507
|
+
"""
|
432
508
|
|
433
509
|
@property
|
434
510
|
def eop(self) -> float:
|
435
|
-
"""Effective overburden pressure (
|
511
|
+
"""Effective overburden pressure ($kPa$)."""
|
436
512
|
return self._eop
|
437
513
|
|
438
514
|
@eop.setter
|
439
|
-
@
|
440
|
-
def eop(self, val: float)
|
515
|
+
@validate_func_args
|
516
|
+
def eop(self, val: Annotated[float, MustBeGreaterThanOrEqual(24.0)]):
|
441
517
|
self._eop = val
|
442
518
|
|
443
519
|
def correction(self) -> float:
|
444
520
|
r"""SPT Correction.
|
445
521
|
|
446
|
-
|
447
|
-
|
448
|
-
|
522
|
+
$$
|
523
|
+
C_N = 0.77 \log \left(\dfrac{2000}{\sigma_o} \right)
|
524
|
+
$$
|
449
525
|
"""
|
450
526
|
return 0.77 * log10(2000.0 / self.eop)
|
451
527
|
|
452
528
|
|
453
529
|
class LiaoWhitmanOPC(OPC):
|
454
|
-
"""Overburden Pressure Correction according to
|
530
|
+
"""Overburden Pressure Correction according to
|
531
|
+
`Liao & Whitman (1986)`.
|
455
532
|
"""
|
456
533
|
|
457
|
-
@property
|
458
|
-
def eop(self) -> float:
|
459
|
-
"""Effective overburden pressure (:math:`kPa`)."""
|
460
|
-
return self._eop
|
461
|
-
|
462
|
-
@eop.setter
|
463
|
-
@validators.gt(0.0)
|
464
|
-
def eop(self, val: float) -> None:
|
465
|
-
self._eop = val
|
466
|
-
|
467
534
|
def correction(self) -> float:
|
468
535
|
r"""SPT Correction.
|
469
536
|
|
470
|
-
|
471
|
-
|
472
|
-
|
537
|
+
$$
|
538
|
+
C_N = \sqrt{\dfrac{100}{\sigma_o}}
|
539
|
+
$$
|
473
540
|
"""
|
474
541
|
return sqrt(100.0 / self.eop)
|
475
542
|
|
476
543
|
|
477
544
|
class SkemptonOPC(OPC):
|
478
|
-
"""Overburden Pressure Correction according to
|
479
|
-
|
480
|
-
@property
|
481
|
-
def eop(self) -> float:
|
482
|
-
"""Effective overburden pressure (:math:`kPa`)."""
|
483
|
-
return self._eop
|
484
|
-
|
485
|
-
@eop.setter
|
486
|
-
@validators.ge(0.0)
|
487
|
-
def eop(self, val: float) -> None:
|
488
|
-
self._eop = val
|
545
|
+
"""Overburden Pressure Correction according to `Skempton (1986)`."""
|
489
546
|
|
490
547
|
def correction(self) -> float:
|
491
548
|
r"""SPT Correction.
|
492
549
|
|
493
|
-
|
494
|
-
|
495
|
-
|
550
|
+
$$
|
551
|
+
C_N = \dfrac{2}{1 + 0.01044 \cdot \sigma_o}
|
552
|
+
$$
|
496
553
|
"""
|
497
554
|
return 2.0 / (1.0 + 0.01044 * self.eop)
|
498
555
|
|
499
556
|
|
500
557
|
class DilatancyCorrection:
|
501
|
-
"""Dilatancy SPT Correction according to
|
558
|
+
"""Dilatancy SPT Correction according to `Terzaghi & Peck (1948)`.
|
502
559
|
|
503
560
|
For coarse sand, this correction is not required. In applying this
|
504
561
|
correction, overburden pressure correction is applied first and then
|
505
562
|
dilatancy correction is applied.
|
506
563
|
"""
|
507
564
|
|
508
|
-
def __init__(self, corr_spt_n_value: float)
|
565
|
+
def __init__(self, corr_spt_n_value: float):
|
509
566
|
"""
|
510
|
-
:param corr_spt_n_value: SPT N-value standardized for field
|
511
|
-
|
512
|
-
|
567
|
+
:param corr_spt_n_value: SPT N-value standardized for field
|
568
|
+
procedures and/or corrected for
|
569
|
+
overburden pressure.
|
513
570
|
"""
|
514
571
|
self.corr_spt_n_value = corr_spt_n_value
|
515
572
|
|
516
573
|
@property
|
517
574
|
def corr_spt_n_value(self) -> float:
|
518
|
-
"""SPT N-value standardized for field procedures and/or corrected
|
519
|
-
overburden pressure.
|
575
|
+
"""SPT N-value standardized for field procedures and/or corrected
|
576
|
+
for overburden pressure.
|
520
577
|
"""
|
521
578
|
return self._corr_spt_n_value
|
522
579
|
|
523
580
|
@corr_spt_n_value.setter
|
524
|
-
@
|
525
|
-
|
526
|
-
|
581
|
+
@validate_func_args
|
582
|
+
def corr_spt_n_value(
|
583
|
+
self, val: Annotated[
|
584
|
+
float, MustBeBetween(min_value=0.0, max_value=100.0)]
|
585
|
+
):
|
527
586
|
self._corr_spt_n_value = val
|
528
587
|
|
529
588
|
@round_(ndigits=1)
|
530
589
|
def corrected_spt_n_value(self) -> float:
|
531
590
|
r"""Corrected SPT N-value.
|
532
591
|
|
533
|
-
|
534
|
-
|
535
|
-
|
592
|
+
$$
|
593
|
+
(N_1)_{60} = 15 + \dfrac{1}{2}((N_1)_{60} - 15) \, , \,
|
594
|
+
(N_1)_{60} \gt 15
|
595
|
+
$$
|
536
596
|
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
(N_1)_{60} &= (N_1)_{60} \, , \, (N_1)_{60} \le 15
|
597
|
+
$$
|
598
|
+
(N_1)_{60} = (N_1)_{60} \, , \, (N_1)_{60} \le 15
|
599
|
+
$$
|
541
600
|
"""
|
542
601
|
if self.corr_spt_n_value <= 15.0:
|
543
602
|
return self.corr_spt_n_value
|
544
603
|
return 15.0 + 0.5 * (self.corr_spt_n_value - 15.0)
|
545
604
|
|
546
605
|
|
547
|
-
|
548
|
-
|
549
|
-
|
606
|
+
class OPCType(AbstractStrEnum):
|
607
|
+
"""
|
608
|
+
Enumeration of overburden pressure correction (OPC) methods.
|
609
|
+
|
610
|
+
Each member represents a method used to correct SPT results
|
611
|
+
for the effects of overburden pressure in geotechnical design.
|
612
|
+
"""
|
613
|
+
|
550
614
|
GIBBS = enum.auto()
|
615
|
+
"""Gibbs method for overburden pressure correction."""
|
616
|
+
|
551
617
|
BAZARAA = enum.auto()
|
618
|
+
"""Bazaraa method for overburden pressure correction."""
|
619
|
+
|
552
620
|
PECK = enum.auto()
|
621
|
+
"""Peck method for overburden pressure correction."""
|
622
|
+
|
553
623
|
LIAO = enum.auto()
|
624
|
+
"""Liao method for overburden pressure correction."""
|
625
|
+
|
554
626
|
SKEMPTON = enum.auto()
|
627
|
+
"""Skempton method for overburden pressure correction."""
|
555
628
|
|
556
629
|
|
557
|
-
_opctypes = {
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
630
|
+
_opctypes = {
|
631
|
+
OPCType.GIBBS: GibbsHoltzOPC,
|
632
|
+
OPCType.BAZARAA: BazaraaPeckOPC,
|
633
|
+
OPCType.PECK: PeckOPC,
|
634
|
+
OPCType.LIAO: LiaoWhitmanOPC,
|
635
|
+
OPCType.SKEMPTON: SkemptonOPC,
|
636
|
+
}
|
562
637
|
|
563
638
|
|
564
|
-
|
565
|
-
|
639
|
+
@validate_func_args
|
640
|
+
def create_overburden_pressure_correction(
|
641
|
+
std_spt_n_value: float,
|
642
|
+
eop: float,
|
643
|
+
opc_type: Annotated[OPCType | str, MustBeMemberOf(OPCType)] = "gibbs",
|
644
|
+
):
|
566
645
|
"""A factory function that encapsulates the creation of overburden
|
567
646
|
pressure correction.
|
568
647
|
|
569
|
-
:param std_spt_n_value: SPT N-value standardized for field
|
570
|
-
|
648
|
+
:param std_spt_n_value: SPT N-value standardized for field
|
649
|
+
procedures.
|
571
650
|
|
572
|
-
:param eop: Effective overburden pressure (
|
573
|
-
:type eop: float
|
651
|
+
:param eop: Effective overburden pressure ($kPa$).
|
574
652
|
|
575
|
-
:param opc_type: Overburden Pressure Correction type to apply
|
576
|
-
defaults to :py:enum:mem:`~OPCType.GIBBS`
|
577
|
-
:type opc_type: OPCType, optional
|
653
|
+
:param opc_type: Overburden Pressure Correction type to apply.
|
578
654
|
"""
|
579
|
-
|
580
|
-
try:
|
581
|
-
opc_type = OPCType(str(opc_type).casefold())
|
582
|
-
except ValueError as e:
|
583
|
-
msg = ErrorMsg(param_name="opc_type",
|
584
|
-
param_value=opc_type,
|
585
|
-
symbol="in",
|
586
|
-
param_value_bound=list(OPCType))
|
587
|
-
raise ValidationError(msg) from e
|
588
|
-
|
655
|
+
opc_type = OPCType(opc_type)
|
589
656
|
opc_class = _opctypes[opc_type]
|
590
657
|
opc_corr = opc_class(std_spt_n_value=std_spt_n_value, eop=eop)
|
591
|
-
|
592
658
|
return opc_corr
|