背景
这个解释有些偏题,但我认为它有必要帮助澄清评论中提出的一些问题,并且因为其中许多内容有些反直觉。
这种引力相互作用的解释依赖于质点的概念。假设你有两个质点,在一个孤立系统中彼此分开一定距离r1,分别具有质量m1和m2。
![enter image description here](https://istack.dev59.com/9F5R3.webp)
引力场是由m1产生的,其表达式为
![enter image description here](https://istack.dev59.com/PMxvb.webp)
其中G是普适引力常数,r是从m1到m2的距离,r̂是沿着它们之间连线的单位方向。
这个场对m2施加的引力为:
![enter image description here](https://istack.dev59.com/horCt.webp)
注意 - 重要的是,这对于任何两个质点在任何距离上都是成立的。1
引力相互作用的场性质使我们能够应用叠加原理来计算多重相互作用导致的净引力。考虑如果我们向之前的情境中添加另一个质量为m3的物体,
![enter image description here](https://istack.dev59.com/fp4kV.webp)
那么对于质量为m2的物体,其所受到的引力是由每个其他物体产生的引力场相加而成的。
![enter image description here](https://istack.dev59.com/YuOQZ.webp)
对于任意数量和分离程度的物体,都有ri,j = rj,i。这也意味着由一组物体创建的场可以通过矢量求和进行聚合,如果您更喜欢这种形式。
现在考虑如果我们有一个非常大的点质量数M,聚集在一个连续的、均匀密度的刚体中。然后我们想要计算单个空间不同点质量m由于聚合质量M而产生的引力。
![enter image description here](https://istack.dev59.com/agCiu.webp)
那么,我们可以考虑质量差异大小的面积(或体积),而不是考虑点质量,并且将这些区域(或体积)对点质量的作用进行积分或求和。在二维情况下,引力的大小为
![enter image description here](https://istack.dev59.com/SJQk6.webp)
其中σ是聚合物质的密度。2这相当于对每个微分质量的重力向量场进行求和,即σdxdy。这种等价性非常重要,因为它意味着对于任何足够远离质量分布的点质量来说,由于质量分布产生的引力力量几乎与位于质量分布center of mass处的质量M的点质量相同。34
这意味着,在计算任何质量分布所产生的引力场时,可以用质量分布在重心处的等效质点代替质量分布,从而得到非常好的近似结果。这适用于任何数量的空间不同的质量分布,无论这些分布是否构成刚体。此外,这意味着您甚至可以将分布组聚集到系统重心处的单个质点中。5只要参考点足够远。
然而,为了找到质量分布在任意点上对点质量的引力,无论质量分布的形状和分离方式如何,我们都必须通过将来自质量分布每个部分的贡献相加来计算该点处的引力场。
6
回到问题
当然,对于任意多边形或多面体,解析解可能会非常困难,因此使用求和方法会更简单,算法方法也会类似地使用求和方法。
从算法角度来看,这里最简单的方法实际上不是
几何包装(使用圆/球或正方形/立方体)。使用包装并非不可能,但从数学上讲,这种方法存在重大挑战-最好采用依赖于更简单数学的方法。其中一种方法是定义一个覆盖质量分布空间范围的网格,然后创建以网格点为顶点的简单(正方形/立方体或矩形/长方体)多边形或多面体。这将创建三种类型的多边形或多面体:
- 不包含任何质量分布的物体
- 被质量分布完全填充的物体
- 被部分质量分布填充的物体
![enter image description here](https://istack.dev59.com/GsZKZ.webp)
质心 - 方法1
当参考点到质量分布的距离相对于分布的角度范围很大,并且没有任何几个分布将参考点围住时,这种方法会很有效。
然后,您可以通过对每个多边形的贡献求和来找到分布的质心R。
![enter image description here](https://istack.dev59.com/Zd35n.webp)
其中M是分布的总质量,ri是到第i个多边形几何中心的空间向量,mi是密度乘以包含质量部分的多边形(即对于完全填充的多边形为1.00,对于完全空的多边形为0.00)。随着采样大小(网格点数)的增加,重心的近似值将接近解析解。一旦你有了重心,就可以轻松地计算所创建的引力场:只需在点R处放置质量为M的点质量,并使用上面的方程。
为了演示,在Python中使用shapely库进行多边形操作的二维实现如下:
import numpy as np
import matplotlib.pyplot as plt
import shapely.geometry as geom
def centerOfMass(r, density = 1.0, n = 100):
theta = np.linspace(0, np.pi*2, len(r))
xy = np.stack([np.cos(theta)*r, np.sin(theta)*r], 1)
mass_dist = geom.Polygon(xy)
x, y = mass_dist.exterior.xy
gx, gy = np.meshgrid(np.linspace(min(x), max(x), n), np.linspace(min(y),
max(y), n))
polygons = [geom.Polygon([[gx[i,j], gy[i,j]],
[gx[i,j+1], gy[i,j+1]],
[gx[i+1,j+1],gy[i+1,j+1]],
[gx[i+1,j], gy[i+1,j]],
[gx[i,j], gy[i,j]]])
for i in range(gx.shape[0]-1) for j in range(gx.shape[1]-1)]
R = np.zeros(2)
M = 0
for p in polygons:
m = (p.intersection(mass_dist).area / p.area) * density
M += m
R += m * np.array([p.centroid.x, p.centroid.y])
return geom.Point(R / M), M
density = 1.0
G = 6.67408e-11
theta = np.linspace(0, np.pi*2, 100)
r = np.cos(theta*2+np.pi)+5+np.sin(theta)+np.cos(theta*3+np.pi/6)
R, M = centerOfMass(r, density)
m = geom.Point(20, 0)
r_1 = m.distance(R)
m_1 = 5.0
F = G * (m_1 * M) / r_1**2
rhat = np.array([R.x - m.x, R.y - m.y])
rhat /= (rhat[0]**2 + rhat[1]**2)**0.5
plt.figure(figsize=(12, 6))
plt.axis('off')
plt.plot(np.cos(theta)*r, np.sin(theta)*r, color='k', lw=0.5, linestyle='-')
plt.scatter(m.x, m.y, s=20, color='k')
plt.text(m.x, m.y-1, r'$m$', ha='center')
plt.text(1, -1, r'$M$', ha='center')
plt.quiver([m.x], [m.y], [rhat[0]], [rhat[1]], width=0.004,
scale=0.25, scale_units='xy')
plt.text(m.x - 5, m.y + 1, r'$F = {:.5e}$'.format(F))
plt.scatter(R.x, R.y, color='k')
plt.text(R.x, R.y+0.5, 'Center of Mass', va='bottom', ha='center')
plt.gca().set_aspect('equal')
plt.show()
![enter image description here](https://istack.dev59.com/v8RzF.webp)
这种方法有些过于复杂:在大多数情况下,只需找到多边形的质心和面积乘以密度即可得到重心和总质量。然而,它也适用于非均匀分布的质量 - 这就是为什么我用它进行演示的原因。
场总和 - 方法2
在许多情况下,这种方法也有些过于复杂,特别是与第一种方法相比,但在任何分布(在经典范围内)下都提供了最佳近似值。
这里的思路是对质量分布的每个块对一个点质量产生的影响进行求和,以确定净引力(基于引力场可以独立添加的前提)。
class pointMass:
def __init__(self, mass, x, y):
self.mass = mass
self.x = x
self.y = y
density = 1.0
G = 6.67408e-11
def netForce(r, m1, density = 1.0, n = 100):
theta = np.linspace(0, np.pi*2, len(r))
xy = np.stack([np.cos(theta)*r, np.sin(theta)*r], 1)
mass_dist = geom.Polygon(xy)
x, y = mass_dist.exterior.xy
gx, gy = np.meshgrid(np.linspace(min(x), max(x), n), np.linspace(min(y),
max(y), n))
polygons = [geom.Polygon([[gx[i,j], gy[i,j]],
[gx[i,j+1], gy[i,j+1]],
[gx[i+1,j+1],gy[i+1,j+1]],
[gx[i+1,j], gy[i+1,j]],
[gx[i,j], gy[i,j]]])
for i in range(gx.shape[0]-1) for j in range(gx.shape[1]-1)]
g = np.zeros(2)
for p in polygons:
m2 = (p.intersection(mass_dist).area / p.area) * density
rhat = np.array([p.centroid.x - m1.x, p.centroid.y - m1.y])
rhat /= (rhat[0]**2 + rhat[1]**2)**0.5
g += m1.mass * m2 / p.centroid.distance(geom.Point(m1.x, m1.y))**2 * rhat
g *= G
return g
theta = np.linspace(0, np.pi*2, 100)
r = np.cos(theta*2+np.pi)+5+np.sin(theta)+np.cos(theta*3+np.pi/6)
m = pointMass(5.0, 20.0, 0.0)
g = netForce(r, m)
plt.figure(figsize=(12, 6))
plt.axis('off')
plt.plot(np.cos(theta)*r, np.sin(theta)*r, color='k', lw=0.5, linestyle='-')
plt.scatter(m.x, m.y, s=20, color='k')
plt.text(m.x, m.y-1, r'$m$', ha='center')
plt.text(1, -1, r'$M$', ha='center')
ghat = g / (g[0]**2 + g[1]**2)**0.5
plt.quiver([m.x], [m.y], [ghat[0]], [ghat[1]], width=0.004,
scale=0.25, scale_units='xy')
plt.text(m.x - 5, m.y + 1, r'$F = ({:0.3e}, {:0.3e})$'.format(g[0], g[1]))
plt.gca().set_aspect('equal')
plt.show()
相对简单的测试案例表明,这种方法得到的结果非常接近第一种方法:
![enter image description here](https://istack.dev59.com/VDTUB.webp)
但是,虽然第一种方法无法正确处理某些情况,但在传统的情况下,第二种方法没有失败的案例,因此建议优先考虑这种方法。
1在极端情况下,例如黑洞事件视界之外或当r趋近于普朗克长度时,它会发生瓦解,但这些情况不是本问题的主题。
2当密度不均匀且无法用符号描述质量分布时,情况变得更加复杂,没有显然的解析解。
3应该注意,这实际上就是积分正在做的事情;寻找质心。
4对于一个质点位于质量分布内部时,必须使用牛顿的壳定理或场的总和。
在天文学中,这被称为
重心,天体
总是绕系统的重心而不是任何给定天体的质心运动。
6在某些情况下,使用牛顿的外壳定理就足够了,但这些情况并不是分布几何无关的。
G(m1*m2/r**2)
只适用于足够远的物体......对于接近的物体,您需要积分(面积或体积)......或者将您的物体转换为一组质点(精度降低但计算速度更快且更简单)。 - Spektre