我正试图用py制作一个基本的重力模拟,但出于某种原因,它把所有的线都画成了直线。当我陷入困境时,我看了几个例子,但它们都使用了类似的方程/绘制数据的方法,所以不确定哪里出了问题
class Body:
# A class to initialise a body of mass to plot
def __init__(self, id, mass, coordinates, velocities):
self.id = id
self.coordinates = np.array(coordinates, dtype=float)
self.v = np.array(velocities, dtype=float)
self.mass = mass
self.a = np.zeros(3, dtype=float)
MOTION_LOG.append({"name": self.id, "x":[coordinates[0]], "y": [coordinates[1]], "z": [coordinates[2]]})
# Procedure for checking gravity effects on body
def gravity(self):
self.a = 0
for body in bodies:
if body != self:
dist = body.coordinates - self.coordinates
r = np.sqrt(np.sum(dist**2))
self.a += (SETTINGS['G'] * body.mass * dist / r**3) ** 2
# Procedure to plot the new coordinates of the body
def move(self):
self.v += self.a * SETTINGS["deltaT"]
self.coordinates += self.v * SETTINGS['deltaT']
然后为了真正模拟它,我做了
# For loop to run a simulation for a specific time set
for step in range(int(SETTINGS["tLimit"] / SETTINGS["deltaT"])):
SETTINGS['elapsedT'] += SETTINGS['deltaT']
if SETTINGS['elapsedT'] % SETTINGS["frequency"] == 0:
prog = ((SETTINGS['elapsedT'] / SETTINGS['tLimit'])*100)//1
for index, location in enumerate(MOTION_LOG):
location["x"].append(bodies[index].coordinates[0])
location["y"].append(bodies[index].coordinates[1])
location["z"].append(bodies[index].coordinates[2])
print(f"{prog}%")
for body in bodies:
body.gravity()
for body in bodies:
body.move()
最后,为了在图表上绘制它,我做了
fig = plt.figure()
ax = fig.add_subplot(1,1,1, projection='3d')
for body in MOTION_LOG:
ax.plot(body["x"], body["y"], body["z"])
plt.show()
不确定我是只是把加速度做错了,还是只是把点画错了,但我看到的其他例子做的事情并没有太大的不同
示例数据
SETTINGS = {
'G' : 6.67e-11,
'deltaT' : 172800,
'elapsedT' : 0,
'tLimit' : 315360000,
"frequency": 1,
}
MOTION_LOG = []
bodies = []
set_bodies = {
"Sun": {
"id": "Sun",
"mass": 1e20,
"coordinates": [0, 0, 0],
"velocities": [0, 0, 0]
},
"Earth": {
"id": "Earth",
"mass": 1e3,
"coordinates": [1e2, -1e2, 0],
"velocities": [0, 0, 0]
}
}
for body, body_data in set_bodies.items():
bodies.append(Body(**body_data))
首先,加速度是平方。你的线路是:
self.a += (SETTINGS['G'] * body.mass * dist / r**3) ** 2
你想要的是:
self.a += (SETTINGS['G'] * body.mass * dist / r**3)
其次,你的数字都不正常。Never,Never只需猜测用于此类模拟的数字组合。要么使用完全自然的单位(其中格拉夫常数、太阳质量和AU都等于一(,要么使用所有实际数字。当你不这样做的时候,你只是在猜测什么时间步长是合适的,而且很难做到这一点。例如,用你用来计算太阳质量、格拉夫常数和地球轨道半径的数字,一个时间单位大约是7.7年。为了得到看起来不错的东西,你需要一个大约7e-4
的时间步长,运行到大约1.3
的最后时间,并使用地球的初始速度[5000, 5000, 0]
(你还需要改变添加到MOTION_LOG
的方式,因为小浮子与mod(%
(配合不好(。但不要这样做——使用合理的数字。当你不必花几个小时来回转换成你真正想要的单位时,你最终会更快乐。
第三,你的"地球;物体并没有初始速度。无论你如何修正方程或单位,它都会落入太阳。
这里有一些关于权利的";真实的";使用国际单位制的数字:
set_bodies = {
"Sun": {
"id": "Sun",
"mass": 2e30,
"coordinates": [0, 0, 0],
"velocities": [0, 0, 0]
},
"Earth": {
"id": "Earth",
"mass": 6e24,
"coordinates": [1.5e11, 0, 0],
"velocities": [0, 3e4, 0]
}
}