在NumPy中确定静态平衡#

在分析物理结构时,理解保持它们稳定的力学机制至关重要。施加在地板、梁或其他结构上的力会产生反作用力和力矩。这些反作用力是结构抵抗移动而不破坏的力。在结构即使受到力作用也不移动的情况下,牛顿第二定律指出,系统的加速度和所有方向上的力之和必须为零。你可以用NumPy数组表示和解决这个概念。

你将做什么:#

  • 在本教程中,您将使用 NumPy 通过 NumPy 数组创建向量和矩

  • 解决涉及电缆和地板支撑结构的问题

  • 写入 NumPy 矩阵以隔离未知数

  • 使用 NumPy 函数执行线性代数运算

你将学到什么:#

  • 如何使用 NumPy 表示点、向量和矩。

  • 如何找到向量的法线

  • 使用 NumPy 计算矩阵运算

你需要什么:#

通过以下命令导入:

import numpy as np
import matplotlib.pyplot as plt

在本教程中,您将使用以下 NumPy 工具:

  • np.linalg.norm : 此函数确定向量大小的度量

  • np.cross : 这个函数接受两个矩阵并生成叉积

用牛顿第二定律求解平衡#

你的模型由一个在力和力矩总和作用下的梁组成。你可以从牛顿第二定律开始分析这个系统:

\[::\]

为了简化所考虑的例子,假设它们是静态的,加速度\(=0\)。由于我们的系统存在于三维空间中,考虑在这些维度中施加的力。这意味着你可以将这些力表示为向量。对于力矩,你也会得出相同的结论,力矩是由于力在物体质心一定距离处施加而产生的。

假设力 \(F\) 表示为一个三维向量

\[F = (F_x, F_y, F_z)\]

其中三个分量分别表示在每个对应方向上施加的力的大小。还假设向量中的每个分量

\[r = (r_x, r_y, r_z)\]

是力在每个分量施加点与系统质心之间的距离。然后,可以通过以下公式计算力矩:

\[::\]

从一些简单的力矢量示例开始

forceA = np.array([1, 0, 0])
forceB = np.array([0, 1, 0])
print("Force A =", forceA)
print("Force B =", forceB)
Force A = [1 0 0]
Force B = [0 1 0]

这定义了 forceA 为一个在 \(x\) 方向上大小为 1 的向量,并将 forceB 定义为在 \(y\) 方向上大小为 1 的向量。

为了更好地理解这些力如何相互作用,可视化这些力可能会有所帮助。Matplotlib 是一个具有可视化工具的库,可以用于此目的。将使用箭头图来演示 三维向量,但该库也可以用于 二维演示

fig = plt.figure()

d3 = fig.add_subplot(projection="3d")

d3.set_xlim(-1, 1)
d3.set_ylim(-1, 1)
d3.set_zlim(-1, 1)

x, y, z = np.array([0, 0, 0])  # defining the point of application.  Make it the origin

u, v, w = forceA  # breaking the force vector into individual components
d3.quiver(x, y, z, u, v, w, color="r", label="forceA")

u, v, w = forceB
d3.quiver(x, y, z, u, v, w, color="b", label="forceB")

plt.legend()
plt.show()
../_images/9efe2e3320ed2f12720ea1755631a42a4717ec9dbfe0ef51965195ff69fe4a8b.png

从单个点发出两个力。为了简化这个问题,你可以将它们相加以求出合力。注意,forceAforceB 都是三维向量,用 NumPy 表示为具有三个分量的数组。因为 NumPy 旨在简化和优化向量之间的操作,所以你可以很容易地计算这两个向量的和,如下所示:

forceC = forceA + forceB
print("Force C =", forceC)
Force C = [1 1 0]

力 C 现在作为代表 A 和 B 的单一力。你可以绘制它以查看结果。

fig = plt.figure()

d3 = fig.add_subplot(projection="3d")

d3.set_xlim(-1, 1)
d3.set_ylim(-1, 1)
d3.set_zlim(-1, 1)

x, y, z = np.array([0, 0, 0])

u, v, w = forceA
d3.quiver(x, y, z, u, v, w, color="r", label="forceA")
u, v, w = forceB
d3.quiver(x, y, z, u, v, w, color="b", label="forceB")
u, v, w = forceC
d3.quiver(x, y, z, u, v, w, color="g", label="forceC")

