PyCBA 0.4.1__tar.gz → 0.5.1__tar.gz

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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyCBA
3
- Version: 0.4.1
3
+ Version: 0.5.1
4
4
  Summary: Python Continuous Beam Analysis
5
5
  Author-email: Colin Caprani <colin.caprani@monash.edu>
6
6
  License: Apache 2.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyCBA
3
- Version: 0.4.1
3
+ Version: 0.5.1
4
4
  Summary: Python Continuous Beam Analysis
5
5
  Author-email: Colin Caprani <colin.caprani@monash.edu>
6
6
  License: Apache 2.0
@@ -2,7 +2,7 @@
2
2
  PyCBA - Continuous Beam Analysis in Python
3
3
  """
4
4
 
5
- __version__ = "0.4.1"
5
+ __version__ = "0.5.1"
6
6
 
7
7
  from .analysis import *
8
8
  from .beam import *
@@ -223,7 +223,7 @@ class BeamAnalysis:
223
223
 
224
224
  for i in range(self._n):
225
225
  dof_i = 2 * i
226
- fmbr = self._beam.get_cnl(i)
226
+ fmbr = self._beam.get_ref(i)
227
227
  # Cumulatively apply forces in opposite direction
228
228
  f[dof_i : dof_i + 4] -= fmbr
229
229
  return f
@@ -220,6 +220,18 @@ class Beam:
220
220
  """
221
221
  return len(self._restraints)
222
222
 
223
+ @property
224
+ def no_fixed_restraints(self):
225
+ """
226
+ Returns the number of fixed restraints of the beam (fully-supported DOFs)
227
+
228
+ Returns
229
+ -------
230
+ no_fixed_restraints : int
231
+ The number of fixed restraints in the beam
232
+ """
233
+ return len(np.where(np.array(self._restraints) == -1)[0])
234
+
223
235
  @property
224
236
  def length(self):
225
237
  """
@@ -268,9 +280,10 @@ class Beam:
268
280
 
269
281
  return ispan, pos_in_span
270
282
 
271
- def get_cnl(self, i_span: int) -> LoadCNL:
283
+ def get_ref(self, i_span: int) -> LoadCNL:
272
284
  """
273
- Returns Consistent Nodal Loads for the member
285
+ Returns Released End Forces for the member; that is, the Consistent Nodal Loads
286
+ modified for the element type (i.e. releases)
274
287
 
275
288
  Parameters
276
289
  ----------
@@ -279,18 +292,18 @@ class Beam:
279
292
 
280
293
  Returns
281
294
  -------
282
- cnl : LoadCNL
295
+ ref : LoadCNL
283
296
  The totalled CNL object for the member, considering all loads.
284
297
 
285
298
  """
286
- cnl = np.zeros(4)
299
+ ref = np.zeros(4)
287
300
  L = self.mbr_lengths[i_span]
288
301
  eType = self.mbr_eletype[i_span]
289
302
 
290
303
  for load in self._loads:
291
304
  if load.i_span == i_span:
292
- cnl += load.get_cnl(L, eType)
293
- return cnl
305
+ ref += load.get_ref(L, eType)
306
+ return ref
294
307
 
295
308
  def get_span_k(self, i_span: int) -> np.ndarray:
296
309
  """
@@ -119,21 +119,72 @@ class InfluenceLines:
119
119
  self.create_ils()
120
120
 
121
121
  x = self.vResults[0].results.x
122
- dx = x[2] - x[1]
123
- idx = np.where(np.abs(x - poi) <= dx * 1e-6)[0][0]
124
- # find the nearest support to the poi
125
- idxr = (
126
- np.abs(np.cumsum(np.insert(self.ba.beam.mbr_lengths, 0, 0)) - poi)
127
- ).argmin()
128
122
  npts = len(self.vResults)
129
123
  eta = np.zeros(npts)
130
124
 
131
- for i, res in enumerate(self.vResults):
132
- if load_effect == "V":
125
+ # Preparations for reaction ILs
126
+ #
127
+ # Get vector of the node locations
128
+ node_locations = np.cumsum(np.insert(self.ba.beam.mbr_lengths, 0, 0))
129
+ # Link the supported DOF to the index in the BeamAnalysis reactions vector
130
+ idx_mask = np.zeros_like(self.ba._beam.restraints)
131
+ idx_mask[np.where(np.array(self.ba._beam.restraints) == -1)] = np.arange(
132
+ self.ba.beam.no_fixed_restraints
133
+ )
134
+
135
+ # idx = np.abs(x - poi).argmin()
136
+
137
+ if load_effect.upper() == "V":
138
+ dx = x[2] - x[1]
139
+ idx = np.where(np.abs(x - poi) <= dx * 1e-6)[0][0]
140
+ for i, res in enumerate(self.vResults):
133
141
  eta[i] = res.results.V[idx]
134
- elif load_effect == "R":
135
- eta[i] = res.R[idxr]
136
- else:
142
+
143
+ elif load_effect.upper() == "R":
144
+ #
145
+ # Getting the correct reaction is tricky
146
+ #
147
+ # The indices of the supported DOFs wrt the node locations vector
148
+ vert_sups_dof_idx = np.where(np.array(self.ba._beam.restraints)[::2] == -1)[
149
+ 0
150
+ ]
151
+ # The locations then of these supports
152
+ vert_sups_locs = node_locations[vert_sups_dof_idx]
153
+ # The index of the closest support
154
+ closest_vert_sup_idx = np.abs(vert_sups_locs - poi).argmin()
155
+ # And its value
156
+ closest_vert_sup = vert_sups_locs[closest_vert_sup_idx]
157
+ # And now the index of this support in the node locations vector
158
+ vert_sup_node_idx = np.where(node_locations == closest_vert_sup)[0][0]
159
+ # And hence its index in the overall DOFs vector
160
+ vert_sup_dof_idx = 2 * vert_sup_node_idx
161
+ # And finally the index of the support nearest the POI in the reactions vector
162
+ vert_sup_idx = idx_mask[vert_sup_dof_idx]
163
+
164
+ for i, res in enumerate(self.vResults):
165
+ eta[i] = res.R[vert_sup_idx]
166
+
167
+ elif load_effect.upper() == "MR":
168
+ #
169
+ # Follows the same logic for the vertical reaction
170
+ #
171
+ mt_sups_dof_idx = np.where(np.array(self.ba._beam.restraints)[1::2] == -1)[
172
+ 0
173
+ ]
174
+ mt_sups_locs = node_locations[mt_sups_dof_idx]
175
+ closest_mt_sup_idx = np.abs(mt_sups_locs - poi).argmin()
176
+ closest_mt_sup = mt_sups_locs[closest_mt_sup_idx]
177
+ mt_sup_node_idx = np.where(node_locations == closest_mt_sup)[0][0]
178
+ mt_sup_dof_idx = 2 * mt_sup_node_idx + 1
179
+ mt_sup_idx = idx_mask[mt_sup_dof_idx]
180
+
181
+ for i, res in enumerate(self.vResults):
182
+ eta[i] = res.R[mt_sup_idx]
183
+
184
+ else:
185
+ dx = x[2] - x[1]
186
+ idx = np.where(np.abs(x - poi) <= dx * 1e-6)[0][0]
187
+ for i, res in enumerate(self.vResults):
137
188
  eta[i] = res.results.M[idx]
