I am done

This commit is contained in:
2024-10-30 22:14:35 +01:00
parent 720dc28c09
commit 40e2a747cf
36901 changed files with 5011519 additions and 0 deletions

View File

@ -0,0 +1,123 @@
from sympy.core.numbers import (Float, pi)
from sympy.core.symbol import symbols
from sympy.functions.elementary.trigonometric import (cos, sin)
from sympy.matrices.immutable import ImmutableDenseMatrix as Matrix
from sympy.physics.vector import ReferenceFrame, dynamicsymbols, outer
from sympy.physics.vector.dyadic import _check_dyadic
from sympy.testing.pytest import raises
A = ReferenceFrame('A')
def test_dyadic():
d1 = A.x | A.x
d2 = A.y | A.y
d3 = A.x | A.y
assert d1 * 0 == 0
assert d1 != 0
assert d1 * 2 == 2 * A.x | A.x
assert d1 / 2. == 0.5 * d1
assert d1 & (0 * d1) == 0
assert d1 & d2 == 0
assert d1 & A.x == A.x
assert d1 ^ A.x == 0
assert d1 ^ A.y == A.x | A.z
assert d1 ^ A.z == - A.x | A.y
assert d2 ^ A.x == - A.y | A.z
assert A.x ^ d1 == 0
assert A.y ^ d1 == - A.z | A.x
assert A.z ^ d1 == A.y | A.x
assert A.x & d1 == A.x
assert A.y & d1 == 0
assert A.y & d2 == A.y
assert d1 & d3 == A.x | A.y
assert d3 & d1 == 0
assert d1.dt(A) == 0
q = dynamicsymbols('q')
qd = dynamicsymbols('q', 1)
B = A.orientnew('B', 'Axis', [q, A.z])
assert d1.express(B) == d1.express(B, B)
assert d1.express(B) == ((cos(q)**2) * (B.x | B.x) + (-sin(q) * cos(q)) *
(B.x | B.y) + (-sin(q) * cos(q)) * (B.y | B.x) + (sin(q)**2) *
(B.y | B.y))
assert d1.express(B, A) == (cos(q)) * (B.x | A.x) + (-sin(q)) * (B.y | A.x)
assert d1.express(A, B) == (cos(q)) * (A.x | B.x) + (-sin(q)) * (A.x | B.y)
assert d1.dt(B) == (-qd) * (A.y | A.x) + (-qd) * (A.x | A.y)
assert d1.to_matrix(A) == Matrix([[1, 0, 0], [0, 0, 0], [0, 0, 0]])
assert d1.to_matrix(A, B) == Matrix([[cos(q), -sin(q), 0],
[0, 0, 0],
[0, 0, 0]])
assert d3.to_matrix(A) == Matrix([[0, 1, 0], [0, 0, 0], [0, 0, 0]])
a, b, c, d, e, f = symbols('a, b, c, d, e, f')
v1 = a * A.x + b * A.y + c * A.z
v2 = d * A.x + e * A.y + f * A.z
d4 = v1.outer(v2)
assert d4.to_matrix(A) == Matrix([[a * d, a * e, a * f],
[b * d, b * e, b * f],
[c * d, c * e, c * f]])
d5 = v1.outer(v1)
C = A.orientnew('C', 'Axis', [q, A.x])
for expected, actual in zip(C.dcm(A) * d5.to_matrix(A) * C.dcm(A).T,
d5.to_matrix(C)):
assert (expected - actual).simplify() == 0
raises(TypeError, lambda: d1.applyfunc(0))
def test_dyadic_simplify():
x, y, z, k, n, m, w, f, s, A = symbols('x, y, z, k, n, m, w, f, s, A')
N = ReferenceFrame('N')
dy = N.x | N.x
test1 = (1 / x + 1 / y) * dy
assert (N.x & test1 & N.x) != (x + y) / (x * y)
test1 = test1.simplify()
assert (N.x & test1 & N.x) == (x + y) / (x * y)
test2 = (A**2 * s**4 / (4 * pi * k * m**3)) * dy
test2 = test2.simplify()
assert (N.x & test2 & N.x) == (A**2 * s**4 / (4 * pi * k * m**3))
test3 = ((4 + 4 * x - 2 * (2 + 2 * x)) / (2 + 2 * x)) * dy
test3 = test3.simplify()
assert (N.x & test3 & N.x) == 0
test4 = ((-4 * x * y**2 - 2 * y**3 - 2 * x**2 * y) / (x + y)**2) * dy
test4 = test4.simplify()
assert (N.x & test4 & N.x) == -2 * y
def test_dyadic_subs():
N = ReferenceFrame('N')
s = symbols('s')
a = s*(N.x | N.x)
assert a.subs({s: 2}) == 2*(N.x | N.x)
def test_check_dyadic():
raises(TypeError, lambda: _check_dyadic(0))
def test_dyadic_evalf():
N = ReferenceFrame('N')
a = pi * (N.x | N.x)
assert a.evalf(3) == Float('3.1416', 3) * (N.x | N.x)
s = symbols('s')
a = 5 * s * pi* (N.x | N.x)
assert a.evalf(2) == Float('5', 2) * Float('3.1416', 2) * s * (N.x | N.x)
assert a.evalf(9, subs={s: 5.124}) == Float('80.48760378', 9) * (N.x | N.x)
def test_dyadic_xreplace():
x, y, z = symbols('x y z')
N = ReferenceFrame('N')
D = outer(N.x, N.x)
v = x*y * D
assert v.xreplace({x : cos(x)}) == cos(x)*y * D
assert v.xreplace({x*y : pi}) == pi * D
v = (x*y)**z * D
assert v.xreplace({(x*y)**z : 1}) == D
assert v.xreplace({x:1, z:0}) == D
raises(TypeError, lambda: v.xreplace())
raises(TypeError, lambda: v.xreplace([x, y]))

View File

@ -0,0 +1,133 @@
from sympy.core.singleton import S
from sympy.core.symbol import Symbol
from sympy.functions.elementary.trigonometric import (cos, sin)
from sympy.physics.vector import ReferenceFrame, Vector, Point, \
dynamicsymbols
from sympy.physics.vector.fieldfunctions import divergence, \
gradient, curl, is_conservative, is_solenoidal, \
scalar_potential, scalar_potential_difference
from sympy.testing.pytest import raises
R = ReferenceFrame('R')
q = dynamicsymbols('q')
P = R.orientnew('P', 'Axis', [q, R.z])
def test_curl():
assert curl(Vector(0), R) == Vector(0)
assert curl(R.x, R) == Vector(0)
assert curl(2*R[1]**2*R.y, R) == Vector(0)
assert curl(R[0]*R[1]*R.z, R) == R[0]*R.x - R[1]*R.y
assert curl(R[0]*R[1]*R[2] * (R.x+R.y+R.z), R) == \
(-R[0]*R[1] + R[0]*R[2])*R.x + (R[0]*R[1] - R[1]*R[2])*R.y + \
(-R[0]*R[2] + R[1]*R[2])*R.z
assert curl(2*R[0]**2*R.y, R) == 4*R[0]*R.z
assert curl(P[0]**2*R.x + P.y, R) == \
- 2*(R[0]*cos(q) + R[1]*sin(q))*sin(q)*R.z
assert curl(P[0]*R.y, P) == cos(q)*P.z
def test_divergence():
assert divergence(Vector(0), R) is S.Zero
assert divergence(R.x, R) is S.Zero
assert divergence(R[0]**2*R.x, R) == 2*R[0]
assert divergence(R[0]*R[1]*R[2] * (R.x+R.y+R.z), R) == \
R[0]*R[1] + R[0]*R[2] + R[1]*R[2]
assert divergence((1/(R[0]*R[1]*R[2])) * (R.x+R.y+R.z), R) == \
-1/(R[0]*R[1]*R[2]**2) - 1/(R[0]*R[1]**2*R[2]) - \
1/(R[0]**2*R[1]*R[2])
v = P[0]*P.x + P[1]*P.y + P[2]*P.z
assert divergence(v, P) == 3
assert divergence(v, R).simplify() == 3
assert divergence(P[0]*R.x + R[0]*P.x, R) == 2*cos(q)
def test_gradient():
a = Symbol('a')
assert gradient(0, R) == Vector(0)
assert gradient(R[0], R) == R.x
assert gradient(R[0]*R[1]*R[2], R) == \
R[1]*R[2]*R.x + R[0]*R[2]*R.y + R[0]*R[1]*R.z
assert gradient(2*R[0]**2, R) == 4*R[0]*R.x
assert gradient(a*sin(R[1])/R[0], R) == \
- a*sin(R[1])/R[0]**2*R.x + a*cos(R[1])/R[0]*R.y
assert gradient(P[0]*P[1], R) == \
((-R[0]*sin(q) + R[1]*cos(q))*cos(q) - (R[0]*cos(q) + R[1]*sin(q))*sin(q))*R.x + \
((-R[0]*sin(q) + R[1]*cos(q))*sin(q) + (R[0]*cos(q) + R[1]*sin(q))*cos(q))*R.y
assert gradient(P[0]*R[2], P) == P[2]*P.x + P[0]*P.z
scalar_field = 2*R[0]**2*R[1]*R[2]
grad_field = gradient(scalar_field, R)
vector_field = R[1]**2*R.x + 3*R[0]*R.y + 5*R[1]*R[2]*R.z
curl_field = curl(vector_field, R)
def test_conservative():
assert is_conservative(0) is True
assert is_conservative(R.x) is True
assert is_conservative(2 * R.x + 3 * R.y + 4 * R.z) is True
assert is_conservative(R[1]*R[2]*R.x + R[0]*R[2]*R.y + R[0]*R[1]*R.z) is \
True
assert is_conservative(R[0] * R.y) is False
assert is_conservative(grad_field) is True
assert is_conservative(curl_field) is False
assert is_conservative(4*R[0]*R[1]*R[2]*R.x + 2*R[0]**2*R[2]*R.y) is \
False
assert is_conservative(R[2]*P.x + P[0]*R.z) is True
def test_solenoidal():
assert is_solenoidal(0) is True
assert is_solenoidal(R.x) is True
assert is_solenoidal(2 * R.x + 3 * R.y + 4 * R.z) is True
assert is_solenoidal(R[1]*R[2]*R.x + R[0]*R[2]*R.y + R[0]*R[1]*R.z) is \
True
assert is_solenoidal(R[1] * R.y) is False
assert is_solenoidal(grad_field) is False
assert is_solenoidal(curl_field) is True
assert is_solenoidal((-2*R[1] + 3)*R.z) is True
assert is_solenoidal(cos(q)*R.x + sin(q)*R.y + cos(q)*P.z) is True
assert is_solenoidal(R[2]*P.x + P[0]*R.z) is True
def test_scalar_potential():
assert scalar_potential(0, R) == 0
assert scalar_potential(R.x, R) == R[0]
assert scalar_potential(R.y, R) == R[1]
assert scalar_potential(R.z, R) == R[2]
assert scalar_potential(R[1]*R[2]*R.x + R[0]*R[2]*R.y + \
R[0]*R[1]*R.z, R) == R[0]*R[1]*R[2]
assert scalar_potential(grad_field, R) == scalar_field
assert scalar_potential(R[2]*P.x + P[0]*R.z, R) == \
R[0]*R[2]*cos(q) + R[1]*R[2]*sin(q)
assert scalar_potential(R[2]*P.x + P[0]*R.z, P) == P[0]*P[2]
raises(ValueError, lambda: scalar_potential(R[0] * R.y, R))
def test_scalar_potential_difference():
origin = Point('O')
point1 = origin.locatenew('P1', 1*R.x + 2*R.y + 3*R.z)
point2 = origin.locatenew('P2', 4*R.x + 5*R.y + 6*R.z)
genericpointR = origin.locatenew('RP', R[0]*R.x + R[1]*R.y + R[2]*R.z)
genericpointP = origin.locatenew('PP', P[0]*P.x + P[1]*P.y + P[2]*P.z)
assert scalar_potential_difference(S.Zero, R, point1, point2, \
origin) == 0
assert scalar_potential_difference(scalar_field, R, origin, \
genericpointR, origin) == \
scalar_field
assert scalar_potential_difference(grad_field, R, origin, \
genericpointR, origin) == \
scalar_field
assert scalar_potential_difference(grad_field, R, point1, point2,
origin) == 948
assert scalar_potential_difference(R[1]*R[2]*R.x + R[0]*R[2]*R.y + \
R[0]*R[1]*R.z, R, point1,
genericpointR, origin) == \
R[0]*R[1]*R[2] - 6
potential_diff_P = 2*P[2]*(P[0]*sin(q) + P[1]*cos(q))*\
(P[0]*cos(q) - P[1]*sin(q))**2
assert scalar_potential_difference(grad_field, P, origin, \
genericpointP, \
origin).simplify() == \
potential_diff_P

View File

