为什么我的天文模拟不准确?

2024-04-29 05:48:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我做了一个程序来模拟太阳系中物体的运动,但是,我的结果有很多不准确的地方。在

我相信这可能和我的积分方法有关。在


太长了,读不下去了,我的模拟和NASA的数据之间的地球的位置和速度有一点不同,如果你能看一下我的代码,告诉我我的数学是不是错了。

我运行的测试是一个10天(864000秒)的模拟,从Thu Mar 13 18:30:59 2006开始,到Thu Mar 23 18:30:59 2006结束。在

在模拟之后,程序报告了地球的以下统计数据:

Earth position: (-1.48934630382e+11, -7437423391.22)
Earth velocity: (990.996767368, -29867.6967867)

测量单位当然是米和米每秒。在

我用水平系统得到了太阳系中大多数大天体的起始位置和速度矢量,并把它们放在模拟中。在

测试结束后,我再次查询了HORIZONS以获取Thu Mar 23 18:30:59 2006地球数据,得到了以下结果:

^{pr2}$

如您所见,结果的前四位数几乎总是相同的。不过,那还是个大小姐!我很担心,因为我要模拟几年的时间,错误可能会升级。在

你能看看我的模拟核心,告诉我我的数学是不是错了?在

def update (self, dt):
    """Pushes the uni 'dt' seconds forward in time."""

    self.time += dt

    for b1, b2 in combinations(self.bodies.values(), 2):
        fg = self.Fg(b1, b2)

        if b1.position.x > b2.position.x:
            b1.force.x -= fg.x
            b2.force.x += fg.x
        else:
            b1.force.x += fg.x
            b2.force.x -= fg.x


        if b1.position.y > b2.position.y:
            b1.force.y -= fg.y
            b2.force.y += fg.y
        else:
            b1.force.y += fg.y
            b2.force.y -= fg.y


    for b in self.bodies.itervalues():
        ax = b.force.x/b.m
        ay = b.force.y/b.m

        b.position.x += b.velocity.x*dt
        b.position.y += b.velocity.y*dt

        nvx = ax*dt
        nvy = ay*dt

        b.position.x += 0.5*nvx*dt
        b.position.y += 0.5*nvy*dt

        b.velocity.x += nvx
        b.velocity.y += nvy

        b.force.x = 0
        b.force.y = 0

我有这个方法的另一个版本,它的性能应该更好,但它的性能要差得多:

def update (self, dt):
    """Pushes the uni 'dt' seconds forward in time."""

    self.time += dt

    for b1, b2 in combinations(self.bodies.values(), 2):
        fg = self.Fg(b1, b2)

        if b1.position.x > b2.position.x:
            b1.force.x -= fg.x
            b2.force.x += fg.x
        else:
            b1.force.x += fg.x
            b2.force.x -= fg.x


        if b1.position.y > b2.position.y:
            b1.force.y -= fg.y
            b2.force.y += fg.y
        else:
            b1.force.y += fg.y
            b2.force.y -= fg.y


    for b in self.bodies.itervalues():
        #Acceleration at (t):
        ax  = b.force.x/b.m
        ay  = b.force.y/b.m
        #Velocity at (t):
        ovx = b.velocity.x
        ovy = b.velocity.y
        #Velocity at (t+dt):
        nvx = ovx + ax*dt
        nvy = ovy + ay*dt
        #Position at (t+dt):
        b.position.x = b.position.x + dt*(ovx+nvx)/2
        b.position.y = b.position.y + dt*(ovy+nvy)/2


        b.force.null() #Reset the forces.

Tags: inselfforiftimedtpositionb2
1条回答
网友
1楼 · 发布于 2024-04-29 05:48:14

积分方法是非常重要的。你使用的是欧拉显式方法,它的精度很低,对于正确的物理模拟来说太低了。现在,你有选择

  • 一般行为最重要:Verlet method,或{a2}(精度更高的Verlet),它们具有很好的节能效果,但位置和速度的精度较低。在
  • 精确的位置最重要:Runge-Kutta顺序4或更多。能量不会守恒,所以你的模拟系统会表现得好像能量增加一样。在

此外,对于大量的步骤,时间=时间+dt将增加精度损失。考虑time=epoch*dt,其中epoch是一个整数,这将使时间变量的精度与步数无关。在

相关问题 更多 >