138
189
 
139
190
  return (np.array(self.pos), eta)
@@ -182,7 +182,7 @@ class Load:
182
182
  """
183
183
  self.i_span = i_span
184
184
 
185
- def get_cnl(self, L, eType):
185
+ def get_cnl(self, L):
186
186
  # Enforce virtual base class
187
187
  raise NotImplementedError
188
188
 
@@ -215,29 +215,26 @@ class Load:
215
215
  """
216
216
  return np.heaviside(v, value)
217
217
 
218
- def released_end_forces(self, cnl: LoadCNL, L: float, eType: int) -> LoadCNL:
218
+ def get_ref(self, L: float, eType: int) -> LoadCNL:
219
219
  """
220
- The released end forces for each element type: converts the Consistent Nodal
221
- Loads of the applied loading to the correct nodal loading depending on the
222
- element type.
220
+ Returns the Released End Forces for a span of length L of element eType:
221
+ converts the Consistent Nodal Loads of the applied loading to the correct nodal
222
+ loading depending on the element type.
223
223
 
224
224
  Parameters
225
225
  ----------
226
- cnl : LoadCNL
227
- The nodal loading statically consistent with the externally applied loads.
228
226
  L : float
229
- The length of the member.
227
+ The length of the member
230
228
  eType : int
231
- The element type.
229
+ The member element type
232
230
 
233
231
  Returns
234
232
  -------
235
233
  LoadCNL
236
- The nodal loads to be applied in the analysis, consistent with the element
237
- type.
238
-
234
+ Released End Forces for this load type: the nodal loads to be applied in
235
+ the analysis, consistent with the element type.
239
236
  """
240
-
237
+ cnl = self.get_cnl(L, eType)
241
238
  ref = np.zeros(4)
242
239
  fm = 6 / (4 * L) # flexibility coeff for moment
243
240
 
@@ -248,14 +245,14 @@ class Load:
248
245
  ref[3] = 1.0 * cnl.Mb
249
246
  elif eType == 3: # DOF = moment at i node
250
247
  ref[0] = fm * cnl.Ma
251
- ref[1] = 0.5 * cnl.Ma
248
+ ref[1] = 1.0 * cnl.Ma
252
249
  ref[2] = -fm * cnl.Ma
253
- ref[3] = 1.0 * cnl.Ma
250
+ ref[3] = 0.5 * cnl.Ma
254
251
  elif eType == 4: # keep only vertical, remove moments
255
- ref[0] = 0
256
- ref[1] = 1.0 * cnl.Va
257
- ref[2] = 0
258
- ref[3] = 1.0 * cnl.Va
252
+ ref[0] = -(cnl.Ma + cnl.Mb) / L
253
+ ref[1] = 1.0 * cnl.Ma
254
+ ref[2] = (cnl.Ma + cnl.Mb) / L
255
+ ref[3] = 1.0 * cnl.Mb
259
256
  else:
260
257
  # no nothing if it is FF
261
258
  pass
@@ -319,8 +316,7 @@ class LoadUDL(Load):
319
316
  Ma=w * L**2 / 12.0,
320
317
  Mb=-w * L**2 / 12.0,
321
318
  )
322
-
323
- return self.released_end_forces(cnl, L, eType)
319
+ return cnl
324
320
 
325
321
  def get_mbr_results(self, x: np.ndarray, L: float) -> MemberResults:
326
322
  """
@@ -416,8 +412,7 @@ class LoadPL(Load):
416
412
  Ma=P * a * b**2 / L**2,
417
413
  Mb=-P * a**2 * b / L**2,
418
414
  )
419
- # implicit conversion to tuple in correct order
420
- return self.released_end_forces(cnl, L, eType)
415
+ return cnl
421
416
 
422
417
  def get_mbr_results(self, x: np.ndarray, L: float) -> MemberResults:
423
418
  """
@@ -512,7 +507,7 @@ class LoadPUDL(Load):
512
507
  Mb=-(w * c / L**2) * (t * s**2 + (t - 2 * s) * c**2 / 12),
513
508
  )
514
509
  # implicit conversion to tuple in correct order
515
- return self.released_end_forces(cnl, L, eType)
510
+ return cnl
516
511
 
517
512
  def get_mbr_results(self, x: np.ndarray, L: float) -> MemberResults:
518
513
  """
@@ -608,8 +603,7 @@ class LoadMaMb(Load):
608
603
  Ma=Ma,
609
604
  Mb=Mb,
610
605
  )
611
- # implicit conversion to tuple in correct order
612
- return self.released_end_forces(cnl, L, eType)
606
+ return cnl
613
607
 
614
608
  def get_mbr_results(self, x: np.ndarray, L: float) -> MemberResults:
615
609
  """
@@ -690,8 +684,7 @@ class LoadML(Load):
690
684
  Ma=(m * b / L**2) * (2 * a - b),
691
685
  Mb=(m * a / L**2) * (2 * b - a),
692
686
  )
693
- # implicit conversion to tuple in correct order
694
- return self.released_end_forces(cnl, L, eType)
687
+ return cnl
695
688
 
696
689
  def get_mbr_results(self, x: np.ndarray, L: float) -> MemberResults:
697
690
  """
@@ -8,7 +8,7 @@ import numpy as np
8
8
  import matplotlib.pyplot as plt
9
9
  from scipy import integrate
10
10
  from .beam import Beam
11
- from .load import MemberResults, LoadMaMb
11
+ from .load import MemberResults, LoadMaMb, LoadCNL
12
12
  from copy import deepcopy
13
13
 
14
14
 
@@ -105,7 +105,7 @@ class BeamResults:
105
105
  fmbr = np.zeros(4)
106
106
  for j in range(4):
107
107
  fmbr[j] = np.sum(kb[j][:] * dmbr[:])
108
- fmbr += beam.get_cnl(i)
108
+ fmbr += beam.get_ref(i)
109
109
  res = self._member_values(beam, i, fmbr, dmbr)
110
110
  # Shift x vals by location of mbr starting point
111
111
  res.x += sumL
@@ -138,6 +138,9 @@ class BeamResults:
138
138
  """