@ -0,0 +1,761 @@
from sympy.core.numbers import pi
from sympy.core.symbol import symbols
from sympy.simplify import trigsimp
from sympy.functions.elementary.trigonometric import (cos, sin)
from sympy.matrices.dense import (eye, zeros)
from sympy.matrices.immutable import ImmutableDenseMatrix as Matrix
from sympy.simplify.simplify import simplify
from sympy.physics.vector import (ReferenceFrame, Vector, CoordinateSym,
dynamicsymbols, time_derivative, express,
dot)
from sympy.physics.vector.frame import _check_frame
from sympy.physics.vector.vector import VectorTypeError
from sympy.testing.pytest import raises
import warnings
import pickle
def test_dict_list():
A = ReferenceFrame('A')
B = ReferenceFrame('B')
C = ReferenceFrame('C')
D = ReferenceFrame('D')
E = ReferenceFrame('E')
F = ReferenceFrame('F')
B.orient_axis(A, A.x, 1.0)
C.orient_axis(B, B.x, 1.0)
D.orient_axis(C, C.x, 1.0)
assert D._dict_list(A, 0) == [D, C, B, A]
E.orient_axis(D, D.x, 1.0)
assert C._dict_list(A, 0) == [C, B, A]
assert C._dict_list(E, 0) == [C, D, E]
# only 0, 1, 2 permitted for second argument
raises(ValueError, lambda: C._dict_list(E, 5))
# no connecting path
raises(ValueError, lambda: F._dict_list(A, 0))
def test_coordinate_vars():
"""Tests the coordinate variables functionality"""
A = ReferenceFrame('A')
assert CoordinateSym('Ax', A, 0) == A[0]
assert CoordinateSym('Ax', A, 1) == A[1]
assert CoordinateSym('Ax', A, 2) == A[2]
raises(ValueError, lambda: CoordinateSym('Ax', A, 3))
q = dynamicsymbols('q')
qd = dynamicsymbols('q', 1)
assert isinstance(A[0], CoordinateSym) and \
isinstance(A[0], CoordinateSym) and \
isinstance(A[0], CoordinateSym)
assert A.variable_map(A) == {A[0]:A[0], A[1]:A[1], A[2]:A[2]}
assert A[0].frame == A
B = A.orientnew('B', 'Axis', [q, A.z])
assert B.variable_map(A) == {B[2]: A[2], B[1]: -A[0]*sin(q) + A[1]*cos(q),
B[0]: A[0]*cos(q) + A[1]*sin(q)}
assert A.variable_map(B) == {A[0]: B[0]*cos(q) - B[1]*sin(q),
A[1]: B[0]*sin(q) + B[1]*cos(q), A[2]: B[2]}
assert time_derivative(B[0], A) == -A[0]*sin(q)*qd + A[1]*cos(q)*qd
assert time_derivative(B[1], A) == -A[0]*cos(q)*qd - A[1]*sin(q)*qd
assert time_derivative(B[2], A) == 0
assert express(B[0], A, variables=True) == A[0]*cos(q) + A[1]*sin(q)
assert express(B[1], A, variables=True) == -A[0]*sin(q) + A[1]*cos(q)
assert express(B[2], A, variables=True) == A[2]
assert time_derivative(A[0]*A.x + A[1]*A.y + A[2]*A.z, B) == A[1]*qd*A.x - A[0]*qd*A.y
assert time_derivative(B[0]*B.x + B[1]*B.y + B[2]*B.z, A) == - B[1]*qd*B.x + B[0]*qd*B.y
assert express(B[0]*B[1]*B[2], A, variables=True) == \
A[2]*(-A[0]*sin(q) + A[1]*cos(q))*(A[0]*cos(q) + A[1]*sin(q))
assert (time_derivative(B[0]*B[1]*B[2], A) -
(A[2]*(-A[0]**2*cos(2*q) -
2*A[0]*A[1]*sin(2*q) +
A[1]**2*cos(2*q))*qd)).trigsimp() == 0
assert express(B[0]*B.x + B[1]*B.y + B[2]*B.z, A) == \
(B[0]*cos(q) - B[1]*sin(q))*A.x + (B[0]*sin(q) + \
B[1]*cos(q))*A.y + B[2]*A.z
assert express(B[0]*B.x + B[1]*B.y + B[2]*B.z, A,
variables=True).simplify() == A[0]*A.x + A[1]*A.y + A[2]*A.z
assert express(A[0]*A.x + A[1]*A.y + A[2]*A.z, B) == \
(A[0]*cos(q) + A[1]*sin(q))*B.x + \
(-A[0]*sin(q) + A[1]*cos(q))*B.y + A[2]*B.z
assert express(A[0]*A.x + A[1]*A.y + A[2]*A.z, B,
variables=True).simplify() == B[0]*B.x + B[1]*B.y + B[2]*B.z
N = B.orientnew('N', 'Axis', [-q, B.z])
assert ({k: v.simplify() for k, v in N.variable_map(A).items()} ==
{N[0]: A[0], N[2]: A[2], N[1]: A[1]})
C = A.orientnew('C', 'Axis', [q, A.x + A.y + A.z])
mapping = A.variable_map(C)
assert trigsimp(mapping[A[0]]) == (2*C[0]*cos(q)/3 + C[0]/3 -
2*C[1]*sin(q + pi/6)/3 +
C[1]/3 - 2*C[2]*cos(q + pi/3)/3 +
C[2]/3)
assert trigsimp(mapping[A[1]]) == -2*C[0]*cos(q + pi/3)/3 + \
C[0]/3 + 2*C[1]*cos(q)/3 + C[1]/3 - 2*C[2]*sin(q + pi/6)/3 + C[2]/3
assert trigsimp(mapping[A[2]]) == -2*C[0]*sin(q + pi/6)/3 + C[0]/3 - \
2*C[1]*cos(q + pi/3)/3 + C[1]/3 + 2*C[2]*cos(q)/3 + C[2]/3
def test_ang_vel():
q1, q2, q3, q4 = dynamicsymbols('q1 q2 q3 q4')
q1d, q2d, q3d, q4d = dynamicsymbols('q1 q2 q3 q4', 1)
N = ReferenceFrame('N')
A = N.orientnew('A', 'Axis', [q1, N.z])
B = A.orientnew('B', 'Axis', [q2, A.x])
C = B.orientnew('C', 'Axis', [q3, B.y])
D = N.orientnew('D', 'Axis', [q4, N.y])
u1, u2, u3 = dynamicsymbols('u1 u2 u3')
assert A.ang_vel_in(N) == (q1d)*A.z
assert B.ang_vel_in(N) == (q2d)*B.x + (q1d)*A.z
assert C.ang_vel_in(N) == (q3d)*C.y + (q2d)*B.x + (q1d)*A.z
A2 = N.orientnew('A2', 'Axis', [q4, N.y])
assert N.ang_vel_in(N) == 0
assert N.ang_vel_in(A) == -q1d*N.z
assert N.ang_vel_in(B) == -q1d*A.z - q2d*B.x
assert N.ang_vel_in(C) == -q1d*A.z - q2d*B.x - q3d*B.y
assert N.ang_vel_in(A2) == -q4d*N.y
assert A.ang_vel_in(N) == q1d*N.z
assert A.ang_vel_in(A) == 0
assert A.ang_vel_in(B) == - q2d*B.x
assert A.ang_vel_in(C) == - q2d*B.x - q3d*B.y
assert A.ang_vel_in(A2) == q1d*N.z - q4d*N.y
assert B.ang_vel_in(N) == q1d*A.z + q2d*A.x
assert B.ang_vel_in(A) == q2d*A.x
assert B.ang_vel_in(B) == 0
assert B.ang_vel_in(C) == -q3d*B.y
assert B.ang_vel_in(A2) == q1d*A.z + q2d*A.x - q4d*N.y
assert C.ang_vel_in(N) == q1d*A.z + q2d*A.x + q3d*B.y
assert C.ang_vel_in(A) == q2d*A.x + q3d*C.y
assert C.ang_vel_in(B) == q3d*B.y
assert C.ang_vel_in(C) == 0
assert C.ang_vel_in(A2) == q1d*A.z + q2d*A.x + q3d*B.y - q4d*N.y
assert A2.ang_vel_in(N) == q4d*A2.y
assert A2.ang_vel_in(A) == q4d*A2.y - q1d*N.z
assert A2.ang_vel_in(B) == q4d*N.y - q1d*A.z - q2d*A.x
assert A2.ang_vel_in(C) == q4d*N.y - q1d*A.z - q2d*A.x - q3d*B.y
assert A2.ang_vel_in(A2) == 0
C.set_ang_vel(N, u1*C.x + u2*C.y + u3*C.z)
assert C.ang_vel_in(N) == (u1)*C.x + (u2)*C.y + (u3)*C.z
assert N.ang_vel_in(C) == (-u1)*C.x + (-u2)*C.y + (-u3)*C.z
assert C.ang_vel_in(D) == (u1)*C.x + (u2)*C.y + (u3)*C.z + (-q4d)*D.y
assert D.ang_vel_in(C) == (-u1)*C.x + (-u2)*C.y + (-u3)*C.z + (q4d)*D.y
q0 = dynamicsymbols('q0')
q0d = dynamicsymbols('q0', 1)
E = N.orientnew('E', 'Quaternion', (q0, q1, q2, q3))
assert E.ang_vel_in(N) == (
2 * (q1d * q0 + q2d * q3 - q3d * q2 - q0d * q1) * E.x +
2 * (q2d * q0 + q3d * q1 - q1d * q3 - q0d * q2) * E.y +
2 * (q3d * q0 + q1d * q2 - q2d * q1 - q0d * q3) * E.z)
F = N.orientnew('F', 'Body', (q1, q2, q3), 313)
assert F.ang_vel_in(N) == ((sin(q2)*sin(q3)*q1d + cos(q3)*q2d)*F.x +
(sin(q2)*cos(q3)*q1d - sin(q3)*q2d)*F.y + (cos(q2)*q1d + q3d)*F.z)
G = N.orientnew('G', 'Axis', (q1, N.x + N.y))
assert G.ang_vel_in(N) == q1d * (N.x + N.y).normalize()
assert N.ang_vel_in(G) == -q1d * (N.x + N.y).normalize()
def test_dcm():
q1, q2, q3, q4 = dynamicsymbols('q1 q2 q3 q4')
N = ReferenceFrame('N')
A = N.orientnew('A', 'Axis', [q1, N.z])
B = A.orientnew('B', 'Axis', [q2, A.x])
C = B.orientnew('C', 'Axis', [q3, B.y])
D = N.orientnew('D', 'Axis', [q4, N.y])
E = N.orientnew('E', 'Space', [q1, q2, q3], '123')
assert N.dcm(C) == Matrix([
[- sin(q1) * sin(q2) * sin(q3) + cos(q1) * cos(q3), - sin(q1) *
cos(q2), sin(q1) * sin(q2) * cos(q3) + sin(q3) * cos(q1)], [sin(q1) *
cos(q3) + sin(q2) * sin(q3) * cos(q1), cos(q1) * cos(q2), sin(q1) *
sin(q3) - sin(q2) * cos(q1) * cos(q3)], [- sin(q3) * cos(q2), sin(q2),
cos(q2) * cos(q3)]])
# This is a little touchy. Is it ok to use simplify in assert?
test_mat = D.dcm(C) - Matrix(
[[cos(q1) * cos(q3) * cos(q4) - sin(q3) * (- sin(q4) * cos(q2) +
sin(q1) * sin(q2) * cos(q4)), - sin(q2) * sin(q4) - sin(q1) *
cos(q2) * cos(q4), sin(q3) * cos(q1) * cos(q4) + cos(q3) * (- sin(q4) *
cos(q2) + sin(q1) * sin(q2) * cos(q4))], [sin(q1) * cos(q3) +
sin(q2) * sin(q3) * cos(q1), cos(q1) * cos(q2), sin(q1) * sin(q3) -
sin(q2) * cos(q1) * cos(q3)], [sin(q4) * cos(q1) * cos(q3) -
sin(q3) * (cos(q2) * cos(q4) + sin(q1) * sin(q2) * sin(q4)), sin(q2) *
cos(q4) - sin(q1) * sin(q4) * cos(q2), sin(q3) * sin(q4) * cos(q1) +
cos(q3) * (cos(q2) * cos(q4) + sin(q1) * sin(q2) * sin(q4))]])
assert test_mat.expand() == zeros(3, 3)
assert E.dcm(N) == Matrix(
[[cos(q2)*cos(q3), sin(q3)*cos(q2), -sin(q2)],
[sin(q1)*sin(q2)*cos(q3) - sin(q3)*cos(q1), sin(q1)*sin(q2)*sin(q3) +
cos(q1)*cos(q3), sin(q1)*cos(q2)], [sin(q1)*sin(q3) +
sin(q2)*cos(q1)*cos(q3), - sin(q1)*cos(q3) + sin(q2)*sin(q3)*cos(q1),
cos(q1)*cos(q2)]])
def test_w_diff_dcm1():
# Ref:
# Dynamics Theory and Applications, Kane 1985
# Sec. 2.1 ANGULAR VELOCITY
A = ReferenceFrame('A')
B = ReferenceFrame('B')
c11, c12, c13 = dynamicsymbols('C11 C12 C13')
c21, c22, c23 = dynamicsymbols('C21 C22 C23')
c31, c32, c33 = dynamicsymbols('C31 C32 C33')
c11d, c12d, c13d = dynamicsymbols('C11 C12 C13', level=1)
c21d, c22d, c23d = dynamicsymbols('C21 C22 C23', level=1)
c31d, c32d, c33d = dynamicsymbols('C31 C32 C33', level=1)
DCM = Matrix([
[c11, c12, c13],
[c21, c22, c23],
[c31, c32, c33]
])
B.orient(A, 'DCM', DCM)
b1a = (B.x).express(A)
b2a = (B.y).express(A)
b3a = (B.z).express(A)
# Equation (2.1.1)
B.set_ang_vel(A, B.x*(dot((b3a).dt(A), B.y))
+ B.y*(dot((b1a).dt(A), B.z))
+ B.z*(dot((b2a).dt(A), B.x)))
# Equation (2.1.21)
expr = ( (c12*c13d + c22*c23d + c32*c33d)*B.x
+ (c13*c11d + c23*c21d + c33*c31d)*B.y
+ (c11*c12d + c21*c22d + c31*c32d)*B.z)
assert B.ang_vel_in(A) - expr == 0
def test_w_diff_dcm2():
q1, q2, q3 = dynamicsymbols('q1:4')
N = ReferenceFrame('N')
A = N.orientnew('A', 'axis', [q1, N.x])
B = A.orientnew('B', 'axis', [q2, A.y])
C = B.orientnew('C', 'axis', [q3, B.z])
DCM = C.dcm(N).T
D = N.orientnew('D', 'DCM', DCM)
# Frames D and C are the same ReferenceFrame,
# since they have equal DCM respect to frame N.
# Therefore, D and C should have same angle velocity in N.
assert D.dcm(N) == C.dcm(N) == Matrix([
[cos(q2)*cos(q3), sin(q1)*sin(q2)*cos(q3) +
sin(q3)*cos(q1), sin(q1)*sin(q3) -
sin(q2)*cos(q1)*cos(q3)], [-sin(q3)*cos(q2),
-sin(q1)*sin(q2)*sin(q3) + cos(q1)*cos(q3),
sin(q1)*cos(q3) + sin(q2)*sin(q3)*cos(q1)],
[sin(q2), -sin(q1)*cos(q2), cos(q1)*cos(q2)]])
assert (D.ang_vel_in(N) - C.ang_vel_in(N)).express(N).simplify() == 0
def test_orientnew_respects_parent_class():
class MyReferenceFrame(ReferenceFrame):
pass
B = MyReferenceFrame('B')
C = B.orientnew('C', 'Axis', [0, B.x])
assert isinstance(C, MyReferenceFrame)
def test_orientnew_respects_input_indices():
N = ReferenceFrame('N')
q1 = dynamicsymbols('q1')
A = N.orientnew('a', 'Axis', [q1, N.z])
#modify default indices:
minds = [x+'1' for x in N.indices]
B = N.orientnew('b', 'Axis', [q1, N.z], indices=minds)
assert N.indices == A.indices
assert B.indices == minds
def test_orientnew_respects_input_latexs():
N = ReferenceFrame('N')
q1 = dynamicsymbols('q1')
A = N.orientnew('a', 'Axis', [q1, N.z])
#build default and alternate latex_vecs:
def_latex_vecs = [(r"\mathbf{\hat{%s}_%s}" % (A.name.lower(),
A.indices[0])), (r"\mathbf{\hat{%s}_%s}" %
(A.name.lower(), A.indices[1])),
(r"\mathbf{\hat{%s}_%s}" % (A.name.lower(),
A.indices[2]))]
name = 'b'
indices = [x+'1' for x in N.indices]
new_latex_vecs = [(r"\mathbf{\hat{%s}_{%s}}" % (name.lower(),
indices[0])), (r"\mathbf{\hat{%s}_{%s}}" %
(name.lower(), indices[1])),
(r"\mathbf{\hat{%s}_{%s}}" % (name.lower(),
indices[2]))]
B = N.orientnew(name, 'Axis', [q1, N.z], latexs=new_latex_vecs)
assert A.latex_vecs == def_latex_vecs
assert B.latex_vecs == new_latex_vecs
assert B.indices != indices
def test_orientnew_respects_input_variables():
N = ReferenceFrame('N')
q1 = dynamicsymbols('q1')
A = N.orientnew('a', 'Axis', [q1, N.z])
#build non-standard variable names
name = 'b'
new_variables = ['notb_'+x+'1' for x in N.indices]
B = N.orientnew(name, 'Axis', [q1, N.z], variables=new_variables)
for j,var in enumerate(A.varlist):
assert var.name == A.name + '_' + A.indices[j]
for j,var in enumerate(B.varlist):
assert var.name == new_variables[j]
def test_issue_10348():
u = dynamicsymbols('u:3')
I = ReferenceFrame('I')
I.orientnew('A', 'space', u, 'XYZ')
def test_issue_11503():
A = ReferenceFrame("A")
A.orientnew("B", "Axis", [35, A.y])
C = ReferenceFrame("C")
A.orient(C, "Axis", [70, C.z])
def test_partial_velocity():
N = ReferenceFrame('N')
A = ReferenceFrame('A')
u1, u2 = dynamicsymbols('u1, u2')
A.set_ang_vel(N, u1 * A.x + u2 * N.y)
assert N.partial_velocity(A, u1) == -A.x
assert N.partial_velocity(A, u1, u2) == (-A.x, -N.y)
assert A.partial_velocity(N, u1) == A.x
assert A.partial_velocity(N, u1, u2) == (A.x, N.y)
assert N.partial_velocity(N, u1) == 0
assert A.partial_velocity(A, u1) == 0
def test_issue_11498():
A = ReferenceFrame('A')
B = ReferenceFrame('B')
# Identity transformation
A.orient(B, 'DCM', eye(3))
assert A.dcm(B) == Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
assert B.dcm(A) == Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
# x -> y
# y -> -z
# z -> -x
A.orient(B, 'DCM', Matrix([[0, 1, 0], [0, 0, -1], [-1, 0, 0]]))
assert B.dcm(A) == Matrix([[0, 1, 0], [0, 0, -1], [-1, 0, 0]])
assert A.dcm(B) == Matrix([[0, 0, -1], [1, 0, 0], [0, -1, 0]])
assert B.dcm(A).T == A.dcm(B)
def test_reference_frame():
raises(TypeError, lambda: ReferenceFrame(0))
raises(TypeError, lambda: ReferenceFrame('N', 0))
raises(ValueError, lambda: ReferenceFrame('N', [0, 1]))
raises(TypeError, lambda: ReferenceFrame('N', [0, 1, 2]))
raises(TypeError, lambda: ReferenceFrame('N', ['a', 'b', 'c'], 0))
raises(ValueError, lambda: ReferenceFrame('N', ['a', 'b', 'c'], [0, 1]))
raises(TypeError, lambda: ReferenceFrame('N', ['a', 'b', 'c'], [0, 1, 2]))
raises(TypeError, lambda: ReferenceFrame('N', ['a', 'b', 'c'],
['a', 'b', 'c'], 0))
raises(ValueError, lambda: ReferenceFrame('N', ['a', 'b', 'c'],
['a', 'b', 'c'], [0, 1]))
raises(TypeError, lambda: ReferenceFrame('N', ['a', 'b', 'c'],
['a', 'b', 'c'], [0, 1, 2]))
N = ReferenceFrame('N')
assert N[0] == CoordinateSym('N_x', N, 0)
assert N[1] == CoordinateSym('N_y', N, 1)
assert N[2] == CoordinateSym('N_z', N, 2)
raises(ValueError, lambda: N[3])
N = ReferenceFrame('N', ['a', 'b', 'c'])
assert N['a'] == N.x
assert N['b'] == N.y
assert N['c'] == N.z
raises(ValueError, lambda: N['d'])
assert str(N) == 'N'
A = ReferenceFrame('A')
B = ReferenceFrame('B')
q0, q1, q2, q3 = symbols('q0 q1 q2 q3')
raises(TypeError, lambda: A.orient(B, 'DCM', 0))
raises(TypeError, lambda: B.orient(N, 'Space', [q1, q2, q3], '222'))
raises(TypeError, lambda: B.orient(N, 'Axis', [q1, N.x + 2 * N.y], '222'))
raises(TypeError, lambda: B.orient(N, 'Axis', q1))
raises(IndexError, lambda: B.orient(N, 'Axis', [q1]))
raises(TypeError, lambda: B.orient(N, 'Quaternion', [q0, q1, q2, q3], '222'))
raises(TypeError, lambda: B.orient(N, 'Quaternion', q0))
raises(TypeError, lambda: B.orient(N, 'Quaternion', [q0, q1, q2]))
raises(NotImplementedError, lambda: B.orient(N, 'Foo', [q0, q1, q2]))
raises(TypeError, lambda: B.orient(N, 'Body', [q1, q2], '232'))
raises(TypeError, lambda: B.orient(N, 'Space', [q1, q2], '232'))
N.set_ang_acc(B, 0)
assert N.ang_acc_in(B) == Vector(0)
N.set_ang_vel(B, 0)
assert N.ang_vel_in(B) == Vector(0)
def test_check_frame():
raises(VectorTypeError, lambda: _check_frame(0))
def test_dcm_diff_16824():
# NOTE : This is a regression test for the bug introduced in PR 14758,
# identified in 16824, and solved by PR 16828.
# This is the solution to Problem 2.2 on page 264 in Kane & Lenvinson's
# 1985 book.
q1, q2, q3 = dynamicsymbols('q1:4')
s1 = sin(q1)
c1 = cos(q1)
s2 = sin(q2)
c2 = cos(q2)
s3 = sin(q3)
c3 = cos(q3)
dcm = Matrix([[c2*c3, s1*s2*c3 - s3*c1, c1*s2*c3 + s3*s1],
[c2*s3, s1*s2*s3 + c3*c1, c1*s2*s3 - c3*s1],
[-s2, s1*c2, c1*c2]])
A = ReferenceFrame('A')
B = ReferenceFrame('B')
B.orient(A, 'DCM', dcm)
AwB = B.ang_vel_in(A)
alpha2 = s3*c2*q1.diff() + c3*q2.diff()
beta2 = s1*c2*q3.diff() + c1*q2.diff()
assert simplify(AwB.dot(A.y) - alpha2) == 0
assert simplify(AwB.dot(B.y) - beta2) == 0
def test_orient_explicit():
cxx, cyy, czz = dynamicsymbols('c_{xx}, c_{yy}, c_{zz}')
cxy, cxz, cyx = dynamicsymbols('c_{xy}, c_{xz}, c_{yx}')
cyz, czx, czy = dynamicsymbols('c_{yz}, c_{zx}, c_{zy}')
dcxx, dcyy, dczz = dynamicsymbols('c_{xx}, c_{yy}, c_{zz}', 1)
dcxy, dcxz, dcyx = dynamicsymbols('c_{xy}, c_{xz}, c_{yx}', 1)
dcyz, dczx, dczy = dynamicsymbols('c_{yz}, c_{zx}, c_{zy}', 1)
A = ReferenceFrame('A')
B = ReferenceFrame('B')
B_C_A = Matrix([[cxx, cxy, cxz],
[cyx, cyy, cyz],
[czx, czy, czz]])
B_w_A = ((cyx*dczx + cyy*dczy + cyz*dczz)*B.x +
(czx*dcxx + czy*dcxy + czz*dcxz)*B.y +
(cxx*dcyx + cxy*dcyy + cxz*dcyz)*B.z)
A.orient_explicit(B, B_C_A)
assert B.dcm(A) == B_C_A
assert A.ang_vel_in(B) == B_w_A
assert B.ang_vel_in(A) == -B_w_A
def test_orient_dcm():
cxx, cyy, czz = dynamicsymbols('c_{xx}, c_{yy}, c_{zz}')
cxy, cxz, cyx = dynamicsymbols('c_{xy}, c_{xz}, c_{yx}')
cyz, czx, czy = dynamicsymbols('c_{yz}, c_{zx}, c_{zy}')
B_C_A = Matrix([[cxx, cxy, cxz],
[cyx, cyy, cyz],
[czx, czy, czz]])
A = ReferenceFrame('A')
B = ReferenceFrame('B')
B.orient_dcm(A, B_C_A)
assert B.dcm(A) == Matrix([[cxx, cxy, cxz],
[cyx, cyy, cyz],
[czx, czy, czz]])
def test_orient_axis():
A = ReferenceFrame('A')
B = ReferenceFrame('B')
A.orient_axis(B,-B.x, 1)
A1 = A.dcm(B)
A.orient_axis(B, B.x, -1)
A2 = A.dcm(B)
A.orient_axis(B, 1, -B.x)
A3 = A.dcm(B)
assert A1 == A2
assert A2 == A3
raises(TypeError, lambda: A.orient_axis(B, 1, 1))
def test_orient_body():
A = ReferenceFrame('A')
B = ReferenceFrame('B')
B.orient_body_fixed(A, (1,1,0), 'XYX')
assert B.dcm(A) == Matrix([[cos(1), sin(1)**2, -sin(1)*cos(1)], [0, cos(1), sin(1)], [sin(1), -sin(1)*cos(1), cos(1)**2]])
def test_orient_body_advanced():
q1, q2, q3 = dynamicsymbols('q1:4')
c1, c2, c3 = symbols('c1:4')
u1, u2, u3 = dynamicsymbols('q1:4', 1)
# Test with everything as dynamicsymbols
A, B = ReferenceFrame('A'), ReferenceFrame('B')
B.orient_body_fixed(A, (q1, q2, q3), 'zxy')
assert A.dcm(B) == Matrix([
[-sin(q1) * sin(q2) * sin(q3) + cos(q1) * cos(q3), -sin(q1) * cos(q2),
sin(q1) * sin(q2) * cos(q3) + sin(q3) * cos(q1)],
[sin(q1) * cos(q3) + sin(q2) * sin(q3) * cos(q1), cos(q1) * cos(q2),
sin(q1) * sin(q3) - sin(q2) * cos(q1) * cos(q3)],
[-sin(q3) * cos(q2), sin(q2), cos(q2) * cos(q3)]])
assert B.ang_vel_in(A).to_matrix(B) == Matrix([
[-sin(q3) * cos(q2) * u1 + cos(q3) * u2],
[sin(q2) * u1 + u3],
[sin(q3) * u2 + cos(q2) * cos(q3) * u1]])
# Test with constant symbol
A, B = ReferenceFrame('A'), ReferenceFrame('B')
B.orient_body_fixed(A, (q1, c2, q3), 131)
assert A.dcm(B) == Matrix([
[cos(c2), -sin(c2) * cos(q3), sin(c2) * sin(q3)],
[sin(c2) * cos(q1), -sin(q1) * sin(q3) + cos(c2) * cos(q1) * cos(q3),
-sin(q1) * cos(q3) - sin(q3) * cos(c2) * cos(q1)],
[sin(c2) * sin(q1), sin(q1) * cos(c2) * cos(q3) + sin(q3) * cos(q1),
-sin(q1) * sin(q3) * cos(c2) + cos(q1) * cos(q3)]])
assert B.ang_vel_in(A).to_matrix(B) == Matrix([
[cos(c2) * u1 + u3],
[-sin(c2) * cos(q3) * u1],
[sin(c2) * sin(q3) * u1]])
# Test all symbols not time dependent
A, B = ReferenceFrame('A'), ReferenceFrame('B')
B.orient_body_fixed(A, (c1, c2, c3), 123)
assert B.ang_vel_in(A) == Vector(0)
def test_orient_space_advanced():
# space fixed is in the end like body fixed only in opposite order
q1, q2, q3 = dynamicsymbols('q1:4')
c1, c2, c3 = symbols('c1:4')
u1, u2, u3 = dynamicsymbols('q1:4', 1)
# Test with everything as dynamicsymbols
A, B = ReferenceFrame('A'), ReferenceFrame('B')
B.orient_space_fixed(A, (q3, q2, q1), 'yxz')
assert A.dcm(B) == Matrix([
[-sin(q1) * sin(q2) * sin(q3) + cos(q1) * cos(q3), -sin(q1) * cos(q2),
sin(q1) * sin(q2) * cos(q3) + sin(q3) * cos(q1)],
[sin(q1) * cos(q3) + sin(q2) * sin(q3) * cos(q1), cos(q1) * cos(q2),
sin(q1) * sin(q3) - sin(q2) * cos(q1) * cos(q3)],
[-sin(q3) * cos(q2), sin(q2), cos(q2) * cos(q3)]])
assert B.ang_vel_in(A).to_matrix(B) == Matrix([
[-sin(q3) * cos(q2) * u1 + cos(q3) * u2],
[sin(q2) * u1 + u3],
[sin(q3) * u2 + cos(q2) * cos(q3) * u1]])
# Test with constant symbol
A, B = ReferenceFrame('A'), ReferenceFrame('B')
B.orient_space_fixed(A, (q3, c2, q1), 131)
assert A.dcm(B) == Matrix([
[cos(c2), -sin(c2) * cos(q3), sin(c2) * sin(q3)],
[sin(c2) * cos(q1), -sin(q1) * sin(q3) + cos(c2) * cos(q1) * cos(q3),
-sin(q1) * cos(q3) - sin(q3) * cos(c2) * cos(q1)],
[sin(c2) * sin(q1), sin(q1) * cos(c2) * cos(q3) + sin(q3) * cos(q1),
-sin(q1) * sin(q3) * cos(c2) + cos(q1) * cos(q3)]])
assert B.ang_vel_in(A).to_matrix(B) == Matrix([
[cos(c2) * u1 + u3],
[-sin(c2) * cos(q3) * u1],
[sin(c2) * sin(q3) * u1]])
# Test all symbols not time dependent
A, B = ReferenceFrame('A'), ReferenceFrame('B')
B.orient_space_fixed(A, (c1, c2, c3), 123)
assert B.ang_vel_in(A) == Vector(0)
def test_orient_body_simple_ang_vel():
"""This test ensures that the simplest form of that linear system solution
is returned, thus the == for the expression comparison."""
psi, theta, phi = dynamicsymbols('psi, theta, varphi')
t = dynamicsymbols._t
A = ReferenceFrame('A')
B = ReferenceFrame('B')
B.orient_body_fixed(A, (psi, theta, phi), 'ZXZ')
A_w_B = B.ang_vel_in(A)
assert A_w_B.args[0][1] == B
assert A_w_B.args[0][0][0] == (sin(theta)*sin(phi)*psi.diff(t) +
cos(phi)*theta.diff(t))
assert A_w_B.args[0][0][1] == (sin(theta)*cos(phi)*psi.diff(t) -
sin(phi)*theta.diff(t))
assert A_w_B.args[0][0][2] == cos(theta)*psi.diff(t) + phi.diff(t)
def test_orient_space():
A = ReferenceFrame('A')
B = ReferenceFrame('B')
B.orient_space_fixed(A, (0,0,0), '123')
assert B.dcm(A) == Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
def test_orient_quaternion():
A = ReferenceFrame('A')
B = ReferenceFrame('B')
B.orient_quaternion(A, (0,0,0,0))
assert B.dcm(A) == Matrix([[0, 0, 0], [0, 0, 0], [0, 0, 0]])
def test_looped_frame_warning():
A = ReferenceFrame('A')
B = ReferenceFrame('B')
C = ReferenceFrame('C')
a, b, c = symbols('a b c')
B.orient_axis(A, A.x, a)
C.orient_axis(B, B.x, b)
with warnings.catch_warnings(record = True) as w:
warnings.simplefilter("always")
A.orient_axis(C, C.x, c)
assert issubclass(w[-1].category, UserWarning)
assert 'Loops are defined among the orientation of frames. ' + \
'This is likely not desired and may cause errors in your calculations.' in str(w[-1].message)
def test_frame_dict():
A = ReferenceFrame('A')
B = ReferenceFrame('B')
C = ReferenceFrame('C')
a, b, c = symbols('a b c')
B.orient_axis(A, A.x, a)
assert A._dcm_dict == {B: Matrix([[1, 0, 0],[0, cos(a), -sin(a)],[0, sin(a), cos(a)]])}
assert B._dcm_dict == {A: Matrix([[1, 0, 0],[0, cos(a), sin(a)],[0, -sin(a), cos(a)]])}
assert C._dcm_dict == {}
B.orient_axis(C, C.x, b)
# Previous relation is not wiped
assert A._dcm_dict == {B: Matrix([[1, 0, 0],[0, cos(a), -sin(a)],[0, sin(a), cos(a)]])}
assert B._dcm_dict == {A: Matrix([[1, 0, 0],[0, cos(a), sin(a)],[0, -sin(a), cos(a)]]), \
C: Matrix([[1, 0, 0],[0, cos(b), sin(b)],[0, -sin(b), cos(b)]])}
assert C._dcm_dict == {B: Matrix([[1, 0, 0],[0, cos(b), -sin(b)],[0, sin(b), cos(b)]])}
A.orient_axis(B, B.x, c)
# Previous relation is updated
assert B._dcm_dict == {C: Matrix([[1, 0, 0],[0, cos(b), sin(b)],[0, -sin(b), cos(b)]]),\
A: Matrix([[1, 0, 0],[0, cos(c), -sin(c)],[0, sin(c), cos(c)]])}
assert A._dcm_dict == {B: Matrix([[1, 0, 0],[0, cos(c), sin(c)],[0, -sin(c), cos(c)]])}
assert C._dcm_dict == {B: Matrix([[1, 0, 0],[0, cos(b), -sin(b)],[0, sin(b), cos(b)]])}
def test_dcm_cache_dict():
A = ReferenceFrame('A')
B = ReferenceFrame('B')
C = ReferenceFrame('C')
D = ReferenceFrame('D')
a, b, c = symbols('a b c')
B.orient_axis(A, A.x, a)
C.orient_axis(B, B.x, b)
D.orient_axis(C, C.x, c)
assert D._dcm_dict == {C: Matrix([[1, 0, 0],[0, cos(c), sin(c)],[0, -sin(c), cos(c)]])}
assert C._dcm_dict == {B: Matrix([[1, 0, 0],[0, cos(b), sin(b)],[0, -sin(b), cos(b)]]), \
D: Matrix([[1, 0, 0],[0, cos(c), -sin(c)],[0, sin(c), cos(c)]])}
assert B._dcm_dict == {A: Matrix([[1, 0, 0],[0, cos(a), sin(a)],[0, -sin(a), cos(a)]]), \
C: Matrix([[1, 0, 0],[0, cos(b), -sin(b)],[0, sin(b), cos(b)]])}
assert A._dcm_dict == {B: Matrix([[1, 0, 0],[0, cos(a), -sin(a)],[0, sin(a), cos(a)]])}
assert D._dcm_dict == D._dcm_cache
D.dcm(A) # Check calculated dcm relation is stored in _dcm_cache and not in _dcm_dict
assert list(A._dcm_cache.keys()) == [A, B, D]
assert list(D._dcm_cache.keys()) == [C, A]
assert list(A._dcm_dict.keys()) == [B]
assert list(D._dcm_dict.keys()) == [C]
assert A._dcm_dict != A._dcm_cache
A.orient_axis(B, B.x, b) # _dcm_cache of A is wiped out and new relation is stored.
assert A._dcm_dict == {B: Matrix([[1, 0, 0],[0, cos(b), sin(b)],[0, -sin(b), cos(b)]])}
assert A._dcm_dict == A._dcm_cache
assert B._dcm_dict == {C: Matrix([[1, 0, 0],[0, cos(b), -sin(b)],[0, sin(b), cos(b)]]), \
A: Matrix([[1, 0, 0],[0, cos(b), -sin(b)],[0, sin(b), cos(b)]])}
def test_xx_dyad():
N = ReferenceFrame('N')
F = ReferenceFrame('F', indices=['1', '2', '3'])
assert N.xx == Vector.outer(N.x, N.x)
assert F.xx == Vector.outer(F.x, F.x)
def test_xy_dyad():
N = ReferenceFrame('N')
F = ReferenceFrame('F', indices=['1', '2', '3'])
assert N.xy == Vector.outer(N.x, N.y)
assert F.xy == Vector.outer(F.x, F.y)
def test_xz_dyad():
N = ReferenceFrame('N')
F = ReferenceFrame('F', indices=['1', '2', '3'])
assert N.xz == Vector.outer(N.x, N.z)
assert F.xz == Vector.outer(F.x, F.z)
def test_yx_dyad():
N = ReferenceFrame('N')
F = ReferenceFrame('F', indices=['1', '2', '3'])
assert N.yx == Vector.outer(N.y, N.x)
assert F.yx == Vector.outer(F.y, F.x)
def test_yy_dyad():
N = ReferenceFrame('N')
F = ReferenceFrame('F', indices=['1', '2', '3'])
assert N.yy == Vector.outer(N.y, N.y)
assert F.yy == Vector.outer(F.y, F.y)
def test_yz_dyad():
N = ReferenceFrame('N')
F = ReferenceFrame('F', indices=['1', '2', '3'])
assert N.yz == Vector.outer(N.y, N.z)
assert F.yz == Vector.outer(F.y, F.z)
def test_zx_dyad():
N = ReferenceFrame('N')
F = ReferenceFrame('F', indices=['1', '2', '3'])
assert N.zx == Vector.outer(N.z, N.x)
assert F.zx == Vector.outer(F.z, F.x)
def test_zy_dyad():
N = ReferenceFrame('N')
F = ReferenceFrame('F', indices=['1', '2', '3'])
assert N.zy == Vector.outer(N.z, N.y)
assert F.zy == Vector.outer(F.z, F.y)
def test_zz_dyad():
N = ReferenceFrame('N')
F = ReferenceFrame('F', indices=['1', '2', '3'])
assert N.zz == Vector.outer(N.z, N.z)
assert F.zz == Vector.outer(F.z, F.z)
def test_unit_dyadic():
N = ReferenceFrame('N')
F = ReferenceFrame('F', indices=['1', '2', '3'])
assert N.u == N.xx + N.yy + N.zz
assert F.u == F.xx + F.yy + F.zz
def test_pickle_frame():
N = ReferenceFrame('N')
A = ReferenceFrame('A')
A.orient_axis(N, N.x, 1)
A_C_N = A.dcm(N)
N1 = pickle.loads(pickle.dumps(N))
A1 = tuple(N1._dcm_dict.keys())[0]
assert A1.dcm(N1) == A_C_N

