图片解析应用
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

252 lines
8.9 KiB

  1. from sympy.core.backend import sin, cos, tan, pi, symbols, Matrix, S
  2. from sympy.physics.mechanics import (Particle, Point, ReferenceFrame,
  3. RigidBody)
  4. from sympy.physics.mechanics import (angular_momentum, dynamicsymbols,
  5. inertia, inertia_of_point_mass,
  6. kinetic_energy, linear_momentum,
  7. outer, potential_energy, msubs,
  8. find_dynamicsymbols, Lagrangian)
  9. from sympy.physics.mechanics.functions import gravity, center_of_mass
  10. from sympy.physics.vector.vector import Vector
  11. from sympy.testing.pytest import raises
  12. Vector.simp = True
  13. q1, q2, q3, q4, q5 = symbols('q1 q2 q3 q4 q5')
  14. N = ReferenceFrame('N')
  15. A = N.orientnew('A', 'Axis', [q1, N.z])
  16. B = A.orientnew('B', 'Axis', [q2, A.x])
  17. C = B.orientnew('C', 'Axis', [q3, B.y])
  18. def test_inertia():
  19. N = ReferenceFrame('N')
  20. ixx, iyy, izz = symbols('ixx iyy izz')
  21. ixy, iyz, izx = symbols('ixy iyz izx')
  22. assert inertia(N, ixx, iyy, izz) == (ixx * (N.x | N.x) + iyy *
  23. (N.y | N.y) + izz * (N.z | N.z))
  24. assert inertia(N, 0, 0, 0) == 0 * (N.x | N.x)
  25. raises(TypeError, lambda: inertia(0, 0, 0, 0))
  26. assert inertia(N, ixx, iyy, izz, ixy, iyz, izx) == (ixx * (N.x | N.x) +
  27. ixy * (N.x | N.y) + izx * (N.x | N.z) + ixy * (N.y | N.x) + iyy *
  28. (N.y | N.y) + iyz * (N.y | N.z) + izx * (N.z | N.x) + iyz * (N.z |
  29. N.y) + izz * (N.z | N.z))
  30. def test_inertia_of_point_mass():
  31. r, s, t, m = symbols('r s t m')
  32. N = ReferenceFrame('N')
  33. px = r * N.x
  34. I = inertia_of_point_mass(m, px, N)
  35. assert I == m * r**2 * (N.y | N.y) + m * r**2 * (N.z | N.z)
  36. py = s * N.y
  37. I = inertia_of_point_mass(m, py, N)
  38. assert I == m * s**2 * (N.x | N.x) + m * s**2 * (N.z | N.z)
  39. pz = t * N.z
  40. I = inertia_of_point_mass(m, pz, N)
  41. assert I == m * t**2 * (N.x | N.x) + m * t**2 * (N.y | N.y)
  42. p = px + py + pz
  43. I = inertia_of_point_mass(m, p, N)
  44. assert I == (m * (s**2 + t**2) * (N.x | N.x) -
  45. m * r * s * (N.x | N.y) -
  46. m * r * t * (N.x | N.z) -
  47. m * r * s * (N.y | N.x) +
  48. m * (r**2 + t**2) * (N.y | N.y) -
  49. m * s * t * (N.y | N.z) -
  50. m * r * t * (N.z | N.x) -
  51. m * s * t * (N.z | N.y) +
  52. m * (r**2 + s**2) * (N.z | N.z))
  53. def test_linear_momentum():
  54. N = ReferenceFrame('N')
  55. Ac = Point('Ac')
  56. Ac.set_vel(N, 25 * N.y)
  57. I = outer(N.x, N.x)
  58. A = RigidBody('A', Ac, N, 20, (I, Ac))
  59. P = Point('P')
  60. Pa = Particle('Pa', P, 1)
  61. Pa.point.set_vel(N, 10 * N.x)
  62. raises(TypeError, lambda: linear_momentum(A, A, Pa))
  63. raises(TypeError, lambda: linear_momentum(N, N, Pa))
  64. assert linear_momentum(N, A, Pa) == 10 * N.x + 500 * N.y
  65. def test_angular_momentum_and_linear_momentum():
  66. """A rod with length 2l, centroidal inertia I, and mass M along with a
  67. particle of mass m fixed to the end of the rod rotate with an angular rate
  68. of omega about point O which is fixed to the non-particle end of the rod.
  69. The rod's reference frame is A and the inertial frame is N."""
  70. m, M, l, I = symbols('m, M, l, I')
  71. omega = dynamicsymbols('omega')
  72. N = ReferenceFrame('N')
  73. a = ReferenceFrame('a')
  74. O = Point('O')
  75. Ac = O.locatenew('Ac', l * N.x)
  76. P = Ac.locatenew('P', l * N.x)
  77. O.set_vel(N, 0 * N.x)
  78. a.set_ang_vel(N, omega * N.z)
  79. Ac.v2pt_theory(O, N, a)
  80. P.v2pt_theory(O, N, a)
  81. Pa = Particle('Pa', P, m)
  82. A = RigidBody('A', Ac, a, M, (I * outer(N.z, N.z), Ac))
  83. expected = 2 * m * omega * l * N.y + M * l * omega * N.y
  84. assert linear_momentum(N, A, Pa) == expected
  85. raises(TypeError, lambda: angular_momentum(N, N, A, Pa))
  86. raises(TypeError, lambda: angular_momentum(O, O, A, Pa))
  87. raises(TypeError, lambda: angular_momentum(O, N, O, Pa))
  88. expected = (I + M * l**2 + 4 * m * l**2) * omega * N.z
  89. assert angular_momentum(O, N, A, Pa) == expected
  90. def test_kinetic_energy():
  91. m, M, l1 = symbols('m M l1')
  92. omega = dynamicsymbols('omega')
  93. N = ReferenceFrame('N')
  94. O = Point('O')
  95. O.set_vel(N, 0 * N.x)
  96. Ac = O.locatenew('Ac', l1 * N.x)
  97. P = Ac.locatenew('P', l1 * N.x)
  98. a = ReferenceFrame('a')
  99. a.set_ang_vel(N, omega * N.z)
  100. Ac.v2pt_theory(O, N, a)
  101. P.v2pt_theory(O, N, a)
  102. Pa = Particle('Pa', P, m)
  103. I = outer(N.z, N.z)
  104. A = RigidBody('A', Ac, a, M, (I, Ac))
  105. raises(TypeError, lambda: kinetic_energy(Pa, Pa, A))
  106. raises(TypeError, lambda: kinetic_energy(N, N, A))
  107. assert 0 == (kinetic_energy(N, Pa, A) - (M*l1**2*omega**2/2
  108. + 2*l1**2*m*omega**2 + omega**2/2)).expand()
  109. def test_potential_energy():
  110. m, M, l1, g, h, H = symbols('m M l1 g h H')
  111. omega = dynamicsymbols('omega')
  112. N = ReferenceFrame('N')
  113. O = Point('O')
  114. O.set_vel(N, 0 * N.x)
  115. Ac = O.locatenew('Ac', l1 * N.x)
  116. P = Ac.locatenew('P', l1 * N.x)
  117. a = ReferenceFrame('a')
  118. a.set_ang_vel(N, omega * N.z)
  119. Ac.v2pt_theory(O, N, a)
  120. P.v2pt_theory(O, N, a)
  121. Pa = Particle('Pa', P, m)
  122. I = outer(N.z, N.z)
  123. A = RigidBody('A', Ac, a, M, (I, Ac))
  124. Pa.potential_energy = m * g * h
  125. A.potential_energy = M * g * H
  126. assert potential_energy(A, Pa) == m * g * h + M * g * H
  127. def test_Lagrangian():
  128. M, m, g, h = symbols('M m g h')
  129. N = ReferenceFrame('N')
  130. O = Point('O')
  131. O.set_vel(N, 0 * N.x)
  132. P = O.locatenew('P', 1 * N.x)
  133. P.set_vel(N, 10 * N.x)
  134. Pa = Particle('Pa', P, 1)
  135. Ac = O.locatenew('Ac', 2 * N.y)
  136. Ac.set_vel(N, 5 * N.y)
  137. a = ReferenceFrame('a')
  138. a.set_ang_vel(N, 10 * N.z)
  139. I = outer(N.z, N.z)
  140. A = RigidBody('A', Ac, a, 20, (I, Ac))
  141. Pa.potential_energy = m * g * h
  142. A.potential_energy = M * g * h
  143. raises(TypeError, lambda: Lagrangian(A, A, Pa))
  144. raises(TypeError, lambda: Lagrangian(N, N, Pa))
  145. def test_msubs():
  146. a, b = symbols('a, b')
  147. x, y, z = dynamicsymbols('x, y, z')
  148. # Test simple substitution
  149. expr = Matrix([[a*x + b, x*y.diff() + y],
  150. [x.diff().diff(), z + sin(z.diff())]])
  151. sol = Matrix([[a + b, y],
  152. [x.diff().diff(), 1]])
  153. sd = {x: 1, z: 1, z.diff(): 0, y.diff(): 0}
  154. assert msubs(expr, sd) == sol
  155. # Test smart substitution
  156. expr = cos(x + y)*tan(x + y) + b*x.diff()
  157. sd = {x: 0, y: pi/2, x.diff(): 1}
  158. assert msubs(expr, sd, smart=True) == b + 1
  159. N = ReferenceFrame('N')
  160. v = x*N.x + y*N.y
  161. d = x*(N.x|N.x) + y*(N.y|N.y)
  162. v_sol = 1*N.y
  163. d_sol = 1*(N.y|N.y)
  164. sd = {x: 0, y: 1}
  165. assert msubs(v, sd) == v_sol
  166. assert msubs(d, sd) == d_sol
  167. def test_find_dynamicsymbols():
  168. a, b = symbols('a, b')
  169. x, y, z = dynamicsymbols('x, y, z')
  170. expr = Matrix([[a*x + b, x*y.diff() + y],
  171. [x.diff().diff(), z + sin(z.diff())]])
  172. # Test finding all dynamicsymbols
  173. sol = {x, y.diff(), y, x.diff().diff(), z, z.diff()}
  174. assert find_dynamicsymbols(expr) == sol
  175. # Test finding all but those in sym_list
  176. exclude_list = [x, y, z]
  177. sol = {y.diff(), x.diff().diff(), z.diff()}
  178. assert find_dynamicsymbols(expr, exclude=exclude_list) == sol
  179. # Test finding all dynamicsymbols in a vector with a given reference frame
  180. d, e, f = dynamicsymbols('d, e, f')
  181. A = ReferenceFrame('A')
  182. v = d * A.x + e * A.y + f * A.z
  183. sol = {d, e, f}
  184. assert find_dynamicsymbols(v, reference_frame=A) == sol
  185. # Test if a ValueError is raised on supplying only a vector as input
  186. raises(ValueError, lambda: find_dynamicsymbols(v))
  187. def test_gravity():
  188. N = ReferenceFrame('N')
  189. m, M, g = symbols('m M g')
  190. F1, F2 = dynamicsymbols('F1 F2')
  191. po = Point('po')
  192. pa = Particle('pa', po, m)
  193. A = ReferenceFrame('A')
  194. P = Point('P')
  195. I = outer(A.x, A.x)
  196. B = RigidBody('B', P, A, M, (I, P))
  197. forceList = [(po, F1), (P, F2)]
  198. forceList.extend(gravity(g*N.y, pa, B))
  199. l = [(po, F1), (P, F2), (po, g*m*N.y), (P, g*M*N.y)]
  200. for i in range(len(l)):
  201. for j in range(len(l[i])):
  202. assert forceList[i][j] == l[i][j]
  203. # This function tests the center_of_mass() function
  204. # that was added in PR #14758 to compute the center of
  205. # mass of a system of bodies.
  206. def test_center_of_mass():
  207. a = ReferenceFrame('a')
  208. m = symbols('m', real=True)
  209. p1 = Particle('p1', Point('p1_pt'), S.One)
  210. p2 = Particle('p2', Point('p2_pt'), S(2))
  211. p3 = Particle('p3', Point('p3_pt'), S(3))
  212. p4 = Particle('p4', Point('p4_pt'), m)
  213. b_f = ReferenceFrame('b_f')
  214. b_cm = Point('b_cm')
  215. mb = symbols('mb')
  216. b = RigidBody('b', b_cm, b_f, mb, (outer(b_f.x, b_f.x), b_cm))
  217. p2.point.set_pos(p1.point, a.x)
  218. p3.point.set_pos(p1.point, a.x + a.y)
  219. p4.point.set_pos(p1.point, a.y)
  220. b.masscenter.set_pos(p1.point, a.y + a.z)
  221. point_o=Point('o')
  222. point_o.set_pos(p1.point, center_of_mass(p1.point, p1, p2, p3, p4, b))
  223. expr = 5/(m + mb + 6)*a.x + (m + mb + 3)/(m + mb + 6)*a.y + mb/(m + mb + 6)*a.z
  224. assert point_o.pos_from(p1.point)-expr == 0