139
139
 
140
140
  L = beam.mbr_lengths[i_span]
141
+ EI = beam.mbr_EIs[i_span]
142
+ etype = beam.mbr_eletype[i_span]
143
+
141
144
  dx = L / self.npts
142
145
  x = np.zeros(self.npts + 3)
143
146
  x[1 : self.npts + 2] = dx * np.arange(0, self.npts + 1)
@@ -148,16 +151,29 @@ class BeamResults:
148
151
  res = MaMb.get_mbr_results(x, L)
149
152
 
150
153
  # Now get the results for all the applied loads on a simple span
154
+ Ma = 0
155
+ Mb = 0
151
156
  for load in beam._loads:
152
157
  if load.i_span != i_span:
153
158
  continue
154
159
  res += load.get_mbr_results(x, L)
160
+ cnl = load.get_cnl(L, etype)
161
+ Ma += cnl.Ma
162
+ Mb += cnl.Mb
163
+
164
+ # If no releases, the rotation at i is easy
165
+ R0 = d[1]
166
+
167
+ # Otherwise, check account for releases
168
+ if etype > 1:
169
+ theta = (d[2] - d[0]) / L
170
+ phi = (L / (3 * EI)) * (-(f[1] - 0.5 * f[3]) + (Ma - 0.5 * Mb))
171
+ R0 = theta - phi
155
172
 
156
173
  # And superimpose end displacements using Moment-Area
157
174
  h = L / self.npts
158
- EI = beam.mbr_EIs[i_span]
159
175
 
160
- R = integrate.cumtrapz(res.M[1:-1], dx=h, initial=0) / EI + d[1]
176
+ R = integrate.cumtrapz(res.M[1:-1], dx=h, initial=0) / EI + R0
161
177
  D = integrate.cumtrapz(R, dx=h, initial=0) + d[0]
162
178
 
163
179
  res.R[1:-1] = R