View File

@ -0,0 +1,509 @@
from sympy.core.numbers import pi
from sympy.core.singleton import S
from sympy.core.symbol import symbols
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.functions.elementary.trigonometric import (cos, sin)
from sympy.integrals.integrals import Integral
from sympy.physics.vector import Dyadic, Point, ReferenceFrame, Vector
from sympy.physics.vector.functions import (cross, dot, express,
time_derivative,
kinematic_equations, outer,
partial_velocity,
get_motion_params, dynamicsymbols)
from sympy.simplify import trigsimp
from sympy.testing.pytest import raises
q1, q2, q3, q4, q5 = symbols('q1 q2 q3 q4 q5')
N = ReferenceFrame('N')
A = N.orientnew('A', 'Axis', [q1, N.z])
B = A.orientnew('B', 'Axis', [q2, A.x])
C = B.orientnew('C', 'Axis', [q3, B.y])
def test_dot():
assert dot(A.x, A.x) == 1
assert dot(A.x, A.y) == 0
assert dot(A.x, A.z) == 0
assert dot(A.y, A.x) == 0
assert dot(A.y, A.y) == 1
assert dot(A.y, A.z) == 0
assert dot(A.z, A.x) == 0
assert dot(A.z, A.y) == 0
assert dot(A.z, A.z) == 1
def test_dot_different_frames():
assert dot(N.x, A.x) == cos(q1)
assert dot(N.x, A.y) == -sin(q1)
assert dot(N.x, A.z) == 0
assert dot(N.y, A.x) == sin(q1)
assert dot(N.y, A.y) == cos(q1)
assert dot(N.y, A.z) == 0
assert dot(N.z, A.x) == 0
assert dot(N.z, A.y) == 0
assert dot(N.z, A.z) == 1
assert trigsimp(dot(N.x, A.x + A.y)) == sqrt(2)*cos(q1 + pi/4)
assert trigsimp(dot(N.x, A.x + A.y)) == trigsimp(dot(A.x + A.y, N.x))
assert dot(A.x, C.x) == cos(q3)
assert dot(A.x, C.y) == 0
assert dot(A.x, C.z) == sin(q3)
assert dot(A.y, C.x) == sin(q2)*sin(q3)
assert dot(A.y, C.y) == cos(q2)
assert dot(A.y, C.z) == -sin(q2)*cos(q3)
assert dot(A.z, C.x) == -cos(q2)*sin(q3)
assert dot(A.z, C.y) == sin(q2)
assert dot(A.z, C.z) == cos(q2)*cos(q3)
def test_cross():
assert cross(A.x, A.x) == 0
assert cross(A.x, A.y) == A.z
assert cross(A.x, A.z) == -A.y
assert cross(A.y, A.x) == -A.z
assert cross(A.y, A.y) == 0
assert cross(A.y, A.z) == A.x
assert cross(A.z, A.x) == A.y
assert cross(A.z, A.y) == -A.x
assert cross(A.z, A.z) == 0
def test_cross_different_frames():
assert cross(N.x, A.x) == sin(q1)*A.z
assert cross(N.x, A.y) == cos(q1)*A.z
assert cross(N.x, A.z) == -sin(q1)*A.x - cos(q1)*A.y
assert cross(N.y, A.x) == -cos(q1)*A.z
assert cross(N.y, A.y) == sin(q1)*A.z
assert cross(N.y, A.z) == cos(q1)*A.x - sin(q1)*A.y
assert cross(N.z, A.x) == A.y
assert cross(N.z, A.y) == -A.x
assert cross(N.z, A.z) == 0
assert cross(N.x, A.x) == sin(q1)*A.z
assert cross(N.x, A.y) == cos(q1)*A.z
assert cross(N.x, A.x + A.y) == sin(q1)*A.z + cos(q1)*A.z
assert cross(A.x + A.y, N.x) == -sin(q1)*A.z - cos(q1)*A.z
assert cross(A.x, C.x) == sin(q3)*C.y
assert cross(A.x, C.y) == -sin(q3)*C.x + cos(q3)*C.z
assert cross(A.x, C.z) == -cos(q3)*C.y
assert cross(C.x, A.x) == -sin(q3)*C.y
assert cross(C.y, A.x).express(C).simplify() == sin(q3)*C.x - cos(q3)*C.z
assert cross(C.z, A.x) == cos(q3)*C.y
def test_operator_match():
"""Test that the output of dot, cross, outer functions match
operator behavior.
"""
A = ReferenceFrame('A')
v = A.x + A.y
d = v | v
zerov = Vector(0)
zerod = Dyadic(0)
# dot products
assert d & d == dot(d, d)
assert d & zerod == dot(d, zerod)
assert zerod & d == dot(zerod, d)
assert d & v == dot(d, v)
assert v & d == dot(v, d)
assert d & zerov == dot(d, zerov)
assert zerov & d == dot(zerov, d)
raises(TypeError, lambda: dot(d, S.Zero))
raises(TypeError, lambda: dot(S.Zero, d))
raises(TypeError, lambda: dot(d, 0))
raises(TypeError, lambda: dot(0, d))
assert v & v == dot(v, v)
assert v & zerov == dot(v, zerov)
assert zerov & v == dot(zerov, v)
raises(TypeError, lambda: dot(v, S.Zero))
raises(TypeError, lambda: dot(S.Zero, v))
raises(TypeError, lambda: dot(v, 0))
raises(TypeError, lambda: dot(0, v))
# cross products
raises(TypeError, lambda: cross(d, d))
raises(TypeError, lambda: cross(d, zerod))
raises(TypeError, lambda: cross(zerod, d))
assert d ^ v == cross(d, v)
assert v ^ d == cross(v, d)
assert d ^ zerov == cross(d, zerov)
assert zerov ^ d == cross(zerov, d)
assert zerov ^ d == cross(zerov, d)
raises(TypeError, lambda: cross(d, S.Zero))
raises(TypeError, lambda: cross(S.Zero, d))
raises(TypeError, lambda: cross(d, 0))
raises(TypeError, lambda: cross(0, d))
assert v ^ v == cross(v, v)
assert v ^ zerov == cross(v, zerov)
assert zerov ^ v == cross(zerov, v)
raises(TypeError, lambda: cross(v, S.Zero))
raises(TypeError, lambda: cross(S.Zero, v))
raises(TypeError, lambda: cross(v, 0))
raises(TypeError, lambda: cross(0, v))
# outer products
raises(TypeError, lambda: outer(d, d))
raises(TypeError, lambda: outer(d, zerod))
raises(TypeError, lambda: outer(zerod, d))
raises(TypeError, lambda: outer(d, v))
raises(TypeError, lambda: outer(v, d))
raises(TypeError, lambda: outer(d, zerov))
raises(TypeError, lambda: outer(zerov, d))
raises(TypeError, lambda: outer(zerov, d))
raises(TypeError, lambda: outer(d, S.Zero))
raises(TypeError, lambda: outer(S.Zero, d))
raises(TypeError, lambda: outer(d, 0))
raises(TypeError, lambda: outer(0, d))
assert v | v == outer(v, v)
assert v | zerov == outer(v, zerov)
assert zerov | v == outer(zerov, v)
raises(TypeError, lambda: outer(v, S.Zero))
raises(TypeError, lambda: outer(S.Zero, v))
raises(TypeError, lambda: outer(v, 0))
raises(TypeError, lambda: outer(0, v))
def test_express():
assert express(Vector(0), N) == Vector(0)
assert express(S.Zero, N) is S.Zero
assert express(A.x, C) == cos(q3)*C.x + sin(q3)*C.z
assert express(A.y, C) == sin(q2)*sin(q3)*C.x + cos(q2)*C.y - \
sin(q2)*cos(q3)*C.z
assert express(A.z, C) == -sin(q3)*cos(q2)*C.x + sin(q2)*C.y + \
cos(q2)*cos(q3)*C.z
assert express(A.x, N) == cos(q1)*N.x + sin(q1)*N.y
assert express(A.y, N) == -sin(q1)*N.x + cos(q1)*N.y
assert express(A.z, N) == N.z
assert express(A.x, A) == A.x
assert express(A.y, A) == A.y
assert express(A.z, A) == A.z
assert express(A.x, B) == B.x
assert express(A.y, B) == cos(q2)*B.y - sin(q2)*B.z
assert express(A.z, B) == sin(q2)*B.y + cos(q2)*B.z
assert express(A.x, C) == cos(q3)*C.x + sin(q3)*C.z
assert express(A.y, C) == sin(q2)*sin(q3)*C.x + cos(q2)*C.y - \
sin(q2)*cos(q3)*C.z
assert express(A.z, C) == -sin(q3)*cos(q2)*C.x + sin(q2)*C.y + \
cos(q2)*cos(q3)*C.z
# Check to make sure UnitVectors get converted properly
assert express(N.x, N) == N.x
assert express(N.y, N) == N.y
assert express(N.z, N) == N.z
assert express(N.x, A) == (cos(q1)*A.x - sin(q1)*A.y)
assert express(N.y, A) == (sin(q1)*A.x + cos(q1)*A.y)
assert express(N.z, A) == A.z
assert express(N.x, B) == (cos(q1)*B.x - sin(q1)*cos(q2)*B.y +
sin(q1)*sin(q2)*B.z)
assert express(N.y, B) == (sin(q1)*B.x + cos(q1)*cos(q2)*B.y -
sin(q2)*cos(q1)*B.z)
assert express(N.z, B) == (sin(q2)*B.y + cos(q2)*B.z)
assert express(N.x, C) == (
(cos(q1)*cos(q3) - sin(q1)*sin(q2)*sin(q3))*C.x -
sin(q1)*cos(q2)*C.y +
(sin(q3)*cos(q1) + sin(q1)*sin(q2)*cos(q3))*C.z)
assert express(N.y, C) == (
(sin(q1)*cos(q3) + sin(q2)*sin(q3)*cos(q1))*C.x +
cos(q1)*cos(q2)*C.y +
(sin(q1)*sin(q3) - sin(q2)*cos(q1)*cos(q3))*C.z)
assert express(N.z, C) == (-sin(q3)*cos(q2)*C.x + sin(q2)*C.y +
cos(q2)*cos(q3)*C.z)
assert express(A.x, N) == (cos(q1)*N.x + sin(q1)*N.y)
assert express(A.y, N) == (-sin(q1)*N.x + cos(q1)*N.y)
assert express(A.z, N) == N.z
assert express(A.x, A) == A.x
assert express(A.y, A) == A.y
assert express(A.z, A) == A.z
assert express(A.x, B) == B.x
assert express(A.y, B) == (cos(q2)*B.y - sin(q2)*B.z)
assert express(A.z, B) == (sin(q2)*B.y + cos(q2)*B.z)
assert express(A.x, C) == (cos(q3)*C.x + sin(q3)*C.z)
assert express(A.y, C) == (sin(q2)*sin(q3)*C.x + cos(q2)*C.y -
sin(q2)*cos(q3)*C.z)
assert express(A.z, C) == (-sin(q3)*cos(q2)*C.x + sin(q2)*C.y +
cos(q2)*cos(q3)*C.z)
assert express(B.x, N) == (cos(q1)*N.x + sin(q1)*N.y)
assert express(B.y, N) == (-sin(q1)*cos(q2)*N.x +
cos(q1)*cos(q2)*N.y + sin(q2)*N.z)
assert express(B.z, N) == (sin(q1)*sin(q2)*N.x -
sin(q2)*cos(q1)*N.y + cos(q2)*N.z)
assert express(B.x, A) == A.x
assert express(B.y, A) == (cos(q2)*A.y + sin(q2)*A.z)
assert express(B.z, A) == (-sin(q2)*A.y + cos(q2)*A.z)
assert express(B.x, B) == B.x
assert express(B.y, B) == B.y
assert express(B.z, B) == B.z
assert express(B.x, C) == (cos(q3)*C.x + sin(q3)*C.z)
assert express(B.y, C) == C.y
assert express(B.z, C) == (-sin(q3)*C.x + cos(q3)*C.z)
assert express(C.x, N) == (
(cos(q1)*cos(q3) - sin(q1)*sin(q2)*sin(q3))*N.x +
(sin(q1)*cos(q3) + sin(q2)*sin(q3)*cos(q1))*N.y -
sin(q3)*cos(q2)*N.z)
assert express(C.y, N) == (
-sin(q1)*cos(q2)*N.x + cos(q1)*cos(q2)*N.y + sin(q2)*N.z)
assert express(C.z, N) == (
(sin(q3)*cos(q1) + sin(q1)*sin(q2)*cos(q3))*N.x +
(sin(q1)*sin(q3) - sin(q2)*cos(q1)*cos(q3))*N.y +
cos(q2)*cos(q3)*N.z)
assert express(C.x, A) == (cos(q3)*A.x + sin(q2)*sin(q3)*A.y -
sin(q3)*cos(q2)*A.z)
assert express(C.y, A) == (cos(q2)*A.y + sin(q2)*A.z)
assert express(C.z, A) == (sin(q3)*A.x - sin(q2)*cos(q3)*A.y +
cos(q2)*cos(q3)*A.z)
assert express(C.x, B) == (cos(q3)*B.x - sin(q3)*B.z)
assert express(C.y, B) == B.y
assert express(C.z, B) == (sin(q3)*B.x + cos(q3)*B.z)
assert express(C.x, C) == C.x
assert express(C.y, C) == C.y
assert express(C.z, C) == C.z == (C.z)
# Check to make sure Vectors get converted back to UnitVectors
assert N.x == express((cos(q1)*A.x - sin(q1)*A.y), N).simplify()
assert N.y == express((sin(q1)*A.x + cos(q1)*A.y), N).simplify()
assert N.x == express((cos(q1)*B.x - sin(q1)*cos(q2)*B.y +
sin(q1)*sin(q2)*B.z), N).simplify()
assert N.y == express((sin(q1)*B.x + cos(q1)*cos(q2)*B.y -
sin(q2)*cos(q1)*B.z), N).simplify()
assert N.z == express((sin(q2)*B.y + cos(q2)*B.z), N).simplify()
"""
These don't really test our code, they instead test the auto simplification
(or lack thereof) of SymPy.
assert N.x == express((
(cos(q1)*cos(q3)-sin(q1)*sin(q2)*sin(q3))*C.x -
sin(q1)*cos(q2)*C.y +
(sin(q3)*cos(q1)+sin(q1)*sin(q2)*cos(q3))*C.z), N)
assert N.y == express((
(sin(q1)*cos(q3) + sin(q2)*sin(q3)*cos(q1))*C.x +
cos(q1)*cos(q2)*C.y +
(sin(q1)*sin(q3) - sin(q2)*cos(q1)*cos(q3))*C.z), N)
assert N.z == express((-sin(q3)*cos(q2)*C.x + sin(q2)*C.y +
cos(q2)*cos(q3)*C.z), N)
"""
assert A.x == express((cos(q1)*N.x + sin(q1)*N.y), A).simplify()
assert A.y == express((-sin(q1)*N.x + cos(q1)*N.y), A).simplify()
assert A.y == express((cos(q2)*B.y - sin(q2)*B.z), A).simplify()
assert A.z == express((sin(q2)*B.y + cos(q2)*B.z), A).simplify()
assert A.x == express((cos(q3)*C.x + sin(q3)*C.z), A).simplify()
# Tripsimp messes up here too.
#print express((sin(q2)*sin(q3)*C.x + cos(q2)*C.y -
# sin(q2)*cos(q3)*C.z), A)
assert A.y == express((sin(q2)*sin(q3)*C.x + cos(q2)*C.y -
sin(q2)*cos(q3)*C.z), A).simplify()
assert A.z == express((-sin(q3)*cos(q2)*C.x + sin(q2)*C.y +
cos(q2)*cos(q3)*C.z), A).simplify()
assert B.x == express((cos(q1)*N.x + sin(q1)*N.y), B).simplify()
assert B.y == express((-sin(q1)*cos(q2)*N.x +
cos(q1)*cos(q2)*N.y + sin(q2)*N.z), B).simplify()
assert B.z == express((sin(q1)*sin(q2)*N.x -
sin(q2)*cos(q1)*N.y + cos(q2)*N.z), B).simplify()
assert B.y == express((cos(q2)*A.y + sin(q2)*A.z), B).simplify()
assert B.z == express((-sin(q2)*A.y + cos(q2)*A.z), B).simplify()
assert B.x == express((cos(q3)*C.x + sin(q3)*C.z), B).simplify()
assert B.z == express((-sin(q3)*C.x + cos(q3)*C.z), B).simplify()
"""
assert C.x == express((
(cos(q1)*cos(q3)-sin(q1)*sin(q2)*sin(q3))*N.x +
(sin(q1)*cos(q3)+sin(q2)*sin(q3)*cos(q1))*N.y -
sin(q3)*cos(q2)*N.z), C)
assert C.y == express((
-sin(q1)*cos(q2)*N.x + cos(q1)*cos(q2)*N.y + sin(q2)*N.z), C)
assert C.z == express((
(sin(q3)*cos(q1)+sin(q1)*sin(q2)*cos(q3))*N.x +
(sin(q1)*sin(q3)-sin(q2)*cos(q1)*cos(q3))*N.y +
cos(q2)*cos(q3)*N.z), C)
"""
assert C.x == express((cos(q3)*A.x + sin(q2)*sin(q3)*A.y -
sin(q3)*cos(q2)*A.z), C).simplify()
assert C.y == express((cos(q2)*A.y + sin(q2)*A.z), C).simplify()
assert C.z == express((sin(q3)*A.x - sin(q2)*cos(q3)*A.y +
cos(q2)*cos(q3)*A.z), C).simplify()
assert C.x == express((cos(q3)*B.x - sin(q3)*B.z), C).simplify()
assert C.z == express((sin(q3)*B.x + cos(q3)*B.z), C).simplify()
def test_time_derivative():
#The use of time_derivative for calculations pertaining to scalar
#fields has been tested in test_coordinate_vars in test_essential.py
A = ReferenceFrame('A')
q = dynamicsymbols('q')
qd = dynamicsymbols('q', 1)
B = A.orientnew('B', 'Axis', [q, A.z])
d = A.x | A.x
assert time_derivative(d, B) == (-qd) * (A.y | A.x) + \
(-qd) * (A.x | A.y)
d1 = A.x | B.y
assert time_derivative(d1, A) == - qd*(A.x|B.x)
assert time_derivative(d1, B) == - qd*(A.y|B.y)
d2 = A.x | B.x
assert time_derivative(d2, A) == qd*(A.x|B.y)
assert time_derivative(d2, B) == - qd*(A.y|B.x)
d3 = A.x | B.z
assert time_derivative(d3, A) == 0
assert time_derivative(d3, B) == - qd*(A.y|B.z)
q1, q2, q3, q4 = dynamicsymbols('q1 q2 q3 q4')
q1d, q2d, q3d, q4d = dynamicsymbols('q1 q2 q3 q4', 1)
q1dd, q2dd, q3dd, q4dd = dynamicsymbols('q1 q2 q3 q4', 2)
C = B.orientnew('C', 'Axis', [q4, B.x])
v1 = q1 * A.z
v2 = q2*A.x + q3*B.y
v3 = q1*A.x + q2*A.y + q3*A.z
assert time_derivative(B.x, C) == 0
assert time_derivative(B.y, C) == - q4d*B.z
assert time_derivative(B.z, C) == q4d*B.y
assert time_derivative(v1, B) == q1d*A.z
assert time_derivative(v1, C) == - q1*sin(q)*q4d*A.x + \
q1*cos(q)*q4d*A.y + q1d*A.z
assert time_derivative(v2, A) == q2d*A.x - q3*qd*B.x + q3d*B.y
assert time_derivative(v2, C) == q2d*A.x - q2*qd*A.y + \
q2*sin(q)*q4d*A.z + q3d*B.y - q3*q4d*B.z
assert time_derivative(v3, B) == (q2*qd + q1d)*A.x + \
(-q1*qd + q2d)*A.y + q3d*A.z
assert time_derivative(d, C) == - qd*(A.y|A.x) + \
sin(q)*q4d*(A.z|A.x) - qd*(A.x|A.y) + sin(q)*q4d*(A.x|A.z)
raises(ValueError, lambda: time_derivative(B.x, C, order=0.5))
raises(ValueError, lambda: time_derivative(B.x, C, order=-1))
def test_get_motion_methods():
#Initialization
t = dynamicsymbols._t
s1, s2, s3 = symbols('s1 s2 s3')
S1, S2, S3 = symbols('S1 S2 S3')
S4, S5, S6 = symbols('S4 S5 S6')
t1, t2 = symbols('t1 t2')
a, b, c = dynamicsymbols('a b c')
ad, bd, cd = dynamicsymbols('a b c', 1)
a2d, b2d, c2d = dynamicsymbols('a b c', 2)
v0 = S1*N.x + S2*N.y + S3*N.z
v01 = S4*N.x + S5*N.y + S6*N.z
v1 = s1*N.x + s2*N.y + s3*N.z
v2 = a*N.x + b*N.y + c*N.z
v2d = ad*N.x + bd*N.y + cd*N.z
v2dd = a2d*N.x + b2d*N.y + c2d*N.z
#Test position parameter
assert get_motion_params(frame = N) == (0, 0, 0)
assert get_motion_params(N, position=v1) == (0, 0, v1)
assert get_motion_params(N, position=v2) == (v2dd, v2d, v2)
#Test velocity parameter
assert get_motion_params(N, velocity=v1) == (0, v1, v1 * t)
assert get_motion_params(N, velocity=v1, position=v0, timevalue1=t1) == \
(0, v1, v0 + v1*(t - t1))
answer = get_motion_params(N, velocity=v1, position=v2, timevalue1=t1)
answer_expected = (0, v1, v1*t - v1*t1 + v2.subs(t, t1))
assert answer == answer_expected
answer = get_motion_params(N, velocity=v2, position=v0, timevalue1=t1)
integral_vector = Integral(a, (t, t1, t))*N.x + Integral(b, (t, t1, t))*N.y \
+ Integral(c, (t, t1, t))*N.z
answer_expected = (v2d, v2, v0 + integral_vector)
assert answer == answer_expected
#Test acceleration parameter
assert get_motion_params(N, acceleration=v1) == \
(v1, v1 * t, v1 * t**2/2)
assert get_motion_params(N, acceleration=v1, velocity=v0,
position=v2, timevalue1=t1, timevalue2=t2) == \
(v1, (v0 + v1*t - v1*t2),
-v0*t1 + v1*t**2/2 + v1*t2*t1 - \
v1*t1**2/2 + t*(v0 - v1*t2) + \
v2.subs(t, t1))
assert get_motion_params(N, acceleration=v1, velocity=v0,
position=v01, timevalue1=t1, timevalue2=t2) == \
(v1, v0 + v1*t - v1*t2,
-v0*t1 + v01 + v1*t**2/2 + \
v1*t2*t1 - v1*t1**2/2 + \
t*(v0 - v1*t2))
answer = get_motion_params(N, acceleration=a*N.x, velocity=S1*N.x,
position=S2*N.x, timevalue1=t1, timevalue2=t2)
i1 = Integral(a, (t, t2, t))
answer_expected = (a*N.x, (S1 + i1)*N.x, \
(S2 + Integral(S1 + i1, (t, t1, t)))*N.x)
assert answer == answer_expected
def test_kin_eqs():
q0, q1, q2, q3 = dynamicsymbols('q0 q1 q2 q3')
q0d, q1d, q2d, q3d = dynamicsymbols('q0 q1 q2 q3', 1)
u1, u2, u3 = dynamicsymbols('u1 u2 u3')
ke = kinematic_equations([u1,u2,u3], [q1,q2,q3], 'body', 313)
assert ke == kinematic_equations([u1,u2,u3], [q1,q2,q3], 'body', '313')
kds = kinematic_equations([u1, u2, u3], [q0, q1, q2, q3], 'quaternion')
assert kds == [-0.5 * q0 * u1 - 0.5 * q2 * u3 + 0.5 * q3 * u2 + q1d,
-0.5 * q0 * u2 + 0.5 * q1 * u3 - 0.5 * q3 * u1 + q2d,
-0.5 * q0 * u3 - 0.5 * q1 * u2 + 0.5 * q2 * u1 + q3d,
0.5 * q1 * u1 + 0.5 * q2 * u2 + 0.5 * q3 * u3 + q0d]
raises(ValueError, lambda: kinematic_equations([u1, u2, u3], [q0, q1, q2], 'quaternion'))
raises(ValueError, lambda: kinematic_equations([u1, u2, u3], [q0, q1, q2, q3], 'quaternion', '123'))
raises(ValueError, lambda: kinematic_equations([u1, u2, u3], [q0, q1, q2, q3], 'foo'))
raises(TypeError, lambda: kinematic_equations(u1, [q0, q1, q2, q3], 'quaternion'))
raises(TypeError, lambda: kinematic_equations([u1], [q0, q1, q2, q3], 'quaternion'))
raises(TypeError, lambda: kinematic_equations([u1, u2, u3], q0, 'quaternion'))
raises(ValueError, lambda: kinematic_equations([u1, u2, u3], [q0, q1, q2, q3], 'body'))
raises(ValueError, lambda: kinematic_equations([u1, u2, u3], [q0, q1, q2, q3], 'space'))
raises(ValueError, lambda: kinematic_equations([u1, u2, u3], [q0, q1, q2], 'body', '222'))
assert kinematic_equations([0, 0, 0], [q0, q1, q2], 'space') == [S.Zero, S.Zero, S.Zero]
def test_partial_velocity():
q1, q2, q3, u1, u2, u3 = dynamicsymbols('q1 q2 q3 u1 u2 u3')
u4, u5 = dynamicsymbols('u4, u5')
r = symbols('r')
N = ReferenceFrame('N')
Y = N.orientnew('Y', 'Axis', [q1, N.z])
L = Y.orientnew('L', 'Axis', [q2, Y.x])
R = L.orientnew('R', 'Axis', [q3, L.y])
R.set_ang_vel(N, u1 * L.x + u2 * L.y + u3 * L.z)
C = Point('C')
C.set_vel(N, u4 * L.x + u5 * (Y.z ^ L.x))
Dmc = C.locatenew('Dmc', r * L.z)
Dmc.v2pt_theory(C, N, R)
vel_list = [Dmc.vel(N), C.vel(N), R.ang_vel_in(N)]
u_list = [u1, u2, u3, u4, u5]
assert (partial_velocity(vel_list, u_list, N) ==
[[- r*L.y, r*L.x, 0, L.x, cos(q2)*L.y - sin(q2)*L.z],
[0, 0, 0, L.x, cos(q2)*L.y - sin(q2)*L.z],
[L.x, L.y, L.z, 0, 0]])
# Make sure that partial velocities can be computed regardless if the
# orientation between frames is defined or not.
A = ReferenceFrame('A')
B = ReferenceFrame('B')
v = u4 * A.x + u5 * B.y
assert partial_velocity((v, ), (u4, u5), A) == [[A.x, B.y]]
raises(TypeError, lambda: partial_velocity(Dmc.vel(N), u_list, N))
raises(TypeError, lambda: partial_velocity(vel_list, u1, N))
def test_dynamicsymbols():
#Tests to check the assumptions applied to dynamicsymbols
f1 = dynamicsymbols('f1')
f2 = dynamicsymbols('f2', real=True)
f3 = dynamicsymbols('f3', positive=True)
f4, f5 = dynamicsymbols('f4,f5', commutative=False)
f6 = dynamicsymbols('f6', integer=True)
assert f1.is_real is None
assert f2.is_real
assert f3.is_positive
assert f4*f5 != f5*f4
assert f6.is_integer

