SymPy 力学 适用于 Autolev 用户

介绍

Autolev(现已被MotionGenesis取代)是一种用于符号多体动力学的特定领域编程语言。SymPy力学模块现在具有足够的功能和能力,可以成为一个功能齐全的符号动力学模块。PyDy包扩展了SymPy的输出,使其适用于数值模拟、分析和可视化。Autolev和SymPy力学有很多共同点,但它们之间也存在许多差异。本页将详细阐述这些差异。它旨在为希望过渡到SymPy力学的Autolev用户提供参考。

在阅读此页面前,最好对 SymPy 和 SymPy 力学有一个基本的了解。如果你完全不熟悉 Python,可以查看官方的 Python 教程。查看 SymPy 文档,特别是教程,以了解 SymPy 的使用。对于 Python 中多体动力学的介绍,这个 讲座非常有帮助。

您可能还会发现 Autolev 解析器 ,这是 SymPy 的一部分,对您有所帮助。

一些关键差异

Autolev

SymPy 力学

Autolev 是一种专门用于多体动力学的编程语言。由于它是一种独立的语言,因此具有非常严格的语言规范。它根据输入代码预定义、假设并计算许多内容。因此,其代码非常简洁。
SymPy 是一个用通用语言 Python 编写的库。尽管 Autolev 的代码更紧凑,但 SymPy(由于是 Python 的附加组件)更加灵活。用户对其所能做的事情有更多的控制权。例如,可以在他们的代码中为某种具有共同属性的刚体创建一个类。可用的广泛的科学 Python 库也是一个很大的优势。
Autolev 从一小部分符号数学中生成 Matlab、C 或 Fortran 代码。
SymPy 从使用 SymPy 创建的大量符号数学中生成数值 Python、C 或 Octave/Matlab 代码。它还基于流行的科学 Python 堆栈,如 NumPy、SciPy、IPython、matplotlib、Cython 和 Theano。
Autolev 使用基于 1 的索引。序列的初始元素通过 a[1] 找到。
Python 使用 0(零)为基础的索引。序列的初始元素通过 a[0] 找到。
Autolev 是不区分大小写的。
SymPy 代码作为 Python 代码是区分大小写的。
在Autolev中,用户可以通过创建 .R 和 .A 文件来定义自己的命令,这些文件可以在他们的程序中使用。
SymPy 代码是 Python 代码,因此可以在代码中定义函数。这非常方便。
Autolev 是专有的。
SymPy 是开源的。

粗略的 Autolev-SymPy 等价物

下表给出了一些常见 Autolev 表达式的粗略等价物。这些并不是精确的等价物,而是应该作为提示,帮助你朝着正确的方向前进。更多细节请阅读内置文档中关于 SymPy 向量SymPy 力学PyDy 的内容。

在下面的表格中,假设您已经在Python中执行了以下命令:

import sympy.physics.mechanics as me
import sympy as sm

数学等价物

Autolev

SymPy

注释

常量 A, B
a, b = sm.symbols(‘a b’, real=True)
请注意,符号的名称可以与它们所赋值的变量名称不同。我们可以定义 a, b = symbols(‘b a’) 但遵循约定是一个好的做法。
常量 C+
c = sm.symbols(‘c’, real=True, nonnegative=True)
更多信息请参考 SymPy 假设
常量 D-
d = sm.symbols(‘d’, real=True, nonpositive=True)

常量 K{4}
k1, k2, k3, k4 = sm.symbols('k1 k2 k3 k4', real=True)

常量 a{2:4}
a2, a3, a4 = sm.symbols('a2 a3 a4', real=True)

Constants b{1:2, 1:2}
b11, b12, b21, b22 = sm.symbols('b11 b12 b21 b22', real=True)