plt.legend()
plt.show()
../_images/12b94a2beb767e77a790520593f0d266e4dd774d8f55428673ae7a7c595ce447.png

然而,目标是平衡。这意味着你希望你的合力为 \((0, 0, 0)\),否则你的物体会经历加速。因此,需要有另一个力来抵消之前的力。

你可以将这个问题写成 \(A+B+R=0\),其中 \(R\) 是解决问题的反作用力。

在这个例子中,这意味着:

\[(1, 0, 0) + (0, 1, 0) + (R_x, R_y, R_z) = (0, 0, 0)\]

分解为 \(x\)\(y\)\(z\) 分量,这给你:

\[\begin{split}\begin{cases} 1+0+R_x=0\\ 0+1+R_y=0\\ 0+0+R_z=0 \end{cases}\end{split}\]

求解 \(R_x\)\(R_y\)\(R_z\) 给你一个向量 \(R\)\((-1, -1, 0)\)

如果绘制,前例中看到的力应被抵消。只有在没有剩余力的情况下,系统才被认为是处于平衡状态。

R = np.array([-1, -1, 0])

fig = plt.figure()

d3.set_xlim(-1, 1)
d3.set_ylim(-1, 1)
d3.set_zlim(-1, 1)

d3 = fig.add_subplot(projection="3d")

x, y, z = np.array([0, 0, 0])

u, v, w = forceA + forceB + R  # add them all together for sum of forces
d3.quiver(x, y, z, u, v, w)

plt.show()
../_images/a4c94672d18e7c4522877b4e5b0eb86c5e28be38e7ce44b23c17726e8086be1f.png

空图表示没有外力。这表示一个处于平衡状态的系统。

求解平衡作为力矩之和#

接下来让我们转向一个更复杂的应用。当力不是全部施加在同一点时,会产生力矩。

类似于力,这些力矩必须全部相加为零,否则将经历旋转加速度。类似于力的总和,这为空间中的每个坐标方向创建了一个线性方程。

一个简单的例子是施加在一个固定在地面上静止杆子上的力。杆子没有移动,所以它必须施加一个反作用力。杆子也没有旋转,所以它也必须产生一个反作用力矩。求解反作用力和力矩。

假设一个5N的力垂直作用在离杆底2米高的地方。

f = 5  # Force in newtons
L = 2  # Length of the pole

R = 0 - f
M = 0 - f * L
print("Reaction force =", R)
print("Reaction moment =", M)
Reaction force = -5
Reaction moment = -10

通过物理属性查找值#

假设有一个力不是垂直作用于梁上,而是通过一根也固定在地面上的绳索作用在我们的杆上。给定这根绳索的张力,你只需要这些物体的物理位置就能解决这个问题。

表示问题的图像

在作用于杆的力作用下,基底在x和y方向上产生了反作用力,以及一个反作用力矩。

将杆的底部表示为原点。现在,假设绳索在地面上沿 x 方向连接到 3 米处,并沿 z 方向向上连接到杆的 2 米处。

将这些点在空间中定义为 NumPy 数组,然后使用这些数组来找到方向向量。

poleBase = np.array([0, 0, 0])
cordBase = np.array([3, 0, 0])
cordConnection = np.array([0, 0, 2])

poleDirection = cordConnection - poleBase
print("Pole direction =", poleDirection)
cordDirection = cordBase - cordConnection
print("Cord direction =", cordDirection)
Pole direction = [0 0 2]
Cord direction = [ 3  0 -2]

为了在使用这些向量与力相关时,你需要将它们转换为单位向量。单位向量的量级为一,并且仅传达力的方向。

cordUnit = cordDirection / np.linalg.norm(cordDirection)
print("Cord unit vector =", cordUnit)
Cord unit vector = [ 0.83205029  0.         -0.5547002 ]

然后,你可以将这个方向与力的大小相乘,以找到力矢量。

假设绳子的张力为5N:

cordTension = 5
forceCord = cordUnit * cordTension
print("Force from the cord =", forceCord)
Force from the cord = [ 4.16025147  0.         -2.77350098]

