簡體   English   中英

數值積分:為什么我的軌道模擬會產生錯誤的結果?

[英]Numerical integration: Why does my orbit simulation yield the wrong result?

我閱讀了費曼的物理講座第 9 章,並嘗試了自己的模擬。 我使用黎曼積分來計算速度和 position。 雖然所有的開始進入都是一樣的,但我的軌道看起來就像一條雙曲線。 這是講義: https://www.feynmanlectures.caltech.edu/I_09.html (表 9.2)

import time
import matplotlib.pyplot as plt
x=list()
y=list()
x_in=0.5
y_in=0.0
x.append(x_in)
y.append(y_in)

class Planet:
    def __init__(self,m,rx,ry,vx,vy,G=1):
        self.m=m
        self.rx=rx
        self.ry=ry
        self.a=0
        self.ax=0
        self.ay=0
        self.vx=vx
        self.vy=vy
        self.r=(rx**2+ry**2)**(1/2)
        self.f=0
        self.G=1
        print(self.r)
    def calculateOrbit(self,dt,planet):
        self.rx=self.rx+self.vx*dt
        self.vx=self.vx+self.ax*dt
        self.ax=0
        for i in planet:
            r=((((self.rx-i.rx)**2)+((self.ry-i.ry)**2))**(1/2))
            self.ax+=-self.G*i.m*self.rx/(r**3)

        self.ry=self.ry+self.vy*dt
        self.vy=self.vy+self.ay*dt
        self.ay=0
        for i in planet:
                self.ay+=-self.G*i.m*self.ry/(r**3)
        global x,y
        x.append(self.rx)
        y.append(self.ry)

        #self.showOrbit()
    def showOrbit(self):
        print(""" X: {} Y: {} Ax: {} Ay: {}, Vx: {}, Vy: {}""".format(self.rx,self.ry,self.ax,self.ay,self.vx,self.vy))

planets=list();
earth = Planet(1,x_in,y_in,0,1.630)
sun =   Planet(1,0,0,0,0)
planets.append(sun)
for i in range(0,1000):
    earth.calculateOrbit(0.1,planets)

plt.plot(x,y)
plt.grid()
plt.xlim(-20.0,20.0)
plt.ylim(-20.0,20.0)
plt.show()

dt應該無限小才能使集成起作用。

dt越大,“局部線性化誤差”就越大(可能有一個更好的數學術語......)。

dt0.1可能看起來足夠小,但是為了讓您的結果正確收斂(接近現實),您還需要檢查更小的時間步長。 如果較小的時間步長收斂到相同的解,則您的方程linar enough線性,可以使用更大的時間步長(並節省計算時間。)

試試你的代碼

for i in range(0, 10000):
    earth.calculateOrbit(0.01, planets)

for i in range(0, 100000):
    earth.calculateOrbit(0.001, planets)

在這兩種計算中,自開始以來經過的總時間與您的原始值相同。 但結果卻大不相同。 因此,您可能必須使用更小的dt

更多信息:

https://en.wikipedia.org/wiki/Trapezoidal_rule

這個頁面說明了你在做什么:

如果被積函數表現得相當好(即分段連續和有界變化),則可以通過以非常小的增量評估被積函數來完成“蠻力”類型的數值積分。

以及我在上面試圖解釋的內容:

任何數值積分方法分析的一個重要部分是研究近似誤差的行為作為被積函數評估次數的 function。

許多聰明的方法可以做出更好的猜測並使用更大的時間步長。 您可能聽說過用於求解微分方程的Runge–Kutta method 它似乎成為上面鏈接中提到的非微分方程的Simpson's rule ,請參見此處

問題是微分方程的數值積分或數值解的方法。 您正在使用的方法(用於微分方程數值解的歐拉方法),雖然它給出的值非常接近實際值,但仍然給出了非常小的誤差。 當在多次迭代中使用這個稍微有誤差的值時(就像你已經完成了 1000 步),這個誤差在每一步都會變得越來越大,這會給你錯誤的結果。

這個問題可以有兩種解決方案:

  1. 將時間間隔減小到更小的值,這樣即使在整個過程中放大了錯誤之后,它也不會在很大程度上偏離實際解決方案。 現在要注意的是,如果您減少時間間隔(dt)而不增加步數,那么您可以在更短的時間內看到系統的演變。 因此,隨着時間間隔(dt)的減少,您也必須增加步數。 我檢查了您的代碼,似乎如果您將 dt = 0.0001 並將步數設置為 100000 而不是 1000,您將獲得您正在尋找的美麗橢圓軌道。 此外,刪除或注釋掉 plt.xlim 和 plt.ylim 行以清楚地查看您的 plot。

  2. 實現微分方程數值解的龍格-庫塔方法。 該方法在每次迭代時對實際解具有更好的收斂性。 因為,這將花費更多的時間和更改您的代碼,這就是為什么我建議它作為第二種選擇,否則這種方法比 Euler 的方法更優越且更通用。

注意:即使沒有任何更改,解決方案也不會表現得像雙曲線。 對於您為系統提供的初始值,解決方案是給出一條有界曲線,但僅僅因為誤差放大,它會螺旋成一個點。 如果您將步長增加到 10000 並將 dt = 0.01,您會注意到這種螺旋式上升。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM