import matplotlib import matplotlib.pyplot as plt matplotlib.use("Agg") import numpy as np m=1.0; GM=4.*np.pi**2 R0=1.; V0=np.pi*2. r1=np.array([R0,0.]) v1=np.array([0., V0]) r1n=np.linalg.norm(r1) a1=np.array([-GM/r1n**3*r1[0],-GM/r1n**3*r1[1]]) xp1=[r1[0]]; yp1=[r1[1]] t=0.; dt=0.01 tp=[t] while t < 2.: print ('%11.5f'*6 %(t,r1[0],r1[1],v1[0],v1[1],r1n)) #print '%9.4f'*7 %(t,dr,drx,r1[0],r1[1],r2[0],r2[1]) v1n=np.linalg.norm(v1) r1n=np.linalg.norm(r1) a1=np.array([-GM/r1n**3*r1[0],-GM/r1n**3*r1[1]]) r1+=v1*dt #Euler v1+=a1*dt #r1+=v1*dt #Euler-Cromer t+=dt tp.append(t) xp1.append(r1[0]) yp1.append(r1[1]) plt.plot(xp1,yp1) plt.axis('equal') plt.savefig("orbital-1.png") plt.close()
# coding=Big5 import numpy as np import matplotlib.pyplot as plt m=1.0; GM=4.*np.pi**2 R0=1.; V0=np.pi*2. r1=np.array([R0,0.]) v1=np.array([0., V0]) r1n=np.linalg.norm(r1) a1=np.array([-GM/r1n**3*r1[0],-GM/r1n**3*r1[1]]) xp1=[r1[0]]; yp1=[r1[1]] r2=np.array([R0,0.]) v2=np.array([0., V0*0.8]) r2n=np.linalg.norm(r2) a2=np.array([-GM/r2n**3*r2[0],-GM/r2n**3*r2[1]]) xp2=[r2[0]]; yp2=[r2[1]] t=0.; dt=0.01 tp=[t] while t < 2.: print '%10.5f'*7 %(t,r1[0],r1[1],r2[0],r2[1],r1n,r2n) #print '%9.4f'*7 %(t,dr,drx,r1[0],r1[1],r2[0],r2[1]) v1n=np.linalg.norm(v1) r1n=np.linalg.norm(r1) a1=np.array([-GM/r1n**3*r1[0],-GM/r1n**3*r1[1]]) r1+=v1*dt v1+=a1*dt #r1+=v1*dt v2n=np.linalg.norm(v2) r2n=np.linalg.norm(r2) a2=np.array([-GM/r2n**3*r2[0],-GM/r2n**3*r2[1]]) r2+=v2*dt v2+=a2*dt #r2+=v2*dt t+=dt tp.append(t) xp1.append(r1[0]); yp1.append(r1[1]) xp2.append(r2[0]); yp2.append(r2[1]) plt.plot(xp1,yp1) plt.axis('equal') plt.plot(xp2,yp2) plt.show()
那麼這樣的順序是對的,因為r1的更新時所使用的速度v1,就是時間為t的時候的速度;v1更新時所使用的加速度,也是在時間為t的時候的加速度a1。Euler-Cromer method是將位置的更新與速度的更新的兩條指令對調:a1=np.array([-GM/r1n**3*r1[0],-GM/r1n**3*r1[1]]) r1+=v1*dt v1+=a1*dt
如此一來雖然速度v1的更新,仍然是使用前一個時刻的加速度a1,但是位置r1的更新,所使用的速度並前一時刻的速度,而是已經更新過後的速度。所以如果我們的數值計算是用這種方式來進行的話,那麼將是兩種更新的混合。原則上我們並不知道哪一個方式會得到比較精確的結果,但是在實際應用中,似乎Euler-Cromer method都具有較高的精確度,例如下面的樣本程式就是比較Euler和Euler-Cromer計算一個行星運動的程式,我們從這個程式執行得到的數據作比較,可以明顯發現Euler-Cromer確實有相當大幅度的改進。a1=np.array([-GM/r1n**3*r1[0],-GM/r1n**3*r1[1]]) v1+=a1*dt r1+=v1*dt
import matplotlib import matplotlib.pyplot as plt matplotlib.use("Agg") import numpy as np m=1.0; GM=4.*np.pi**2 R0=1.; V0=np.pi*2. r1=np.array([R0,0.]) v1=np.array([0., V0]) r1n=np.linalg.norm(r1) a1=np.array([-GM/r1n**3*r1[0],-GM/r1n**3*r1[1]]) xp1=[r1[0]]; yp1=[r1[1]] r2=np.array([R0,0.]) v2=np.array([0., V0*1.]) r2n=np.linalg.norm(r2) a2=np.array([-GM/r2n**3*r2[0],-GM/r2n**3*r2[1]]) xp2=[r2[0]]; yp2=[r2[1]] t=0.; dt=0.01 tp=[t] while t < 2.: print ('%10.5f'*7 %(t,r1[0],r1[1],r2[0],r2[1],r1n,r2n)) v1n=np.linalg.norm(v1) r1n=np.linalg.norm(r1) a1=np.array([-GM/r1n**3*r1[0],-GM/r1n**3*r1[1]]) r1+=v1*dt v1+=a1*dt #r1+=v1*dt v2n=np.linalg.norm(v2) r2n=np.linalg.norm(r2) a2=np.array([-GM/r2n**3*r2[0],-GM/r2n**3*r2[1]]) #r2+=v2*dt v2+=a2*dt r2+=v2*dt t+=dt tp.append(t) xp1.append(r1[0]); yp1.append(r1[1]) xp2.append(r2[0]); yp2.append(r2[1]) plt.plot(xp1,yp1,label=r"Euler") plt.plot(xp2,yp2,label=r"Euler-Cromer") plt.axis('equal') plt.legend() plt.savefig("orbital-3.png") plt.close()
import matplotlib import matplotlib.pyplot as plt matplotlib.use("Agg") import numpy as np m=1.0; GM=4.*np.pi**2 R0=1.; V0=np.pi*2. r1=np.array([R0,0.]) v1=np.array([0., V0]) r1n=np.linalg.norm(r1) a1=np.array([-GM/r1n**3*r1[0],-GM/r1n**3*r1[1]]) xp1=[r1[0]]; yp1=[r1[1]] r2=np.array([R0,0.]) v2=np.array([0., V0*1.]) r2n=np.linalg.norm(r2) a2=np.array([-GM/r2n**3*r2[0],-GM/r2n**3*r2[1]]) xp2=[r2[0]]; yp2=[r2[1]] t=0.; dt=0.01; dt2=dt/2. tp=[t] while t < 2.: print ('%10.5f'*7 %(t,r1[0],r1[1],r2[0],r2[1],r1n,r2n)) v1n=np.linalg.norm(v1) r1n=np.linalg.norm(r1) a1=np.array([-GM/r1n**3*r1[0],-GM/r1n**3*r1[1]]) r1+=v1*dt v1+=a1*dt #r1+=v1*dt v2n=np.linalg.norm(v2) r2n=np.linalg.norm(r2) a2=np.array([-GM/r2n**3*r2[0],-GM/r2n**3*r2[1]]) ts=+dt2 r2s=r2+v2*dt2 v2s=v2+a2*dt2 r2sn=np.linalg.norm(r2s) a2s=np.array([-GM/r2sn**3*r2s[0],-GM/r2sn**3*r2s[1]]) r2+=v2s*dt v2+=a2s*dt #r2+=v2*dt t+=dt tp.append(t) xp1.append(r1[0]); yp1.append(r1[1]) xp2.append(r2[0]); yp2.append(r2[1]) plt.plot(xp1,yp1,label=r"Euler") plt.plot(xp2,yp2,label=r"RK2") plt.axis('equal') plt.legend() plt.savefig("orbital-4.png") plt.close()