View File

@ -0,0 +1,75 @@
from sympy.core.singleton import S
from sympy.physics.vector import Vector, ReferenceFrame, Dyadic
from sympy.testing.pytest import raises
A = ReferenceFrame('A')
def test_output_type():
A = ReferenceFrame('A')
v = A.x + A.y
d = v | v
zerov = Vector(0)
zerod = Dyadic(0)
# dot products
assert isinstance(d & d, Dyadic)
assert isinstance(d & zerod, Dyadic)
assert isinstance(zerod & d, Dyadic)
assert isinstance(d & v, Vector)
assert isinstance(v & d, Vector)
assert isinstance(d & zerov, Vector)
assert isinstance(zerov & d, Vector)
raises(TypeError, lambda: d & S.Zero)
raises(TypeError, lambda: S.Zero & d)
raises(TypeError, lambda: d & 0)
raises(TypeError, lambda: 0 & d)
assert not isinstance(v & v, (Vector, Dyadic))
assert not isinstance(v & zerov, (Vector, Dyadic))
assert not isinstance(zerov & v, (Vector, Dyadic))
raises(TypeError, lambda: v & S.Zero)
raises(TypeError, lambda: S.Zero & v)
raises(TypeError, lambda: v & 0)
raises(TypeError, lambda: 0 & v)
# cross products
raises(TypeError, lambda: d ^ d)
raises(TypeError, lambda: d ^ zerod)
raises(TypeError, lambda: zerod ^ d)
assert isinstance(d ^ v, Dyadic)
assert isinstance(v ^ d, Dyadic)
assert isinstance(d ^ zerov, Dyadic)
assert isinstance(zerov ^ d, Dyadic)
assert isinstance(zerov ^ d, Dyadic)
raises(TypeError, lambda: d ^ S.Zero)
raises(TypeError, lambda: S.Zero ^ d)
raises(TypeError, lambda: d ^ 0)
raises(TypeError, lambda: 0 ^ d)
assert isinstance(v ^ v, Vector)
assert isinstance(v ^ zerov, Vector)
assert isinstance(zerov ^ v, Vector)
raises(TypeError, lambda: v ^ S.Zero)
raises(TypeError, lambda: S.Zero ^ v)
raises(TypeError, lambda: v ^ 0)
raises(TypeError, lambda: 0 ^ v)
# outer products
raises(TypeError, lambda: d | d)
raises(TypeError, lambda: d | zerod)
raises(TypeError, lambda: zerod | d)
raises(TypeError, lambda: d | v)
raises(TypeError, lambda: v | d)
raises(TypeError, lambda: d | zerov)
raises(TypeError, lambda: zerov | d)
raises(TypeError, lambda: zerov | d)
raises(TypeError, lambda: d | S.Zero)
raises(TypeError, lambda: S.Zero | d)
raises(TypeError, lambda: d | 0)
raises(TypeError, lambda: 0 | d)
assert isinstance(v | v, Dyadic)
assert isinstance(v | zerov, Dyadic)
assert isinstance(zerov | v, Dyadic)
raises(TypeError, lambda: v | S.Zero)
raises(TypeError, lambda: S.Zero | v)
raises(TypeError, lambda: v | 0)
raises(TypeError, lambda: 0 | v)