@@ -0,0 +1,554 @@
1
+ """
2
+ Basic tests for PyCBA operation
3
+ """
4
+
5
+ import pytest
6
+ import numpy as np
7
+ import pycba as cba
8
+
9
+
10
+ def test_1span_ee():
11
+ """
12
+ Test fixed-fixed beam with point load in the middle
13
+ """
14
+
15
+ P = 10 # kN
16
+ L = 10 # m
17
+ EI = 30 * 600e7 * 1e-6 # kNm2
18
+ R = [-1, -1, -1, -1]
19
+ LM = [[1, 2, P, 0.5 * L, 0]]
20
+
21
+ beam_analysis = cba.BeamAnalysis([L], EI, R, LM)
22
+ out = beam_analysis.analyze()
23
+ assert out == 0
24
+
25
+ Ma = beam_analysis.beam_results.results.M[1]
26
+ Mb = beam_analysis.beam_results.results.M[-2]
27
+ Mc = beam_analysis.beam_results.results.M[51]
28
+
29
+ assert Ma == pytest.approx(-P * L / 8)
30
+ assert Mb == pytest.approx(-P * L / 8)
31
+ assert Mc == pytest.approx(P * L / 8)
32
+
33
+
34
+ def test_1span_ep():
35
+ """
36
+ Test fixed-pinned beam with point load in the middle
37
+ """
38
+
39
+ P = 10 # kN
40
+ L = 10 # m
41
+ EI = 30 * 600e7 * 1e-6 # kNm2
42
+ R = [-1, -1, -1, 0]
43
+ LM = [[1, 2, P, 0.5 * L, 0]]
44
+
45
+ beam_analysis = cba.BeamAnalysis([L], EI, R, LM)
46
+ out = beam_analysis.analyze()
47
+ assert out == 0
48
+
49
+ Ma = beam_analysis.beam_results.results.M[1]
50
+ Mb = beam_analysis.beam_results.results.M[-2]
51
+ Mc = beam_analysis.beam_results.results.M[51]
52
+
53
+ assert Ma == pytest.approx(-3 * P * L / 16)
54
+ assert Mb == pytest.approx(0)
55
+ assert Mc == pytest.approx(5 * P * L / 32)
56
+
57
+
58
+ def test_1span_ep_eletype2():
59
+ """
60
+ Test fixed-pinned beam with point load in the middle, using eleType 2
61
+ """
62
+
63
+ P = 10 # kN
64
+ L = 10 # m
65
+ EI = 30 * 600e7 * 1e-6 # kNm2
66
+ R = [-1, -1, -1, -1] # Notice, fixed-fixed supports
67
+ LM = [[1, 2, P, 0.5 * L, 0]]
68
+
69
+ beam_analysis = cba.BeamAnalysis([L], EI, R, LM, eletype=[2])
70
+ out = beam_analysis.analyze()
71
+ assert out == 0
72
+
73
+ Ma = beam_analysis.beam_results.results.M[1]
74
+ Mb = beam_analysis.beam_results.results.M[-2]
75
+ Mc = beam_analysis.beam_results.results.M[51]
76
+
77
+ assert Ma == pytest.approx(-3 * P * L / 16)
78
+ assert Mb == pytest.approx(0)
79
+ assert Mc == pytest.approx(5 * P * L / 32)
80
+
81
+
82
+ def test_1span_pe():
83
+ """
84
+ Test pinned-fixed beam with point load in the middle
85
+ """
86
+
87
+ P = 10 # kN
88
+ L = 10 # m
89
+ EI = 30 * 600e7 * 1e-6 # kNm2
90
+ R = [-1, 0, -1, -1]
91
+ LM = [[1, 2, P, 0.5 * L, 0]]
92
+
93
+ beam_analysis = cba.BeamAnalysis([L], EI, R, LM)
94
+ out = beam_analysis.analyze()
95
+ assert out == 0
96
+
97
+ Ma = beam_analysis.beam_results.results.M[1]
98
+ Mb = beam_analysis.beam_results.results.M[-2]
99
+ Mc = beam_analysis.beam_results.results.M[51]
100
+
101
+ assert Ma == pytest.approx(0)
102
+ assert Mb == pytest.approx(-3 * P * L / 16)
103
+ assert Mc == pytest.approx(5 * P * L / 32)
104
+
105
+
106
+ def test_1span_pe_eletype3():
107
+ """
108
+ Test pinned-fixed beam with point load in the middle, using eleType 3
109
+ """
110
+
111
+ P = 10 # kN
112
+ L = 10 # m
113
+ EI = 30 * 600e7 * 1e-6 # kNm2
114
+ R = [-1, -1, -1, -1] # Notice, fixed-fixed supports
115
+ LM = [[1, 2, P, 0.5 * L, 0]]
116
+
117
+ beam_analysis = cba.BeamAnalysis([L], EI, R, LM, eletype=[3])
118
+ out = beam_analysis.analyze()
119
+ assert out == 0
120
+
121
+ Ma = beam_analysis.beam_results.results.M[1]
122
+ Mb = beam_analysis.beam_results.results.M[-2]
123
+ Mc = beam_analysis.beam_results.results.M[51]
124
+
125
+ assert Ma == pytest.approx(0)
126
+ assert Mb == pytest.approx(-3 * P * L / 16)
127
+ assert Mc == pytest.approx(5 * P * L / 32)
128
+
129
+
130
+ def test_1span_pp():
131
+ """
132
+ Test pinned-pinned beam with point load in the middle
133
+ """
134
+
135
+ P = 10 # kN
136
+ L = 10 # m
137
+ EI = 30 * 600e7 * 1e-6 # kNm2
138
+ R = [-1, 0, -1, 0]
139
+ LM = [[1, 2, P, 0.5 * L, 0]]
140
+
141
+ beam_analysis = cba.BeamAnalysis([L], EI, R, LM)
142
+ out = beam_analysis.analyze()
143
+ assert out == 0
144
+
145
+ Ma = beam_analysis.beam_results.results.M[1]
146
+ Mb = beam_analysis.beam_results.results.M[-2]
147
+ Mc = beam_analysis.beam_results.results.M[51]
148
+
149
+ assert Ma == pytest.approx(0)
150
+ assert Mb == pytest.approx(0)
151
+ assert Mc == pytest.approx(P * L / 4)
152
+
153
+
154
+ def test_1span_pp_eletype4():
155
+ """
156
+ Test pinned-pinned beam with point load in the middle, using eleType 4
157
+ """
158
+
159
+ P = 10 # kN
160
+ L = 10 # m
161
+ EI = 30 * 600e7 * 1e-6 # kNm2
162
+ R = [-1, -1, -1, -1] # Notice, fixed-fixed supports
163
+ LM = [[1, 2, P, 0.5 * L, 0]]
164
+
165
+ beam_analysis = cba.BeamAnalysis([L], EI, R, LM, eletype=[4])
166
+ out = beam_analysis.analyze()
167
+ assert out == 0
168
+
169
+ Ma = beam_analysis.beam_results.results.M[1]
170
+ Mb = beam_analysis.beam_results.results.M[-2]
171
+ Mc = beam_analysis.beam_results.results.M[51]
172
+
173
+ assert Ma == pytest.approx(0)
174
+ assert Mb == pytest.approx(0)
175
+ assert Mc == pytest.approx(P * L / 4)
176
+
177
+
178
+ def get_1span_beam_def(etype):
179
+ P = 10 # kN
180
+ L = 10 # m
181
+ a = 0.25 * L
182
+ EI = 30 * 600e7 * 1e-6 # kNm2
183
+ R = [-1, -1, -1, -1] # Notice, fixed-fixed supports
184
+ LM = [[1, 2, P, a, 0]]
185
+
186
+ beam_analysis = cba.BeamAnalysis([L], EI, R, LM, eletype=[etype])
187
+ beam_analysis.analyze()
188
+
189
+ d = beam_analysis.beam_results.results.D
190
+ dmax = min(d)
191
+
192
+ return P, L, EI, a, dmax
193
+
194
+
195
+ def test_1span_def_ff():
196
+ """
197
+ Test fixed-fixed beam deflection for off-centre point load
198
+ """
199
+
200
+ P, L, EI, aa, dmax = get_1span_beam_def(etype=1)
201
+
202
+ # a>b
203
+ b = aa
204
+ a = L - b
205
+ ymax = -(2 * P * a**3 * b**2) / (3 * (3 * a + b) ** 2 * EI)
206
+
207
+ assert dmax == pytest.approx(ymax, abs=1e-6)
208
+
209
+
210
+ def test_1span_def_fp():
211
+ """
212
+ Test fixed-pinned beam deflection for off-centre point load
213
+ """
214
+ P, L, EI, aa, dmax = get_1span_beam_def(etype=2)
215
+
216
+ a = aa
217
+ b = L - a
218
+ ymax = -(P * a**2 * b) / (6 * EI) * (b / (3 * L - a)) ** 0.5
219
+
220
+ assert dmax == pytest.approx(ymax, abs=1e-6)
221
+
222
+
223
+ def test_1span_def_pf():
224
+ """
225
+ Test pinned-fixed beam deflection for off-centre point load
226
+ """
227
+ P, L, EI, aa, dmax = get_1span_beam_def(etype=3)
228
+
229
+ b = aa
230
+ ymax = -(P * b) / (3 * EI) * (L**2 - b**2) ** 3 / (3 * L**2 - b**2) ** 2
231
+
232
+ assert dmax == pytest.approx(ymax, abs=1e-6)
233
+
234
+
235
+ def test_1span_def_pp():
236
+ """
237
+ Test pinned-pinned beam deflection for off-centre point load
238
+ """
239
+ P, L, EI, aa, dmax = get_1span_beam_def(etype=4)
240
+
241
+ a = aa
242
+ ymax = -(3**0.5) * P * a * (L**2 - a**2) ** 1.5 / (27 * EI * L)
243
+
244
+ assert dmax == pytest.approx(ymax, abs=1e-6)
245
+
246
+
247
+ def test_2span_udl():
248
+ """
249
+ Execute a two-span beam analysis and check the reaction results.
250
+ Uses a direct definition of the LM
251
+ """
252
+
253
+ L = [7.5, 7.0]
254
+ EI = 30 * 600e7 * 1e-6 # kNm2
255
+ R = [-1, 0, -1, 0, -1, 0]
256
+ LM = [[1, 1, 20, 0, 0], [2, 1, 20, 0, 0]]
257
+
258
+ beam_analysis = cba.BeamAnalysis(L, EI, R, LM)
259
+ out = beam_analysis.analyze()
260
+ assert out == 0
261
+
262
+ r = beam_analysis.beam_results.R
263
+ assert r == pytest.approx([57.41666667, 181.42261905, 51.16071429])
264
+
265
+ dmax = max(beam_analysis.beam_results.results.D)
266
+ dmin = min(beam_analysis.beam_results.results.D)
267
+ assert [dmax, dmin] == pytest.approx(
268
+ [1.0118938958333364e-05, -0.0020629648925781247], abs=1e-6
269
+ )
270
+
271
+
272
+ def test_2span_load_wrappers():
273
+ """
274
+ Execute a two-span beam analysis and check the reaction results.
275
+ Uses the wrappers for defining loads.
276
+ """
277
+
278
+ L = [7.5, 7.0]
279
+ EI = 30 * 600e7 * 1e-6 # kNm2
280
+ R = [-1, 0, -1, 0, -1, 0]
281
+
282
+ beam_analysis = cba.BeamAnalysis(L, EI, R)
283
+ beam_analysis.add_pl(1, 40, 3.5)
284
+ beam_analysis.add_udl(1, 10)
285
+ beam_analysis.add_pudl(2, 20, 2.0, 3.0)
286
+ beam_analysis.add_ml(2, 50, 3)
287
+
288
+ out = beam_analysis.analyze()
289
+ assert out == 0
290
+
291
+ r = beam_analysis.beam_results.R
292
+ assert r == pytest.approx([45.41648878, 121.10155896, 8.48195226])
293
+
294
+ dmax = max(beam_analysis.beam_results.results.D)
295
+ dmin = min(beam_analysis.beam_results.results.D)
296
+ assert [dmax, dmin] == pytest.approx(
297
+ [0.00011753212898873195, -0.0023044064201367506]
298
+ )
299
+
300
+
301
+ def test_2span_pl_ml_fixed():
302
+ """
303
+ Execute a two-span beam analysis and check the reaction results
304
+ """
305
+
306
+ L = [5.0, 5.0]
307
+ EI = 30 * 600e7 * 1e-6 # kNm2
308
+ R = [-1, 0, -1, 0, -1, -1]
309
+ LM = [[1, 2, 50, 3, 0], [2, 4, 50, 2, 0]]
310
+
311
+ beam_analysis = cba.BeamAnalysis(L, EI, R, LM)
312
+ out = beam_analysis.analyze()
313
+ assert out == 0
314
+
315
+ r = beam_analysis.beam_results.R
316
+ assert r == pytest.approx([14.0, 57.6, -21.6, 28.0])
317
+
318
+ dmax = max(beam_analysis.beam_results.results.D)
319
+ dmin = min(beam_analysis.beam_results.results.D)
320
+ assert [dmax, dmin] == pytest.approx(
321
+ [0.00017414416666666662, -0.00042251493055555565], abs=1e-6
322
+ )
323
+
324
+
325
+ def test_3span_diff_settlement():
326
+ L = [15, 15, 15]
327
+ EI = 30 * np.array([500e8, 500e8, 500e8]) * 1e-6 # kNm2
328
+ R = [-1, 0, 1e8, 0, 1e8, 0, -1, 0]
329
+ LM = [[1, 1, 20, 0, 0], [2, 1, 20, 0, 0], [3, 1, 20, 0, 0]]
330
+
331
+ beam_analysis = cba.BeamAnalysis(L, EI, R, LM)
332
+ out = beam_analysis.analyze()
333
+ assert out == 0
334
+
335
+ r = beam_analysis.beam_results.R
336
+ assert r == pytest.approx([120.00175999, 120.00175999])
337
+
338
+ dmax = max(beam_analysis.beam_results.results.D)
339
+ dmin = min(beam_analysis.beam_results.results.D)
340
+ assert [dmax, dmin] == pytest.approx(
341
+ [0.0002778734578837245, -0.004648274177216889], abs=1e-5
342
+ )
343
+
344
+
345
+ def test_3span_subframe():
346
+ L = [6, 8, 6]
347
+ EI = 30 * np.array([50e8, 50e8, 50e8]) * 1e-6
348
+ R = [-1, 486e9, -1, 486e9, -1, 486e9, -1, 486e9]
349
+ LM = [[1, 1, 10, 0, 0], [2, 1, 20, 0, 0], [3, 1, 10, 0, 0]]
350
+
351
+ beam_analysis = cba.BeamAnalysis(L, EI, R, LM)
352
+ out = beam_analysis.analyze()
353
+ assert out == 0
354
+
355
+ r = beam_analysis.beam_results.R
356
+ assert r == pytest.approx([29.99999451, 110.00000549, 110.00000549, 29.99999451])
357
+
358
+ dmax = max(beam_analysis.beam_results.results.D)
359
+ dmin = min(beam_analysis.beam_results.results.D)
360
+ assert [dmax, dmin] == pytest.approx([0.0, -0.0014222225377228067], abs=1e-6)
361
+
362
+
363
+ def test_4span_posttensioned():
364
+ L = [6, 8, 6, 8]
365
+ EI = 30 * np.array([100e8, 100e8, 100e8, 100e8]) * 1e-6 # kNm2
366
+ R = [-1, 0, -1, 0, -1, 0, -1, 0, -1, 0]
367
+ LM = [
368
+ [1, 3, 20, 0, 1],
369
+ [1, 3, -10, 1, 4],
370
+ [1, 3, 20, 5, 1],
371
+ [1, 4, 50, 0, 0],
372
+ [2, 3, 20, 0, 1.5],
373
+ [2, 3, -10, 1.5, 5],
374
+ [2, 3, 20, 6.5, 1.5],
375
+ [3, 3, 20, 0, 1],
376
+ [3, 3, -10, 1, 4],
377
+ [3, 3, 20, 5, 1],
378
+ [4, 3, 20, 0, 1.5],
379
+ [4, 3, -10, 1.5, 5],
380
+ [4, 3, 20, 6.5, 1.5],
381
+ [4, 4, -75, 8, 0],
382
+ ]
383
+ beam_analysis = cba.BeamAnalysis(L, EI, R, LM)
384
+ out = beam_analysis.analyze()
385
+ assert out == 0
386
+
387
+ r = beam_analysis.beam_results.R
388
+ assert r == pytest.approx(
389
+ [14.87359893, -13.64621406, 15.69634808, -17.62411672, 20.70038377]
390
+ )
391
+
392
+ dmax = max(beam_analysis.beam_results.results.D)
393
+ dmin = min(beam_analysis.beam_results.results.D)
394
+ assert [dmax, dmin] == pytest.approx(
395
+ [0.0012715273282923978, -0.00013897273612280755], abs=1e-6
396
+ )
397
+
398
+
399
+ def test_2span_pinned():
400
+ w = 20
401
+ L = [10, 10]
402
+ EI = 30 * np.array([600e7, 600e7]) * 1e-6
403
+ eType = [2, 1]
404
+ R = [-1, 0, -1, 0, -1, 0]
405
+ LM = [[1, 1, w, 0, 0], [2, 1, w, 0, 0]]
406
+ beam_analysis = cba.BeamAnalysis(L, EI, R, LM, eType)
407
+ out = beam_analysis.analyze()
408
+ assert out == 0
409
+
410
+ r = beam_analysis.beam_results.R
411
+ assert r == pytest.approx([w * 5, w * 10, w * 5])
412
+
413
+ dmax = max(beam_analysis.beam_results.results.D)
414
+ dmin = min(beam_analysis.beam_results.results.D)
415
+ assert [dmax, dmin] == pytest.approx([0, -5 * w * L[0] ** 4 / (384 * EI[0])])
416
+
417
+
418
+ def test_3span_hinge():
419
+ L = [5, 5, 10]
420
+ EI = 30 * 600e7 * np.ones(len(L)) * 1e-6
421
+ eType = [2, 1, 1]
422
+ R = [-1, -1, 0, 0, -1, 0, -1, 0]
423
+ LM = [[3, 2, 20, 5, 0]]
424
+ beam_analysis = cba.BeamAnalysis(L, EI, R, LM, eType)
425
+ out = beam_analysis.analyze()
426
+ assert out == 0
427
+
428
+ r = beam_analysis.beam_results.R
429
+ assert r == pytest.approx([-3.75, -18.75, 15.625, 8.125])
430
+
431
+ dmax = max(beam_analysis.beam_results.results.D)
432
+ dmin = min(beam_analysis.beam_results.results.D)
433
+ assert [dmax, dmin] == pytest.approx(
434
+ [0.0008680555555555557, -0.0016677326388888887], abs=1e-6
435
+ )
436
+
437
+
438
+ def test_flipped_hinge():
439
+ # 3-span with etype 2
440
+ L = [5, 5, 10]
441
+ EI = 30 * 600e7 * np.ones(len(L)) * 1e-6
442
+ eType = [2, 1, 1]
443
+ R = [-1, -1, 0, 0, -1, 0, -1, -1]
444
+ LM = [[3, 2, 20, 5, 0]]
445
+ beam_analysis = cba.BeamAnalysis(L, EI, R, LM, eType)
446
+ out = beam_analysis.analyze()
447
+ d1 = beam_analysis.beam_results.results.D
448
+
449
+ # Same beam flipped, etype 3
450
+ L = [10, 5, 5]
451
+ EI = 30 * 600e7 * np.ones(len(L)) * 1e-6
452
+ eType = [1, 1, 3]
453
+ R = [-1, -1, -1, 0, 0, 0, -1, -1]
454
+ LM = [[1, 2, 20, 5, 0]]
455
+ beam_analysis = cba.BeamAnalysis(L, EI, R, LM, eType)
456
+ beam_analysis.analyze()
457
+ d2 = beam_analysis.beam_results.results.D
458
+
459
+ # Confirm flipped deflected shapes are close
460
+ assert d1 == pytest.approx(d2[::-1], abs=1e-7)
461
+
462
+
463
+ def test_hinges():
464
+ # Based on example in Logan's First Course in FE, Ex. 4.10
465
+ a = 4
466
+ b = 2
467
+ P = 20
468
+ L = [a, b]
469
+ EI = 30 * 600e7 * 1e-6
470
+ EIvec = EI * np.ones(len(L))
471
+ eType = [1, 3]
472
+ R = [-1, -1, 0, 0, -1, -1]
473
+ LM = [[1, 2, P, a, 0]]
474
+ beam_analysis = cba.BeamAnalysis(L, EIvec, R, LM, eType)
475
+ beam_analysis.analyze()
476
+
477
+ phi2_1 = beam_analysis.beam_results.vRes[0].R[-2]
478
+ phi2_1_theory = -(a**2 * b**3 * P) / (2 * (b**3 + a**3) * EI)
479
+
480
+ assert phi2_1_theory == pytest.approx(phi2_1)
481
+
482
+ phi2_2 = beam_analysis.beam_results.vRes[1].R[1]
483
+ phi2_2_theory = (a**3 * b**2 * P) / (2 * (b**3 + a**3) * EI)
484
+
485
+ assert phi2_2_theory == pytest.approx(phi2_2)
486
+
487
+
488
+ def test_3span_hinge_il():
489
+ L = [5, 5, 10]
490
+ EI = 30 * 600e7 * np.ones(len(L)) * 1e-6
491
+ eType = [2, 1, 1]
492
+ R = [-1, -1, 0, 0, -1, 0, -1, 0]
493
+
494
+ ils = cba.InfluenceLines(L, EI, R, eType)
495
+ ils.create_ils(step=0.05)
496
+ (x, y) = ils.get_il(15.0, "V")
497
+
498
+ assert [min(y), max(y)] == pytest.approx([-0.4009469062500001, 0.59375], abs=1e-6)
499
+
500
+
501
+ def test_moment_load():
502
+ L = [10.0]
503
+ EI = 30 * 600e7 * np.ones(len(L)) * 1e-6
504
+ eType = [1]
505
+ R = [-1, 0, -1, 0]
506
+
507
+ for a in [0, 5, 10]:
508
+ LM = [[1, 4, 10, a, 0]]
509
+ beam_analysis = cba.BeamAnalysis(L, EI, R, LM, eType)
510
+ out = beam_analysis.analyze()
511
+ assert out == 0
512
+
513
+ # Check deflection closes
514
+ d = beam_analysis.beam_results.D[[0, 2]]
515
+ assert d == pytest.approx([0.0, 0.0])
516
+
517
+
518
+ def test_envelopes():
519
+ L = [6, 4, 6]
520
+ EI = 30 * 10e9 * 1e-6
521
+ R = [-1, 0, -1, 0, -1, 0, -1, 0]
522
+ beam_analysis = cba.BeamAnalysis(L, EI, R)
523
+
524
+ LMg = [[1, 1, 25, 0, 0], [2, 1, 25, 0, 0], [3, 1, 25, 0, 0]]
525
+ γg_max = 1.4
526
+ γg_min = 1.0
527
+ LMq = [[1, 1, 10, 0, 0], [2, 1, 10, 0, 0], [3, 1, 10, 0, 0]]
528
+ γq_max = 1.6
529
+ γq_min = 0
530
+
531
+ lp = cba.LoadPattern(beam_analysis)
532
+ lp.set_dead_loads(LMg, γg_max, γg_min)
533
+ lp.set_live_loads(LMq, γq_max, γq_min)
534
+ env = lp.analyze()
535
+
536
+ m_locs = np.array([3, 6, 8, 10, 13])
537
+ idx = [(np.abs(env.x - x)).argmin() for x in m_locs]
538
+ assert np.allclose(
539
+ env.Mmax[idx], np.array([163.79, 0, 11.75, 0, 163.79]), atol=1e-2
540
+ )
541
+ assert np.allclose(
542
+ env.Mmin[idx], np.array([0, -163.38, -81.42, -163.38, 0]), atol=1e-2
543
+ )
544
+
545
+ n = beam_analysis.beam_results.npts
546
+ nspans = beam_analysis.beam.no_spans
547
+ Vmax = np.array(
548
+ [np.max(env.Vmax[i * (n + 3) : (i + 1) * (n + 3)]) for i in range(nspans)]
549
+ )
550
+ assert np.allclose(Vmax, np.array([131.1, 123.94, 180.23]), atol=1e-2)
551
+ Vmin = np.array(
552
+ [np.min(env.Vmin[i * (n + 3) : (i + 1) * (n + 3)]) for i in range(nspans)]
553
+ )
554
+ assert np.allclose(Vmin, np.array([-180.23, -123.94, -131.10]), atol=1e-2)
@@ -177,7 +177,7 @@ def test_parse_beam_notation():
177
177
  assert eType == [1, 2, 1, 1]
