test_beam.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. from sympy.core.function import expand
  2. from sympy.core.numbers import (Rational, pi)
  3. from sympy.core.singleton import S
  4. from sympy.core.symbol import (Symbol, symbols)
  5. from sympy.sets.sets import Interval
  6. from sympy.simplify.simplify import simplify
  7. from sympy.physics.continuum_mechanics.beam import Beam
  8. from sympy.functions import SingularityFunction, Piecewise, meijerg, Abs, log
  9. from sympy.testing.pytest import raises
  10. from sympy.physics.units import meter, newton, kilo, giga, milli
  11. from sympy.physics.continuum_mechanics.beam import Beam3D
  12. from sympy.geometry import Circle, Polygon, Point2D, Triangle
  13. from sympy.core.sympify import sympify
  14. x = Symbol('x')
  15. y = Symbol('y')
  16. R1, R2 = symbols('R1, R2')
  17. def test_Beam():
  18. E = Symbol('E')
  19. E_1 = Symbol('E_1')
  20. I = Symbol('I')
  21. I_1 = Symbol('I_1')
  22. A = Symbol('A')
  23. b = Beam(1, E, I)
  24. assert b.length == 1
  25. assert b.elastic_modulus == E
  26. assert b.second_moment == I
  27. assert b.variable == x
  28. # Test the length setter
  29. b.length = 4
  30. assert b.length == 4
  31. # Test the E setter
  32. b.elastic_modulus = E_1
  33. assert b.elastic_modulus == E_1
  34. # Test the I setter
  35. b.second_moment = I_1
  36. assert b.second_moment is I_1
  37. # Test the variable setter
  38. b.variable = y
  39. assert b.variable is y
  40. # Test for all boundary conditions.
  41. b.bc_deflection = [(0, 2)]
  42. b.bc_slope = [(0, 1)]
  43. assert b.boundary_conditions == {'deflection': [(0, 2)], 'slope': [(0, 1)]}
  44. # Test for slope boundary condition method
  45. b.bc_slope.extend([(4, 3), (5, 0)])
  46. s_bcs = b.bc_slope
  47. assert s_bcs == [(0, 1), (4, 3), (5, 0)]
  48. # Test for deflection boundary condition method
  49. b.bc_deflection.extend([(4, 3), (5, 0)])
  50. d_bcs = b.bc_deflection
  51. assert d_bcs == [(0, 2), (4, 3), (5, 0)]
  52. # Test for updated boundary conditions
  53. bcs_new = b.boundary_conditions
  54. assert bcs_new == {
  55. 'deflection': [(0, 2), (4, 3), (5, 0)],
  56. 'slope': [(0, 1), (4, 3), (5, 0)]}
  57. b1 = Beam(30, E, I)
  58. b1.apply_load(-8, 0, -1)
  59. b1.apply_load(R1, 10, -1)
  60. b1.apply_load(R2, 30, -1)
  61. b1.apply_load(120, 30, -2)
  62. b1.bc_deflection = [(10, 0), (30, 0)]
  63. b1.solve_for_reaction_loads(R1, R2)
  64. # Test for finding reaction forces
  65. p = b1.reaction_loads
  66. q = {R1: 6, R2: 2}
  67. assert p == q
  68. # Test for load distribution function.
  69. p = b1.load
  70. q = -8*SingularityFunction(x, 0, -1) + 6*SingularityFunction(x, 10, -1) \
  71. + 120*SingularityFunction(x, 30, -2) + 2*SingularityFunction(x, 30, -1)
  72. assert p == q
  73. # Test for shear force distribution function
  74. p = b1.shear_force()
  75. q = 8*SingularityFunction(x, 0, 0) - 6*SingularityFunction(x, 10, 0) \
  76. - 120*SingularityFunction(x, 30, -1) - 2*SingularityFunction(x, 30, 0)
  77. assert p == q
  78. # Test for shear stress distribution function
  79. p = b1.shear_stress()
  80. q = (8*SingularityFunction(x, 0, 0) - 6*SingularityFunction(x, 10, 0) \
  81. - 120*SingularityFunction(x, 30, -1) \
  82. - 2*SingularityFunction(x, 30, 0))/A
  83. assert p==q
  84. # Test for bending moment distribution function
  85. p = b1.bending_moment()
  86. q = 8*SingularityFunction(x, 0, 1) - 6*SingularityFunction(x, 10, 1) \
  87. - 120*SingularityFunction(x, 30, 0) - 2*SingularityFunction(x, 30, 1)
  88. assert p == q
  89. # Test for slope distribution function
  90. p = b1.slope()
  91. q = -4*SingularityFunction(x, 0, 2) + 3*SingularityFunction(x, 10, 2) \
  92. + 120*SingularityFunction(x, 30, 1) + SingularityFunction(x, 30, 2) \
  93. + Rational(4000, 3)
  94. assert p == q/(E*I)
  95. # Test for deflection distribution function
  96. p = b1.deflection()
  97. q = x*Rational(4000, 3) - 4*SingularityFunction(x, 0, 3)/3 \
  98. + SingularityFunction(x, 10, 3) + 60*SingularityFunction(x, 30, 2) \
  99. + SingularityFunction(x, 30, 3)/3 - 12000
  100. assert p == q/(E*I)
  101. # Test using symbols
  102. l = Symbol('l')
  103. w0 = Symbol('w0')
  104. w2 = Symbol('w2')
  105. a1 = Symbol('a1')
  106. c = Symbol('c')
  107. c1 = Symbol('c1')
  108. d = Symbol('d')
  109. e = Symbol('e')
  110. f = Symbol('f')
  111. b2 = Beam(l, E, I)
  112. b2.apply_load(w0, a1, 1)
  113. b2.apply_load(w2, c1, -1)
  114. b2.bc_deflection = [(c, d)]
  115. b2.bc_slope = [(e, f)]
  116. # Test for load distribution function.
  117. p = b2.load
  118. q = w0*SingularityFunction(x, a1, 1) + w2*SingularityFunction(x, c1, -1)
  119. assert p == q
  120. # Test for shear force distribution function
  121. p = b2.shear_force()
  122. q = -w0*SingularityFunction(x, a1, 2)/2 \
  123. - w2*SingularityFunction(x, c1, 0)
  124. assert p == q
  125. # Test for shear stress distribution function
  126. p = b2.shear_stress()
  127. q = (-w0*SingularityFunction(x, a1, 2)/2 \
  128. - w2*SingularityFunction(x, c1, 0))/A
  129. assert p == q
  130. # Test for bending moment distribution function
  131. p = b2.bending_moment()
  132. q = -w0*SingularityFunction(x, a1, 3)/6 - w2*SingularityFunction(x, c1, 1)
  133. assert p == q
  134. # Test for slope distribution function
  135. p = b2.slope()
  136. q = (w0*SingularityFunction(x, a1, 4)/24 + w2*SingularityFunction(x, c1, 2)/2)/(E*I) + (E*I*f - w0*SingularityFunction(e, a1, 4)/24 - w2*SingularityFunction(e, c1, 2)/2)/(E*I)
  137. assert expand(p) == expand(q)
  138. # Test for deflection distribution function
  139. p = b2.deflection()
  140. q = x*(E*I*f - w0*SingularityFunction(e, a1, 4)/24 \
  141. - w2*SingularityFunction(e, c1, 2)/2)/(E*I) \
  142. + (w0*SingularityFunction(x, a1, 5)/120 \
  143. + w2*SingularityFunction(x, c1, 3)/6)/(E*I) \
  144. + (E*I*(-c*f + d) + c*w0*SingularityFunction(e, a1, 4)/24 \
  145. + c*w2*SingularityFunction(e, c1, 2)/2 \
  146. - w0*SingularityFunction(c, a1, 5)/120 \
  147. - w2*SingularityFunction(c, c1, 3)/6)/(E*I)
  148. assert simplify(p - q) == 0
  149. b3 = Beam(9, E, I, 2)
  150. b3.apply_load(value=-2, start=2, order=2, end=3)
  151. b3.bc_slope.append((0, 2))
  152. C3 = symbols('C3')
  153. C4 = symbols('C4')
  154. p = b3.load
  155. q = -2*SingularityFunction(x, 2, 2) + 2*SingularityFunction(x, 3, 0) \
  156. + 4*SingularityFunction(x, 3, 1) + 2*SingularityFunction(x, 3, 2)
  157. assert p == q
  158. p = b3.shear_force()
  159. q = 2*SingularityFunction(x, 2, 3)/3 - 2*SingularityFunction(x, 3, 1) \
  160. - 2*SingularityFunction(x, 3, 2) - 2*SingularityFunction(x, 3, 3)/3
  161. assert p == q
  162. p = b3.shear_stress()
  163. q = SingularityFunction(x, 2, 3)/3 - 1*SingularityFunction(x, 3, 1) \
  164. - 1*SingularityFunction(x, 3, 2) - 1*SingularityFunction(x, 3, 3)/3
  165. assert p == q
  166. p = b3.slope()
  167. q = 2 - (SingularityFunction(x, 2, 5)/30 - SingularityFunction(x, 3, 3)/3 \
  168. - SingularityFunction(x, 3, 4)/6 - SingularityFunction(x, 3, 5)/30)/(E*I)
  169. assert p == q
  170. p = b3.deflection()
  171. q = 2*x - (SingularityFunction(x, 2, 6)/180 \
  172. - SingularityFunction(x, 3, 4)/12 - SingularityFunction(x, 3, 5)/30 \
  173. - SingularityFunction(x, 3, 6)/180)/(E*I)
  174. assert p == q + C4
  175. b4 = Beam(4, E, I, 3)
  176. b4.apply_load(-3, 0, 0, end=3)
  177. p = b4.load
  178. q = -3*SingularityFunction(x, 0, 0) + 3*SingularityFunction(x, 3, 0)
  179. assert p == q
  180. p = b4.shear_force()
  181. q = 3*SingularityFunction(x, 0, 1) \
  182. - 3*SingularityFunction(x, 3, 1)
  183. assert p == q
  184. p = b4.shear_stress()
  185. q = SingularityFunction(x, 0, 1) - SingularityFunction(x, 3, 1)
  186. assert p == q
  187. p = b4.slope()
  188. q = -3*SingularityFunction(x, 0, 3)/6 + 3*SingularityFunction(x, 3, 3)/6
  189. assert p == q/(E*I) + C3
  190. p = b4.deflection()
  191. q = -3*SingularityFunction(x, 0, 4)/24 + 3*SingularityFunction(x, 3, 4)/24
  192. assert p == q/(E*I) + C3*x + C4
  193. # can't use end with point loads
  194. raises(ValueError, lambda: b4.apply_load(-3, 0, -1, end=3))
  195. with raises(TypeError):
  196. b4.variable = 1
  197. def test_insufficient_bconditions():
  198. # Test cases when required number of boundary conditions
  199. # are not provided to solve the integration constants.
  200. L = symbols('L', positive=True)
  201. E, I, P, a3, a4 = symbols('E I P a3 a4')
  202. b = Beam(L, E, I, base_char='a')
  203. b.apply_load(R2, L, -1)
  204. b.apply_load(R1, 0, -1)
  205. b.apply_load(-P, L/2, -1)
  206. b.solve_for_reaction_loads(R1, R2)
  207. p = b.slope()
  208. q = P*SingularityFunction(x, 0, 2)/4 - P*SingularityFunction(x, L/2, 2)/2 + P*SingularityFunction(x, L, 2)/4
  209. assert p == q/(E*I) + a3
  210. p = b.deflection()
  211. q = P*SingularityFunction(x, 0, 3)/12 - P*SingularityFunction(x, L/2, 3)/6 + P*SingularityFunction(x, L, 3)/12
  212. assert p == q/(E*I) + a3*x + a4
  213. b.bc_deflection = [(0, 0)]
  214. p = b.deflection()
  215. q = a3*x + P*SingularityFunction(x, 0, 3)/12 - P*SingularityFunction(x, L/2, 3)/6 + P*SingularityFunction(x, L, 3)/12
  216. assert p == q/(E*I)
  217. b.bc_deflection = [(0, 0), (L, 0)]
  218. p = b.deflection()
  219. q = -L**2*P*x/16 + P*SingularityFunction(x, 0, 3)/12 - P*SingularityFunction(x, L/2, 3)/6 + P*SingularityFunction(x, L, 3)/12
  220. assert p == q/(E*I)
  221. def test_statically_indeterminate():
  222. E = Symbol('E')
  223. I = Symbol('I')
  224. M1, M2 = symbols('M1, M2')
  225. F = Symbol('F')
  226. l = Symbol('l', positive=True)
  227. b5 = Beam(l, E, I)
  228. b5.bc_deflection = [(0, 0),(l, 0)]
  229. b5.bc_slope = [(0, 0),(l, 0)]
  230. b5.apply_load(R1, 0, -1)
  231. b5.apply_load(M1, 0, -2)
  232. b5.apply_load(R2, l, -1)
  233. b5.apply_load(M2, l, -2)
  234. b5.apply_load(-F, l/2, -1)
  235. b5.solve_for_reaction_loads(R1, R2, M1, M2)
  236. p = b5.reaction_loads
  237. q = {R1: F/2, R2: F/2, M1: -F*l/8, M2: F*l/8}
  238. assert p == q
  239. def test_beam_units():
  240. E = Symbol('E')
  241. I = Symbol('I')
  242. R1, R2 = symbols('R1, R2')
  243. kN = kilo*newton
  244. gN = giga*newton
  245. b = Beam(8*meter, 200*gN/meter**2, 400*1000000*(milli*meter)**4)
  246. b.apply_load(5*kN, 2*meter, -1)
  247. b.apply_load(R1, 0*meter, -1)
  248. b.apply_load(R2, 8*meter, -1)
  249. b.apply_load(10*kN/meter, 4*meter, 0, end=8*meter)
  250. b.bc_deflection = [(0*meter, 0*meter), (8*meter, 0*meter)]
  251. b.solve_for_reaction_loads(R1, R2)
  252. assert b.reaction_loads == {R1: -13750*newton, R2: -31250*newton}
  253. b = Beam(3*meter, E*newton/meter**2, I*meter**4)
  254. b.apply_load(8*kN, 1*meter, -1)
  255. b.apply_load(R1, 0*meter, -1)
  256. b.apply_load(R2, 3*meter, -1)
  257. b.apply_load(12*kN*meter, 2*meter, -2)
  258. b.bc_deflection = [(0*meter, 0*meter), (3*meter, 0*meter)]
  259. b.solve_for_reaction_loads(R1, R2)
  260. assert b.reaction_loads == {R1: newton*Rational(-28000, 3), R2: newton*Rational(4000, 3)}
  261. assert b.deflection().subs(x, 1*meter) == 62000*meter/(9*E*I)
  262. def test_variable_moment():
  263. E = Symbol('E')
  264. I = Symbol('I')
  265. b = Beam(4, E, 2*(4 - x))
  266. b.apply_load(20, 4, -1)
  267. R, M = symbols('R, M')
  268. b.apply_load(R, 0, -1)
  269. b.apply_load(M, 0, -2)
  270. b.bc_deflection = [(0, 0)]
  271. b.bc_slope = [(0, 0)]
  272. b.solve_for_reaction_loads(R, M)
  273. assert b.slope().expand() == ((10*x*SingularityFunction(x, 0, 0)
  274. - 10*(x - 4)*SingularityFunction(x, 4, 0))/E).expand()
  275. assert b.deflection().expand() == ((5*x**2*SingularityFunction(x, 0, 0)
  276. - 10*Piecewise((0, Abs(x)/4 < 1), (16*meijerg(((3, 1), ()), ((), (2, 0)), x/4), True))
  277. + 40*SingularityFunction(x, 4, 1))/E).expand()
  278. b = Beam(4, E - x, I)
  279. b.apply_load(20, 4, -1)
  280. R, M = symbols('R, M')
  281. b.apply_load(R, 0, -1)
  282. b.apply_load(M, 0, -2)
  283. b.bc_deflection = [(0, 0)]
  284. b.bc_slope = [(0, 0)]
  285. b.solve_for_reaction_loads(R, M)
  286. assert b.slope().expand() == ((-80*(-log(-E) + log(-E + x))*SingularityFunction(x, 0, 0)
  287. + 80*(-log(-E + 4) + log(-E + x))*SingularityFunction(x, 4, 0) + 20*(-E*log(-E)
  288. + E*log(-E + x) + x)*SingularityFunction(x, 0, 0) - 20*(-E*log(-E + 4) + E*log(-E + x)
  289. + x - 4)*SingularityFunction(x, 4, 0))/I).expand()
  290. def test_composite_beam():
  291. E = Symbol('E')
  292. I = Symbol('I')
  293. b1 = Beam(2, E, 1.5*I)
  294. b2 = Beam(2, E, I)
  295. b = b1.join(b2, "fixed")
  296. b.apply_load(-20, 0, -1)
  297. b.apply_load(80, 0, -2)
  298. b.apply_load(20, 4, -1)
  299. b.bc_slope = [(0, 0)]
  300. b.bc_deflection = [(0, 0)]
  301. assert b.length == 4
  302. assert b.second_moment == Piecewise((1.5*I, x <= 2), (I, x <= 4))
  303. assert b.slope().subs(x, 4) == 120.0/(E*I)
  304. assert b.slope().subs(x, 2) == 80.0/(E*I)
  305. assert int(b.deflection().subs(x, 4).args[0]) == -302 # Coefficient of 1/(E*I)
  306. l = symbols('l', positive=True)
  307. R1, M1, R2, R3, P = symbols('R1 M1 R2 R3 P')
  308. b1 = Beam(2*l, E, I)
  309. b2 = Beam(2*l, E, I)
  310. b = b1.join(b2,"hinge")
  311. b.apply_load(M1, 0, -2)
  312. b.apply_load(R1, 0, -1)
  313. b.apply_load(R2, l, -1)
  314. b.apply_load(R3, 4*l, -1)
  315. b.apply_load(P, 3*l, -1)
  316. b.bc_slope = [(0, 0)]
  317. b.bc_deflection = [(0, 0), (l, 0), (4*l, 0)]
  318. b.solve_for_reaction_loads(M1, R1, R2, R3)
  319. assert b.reaction_loads == {R3: -P/2, R2: P*Rational(-5, 4), M1: -P*l/4, R1: P*Rational(3, 4)}
  320. assert b.slope().subs(x, 3*l) == -7*P*l**2/(48*E*I)
  321. assert b.deflection().subs(x, 2*l) == 7*P*l**3/(24*E*I)
  322. assert b.deflection().subs(x, 3*l) == 5*P*l**3/(16*E*I)
  323. # When beams having same second moment are joined.
  324. b1 = Beam(2, 500, 10)
  325. b2 = Beam(2, 500, 10)
  326. b = b1.join(b2, "fixed")
  327. b.apply_load(M1, 0, -2)
  328. b.apply_load(R1, 0, -1)
  329. b.apply_load(R2, 1, -1)
  330. b.apply_load(R3, 4, -1)
  331. b.apply_load(10, 3, -1)
  332. b.bc_slope = [(0, 0)]
  333. b.bc_deflection = [(0, 0), (1, 0), (4, 0)]
  334. b.solve_for_reaction_loads(M1, R1, R2, R3)
  335. assert b.slope() == -2*SingularityFunction(x, 0, 1)/5625 + SingularityFunction(x, 0, 2)/1875\
  336. - 133*SingularityFunction(x, 1, 2)/135000 + SingularityFunction(x, 3, 2)/1000\
  337. - 37*SingularityFunction(x, 4, 2)/67500
  338. assert b.deflection() == -SingularityFunction(x, 0, 2)/5625 + SingularityFunction(x, 0, 3)/5625\
  339. - 133*SingularityFunction(x, 1, 3)/405000 + SingularityFunction(x, 3, 3)/3000\
  340. - 37*SingularityFunction(x, 4, 3)/202500
  341. def test_point_cflexure():
  342. E = Symbol('E')
  343. I = Symbol('I')
  344. b = Beam(10, E, I)
  345. b.apply_load(-4, 0, -1)
  346. b.apply_load(-46, 6, -1)
  347. b.apply_load(10, 2, -1)
  348. b.apply_load(20, 4, -1)
  349. b.apply_load(3, 6, 0)
  350. assert b.point_cflexure() == [Rational(10, 3)]
  351. def test_remove_load():
  352. E = Symbol('E')
  353. I = Symbol('I')
  354. b = Beam(4, E, I)
  355. try:
  356. b.remove_load(2, 1, -1)
  357. # As no load is applied on beam, ValueError should be returned.
  358. except ValueError:
  359. assert True
  360. else:
  361. assert False
  362. b.apply_load(-3, 0, -2)
  363. b.apply_load(4, 2, -1)
  364. b.apply_load(-2, 2, 2, end = 3)
  365. b.remove_load(-2, 2, 2, end = 3)
  366. assert b.load == -3*SingularityFunction(x, 0, -2) + 4*SingularityFunction(x, 2, -1)
  367. assert b.applied_loads == [(-3, 0, -2, None), (4, 2, -1, None)]
  368. try:
  369. b.remove_load(1, 2, -1)
  370. # As load of this magnitude was never applied at
  371. # this position, method should return a ValueError.
  372. except ValueError:
  373. assert True
  374. else:
  375. assert False
  376. b.remove_load(-3, 0, -2)
  377. b.remove_load(4, 2, -1)
  378. assert b.load == 0
  379. assert b.applied_loads == []
  380. def test_apply_support():
  381. E = Symbol('E')
  382. I = Symbol('I')
  383. b = Beam(4, E, I)
  384. b.apply_support(0, "cantilever")
  385. b.apply_load(20, 4, -1)
  386. M_0, R_0 = symbols('M_0, R_0')
  387. b.solve_for_reaction_loads(R_0, M_0)
  388. assert simplify(b.slope()) == simplify((80*SingularityFunction(x, 0, 1) - 10*SingularityFunction(x, 0, 2)
  389. + 10*SingularityFunction(x, 4, 2))/(E*I))
  390. assert simplify(b.deflection()) == simplify((40*SingularityFunction(x, 0, 2) - 10*SingularityFunction(x, 0, 3)/3
  391. + 10*SingularityFunction(x, 4, 3)/3)/(E*I))
  392. b = Beam(30, E, I)
  393. b.apply_support(10, "pin")
  394. b.apply_support(30, "roller")
  395. b.apply_load(-8, 0, -1)
  396. b.apply_load(120, 30, -2)
  397. R_10, R_30 = symbols('R_10, R_30')
  398. b.solve_for_reaction_loads(R_10, R_30)
  399. assert b.slope() == (-4*SingularityFunction(x, 0, 2) + 3*SingularityFunction(x, 10, 2)
  400. + 120*SingularityFunction(x, 30, 1) + SingularityFunction(x, 30, 2) + Rational(4000, 3))/(E*I)
  401. assert b.deflection() == (x*Rational(4000, 3) - 4*SingularityFunction(x, 0, 3)/3 + SingularityFunction(x, 10, 3)
  402. + 60*SingularityFunction(x, 30, 2) + SingularityFunction(x, 30, 3)/3 - 12000)/(E*I)
  403. P = Symbol('P', positive=True)
  404. L = Symbol('L', positive=True)
  405. b = Beam(L, E, I)
  406. b.apply_support(0, type='fixed')
  407. b.apply_support(L, type='fixed')
  408. b.apply_load(-P, L/2, -1)
  409. R_0, R_L, M_0, M_L = symbols('R_0, R_L, M_0, M_L')
  410. b.solve_for_reaction_loads(R_0, R_L, M_0, M_L)
  411. assert b.reaction_loads == {R_0: P/2, R_L: P/2, M_0: -L*P/8, M_L: L*P/8}
  412. def test_max_shear_force():
  413. E = Symbol('E')
  414. I = Symbol('I')
  415. b = Beam(3, E, I)
  416. R, M = symbols('R, M')
  417. b.apply_load(R, 0, -1)
  418. b.apply_load(M, 0, -2)
  419. b.apply_load(2, 3, -1)
  420. b.apply_load(4, 2, -1)
  421. b.apply_load(2, 2, 0, end=3)
  422. b.solve_for_reaction_loads(R, M)
  423. assert b.max_shear_force() == (Interval(0, 2), 8)
  424. l = symbols('l', positive=True)
  425. P = Symbol('P')
  426. b = Beam(l, E, I)
  427. R1, R2 = symbols('R1, R2')
  428. b.apply_load(R1, 0, -1)
  429. b.apply_load(R2, l, -1)
  430. b.apply_load(P, 0, 0, end=l)
  431. b.solve_for_reaction_loads(R1, R2)
  432. assert b.max_shear_force() == (0, l*Abs(P)/2)
  433. def test_max_bmoment():
  434. E = Symbol('E')
  435. I = Symbol('I')
  436. l, P = symbols('l, P', positive=True)
  437. b = Beam(l, E, I)
  438. R1, R2 = symbols('R1, R2')
  439. b.apply_load(R1, 0, -1)
  440. b.apply_load(R2, l, -1)
  441. b.apply_load(P, l/2, -1)
  442. b.solve_for_reaction_loads(R1, R2)
  443. b.reaction_loads
  444. assert b.max_bmoment() == (l/2, P*l/4)
  445. b = Beam(l, E, I)
  446. R1, R2 = symbols('R1, R2')
  447. b.apply_load(R1, 0, -1)
  448. b.apply_load(R2, l, -1)
  449. b.apply_load(P, 0, 0, end=l)
  450. b.solve_for_reaction_loads(R1, R2)
  451. assert b.max_bmoment() == (l/2, P*l**2/8)
  452. def test_max_deflection():
  453. E, I, l, F = symbols('E, I, l, F', positive=True)
  454. b = Beam(l, E, I)
  455. b.bc_deflection = [(0, 0),(l, 0)]
  456. b.bc_slope = [(0, 0),(l, 0)]
  457. b.apply_load(F/2, 0, -1)
  458. b.apply_load(-F*l/8, 0, -2)
  459. b.apply_load(F/2, l, -1)
  460. b.apply_load(F*l/8, l, -2)
  461. b.apply_load(-F, l/2, -1)
  462. assert b.max_deflection() == (l/2, F*l**3/(192*E*I))
  463. def test_Beam3D():
  464. l, E, G, I, A = symbols('l, E, G, I, A')
  465. R1, R2, R3, R4 = symbols('R1, R2, R3, R4')
  466. b = Beam3D(l, E, G, I, A)
  467. m, q = symbols('m, q')
  468. b.apply_load(q, 0, 0, dir="y")
  469. b.apply_moment_load(m, 0, 0, dir="z")
  470. b.bc_slope = [(0, [0, 0, 0]), (l, [0, 0, 0])]
  471. b.bc_deflection = [(0, [0, 0, 0]), (l, [0, 0, 0])]
  472. b.solve_slope_deflection()
  473. assert b.polar_moment() == 2*I
  474. assert b.shear_force() == [0, -q*x, 0]
  475. assert b.shear_stress() == [0, -q*x/A, 0]
  476. assert b.axial_stress() == 0
  477. assert b.bending_moment() == [0, 0, -m*x + q*x**2/2]
  478. expected_deflection = (x*(A*G*q*x**3/4 + A*G*x**2*(-l*(A*G*l*(l*q - 2*m) +
  479. 12*E*I*q)/(A*G*l**2 + 12*E*I)/2 - m) + 3*E*I*l*(A*G*l*(l*q - 2*m) +
  480. 12*E*I*q)/(A*G*l**2 + 12*E*I) + x*(-A*G*l**2*q/2 +
  481. 3*A*G*l**2*(A*G*l*(l*q - 2*m) + 12*E*I*q)/(A*G*l**2 + 12*E*I)/4 +
  482. A*G*l*m*Rational(3, 2) - 3*E*I*q))/(6*A*E*G*I))
  483. dx, dy, dz = b.deflection()
  484. assert dx == dz == 0
  485. assert simplify(dy - expected_deflection) == 0
  486. b2 = Beam3D(30, E, G, I, A, x)
  487. b2.apply_load(50, start=0, order=0, dir="y")
  488. b2.bc_deflection = [(0, [0, 0, 0]), (30, [0, 0, 0])]
  489. b2.apply_load(R1, start=0, order=-1, dir="y")
  490. b2.apply_load(R2, start=30, order=-1, dir="y")
  491. b2.solve_for_reaction_loads(R1, R2)
  492. assert b2.reaction_loads == {R1: -750, R2: -750}
  493. b2.solve_slope_deflection()
  494. assert b2.slope() == [0, 0, 25*x**3/(3*E*I) - 375*x**2/(E*I) + 3750*x/(E*I)]
  495. expected_deflection = 25*x**4/(12*E*I) - 125*x**3/(E*I) + 1875*x**2/(E*I) - \
  496. 25*x**2/(A*G) + 750*x/(A*G)
  497. dx, dy, dz = b2.deflection()
  498. assert dx == dz == 0
  499. assert dy == expected_deflection
  500. # Test for solve_for_reaction_loads
  501. b3 = Beam3D(30, E, G, I, A, x)
  502. b3.apply_load(8, start=0, order=0, dir="y")
  503. b3.apply_load(9*x, start=0, order=0, dir="z")
  504. b3.apply_load(R1, start=0, order=-1, dir="y")
  505. b3.apply_load(R2, start=30, order=-1, dir="y")
  506. b3.apply_load(R3, start=0, order=-1, dir="z")
  507. b3.apply_load(R4, start=30, order=-1, dir="z")
  508. b3.solve_for_reaction_loads(R1, R2, R3, R4)
  509. assert b3.reaction_loads == {R1: -120, R2: -120, R3: -1350, R4: -2700}
  510. def test_polar_moment_Beam3D():
  511. l, E, G, A, I1, I2 = symbols('l, E, G, A, I1, I2')
  512. I = [I1, I2]
  513. b = Beam3D(l, E, G, I, A)
  514. assert b.polar_moment() == I1 + I2
  515. def test_parabolic_loads():
  516. E, I, L = symbols('E, I, L', positive=True, real=True)
  517. R, M, P = symbols('R, M, P', real=True)
  518. # cantilever beam fixed at x=0 and parabolic distributed loading across
  519. # length of beam
  520. beam = Beam(L, E, I)
  521. beam.bc_deflection.append((0, 0))
  522. beam.bc_slope.append((0, 0))
  523. beam.apply_load(R, 0, -1)
  524. beam.apply_load(M, 0, -2)
  525. # parabolic load
  526. beam.apply_load(1, 0, 2)
  527. beam.solve_for_reaction_loads(R, M)
  528. assert beam.reaction_loads[R] == -L**3/3
  529. # cantilever beam fixed at x=0 and parabolic distributed loading across
  530. # first half of beam
  531. beam = Beam(2*L, E, I)
  532. beam.bc_deflection.append((0, 0))
  533. beam.bc_slope.append((0, 0))
  534. beam.apply_load(R, 0, -1)
  535. beam.apply_load(M, 0, -2)
  536. # parabolic load from x=0 to x=L
  537. beam.apply_load(1, 0, 2, end=L)
  538. beam.solve_for_reaction_loads(R, M)
  539. # result should be the same as the prior example
  540. assert beam.reaction_loads[R] == -L**3/3
  541. # check constant load
  542. beam = Beam(2*L, E, I)
  543. beam.apply_load(P, 0, 0, end=L)
  544. loading = beam.load.xreplace({L: 10, E: 20, I: 30, P: 40})
  545. assert loading.xreplace({x: 5}) == 40
  546. assert loading.xreplace({x: 15}) == 0
  547. # check ramp load
  548. beam = Beam(2*L, E, I)
  549. beam.apply_load(P, 0, 1, end=L)
  550. assert beam.load == (P*SingularityFunction(x, 0, 1) -
  551. P*SingularityFunction(x, L, 1) -
  552. P*L*SingularityFunction(x, L, 0))
  553. # check higher order load: x**8 load from x=0 to x=L
  554. beam = Beam(2*L, E, I)
  555. beam.apply_load(P, 0, 8, end=L)
  556. loading = beam.load.xreplace({L: 10, E: 20, I: 30, P: 40})
  557. assert loading.xreplace({x: 5}) == 40*5**8
  558. assert loading.xreplace({x: 15}) == 0
  559. def test_cross_section():
  560. I = Symbol('I')
  561. l = Symbol('l')
  562. E = Symbol('E')
  563. C3, C4 = symbols('C3, C4')
  564. a, c, g, h, r, n = symbols('a, c, g, h, r, n')
  565. # test for second_moment and cross_section setter
  566. b0 = Beam(l, E, I)
  567. assert b0.second_moment == I
  568. assert b0.cross_section == None
  569. b0.cross_section = Circle((0, 0), 5)
  570. assert b0.second_moment == pi*Rational(625, 4)
  571. assert b0.cross_section == Circle((0, 0), 5)
  572. b0.second_moment = 2*n - 6
  573. assert b0.second_moment == 2*n-6
  574. assert b0.cross_section == None
  575. with raises(ValueError):
  576. b0.second_moment = Circle((0, 0), 5)
  577. # beam with a circular cross-section
  578. b1 = Beam(50, E, Circle((0, 0), r))
  579. assert b1.cross_section == Circle((0, 0), r)
  580. assert b1.second_moment == pi*r*Abs(r)**3/4
  581. b1.apply_load(-10, 0, -1)
  582. b1.apply_load(R1, 5, -1)
  583. b1.apply_load(R2, 50, -1)
  584. b1.apply_load(90, 45, -2)
  585. b1.solve_for_reaction_loads(R1, R2)
  586. assert b1.load == (-10*SingularityFunction(x, 0, -1) + 82*SingularityFunction(x, 5, -1)/S(9)
  587. + 90*SingularityFunction(x, 45, -2) + 8*SingularityFunction(x, 50, -1)/9)
  588. assert b1.bending_moment() == (10*SingularityFunction(x, 0, 1) - 82*SingularityFunction(x, 5, 1)/9
  589. - 90*SingularityFunction(x, 45, 0) - 8*SingularityFunction(x, 50, 1)/9)
  590. q = (-5*SingularityFunction(x, 0, 2) + 41*SingularityFunction(x, 5, 2)/S(9)
  591. + 90*SingularityFunction(x, 45, 1) + 4*SingularityFunction(x, 50, 2)/S(9))/(pi*E*r*Abs(r)**3)
  592. assert b1.slope() == C3 + 4*q
  593. q = (-5*SingularityFunction(x, 0, 3)/3 + 41*SingularityFunction(x, 5, 3)/27 + 45*SingularityFunction(x, 45, 2)
  594. + 4*SingularityFunction(x, 50, 3)/27)/(pi*E*r*Abs(r)**3)
  595. assert b1.deflection() == C3*x + C4 + 4*q
  596. # beam with a recatangular cross-section
  597. b2 = Beam(20, E, Polygon((0, 0), (a, 0), (a, c), (0, c)))
  598. assert b2.cross_section == Polygon((0, 0), (a, 0), (a, c), (0, c))
  599. assert b2.second_moment == a*c**3/12
  600. # beam with a triangular cross-section
  601. b3 = Beam(15, E, Triangle((0, 0), (g, 0), (g/2, h)))
  602. assert b3.cross_section == Triangle(Point2D(0, 0), Point2D(g, 0), Point2D(g/2, h))
  603. assert b3.second_moment == g*h**3/36
  604. # composite beam
  605. b = b2.join(b3, "fixed")
  606. b.apply_load(-30, 0, -1)
  607. b.apply_load(65, 0, -2)
  608. b.apply_load(40, 0, -1)
  609. b.bc_slope = [(0, 0)]
  610. b.bc_deflection = [(0, 0)]
  611. assert b.second_moment == Piecewise((a*c**3/12, x <= 20), (g*h**3/36, x <= 35))
  612. assert b.cross_section == None
  613. assert b.length == 35
  614. assert b.slope().subs(x, 7) == 8400/(E*a*c**3)
  615. assert b.slope().subs(x, 25) == 52200/(E*g*h**3) + 39600/(E*a*c**3)
  616. assert b.deflection().subs(x, 30) == -537000/(E*g*h**3) - 712000/(E*a*c**3)
  617. def test_max_shear_force_Beam3D():
  618. x = symbols('x')
  619. b = Beam3D(20, 40, 21, 100, 25)
  620. b.apply_load(15, start=0, order=0, dir="z")
  621. b.apply_load(12*x, start=0, order=0, dir="y")
  622. b.bc_deflection = [(0, [0, 0, 0]), (20, [0, 0, 0])]
  623. assert b.max_shear_force() == [(0, 0), (20, 2400), (20, 300)]
  624. def test_max_bending_moment_Beam3D():
  625. x = symbols('x')
  626. b = Beam3D(20, 40, 21, 100, 25)
  627. b.apply_load(15, start=0, order=0, dir="z")
  628. b.apply_load(12*x, start=0, order=0, dir="y")
  629. b.bc_deflection = [(0, [0, 0, 0]), (20, [0, 0, 0])]
  630. assert b.max_bmoment() == [(0, 0), (20, 3000), (20, 16000)]
  631. def test_max_deflection_Beam3D():
  632. x = symbols('x')
  633. b = Beam3D(20, 40, 21, 100, 25)
  634. b.apply_load(15, start=0, order=0, dir="z")
  635. b.apply_load(12*x, start=0, order=0, dir="y")
  636. b.bc_deflection = [(0, [0, 0, 0]), (20, [0, 0, 0])]
  637. b.solve_slope_deflection()
  638. c = sympify("495/14")
  639. p = sympify("-10 + 10*sqrt(10793)/43")
  640. q = sympify("(10 - 10*sqrt(10793)/43)**3/160 - 20/7 + (10 - 10*sqrt(10793)/43)**4/6400 + 20*sqrt(10793)/301 + 27*(10 - 10*sqrt(10793)/43)**2/560")
  641. assert b.max_deflection() == [(0, 0), (10, c), (p, q)]
  642. def test_torsion_Beam3D():
  643. x = symbols('x')
  644. b = Beam3D(20, 40, 21, 100, 25)
  645. b.apply_moment_load(15, 5, -2, dir='x')
  646. b.apply_moment_load(25, 10, -2, dir='x')
  647. b.apply_moment_load(-5, 20, -2, dir='x')
  648. b.solve_for_torsion()
  649. assert b.angular_deflection().subs(x, 3) == sympify("1/40")
  650. assert b.angular_deflection().subs(x, 9) == sympify("17/280")
  651. assert b.angular_deflection().subs(x, 12) == sympify("53/840")
  652. assert b.angular_deflection().subs(x, 17) == sympify("2/35")
  653. assert b.angular_deflection().subs(x, 20) == sympify("3/56")