View File

@ -0,0 +1,382 @@
from sympy.physics.vector import dynamicsymbols, Point, ReferenceFrame
from sympy.testing.pytest import raises, ignore_warnings
import warnings
def test_point_v1pt_theorys():
q, q2 = dynamicsymbols('q q2')
qd, q2d = dynamicsymbols('q q2', 1)
qdd, q2dd = dynamicsymbols('q q2', 2)
N = ReferenceFrame('N')
B = ReferenceFrame('B')
B.set_ang_vel(N, qd * B.z)
O = Point('O')
P = O.locatenew('P', B.x)
P.set_vel(B, 0)
O.set_vel(N, 0)
assert P.v1pt_theory(O, N, B) == qd * B.y
O.set_vel(N, N.x)
assert P.v1pt_theory(O, N, B) == N.x + qd * B.y
P.set_vel(B, B.z)
assert P.v1pt_theory(O, N, B) == B.z + N.x + qd * B.y
def test_point_a1pt_theorys():
q, q2 = dynamicsymbols('q q2')
qd, q2d = dynamicsymbols('q q2', 1)
qdd, q2dd = dynamicsymbols('q q2', 2)
N = ReferenceFrame('N')
B = ReferenceFrame('B')
B.set_ang_vel(N, qd * B.z)
O = Point('O')
P = O.locatenew('P', B.x)
P.set_vel(B, 0)
O.set_vel(N, 0)
assert P.a1pt_theory(O, N, B) == -(qd**2) * B.x + qdd * B.y
P.set_vel(B, q2d * B.z)
assert P.a1pt_theory(O, N, B) == -(qd**2) * B.x + qdd * B.y + q2dd * B.z
O.set_vel(N, q2d * B.x)
assert P.a1pt_theory(O, N, B) == ((q2dd - qd**2) * B.x + (q2d * qd + qdd) * B.y +
q2dd * B.z)
def test_point_v2pt_theorys():
q = dynamicsymbols('q')
qd = dynamicsymbols('q', 1)
N = ReferenceFrame('N')
B = N.orientnew('B', 'Axis', [q, N.z])
O = Point('O')
P = O.locatenew('P', 0)
O.set_vel(N, 0)
assert P.v2pt_theory(O, N, B) == 0
P = O.locatenew('P', B.x)
assert P.v2pt_theory(O, N, B) == (qd * B.z ^ B.x)
O.set_vel(N, N.x)
assert P.v2pt_theory(O, N, B) == N.x + qd * B.y
def test_point_a2pt_theorys():
q = dynamicsymbols('q')
qd = dynamicsymbols('q', 1)
qdd = dynamicsymbols('q', 2)
N = ReferenceFrame('N')
B = N.orientnew('B', 'Axis', [q, N.z])
O = Point('O')
P = O.locatenew('P', 0)
O.set_vel(N, 0)
assert P.a2pt_theory(O, N, B) == 0
P.set_pos(O, B.x)
assert P.a2pt_theory(O, N, B) == (-qd**2) * B.x + (qdd) * B.y
def test_point_funcs():
q, q2 = dynamicsymbols('q q2')
qd, q2d = dynamicsymbols('q q2', 1)
qdd, q2dd = dynamicsymbols('q q2', 2)
N = ReferenceFrame('N')
B = ReferenceFrame('B')
B.set_ang_vel(N, 5 * B.y)
O = Point('O')
P = O.locatenew('P', q * B.x + q2 * B.y)
assert P.pos_from(O) == q * B.x + q2 * B.y
P.set_vel(B, qd * B.x + q2d * B.y)
assert P.vel(B) == qd * B.x + q2d * B.y
O.set_vel(N, 0)
assert O.vel(N) == 0
assert P.a1pt_theory(O, N, B) == ((-25 * q + qdd) * B.x + (q2dd) * B.y +
(-10 * qd) * B.z)
B = N.orientnew('B', 'Axis', [q, N.z])
O = Point('O')
P = O.locatenew('P', 10 * B.x)
O.set_vel(N, 5 * N.x)
assert O.vel(N) == 5 * N.x
assert P.a2pt_theory(O, N, B) == (-10 * qd**2) * B.x + (10 * qdd) * B.y
B.set_ang_vel(N, 5 * B.y)
O = Point('O')
P = O.locatenew('P', q * B.x + q2 * B.y)
P.set_vel(B, qd * B.x + q2d * B.y)
O.set_vel(N, 0)
assert P.v1pt_theory(O, N, B) == qd * B.x + q2d * B.y - 5 * q * B.z
def test_point_pos():
q = dynamicsymbols('q')
N = ReferenceFrame('N')
B = N.orientnew('B', 'Axis', [q, N.z])
O = Point('O')
P = O.locatenew('P', 10 * N.x + 5 * B.x)
assert P.pos_from(O) == 10 * N.x + 5 * B.x
Q = P.locatenew('Q', 10 * N.y + 5 * B.y)
assert Q.pos_from(P) == 10 * N.y + 5 * B.y
assert Q.pos_from(O) == 10 * N.x + 10 * N.y + 5 * B.x + 5 * B.y
assert O.pos_from(Q) == -10 * N.x - 10 * N.y - 5 * B.x - 5 * B.y
def test_point_partial_velocity():
N = ReferenceFrame('N')
A = ReferenceFrame('A')
p = Point('p')
u1, u2 = dynamicsymbols('u1, u2')
p.set_vel(N, u1 * A.x + u2 * N.y)
assert p.partial_velocity(N, u1) == A.x
assert p.partial_velocity(N, u1, u2) == (A.x, N.y)
raises(ValueError, lambda: p.partial_velocity(A, u1))
def test_point_vel(): #Basic functionality
q1, q2 = dynamicsymbols('q1 q2')
N = ReferenceFrame('N')
B = ReferenceFrame('B')
Q = Point('Q')
O = Point('O')
Q.set_pos(O, q1 * N.x)
raises(ValueError , lambda: Q.vel(N)) # Velocity of O in N is not defined
O.set_vel(N, q2 * N.y)
assert O.vel(N) == q2 * N.y
raises(ValueError , lambda : O.vel(B)) #Velocity of O is not defined in B
def test_auto_point_vel():
t = dynamicsymbols._t
q1, q2 = dynamicsymbols('q1 q2')
N = ReferenceFrame('N')
B = ReferenceFrame('B')
O = Point('O')
Q = Point('Q')
Q.set_pos(O, q1 * N.x)
O.set_vel(N, q2 * N.y)
assert Q.vel(N) == q1.diff(t) * N.x + q2 * N.y # Velocity of Q using O
P1 = Point('P1')
P1.set_pos(O, q1 * B.x)
P2 = Point('P2')
P2.set_pos(P1, q2 * B.z)
raises(ValueError, lambda : P2.vel(B)) # O's velocity is defined in different frame, and no
#point in between has its velocity defined
raises(ValueError, lambda: P2.vel(N)) # Velocity of O not defined in N
def test_auto_point_vel_multiple_point_path():
t = dynamicsymbols._t
q1, q2 = dynamicsymbols('q1 q2')
B = ReferenceFrame('B')
P = Point('P')
P.set_vel(B, q1 * B.x)
P1 = Point('P1')
P1.set_pos(P, q2 * B.y)
P1.set_vel(B, q1 * B.z)
P2 = Point('P2')
P2.set_pos(P1, q1 * B.z)
P3 = Point('P3')
P3.set_pos(P2, 10 * q1 * B.y)
assert P3.vel(B) == 10 * q1.diff(t) * B.y + (q1 + q1.diff(t)) * B.z
def test_auto_vel_dont_overwrite():
t = dynamicsymbols._t
q1, q2, u1 = dynamicsymbols('q1, q2, u1')
N = ReferenceFrame('N')
P = Point('P1')
P.set_vel(N, u1 * N.x)
P1 = Point('P1')
P1.set_pos(P, q2 * N.y)
assert P1.vel(N) == q2.diff(t) * N.y + u1 * N.x
assert P.vel(N) == u1 * N.x
P1.set_vel(N, u1 * N.z)
assert P1.vel(N) == u1 * N.z
def test_auto_point_vel_if_tree_has_vel_but_inappropriate_pos_vector():
q1, q2 = dynamicsymbols('q1 q2')
B = ReferenceFrame('B')
S = ReferenceFrame('S')
P = Point('P')
P.set_vel(B, q1 * B.x)
P1 = Point('P1')
P1.set_pos(P, S.y)
raises(ValueError, lambda : P1.vel(B)) # P1.pos_from(P) can't be expressed in B
raises(ValueError, lambda : P1.vel(S)) # P.vel(S) not defined
def test_auto_point_vel_shortest_path():
t = dynamicsymbols._t
q1, q2, u1, u2 = dynamicsymbols('q1 q2 u1 u2')
B = ReferenceFrame('B')
P = Point('P')
P.set_vel(B, u1 * B.x)
P1 = Point('P1')
P1.set_pos(P, q2 * B.y)
P1.set_vel(B, q1 * B.z)
P2 = Point('P2')
P2.set_pos(P1, q1 * B.z)
P3 = Point('P3')
P3.set_pos(P2, 10 * q1 * B.y)
P4 = Point('P4')
P4.set_pos(P3, q1 * B.x)
O = Point('O')
O.set_vel(B, u2 * B.y)
O1 = Point('O1')
O1.set_pos(O, q2 * B.z)
P4.set_pos(O1, q1 * B.x + q2 * B.z)
with warnings.catch_warnings(): #There are two possible paths in this point tree, thus a warning is raised
warnings.simplefilter('error')
with ignore_warnings(UserWarning):
assert P4.vel(B) == q1.diff(t) * B.x + u2 * B.y + 2 * q2.diff(t) * B.z
def test_auto_point_vel_connected_frames():
t = dynamicsymbols._t
q, q1, q2, u = dynamicsymbols('q q1 q2 u')
N = ReferenceFrame('N')
B = ReferenceFrame('B')
O = Point('O')
O.set_vel(N, u * N.x)
P = Point('P')
P.set_pos(O, q1 * N.x + q2 * B.y)
raises(ValueError, lambda: P.vel(N))
N.orient(B, 'Axis', (q, B.x))
assert P.vel(N) == (u + q1.diff(t)) * N.x + q2.diff(t) * B.y - q2 * q.diff(t) * B.z
def test_auto_point_vel_multiple_paths_warning_arises():
q, u = dynamicsymbols('q u')
N = ReferenceFrame('N')
O = Point('O')
P = Point('P')
Q = Point('Q')
R = Point('R')
P.set_vel(N, u * N.x)
Q.set_vel(N, u *N.y)
R.set_vel(N, u * N.z)
O.set_pos(P, q * N.z)
O.set_pos(Q, q * N.y)
O.set_pos(R, q * N.x)
with warnings.catch_warnings(): #There are two possible paths in this point tree, thus a warning is raised
warnings.simplefilter("error")
raises(UserWarning ,lambda: O.vel(N))
def test_auto_vel_cyclic_warning_arises():
P = Point('P')
P1 = Point('P1')
P2 = Point('P2')
P3 = Point('P3')
N = ReferenceFrame('N')
P.set_vel(N, N.x)
P1.set_pos(P, N.x)
P2.set_pos(P1, N.y)
P3.set_pos(P2, N.z)
P1.set_pos(P3, N.x + N.y)
with warnings.catch_warnings(): #The path is cyclic at P1, thus a warning is raised
warnings.simplefilter("error")
raises(UserWarning ,lambda: P2.vel(N))
def test_auto_vel_cyclic_warning_msg():
P = Point('P')
P1 = Point('P1')
P2 = Point('P2')
P3 = Point('P3')
N = ReferenceFrame('N')
P.set_vel(N, N.x)
P1.set_pos(P, N.x)
P2.set_pos(P1, N.y)
P3.set_pos(P2, N.z)
P1.set_pos(P3, N.x + N.y)
with warnings.catch_warnings(record = True) as w: #The path is cyclic at P1, thus a warning is raised
warnings.simplefilter("always")
P2.vel(N)
msg = str(w[-1].message).replace("\n", " ")
assert issubclass(w[-1].category, UserWarning)
assert 'Kinematic loops are defined among the positions of points. This is likely not desired and may cause errors in your calculations.' in msg
def test_auto_vel_multiple_path_warning_msg():
N = ReferenceFrame('N')
O = Point('O')
P = Point('P')
Q = Point('Q')
P.set_vel(N, N.x)
Q.set_vel(N, N.y)
O.set_pos(P, N.z)
O.set_pos(Q, N.y)
with warnings.catch_warnings(record = True) as w: #There are two possible paths in this point tree, thus a warning is raised
warnings.simplefilter("always")
O.vel(N)
msg = str(w[-1].message).replace("\n", " ")
assert issubclass(w[-1].category, UserWarning)
assert 'Velocity' in msg
assert 'automatically calculated based on point' in msg
assert 'Velocities from these points are not necessarily the same. This may cause errors in your calculations.' in msg
def test_auto_vel_derivative():
q1, q2 = dynamicsymbols('q1:3')
u1, u2 = dynamicsymbols('u1:3', 1)
A = ReferenceFrame('A')
B = ReferenceFrame('B')
C = ReferenceFrame('C')
B.orient_axis(A, A.z, q1)
B.set_ang_vel(A, u1 * A.z)
C.orient_axis(B, B.z, q2)
C.set_ang_vel(B, u2 * B.z)
Am = Point('Am')
Am.set_vel(A, 0)
Bm = Point('Bm')
Bm.set_pos(Am, B.x)
Bm.set_vel(B, 0)
Bm.set_vel(C, 0)
Cm = Point('Cm')
Cm.set_pos(Bm, C.x)
Cm.set_vel(C, 0)
temp = Cm._vel_dict.copy()
assert Cm.vel(A) == (u1 * B.y + (u1 + u2) * C.y)
Cm._vel_dict = temp
Cm.v2pt_theory(Bm, B, C)
assert Cm.vel(A) == (u1 * B.y + (u1 + u2) * C.y)
def test_auto_point_acc_zero_vel():
N = ReferenceFrame('N')
O = Point('O')
O.set_vel(N, 0)
assert O.acc(N) == 0 * N.x
def test_auto_point_acc_compute_vel():
t = dynamicsymbols._t
q1 = dynamicsymbols('q1')
N = ReferenceFrame('N')
A = ReferenceFrame('A')
A.orient_axis(N, N.z, q1)
O = Point('O')
O.set_vel(N, 0)
P = Point('P')
P.set_pos(O, A.x)
assert P.acc(N) == -q1.diff(t) ** 2 * A.x + q1.diff(t, 2) * A.y
def test_auto_acc_derivative():
# Tests whether the Point.acc method gives the correct acceleration of the
# end point of two linkages in series, while getting minimal information.
q1, q2 = dynamicsymbols('q1:3')
u1, u2 = dynamicsymbols('q1:3', 1)
v1, v2 = dynamicsymbols('q1:3', 2)
A = ReferenceFrame('A')
B = ReferenceFrame('B')
C = ReferenceFrame('C')
B.orient_axis(A, A.z, q1)
C.orient_axis(B, B.z, q2)
Am = Point('Am')
Am.set_vel(A, 0)
Bm = Point('Bm')
Bm.set_pos(Am, B.x)
Bm.set_vel(B, 0)
Bm.set_vel(C, 0)
Cm = Point('Cm')
Cm.set_pos(Bm, C.x)
Cm.set_vel(C, 0)
# Copy dictionaries to later check the calculation using the 2pt_theories
Bm_vel_dict, Cm_vel_dict = Bm._vel_dict.copy(), Cm._vel_dict.copy()
Bm_acc_dict, Cm_acc_dict = Bm._acc_dict.copy(), Cm._acc_dict.copy()
check = -u1 ** 2 * B.x + v1 * B.y - (u1 + u2) ** 2 * C.x + (v1 + v2) * C.y
assert Cm.acc(A) == check
Bm._vel_dict, Cm._vel_dict = Bm_vel_dict, Cm_vel_dict
Bm._acc_dict, Cm._acc_dict = Bm_acc_dict, Cm_acc_dict
Bm.v2pt_theory(Am, A, B)
Cm.v2pt_theory(Bm, A, C)
Bm.a2pt_theory(Am, A, B)
assert Cm.a2pt_theory(Bm, A, C) == check

