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