178
178
 
179
179
 
180
- def test_distcretization():
180
+ def test_discretization():
181
181
  """
182
182
  Confirm that poi rounding to find the closest idx for ILs works
183
183
  """
@@ -1,267 +0,0 @@
1
- """
2
- Basic tests for PyCBA operation
3
- """
4
-
5
- import pytest
6
- import numpy as np
7
- import pycba as cba
8
-
9
-
10
- def test_2span_udl():
11
- """
12
- Execute a two-span beam analysis and check the reaction results.
13
- Uses a direct definition of the LM
14
- """
15
-
16
- L = [7.5, 7.0]
17
- EI = 30 * 600e7 * 1e-6 # kNm2
18
- R = [-1, 0, -1, 0, -1, 0]
19
- LM = [[1, 1, 20, 0, 0], [2, 1, 20, 0, 0]]
20
-
21
- beam_analysis = cba.BeamAnalysis(L, EI, R, LM)
22
- out = beam_analysis.analyze()
23
- assert out == 0
24
-
25
- r = beam_analysis.beam_results.R
26
- assert r == pytest.approx([57.41666667, 181.42261905, 51.16071429])
27
-
28
- dmax = max(beam_analysis.beam_results.results.D)
29
- dmin = min(beam_analysis.beam_results.results.D)
30
- assert [dmax, dmin] == pytest.approx(
31
- [1.0118938958333364e-05, -0.0020629648925781247], abs=1e-6
32
- )
33
-
34
-
35
- def test_2span_load_wrappers():
36
- """
37
- Execute a two-span beam analysis and check the reaction results.
38
- Uses the wrappers for defining loads.
39
- """
40
-
41
- L = [7.5, 7.0]
42
- EI = 30 * 600e7 * 1e-6 # kNm2
43
- R = [-1, 0, -1, 0, -1, 0]
44
-
45
- beam_analysis = cba.BeamAnalysis(L, EI, R)
46
- beam_analysis.add_pl(1, 40, 3.5)
47
- beam_analysis.add_udl(1, 10)
48
- beam_analysis.add_pudl(2, 20, 2.0, 3.0)
49
- beam_analysis.add_ml(2, 50, 3)
50
-
51
- out = beam_analysis.analyze()
52
- assert out == 0
53
-
54
- r = beam_analysis.beam_results.R
55
- assert r == pytest.approx([45.41648878, 121.10155896, 8.48195226])
56
-
57
- dmax = max(beam_analysis.beam_results.results.D)
58
- dmin = min(beam_analysis.beam_results.results.D)
59
- assert [dmax, dmin] == pytest.approx(
60
- [0.00011753212898873195, -0.0023044064201367506]
61
- )
62
-
63
-
64
- def test_2span_pl_ml_fixed():
65
- """
66
- Execute a two-span beam analysis and check the reaction results
67
- """
68
-
69
- L = [5.0, 5.0]
70
- EI = 30 * 600e7 * 1e-6 # kNm2
71
- R = [-1, 0, -1, 0, -1, -1]
72
- LM = [[1, 2, 50, 3, 0], [2, 4, 50, 2, 0]]
73
-
74
- beam_analysis = cba.BeamAnalysis(L, EI, R, LM)
75
- out = beam_analysis.analyze()
76
- assert out == 0
77
-
78
- r = beam_analysis.beam_results.R
79
- assert r == pytest.approx([14.0, 57.6, -21.6, 28.0])
80
-
81
- dmax = max(beam_analysis.beam_results.results.D)
82
- dmin = min(beam_analysis.beam_results.results.D)
83
- assert [dmax, dmin] == pytest.approx(
84
- [0.00017414416666666662, -0.00042251493055555565], abs=1e-6
85
- )
86
-
87
-
88
- def test_3span_diff_settlement():
89
- L = [15, 15, 15]
90
- EI = 30 * np.array([500e8, 500e8, 500e8]) * 1e-6 # kNm2
91
- R = [-1, 0, 1e8, 0, 1e8, 0, -1, 0]
92
- LM = [[1, 1, 20, 0, 0], [2, 1, 20, 0, 0], [3, 1, 20, 0, 0]]
93
-
94
- beam_analysis = cba.BeamAnalysis(L, EI, R, LM)
95
- out = beam_analysis.analyze()
96
- assert out == 0
97
-
98
- r = beam_analysis.beam_results.R
99
- assert r == pytest.approx([120.00175999, 120.00175999])
100
-
101
- dmax = max(beam_analysis.beam_results.results.D)
102
- dmin = min(beam_analysis.beam_results.results.D)
103
- assert [dmax, dmin] == pytest.approx(
104
- [0.0002778734578837245, -0.004648274177216889], abs=1e-6
105
- )
106
-
107
-
108
- def test_3span_subframe():
109
- L = [6, 8, 6]
110
- EI = 30 * np.array([50e8, 50e8, 50e8]) * 1e-6
111
- R = [-1, 486e9, -1, 486e9, -1, 486e9, -1, 486e9]
112
- LM = [[1, 1, 10, 0, 0], [2, 1, 20, 0, 0], [3, 1, 10, 0, 0]]
113
-
114
- beam_analysis = cba.BeamAnalysis(L, EI, R, LM)
115
- out = beam_analysis.analyze()
116
- assert out == 0
117
-
118
- r = beam_analysis.beam_results.R
119
- assert r == pytest.approx([29.99999451, 110.00000549, 110.00000549, 29.99999451])
120
-
121
- dmax = max(beam_analysis.beam_results.results.D)
122
- dmin = min(beam_analysis.beam_results.results.D)
123
- assert [dmax, dmin] == pytest.approx([0.0, -0.0014222225377228067], abs=1e-6)
124
-
125
-
126
- def test_4span_posttensioned():
127
- L = [6, 8, 6, 8]
128
- EI = 30 * np.array([100e8, 100e8, 100e8, 100e8]) * 1e-6 # kNm2
129
- R = [-1, 0, -1, 0, -1, 0, -1, 0, -1, 0]
130
- LM = [
131
- [1, 3, 20, 0, 1],
132
- [1, 3, -10, 1, 4],
133
- [1, 3, 20, 5, 1],
134
- [1, 4, 50, 0, 0],
135
- [2, 3, 20, 0, 1.5],
136
- [2, 3, -10, 1.5, 5],
137
- [2, 3, 20, 6.5, 1.5],
138
- [3, 3, 20, 0, 1],
139
- [3, 3, -10, 1, 4],
140
- [3, 3, 20, 5, 1],
141
- [4, 3, 20, 0, 1.5],
142
- [4, 3, -10, 1.5, 5],
143
- [4, 3, 20, 6.5, 1.5],
144
- [4, 4, -75, 8, 0],
145
- ]
146
- beam_analysis = cba.BeamAnalysis(L, EI, R, LM)
147
- out = beam_analysis.analyze()
148
- assert out == 0
149
-
150
- r = beam_analysis.beam_results.R
151
- assert r == pytest.approx(
152
- [14.87359893, -13.64621406, 15.69634808, -17.62411672, 20.70038377]
153
- )
154
-
155
- dmax = max(beam_analysis.beam_results.results.D)
156
- dmin = min(beam_analysis.beam_results.results.D)
157
- assert [dmax, dmin] == pytest.approx(
158
- [0.0012715273282923978, -0.00013897273612280755], abs=1e-6
159
- )
160
-
161
-
162
- def test_2span_pinned():
163
- w = 20
164
- L = [10, 10]
165
- EI = 30 * np.array([600e7, 600e7]) * 1e-6
166
- eType = [2, 1]
167
- R = [-1, 0, -1, 0, -1, 0]
168
- LM = [[1, 1, w, 0, 0], [2, 1, w, 0, 0]]
169
- beam_analysis = cba.BeamAnalysis(L, EI, R, LM, eType)
170
- out = beam_analysis.analyze()
171
- assert out == 0
172
-
173
- r = beam_analysis.beam_results.R
174
- assert r == pytest.approx([w * 5, w * 10, w * 5])
175
-
176
- dmax = max(beam_analysis.beam_results.results.D)
177
- dmin = min(beam_analysis.beam_results.results.D)
178
- assert [dmax, dmin] == pytest.approx([0, -5 * w * L[0] ** 4 / (384 * EI[0])])
179
-
180
-
181
- def test_3span_hinge():
182
- L = [5, 5, 10]
183
- EI = 30 * 600e7 * np.ones(len(L)) * 1e-6
184
- eType = [2, 1, 1]
185
- R = [-1, -1, 0, 0, -1, 0, -1, 0]
186
- LM = [[3, 2, 20, 5, 0]]
187
- beam_analysis = cba.BeamAnalysis(L, EI, R, LM, eType)
188
- out = beam_analysis.analyze()
189
- assert out == 0
190
-
191
- r = beam_analysis.beam_results.R
192
- assert r == pytest.approx([-3.75, -18.75, 15.625, 8.125])
193
-
194
- dmax = max(beam_analysis.beam_results.results.D)
195
- dmin = min(beam_analysis.beam_results.results.D)
196
- assert [dmax, dmin] == pytest.approx(
197
- [0.0008680555555555557, -0.0016677326388888887], abs=1e-6
198
- )
199
-
200
-
201
- def test_3span_hinge_il():
202
- L = [5, 5, 10]
203
- EI = 30 * 600e7 * np.ones(len(L)) * 1e-6
204
- eType = [2, 1, 1]
205
- R = [-1, -1, 0, 0, -1, 0, -1, 0]
206
-
207
- ils = cba.InfluenceLines(L, EI, R, eType)
208
- ils.create_ils(step=0.05)
209
- (x, y) = ils.get_il(15.0, "V")
210
-
211
- assert [min(y), max(y)] == pytest.approx([-0.4009469062500001, 0.59375], abs=1e-6)
212
-
213
-
214
- def test_moment_load():
215
- L = [10.0]
216
- EI = 30 * 600e7 * np.ones(len(L)) * 1e-6
217
- eType = [1]
218
- R = [-1, 0, -1, 0]
219
-
220
- for a in [0, 5, 10]:
221
- LM = [[1, 4, 10, a, 0]]
222
- beam_analysis = cba.BeamAnalysis(L, EI, R, LM, eType)
223
- out = beam_analysis.analyze()
224
- assert out == 0
225
-
226
- # Check deflection closes
227
- d = beam_analysis.beam_results.D[[0, 2]]
228
- assert d == pytest.approx([0.0, 0.0])
229
-
230
-
231
- def test_envelopes():
232
- L = [6, 4, 6]
233
- EI = 30 * 10e9 * 1e-6
234
- R = [-1, 0, -1, 0, -1, 0, -1, 0]
235
- beam_analysis = cba.BeamAnalysis(L, EI, R)
236
-
237
- LMg = [[1, 1, 25, 0, 0], [2, 1, 25, 0, 0], [3, 1, 25, 0, 0]]
238
- γg_max = 1.4
239
- γg_min = 1.0
240
- LMq = [[1, 1, 10, 0, 0], [2, 1, 10, 0, 0], [3, 1, 10, 0, 0]]
241
- γq_max = 1.6
242
- γq_min = 0
243
-
244
- lp = cba.LoadPattern(beam_analysis)
245
- lp.set_dead_loads(LMg, γg_max, γg_min)
246
- lp.set_live_loads(LMq, γq_max, γq_min)
247
- env = lp.analyze()
248
-
249
- m_locs = np.array([3, 6, 8, 10, 13])
250
- idx = [(np.abs(env.x - x)).argmin() for x in m_locs]
251
- assert np.allclose(
252
- env.Mmax[idx], np.array([163.79, 0, 11.75, 0, 163.79]), atol=1e-2
253
- )
254
- assert np.allclose(
255
- env.Mmin[idx], np.array([0, -163.38, -81.42, -163.38, 0]), atol=1e-2
256
- )
257
-
258
- n = beam_analysis.beam_results.npts
259
- nspans = beam_analysis.beam.no_spans
260
- Vmax = np.array(
261
- [np.max(env.Vmax[i * (n + 3) : (i + 1) * (n + 3)]) for i in range(nspans)]
262
- )
263
- assert np.allclose(Vmax, np.array([131.1, 123.94, 180.23]), atol=1e-2)
264
- Vmin = np.array(
265
- [np.min(env.Vmin[i * (n + 3) : (i + 1) * (n + 3)]) for i in range(nspans)]
266
- )
267
- assert np.allclose(Vmin, np.array([-180.23, -123.94, -131.10]), atol=1e-2)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes