test_coordsysrect.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. from sympy.testing.pytest import raises
  2. from sympy.vector.coordsysrect import CoordSys3D
  3. from sympy.vector.scalar import BaseScalar
  4. from sympy.core.function import expand
  5. from sympy.core.numbers import pi
  6. from sympy.core.symbol import symbols
  7. from sympy.functions.elementary.hyperbolic import (cosh, sinh)
  8. from sympy.functions.elementary.miscellaneous import sqrt
  9. from sympy.functions.elementary.trigonometric import (acos, atan2, cos, sin)
  10. from sympy.matrices.dense import zeros
  11. from sympy.matrices.immutable import ImmutableDenseMatrix as Matrix
  12. from sympy.simplify.simplify import simplify
  13. from sympy.vector.functions import express
  14. from sympy.vector.point import Point
  15. from sympy.vector.vector import Vector
  16. from sympy.vector.orienters import (AxisOrienter, BodyOrienter,
  17. SpaceOrienter, QuaternionOrienter)
  18. x, y, z = symbols('x y z')
  19. a, b, c, q = symbols('a b c q')
  20. q1, q2, q3, q4 = symbols('q1 q2 q3 q4')
  21. def test_func_args():
  22. A = CoordSys3D('A')
  23. assert A.x.func(*A.x.args) == A.x
  24. expr = 3*A.x + 4*A.y
  25. assert expr.func(*expr.args) == expr
  26. assert A.i.func(*A.i.args) == A.i
  27. v = A.x*A.i + A.y*A.j + A.z*A.k
  28. assert v.func(*v.args) == v
  29. assert A.origin.func(*A.origin.args) == A.origin
  30. def test_coordsys3d_equivalence():
  31. A = CoordSys3D('A')
  32. A1 = CoordSys3D('A')
  33. assert A1 == A
  34. B = CoordSys3D('B')
  35. assert A != B
  36. def test_orienters():
  37. A = CoordSys3D('A')
  38. axis_orienter = AxisOrienter(a, A.k)
  39. body_orienter = BodyOrienter(a, b, c, '123')
  40. space_orienter = SpaceOrienter(a, b, c, '123')
  41. q_orienter = QuaternionOrienter(q1, q2, q3, q4)
  42. assert axis_orienter.rotation_matrix(A) == Matrix([
  43. [ cos(a), sin(a), 0],
  44. [-sin(a), cos(a), 0],
  45. [ 0, 0, 1]])
  46. assert body_orienter.rotation_matrix() == Matrix([
  47. [ cos(b)*cos(c), sin(a)*sin(b)*cos(c) + sin(c)*cos(a),
  48. sin(a)*sin(c) - sin(b)*cos(a)*cos(c)],
  49. [-sin(c)*cos(b), -sin(a)*sin(b)*sin(c) + cos(a)*cos(c),
  50. sin(a)*cos(c) + sin(b)*sin(c)*cos(a)],
  51. [ sin(b), -sin(a)*cos(b),
  52. cos(a)*cos(b)]])
  53. assert space_orienter.rotation_matrix() == Matrix([
  54. [cos(b)*cos(c), sin(c)*cos(b), -sin(b)],
  55. [sin(a)*sin(b)*cos(c) - sin(c)*cos(a),
  56. sin(a)*sin(b)*sin(c) + cos(a)*cos(c), sin(a)*cos(b)],
  57. [sin(a)*sin(c) + sin(b)*cos(a)*cos(c), -sin(a)*cos(c) +
  58. sin(b)*sin(c)*cos(a), cos(a)*cos(b)]])
  59. assert q_orienter.rotation_matrix() == Matrix([
  60. [q1**2 + q2**2 - q3**2 - q4**2, 2*q1*q4 + 2*q2*q3,
  61. -2*q1*q3 + 2*q2*q4],
  62. [-2*q1*q4 + 2*q2*q3, q1**2 - q2**2 + q3**2 - q4**2,
  63. 2*q1*q2 + 2*q3*q4],
  64. [2*q1*q3 + 2*q2*q4,
  65. -2*q1*q2 + 2*q3*q4, q1**2 - q2**2 - q3**2 + q4**2]])
  66. def test_coordinate_vars():
  67. """
  68. Tests the coordinate variables functionality with respect to
  69. reorientation of coordinate systems.
  70. """
  71. A = CoordSys3D('A')
  72. # Note that the name given on the lhs is different from A.x._name
  73. assert BaseScalar(0, A, 'A_x', r'\mathbf{{x}_{A}}') == A.x
  74. assert BaseScalar(1, A, 'A_y', r'\mathbf{{y}_{A}}') == A.y
  75. assert BaseScalar(2, A, 'A_z', r'\mathbf{{z}_{A}}') == A.z
  76. assert BaseScalar(0, A, 'A_x', r'\mathbf{{x}_{A}}').__hash__() == A.x.__hash__()
  77. assert isinstance(A.x, BaseScalar) and \
  78. isinstance(A.y, BaseScalar) and \
  79. isinstance(A.z, BaseScalar)
  80. assert A.x*A.y == A.y*A.x
  81. assert A.scalar_map(A) == {A.x: A.x, A.y: A.y, A.z: A.z}
  82. assert A.x.system == A
  83. assert A.x.diff(A.x) == 1
  84. B = A.orient_new_axis('B', q, A.k)
  85. assert B.scalar_map(A) == {B.z: A.z, B.y: -A.x*sin(q) + A.y*cos(q),
  86. B.x: A.x*cos(q) + A.y*sin(q)}
  87. assert A.scalar_map(B) == {A.x: B.x*cos(q) - B.y*sin(q),
  88. A.y: B.x*sin(q) + B.y*cos(q), A.z: B.z}
  89. assert express(B.x, A, variables=True) == A.x*cos(q) + A.y*sin(q)
  90. assert express(B.y, A, variables=True) == -A.x*sin(q) + A.y*cos(q)
  91. assert express(B.z, A, variables=True) == A.z
  92. assert expand(express(B.x*B.y*B.z, A, variables=True)) == \
  93. expand(A.z*(-A.x*sin(q) + A.y*cos(q))*(A.x*cos(q) + A.y*sin(q)))
  94. assert express(B.x*B.i + B.y*B.j + B.z*B.k, A) == \
  95. (B.x*cos(q) - B.y*sin(q))*A.i + (B.x*sin(q) + \
  96. B.y*cos(q))*A.j + B.z*A.k
  97. assert simplify(express(B.x*B.i + B.y*B.j + B.z*B.k, A, \
  98. variables=True)) == \
  99. A.x*A.i + A.y*A.j + A.z*A.k
  100. assert express(A.x*A.i + A.y*A.j + A.z*A.k, B) == \
  101. (A.x*cos(q) + A.y*sin(q))*B.i + \
  102. (-A.x*sin(q) + A.y*cos(q))*B.j + A.z*B.k
  103. assert simplify(express(A.x*A.i + A.y*A.j + A.z*A.k, B, \
  104. variables=True)) == \
  105. B.x*B.i + B.y*B.j + B.z*B.k
  106. N = B.orient_new_axis('N', -q, B.k)
  107. assert N.scalar_map(A) == \
  108. {N.x: A.x, N.z: A.z, N.y: A.y}
  109. C = A.orient_new_axis('C', q, A.i + A.j + A.k)
  110. mapping = A.scalar_map(C)
  111. assert mapping[A.x].equals(C.x*(2*cos(q) + 1)/3 +
  112. C.y*(-2*sin(q + pi/6) + 1)/3 +
  113. C.z*(-2*cos(q + pi/3) + 1)/3)
  114. assert mapping[A.y].equals(C.x*(-2*cos(q + pi/3) + 1)/3 +
  115. C.y*(2*cos(q) + 1)/3 +
  116. C.z*(-2*sin(q + pi/6) + 1)/3)
  117. assert mapping[A.z].equals(C.x*(-2*sin(q + pi/6) + 1)/3 +
  118. C.y*(-2*cos(q + pi/3) + 1)/3 +
  119. C.z*(2*cos(q) + 1)/3)
  120. D = A.locate_new('D', a*A.i + b*A.j + c*A.k)
  121. assert D.scalar_map(A) == {D.z: A.z - c, D.x: A.x - a, D.y: A.y - b}
  122. E = A.orient_new_axis('E', a, A.k, a*A.i + b*A.j + c*A.k)
  123. assert A.scalar_map(E) == {A.z: E.z + c,
  124. A.x: E.x*cos(a) - E.y*sin(a) + a,
  125. A.y: E.x*sin(a) + E.y*cos(a) + b}
  126. assert E.scalar_map(A) == {E.x: (A.x - a)*cos(a) + (A.y - b)*sin(a),
  127. E.y: (-A.x + a)*sin(a) + (A.y - b)*cos(a),
  128. E.z: A.z - c}
  129. F = A.locate_new('F', Vector.zero)
  130. assert A.scalar_map(F) == {A.z: F.z, A.x: F.x, A.y: F.y}
  131. def test_rotation_matrix():
  132. N = CoordSys3D('N')
  133. A = N.orient_new_axis('A', q1, N.k)
  134. B = A.orient_new_axis('B', q2, A.i)
  135. C = B.orient_new_axis('C', q3, B.j)
  136. D = N.orient_new_axis('D', q4, N.j)
  137. E = N.orient_new_space('E', q1, q2, q3, '123')
  138. F = N.orient_new_quaternion('F', q1, q2, q3, q4)
  139. G = N.orient_new_body('G', q1, q2, q3, '123')
  140. assert N.rotation_matrix(C) == Matrix([
  141. [- sin(q1) * sin(q2) * sin(q3) + cos(q1) * cos(q3), - sin(q1) *
  142. cos(q2), sin(q1) * sin(q2) * cos(q3) + sin(q3) * cos(q1)], \
  143. [sin(q1) * cos(q3) + sin(q2) * sin(q3) * cos(q1), \
  144. cos(q1) * cos(q2), sin(q1) * sin(q3) - sin(q2) * cos(q1) * \
  145. cos(q3)], [- sin(q3) * cos(q2), sin(q2), cos(q2) * cos(q3)]])
  146. test_mat = D.rotation_matrix(C) - Matrix(
  147. [[cos(q1) * cos(q3) * cos(q4) - sin(q3) * (- sin(q4) * cos(q2) +
  148. sin(q1) * sin(q2) * cos(q4)), - sin(q2) * sin(q4) - sin(q1) *
  149. cos(q2) * cos(q4), sin(q3) * cos(q1) * cos(q4) + cos(q3) * \
  150. (- sin(q4) * cos(q2) + sin(q1) * sin(q2) * cos(q4))], \
  151. [sin(q1) * cos(q3) + sin(q2) * sin(q3) * cos(q1), cos(q1) * \
  152. cos(q2), sin(q1) * sin(q3) - sin(q2) * cos(q1) * cos(q3)], \
  153. [sin(q4) * cos(q1) * cos(q3) - sin(q3) * (cos(q2) * cos(q4) + \
  154. sin(q1) * sin(q2) * \
  155. sin(q4)), sin(q2) *
  156. cos(q4) - sin(q1) * sin(q4) * cos(q2), sin(q3) * \
  157. sin(q4) * cos(q1) + cos(q3) * (cos(q2) * cos(q4) + \
  158. sin(q1) * sin(q2) * sin(q4))]])
  159. assert test_mat.expand() == zeros(3, 3)
  160. assert E.rotation_matrix(N) == Matrix(
  161. [[cos(q2)*cos(q3), sin(q3)*cos(q2), -sin(q2)],
  162. [sin(q1)*sin(q2)*cos(q3) - sin(q3)*cos(q1), \
  163. sin(q1)*sin(q2)*sin(q3) + cos(q1)*cos(q3), sin(q1)*cos(q2)], \
  164. [sin(q1)*sin(q3) + sin(q2)*cos(q1)*cos(q3), - \
  165. sin(q1)*cos(q3) + sin(q2)*sin(q3)*cos(q1), cos(q1)*cos(q2)]])
  166. assert F.rotation_matrix(N) == Matrix([[
  167. q1**2 + q2**2 - q3**2 - q4**2,
  168. 2*q1*q4 + 2*q2*q3, -2*q1*q3 + 2*q2*q4],[ -2*q1*q4 + 2*q2*q3,
  169. q1**2 - q2**2 + q3**2 - q4**2, 2*q1*q2 + 2*q3*q4],
  170. [2*q1*q3 + 2*q2*q4,
  171. -2*q1*q2 + 2*q3*q4,
  172. q1**2 - q2**2 - q3**2 + q4**2]])
  173. assert G.rotation_matrix(N) == Matrix([[
  174. cos(q2)*cos(q3), sin(q1)*sin(q2)*cos(q3) + sin(q3)*cos(q1),
  175. sin(q1)*sin(q3) - sin(q2)*cos(q1)*cos(q3)], [
  176. -sin(q3)*cos(q2), -sin(q1)*sin(q2)*sin(q3) + cos(q1)*cos(q3),
  177. sin(q1)*cos(q3) + sin(q2)*sin(q3)*cos(q1)],[
  178. sin(q2), -sin(q1)*cos(q2), cos(q1)*cos(q2)]])
  179. def test_vector_with_orientation():
  180. """
  181. Tests the effects of orientation of coordinate systems on
  182. basic vector operations.
  183. """
  184. N = CoordSys3D('N')
  185. A = N.orient_new_axis('A', q1, N.k)
  186. B = A.orient_new_axis('B', q2, A.i)
  187. C = B.orient_new_axis('C', q3, B.j)
  188. # Test to_matrix
  189. v1 = a*N.i + b*N.j + c*N.k
  190. assert v1.to_matrix(A) == Matrix([[ a*cos(q1) + b*sin(q1)],
  191. [-a*sin(q1) + b*cos(q1)],
  192. [ c]])
  193. # Test dot
  194. assert N.i.dot(A.i) == cos(q1)
  195. assert N.i.dot(A.j) == -sin(q1)
  196. assert N.i.dot(A.k) == 0
  197. assert N.j.dot(A.i) == sin(q1)
  198. assert N.j.dot(A.j) == cos(q1)
  199. assert N.j.dot(A.k) == 0
  200. assert N.k.dot(A.i) == 0
  201. assert N.k.dot(A.j) == 0
  202. assert N.k.dot(A.k) == 1
  203. assert N.i.dot(A.i + A.j) == -sin(q1) + cos(q1) == \
  204. (A.i + A.j).dot(N.i)
  205. assert A.i.dot(C.i) == cos(q3)
  206. assert A.i.dot(C.j) == 0
  207. assert A.i.dot(C.k) == sin(q3)
  208. assert A.j.dot(C.i) == sin(q2)*sin(q3)
  209. assert A.j.dot(C.j) == cos(q2)
  210. assert A.j.dot(C.k) == -sin(q2)*cos(q3)
  211. assert A.k.dot(C.i) == -cos(q2)*sin(q3)
  212. assert A.k.dot(C.j) == sin(q2)
  213. assert A.k.dot(C.k) == cos(q2)*cos(q3)
  214. # Test cross
  215. assert N.i.cross(A.i) == sin(q1)*A.k
  216. assert N.i.cross(A.j) == cos(q1)*A.k
  217. assert N.i.cross(A.k) == -sin(q1)*A.i - cos(q1)*A.j
  218. assert N.j.cross(A.i) == -cos(q1)*A.k
  219. assert N.j.cross(A.j) == sin(q1)*A.k
  220. assert N.j.cross(A.k) == cos(q1)*A.i - sin(q1)*A.j
  221. assert N.k.cross(A.i) == A.j
  222. assert N.k.cross(A.j) == -A.i
  223. assert N.k.cross(A.k) == Vector.zero
  224. assert N.i.cross(A.i) == sin(q1)*A.k
  225. assert N.i.cross(A.j) == cos(q1)*A.k
  226. assert N.i.cross(A.i + A.j) == sin(q1)*A.k + cos(q1)*A.k
  227. assert (A.i + A.j).cross(N.i) == (-sin(q1) - cos(q1))*N.k
  228. assert A.i.cross(C.i) == sin(q3)*C.j
  229. assert A.i.cross(C.j) == -sin(q3)*C.i + cos(q3)*C.k
  230. assert A.i.cross(C.k) == -cos(q3)*C.j
  231. assert C.i.cross(A.i) == (-sin(q3)*cos(q2))*A.j + \
  232. (-sin(q2)*sin(q3))*A.k
  233. assert C.j.cross(A.i) == (sin(q2))*A.j + (-cos(q2))*A.k
  234. assert express(C.k.cross(A.i), C).trigsimp() == cos(q3)*C.j
  235. def test_orient_new_methods():
  236. N = CoordSys3D('N')
  237. orienter1 = AxisOrienter(q4, N.j)
  238. orienter2 = SpaceOrienter(q1, q2, q3, '123')
  239. orienter3 = QuaternionOrienter(q1, q2, q3, q4)
  240. orienter4 = BodyOrienter(q1, q2, q3, '123')
  241. D = N.orient_new('D', (orienter1, ))
  242. E = N.orient_new('E', (orienter2, ))
  243. F = N.orient_new('F', (orienter3, ))
  244. G = N.orient_new('G', (orienter4, ))
  245. assert D == N.orient_new_axis('D', q4, N.j)
  246. assert E == N.orient_new_space('E', q1, q2, q3, '123')
  247. assert F == N.orient_new_quaternion('F', q1, q2, q3, q4)
  248. assert G == N.orient_new_body('G', q1, q2, q3, '123')
  249. def test_locatenew_point():
  250. """
  251. Tests Point class, and locate_new method in CoordSys3D.
  252. """
  253. A = CoordSys3D('A')
  254. assert isinstance(A.origin, Point)
  255. v = a*A.i + b*A.j + c*A.k
  256. C = A.locate_new('C', v)
  257. assert C.origin.position_wrt(A) == \
  258. C.position_wrt(A) == \
  259. C.origin.position_wrt(A.origin) == v
  260. assert A.origin.position_wrt(C) == \
  261. A.position_wrt(C) == \
  262. A.origin.position_wrt(C.origin) == -v
  263. assert A.origin.express_coordinates(C) == (-a, -b, -c)
  264. p = A.origin.locate_new('p', -v)
  265. assert p.express_coordinates(A) == (-a, -b, -c)
  266. assert p.position_wrt(C.origin) == p.position_wrt(C) == \
  267. -2 * v
  268. p1 = p.locate_new('p1', 2*v)
  269. assert p1.position_wrt(C.origin) == Vector.zero
  270. assert p1.express_coordinates(C) == (0, 0, 0)
  271. p2 = p.locate_new('p2', A.i)
  272. assert p1.position_wrt(p2) == 2*v - A.i
  273. assert p2.express_coordinates(C) == (-2*a + 1, -2*b, -2*c)
  274. def test_create_new():
  275. a = CoordSys3D('a')
  276. c = a.create_new('c', transformation='spherical')
  277. assert c._parent == a
  278. assert c.transformation_to_parent() == \
  279. (c.r*sin(c.theta)*cos(c.phi), c.r*sin(c.theta)*sin(c.phi), c.r*cos(c.theta))
  280. assert c.transformation_from_parent() == \
  281. (sqrt(a.x**2 + a.y**2 + a.z**2), acos(a.z/sqrt(a.x**2 + a.y**2 + a.z**2)), atan2(a.y, a.x))
  282. def test_evalf():
  283. A = CoordSys3D('A')
  284. v = 3*A.i + 4*A.j + a*A.k
  285. assert v.n() == v.evalf()
  286. assert v.evalf(subs={a:1}) == v.subs(a, 1).evalf()
  287. def test_lame_coefficients():
  288. a = CoordSys3D('a', 'spherical')
  289. assert a.lame_coefficients() == (1, a.r, sin(a.theta)*a.r)
  290. a = CoordSys3D('a')
  291. assert a.lame_coefficients() == (1, 1, 1)
  292. a = CoordSys3D('a', 'cartesian')
  293. assert a.lame_coefficients() == (1, 1, 1)
  294. a = CoordSys3D('a', 'cylindrical')
  295. assert a.lame_coefficients() == (1, a.r, 1)
  296. def test_transformation_equations():
  297. x, y, z = symbols('x y z')
  298. # Str
  299. a = CoordSys3D('a', transformation='spherical',
  300. variable_names=["r", "theta", "phi"])
  301. r, theta, phi = a.base_scalars()
  302. assert r == a.r
  303. assert theta == a.theta
  304. assert phi == a.phi
  305. raises(AttributeError, lambda: a.x)
  306. raises(AttributeError, lambda: a.y)
  307. raises(AttributeError, lambda: a.z)
  308. assert a.transformation_to_parent() == (
  309. r*sin(theta)*cos(phi),
  310. r*sin(theta)*sin(phi),
  311. r*cos(theta)
  312. )
  313. assert a.lame_coefficients() == (1, r, r*sin(theta))
  314. assert a.transformation_from_parent_function()(x, y, z) == (
  315. sqrt(x ** 2 + y ** 2 + z ** 2),
  316. acos((z) / sqrt(x**2 + y**2 + z**2)),
  317. atan2(y, x)
  318. )
  319. a = CoordSys3D('a', transformation='cylindrical',
  320. variable_names=["r", "theta", "z"])
  321. r, theta, z = a.base_scalars()
  322. assert a.transformation_to_parent() == (
  323. r*cos(theta),
  324. r*sin(theta),
  325. z
  326. )
  327. assert a.lame_coefficients() == (1, a.r, 1)
  328. assert a.transformation_from_parent_function()(x, y, z) == (sqrt(x**2 + y**2),
  329. atan2(y, x), z)
  330. a = CoordSys3D('a', 'cartesian')
  331. assert a.transformation_to_parent() == (a.x, a.y, a.z)
  332. assert a.lame_coefficients() == (1, 1, 1)
  333. assert a.transformation_from_parent_function()(x, y, z) == (x, y, z)
  334. # Variables and expressions
  335. # Cartesian with equation tuple:
  336. x, y, z = symbols('x y z')
  337. a = CoordSys3D('a', ((x, y, z), (x, y, z)))
  338. a._calculate_inv_trans_equations()
  339. assert a.transformation_to_parent() == (a.x1, a.x2, a.x3)
  340. assert a.lame_coefficients() == (1, 1, 1)
  341. assert a.transformation_from_parent_function()(x, y, z) == (x, y, z)
  342. r, theta, z = symbols("r theta z")
  343. # Cylindrical with equation tuple:
  344. a = CoordSys3D('a', [(r, theta, z), (r*cos(theta), r*sin(theta), z)],
  345. variable_names=["r", "theta", "z"])
  346. r, theta, z = a.base_scalars()
  347. assert a.transformation_to_parent() == (
  348. r*cos(theta), r*sin(theta), z
  349. )
  350. assert a.lame_coefficients() == (
  351. sqrt(sin(theta)**2 + cos(theta)**2),
  352. sqrt(r**2*sin(theta)**2 + r**2*cos(theta)**2),
  353. 1
  354. ) # ==> this should simplify to (1, r, 1), tests are too slow with `simplify`.
  355. # Definitions with `lambda`:
  356. # Cartesian with `lambda`
  357. a = CoordSys3D('a', lambda x, y, z: (x, y, z))
  358. assert a.transformation_to_parent() == (a.x1, a.x2, a.x3)
  359. assert a.lame_coefficients() == (1, 1, 1)
  360. a._calculate_inv_trans_equations()
  361. assert a.transformation_from_parent_function()(x, y, z) == (x, y, z)
  362. # Spherical with `lambda`
  363. a = CoordSys3D('a', lambda r, theta, phi: (r*sin(theta)*cos(phi), r*sin(theta)*sin(phi), r*cos(theta)),
  364. variable_names=["r", "theta", "phi"])
  365. r, theta, phi = a.base_scalars()
  366. assert a.transformation_to_parent() == (
  367. r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta)
  368. )
  369. assert a.lame_coefficients() == (
  370. sqrt(sin(phi)**2*sin(theta)**2 + sin(theta)**2*cos(phi)**2 + cos(theta)**2),
  371. sqrt(r**2*sin(phi)**2*cos(theta)**2 + r**2*sin(theta)**2 + r**2*cos(phi)**2*cos(theta)**2),
  372. sqrt(r**2*sin(phi)**2*sin(theta)**2 + r**2*sin(theta)**2*cos(phi)**2)
  373. ) # ==> this should simplify to (1, r, sin(theta)*r), `simplify` is too slow.
  374. # Cylindrical with `lambda`
  375. a = CoordSys3D('a', lambda r, theta, z:
  376. (r*cos(theta), r*sin(theta), z),
  377. variable_names=["r", "theta", "z"]
  378. )
  379. r, theta, z = a.base_scalars()
  380. assert a.transformation_to_parent() == (r*cos(theta), r*sin(theta), z)
  381. assert a.lame_coefficients() == (
  382. sqrt(sin(theta)**2 + cos(theta)**2),
  383. sqrt(r**2*sin(theta)**2 + r**2*cos(theta)**2),
  384. 1
  385. ) # ==> this should simplify to (1, a.x, 1)
  386. raises(TypeError, lambda: CoordSys3D('a', transformation={
  387. x: x*sin(y)*cos(z), y:x*sin(y)*sin(z), z: x*cos(y)}))
  388. def test_check_orthogonality():
  389. x, y, z = symbols('x y z')
  390. u,v = symbols('u, v')
  391. a = CoordSys3D('a', transformation=((x, y, z), (x*sin(y)*cos(z), x*sin(y)*sin(z), x*cos(y))))
  392. assert a._check_orthogonality(a._transformation) is True
  393. a = CoordSys3D('a', transformation=((x, y, z), (x * cos(y), x * sin(y), z)))
  394. assert a._check_orthogonality(a._transformation) is True
  395. a = CoordSys3D('a', transformation=((u, v, z), (cosh(u) * cos(v), sinh(u) * sin(v), z)))
  396. assert a._check_orthogonality(a._transformation) is True
  397. raises(ValueError, lambda: CoordSys3D('a', transformation=((x, y, z), (x, x, z))))
  398. raises(ValueError, lambda: CoordSys3D('a', transformation=(
  399. (x, y, z), (x*sin(y/2)*cos(z), x*sin(y)*sin(z), x*cos(y)))))
  400. def test_rotation_trans_equations():
  401. a = CoordSys3D('a')
  402. from sympy.core.symbol import symbols
  403. q0 = symbols('q0')
  404. assert a._rotation_trans_equations(a._parent_rotation_matrix, a.base_scalars()) == (a.x, a.y, a.z)
  405. assert a._rotation_trans_equations(a._inverse_rotation_matrix(), a.base_scalars()) == (a.x, a.y, a.z)
  406. b = a.orient_new_axis('b', 0, -a.k)
  407. assert b._rotation_trans_equations(b._parent_rotation_matrix, b.base_scalars()) == (b.x, b.y, b.z)
  408. assert b._rotation_trans_equations(b._inverse_rotation_matrix(), b.base_scalars()) == (b.x, b.y, b.z)
  409. c = a.orient_new_axis('c', q0, -a.k)
  410. assert c._rotation_trans_equations(c._parent_rotation_matrix, c.base_scalars()) == \
  411. (-sin(q0) * c.y + cos(q0) * c.x, sin(q0) * c.x + cos(q0) * c.y, c.z)
  412. assert c._rotation_trans_equations(c._inverse_rotation_matrix(), c.base_scalars()) == \
  413. (sin(q0) * c.y + cos(q0) * c.x, -sin(q0) * c.x + cos(q0) * c.y, c.z)