View File

@ -0,0 +1,353 @@
# -*- coding: utf-8 -*-
from sympy.core.function import Function
from sympy.core.symbol import symbols
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.functions.elementary.trigonometric import (asin, cos, sin)
from sympy.physics.vector import ReferenceFrame, dynamicsymbols, Dyadic
from sympy.physics.vector.printing import (VectorLatexPrinter, vpprint,
vsprint, vsstrrepr, vlatex)
a, b, c = symbols('a, b, c')
alpha, omega, beta = dynamicsymbols('alpha, omega, beta')
A = ReferenceFrame('A')
N = ReferenceFrame('N')
v = a ** 2 * N.x + b * N.y + c * sin(alpha) * N.z
w = alpha * N.x + sin(omega) * N.y + alpha * beta * N.z
ww = alpha * N.x + asin(omega) * N.y - alpha.diff() * beta * N.z
o = a/b * N.x + (c+b)/a * N.y + c**2/b * N.z
y = a ** 2 * (N.x | N.y) + b * (N.y | N.y) + c * sin(alpha) * (N.z | N.y)
x = alpha * (N.x | N.x) + sin(omega) * (N.y | N.z) + alpha * beta * (N.z | N.x)
xx = N.x | (-N.y - N.z)
xx2 = N.x | (N.y + N.z)
def ascii_vpretty(expr):
return vpprint(expr, use_unicode=False, wrap_line=False)
def unicode_vpretty(expr):
return vpprint(expr, use_unicode=True, wrap_line=False)
def test_latex_printer():
r = Function('r')('t')
assert VectorLatexPrinter().doprint(r ** 2) == "r^{2}"
r2 = Function('r^2')('t')
assert VectorLatexPrinter().doprint(r2.diff()) == r'\dot{r^{2}}'
ra = Function('r__a')('t')
assert VectorLatexPrinter().doprint(ra.diff().diff()) == r'\ddot{r^{a}}'
def test_vector_pretty_print():
# TODO : The unit vectors should print with subscripts but they just
# print as `n_x` instead of making `x` a subscript with unicode.
# TODO : The pretty print division does not print correctly here:
# w = alpha * N.x + sin(omega) * N.y + alpha / beta * N.z
expected = """\
2 \n\
a n_x + b n_y + c*sin(alpha) n_z\
"""
uexpected = """\
2 \n\
a n_x + b n_y + c⋅sin(α) n_z\
"""
assert ascii_vpretty(v) == expected
assert unicode_vpretty(v) == uexpected
expected = 'alpha n_x + sin(omega) n_y + alpha*beta n_z'
uexpected = 'α n_x + sin(ω) n_y + α⋅β n_z'
assert ascii_vpretty(w) == expected
assert unicode_vpretty(w) == uexpected
expected = """\
2 \n\
a b + c c \n\
- n_x + ----- n_y + -- n_z\n\
b a b \
"""
uexpected = """\
2 \n\
a b + c c \n\
─ n_x + ───── n_y + ── n_z\n\
b a b \
"""
assert ascii_vpretty(o) == expected
assert unicode_vpretty(o) == uexpected
# https://github.com/sympy/sympy/issues/26731
assert ascii_vpretty(-A.x) == '-a_x'
assert unicode_vpretty(-A.x) == '-a_x'
# https://github.com/sympy/sympy/issues/26799
assert ascii_vpretty(0*A.x) == '0'
assert unicode_vpretty(0*A.x) == '0'
def test_vector_latex():
a, b, c, d, omega = symbols('a, b, c, d, omega')
v = (a ** 2 + b / c) * A.x + sqrt(d) * A.y + cos(omega) * A.z
assert vlatex(v) == (r'(a^{2} + \frac{b}{c})\mathbf{\hat{a}_x} + '
r'\sqrt{d}\mathbf{\hat{a}_y} + '
r'\cos{\left(\omega \right)}'
r'\mathbf{\hat{a}_z}')
theta, omega, alpha, q = dynamicsymbols('theta, omega, alpha, q')
v = theta * A.x + omega * omega * A.y + (q * alpha) * A.z
assert vlatex(v) == (r'\theta\mathbf{\hat{a}_x} + '
r'\omega^{2}\mathbf{\hat{a}_y} + '
r'\alpha q\mathbf{\hat{a}_z}')
phi1, phi2, phi3 = dynamicsymbols('phi1, phi2, phi3')
theta1, theta2, theta3 = symbols('theta1, theta2, theta3')
v = (sin(theta1) * A.x +
cos(phi1) * cos(phi2) * A.y +
cos(theta1 + phi3) * A.z)
assert vlatex(v) == (r'\sin{\left(\theta_{1} \right)}'
r'\mathbf{\hat{a}_x} + \cos{'
r'\left(\phi_{1} \right)} \cos{'
r'\left(\phi_{2} \right)}\mathbf{\hat{a}_y} + '
r'\cos{\left(\theta_{1} + '
r'\phi_{3} \right)}\mathbf{\hat{a}_z}')
N = ReferenceFrame('N')
a, b, c, d, omega = symbols('a, b, c, d, omega')
v = (a ** 2 + b / c) * N.x + sqrt(d) * N.y + cos(omega) * N.z
expected = (r'(a^{2} + \frac{b}{c})\mathbf{\hat{n}_x} + '
r'\sqrt{d}\mathbf{\hat{n}_y} + '
r'\cos{\left(\omega \right)}'
r'\mathbf{\hat{n}_z}')
assert vlatex(v) == expected
# Try custom unit vectors.
N = ReferenceFrame('N', latexs=(r'\hat{i}', r'\hat{j}', r'\hat{k}'))
v = (a ** 2 + b / c) * N.x + sqrt(d) * N.y + cos(omega) * N.z
expected = (r'(a^{2} + \frac{b}{c})\hat{i} + '
r'\sqrt{d}\hat{j} + '
r'\cos{\left(\omega \right)}\hat{k}')
assert vlatex(v) == expected
expected = r'\alpha\mathbf{\hat{n}_x} + \operatorname{asin}{\left(\omega ' \
r'\right)}\mathbf{\hat{n}_y} - \beta \dot{\alpha}\mathbf{\hat{n}_z}'
assert vlatex(ww) == expected
expected = r'- \mathbf{\hat{n}_x}\otimes \mathbf{\hat{n}_y} - ' \
r'\mathbf{\hat{n}_x}\otimes \mathbf{\hat{n}_z}'
assert vlatex(xx) == expected
expected = r'\mathbf{\hat{n}_x}\otimes \mathbf{\hat{n}_y} + ' \
r'\mathbf{\hat{n}_x}\otimes \mathbf{\hat{n}_z}'
assert vlatex(xx2) == expected
def test_vector_latex_arguments():
assert vlatex(N.x * 3.0, full_prec=False) == r'3.0\mathbf{\hat{n}_x}'
assert vlatex(N.x * 3.0, full_prec=True) == r'3.00000000000000\mathbf{\hat{n}_x}'
def test_vector_latex_with_functions():
N = ReferenceFrame('N')
omega, alpha = dynamicsymbols('omega, alpha')
v = omega.diff() * N.x
assert vlatex(v) == r'\dot{\omega}\mathbf{\hat{n}_x}'
v = omega.diff() ** alpha * N.x
assert vlatex(v) == (r'\dot{\omega}^{\alpha}'
r'\mathbf{\hat{n}_x}')
def test_dyadic_pretty_print():
expected = """\
2
a n_x|n_y + b n_y|n_y + c*sin(alpha) n_z|n_y\
"""
uexpected = """\
2
a n_x⊗n_y + b n_y⊗n_y + c⋅sin(α) n_z⊗n_y\
"""
assert ascii_vpretty(y) == expected
assert unicode_vpretty(y) == uexpected
expected = 'alpha n_x|n_x + sin(omega) n_y|n_z + alpha*beta n_z|n_x'
uexpected = 'α n_x⊗n_x + sin(ω) n_y⊗n_z + α⋅β n_z⊗n_x'
assert ascii_vpretty(x) == expected
assert unicode_vpretty(x) == uexpected
assert ascii_vpretty(Dyadic([])) == '0'
assert unicode_vpretty(Dyadic([])) == '0'
assert ascii_vpretty(xx) == '- n_x|n_y - n_x|n_z'
assert unicode_vpretty(xx) == '- n_x⊗n_y - n_x⊗n_z'
assert ascii_vpretty(xx2) == 'n_x|n_y + n_x|n_z'
assert unicode_vpretty(xx2) == 'n_x⊗n_y + n_x⊗n_z'
def test_dyadic_latex():
expected = (r'a^{2}\mathbf{\hat{n}_x}\otimes \mathbf{\hat{n}_y} + '
r'b\mathbf{\hat{n}_y}\otimes \mathbf{\hat{n}_y} + '
r'c \sin{\left(\alpha \right)}'
r'\mathbf{\hat{n}_z}\otimes \mathbf{\hat{n}_y}')
assert vlatex(y) == expected
expected = (r'\alpha\mathbf{\hat{n}_x}\otimes \mathbf{\hat{n}_x} + '
r'\sin{\left(\omega \right)}\mathbf{\hat{n}_y}'
r'\otimes \mathbf{\hat{n}_z} + '
r'\alpha \beta\mathbf{\hat{n}_z}\otimes \mathbf{\hat{n}_x}')
assert vlatex(x) == expected
assert vlatex(Dyadic([])) == '0'
def test_dyadic_str():
assert vsprint(Dyadic([])) == '0'
assert vsprint(y) == 'a**2*(N.x|N.y) + b*(N.y|N.y) + c*sin(alpha)*(N.z|N.y)'
assert vsprint(x) == 'alpha*(N.x|N.x) + sin(omega)*(N.y|N.z) + alpha*beta*(N.z|N.x)'
assert vsprint(ww) == "alpha*N.x + asin(omega)*N.y - beta*alpha'*N.z"
assert vsprint(xx) == '- (N.x|N.y) - (N.x|N.z)'
assert vsprint(xx2) == '(N.x|N.y) + (N.x|N.z)'
def test_vlatex(): # vlatex is broken #12078
from sympy.physics.vector import vlatex
x = symbols('x')
J = symbols('J')
f = Function('f')
g = Function('g')
h = Function('h')
expected = r'J \left(\frac{d}{d x} g{\left(x \right)} - \frac{d}{d x} h{\left(x \right)}\right)'
expr = J*f(x).diff(x).subs(f(x), g(x)-h(x))
assert vlatex(expr) == expected
def test_issue_13354():
"""
Test for proper pretty printing of physics vectors with ADD
instances in arguments.
Test is exactly the one suggested in the original bug report by
@moorepants.
"""
a, b, c = symbols('a, b, c')
A = ReferenceFrame('A')
v = a * A.x + b * A.y + c * A.z
w = b * A.x + c * A.y + a * A.z
z = w + v
expected = """(a + b) a_x + (b + c) a_y + (a + c) a_z"""
assert ascii_vpretty(z) == expected
def test_vector_derivative_printing():
# First order
v = omega.diff() * N.x
assert unicode_vpretty(v) == 'ω̇ n_x'
assert ascii_vpretty(v) == "omega'(t) n_x"
# Second order
v = omega.diff().diff() * N.x
assert vlatex(v) == r'\ddot{\omega}\mathbf{\hat{n}_x}'
assert unicode_vpretty(v) == 'ω̈ n_x'
assert ascii_vpretty(v) == "omega''(t) n_x"
# Third order
v = omega.diff().diff().diff() * N.x
assert vlatex(v) == r'\dddot{\omega}\mathbf{\hat{n}_x}'
assert unicode_vpretty(v) == 'ω⃛ n_x'
assert ascii_vpretty(v) == "omega'''(t) n_x"
# Fourth order
v = omega.diff().diff().diff().diff() * N.x
assert vlatex(v) == r'\ddddot{\omega}\mathbf{\hat{n}_x}'
assert unicode_vpretty(v) == 'ω⃜ n_x'
assert ascii_vpretty(v) == "omega''''(t) n_x"
# Fifth order
v = omega.diff().diff().diff().diff().diff() * N.x
assert vlatex(v) == r'\frac{d^{5}}{d t^{5}} \omega\mathbf{\hat{n}_x}'
expected = '''\
5 \n\
d \n\
---(omega) n_x\n\
5 \n\
dt \
'''
uexpected = '''\
5 \n\
d \n\
───(ω) n_x\n\
5 \n\
dt \
'''
assert unicode_vpretty(v) == uexpected
assert ascii_vpretty(v) == expected
def test_vector_str_printing():
assert vsprint(w) == 'alpha*N.x + sin(omega)*N.y + alpha*beta*N.z'
assert vsprint(omega.diff() * N.x) == "omega'*N.x"
assert vsstrrepr(w) == 'alpha*N.x + sin(omega)*N.y + alpha*beta*N.z'
def test_vector_str_arguments():
assert vsprint(N.x * 3.0, full_prec=False) == '3.0*N.x'
assert vsprint(N.x * 3.0, full_prec=True) == '3.00000000000000*N.x'
def test_issue_14041():
import sympy.physics.mechanics as me
A_frame = me.ReferenceFrame('A')
thetad, phid = me.dynamicsymbols('theta, phi', 1)
L = symbols('L')
assert vlatex(L*(phid + thetad)**2*A_frame.x) == \
r"L \left(\dot{\phi} + \dot{\theta}\right)^{2}\mathbf{\hat{a}_x}"
assert vlatex((phid + thetad)**2*A_frame.x) == \
r"\left(\dot{\phi} + \dot{\theta}\right)^{2}\mathbf{\hat{a}_x}"
assert vlatex((phid*thetad)**a*A_frame.x) == \
r"\left(\dot{\phi} \dot{\theta}\right)^{a}\mathbf{\hat{a}_x}"

