geolysis 0.4.2__py3-none-any.whl → 0.4.4__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.
@@ -0,0 +1,337 @@
1
+ """ Ultimate bearing capacity estimation package
2
+
3
+ Enum
4
+ ====
5
+
6
+ .. autosummary::
7
+ :toctree: _autosummary
8
+ :nosignatures:
9
+
10
+ UBC_TYPE
11
+
12
+ Functions
13
+ =========
14
+
15
+ .. autosummary::
16
+ :toctree: _autosummary
17
+
18
+ create_ultimate_bearing_capacity
19
+ """
20
+ import enum
21
+ from abc import ABC, abstractmethod
22
+ from typing import Optional
23
+
24
+ from geolysis.foundation import FoundationSize, Shape, create_foundation
25
+ from geolysis.utils import arctan, enum_repr, tan, round_, validators
26
+
27
+ __all__ = ["UltimateBearingCapacity",
28
+ "TerzaghiUBC4StripFooting",
29
+ "TerzaghiUBC4CircularFooting",
30
+ "TerzaghiUBC4RectangularFooting",
31
+ "TerzaghiUBC4SquareFooting",
32
+ "HansenUltimateBearingCapacity",
33
+ "VesicUltimateBearingCapacity",
34
+ "create_ultimate_bearing_capacity"]
35
+
36
+
37
+ class UltimateBearingCapacity(ABC):
38
+ def __init__(self, friction_angle: float,
39
+ cohesion: float,
40
+ moist_unit_wgt: float,
41
+ foundation_size: FoundationSize,
42
+ load_angle=0.0,
43
+ apply_local_shear=False) -> None:
44
+ r"""
45
+ :param friction_angle: Internal angle of friction for general shear
46
+ failure (degrees).
47
+ :type friction_angle: float
48
+
49
+ :param cohesion: Cohesion of soil (:math:`kPa`).
50
+ :type cohesion: float
51
+
52
+ :param moist_unit_wgt: Moist unit weight of soil (:math:`kN/m^3`).
53
+ :type moist_unit_wgt: float
54
+
55
+ :param foundation_size: Size of the foundation.
56
+ :type foundation_size: FoundationSize
57
+
58
+ :param load_angle: Inclination of the applied load with the vertical
59
+ (:math:`\alpha^{\circ}`), defaults to 0.0.
60
+ :type load_angle: float, optional
61
+
62
+ :param apply_local_shear: Indicate whether bearing capacity failure is
63
+ general shear or local shear failure,
64
+ defaults to False.
65
+ :type apply_local_shear: bool, optional
66
+ """
67
+ self.friction_angle = friction_angle
68
+ self.cohesion = cohesion
69
+ self.moist_unit_wgt = moist_unit_wgt
70
+ self.load_angle = load_angle
71
+ self.foundation_size = foundation_size
72
+ self.apply_local_shear = apply_local_shear
73
+
74
+ @property
75
+ def friction_angle(self) -> float:
76
+ """Return friction angle for local shear in the case of local shear
77
+ failure or general shear in the case of general shear failure.
78
+ """
79
+ if self.apply_local_shear:
80
+ return arctan((2 / 3) * tan(self._friction_angle))
81
+ return self._friction_angle
82
+
83
+ @friction_angle.setter
84
+ @validators.ge(0.0)
85
+ def friction_angle(self, val: float):
86
+ self._friction_angle = val
87
+
88
+ @property
89
+ def cohesion(self) -> float:
90
+ """Return cohesion for local shear in the case of local shear failure
91
+ or general shear in the case of general shear failure.
92
+ """
93
+ if self.apply_local_shear:
94
+ return (2.0 / 3.0) * self._cohesion
95
+ return self._cohesion
96
+
97
+ @cohesion.setter
98
+ @validators.ge(0.0)
99
+ def cohesion(self, val: float):
100
+ self._cohesion = val
101
+
102
+ @property
103
+ def moist_unit_wgt(self) -> float:
104
+ return self._moist_unit_wgt
105
+
106
+ @moist_unit_wgt.setter
107
+ @validators.gt(0.0)
108
+ def moist_unit_wgt(self, val: float):
109
+ self._moist_unit_wgt = val
110
+
111
+ @property
112
+ def load_angle(self) -> float:
113
+ return self._load_angle
114
+
115
+ @load_angle.setter
116
+ @validators.le(90.0)
117
+ @validators.ge(0.0)
118
+ def load_angle(self, val: float):
119
+ self._load_angle = val
120
+
121
+ @property
122
+ def s_c(self) -> float:
123
+ return 1.0
124
+
125
+ @property
126
+ def s_q(self) -> float:
127
+ return 1.0
128
+
129
+ @property
130
+ def s_gamma(self) -> float:
131
+ return 1.0
132
+
133
+ @property
134
+ def d_c(self) -> float:
135
+ return 1.0
136
+
137
+ @property
138
+ def d_q(self) -> float:
139
+ return 1.0
140
+
141
+ @property
142
+ def d_gamma(self) -> float:
143
+ return 1.0
144
+
145
+ @property
146
+ def i_c(self) -> float:
147
+ return 1.0
148
+
149
+ @property
150
+ def i_q(self) -> float:
151
+ return 1.0
152
+
153
+ @property
154
+ def i_gamma(self) -> float:
155
+ return 1.0
156
+
157
+ def _cohesion_term(self, coef: float = 1.0) -> float:
158
+ return coef * self.cohesion * self.n_c * self.s_c * self.d_c * self.i_c
159
+
160
+ def _surcharge_term(self) -> float:
161
+ depth = self.foundation_size.depth
162
+ water_level = self.foundation_size.ground_water_level
163
+
164
+ if water_level is None:
165
+ water_corr = 1.0 # water correction
166
+ else:
167
+ # water level above the base of the foundation
168
+ a = max(depth - water_level, 0.0)
169
+ water_corr = min(1 - 0.5 * a / depth, 1)
170
+
171
+ # effective overburden pressure (surcharge)
172
+ eop = self.moist_unit_wgt * depth
173
+ return eop * self.n_q * self.s_q * self.d_q * self.i_q * water_corr
174
+
175
+ def _embedment_term(self, coef: float = 0.5) -> float:
176
+ depth = self.foundation_size.depth
177
+ width = self.foundation_size.effective_width
178
+ water_level = self.foundation_size.ground_water_level
179
+
180
+ if water_level is None:
181
+ # water correction
182
+ water_corr = 1.0
183
+ else:
184
+ #: b -> water level below the base of the foundation
185
+ b = max(water_level - depth, 0)
186
+ water_corr = min(0.5 + 0.5 * b / width, 1)
187
+
188
+ return (coef * self.moist_unit_wgt * width * self.n_gamma
189
+ * self.s_gamma * self.d_gamma * self.i_gamma * water_corr)
190
+
191
+ @round_
192
+ def bearing_capacity(self):
193
+ """Calculates the ultimate bearing capacity."""
194
+ return (self._cohesion_term(1.0)
195
+ + self._surcharge_term()
196
+ + self._embedment_term(0.5))
197
+
198
+ @property
199
+ @abstractmethod
200
+ def n_c(self) -> float:
201
+ ...
202
+
203
+ @property
204
+ @abstractmethod
205
+ def n_q(self) -> float:
206
+ ...
207
+
208
+ @property
209
+ @abstractmethod
210
+ def n_gamma(self) -> float:
211
+ ...
212
+
213
+
214
+ from .hansen_ubc import HansenUltimateBearingCapacity
215
+ from .terzaghi_ubc import (TerzaghiUBC4CircularFooting,
216
+ TerzaghiUBC4RectangularFooting,
217
+ TerzaghiUBC4SquareFooting,
218
+ TerzaghiUBC4StripFooting)
219
+ from .vesic_ubc import VesicUltimateBearingCapacity
220
+
221
+
222
+ @enum_repr
223
+ class UBC_TYPE(enum.StrEnum):
224
+ """Enumeration of available ultimate bearing capacity types."""
225
+ HANSEN = enum.auto()
226
+ TERZAGHI = enum.auto()
227
+ VESIC = enum.auto()
228
+
229
+
230
+ def create_ultimate_bearing_capacity(friction_angle: float,
231
+ cohesion: float,
232
+ moist_unit_wgt: float,
233
+ depth: float,
234
+ width: float,
235
+ length: Optional[float] = None,
236
+ eccentricity: float = 0.0,
237
+ ground_water_level: Optional[
238
+ float] = None,
239
+ shape: Shape | str = Shape.SQUARE,
240
+ load_angle=0.0,
241
+ apply_local_shear=False,
242
+ ubc_type: Optional[UBC_TYPE | str] = None,
243
+ ) -> UltimateBearingCapacity:
244
+ r"""A factory function that encapsulate the creation of ultimate bearing
245
+ capacity.
246
+
247
+ :param friction_angle: Internal angle of friction for general shear
248
+ failure. (degree)
249
+ :type friction_angle: float
250
+
251
+ :param cohesion: Cohesion of soil. (kPa)
252
+ :type cohesion: float
253
+
254
+ :param moist_unit_wgt: Moist unit weight of soil. (:math:`kN/m^3`)
255
+ :type moist_unit_wgt: float
256
+
257
+ :param depth: Depth of foundation. (m)
258
+ :type depth: float
259
+
260
+ :param width: Width of foundation footing. (m)
261
+ :type width: float
262
+
263
+ :param length: Length of foundation footing. (m)
264
+ :type length: float, optional
265
+
266
+ :param eccentricity: The deviation of the foundation load from the
267
+ center of gravity of the foundation footing,
268
+ defaults to 0.0. This means that the foundation
269
+ load aligns with the center of gravity of the
270
+ foundation footing. (m)
271
+ :type eccentricity: float, optional
272
+
273
+ :param ground_water_level: Depth of water below ground level. (m)
274
+ :type ground_water_level: float
275
+
276
+ :param shape: Shape of foundation footing, defaults to "SQUARE".
277
+ :type shape: Shape | str, optional
278
+
279
+ :param load_angle: Inclination of the applied load with the vertical
280
+ (:math:`\alpha^{\circ}`), defaults to 0.0.
281
+ :type load_angle: float, optional
282
+
283
+ :param apply_local_shear: Indicate whether bearing capacity failure is
284
+ general or local shear failure, defaults to
285
+ False.
286
+ :type apply_local_shear: bool, optional
287
+
288
+ :param ubc_type: Type of allowable bearing capacity calculation to apply.
289
+ Available values are: "HANSEN", "TERZAGHI", "VESIC".
290
+ defaults to None.
291
+ :type ubc_type: UBC_TYPE | str, optional
292
+
293
+ :raises ValueError: Raised if ubc_type is not supported.
294
+ :raises ValueError: Raised when length is not provided for a rectangular
295
+ footing.
296
+ :raises ValueError: Raised if an invalid footing shape is provided.
297
+ """
298
+ msg = (f"{ubc_type = } is not supported, Supported "
299
+ f"types are: {list(UBC_TYPE)}")
300
+
301
+ if ubc_type is None:
302
+ raise ValueError(msg)
303
+
304
+ try:
305
+ ubc_type = UBC_TYPE(str(ubc_type).casefold())
306
+ except ValueError as e:
307
+ raise ValueError(msg) from e
308
+
309
+ # exception from create_foundation will automaatically propagate
310
+ # no need to catch and handle it.
311
+ fnd_size = create_foundation(depth=depth,
312
+ width=width,
313
+ length=length,
314
+ eccentricity=eccentricity,
315
+ ground_water_level=ground_water_level,
316
+ shape=shape)
317
+ ubc_classes = {
318
+ UBC_TYPE.HANSEN: HansenUltimateBearingCapacity,
319
+ UBC_TYPE.TERZAGHI: {Shape.STRIP: TerzaghiUBC4StripFooting,
320
+ Shape.CIRCLE: TerzaghiUBC4CircularFooting,
321
+ Shape.SQUARE: TerzaghiUBC4SquareFooting,
322
+ Shape.RECTANGLE: TerzaghiUBC4RectangularFooting},
323
+ UBC_TYPE.VESIC: VesicUltimateBearingCapacity,
324
+ }
325
+
326
+ if ubc_type == UBC_TYPE.TERZAGHI:
327
+ ubc_class = ubc_classes[ubc_type][fnd_size.footing_shape]
328
+ else:
329
+ ubc_class = ubc_classes[ubc_type]
330
+
331
+ ubc = ubc_class(friction_angle=friction_angle,
332
+ cohesion=cohesion,
333
+ moist_unit_wgt=moist_unit_wgt,
334
+ foundation_size=fnd_size,
335
+ load_angle=load_angle,
336
+ apply_local_shear=apply_local_shear)
337
+ return ubc
@@ -0,0 +1,296 @@
1
+ """ Hansen ultimate bearing capacity module.
2
+
3
+ Classes
4
+ =======
5
+
6
+ .. autosummary::
7
+ :toctree: _autosummary
8
+
9
+ HansenUltimateBearingCapacity
10
+ """
11
+ from geolysis.bearing_capacity.ubc import UltimateBearingCapacity
12
+ from geolysis.foundation import FoundationSize, Shape
13
+ from geolysis.utils import cos, cot, exp, isclose, pi, round_, sin, tan
14
+
15
+ __all__ = ["HansenUltimateBearingCapacity"]
16
+
17
+
18
+ @round_
19
+ def n_c(friction_angle: float) -> float:
20
+ if isclose(friction_angle, 0.0):
21
+ return 5.14
22
+ return cot(friction_angle) * (n_q(friction_angle) - 1.0)
23
+
24
+
25
+ @round_
26
+ def n_q(friction_angle: float) -> float:
27
+ return (tan(45.0 + friction_angle / 2.0) ** 2.0
28
+ * exp(pi * tan(friction_angle)))
29
+
30
+
31
+ @round_
32
+ def n_gamma(friction_angle: float) -> float:
33
+ return 1.8 * (n_q(friction_angle) - 1.0) * tan(friction_angle)
34
+
35
+
36
+ @round_
37
+ def s_c(f_width: float, f_length: float, f_shape: Shape) -> float:
38
+ if f_shape == Shape.STRIP:
39
+ return 1.0
40
+ elif f_shape == Shape.RECTANGLE:
41
+ return 1.0 + 0.2 * f_width / f_length
42
+ else: # SQUARE & CIRCLE
43
+ return 1.3
44
+
45
+
46
+ @round_
47
+ def s_q(f_width: float, f_length: float, f_shape: Shape) -> float:
48
+ if f_shape == Shape.STRIP:
49
+ return 1.0
50
+ elif f_shape == Shape.RECTANGLE:
51
+ return 1.0 + 0.2 * f_width / f_length
52
+ else: # SQUARE & CIRCLE
53
+ return 1.2
54
+
55
+
56
+ @round_
57
+ def s_gamma(f_width: float, f_length: float, f_shape: Shape) -> float:
58
+ if f_shape == Shape.STRIP:
59
+ return 1.0
60
+ elif f_shape == Shape.RECTANGLE:
61
+ return 1.0 - 0.4 * f_width / f_length
62
+ elif f_shape == Shape.SQUARE:
63
+ return 0.8
64
+ else: # CIRCLE
65
+ return 0.6
66
+
67
+
68
+ @round_
69
+ def d_c(f_depth: float, f_width: float) -> float:
70
+ return 1.0 + 0.35 * f_depth / f_width
71
+
72
+
73
+ @round_
74
+ def d_q(f_depth: float, f_width: float) -> float:
75
+ return d_c(f_depth, f_width)
76
+
77
+
78
+ @round_
79
+ def d_gamma() -> float:
80
+ return 1.0
81
+
82
+
83
+ @round_
84
+ def i_c(cohesion: float,
85
+ load_angle: float,
86
+ f_width: float,
87
+ f_length: float) -> float:
88
+ return 1.0 - sin(load_angle) / (2.0 * cohesion * f_width * f_length)
89
+
90
+
91
+ @round_
92
+ def i_q(load_angle: float) -> float:
93
+ return 1.0 - (1.5 * sin(load_angle)) / cos(load_angle)
94
+
95
+
96
+ @round_
97
+ def i_gamma(load_angle: float) -> float:
98
+ return i_q(load_angle) ** 2.0
99
+
100
+
101
+ class HansenUltimateBearingCapacity(UltimateBearingCapacity):
102
+ r"""Ultimate bearing capacity for soils according to ``Hansen (1961)``.
103
+
104
+ :Equation:
105
+
106
+ .. math::
107
+
108
+ q_u = cN_c s_c d_c i_c + qN_q s_q d_q i_q
109
+ + 0.5 \gamma B N_{\gamma} s_{\gamma} d_{\gamma} i_{\gamma}
110
+
111
+ .. list-table::
112
+ :widths: auto
113
+ :header-rows: 1
114
+
115
+ * - Symbol
116
+ - Description
117
+ - Unit
118
+ * - :math:`q_u`
119
+ - Ultimate bearing capacity
120
+ - :math:`kPa`
121
+ * - :math:`c`
122
+ - Cohesion of soil
123
+ - :math:`kPa`
124
+ * - :math:`q`
125
+ - Overburden pressure of soil
126
+ - :math:`kPa`
127
+ * - :math:`\gamma`
128
+ - Unit weight of soil
129
+ - :math:`kN/m^3`
130
+ * - :math:`B`
131
+ - Width of foundation footing
132
+ - :math:`m`
133
+ * - :math:`N_c`, :math:`N_q`, :math:`N_{\gamma}`
134
+ - Bearing capacity factors
135
+ - —
136
+ * - :math:`s_c`, :math:`s_q`, :math:`s_{\gamma}`
137
+ - Shape factors
138
+ - —
139
+ * - :math:`d_c`, :math:`d_q`, :math:`d_{\gamma}`
140
+ - Depth factors
141
+ - —
142
+ * - :math:`i_c`, :math:`i_q`, :math:`i_{\gamma}`
143
+ - Inclination factors
144
+ - —
145
+ """
146
+
147
+ @property
148
+ def n_c(self) -> float:
149
+ r"""Bearing capacity factor :math:`N_c`.
150
+
151
+ :Equation:
152
+
153
+ .. math:: N_c = \cot(\phi) \left(N_q - 1\right)
154
+ """
155
+ return n_c(self.friction_angle)
156
+
157
+ @property
158
+ def n_q(self) -> float:
159
+ r"""Bearing capacity factor :math:`N_q`.
160
+
161
+ :Equation:
162
+
163
+ .. math::
164
+
165
+ N_q = \tan^2\left(45 + \frac{\phi}{2}\right) \cdot e^{\pi \tan(\phi)}
166
+ """
167
+ return n_q(self.friction_angle)
168
+
169
+ @property
170
+ def n_gamma(self) -> float:
171
+ r"""Bearing capacity factor :math:`N_{\gamma}`.
172
+
173
+ :Equation:
174
+
175
+ .. math:: N_{\gamma} = 1.8 \left(N_q - 1\right) \tan(\phi)
176
+ """
177
+ return n_gamma(self.friction_angle)
178
+
179
+ @property
180
+ def s_c(self) -> float:
181
+ r"""Shape factor :math:`S_c`.
182
+
183
+ :Equation:
184
+
185
+ .. math::
186
+
187
+ s_c &= 1.0 \rightarrow \text{Strip footing}
188
+
189
+ s_c &= 1.0 + 0.2 \frac{B}{L} \rightarrow \text{Rectangular footing}
190
+
191
+ s_c &= 1.3 \rightarrow \text{Square or circular footing}
192
+ """
193
+ width, length, shape = self.foundation_size.footing_params()
194
+ return s_c(width, length, shape)
195
+
196
+ @property
197
+ def s_q(self) -> float:
198
+ r"""Shape factor :math:`S_q`.
199
+
200
+ :Equation:
201
+
202
+ .. math::
203
+
204
+ s_q &= 1.0 \rightarrow \text{Strip footing}
205
+
206
+ s_q &= 1.0 + 0.2 \frac{B}{L} \rightarrow \text{Rectangular footing}
207
+
208
+ s_q &= 1.2 \rightarrow \text{Square or circular footing}
209
+ """
210
+ width, length, shape = self.foundation_size.footing_params()
211
+ return s_q(width, length, shape)
212
+
213
+ @property
214
+ def s_gamma(self) -> float:
215
+ r"""Shape factor :math:`S_{\gamma}`.
216
+
217
+ :Equation:
218
+
219
+ .. math::
220
+
221
+ s_{\gamma} &= 1.0 \rightarrow \text{Strip footing}
222
+
223
+ s_{\gamma} &= 1.0 - 0.4 \frac{B}{L} \rightarrow
224
+ \text{Rectangular footing}
225
+
226
+ s_{\gamma} &= 0.8 \rightarrow \text{Square footing}
227
+
228
+ s_{\gamma} &= 0.6 \rightarrow \text{Circular footing}
229
+ """
230
+ width, length, shape = self.foundation_size.footing_params()
231
+ return s_gamma(width, length, shape)
232
+
233
+ @property
234
+ def d_c(self) -> float:
235
+ r"""Depth factor :math:`D_c`.
236
+
237
+ :Equation:
238
+
239
+ .. math:: d_c = 1.0 + 0.35 \cdot \frac{D_f}{B}
240
+ """
241
+ depth = self.foundation_size.depth
242
+ width = self.foundation_size.width
243
+ return d_c(depth, width)
244
+
245
+ @property
246
+ def d_q(self) -> float:
247
+ r"""Depth factor :math:`D_q`.
248
+
249
+ :Equation:
250
+
251
+ .. math:: d_q = 1.0 + 0.35 \cdot \frac{D_f}{B}
252
+ """
253
+ depth = self.foundation_size.depth
254
+ width = self.foundation_size.width
255
+ return d_q(depth, width)
256
+
257
+ @property
258
+ def d_gamma(self) -> float:
259
+ r"""Depth factor :math:`D_{\gamma}`.
260
+
261
+ :Equation:
262
+
263
+ .. math:: d_{\gamma} = 1.0
264
+ """
265
+ return d_gamma()
266
+
267
+ @property
268
+ def i_c(self) -> float:
269
+ r"""Inclination factor :math:`I_c`.
270
+
271
+ :Equation:
272
+
273
+ .. math:: I_c = 1 - \frac{\sin(\alpha)}{2cBL}
274
+ """
275
+ width, length = self.foundation_size.width, self.foundation_size.length
276
+ return i_c(self.cohesion, self.load_angle, width, length)
277
+
278
+ @property
279
+ def i_q(self) -> float:
280
+ r"""Inclination factor :math:`I_q`.
281
+
282
+ :Equation:
283
+
284
+ .. math:: I_q = 1 - \frac{1.5 \sin(\alpha)}{\cos(\alpha)}
285
+ """
286
+ return i_q(self.load_angle)
287
+
288
+ @property
289
+ def i_gamma(self) -> float:
290
+ r"""Inclination factor :math:`I_{\gamma}`.
291
+
292
+ :Equation:
293
+
294
+ .. math:: I_{\gamma} = I_q^2
295
+ """
296
+ return i_gamma(self.load_angle)