指定的Phi
phi = me.dynamicsymbols(‘phi ')

变量 q, s
q, s = me.dynamicsymbols(q, s)

变量 x’’

x = me.dynamicsymbols(‘x’ )

xd = me.dynamicsymbols(‘x’ , 1)

xd2 = me.dynamicsymbols(‘x’ , 2)

变量 y{2}’

y1 = me.dynamicsymbols(‘y1’ )

y2 = me.dynamicsymbols(‘y2’ )

y1d = me.dynamicsymbols(‘y1’ , 1)

y2d = me.dynamicsymbols(‘y2' , 1)

MotionVariables u{2}

u1 = me.dynamicsymbols(‘u1’ )

u2 = me.dynamicsymbols('u2' )

SymPy 在声明时不区分变量、运动变量和指定变量。相反,它在 KanesMethod 等对象中将这些变量的不同列表作为参数。

Imaginary j

j = sm.I

I 是一个代表虚数单位的 sympy 对象。可以使用它来定义复数。

z = x + I*y

其中 x、y 和 z 是符号。

Tina = 2*pi

s = u*t + a*t^2/2

tina = 2*sm.pi

tina = tina.evalf()

t = me.dynamicsymbols._t

s = u*t + a*t**2/2

使用 .evalf() 将得到数值结果。

abs(x)^3 + sin(x)^2 + acos(x)
sm.abs(x)**3 + sm.sin(x)**2 + sm.acos(x)

E = (x+2*y)^2 + 3*(7+x)*(x+y)

Expand(E)

Factor(E, x)

Coef(y, x)

Replace(y, sin(x)=3)

Exclude(E,x)

Include(E,x)

Arrange(E,2,y)

E = (x+2*y)**2 + 3*(7+x)*(x+y)

sm.expand(E)

sm.horner(E, wrt=x)

y.coeff(x)

y.subs({sm.sin(x): 3})

e.collect(x).coeff( x, 0)

e.collect(x).coeff( x, 1)

e.collect(y)

更多信息请参考 简化。

这些 SymPy 函数不会就地工作。它们只是返回表达式。如果你想覆盖原始表达式,你需要做类似的事情:

y = y.subs({sm.sin(x): 3})

Dy = D(E, y)

Dt = Dt(E)

Dt2 = Dt(V, A) 其中 V 是一个向量,A 是一个框架

Dy2 = D(V, y, A)

E.diff(y)

E.diff( me.dynamicsymbols._t )

如果表达式由dynamicsymbols组成,则该方法有效。

dt2 = v.dt(A)

dy2 = v.diff(y, A)

更多信息请参考 微积分。

E = COS(X*Y)

TY = Taylor(E, 0:2, x=0, y=0)

e = sm.cos(x*y)

b = e.series(x, 0, 2).removeO().series(y, 0, 2).removeO()

更多信息请参考 系列。

F = Evaluate(E, x=a, y=2)

E.subs([(x, a), (y, 2)])

要从数值表达式中获取浮点数,请使用 .evalf()

E.evalf((a + sm.pi).subs({a: 3}))

P = Polynomial([a, b, c], x)

p = sm.Poly(sm.Matrix([a, b, c]).reshape(1, 3), x)

更多信息请参考 polys.

Roots(Polynomial( a*x^2 + b*x + c, x, 2)

Roots([1;2;3])

sm.solve( sm.Poly(a*x**2 + b*x + c))

sm.solve(sm.Poly( sm.Matrix([1,2,3]). reshape(3, 1), x), x)

更多信息请参考 求解器

关于与多项式和根相关的数值计算,请参考 mpmath/calculus.

Solve(A, x1, x2)

其中 A 是一个表示线性方程的增广矩阵,x1, x2 是待求解的变量。

sm.linsolve(A, (x1, x2))

其中 A 是一个增广矩阵

更多信息请参考 :ref:` solvers/solveset. <solveset>`

对于非线性求解器,请参考 求解器文档 中的 nonlinsolvensolve

RowMatrix = [1, 2, 3, 4]

ColMatrix = [1; 2; 3; 4]

MO = [a, b; c, 0]

MO[2, 2] := d

A + B*C

Cols(A)

Cols(A, 1)

Rows(A)

Rows(A, 1)

Det(A)

Element(A, 2, 3)

Inv(A)

Trace(A)

Transpose(A)

Diagmat(4, 1)

Eig(A)

Eig(A, EigVal, EigVec)

row_matrix = sm.Matrix([[1],[2], [3],[4]])

col_matrix = sm.Matrix([1, 2, 3, 4])

MO = sm.Matrix([[a, b], [c, 0]])

MO[1, 1] = d

A + B*C

A.cols

A.col(0)

A.rows

A.row(0)

M.det()

M[2, 3]

M**-1

sm.trace(A)

A.T

sm.diag(1,1,1,1)

A.eigenvals()

eigval = A.eigenvals()

eigvec = A.eigenvects()

更多信息请参考 矩阵。

物理等效物

Autolev

SymPy

注释

Bodies A

声明 A,其质心 Ao,以及在 A 中固定的正交向量 A1>、A2> 和 A3>。

m = sm.symbols(‘m’)

Ao = sm.symbols(‘Ao’)

Af = me.ReferenceFrame(‘Af’ )

I = me.outer(Af.x,Af.x)

P = me.Point('P')

A =me.RigidBody(‘A’, Ao, Af, m, (I, P))

Af.x、Af.y 和 Af.z 等同于 A1>、A2> 和 A3>。

第4和第5个参数用于质量和惯性。这些在Autolev中的声明之后指定。

可以使用参数的占位符,并通过设置器 A.mass = \_A.inertia = \_ 在稍后进行设置。

更多信息请参考 mechanics/masses .

Frames A

V1> = X1*A1> + X2*A2>

A = me.ReferenceFrame(‘A’ )

v1 = x1*A.x + x2*A.y

更多信息请参考 物理/向量。

牛顿N

N = me.ReferenceFrame(‘N’ )

SymPy 在声明时并不指定框架是否为惯性。许多函数,如 set_ang_vel(),将惯性参考系作为参数。

Particles C

m = sm.symbols(‘m’)

Po = me.Point('Po')

C = me.Particle(‘C’, Po, m)

第二个和第三个参数用于点和质量。在Autolev中,这些是在声明之后指定的。

可以使用一个虚拟对象并通过设置器(A.point = \_A.mass = \_)稍后设置它们。

P, Q

P = me.Point('P')

Q = me.Point('Q')

Mass B=mB

mB = symbols(‘mB’)

B.mass = mB

Inertia B, I1, I2, I3, I12, I23, I31

I = me.inertia(Bf, i1, i2, i3, i12, i23, i31)

B.inertia = (I, P) 其中 B 是一个刚体,Bf 是相关框架,P 是 B 的质量中心。

惯性二元组也可以使用向量的外积来形成。

I = me.outer(N.x, N.x)

更多信息请参考 mechanics api.

vec> = P_O_Q>/L

vec> = u1*N1> + u2*N2>

Cross(a>, b>)

Dot(a>, b>)

Mag(v>)

Unitvec(v>)

DYAD>> = 3*A1>*A1> + A2>*A2> + 2*A3>*A3>

vec  = (Qo.pos_from(O))/L

vec = u1*N.x + u2*N.y

cross(a, b)

dot(a, b)

v.magnitude()

v.normalize()

dyad = 3*me.outer(a.x ,a.x) + me.outer(a.y, a.y) + 2*me.outer(a.z ,a.z)

更多信息请参考 物理/向量。

P_O_Q> = LA*A1>

P_P_Q> = LA*A1>

Q.point = O.locatenew(‘Qo’, LA*A.x)

其中 A 是一个参考系。

Q.point = P.point.locatenew(‘Qo ’, LA*A.x)

更多信息请参考 运动学 API。

所有这些向量和运动学函数都应作用于 Point 对象,而不是 Particle 对象,因此对于粒子必须使用 .point

V_O_N> = u3*N.1> + u4*N.2>

Partials(V_O_N>, u3)

O.set_vel(N, u1*N.x + u2*N.y)

O.partial_velocity(N , u3)

获取器将是 O.vel(N)

A_O_N> = 0>

参考系N中点O的加速度。

O.set_acc(N, 0)

获取器将是 O.acc(N)

W_B_N> = qB’*B3>

参考系F中物体B的角速度。

B.set_ang_vel(N, qBd*Bf.z)

其中 Bf 是与物体 B 相关联的框架。

获取器将是 B.ang_vel_in(N)

ALF_B_N> =Dt(W_B_N>, N)

参考系N中物体B的角加速度。

B.set_ang_acc(N, diff(B.ang_vel_in(N) )

获取器将是 B.ang_acc_in(N)

Force_O> = F1*N1> + F2*N2>

Torque_A> = -c*qA’*A3>

在 SymPy 中,应该有一个包含所有力和力矩的列表。

fL.append((O, f1*N.x + f2*N.y))

其中 fL 是力列表。

fl.append((A, -c*qAd*A.z))

A_B = M 其中 M 是一个矩阵,A 和 B 是框架。

D = A_B*2 + 1

B.orient(A, 'DCM', M) 其中 M 是一个 SymPy 矩阵。

D = A.dcm(B)*2 + 1

CM(B)

B.masscenter

Mass(A,B,C)

A.mass + B.mass + C.mass

V1pt(A,B,P,Q)

Q.v1pt_theory(P, A, B)

这里假设 P 和 Q 是 Point 对象。记住对粒子使用 .point

V2pts(A,B,P,Q)

Q.v2pt_theory(P, A, B)

A1pt(A,B,P,Q)

Q.a1pt_theory(P, A, B)

A2pts(A,B,P,Q)

Q.a2pt_theory(P, A, B)

Angvel(A,B)

B.ang_vel_in(A)

Simprot(A, B, 1, qA)

B.orient(A, 'Axis', qA, A.x)

Gravity(G*N1>)

fL.extend(gravity( g*N.x, P1, P2, ...))

在 SymPy 中,我们必须使用一个包含形式为 (点, 力矢量) 的元组的力列表(此处为 fL)。这被传递给 KanesMethod 对象的 kanes_equations() 方法。

CM(O,P1,R)

me.functions. center_of_mass(o, p1, r)

Force(P/Q, v>)

fL.append((P, -1*v), (Q, v))

Torque(A/B, v>)

fL.append((A, -1*v), (B, v))

Kindiffs(A, B ...)

KM.kindiffdict()

Momentum(选项)

linear_momentum(N, B1, B2 ...)

参考系后跟随一个或多个物体

angular_momentum(O, N, B1, B2 ...)

点,参考系后跟一个或多个物体

KE()

kinetic_energy(N, B1, B2 ...)

参考系后跟随一个或多个物体

Constrain(...)

velocity_constraints = [...]

u_dependent = [...]

u_auxiliary = [...]

这些列表被传递给 KanesMethod 对象。

更多详情请参阅 mechanics/kanekane api.

Fr() FrStar()

KM = KanesMethod(f, q_ind, u_ind, kd_eqs, q_dependent, configuration_constraints, u_dependent, velocity_constraints, acceleration_constraints, u_auxiliary)

KanesMethod 对象接受一个参考系,后跟多个列表作为参数。

(fr, frstar) = KM.kanes_equations(fL, bL) 其中 fL 和 bL 分别是力和物体的列表。

更多详情请参阅 mechanics/kanekane api.

数值评估与可视化

Autolev 的 CODE Option() 命令允许用户生成用于数值评估和可视化的 Matlab、C 或 Fortran 代码。选项可以是 Dynamics、ODE、Nonlinear 或 Algebraic。

可以使用 PyDy 进行动力学的数值评估。可以将 KanesMethod 对象与常量、指定量、初始条件和时间步长的值一起传递给 System 类。然后可以对运动方程进行积分。绘图使用 matlplotlib 实现。以下是来自 PyDy 文档 的一个示例,展示了如何完成:

from numpy import array, linspace, sin
from pydy.system import System

sys = System(kane,
             constants = {mass: 1.0, stiffness: 1.0,
                          damping: 0.2, gravity: 9.8},
             specifieds = {force: lambda x, t: sin(t)},
             initial_conditions = {position: 0.1, speed:-1.0},
             times = linspace(0.0, 10.0, 1000))

y = sys.integrate()

import matplotlib.pyplot as plt
plt.plot(sys.times, y)
plt.legend((str(position), str(speed)))
plt.show()

有关 PyDy 能够完成的所有功能的信息,请参阅 PyDy 文档

PyDy 工作流程中的工具有:

  • SymPy: SymPy 是一个用于

    符号计算。它提供了计算机代数功能,既可以作为一个独立应用程序,也可以作为其他应用程序的库,或者在网络上作为 SymPy Live 或 SymPy Gamma 实时运行。

  • NumPy: NumPy 是一个用于

    Python 编程语言,增加了对大型、多维数组和矩阵的支持,以及大量用于操作这些数组的高级数学函数。

  • SciPy: SciPy 是一个开源项目

    用于科学计算和技术计算的Python库。SciPy包含用于优化、线性代数、积分、插值、特殊函数、FFT、信号和图像处理、ODE求解器以及其他科学和工程中常见任务的模块。

  • IPython: IPython 是一个命令行 shell

    用于多种编程语言的交互式计算,最初为 Python 编程语言开发,提供内省、丰富的媒体、shell 语法、Tab 补全和历史记录。

  • Aesara: Aesara 是一个

    一个用于Python的数值计算库。在Aesara中,计算使用类似NumPy的语法表达,并编译为在CPU或GPU架构上高效运行。

  • Cython: Cython 是 Python 的超集

    Python 编程语言,旨在以主要用 Python 编写的代码提供类似 C 的性能。Cython 是一种编译语言,生成 CPython 扩展模块。

  • matplotlib: matplotlib 是一个

    用于Python编程语言及其数值数学扩展NumPy的绘图库。

通过这些科学计算工具,人们将能够编写与Autolev生成的Matlab、C或Fortran代码等效的代码。建议浏览这些模块,以深入理解使用Python进行科学计算。