平面内模拟万有引力

前言

一、研究背景

在高中物理必修二中,我们学习了牛顿运动定律和万有引力定律的有关内容,领略了宇宙中无穷的奥秘。

虽然在现阶段的物理界中,牛顿定律的理论基础已经被爱因斯坦的广义相对论所取代。但它在大多数应用中仍然被用作重力效应的经典近似。只有在需要极端精确的时候,或者在处理非常强大的引力场的时候,比如那些在极其密集的物体上,或者在非常近的距离时,才需要相对论。

介于一种学以致用的精神,考虑到我们的计算机基本水平,我们产生了对于模拟万有引力的极大兴趣。

二、研究方法

1.物理原理

(1).基本定律

万有引力定律:任意两个质点由通过连心线方向上的力相互吸引。该吸引力的大小与它们的质量乘积成正比,与它们距离的平方成反比。
$$
F=G\frac{m_1m_2}{r^2}
$$
其中,F为万有引力,G为万有引力常数,m1为物体1的质量,m2为物体2的质量,r为两者的距离。

牛顿第二定律:物体所受到的外力等于质量与加速度的乘积,而加速度与外力同方向。
$$
F=ma
$$

(2).原理

根据万有引力定律,已知所有物体之间的距离和质量,对于一个时刻内的所有物体,我们可以计算所有其他物体与其的万有引力。

对于该物体所受的所有力进行矢量合成,可以得知力的方向。

根据牛顿第二定律,已知一个力的合力,可以计算其在合力方向的加速度,与时间相乘后得知速度的变化量,最终得知其在下一时刻的速度与位移。

2.计算机原理

(1).工具及模块

  • Python3.6及以上版本
  • Python第三方库模块pygame用以可视化表现
  • Python第三方库模块easygui用以与用户进行可视化交互操作
  • Python第三方库模块matplotlib用以记录基本数据和进行数学操作

(2).原理

在物理中,速度、位移、加速度均为有方向的矢量;对于计算机中,二维矢量的方向不便于表示,此时联想到所学的正交分解法,通过三角函数将有方向的向量分别分解到两个垂直的方向上。这样就便于计算机进行存储和计算。

数据结构与存储

介于这一点,对于进行星球部分的数据结构如下:

1
2
3
4
5
6
7
8
9
10
11
class plt(object):
def __init__(self,st ,pos, vel, mass, acc):
self.status = pygame.transform.scale(pygame.image.load("./resources/" + st).convert(),(10,10))
screen.blit(self.status, (pos[0],pos[1]))
self.rect = pygame.image.load("./resources/" + st).get_rect()
self.pos = pos
self.acc = acc
self.vel = vel
self.mass = mass
self.recordline = [[],[]]
self.recordspeed = [[1],[math.sqrt(self.vel[0] ** 2 + self.vel[1] ** 2)]]

在这个类中,

  • *.status存储在屏幕上绘制星球所需的图片
  • *.rect存储星球的大小
  • *.pos存储星球的坐标位置,是类似于(200,200)的一个二元向量结构,分别表示在X轴和Y轴方向上的数值,以下的加速度、速度等都是如此
  • *.acc存储星球的加速度,类似于pos的数据结构
  • *.vel存储星球的速度,类似于pos的数据结构
  • *.mass存储星球的质量
  • *.recordline记录星球的轨迹,*.recordspeed记录星球的速度

以上,便实现了对于星球数据的基本存储。

计算
1
2
3
4
5
6
7
8
def cal(a, b):
x=b.pos[0]-a.pos[0]
y=b.pos[1]-a.pos[1]
dis=math.sqrt(x ** 2 + y ** 2)
sin=x/dis
cos=y/dis
f=G*a.mass*b.mass/(dis ** 2)
return f*sin,f*cos

在这个函数中,传入两个刚刚新建的plt类变量。通过计算两者横纵坐标之差,根据勾股定理计算距离,接着计算出两者万有引力大小。根据横纵坐标之差,夹角的sin值和cos值进一步将万有引力分解到X轴和Y轴上,函数最终返回值是两者的万有引力分解到X轴方向和Y轴方向上的二元向量。

交互

pygame模块中有关于按键事件的监测,easygui模块中可以轻松调用一些简单的可交互式窗口,便于用户进行最基本的操作,如修改星球、添加星球、修改基本参数、查看数据记录等。

具体代码实现部分过长,可以去开源托管网站(下一章节有提及)查看。

三、研究成果

在我们小组多天的共同努力之下,对于程序不断地修改完善,最终形成了一套可以完整运行的程序

并在以下两个平台开源:

simulate-gravity: 模拟引力 - Gitee.com https://gitee.com/wzcwzc0/simulate-gravity/tree/main/

wzcwzc05/simulate-gravity https://github.com/wzcwzc05/simulate-gravity/tree/main

最终成果演示:

image-20220203215808967

image-20220203215910351image-20220203220127591

image-20220203215952869image-20220203220042715

四、演示

下面演示模拟构建一个存在一个质量为10000的中心天体的恒星系。

首先左键暂停,添加中心天体:

2022-02-11_10-36

计算质量为1的行星在距离为200时进行匀速圆周运动所需的线速度:
$$
已知:G=6.67408e-11(放大10倍)
$$

$$
m_1=10000 \quad m_2=1 \quad r=200
$$

$$
F = G \frac{m_1m_2}{r^2} = 0.166852
$$

$$
F_{向心}=F=m_1\frac{v^2}{r} \quad v=\sqrt{\frac{Fr}{m_1}}=5.7767118
$$

添加行星:

image-20220211105838663

最终结果:

image-20220211105937038image-20220211110014297

速度误差范围在可接受范围内,可近似认为是匀速圆周运动。

五、改进及其建议

虽然程序的大体已经完成,基本功能已经得到实现,但依旧存在与用户交互效果不够好等问题。

在核心原理上,万有引力定律属于经典力学范畴,对于广义相对论存在一定的不足,后期可以考虑使用引力场代替力的计算。

同时在两个星球距离过近时,并未加入碰撞或撕裂等判断,导致一些不合理现象的产生,后期可以加入碰撞或撕裂的判断。