View File

@ -0,0 +1,274 @@
from sympy.core.numbers import (Float, pi)
from sympy.core.symbol import symbols
from sympy.core.sorting import ordered
from sympy.functions.elementary.trigonometric import (cos, sin)
from sympy.matrices.immutable import ImmutableDenseMatrix as Matrix
from sympy.physics.vector import ReferenceFrame, Vector, dynamicsymbols, dot
from sympy.physics.vector.vector import VectorTypeError
from sympy.abc import x, y, z
from sympy.testing.pytest import raises
A = ReferenceFrame('A')
def test_free_dynamicsymbols():
A, B, C, D = symbols('A, B, C, D', cls=ReferenceFrame)
a, b, c, d, e, f = dynamicsymbols('a, b, c, d, e, f')
B.orient_axis(A, a, A.x)
C.orient_axis(B, b, B.y)
D.orient_axis(C, c, C.x)
v = d*D.x + e*D.y + f*D.z
assert set(ordered(v.free_dynamicsymbols(A))) == {a, b, c, d, e, f}
assert set(ordered(v.free_dynamicsymbols(B))) == {b, c, d, e, f}
assert set(ordered(v.free_dynamicsymbols(C))) == {c, d, e, f}
assert set(ordered(v.free_dynamicsymbols(D))) == {d, e, f}
def test_Vector():
assert A.x != A.y
assert A.y != A.z
assert A.z != A.x
assert A.x + 0 == A.x
v1 = x*A.x + y*A.y + z*A.z
v2 = x**2*A.x + y**2*A.y + z**2*A.z
v3 = v1 + v2
v4 = v1 - v2
assert isinstance(v1, Vector)
assert dot(v1, A.x) == x
assert dot(v1, A.y) == y
assert dot(v1, A.z) == z
assert isinstance(v2, Vector)
assert dot(v2, A.x) == x**2
assert dot(v2, A.y) == y**2
assert dot(v2, A.z) == z**2
assert isinstance(v3, Vector)
# We probably shouldn't be using simplify in dot...
assert dot(v3, A.x) == x**2 + x
assert dot(v3, A.y) == y**2 + y
assert dot(v3, A.z) == z**2 + z
assert isinstance(v4, Vector)
# We probably shouldn't be using simplify in dot...
assert dot(v4, A.x) == x - x**2
assert dot(v4, A.y) == y - y**2
assert dot(v4, A.z) == z - z**2
assert v1.to_matrix(A) == Matrix([[x], [y], [z]])
q = symbols('q')
B = A.orientnew('B', 'Axis', (q, A.x))
assert v1.to_matrix(B) == Matrix([[x],
[ y * cos(q) + z * sin(q)],
[-y * sin(q) + z * cos(q)]])
#Test the separate method
B = ReferenceFrame('B')
v5 = x*A.x + y*A.y + z*B.z
assert Vector(0).separate() == {}
assert v1.separate() == {A: v1}
assert v5.separate() == {A: x*A.x + y*A.y, B: z*B.z}
#Test the free_symbols property
v6 = x*A.x + y*A.y + z*A.z
assert v6.free_symbols(A) == {x,y,z}
raises(TypeError, lambda: v3.applyfunc(v1))
def test_Vector_diffs():
q1, q2, q3, q4 = dynamicsymbols('q1 q2 q3 q4')
q1d, q2d, q3d, q4d = dynamicsymbols('q1 q2 q3 q4', 1)
q1dd, q2dd, q3dd, q4dd = dynamicsymbols('q1 q2 q3 q4', 2)
N = ReferenceFrame('N')
A = N.orientnew('A', 'Axis', [q3, N.z])
B = A.orientnew('B', 'Axis', [q2, A.x])
v1 = q2 * A.x + q3 * N.y
v2 = q3 * B.x + v1
v3 = v1.dt(B)
v4 = v2.dt(B)
v5 = q1*A.x + q2*A.y + q3*A.z
assert v1.dt(N) == q2d * A.x + q2 * q3d * A.y + q3d * N.y
assert v1.dt(A) == q2d * A.x + q3 * q3d * N.x + q3d * N.y
assert v1.dt(B) == (q2d * A.x + q3 * q3d * N.x + q3d *
N.y - q3 * cos(q3) * q2d * N.z)
assert v2.dt(N) == (q2d * A.x + (q2 + q3) * q3d * A.y + q3d * B.x + q3d *
N.y)
assert v2.dt(A) == q2d * A.x + q3d * B.x + q3 * q3d * N.x + q3d * N.y
assert v2.dt(B) == (q2d * A.x + q3d * B.x + q3 * q3d * N.x + q3d * N.y -
q3 * cos(q3) * q2d * N.z)
assert v3.dt(N) == (q2dd * A.x + q2d * q3d * A.y + (q3d**2 + q3 * q3dd) *
N.x + q3dd * N.y + (q3 * sin(q3) * q2d * q3d -
cos(q3) * q2d * q3d - q3 * cos(q3) * q2dd) * N.z)
assert v3.dt(A) == (q2dd * A.x + (2 * q3d**2 + q3 * q3dd) * N.x + (q3dd -
q3 * q3d**2) * N.y + (q3 * sin(q3) * q2d * q3d -
cos(q3) * q2d * q3d - q3 * cos(q3) * q2dd) * N.z)
assert (v3.dt(B) - (q2dd*A.x - q3*cos(q3)*q2d**2*A.y + (2*q3d**2 +
q3*q3dd)*N.x + (q3dd - q3*q3d**2)*N.y + (2*q3*sin(q3)*q2d*q3d -
2*cos(q3)*q2d*q3d - q3*cos(q3)*q2dd)*N.z)).express(B).simplify() == 0
assert v4.dt(N) == (q2dd * A.x + q3d * (q2d + q3d) * A.y + q3dd * B.x +
(q3d**2 + q3 * q3dd) * N.x + q3dd * N.y + (q3 *
sin(q3) * q2d * q3d - cos(q3) * q2d * q3d - q3 *
cos(q3) * q2dd) * N.z)
assert v4.dt(A) == (q2dd * A.x + q3dd * B.x + (2 * q3d**2 + q3 * q3dd) *
N.x + (q3dd - q3 * q3d**2) * N.y + (q3 * sin(q3) *
q2d * q3d - cos(q3) * q2d * q3d - q3 * cos(q3) *
q2dd) * N.z)
assert (v4.dt(B) - (q2dd*A.x - q3*cos(q3)*q2d**2*A.y + q3dd*B.x +
(2*q3d**2 + q3*q3dd)*N.x + (q3dd - q3*q3d**2)*N.y +
(2*q3*sin(q3)*q2d*q3d - 2*cos(q3)*q2d*q3d -
q3*cos(q3)*q2dd)*N.z)).express(B).simplify() == 0
assert v5.dt(B) == q1d*A.x + (q3*q2d + q2d)*A.y + (-q2*q2d + q3d)*A.z
assert v5.dt(A) == q1d*A.x + q2d*A.y + q3d*A.z
assert v5.dt(N) == (-q2*q3d + q1d)*A.x + (q1*q3d + q2d)*A.y + q3d*A.z
assert v3.diff(q1d, N) == 0
assert v3.diff(q2d, N) == A.x - q3 * cos(q3) * N.z
assert v3.diff(q3d, N) == q3 * N.x + N.y
assert v3.diff(q1d, A) == 0
assert v3.diff(q2d, A) == A.x - q3 * cos(q3) * N.z
assert v3.diff(q3d, A) == q3 * N.x + N.y
assert v3.diff(q1d, B) == 0
assert v3.diff(q2d, B) == A.x - q3 * cos(q3) * N.z
assert v3.diff(q3d, B) == q3 * N.x + N.y
assert v4.diff(q1d, N) == 0
assert v4.diff(q2d, N) == A.x - q3 * cos(q3) * N.z
assert v4.diff(q3d, N) == B.x + q3 * N.x + N.y
assert v4.diff(q1d, A) == 0
assert v4.diff(q2d, A) == A.x - q3 * cos(q3) * N.z
assert v4.diff(q3d, A) == B.x + q3 * N.x + N.y
assert v4.diff(q1d, B) == 0
assert v4.diff(q2d, B) == A.x - q3 * cos(q3) * N.z
assert v4.diff(q3d, B) == B.x + q3 * N.x + N.y
# diff() should only express vector components in the derivative frame if
# the orientation of the component's frame depends on the variable
v6 = q2**2*N.y + q2**2*A.y + q2**2*B.y
# already expressed in N
n_measy = 2*q2
# A_C_N does not depend on q2, so don't express in N
a_measy = 2*q2
# B_C_N depends on q2, so express in N
b_measx = (q2**2*B.y).dot(N.x).diff(q2)
b_measy = (q2**2*B.y).dot(N.y).diff(q2)
b_measz = (q2**2*B.y).dot(N.z).diff(q2)
n_comp, a_comp = v6.diff(q2, N).args
assert len(v6.diff(q2, N).args) == 2 # only N and A parts
assert n_comp[1] == N
assert a_comp[1] == A
assert n_comp[0] == Matrix([b_measx, b_measy + n_measy, b_measz])
assert a_comp[0] == Matrix([0, a_measy, 0])
def test_vector_var_in_dcm():
N = ReferenceFrame('N')
A = ReferenceFrame('A')
B = ReferenceFrame('B')
u1, u2, u3, u4 = dynamicsymbols('u1 u2 u3 u4')
v = u1 * u2 * A.x + u3 * N.y + u4**2 * N.z
assert v.diff(u1, N, var_in_dcm=False) == u2 * A.x
assert v.diff(u1, A, var_in_dcm=False) == u2 * A.x
assert v.diff(u3, N, var_in_dcm=False) == N.y
assert v.diff(u3, A, var_in_dcm=False) == N.y
assert v.diff(u3, B, var_in_dcm=False) == N.y
assert v.diff(u4, N, var_in_dcm=False) == 2 * u4 * N.z
raises(ValueError, lambda: v.diff(u1, N))
def test_vector_simplify():
x, y, z, k, n, m, w, f, s, A = symbols('x, y, z, k, n, m, w, f, s, A')
N = ReferenceFrame('N')
test1 = (1 / x + 1 / y) * N.x
assert (test1 & N.x) != (x + y) / (x * y)
test1 = test1.simplify()
assert (test1 & N.x) == (x + y) / (x * y)
test2 = (A**2 * s**4 / (4 * pi * k * m**3)) * N.x
test2 = test2.simplify()
assert (test2 & N.x) == (A**2 * s**4 / (4 * pi * k * m**3))
test3 = ((4 + 4 * x - 2 * (2 + 2 * x)) / (2 + 2 * x)) * N.x
test3 = test3.simplify()
assert (test3 & N.x) == 0
test4 = ((-4 * x * y**2 - 2 * y**3 - 2 * x**2 * y) / (x + y)**2) * N.x
test4 = test4.simplify()
assert (test4 & N.x) == -2 * y
def test_vector_evalf():
a, b = symbols('a b')
v = pi * A.x
assert v.evalf(2) == Float('3.1416', 2) * A.x
v = pi * A.x + 5 * a * A.y - b * A.z
assert v.evalf(3) == Float('3.1416', 3) * A.x + Float('5', 3) * a * A.y - b * A.z
assert v.evalf(5, subs={a: 1.234, b:5.8973}) == Float('3.1415926536', 5) * A.x + Float('6.17', 5) * A.y - Float('5.8973', 5) * A.z
def test_vector_angle():
A = ReferenceFrame('A')
v1 = A.x + A.y
v2 = A.z
assert v1.angle_between(v2) == pi/2
B = ReferenceFrame('B')
B.orient_axis(A, A.x, pi)
v3 = A.x
v4 = B.x
assert v3.angle_between(v4) == 0
def test_vector_xreplace():
x, y, z = symbols('x y z')
v = x**2 * A.x + x*y * A.y + x*y*z * A.z
assert v.xreplace({x : cos(x)}) == cos(x)**2 * A.x + y*cos(x) * A.y + y*z*cos(x) * A.z
assert v.xreplace({x*y : pi}) == x**2 * A.x + pi * A.y + x*y*z * A.z
assert v.xreplace({x*y*z : 1}) == x**2*A.x + x*y*A.y + A.z
assert v.xreplace({x:1, z:0}) == A.x + y * A.y
raises(TypeError, lambda: v.xreplace())
raises(TypeError, lambda: v.xreplace([x, y]))
def test_issue_23366():
u1 = dynamicsymbols('u1')
N = ReferenceFrame('N')
N_v_A = u1*N.x
raises(VectorTypeError, lambda: N_v_A.diff(N, u1))
def test_vector_outer():
a, b, c, d, e, f = symbols('a, b, c, d, e, f')
N = ReferenceFrame('N')
v1 = a*N.x + b*N.y + c*N.z
v2 = d*N.x + e*N.y + f*N.z
v1v2 = Matrix([[a*d, a*e, a*f],
[b*d, b*e, b*f],
[c*d, c*e, c*f]])
assert v1.outer(v2).to_matrix(N) == v1v2
assert (v1 | v2).to_matrix(N) == v1v2
v2v1 = Matrix([[d*a, d*b, d*c],
[e*a, e*b, e*c],
[f*a, f*b, f*c]])
assert v2.outer(v1).to_matrix(N) == v2v1
assert (v2 | v1).to_matrix(N) == v2v1
def test_overloaded_operators():
a, b, c, d, e, f = symbols('a, b, c, d, e, f')
N = ReferenceFrame('N')
v1 = a*N.x + b*N.y + c*N.z
v2 = d*N.x + e*N.y + f*N.z
assert v1 + v2 == v2 + v1
assert v1 - v2 == -v2 + v1
assert v1 & v2 == v2 & v1
assert v1 ^ v2 == v1.cross(v2)
assert v2 ^ v1 == v2.cross(v1)