test_system.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. from sympy.core.backend import symbols, Matrix, atan, zeros
  2. from sympy.simplify.simplify import simplify
  3. from sympy.physics.mechanics import (dynamicsymbols, Particle, Point,
  4. ReferenceFrame, SymbolicSystem)
  5. from sympy.testing.pytest import raises
  6. # This class is going to be tested using a simple pendulum set up in x and y
  7. # coordinates
  8. x, y, u, v, lam = dynamicsymbols('x y u v lambda')
  9. m, l, g = symbols('m l g')
  10. # Set up the different forms the equations can take
  11. # [1] Explicit form where the kinematics and dynamics are combined
  12. # x' = F(x, t, r, p)
  13. #
  14. # [2] Implicit form where the kinematics and dynamics are combined
  15. # M(x, p) x' = F(x, t, r, p)
  16. #
  17. # [3] Implicit form where the kinematics and dynamics are separate
  18. # M(q, p) u' = F(q, u, t, r, p)
  19. # q' = G(q, u, t, r, p)
  20. dyn_implicit_mat = Matrix([[1, 0, -x/m],
  21. [0, 1, -y/m],
  22. [0, 0, l**2/m]])
  23. dyn_implicit_rhs = Matrix([0, 0, u**2 + v**2 - g*y])
  24. comb_implicit_mat = Matrix([[1, 0, 0, 0, 0],
  25. [0, 1, 0, 0, 0],
  26. [0, 0, 1, 0, -x/m],
  27. [0, 0, 0, 1, -y/m],
  28. [0, 0, 0, 0, l**2/m]])
  29. comb_implicit_rhs = Matrix([u, v, 0, 0, u**2 + v**2 - g*y])
  30. kin_explicit_rhs = Matrix([u, v])
  31. comb_explicit_rhs = comb_implicit_mat.LUsolve(comb_implicit_rhs)
  32. # Set up a body and load to pass into the system
  33. theta = atan(x/y)
  34. N = ReferenceFrame('N')
  35. A = N.orientnew('A', 'Axis', [theta, N.z])
  36. O = Point('O')
  37. P = O.locatenew('P', l * A.x)
  38. Pa = Particle('Pa', P, m)
  39. bodies = [Pa]
  40. loads = [(P, g * m * N.x)]
  41. # Set up some output equations to be given to SymbolicSystem
  42. # Change to make these fit the pendulum
  43. PE = symbols("PE")
  44. out_eqns = {PE: m*g*(l+y)}
  45. # Set up remaining arguments that can be passed to SymbolicSystem
  46. alg_con = [2]
  47. alg_con_full = [4]
  48. coordinates = (x, y, lam)
  49. speeds = (u, v)
  50. states = (x, y, u, v, lam)
  51. coord_idxs = (0, 1)
  52. speed_idxs = (2, 3)
  53. def test_form_1():
  54. symsystem1 = SymbolicSystem(states, comb_explicit_rhs,
  55. alg_con=alg_con_full, output_eqns=out_eqns,
  56. coord_idxs=coord_idxs, speed_idxs=speed_idxs,
  57. bodies=bodies, loads=loads)
  58. assert symsystem1.coordinates == Matrix([x, y])
  59. assert symsystem1.speeds == Matrix([u, v])
  60. assert symsystem1.states == Matrix([x, y, u, v, lam])
  61. assert symsystem1.alg_con == [4]
  62. inter = comb_explicit_rhs
  63. assert simplify(symsystem1.comb_explicit_rhs - inter) == zeros(5, 1)
  64. assert set(symsystem1.dynamic_symbols()) == {y, v, lam, u, x}
  65. assert type(symsystem1.dynamic_symbols()) == tuple
  66. assert set(symsystem1.constant_symbols()) == {l, g, m}
  67. assert type(symsystem1.constant_symbols()) == tuple
  68. assert symsystem1.output_eqns == out_eqns
  69. assert symsystem1.bodies == (Pa,)
  70. assert symsystem1.loads == ((P, g * m * N.x),)
  71. def test_form_2():
  72. symsystem2 = SymbolicSystem(coordinates, comb_implicit_rhs, speeds=speeds,
  73. mass_matrix=comb_implicit_mat,
  74. alg_con=alg_con_full, output_eqns=out_eqns,
  75. bodies=bodies, loads=loads)
  76. assert symsystem2.coordinates == Matrix([x, y, lam])
  77. assert symsystem2.speeds == Matrix([u, v])
  78. assert symsystem2.states == Matrix([x, y, lam, u, v])
  79. assert symsystem2.alg_con == [4]
  80. inter = comb_implicit_rhs
  81. assert simplify(symsystem2.comb_implicit_rhs - inter) == zeros(5, 1)
  82. assert simplify(symsystem2.comb_implicit_mat-comb_implicit_mat) == zeros(5)
  83. assert set(symsystem2.dynamic_symbols()) == {y, v, lam, u, x}
  84. assert type(symsystem2.dynamic_symbols()) == tuple
  85. assert set(symsystem2.constant_symbols()) == {l, g, m}
  86. assert type(symsystem2.constant_symbols()) == tuple
  87. inter = comb_explicit_rhs
  88. symsystem2.compute_explicit_form()
  89. assert simplify(symsystem2.comb_explicit_rhs - inter) == zeros(5, 1)
  90. assert symsystem2.output_eqns == out_eqns
  91. assert symsystem2.bodies == (Pa,)
  92. assert symsystem2.loads == ((P, g * m * N.x),)
  93. def test_form_3():
  94. symsystem3 = SymbolicSystem(states, dyn_implicit_rhs,
  95. mass_matrix=dyn_implicit_mat,
  96. coordinate_derivatives=kin_explicit_rhs,
  97. alg_con=alg_con, coord_idxs=coord_idxs,
  98. speed_idxs=speed_idxs, bodies=bodies,
  99. loads=loads)
  100. assert symsystem3.coordinates == Matrix([x, y])
  101. assert symsystem3.speeds == Matrix([u, v])
  102. assert symsystem3.states == Matrix([x, y, u, v, lam])
  103. assert symsystem3.alg_con == [4]
  104. inter1 = kin_explicit_rhs
  105. inter2 = dyn_implicit_rhs
  106. assert simplify(symsystem3.kin_explicit_rhs - inter1) == zeros(2, 1)
  107. assert simplify(symsystem3.dyn_implicit_mat - dyn_implicit_mat) == zeros(3)
  108. assert simplify(symsystem3.dyn_implicit_rhs - inter2) == zeros(3, 1)
  109. inter = comb_implicit_rhs
  110. assert simplify(symsystem3.comb_implicit_rhs - inter) == zeros(5, 1)
  111. assert simplify(symsystem3.comb_implicit_mat-comb_implicit_mat) == zeros(5)
  112. inter = comb_explicit_rhs
  113. symsystem3.compute_explicit_form()
  114. assert simplify(symsystem3.comb_explicit_rhs - inter) == zeros(5, 1)
  115. assert set(symsystem3.dynamic_symbols()) == {y, v, lam, u, x}
  116. assert type(symsystem3.dynamic_symbols()) == tuple
  117. assert set(symsystem3.constant_symbols()) == {l, g, m}
  118. assert type(symsystem3.constant_symbols()) == tuple
  119. assert symsystem3.output_eqns == {}
  120. assert symsystem3.bodies == (Pa,)
  121. assert symsystem3.loads == ((P, g * m * N.x),)
  122. def test_property_attributes():
  123. symsystem = SymbolicSystem(states, comb_explicit_rhs,
  124. alg_con=alg_con_full, output_eqns=out_eqns,
  125. coord_idxs=coord_idxs, speed_idxs=speed_idxs,
  126. bodies=bodies, loads=loads)
  127. with raises(AttributeError):
  128. symsystem.bodies = 42
  129. with raises(AttributeError):
  130. symsystem.coordinates = 42
  131. with raises(AttributeError):
  132. symsystem.dyn_implicit_rhs = 42
  133. with raises(AttributeError):
  134. symsystem.comb_implicit_rhs = 42
  135. with raises(AttributeError):
  136. symsystem.loads = 42
  137. with raises(AttributeError):
  138. symsystem.dyn_implicit_mat = 42
  139. with raises(AttributeError):
  140. symsystem.comb_implicit_mat = 42
  141. with raises(AttributeError):
  142. symsystem.kin_explicit_rhs = 42
  143. with raises(AttributeError):
  144. symsystem.comb_explicit_rhs = 42
  145. with raises(AttributeError):
  146. symsystem.speeds = 42
  147. with raises(AttributeError):
  148. symsystem.states = 42
  149. with raises(AttributeError):
  150. symsystem.alg_con = 42
  151. def test_not_specified_errors():
  152. """This test will cover errors that arise from trying to access attributes
  153. that were not specified upon object creation or were specified on creation
  154. and the user tries to recalculate them."""
  155. # Trying to access form 2 when form 1 given
  156. # Trying to access form 3 when form 2 given
  157. symsystem1 = SymbolicSystem(states, comb_explicit_rhs)
  158. with raises(AttributeError):
  159. symsystem1.comb_implicit_mat
  160. with raises(AttributeError):
  161. symsystem1.comb_implicit_rhs
  162. with raises(AttributeError):
  163. symsystem1.dyn_implicit_mat
  164. with raises(AttributeError):
  165. symsystem1.dyn_implicit_rhs
  166. with raises(AttributeError):
  167. symsystem1.kin_explicit_rhs
  168. with raises(AttributeError):
  169. symsystem1.compute_explicit_form()
  170. symsystem2 = SymbolicSystem(coordinates, comb_implicit_rhs, speeds=speeds,
  171. mass_matrix=comb_implicit_mat)
  172. with raises(AttributeError):
  173. symsystem2.dyn_implicit_mat
  174. with raises(AttributeError):
  175. symsystem2.dyn_implicit_rhs
  176. with raises(AttributeError):
  177. symsystem2.kin_explicit_rhs
  178. # Attribute error when trying to access coordinates and speeds when only the
  179. # states were given.
  180. with raises(AttributeError):
  181. symsystem1.coordinates
  182. with raises(AttributeError):
  183. symsystem1.speeds
  184. # Attribute error when trying to access bodies and loads when they are not
  185. # given
  186. with raises(AttributeError):
  187. symsystem1.bodies
  188. with raises(AttributeError):
  189. symsystem1.loads
  190. # Attribute error when trying to access comb_explicit_rhs before it was
  191. # calculated
  192. with raises(AttributeError):
  193. symsystem2.comb_explicit_rhs