geolysis 0.10.3__py3-none-any.whl → 0.12.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.
@@ -1,5 +1,6 @@
1
1
  from abc import ABC, abstractmethod
2
- from typing import Annotated
2
+ from dataclasses import dataclass
3
+ from typing import Annotated, Optional
3
4
 
4
5
  from func_validator import (
5
6
  validate_func_args,
@@ -8,40 +9,48 @@ from func_validator import (
8
9
  )
9
10
 
10
11
  from geolysis.foundation import Foundation
11
- from geolysis.utils import arctan, round_, tan
12
+ from geolysis.utils import arctandeg, round_, tandeg
13
+
14
+
15
+ @dataclass(frozen=True, slots=True)
16
+ class UltimateBearingCapacityResult:
17
+ ultimate_bearing_capacity: float
18
+ allowable_bearing_capacity: float
19
+ allowable_applied_load: float
20
+ n_c: float
21
+ n_q: float
22
+ n_gamma: float
23
+ s_c: float
24
+ s_q: float
25
+ s_gamma: float
26
+ d_c: float
27
+ d_q: float
28
+ d_gamma: float
29
+ i_c: float
30
+ i_q: float
31
+ i_gamma: float
12
32
 
13
33
 
14
34
  class UltimateBearingCapacity(ABC):
15
35
  def __init__(
16
- self,
17
- friction_angle: float,
18
- cohesion: float,
19
- moist_unit_wgt: float,
20
- foundation_size: Foundation,
21
- apply_local_shear: bool = False,
36
+ self,
37
+ friction_angle: float,
38
+ cohesion: float,
39
+ moist_unit_wgt: float,
40
+ foundation_size: Foundation,
41
+ saturated_unit_wgt: float = 20.5,
42
+ apply_local_shear: bool = False,
43
+ factor_of_safety: float = 3.0,
22
44
  ) -> None:
23
45
  r"""
24
-
25
- $$
26
- q_u = cN_c s_c d_c i_c + qN_q s_q d_q i_q
27
- + 0.5 \gamma B N_{\gamma} s_{\gamma} d_{\gamma} i_{\gamma}
28
- $$
29
-
30
- - $q_u$ (kPa): Ultimate bearing capacity
31
- - $c$ (kPa): Cohesion of soil
32
- - $q$ (kPa): Overburden pressure of soil
33
- - $\gamma$ (kN/m³): Unit weight of soil
34
- - $B$ (m): Width of foundation footing
35
- - $N_c$, $N_q$, $N_{\gamma}$: Bearing capacity factors
36
- - $s_c$, $s_q$, $s_{\gamma}$: Shape factors
37
- - $d_c$, $d_q$, $d_{\gamma}$: Depth factors
38
- - $i_c$, $i_q$, $i_{\gamma}$: Inclination factors
39
-
40
46
  :param friction_angle: Internal angle of friction for general
41
47
  shear failure (degrees).
42
48
  :param cohesion: Cohesion of soil ($kPa$).
43
49
  :param moist_unit_wgt: Moist unit weight of soil ($kN/m^3$).
44
50
  :param foundation_size: Size of the foundation.
51
+ :param saturated_unit_wgt: Saturated unit weight of soil ($kN/m^3$).
52
+ :param factor_of_safety: Factor of safety against bearing
53
+ capacity failure. Added in v0.12.0.
45
54
  :param apply_local_shear: Indicate whether bearing capacity
46
55
  failure is general shear or local
47
56
  shear failure.
@@ -50,6 +59,8 @@ class UltimateBearingCapacity(ABC):
50
59
  self.cohesion = cohesion
51
60
  self.moist_unit_wgt = moist_unit_wgt
52
61
  self.foundation_size = foundation_size
62
+ self.saturated_unit_wgt = saturated_unit_wgt
63
+ self.factor_of_safety = factor_of_safety
53
64
  self.apply_local_shear = apply_local_shear
54
65
 
55
66
  @property
@@ -65,7 +76,7 @@ class UltimateBearingCapacity(ABC):
65
76
 
66
77
  """
67
78
  if self.apply_local_shear:
68
- return arctan((2.0 / 3.0) * tan(self._friction_angle))
79
+ return arctandeg((2.0 / 3.0) * tandeg(self._friction_angle))
69
80
  return self._friction_angle
70
81
 
71
82
  @friction_angle.setter
@@ -80,9 +91,7 @@ class UltimateBearingCapacity(ABC):
80
91
 
81
92
  In the case of local shear failure:
82
93
 
83
- $$
84
- C^{'} = \dfrac{2}{3} \cdot C
85
- $$
94
+ $$C^{'} = \dfrac{2}{3} \cdot C$$
86
95
  """
87
96
  if self.apply_local_shear:
88
97
  return (2.0 / 3.0) * self._cohesion
@@ -103,6 +112,16 @@ class UltimateBearingCapacity(ABC):
103
112
  def moist_unit_wgt(self, val: Annotated[float, MustBePositive]):
104
113
  self._moist_unit_wgt = val
105
114
 
115
+ @property
116
+ def saturated_unit_wgt(self) -> float:
117
+ """Saturated unit weight of soil ($kN/m^3$)."""
118
+ return self._saturated_unit_wgt
119
+
120
+ @saturated_unit_wgt.setter
121
+ @validate_func_args
122
+ def saturated_unit_wgt(self, val: Annotated[float, MustBePositive]):
123
+ self._saturated_unit_wgt = val
124
+
106
125
  @property
107
126
  def load_angle(self):
108
127
  """Inclination of the applied load with the vertical."""
@@ -151,78 +170,107 @@ class UltimateBearingCapacity(ABC):
151
170
  depth = self.foundation_size.depth
152
171
  water_level = self.foundation_size.ground_water_level
153
172
 
154
- if water_level is None:
155
- water_corr = 1.0 # water correction
156
- else:
157
- # water level above the base of the foundation
158
- a = max(depth - water_level, 0.0)
159
- water_corr = min(1 - 0.5 * a / depth, 1)
160
-
161
- # effective overburden pressure (surcharge)
162
- eop = self.moist_unit_wgt * depth
163
- return eop * self.n_q * self.s_q * self.d_q * self.i_q * water_corr
173
+ unit_wgt = self.moist_unit_wgt
174
+ eop = unit_wgt * depth
175
+ if water_level is not None:
176
+ if water_level < depth:
177
+ d_1 = water_level
178
+ d_2 = depth - d_1
179
+ unit_wgt = self.saturated_unit_wgt - 9.81
180
+ eop = self.moist_unit_wgt * d_1 + unit_wgt * d_2
181
+ return eop * self.n_q * self.s_q * self.d_q * self.i_q
164
182
 
165
183
  def _embedment_term(self, coef: float = 0.5) -> float:
166
184
  depth = self.foundation_size.depth
167
185
  width = self.foundation_size.effective_width
168
186
  water_level = self.foundation_size.ground_water_level
169
187
 
170
- if water_level is None:
171
- # water correction
172
- water_corr = 1.0
173
- else:
174
- #: b -> water level below the base of the foundation
175
- b = max(water_level - depth, 0)
176
- water_corr = min(0.5 + 0.5 * b / width, 1)
188
+ unit_wgt = self.moist_unit_wgt
189
+
190
+ if water_level is not None:
191
+ wgt = self.saturated_unit_wgt - 9.81
192
+ if water_level < depth:
193
+ unit_wgt = wgt
194
+ else:
195
+ d = water_level - depth
196
+ if d <= width:
197
+ unit_wgt = wgt + (d / width) * (self.moist_unit_wgt - wgt)
177
198
 
178
199
  return (
179
- coef
180
- * self.moist_unit_wgt
181
- * width
182
- * self.n_gamma
183
- * self.s_gamma
184
- * self.d_gamma
185
- * self.i_gamma
186
- * water_corr
200
+ coef
201
+ * unit_wgt
202
+ * width
203
+ * self.n_gamma
204
+ * self.s_gamma
205
+ * self.d_gamma
206
+ * self.i_gamma
187
207
  )
188
208
 
189
- @round_(ndigits=2)
190
- def bearing_capacity(self) -> float:
191
- """Calculates the ultimate bearing capacity."""
209
+ def _bearing_capacity(self) -> float:
192
210
  return (
193
- self._cohesion_term(1.0)
194
- + self._surcharge_term()
195
- + self._embedment_term(0.5)
211
+ self._cohesion_term(1.0)
212
+ + self._surcharge_term()
213
+ + self._embedment_term(0.5)
196
214
  )
197
215
 
198
- def bearing_capacity_results(self) -> dict:
199
- return {
200
- "bearing_capacity": self.bearing_capacity(),
201
- "n_c": self.n_c,
202
- "n_q": self.n_q,
203
- "n_gamma": self.n_gamma,
204
- "s_c": self.s_c,
205
- "s_q": self.s_q,
206
- "s_gamma": self.s_gamma,
207
- "d_c": self.d_c,
208
- "d_q": self.d_q,
209
- "d_gamma": self.d_gamma,
210
- "i_c": self.i_c,
211
- "i_q": self.i_q,
212
- "i_gamma": self.i_gamma,
213
- }
216
+ def bearing_capacity_results(self) -> UltimateBearingCapacityResult:
217
+ """Return a dictionary of bearing capacity results with
218
+ intermediate calculations.
219
+
220
+ !!! info "Added in v0.11.0"
221
+
222
+ """
223
+ return UltimateBearingCapacityResult(
224
+ ultimate_bearing_capacity=self.ultimate_bearing_capacity(),
225
+ allowable_bearing_capacity=self.allowable_bearing_capacity(),
226
+ allowable_applied_load=self.allowable_applied_load(),
227
+ n_c=self.n_c,
228
+ n_q=self.n_q,
229
+ n_gamma=self.n_gamma,
230
+ s_c=self.s_c,
231
+ s_q=self.s_q,
232
+ s_gamma=self.s_gamma,
233
+ d_c=self.d_c,
234
+ d_q=self.d_q,
235
+ d_gamma=self.d_gamma,
236
+ i_c=self.i_c,
237
+ i_q=self.i_q,
238
+ i_gamma=self.i_gamma,
239
+ )
240
+
241
+ @round_(ndigits=1)
242
+ def ultimate_bearing_capacity(self) -> float:
243
+ """Calculates the ultimate bearing capacity.
244
+
245
+ !!! info "Added in v0.12.0"
246
+ """
247
+ return self._bearing_capacity()
248
+
249
+ @round_(ndigits=1)
250
+ def allowable_bearing_capacity(self) -> float:
251
+ """Calculates the allowable bearing capacity.
252
+
253
+ !!! info "Added in v0.12.0"
254
+ """
255
+ return self._bearing_capacity() / self.factor_of_safety
256
+
257
+ @round_(ndigits=1)
258
+ def allowable_applied_load(self) -> float:
259
+ """Calculates the allowable applied load.
260
+
261
+ !!! info "Added in v0.12.0"
262
+ """
263
+ area = self.foundation_size.foundation_area()
264
+ return self.allowable_bearing_capacity() * area
214
265
 
215
266
  @property
216
267
  @abstractmethod
217
- def n_c(self) -> float:
218
- ...
268
+ def n_c(self) -> float: ...
219
269
 
220
270
  @property
221
271
  @abstractmethod
222
- def n_q(self) -> float:
223
- ...
272
+ def n_q(self) -> float: ...
224
273
 
225
274
  @property
226
275
  @abstractmethod
227
- def n_gamma(self) -> float:
228
- ...
276
+ def n_gamma(self) -> float: ...
@@ -1,5 +1,15 @@
1
1
  from geolysis.foundation import Shape
2
- from geolysis.utils import cos, cot, exp, isclose, pi, round_, sin, tan
2
+ from geolysis.utils import (
3
+ cosdeg,
4
+ cotdeg,
5
+ exp,
6
+ isclose,
7
+ pi,
8
+ round_,
9
+ sindeg,
10
+ tandeg,
11
+ add_repr,
12
+ )
3
13
 
4
14
  from ._core import UltimateBearingCapacity
5
15
 
@@ -13,14 +23,16 @@ class HansenBearingCapacityFactors:
13
23
  def n_c(friction_angle: float) -> float:
14
24
  if isclose(friction_angle, 0.0):
15
25
  return 5.14
16
- return cot(friction_angle) * (
26
+ return cotdeg(friction_angle) * (
17
27
  HansenBearingCapacityFactors.n_q(friction_angle) - 1.0
18
28
  )
19
29
 
20
30
  @staticmethod
21
31
  @round_(ndigits=2)
22
32
  def n_q(friction_angle: float) -> float:
23
- return tan(45.0 + friction_angle / 2.0) ** 2.0 * exp(pi * tan(friction_angle))
33
+ return tandeg(45.0 + friction_angle / 2.0) ** 2.0 * exp(
34
+ pi * tandeg(friction_angle)
35
+ )
24
36
 
25
37
  @staticmethod
26
38
  @round_(ndigits=2)
@@ -28,7 +40,7 @@ class HansenBearingCapacityFactors:
28
40
  return (
29
41
  1.8
30
42
  * (HansenBearingCapacityFactors.n_q(friction_angle) - 1.0)
31
- * tan(friction_angle)
43
+ * tandeg(friction_angle)
32
44
  )
33
45
 
34
46
 
@@ -95,12 +107,12 @@ class HansenInclinationFactors:
95
107
  f_width: float,
96
108
  f_length: float,
97
109
  ) -> float:
98
- return 1.0 - sin(load_angle) / (2.0 * cohesion * f_width * f_length)
110
+ return 1.0 - sindeg(load_angle) / (2.0 * cohesion * f_width * f_length)
99
111
 
100
112
  @staticmethod
101
113
  @round_(ndigits=2)
102
114
  def i_q(load_angle: float) -> float:
103
- return 1.0 - (1.5 * sin(load_angle)) / cos(load_angle)
115
+ return 1.0 - (1.5 * sindeg(load_angle)) / cosdeg(load_angle)
104
116
 
105
117
  @staticmethod
106
118
  @round_(ndigits=2)
@@ -108,143 +120,70 @@ class HansenInclinationFactors:
108
120
  return HansenInclinationFactors.i_q(load_angle) ** 2.0
109
121
 
110
122
 
123
+ @add_repr
111
124
  class HansenUltimateBearingCapacity(UltimateBearingCapacity):
112
- r"""Ultimate bearing capacity for soils according to `Hansen (1961)`."""
125
+ r"""Ultimate bearing capacity for soils according to `Hansen (1961)`.
126
+
127
+ See [implementation](../formulas/ultimate-bearing-capacity.md/#hansen-bearing-capacity)
128
+ for more details on bearing capacity equation used.
129
+
130
+ """
113
131
 
114
132
  @property
115
133
  def n_c(self) -> float:
116
- r"""Bearing capacity factor $N_c$.
117
-
118
- $$
119
- N_c = \cot(\phi) \left(N_q - 1\right)
120
- $$
121
- """
134
+ r"""Bearing capacity factor $N_c$."""
122
135
  return HansenBearingCapacityFactors.n_c(self.friction_angle)
123
136
 
124
137
  @property
125
138
  def n_q(self) -> float:
126
- r"""Bearing capacity factor $N_q$.
127
-
128
- $$
129
- N_q = \tan^2\left(45 + \frac{\phi}{2}\right) \cdot e^{\pi \tan(\phi)}
130
- $$
131
- """
139
+ r"""Bearing capacity factor $N_q$."""
132
140
  return HansenBearingCapacityFactors.n_q(self.friction_angle)
133
141
 
134
142
  @property
135
143
  def n_gamma(self) -> float:
136
- r"""Bearing capacity factor $N_{\gamma}$.
137
-
138
- $$
139
- N_{\gamma} = 1.8 \left(N_q - 1\right) \tan(\phi)
140
- $$
141
- """
144
+ r"""Bearing capacity factor $N_{\gamma}$."""
142
145
  return HansenBearingCapacityFactors.n_gamma(self.friction_angle)
143
146
 
144
147
  @property
145
148
  def s_c(self) -> float:
146
- r"""Shape factor $S_c$.
147
-
148
- $$
149
- s_c = 1.0 \rightarrow \text{Strip footing}
150
- $$
151
-
152
- $$
153
- s_c = 1.0 + 0.2 \frac{B}{L} \rightarrow \text{Rectangular footing}
154
- $$
155
-
156
- $$
157
- s_c = 1.3 \rightarrow \text{Square or circular footing}
158
- $$
159
- """
149
+ r"""Shape factor $S_c$."""
160
150
  width, length, shape = self.foundation_size.footing_params()
161
151
  return HansenShapeFactors.s_c(width, length, shape)
162
152
 
163
153
  @property
164
154
  def s_q(self) -> float:
165
- r"""Shape factor $S_q$.
166
-
167
- $$
168
- s_q = 1.0 \rightarrow \text{Strip footing}
169
- $$
170
-
171
- $$
172
- s_q = 1.0 + 0.2 \cdot \frac{B}{L} \rightarrow \text{Rectangular footing}
173
- $$
174
-
175
- $$
176
- s_q = 1.2 \rightarrow \text{Square or circular footing}
177
- $$
178
- """
155
+ r"""Shape factor $S_q$."""
179
156
  width, length, shape = self.foundation_size.footing_params()
180
157
  return HansenShapeFactors.s_q(width, length, shape)
181
158
 
182
159
  @property
183
160
  def s_gamma(self) -> float:
184
- r"""Shape factor $S_{\gamma}$.
185
-
186
- $$
187
- s_{\gamma} = 1.0 \rightarrow \text{Strip footing}
188
- $$
189
-
190
- $$
191
- s_{\gamma} = 1.0 - 0.4 \frac{B}{L} \rightarrow
192
- \text{Rectangular footing}
193
- $$
194
-
195
- $$
196
- s_{\gamma} = 0.8 \rightarrow \text{Square footing}
197
- $$
198
-
199
- $$
200
- s_{\gamma} = 0.6 \rightarrow \text{Circular footing}
201
- $$
202
- """
161
+ r"""Shape factor $S_{\gamma}$."""
203
162
  width, length, shape = self.foundation_size.footing_params()
204
163
  return HansenShapeFactors.s_gamma(width, length, shape)
205
164
 
206
165
  @property
207
166
  def d_c(self) -> float:
208
- r"""Depth factor $D_c$.
209
-
210
- $$
211
- d_c = 1.0 + 0.35 \cdot \frac{D_f}{B}
212
- $$
213
- """
167
+ r"""Depth factor $D_c$."""
214
168
  depth = self.foundation_size.depth
215
169
  width = self.foundation_size.width
216
170
  return HansenDepthFactors.d_c(depth, width)
217
171
 
218
172
  @property
219
173
  def d_q(self) -> float:
220
- r"""Depth factor $D_q$.
221
-
222
- $$
223
- d_q = 1.0 + 0.35 \cdot \frac{D_f}{B}
224
- $$
225
- """
174
+ r"""Depth factor $D_q$."""
226
175
  depth = self.foundation_size.depth
227
176
  width = self.foundation_size.width
228
177
  return HansenDepthFactors.d_q(depth, width)
229
178
 
230
179
  @property
231
180
  def d_gamma(self) -> float:
232
- r"""Depth factor $D_{\gamma}$.
233
-
234
- $$
235
- d_{\gamma} = 1.0
236
- $$
237
- """
181
+ r"""Depth factor $D_{\gamma}$."""
238
182
  return HansenDepthFactors.d_gamma()
239
183
 
240
184
  @property
241
185
  def i_c(self) -> float:
242
- r"""Inclination factor $I_c$.
243
-
244
- $$
245
- I_c = 1 - \frac{\sin(\alpha)}{2cBL}
246
- $$
247
- """
186
+ r"""Inclination factor $I_c$."""
248
187
  width, length = self.foundation_size.width, self.foundation_size.length
249
188
  return HansenInclinationFactors.i_c(
250
189
  self.cohesion, self.load_angle, width, length
@@ -252,20 +191,10 @@ class HansenUltimateBearingCapacity(UltimateBearingCapacity):
252
191
 
253
192
  @property
254
193
  def i_q(self) -> float:
255
- r"""Inclination factor $I_q$.
256
-
257
- $$
258
- I_q = 1 - \frac{1.5 \sin(\alpha)}{\cos(\alpha)}
259
- $$
260
- """
194
+ r"""Inclination factor $I_q$."""
261
195
  return HansenInclinationFactors.i_q(self.load_angle)
262
196
 
263
197
  @property
264
198
  def i_gamma(self) -> float:
265
- r"""Inclination factor $I_{\gamma}$.
266
-
267
- $$
268
- I_{\gamma} = I_q^2
269
- $$
270
- """
199
+ r"""Inclination factor $I_{\gamma}$."""
271
200
  return HansenInclinationFactors.i_gamma(self.load_angle)