geolysis 0.9.0__py3-none-any.whl → 0.10.1__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 +25 -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 +148 -0
- geolysis/bearing_capacity/ubc/__init__.py +107 -128
- geolysis/bearing_capacity/ubc/_core.py +82 -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 +386 -290
- geolysis/spt.py +323 -257
- geolysis/{utils/__init__.py → utils.py} +44 -33
- geolysis-0.10.1.dist-info/METADATA +182 -0
- geolysis-0.10.1.dist-info/RECORD +22 -0
- {geolysis-0.9.0.dist-info → geolysis-0.10.1.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.1.dist-info}/licenses/LICENSE.txt +0 -0
- {geolysis-0.9.0.dist-info → geolysis-0.10.1.dist-info}/top_level.txt +0 -0
geolysis/soil_classifier.py
CHANGED
@@ -1,25 +1,25 @@
|
|
1
|
-
"""This module provides classes for soil classification using systems like
|
2
|
-
USCS and AASHTO, based on particle size distribution and Atterberg limits.
|
3
|
-
"""
|
4
1
|
import enum
|
5
|
-
from
|
2
|
+
from dataclasses import dataclass
|
3
|
+
from typing import Annotated, Sequence
|
6
4
|
|
7
|
-
from
|
8
|
-
from .utils.exceptions import ErrorMsg, ValidationError
|
5
|
+
from func_validator import validate_func_args, MustBeNonNegative
|
9
6
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
7
|
+
from .utils import isclose, round_
|
8
|
+
|
9
|
+
__all__ = [
|
10
|
+
"AtterbergLimits",
|
11
|
+
"PSD",
|
12
|
+
"AASHTO",
|
13
|
+
"USCS",
|
14
|
+
"create_aashto_classifier",
|
15
|
+
"create_uscs_classifier",
|
16
|
+
]
|
16
17
|
|
17
18
|
|
18
19
|
class SizeDistError(ZeroDivisionError):
|
19
20
|
"""Exception raised when size distribution is not provided."""
|
20
21
|
|
21
22
|
|
22
|
-
@enum_repr
|
23
23
|
class _Clf(tuple, enum.Enum):
|
24
24
|
|
25
25
|
def __str__(self) -> str:
|
@@ -35,63 +35,191 @@ class _Clf(tuple, enum.Enum):
|
|
35
35
|
|
36
36
|
|
37
37
|
class USCSSymbol(_Clf):
|
38
|
-
"""
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
38
|
+
"""
|
39
|
+
Unified Soil Classification System (USCS) symbols and descriptions.
|
40
|
+
|
41
|
+
Each member represents a USCS soil type, grading, or plasticity symbol.
|
42
|
+
Aliases are provided where applicable.
|
43
|
+
"""
|
44
|
+
|
45
|
+
# General soil types
|
46
|
+
G = ("G", "Gravel")
|
47
|
+
"""Gravel"""
|
48
|
+
|
49
|
+
GRAVEL = G
|
50
|
+
|
51
|
+
S = ("S", "Sand")
|
52
|
+
"""Sand"""
|
53
|
+
|
54
|
+
SAND = S
|
55
|
+
|
56
|
+
M = ("M", "Silt")
|
57
|
+
"""Silt"""
|
58
|
+
|
59
|
+
SILT = M
|
60
|
+
|
61
|
+
C = ("C", "Clay")
|
62
|
+
"""Clay"""
|
63
|
+
|
64
|
+
CLAY = C
|
65
|
+
|
66
|
+
O = ("O", "Organic")
|
67
|
+
"""Organic soil"""
|
68
|
+
|
69
|
+
ORGANIC = O
|
70
|
+
|
71
|
+
# Grading descriptors
|
72
|
+
W = ("W", "Well graded")
|
73
|
+
"""Well graded"""
|
74
|
+
|
75
|
+
WELL_GRADED = W
|
76
|
+
|
77
|
+
P = ("P", "Poorly graded")
|
78
|
+
"""Poorly graded"""
|
79
|
+
|
80
|
+
POORLY_GRADED = P
|
81
|
+
|
82
|
+
# Plasticity descriptors
|
83
|
+
L = ("L", "Low plasticity")
|
84
|
+
"""Low plasticity"""
|
85
|
+
|
86
|
+
LOW_PLASTICITY = L
|
87
|
+
|
88
|
+
H = ("H", "High plasticity")
|
89
|
+
"""High plasticity"""
|
90
|
+
|
91
|
+
HIGH_PLASTICITY = H
|
92
|
+
|
93
|
+
# Gravels
|
48
94
|
GW = ("GW", "Well graded gravels")
|
95
|
+
"""Well graded gravels"""
|
96
|
+
|
49
97
|
GP = ("GP", "Poorly graded gravels")
|
98
|
+
"""Poorly graded gravels"""
|
99
|
+
|
50
100
|
GM = ("GM", "Silty gravels")
|
101
|
+
"""Silty gravels"""
|
102
|
+
|
51
103
|
GC = ("GC", "Clayey gravels")
|
104
|
+
"""Clayey gravels"""
|
105
|
+
|
52
106
|
GM_GC = ("GM-GC", "Gravelly clayey silt")
|
107
|
+
"""Gravelly clayey silt"""
|
108
|
+
|
53
109
|
GW_GM = ("GW-GM", "Well graded gravel with silt")
|
110
|
+
"""Well graded gravel with silt"""
|
111
|
+
|
54
112
|
GP_GM = ("GP-GM", "Poorly graded gravel with silt")
|
113
|
+
"""Poorly graded gravel with silt"""
|
114
|
+
|
55
115
|
GW_GC = ("GW-GC", "Well graded gravel with clay")
|
116
|
+
"""Well graded gravel with clay"""
|
117
|
+
|
56
118
|
GP_GC = ("GP-GC", "Poorly graded gravel with clay")
|
119
|
+
"""Poorly graded gravel with clay"""
|
120
|
+
|
121
|
+
# Sands
|
57
122
|
SW = ("SW", "Well graded sands")
|
123
|
+
"""Well graded sands"""
|
124
|
+
|
58
125
|
SP = ("SP", "Poorly graded sands")
|
126
|
+
"""Poorly graded sands"""
|
127
|
+
|
59
128
|
SM = ("SM", "Silty sands")
|
129
|
+
"""Silty sands"""
|
130
|
+
|
60
131
|
SC = ("SC", "Clayey sands")
|
132
|
+
"""Clayey sands"""
|
133
|
+
|
61
134
|
SM_SC = ("SM-SC", "Sandy clayey silt")
|
135
|
+
"""Sandy clayey silt"""
|
136
|
+
|
62
137
|
SW_SM = ("SW-SM", "Well graded sand with silt")
|
138
|
+
"""Well graded sand with silt"""
|
139
|
+
|
63
140
|
SP_SM = ("SP-SM", "Poorly graded sand with silt")
|
141
|
+
"""Poorly graded sand with silt"""
|
142
|
+
|
64
143
|
SW_SC = ("SW-SC", "Well graded sand with clay")
|
144
|
+
"""Well graded sand with clay"""
|
145
|
+
|
65
146
|
SP_SC = ("SP-SC", "Poorly graded sand with clay")
|
147
|
+
"""Poorly graded sand with clay"""
|
148
|
+
|
149
|
+
# Silts and clays
|
66
150
|
ML = ("ML", "Inorganic silts with low plasticity")
|
151
|
+
"""Inorganic silts with low plasticity"""
|
152
|
+
|
67
153
|
CL = ("CL", "Inorganic clays with low plasticity")
|
154
|
+
"""Inorganic clays with low plasticity"""
|
155
|
+
|
68
156
|
ML_CL = ("ML-CL", "Clayey silt with low plasticity")
|
157
|
+
"""Clayey silt with low plasticity"""
|
158
|
+
|
69
159
|
OL = ("OL", "Organic clays with low plasticity")
|
160
|
+
"""Organic clays with low plasticity"""
|
161
|
+
|
70
162
|
MH = ("MH", "Inorganic silts with high plasticity")
|
163
|
+
"""Inorganic silts with high plasticity"""
|
164
|
+
|
71
165
|
CH = ("CH", "Inorganic clays with high plasticity")
|
166
|
+
"""Inorganic clays with high plasticity"""
|
167
|
+
|
72
168
|
OH = ("OH", "Organic silts with high plasticity")
|
169
|
+
"""Organic silts with high plasticity"""
|
170
|
+
|
73
171
|
Pt = ("Pt", "Highly organic soils")
|
172
|
+
"""Highly organic soils"""
|
74
173
|
|
75
174
|
|
76
175
|
class AASHTOSymbol(_Clf):
|
77
|
-
"""
|
176
|
+
"""
|
177
|
+
AASHTO soil classification symbols and descriptions.
|
178
|
+
|
179
|
+
Each member represents a standard AASHTO soil class used in
|
180
|
+
pavement and highway engineering.
|
181
|
+
"""
|
182
|
+
|
78
183
|
A_1_a = ("A-1-a", "Stone fragments, gravel, and sand")
|
184
|
+
"""Stone fragments, gravel, and sand"""
|
185
|
+
|
79
186
|
A_1_b = ("A-1-b", "Stone fragments, gravel, and sand")
|
187
|
+
"""Stone fragments, gravel, and sand"""
|
188
|
+
|
80
189
|
A_3 = ("A-3", "Fine sand")
|
190
|
+
"""Fine sand"""
|
191
|
+
|
81
192
|
A_2_4 = ("A-2-4", "Silty or clayey gravel and sand")
|
193
|
+
"""Silty or clayey gravel and sand"""
|
194
|
+
|
82
195
|
A_2_5 = ("A-2-5", "Silty or clayey gravel and sand")
|
196
|
+
"""Silty or clayey gravel and sand"""
|
197
|
+
|
83
198
|
A_2_6 = ("A-2-6", "Silty or clayey gravel and sand")
|
199
|
+
"""Silty or clayey gravel and sand"""
|
200
|
+
|
84
201
|
A_2_7 = ("A-2-7", "Silty or clayey gravel and sand")
|
202
|
+
"""Silty or clayey gravel and sand"""
|
203
|
+
|
85
204
|
A_4 = ("A-4", "Silty soils")
|
205
|
+
"""Silty soils"""
|
206
|
+
|
86
207
|
A_5 = ("A-5", "Silty soils")
|
208
|
+
"""Silty soils"""
|
209
|
+
|
87
210
|
A_6 = ("A-6", "Clayey soils")
|
211
|
+
"""Clayey soils"""
|
212
|
+
|
88
213
|
A_7_5 = ("A-7-5", "Clayey soils")
|
214
|
+
"""Clayey soils"""
|
215
|
+
|
89
216
|
A_7_6 = ("A-7-6", "Clayey soils")
|
217
|
+
"""Clayey soils"""
|
90
218
|
|
91
219
|
|
92
220
|
class AtterbergLimits:
|
93
|
-
"""Represents the water contents at which soil changes from one state
|
94
|
-
the other.
|
221
|
+
"""Represents the water contents at which soil changes from one state
|
222
|
+
to the other.
|
95
223
|
"""
|
96
224
|
|
97
225
|
class __A_LINE:
|
@@ -99,67 +227,69 @@ class AtterbergLimits:
|
|
99
227
|
def __get__(self, obj, objtype=None) -> float:
|
100
228
|
return 0.73 * (obj.liquid_limit - 20.0)
|
101
229
|
|
102
|
-
#: The ``A-line`` determines if a soil is clayey or silty.
|
103
|
-
#: :math:`A = 0.73(LL - 20.0)`
|
104
230
|
A_LINE = __A_LINE()
|
231
|
+
"""The ``A-line`` determines if a soil is clayey or silty.
|
232
|
+
|
233
|
+
$A = 0.73(LL - 20.0)$
|
234
|
+
"""
|
105
235
|
|
106
236
|
def __init__(self, liquid_limit: float, plastic_limit: float):
|
107
237
|
"""
|
108
|
-
:param liquid_limit: Water content beyond which soils flows
|
109
|
-
own weight (%). It can also be
|
110
|
-
minimum moisture content at
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
:type plastic_limit: float
|
238
|
+
:param liquid_limit: Water content beyond which soils flows
|
239
|
+
under their own weight (%). It can also be
|
240
|
+
defined as the minimum moisture content at
|
241
|
+
which a soil flows upon application of a
|
242
|
+
very small shear force.
|
243
|
+
:param plastic_limit: Water content at which plastic deformation
|
244
|
+
can be initiated (%). It is also the
|
245
|
+
minimum water content at which soil can be
|
246
|
+
rolled into a thread 3mm thick (molded
|
247
|
+
without breaking).
|
119
248
|
"""
|
120
249
|
self.liquid_limit = liquid_limit
|
121
250
|
self.plastic_limit = plastic_limit
|
122
251
|
|
123
252
|
@property
|
124
253
|
def liquid_limit(self) -> float:
|
125
|
-
"""
|
254
|
+
"""
|
255
|
+
Water content beyond which soils flows under their own weight (%).
|
256
|
+
"""
|
126
257
|
return self._liquid_limit
|
127
258
|
|
128
259
|
@liquid_limit.setter
|
129
|
-
@
|
130
|
-
def liquid_limit(self, val: float)
|
260
|
+
@validate_func_args
|
261
|
+
def liquid_limit(self, val: Annotated[float, MustBeNonNegative]):
|
131
262
|
self._liquid_limit = val
|
132
263
|
|
133
264
|
@property
|
134
265
|
def plastic_limit(self) -> float:
|
135
|
-
"""
|
266
|
+
"""
|
267
|
+
Water content at which plastic deformation can be initiated (%).
|
268
|
+
"""
|
136
269
|
return self._plastic_limit
|
137
270
|
|
138
271
|
@plastic_limit.setter
|
139
|
-
@
|
140
|
-
def plastic_limit(self, val: float)
|
272
|
+
@validate_func_args
|
273
|
+
def plastic_limit(self, val: Annotated[float, MustBeNonNegative]):
|
141
274
|
if self.liquid_limit < val:
|
142
|
-
msg =
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
raise ValidationError(msg)
|
275
|
+
msg = (
|
276
|
+
f"plastic_limit: {val} cannot be greater than "
|
277
|
+
f"liquid_limit: {self.liquid_limit}"
|
278
|
+
)
|
279
|
+
raise ValueError(msg)
|
148
280
|
|
149
281
|
self._plastic_limit = val
|
150
282
|
|
151
283
|
@property
|
152
284
|
@round_(2)
|
153
285
|
def plasticity_index(self) -> float:
|
154
|
-
"""Plasticity index (PI) is the range of water content over which
|
155
|
-
soil remains in the plastic state.
|
286
|
+
"""Plasticity index (PI) is the range of water content over which
|
287
|
+
the soil remains in the plastic state.
|
156
288
|
|
157
289
|
It is also the numerical difference between the liquid limit and
|
158
290
|
plastic limit of the soil.
|
159
291
|
|
160
|
-
|
161
|
-
|
162
|
-
.. math:: PI = LL - PL
|
292
|
+
$$PI = LL - PL$$
|
163
293
|
"""
|
164
294
|
return self.liquid_limit - self.plastic_limit
|
165
295
|
|
@@ -173,8 +303,8 @@ class AtterbergLimits:
|
|
173
303
|
return self.plasticity_index > self.A_LINE
|
174
304
|
|
175
305
|
def limit_plot_in_hatched_zone(self) -> bool:
|
176
|
-
"""Checks if soil sample plot in the hatched zone on the
|
177
|
-
chart.
|
306
|
+
"""Checks if soil sample plot in the hatched zone on the
|
307
|
+
atterberg chart.
|
178
308
|
"""
|
179
309
|
return 4 <= self.plasticity_index <= 7 and 10 < self.liquid_limit < 30
|
180
310
|
|
@@ -182,17 +312,16 @@ class AtterbergLimits:
|
|
182
312
|
def liquidity_index(self, nmc: float) -> float:
|
183
313
|
r"""Return the liquidity index of the soil.
|
184
314
|
|
185
|
-
|
186
|
-
content`` to its ``liquid limit``. When the soil is at the plastic
|
187
|
-
limit its liquidity index is zero. Negative values of the liquidity
|
188
|
-
index indicate that the soil is in a hard (desiccated) state. It is
|
189
|
-
also known as Water-Plasticity ratio.
|
190
|
-
|
191
|
-
:param float nmc: Moisture contents of the soil in natural condition.
|
315
|
+
$$I_l = \dfrac{w - PL}{PI} \cdot 100$$
|
192
316
|
|
193
|
-
|
317
|
+
Liquidity index of a soil indicates the nearness of its
|
318
|
+
`natural water content` to its `liquid limit`. When the soil
|
319
|
+
is at the plastic limit its liquidity index is zero. Negative
|
320
|
+
values of the liquidity index indicate that the soil is in a
|
321
|
+
hard (desiccated) state. It is also known as Water-Plasticity
|
322
|
+
ratio.
|
194
323
|
|
195
|
-
|
324
|
+
:param nmc: Moisture contents of the soil in natural condition.
|
196
325
|
"""
|
197
326
|
return ((nmc - self.plastic_limit) / self.plasticity_index) * 100.0
|
198
327
|
|
@@ -200,22 +329,21 @@ class AtterbergLimits:
|
|
200
329
|
def consistency_index(self, nmc: float) -> float:
|
201
330
|
r"""Return the consistency index of the soil.
|
202
331
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
.. math:: I_c = \dfrac{LL - w}{PI} \cdot 100
|
332
|
+
$$I_c = \dfrac{LL - w}{PI} \cdot 100$$
|
333
|
+
|
334
|
+
Consistency index indicates the consistency (firmness) of soil.
|
335
|
+
It shows the nearness of the ``natural water content`` of the
|
336
|
+
soil to its `plastic limit`. When the soil is at the liquid
|
337
|
+
limit, the consistency index is zero. The soil at consistency
|
338
|
+
index of zero will be extremely soft and has negligible shear
|
339
|
+
strength. A soil at a water content equal to the plastic limit
|
340
|
+
has consistency index of 100% indicating that the soil is
|
341
|
+
relatively firm. A consistency index of greater than 100% shows
|
342
|
+
the soil is relatively strong (semi-solid state). A negative
|
343
|
+
value indicate the soil is in the liquid state. It is also known
|
344
|
+
as Relative Consistency.
|
345
|
+
|
346
|
+
:param nmc: Moisture contents of the soil in natural condition.
|
219
347
|
"""
|
220
348
|
return ((self.liquid_limit - nmc) / self.plasticity_index) * 100.0
|
221
349
|
|
@@ -226,8 +354,7 @@ class _SizeDistribution:
|
|
226
354
|
Features obtained from the Particle Size Distribution graph.
|
227
355
|
"""
|
228
356
|
|
229
|
-
def __init__(self, d_10: float = 0.0,
|
230
|
-
d_30: float = 0.0,
|
357
|
+
def __init__(self, d_10: float = 0.0, d_30: float = 0.0,
|
231
358
|
d_60: float = 0.0):
|
232
359
|
self.d_10 = d_10
|
233
360
|
self.d_30 = d_30
|
@@ -245,12 +372,10 @@ class _SizeDistribution:
|
|
245
372
|
return self.d_60 / self.d_10
|
246
373
|
|
247
374
|
def grade(self, coarse_soil: USCSSymbol) -> USCSSymbol:
|
248
|
-
"""Grade of soil sample. Soil grade can either be well graded or
|
249
|
-
graded.
|
375
|
+
"""Grade of soil sample. Soil grade can either be well graded or
|
376
|
+
poorly graded.
|
250
377
|
|
251
|
-
:param coarse_soil: Coarse fraction of the soil sample.
|
252
|
-
are :py:enum:mem:`~USCSSymbol.GRAVEL` and
|
253
|
-
:py:enum:mem:`~USCSSymbol.SAND`.
|
378
|
+
:param coarse_soil: Coarse fraction of the soil sample.
|
254
379
|
"""
|
255
380
|
if coarse_soil is USCSSymbol.GRAVEL:
|
256
381
|
if 1 < self.coeff_of_curvature < 3 and self.coeff_of_uniformity >= 4:
|
@@ -268,27 +393,26 @@ class _SizeDistribution:
|
|
268
393
|
|
269
394
|
|
270
395
|
class PSD:
|
271
|
-
"""Quantitative proportions by mass of various sizes of particles
|
272
|
-
in a soil.
|
396
|
+
"""Quantitative proportions by mass of various sizes of particles
|
397
|
+
present in a soil.
|
273
398
|
"""
|
274
399
|
|
275
|
-
def __init__(
|
276
|
-
|
400
|
+
def __init__(
|
401
|
+
self,
|
402
|
+
fines: float,
|
403
|
+
sand: float,
|
404
|
+
d_10: float = 0,
|
405
|
+
d_30: float = 0,
|
406
|
+
d_60: float = 0,
|
407
|
+
):
|
277
408
|
"""
|
278
409
|
:param fines: Percentage of fines in soil sample (%) i.e. The
|
279
|
-
percentage of soil sample passing through No. 200
|
280
|
-
(0.075mm).
|
281
|
-
:type fines: float
|
282
|
-
|
410
|
+
percentage of soil sample passing through No. 200
|
411
|
+
sieve (0.075mm).
|
283
412
|
:param sand: Percentage of sand in soil sample (%).
|
284
|
-
:type sand: float
|
285
|
-
|
286
413
|
:param d_10: Diameter at which 10% of the soil by weight is finer.
|
287
|
-
:type d_10: float
|
288
414
|
:param d_30: Diameter at which 30% of the soil by weight is finer.
|
289
|
-
:type d_30: float
|
290
415
|
:param d_60: Diameter at which 60% of the soil by weight is finer.
|
291
|
-
:type d_60: float
|
292
416
|
"""
|
293
417
|
self.fines = fines
|
294
418
|
self.sand = sand
|
@@ -311,11 +435,9 @@ class PSD:
|
|
311
435
|
def coeff_of_curvature(self) -> float:
|
312
436
|
r"""Coefficient of curvature of soil sample.
|
313
437
|
|
314
|
-
|
315
|
-
|
316
|
-
.. math:: C_c = \dfrac{D^2_{30}}{D_{60} \cdot D_{10}}
|
438
|
+
$$C_c = \dfrac{D^2_{30}}{D_{60} \cdot D_{10}}$$
|
317
439
|
|
318
|
-
For the soil to be well graded, the value of
|
440
|
+
For the soil to be well graded, the value of $C_c$ must be
|
319
441
|
between 1 and 3.
|
320
442
|
"""
|
321
443
|
return self.size_dist.coeff_of_curvature
|
@@ -325,15 +447,14 @@ class PSD:
|
|
325
447
|
def coeff_of_uniformity(self) -> float:
|
326
448
|
r"""Coefficient of uniformity of soil sample.
|
327
449
|
|
328
|
-
|
329
|
-
|
330
|
-
.. math:: C_u = \dfrac{D_{60}}{D_{10}}
|
450
|
+
$$C_u = \dfrac{D_{60}}{D_{10}}$$
|
331
451
|
|
332
|
-
|
333
|
-
graded for gravels and sands respectively. When
|
334
|
-
than 4, it is classified as poorly graded or uniformly graded
|
452
|
+
$C_u$ value greater than 4 to 6 classifies the soil as well
|
453
|
+
graded for gravels and sands respectively. When $C_u$ is less
|
454
|
+
than 4, it is classified as poorly graded or uniformly graded
|
455
|
+
soil.
|
335
456
|
|
336
|
-
Higher values of
|
457
|
+
Higher values of $C_u$ indicates that the soil mass consists of
|
337
458
|
soil particles with different size ranges.
|
338
459
|
"""
|
339
460
|
return self.size_dist.coeff_of_uniformity
|
@@ -343,70 +464,64 @@ class PSD:
|
|
343
464
|
return any(self.size_dist)
|
344
465
|
|
345
466
|
def grade(self) -> USCSSymbol:
|
346
|
-
r"""Return the grade of the soil sample, either well graded or
|
347
|
-
graded.
|
467
|
+
r"""Return the grade of the soil sample, either well graded or
|
468
|
+
poorly graded.
|
348
469
|
|
349
470
|
Conditions for a well-graded soil:
|
350
471
|
|
351
|
-
|
352
|
-
|
353
|
-
- :math:`1 \lt C_c \lt 3` and :math:`C_u \ge 4` (for gravels)
|
354
|
-
- :math:`1 \lt C_c \lt 3` and :math:`C_u \ge 6` (for sands)
|
472
|
+
- $1 \lt C_c \lt 3$ and $C_u \ge 4$ (for gravels)
|
473
|
+
- $1 \lt C_c \lt 3$ and $C_u \ge 6$ (for sands)
|
355
474
|
"""
|
356
475
|
return self.size_dist.grade(coarse_soil=self.coarse_material_type)
|
357
476
|
|
358
477
|
|
359
|
-
|
478
|
+
@dataclass
|
479
|
+
class AASHTOResult:
|
360
480
|
symbol: str
|
481
|
+
symbol_no_group_idx: str
|
361
482
|
description: str
|
483
|
+
group_index: str
|
362
484
|
|
363
485
|
|
364
486
|
class AASHTO:
|
365
|
-
r"""American Association of State Highway and Transportation
|
366
|
-
(AASHTO) classification system.
|
487
|
+
r"""American Association of State Highway and Transportation
|
488
|
+
Officials (AASHTO) classification system.
|
367
489
|
|
368
490
|
The AASHTO classification system is useful for classifying soils for
|
369
|
-
highways. It categorizes soils for highways based on particle size
|
370
|
-
and plasticity characteristics. It classifies both
|
371
|
-
fine-grained soils into eight main groups (A1-A7)
|
372
|
-
a separate category (A8) for organic
|
373
|
-
|
374
|
-
- ``A1 ~ A3`` (Granular Materials) :math:`\le` 35% pass No. 200 sieve
|
375
|
-
- ``A4 ~ A7`` (Silt-clay Materials) :math:`\ge` 36% pass No. 200 sieve
|
376
|
-
- ``A8`` (Organic Materials)
|
491
|
+
highways. It categorizes soils for highways based on particle size
|
492
|
+
analysis and plasticity characteristics. It classifies both
|
493
|
+
coarse-grained and fine-grained soils into eight main groups (A1-A7)
|
494
|
+
with subgroups, along with a separate category (A8) for organic
|
495
|
+
soils.
|
377
496
|
|
378
|
-
|
497
|
+
- `A1 ~ A3` (Granular Materials) $\le$ 35% pass No. 200 sieve
|
498
|
+
- `A4 ~ A7` (Silt-clay Materials) $\ge$ 36% pass No. 200 sieve
|
499
|
+
- `A8` (Organic Materials)
|
379
500
|
|
380
|
-
|
501
|
+
The Group Index `(GI)` is used to further evaluate soils within a
|
502
|
+
group.
|
381
503
|
|
382
|
-
|
383
|
-
soil has been classified as per AASHTO system.
|
504
|
+
!!! note
|
384
505
|
|
385
|
-
|
506
|
+
The `GI` must be mentioned even when it is zero, to indicate
|
507
|
+
that the soil has been classified as per AASHTO system.
|
386
508
|
|
387
|
-
.. math::
|
388
509
|
|
389
|
-
|
510
|
+
$$
|
511
|
+
GI = (F_{200} - 35)[0.2 + 0.005(LL - 40)] + 0.01(F_{200} - 15)(PI - 10)
|
512
|
+
$$
|
390
513
|
"""
|
391
514
|
|
392
|
-
def __init__(self, atterberg_limits: AtterbergLimits,
|
393
|
-
fines: float, add_group_idx: bool = True):
|
515
|
+
def __init__(self, atterberg_limits: AtterbergLimits, fines: float):
|
394
516
|
"""
|
395
517
|
:param atterberg_limits: Atterberg limits of soil sample.
|
396
|
-
:type atterberg_limits: AtterbergLimits
|
397
518
|
|
398
|
-
:param fines: Percentage of fines in soil sample (%) i.e. The
|
399
|
-
of soil sample passing through No. 200
|
400
|
-
|
401
|
-
|
402
|
-
:param add_group_idx: Used to indicate whether the group index should
|
403
|
-
be added to the classification or not, defaults
|
404
|
-
to True.
|
405
|
-
:type add_group_idx: bool, optional
|
519
|
+
:param fines: Percentage of fines in soil sample (%) i.e. The
|
520
|
+
percentage of soil sample passing through No. 200
|
521
|
+
sieve (0.075mm).
|
406
522
|
"""
|
407
523
|
self.atterberg_limits = atterberg_limits
|
408
524
|
self.fines = fines
|
409
|
-
self.add_group_idx = add_group_idx
|
410
525
|
|
411
526
|
@property
|
412
527
|
def fines(self) -> float:
|
@@ -414,14 +529,13 @@ class AASHTO:
|
|
414
529
|
return self._fines
|
415
530
|
|
416
531
|
@fines.setter
|
417
|
-
@
|
418
|
-
def fines(self, val: float)
|
532
|
+
@validate_func_args
|
533
|
+
def fines(self, val: Annotated[float, MustBeNonNegative]):
|
419
534
|
self._fines = val
|
420
535
|
|
421
536
|
@round_(ndigits=0)
|
422
537
|
def group_index(self) -> float:
|
423
538
|
"""Return the Group Index (GI) of the soil sample."""
|
424
|
-
|
425
539
|
liquid_lmt = self.atterberg_limits.liquid_limit
|
426
540
|
plasticity_idx = self.atterberg_limits.plasticity_index
|
427
541
|
fines = self.fines
|
@@ -433,16 +547,20 @@ class AASHTO:
|
|
433
547
|
|
434
548
|
return x_1 * (0.2 + 0.005 * x_2) + 0.01 * x_3 * x_4
|
435
549
|
|
436
|
-
def classify(self) ->
|
550
|
+
def classify(self) -> AASHTOResult:
|
437
551
|
"""Return the AASHTO classification of the soil."""
|
438
552
|
soil_clf = self._classify()
|
439
553
|
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
symbol = f"{symbol}({self.group_index():.0f})"
|
554
|
+
symbol_no_grp_idx, description = soil_clf.symbol, soil_clf.description
|
555
|
+
group_idx = f"{self.group_index():.0f}"
|
556
|
+
symbol = f"{symbol_no_grp_idx}({group_idx})"
|
444
557
|
|
445
|
-
return
|
558
|
+
return AASHTOResult(
|
559
|
+
symbol=symbol,
|
560
|
+
symbol_no_group_idx=symbol_no_grp_idx,
|
561
|
+
description=description,
|
562
|
+
group_index=group_idx,
|
563
|
+
)
|
446
564
|
|
447
565
|
def _classify(self) -> AASHTOSymbol:
|
448
566
|
# Silts A4-A7
|
@@ -503,46 +621,50 @@ class AASHTO:
|
|
503
621
|
return soil_clf
|
504
622
|
|
505
623
|
|
624
|
+
@dataclass
|
625
|
+
class USCSResult:
|
626
|
+
symbol: str
|
627
|
+
description: str
|
628
|
+
|
629
|
+
|
506
630
|
class USCS:
|
507
631
|
"""Unified Soil Classification System (USCS).
|
508
632
|
|
509
|
-
The Unified Soil Classification System, initially developed by
|
510
|
-
in 1948 and later modified in 1952, is widely utilized in
|
511
|
-
projects involving soils. It is the most popular system
|
512
|
-
classification and is similar to Casagrande's
|
513
|
-
system relies on particle size analysis
|
514
|
-
classification.
|
633
|
+
The Unified Soil Classification System, initially developed by
|
634
|
+
Casagrande in 1948 and later modified in 1952, is widely utilized in
|
635
|
+
engineering projects involving soils. It is the most popular system
|
636
|
+
for soil classification and is similar to Casagrande's
|
637
|
+
Classification System. The system relies on particle size analysis
|
638
|
+
and atterberg limits for classification.
|
515
639
|
|
516
640
|
In this system, soils are first classified into two categories:
|
517
641
|
|
518
642
|
- Coarse grained soils: If more than 50% of the soils is retained on
|
519
643
|
No. 200 (0.075 mm) sieve, it is designated as coarse-grained soil.
|
520
644
|
|
521
|
-
- Fine grained soils: If more than 50% of the soil passes through
|
522
|
-
sieve, it is designated as fine-grained soil.
|
645
|
+
- Fine grained soils: If more than 50% of the soil passes through
|
646
|
+
No. 200 sieve, it is designated as fine-grained soil.
|
523
647
|
|
524
|
-
Highly Organic soils are identified by visual inspection. These
|
525
|
-
termed as Peat
|
648
|
+
Highly Organic soils are identified by visual inspection. These
|
649
|
+
soils are termed as Peat ($P_t$).
|
526
650
|
"""
|
527
651
|
|
528
|
-
def __init__(
|
529
|
-
|
652
|
+
def __init__(
|
653
|
+
self,
|
654
|
+
atterberg_limits: AtterbergLimits,
|
655
|
+
psd: PSD,
|
656
|
+
organic=False,
|
657
|
+
):
|
530
658
|
"""
|
531
659
|
:param atterberg_limits: Atterberg limits of the soil.
|
532
|
-
:type atterberg_limits: AtterbergLimits
|
533
|
-
|
534
660
|
:param psd: Particle size distribution of the soil.
|
535
|
-
:
|
536
|
-
|
537
|
-
:param organic: Indicates whether soil is organic or not, defaults to
|
538
|
-
False.
|
539
|
-
:type organic: bool, optional
|
661
|
+
:param organic: Indicates whether soil is organic or not.
|
540
662
|
"""
|
541
663
|
self.atterberg_limits = atterberg_limits
|
542
664
|
self.psd = psd
|
543
665
|
self.organic = organic
|
544
666
|
|
545
|
-
def classify(self)
|
667
|
+
def classify(self):
|
546
668
|
"""Return the USCS classification of the soil."""
|
547
669
|
soil_clf = self._classify()
|
548
670
|
|
@@ -551,15 +673,17 @@ class USCS:
|
|
551
673
|
soil_clf = USCSSymbol[soil_clf]
|
552
674
|
|
553
675
|
if isinstance(soil_clf, USCSSymbol):
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
676
|
+
soil_clf = USCSResult(
|
677
|
+
symbol=soil_clf.symbol, description=soil_clf.description
|
678
|
+
)
|
679
|
+
else:
|
680
|
+
# Handling tuple or list case for dual classification
|
681
|
+
first_clf, second_clf = map(lambda clf: USCSSymbol[clf], soil_clf)
|
682
|
+
comb_symbol = f"{first_clf.symbol},{second_clf.symbol}"
|
683
|
+
comb_desc = f"{first_clf.description},{second_clf.description}"
|
684
|
+
soil_clf = USCSResult(symbol=comb_symbol, description=comb_desc)
|
561
685
|
|
562
|
-
return
|
686
|
+
return soil_clf
|
563
687
|
|
564
688
|
def _classify(self) -> USCSSymbol | str | Sequence[str]:
|
565
689
|
# Fine-grained, Run Atterberg
|
@@ -578,21 +702,17 @@ class USCS:
|
|
578
702
|
# Above A-line and PI > 7
|
579
703
|
if self.atterberg_limits.above_A_LINE() and plasticity_idx > 7.0:
|
580
704
|
soil_clf = USCSSymbol.CL
|
581
|
-
|
582
705
|
# Limit plot in hatched area on plasticity chart
|
583
706
|
elif self.atterberg_limits.limit_plot_in_hatched_zone():
|
584
707
|
soil_clf = USCSSymbol.ML_CL
|
585
|
-
|
586
708
|
# Below A-line or PI < 4
|
587
709
|
else:
|
588
710
|
soil_clf = USCSSymbol.OL if self.organic else USCSSymbol.ML
|
589
|
-
|
590
711
|
# High LL
|
591
712
|
else:
|
592
713
|
# Above A-Line
|
593
714
|
if self.atterberg_limits.above_A_LINE():
|
594
715
|
soil_clf = USCSSymbol.CH
|
595
|
-
|
596
716
|
# Below A-Line
|
597
717
|
else:
|
598
718
|
soil_clf = USCSSymbol.OH if self.organic else USCSSymbol.MH
|
@@ -628,11 +748,12 @@ class USCS:
|
|
628
748
|
soil_clf = self._dual_soil_classifier()
|
629
749
|
else:
|
630
750
|
fine_material_type = self.atterberg_limits.fine_material_type
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
751
|
+
soil_clf = (
|
752
|
+
f"{coarse_material_type}{USCSSymbol.WELL_GRADED}_"
|
753
|
+
f"{coarse_material_type}{fine_material_type}",
|
754
|
+
f"{coarse_material_type}{USCSSymbol.POORLY_GRADED}_"
|
755
|
+
f"{coarse_material_type}{fine_material_type}",
|
756
|
+
)
|
636
757
|
|
637
758
|
# Less than 5% pass No. 200 sieve
|
638
759
|
# Obtain Cc and Cu from grain size graph
|
@@ -641,8 +762,10 @@ class USCS:
|
|
641
762
|
soil_clf = f"{coarse_material_type}{self.psd.grade()}"
|
642
763
|
|
643
764
|
else:
|
644
|
-
soil_clf = (
|
645
|
-
|
765
|
+
soil_clf = (
|
766
|
+
f"{coarse_material_type}{USCSSymbol.WELL_GRADED}",
|
767
|
+
f"{coarse_material_type}{USCSSymbol.POORLY_GRADED}",
|
768
|
+
)
|
646
769
|
|
647
770
|
return soil_clf
|
648
771
|
|
@@ -650,104 +773,77 @@ class USCS:
|
|
650
773
|
fine_material_type = self.atterberg_limits.fine_material_type
|
651
774
|
coarse_material_type = self.psd.coarse_material_type
|
652
775
|
|
653
|
-
return (
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
776
|
+
return (
|
777
|
+
f"{coarse_material_type}{self.psd.grade()}_"
|
778
|
+
f"{coarse_material_type}{fine_material_type}"
|
779
|
+
)
|
780
|
+
|
781
|
+
|
782
|
+
def create_aashto_classifier(
|
783
|
+
liquid_limit: float,
|
784
|
+
plastic_limit: float,
|
785
|
+
fines: float,
|
786
|
+
) -> AASHTO:
|
787
|
+
"""A helper function that encapsulates the creation of a AASHTO
|
788
|
+
classifier.
|
789
|
+
|
790
|
+
:param liquid_limit: Water content beyond which soils flows under
|
791
|
+
their own weight (%). It can also be defined as
|
792
|
+
the minimum moisture content at which a soil
|
793
|
+
flows upon application of a very small shear
|
794
|
+
force.
|
795
|
+
|
796
|
+
:param plastic_limit: Water content at which plastic deformation can
|
797
|
+
be initiated (%). It is also the minimum water
|
798
|
+
content at which soil can be rolled into a
|
799
|
+
thread 3mm thick (molded without breaking).
|
800
|
+
|
801
|
+
:param fines: Percentage of fines in soil sample (%) i.e. The
|
802
|
+
percentage of soil sample passing through No. 200
|
803
|
+
sieve (0.075mm).
|
804
|
+
"""
|
805
|
+
atterberg_limits = AtterbergLimits(liquid_limit, plastic_limit)
|
806
|
+
return AASHTO(atterberg_limits, fines)
|
807
|
+
|
808
|
+
|
809
|
+
def create_uscs_classifier(
|
810
|
+
liquid_limit: float,
|
811
|
+
plastic_limit: float,
|
812
|
+
fines: float,
|
813
|
+
sand: float,
|
814
|
+
d_10: float = 0,
|
815
|
+
d_30: float = 0,
|
816
|
+
d_60: float = 0,
|
817
|
+
organic: bool = False,
|
818
|
+
):
|
819
|
+
"""A helper function that encapsulates the creation of a USCS
|
820
|
+
classifier.
|
821
|
+
|
822
|
+
:param liquid_limit: Water content beyond which soils flows under
|
823
|
+
their own weight (%). It can also be defined as
|
824
|
+
the minimum moisture content at which a soil
|
825
|
+
flows upon application of a very small shear
|
826
|
+
force.
|
827
|
+
|
828
|
+
:param plastic_limit: Water content at which plastic deformation can
|
829
|
+
be initiated (%). It is also the minimum water
|
830
|
+
content at which soil can be rolled into a
|
831
|
+
thread 3mm thick. (molded without breaking)
|
832
|
+
|
833
|
+
:param fines: Percentage of fines in soil sample (%) i.e. The
|
834
|
+
percentage of soil sample passing through No. 200
|
835
|
+
sieve (0.075mm).
|
836
|
+
|
837
|
+
:param sand: Percentage of sand in soil sample (%).
|
694
838
|
|
695
839
|
:param d_10: Diameter at which 10% of the soil by weight is finer.
|
696
|
-
:type d_10: float, optional
|
697
840
|
|
698
841
|
:param d_30: Diameter at which 30% of the soil by weight is finer.
|
699
|
-
:type d_30: float, optional
|
700
842
|
|
701
843
|
:param d_60: Diameter at which 60% of the soil by weight is finer.
|
702
|
-
:type d_60: float, optional
|
703
|
-
|
704
|
-
:param add_group_idx: Used to indicate whether the group index should
|
705
|
-
be added to the classification or not, defaults to
|
706
|
-
True.
|
707
|
-
:type add_group_idx: bool, optional
|
708
|
-
|
709
|
-
:param organic: Indicates whether soil is organic or not, defaults to False.
|
710
|
-
:type organic: bool, optional
|
711
844
|
|
712
|
-
:param
|
713
|
-
used, defaults to None.
|
714
|
-
:type clf_type: ClfType | str
|
715
|
-
|
716
|
-
:raises ValueError: Raises ValueError if ``clf_type`` is not supported or
|
717
|
-
None
|
718
|
-
:raises ValueError: Raises ValueError if ``sand`` is not provided for
|
719
|
-
:class:`USCS` classification.
|
845
|
+
:param organic: Indicates whether soil is organic or not.
|
720
846
|
"""
|
721
|
-
|
722
|
-
param_value=clf_type,
|
723
|
-
symbol="in",
|
724
|
-
param_value_bound=list(ClfType))
|
725
|
-
|
726
|
-
if clf_type is None:
|
727
|
-
raise ValidationError(msg)
|
728
|
-
|
729
|
-
try:
|
730
|
-
clf_type = ClfType(str(clf_type).casefold())
|
731
|
-
except ValueError as e:
|
732
|
-
raise ValidationError(msg) from e
|
733
|
-
|
734
|
-
atterberg_lmts = AtterbergLimits(liquid_limit=liquid_limit,
|
735
|
-
plastic_limit=plastic_limit)
|
736
|
-
|
737
|
-
if clf_type == ClfType.AASHTO:
|
738
|
-
clf = AASHTO(atterberg_limits=atterberg_lmts,
|
739
|
-
fines=fines,
|
740
|
-
add_group_idx=add_group_idx)
|
741
|
-
return clf
|
742
|
-
|
743
|
-
# USCS classification
|
744
|
-
if not sand:
|
745
|
-
msg = ErrorMsg(param_name="sand",
|
746
|
-
param_value=sand,
|
747
|
-
msg="sand must be specified for USCS classification")
|
748
|
-
raise ValidationError(msg)
|
749
|
-
|
847
|
+
atterberg_lmts = AtterbergLimits(liquid_limit, plastic_limit)
|
750
848
|
psd = PSD(fines=fines, sand=sand, d_10=d_10, d_30=d_30, d_60=d_60)
|
751
|
-
|
752
|
-
|
753
|
-
return clf
|
849
|
+
return USCS(atterberg_limits=atterberg_lmts, psd=psd, organic=organic)
|