为了找到你需要的力量矢量和半径的叉积的时刻。

momentCord = np.cross(forceCord, poleDirection)
print("Moment from the cord =", momentCord)
Moment from the cord = [ 0.         -8.32050294  0.        ]

现在你需要做的就是找到反作用力和力矩。

equilibrium = np.array([0, 0, 0])
R = equilibrium - forceCord
M = equilibrium - momentCord
print("Reaction force =", R)
print("Reaction moment =", M)
Reaction force = [-4.16025147  0.          2.77350098]
Reaction moment = [0.         8.32050294 0.        ]

另一个例子#

让我们来看一个稍微复杂一点的模型。在这个例子中,你将观察到一个带有两根电缆和施加力的梁。这次你需要找到电缆的张力和梁的反作用力。(来源: Vector Mechanics for Engineers: Statics, Problem 4.106)

image.png

定义距离 a 为 3 米

如前所述,首先将每个相关点的位置定义为一个数组。

A = np.array([0, 0, 0])
B = np.array([0, 3, 0])
C = np.array([0, 6, 0])
D = np.array([1.5, 0, -3])
E = np.array([1.5, 0, 3])
F = np.array([-3, 0, 2])

从这些方程中,你首先通过单位向量确定向量方向。

AB = B - C
AC = C - A
BD = D - B
BE = E - B
CF = F - C

UnitBD = BD / np.linalg.norm(BD)
UnitBE = BE / np.linalg.norm(BE)
UnitCF = CF / np.linalg.norm(CF)

RadBD = np.cross(AB, UnitBD)
RadBE = np.cross(AB, UnitBE)
RadCF = np.cross(AC, UnitCF)

这允许你表示作用在系统上的张力 (T) 和反作用力 (R)。

\[\begin{split}\left[ \begin{array} ~1/3 & 1/3 & 1 & 0 & 0\\ -2/3 & -2/3 & 0 & 1 & 0\\ -2/3 & 2/3 & 0 & 0 & 1\\ \end{array} \right] \left[ \begin{array} ~T_{BD}\\ T_{BE}\\ R_{x}\\ R_{y}\\ R_{z}\\ \end{array} \right] = \left[ \begin{array} ~195\\ 390\\ -130\\ \end{array} \right]\end{split}\]

和那些时刻

\[\begin{split}\left[ \begin{array} ~2 & -2\\ 1 & 1\\ \end{array} \right] \left[ \begin{array} ~T_{BD}\\ T_{BE}\\ \end{array} \right] = \left[ \begin{array} ~780\\ 1170\\ \end{array} \right]\end{split}\]

其中 \(T\) 是相应绳索的张力,\(R\) 是相应方向的反作用力。然后你只有六个方程:

\(\sum F_{x} = 0 = T_{BE}/3+T_{BD}/3-195+R_{x}\)

\(\sum F_{y} = 0 = (-\frac{2}{3})T_{BE}-\frac{2}{3}T_{BD}-390+R_{y}\)

\(\sum F_{z} = 0 = (-\frac{2}{3})T_{BE}+\frac{2}{3}T_{BD}+130+R_{z}\)

\(\sum M_{x} = 0 = 780+2T_{BE}-2T_{BD}\)

\(\sum M_{z} = 0 = 1170-T_{BE}-T_{BD}\)

你现在有五个未知数和五个方程,可以求解:

\(\ T_{BD} = 780N\)

\(\ T_{BE} = 390N\)

\(\ R_{x} = -195N\)

\(\ R_{y} = 1170N\)

\(\ R_{z} = 130N\)

总结#

你已经学会了如何使用数组来表示三维空间中的点、力和力矩。数组中的每个条目都可以用来表示分解为方向分量的物理属性。然后可以使用 NumPy 函数轻松操作这些属性。

附加应用#

这个相同的流程可以应用于动力学问题或在任意数量的维度中。本教程中的示例假设了在静态平衡中的三维问题。这些方法可以轻松地用于更多样化的问题。更多或更少的维度需要更大或更小的数组来表示。在经历加速的系统中,速度和加速度同样可以被表示为向量。

参考文献#

  1. 工程师的矢量力学:静力学 (Beer & Johnston & Mazurek)

  2. NumPy 参考