物理/力学中的符号系统¶
物理/力学中的 \(SymbolicSystem\) 类是多体动力系统相关信息的存放位置。在其最基本的形式中,它包含动力系统的运动方程,然而,它还可以包含系统所受载荷的信息、系统所包含的物体以及用户认为对系统重要的任何附加方程。该类的目标是提供一个统一的输出格式,以便数值分析代码可以围绕运动方程进行设计。
SymbolicSystem 示例用法¶
此代码将遍历简单摆的运动方程的手动输入,该摆使用质量的笛卡尔位置作为广义坐标,并将其输入到 \(SymbolicSystem\) 中。
运动方程在 physics/mechanics/examples 中形成。在那里,变量 q1 和 q2 代替了 x 和 y,参考系旋转了 90 度。
>>> from sympy import atan, symbols, Matrix
>>> from sympy.physics.mechanics import (dynamicsymbols, ReferenceFrame,
... Particle, Point)
>>> import sympy.physics.mechanics.system as system
>>> from sympy.physics.vector import init_vprinting
>>> init_vprinting(pretty_print=False)
第一步将是初始化所有动态和常量符号。:
>>> x, y, u, v, lam = dynamicsymbols('x y u v lambda')
>>> m, l, g = symbols('m l g')
下一步是定义多种形式的方程:
- [1] 显式形式,其中运动学和动力学相结合
x’ = F_1(x, t, r, p)
- [2] 隐式形式,其中运动学和动力学被结合在一起
M_2(x, p) x’ = F_2(x, t, r, p)
- [3] 隐式形式,其中运动学和动力学是分开的
M_3(q, p) u’ = F_3(q, u, t, r, p) q’ = G(q, u, t, r, p)
哪里
x : 状态, 例如 [q, u] t : 时间 r : 指定的 (外生) 输入 p : 常数 q : 广义坐标 u : 广义速度 F_1 : 组合方程的显式形式的右侧 F_2 : 组合方程的隐式形式的右侧 F_3 : 动力学方程的隐式形式的右侧 M_2 : 组合方程的隐式形式的质矩阵 M_3 : 动力学方程的隐式形式的质矩阵 G : 运动学微分方程的右侧
>>> dyn_implicit_mat = Matrix([[1, 0, -x/m],
... [0, 1, -y/m],
... [0, 0, l**2/m]])
>>> dyn_implicit_rhs = Matrix([0, 0, u**2 + v**2 - g*y])
>>> comb_implicit_mat = Matrix([[1, 0, 0, 0, 0],
... [0, 1, 0, 0, 0],
... [0, 0, 1, 0, -x/m],
... [0, 0, 0, 1, -y/m],
... [0, 0, 0, 0, l**2/m]])
>>> comb_implicit_rhs = Matrix([u, v, 0, 0, u**2 + v**2 - g*y])
>>> kin_explicit_rhs = Matrix([u, v])
>>> comb_explicit_rhs = comb_implicit_mat.LUsolve(comb_implicit_rhs)
现在将设置参考框架、点和粒子,以便可以将此信息以身体和负载可迭代的形式传递到 \(system.SymbolicSystem\) 中。:
>>> theta = atan(x/y)
>>> omega = dynamicsymbols('omega')
>>> N = ReferenceFrame('N')
>>> A = N.orientnew('A', 'Axis', [theta, N.z])
>>> A.set_ang_vel(N, omega * N.z)
>>> O = Point('O')
>>> O.set_vel(N, 0)
>>> P = O.locatenew('P', l * A.x)
>>> P.v2pt_theory(O, N, A)
l*omega*A.y
>>> Pa = Particle('Pa', P, m)
现在需要初始化bodies和loads的可迭代对象。:
>>> bodies = [Pa]
>>> loads = [(P, g * m * N.x)]
运动方程的形式是微分代数方程(DAE),DAE求解器需要知道哪些方程是代数表达式。这些信息作为指定哪些行是代数方程的列表传递给 \(SymbolicSystem\)。在这个例子中,它是基于所选运动方程格式的不同行。行索引应始终对应于输入到 \(SymbolicSystem\) 类的质量矩阵,但当从 \(SymbolicSystem\) 类访问时,始终对应于组合动力学和运动学的行索引。
>>> alg_con = [2]
>>> alg_con_full = [4]
系统现在需要创建一个包含状态的可迭代对象。\(SymbolicSystem\) 类可以通过传入坐标和速度的索引来确定哪些状态被视为坐标或速度。如果没有传入这些索引,对象将无法区分坐标和速度。:
>>> states = (x, y, u, v, lam)
>>> coord_idxs = (0, 1)
>>> speed_idxs = (2, 3)
现在可以使用上述的运动方程格式创建运动方程实例。:
>>> symsystem1 = system.SymbolicSystem(states, comb_explicit_rhs,
... alg_con=alg_con_full, bodies=bodies,
... loads=loads)
>>> symsystem2 = system.SymbolicSystem(states, comb_implicit_rhs,
... mass_matrix=comb_implicit_mat,
... alg_con=alg_con_full,
... coord_idxs=coord_idxs)
>>> symsystem3 = system.SymbolicSystem(states, dyn_implicit_rhs,
... mass_matrix=dyn_implicit_mat,
... coordinate_derivatives=kin_explicit_rhs,
... alg_con=alg_con,
... coord_idxs=coord_idxs,
... speed_idxs=speed_idxs)
像坐标和速度一样,bodies和loads属性只能在初始化`SymbolicSystem`类时指定后才能访问。最后,这里有一些可以从`SymbolicSystem`类访问的属性。:
>>> symsystem1.states
Matrix([
[ x],
[ y],
[ u],
[ v],
[lambda]])
>>> symsystem2.coordinates
Matrix([
[x],
[y]])
>>> symsystem3.speeds
Matrix([
[u],
[v]])
>>> symsystem1.comb_explicit_rhs
Matrix([
[ u],
[ v],
[(-g*y + u**2 + v**2)*x/l**2],
[(-g*y + u**2 + v**2)*y/l**2],
[m*(-g*y + u**2 + v**2)/l**2]])
>>> symsystem2.comb_implicit_rhs
Matrix([
[ u],
[ v],
[ 0],
[ 0],
[-g*y + u**2 + v**2]])
>>> symsystem2.comb_implicit_mat
Matrix([
[1, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[0, 0, 1, 0, -x/m],
[0, 0, 0, 1, -y/m],
[0, 0, 0, 0, l**2/m]])
>>> symsystem3.dyn_implicit_rhs
Matrix([
[ 0],
[ 0],
[-g*y + u**2 + v**2]])
>>> symsystem3.dyn_implicit_mat
Matrix([
[1, 0, -x/m],
[0, 1, -y/m],
[0, 0, l**2/m]])
>>> symsystem3.kin_explicit_rhs
Matrix([
[u],
[v]])
>>> symsystem1.alg_con
[4]
>>> symsystem1.bodies
(Pa,)
>>> symsystem1.loads
((P, g*m*N.x),)