2

太陽系の物体の動きをシミュレートするプログラムを作成しましたが、結果にさまざまな不正確さが生じています。

それはおそらく私の統合方法と関係があると思います。


tl;dr 私のシミュレーションと 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 13 18:30:59 2006て、太陽系のほとんどの大きな天体の開始位置と速度ベクトルを取得し、それらをシミュレーションに入れました。

テストの後、HORIZONS にThu Mar 23 18:30:59 2006地球データを再度問い合わせたところ、次の結果が得られました。

Earth position: (-1.489348720130393E+11, -7437325664.023257)
Earth velocity: (990.4160633376971, -2986.736541327986)

ご覧のとおり、結果はほとんど常に最初の 4 桁で同じです。しかし、それはまだかなり大きなミスです!数年後にシミュレートする必要があり、エラーがエスカレートする可能性があるため、心配しています。

私のシミュレーションの核心を見て、私の計算が間違っているか教えていただけませんか?

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.
4

1 に答える 1

11

統合方法は非常に重要です。オイラー明示的方法を使用しています。これは低次の精度であり、適切な物理シミュレーションには低すぎます。今、あなたは選択肢を得る

  • 一般的な動作が最も重要です:Verlet法、またはBeeman法(より精度の高いVerlet)。これらは非常に優れたエネルギー節約を実現しますが、位置と速度の精度は低くなります。
  • 正確な位置が最も重要です:ルンゲクッタ法4以上。エネルギーは保存されないため、シミュレートされたシステムはエネルギーが増加したかのように動作します。

さらに、時間=時間+ dtでは、多数のステップで精度が低下します。time = epoch * dtを考えます。ここで、epochは整数であり、時間変数の精度はステップ数に依存しません。

于 2013-02-27T11:48:03.887 に答える