新しく発言する EXIT インデックスへ
3体問題の実験がうまくいきません

  3体問題の実験がうまくいきません 会社員 2005/12/18 22:11:10 
  3体問題の実験がうまくいきません 青木太一 2005/12/19 07:49:24 
  │├接近してしまうと、ものすごく大きい力にな... 青木太一 2005/12/19 08:18:52 
  │└会社員さんのコードをちょっと書き換えまし... 青木太一 2005/12/19 08:31:56 
  │ ├このコードでも86万ぐらいになったところで... 青木太一 2005/12/19 08:57:01 
  │ └ありがとうございました 会社員 2005/12/19 21:15:58 
  エネルギー保存の法則を使って 会社員 2005/12/24 01:56:49 
   ├前半コード(1/2) 会社員 2005/12/24 02:00:15 
   ├後半コード(2/2) 会社員 2005/12/24 02:01:31 
   └計算量が減りません 青木太一 2005/12/26 21:42:31 
    └三回目以降のdtの値が小さすぎます。 会社員 2005/12/29 15:50:50 

  3体問題の実験がうまくいきません 会社員 2005/12/18 22:11:10  ツリーへ

3体問題の実験がうまくいきません 返事を書く
会社員 2005/12/18 22:11:10
係数がだめなんでしょうか?

!*************3体問題の実験 *****************************

!******画面の準備**********************
LET mado=1000
SET window -mado,mado,-mado,mado
DRAW grid
SET TEXT COLOR 4
PLOT TEXT ,AT -0.8*mado,0.8*mado:"TEST"
!************************************

!■■■初期設定■■■■■■■■■■
LET K=0.1 !場の係数
DIM X(3),Y(3),XV(3),YV(3),XG(3),YG(3)
!*****Aの初期位置と速度**********
LET X(1)=0.3*mado
LET Y(1)=-0.1*mado
!*****Bの初期位置と速度**********
LET X(2)=-0.35*mado
LET Y(2)=0.25*mado
!*****Cの初期位置と速度**********
LET X(3)=0.2*mado
LET Y(3)=0.35*mado
!********************************
FOR I=1 TO 3
LET XV(I)=0
LET YV(I)=0
NEXT I
!********************************


!******メインルーチン***************
FOR T=0 TO 1000000
gosub 800 !表示
NEXT T
!******************************************


!****サブルーチン**********************
800
!■場の計算 距離の2乗に反比例
FOR I=0 TO 2
LET A=MOD(I,3)+1
LET B=MOD(I+1,3)+1
LET C=MOD(I+2,3)+1
LET XG(A)=-K/((X(A)-X(B))^2+(Y(A)-Y(B))^2)*(X(A)-X(B))/((X(A)-X(B))^2+(Y(A)-Y(B))^2)^0.5 !X成分
LET XG(A)=-K/((X(A)-X(C))^2+(Y(A)-Y(C))^2)*(X(A)-X(C))/((X(A)-X(C))^2+(Y(A)-Y(C))^2)^0.5+XG(A) !X成分
LET YG(A)=-K/((X(A)-X(B))^2+(Y(A)-Y(B))^2)*(Y(A)-Y(B))/((X(A)-X(B))^2+(Y(A)-Y(B))^2)^0.5 !Y成分
LET YG(A)=-K/((X(A)-X(C))^2+(Y(A)-Y(C))^2)*(Y(A)-Y(C))/((X(A)-X(C))^2+(Y(A)-Y(C))^2)^0.5+YG(A) !Y成分
NEXT I

!■軌跡をプロット
SET POINT COLOR 3 ! 白0黒1青2緑3赤4緑5黄6
SET POINT STYLE 5 ! 1・2+3*4○5×
FOR I=1 TO 3
PLOT POINTS:X(I),Y(I)
NEXT I

!■単位時間後の位置
FOR I=1 TO 3
LET X(I)=XV(I)+X(I)
LET Y(I)=YV(I)+Y(I)
NEXT I

!■単位時間後の速度
FOR I=1 TO 3
LET XV(I)=XV(I)+XG(I)
LET YV(I)=YV(I)+YG(I)
NEXT I

!■移動後の位置をプロット
SET POINT COLOR 1 ! 白0黒1青2緑3赤4緑5黄6
SET POINT STYLE 5 ! 1・2+3*4○5×
FOR I=1 TO 3
PLOT POINTS:X(I),Y(I)
NEXT I
! WAIT DELAY 0.001
RETURN

END

  3体問題の実験がうまくいきません 青木太一 2005/12/19 07:49:24  ツリーへ

Re: 3体問題の実験がうまくいきません 返事を書く
青木太一 2005/12/19 07:49:24
>3体問題の実験がうまくいきません
なぜうまくいっていないと思われるのでしょうか?

もしTが6万になったころ1番と3番が接近して、お互いを吹き飛ばすような動きをするのがおかしいと思われるのでしたら、それは正常な動きだと思います。
重力は距離の二乗に反比例するので、接近した二体間ではものすごい力が働くからです。

今回の話とはちょっとズレますが、実際に太陽系ができるとき、小さい星は木星などによって重力的にボンボン吹き飛ばされたいたという話もあります。
http://www.moriyama.com/netscience/Ida_Shigeru/Ida-1.html#03

  │├接近してしまうと、ものすごく大きい力にな... 青木太一 2005/12/19 08:18:52  ツリーへ

Re: 3体問題の実験がうまくいきません 返事を書く
青木太一 2005/12/19 08:18:52
接近してしまうと、ものすごく大きい力になってしまうため、単位時間あたりの移動量が大きくなって精度が落ちるという問題もあります。
http://jun.artcompsci.org/~makino/papers/ode/node5.html
上記URLによると解決方法として
・重力の式を変えてしまう
・時間刻み幅を変える
などがあるようです。

  │└会社員さんのコードをちょっと書き換えまし... 青木太一 2005/12/19 08:31:56  ツリーへ

Re: 3体問題の実験がうまくいきません 返事を書く
青木太一 2005/12/19 08:31:56
会社員さんのコードをちょっと書き換えました。
変更点は
・gotoを使わない
・3体以上の問題も解けるように、力の計算のforループを変更
・時間刻み(単位時間)dtを変更できるようにした。
・位置の更新より速度の更新を先にした

最後のは
http://jun.artcompsci.org/~makino/papers/ode/ode-e.html
の1章の最後と2章の最初で言っている一次のシンプレクティック法というやつみたいです。オイラー法とどう違うのか、私にはよくわかりません(笑)。

で、シンプレクティック法にしたら、Tが6万のころ吹き飛ぶ現象はなくなりました。これはシンプレクティック法にして精度があがったおかげなのか、たまたまなのかはわかりません。(シンプレクティック法だって、吹き飛ぶときは吹き飛ぶだろうし)

!******画面の準備**********************
LET mado=1000
SET window -mado,mado,-mado,mado
DRAW grid
SET TEXT COLOR 4
PLOT TEXT ,AT -0.8*mado,0.8*mado:"TEST"
!************************************

!■■■初期設定■■■■■■■■■■
LET K=0.1 !場の係数
LET dt=1!単位時間
DIM X(3),Y(3),XV(3),YV(3),XG(3),YG(3)
!*****Aの初期位置と速度**********
LET X(1)=0.3*mado
LET Y(1)=-0.1*mado
!*****Bの初期位置と速度**********
LET X(2)=-0.35*mado
LET Y(2)=0.25*mado
!*****Cの初期位置と速度**********
LET X(3)=0.2*mado
LET Y(3)=0.35*mado
!********************************
FOR I=1 TO 3
LET XV(I)=0
LET YV(I)=0
NEXT I
!********************************


!******メインルーチン***************
FOR T=0 TO 1000000
call main_loop
NEXT T
!******************************************

!****サブルーチン**********************
sub main_loop

!■場の計算 距離の2乗に反比例
for i=1 to 3
LET xg(i)=0
LET yg(i)=0
next i
for i=1 to 3
for j=i+1 to 3
LET rr=(x(i)-x(j))^2 + (y(i)-y(j))^2
LET r=sqr(rr)
LET f_ij=-K/rr ! iがjに引かれる引力
LET fx_ij=f_ij*(x(i)-x(j))/r !x成分
LET xg(i)=xg(i)+fx_ij
LET xg(j)=xg(j)-fx_ij
LET fy_ij=f_ij*(y(i)-y(j))/r !y成分
LET yg(i)=yg(i)+fy_ij
LET yg(j)=yg(j)-fy_ij
next j
next i

!■軌跡をプロット
SET POINT COLOR 3 ! 白0黒1青2緑3赤4緑5黄6
SET POINT STYLE 5 ! 1・2+3*4○5×
FOR I=1 TO 3
PLOT POINTS:X(I),Y(I)
NEXT I

!■単位時間後の速度
FOR I=1 TO 3
LET XV(I)=XV(I)+XG(I)*dt
LET YV(I)=YV(I)+YG(I)*dt
NEXT I

!■単位時間後の位置
FOR I=1 TO 3
LET X(I)=X(I)+XV(I)*dt
LET Y(I)=Y(I)+YV(I)*dt
NEXT I

!■移動後の位置をプロット
SET POINT COLOR 1 ! 白0黒1青2緑3赤4緑5黄6
SET POINT STYLE 5 ! 1・2+3*4○5×
FOR I=1 TO 3
PLOT POINTS:X(I),Y(I)
NEXT I
! WAIT DELAY 0.001

end sub

END

  │ ├このコードでも86万ぐらいになったところで... 青木太一 2005/12/19 08:57:01  ツリーへ

Re: 会社員さんのコードをちょっと書き換えまし... 返事を書く
青木太一 2005/12/19 08:57:01
このコードでも86万ぐらいになったところで、吹き飛んでしまいました。軌跡の描き方をちょっと変更しましたが、こんな感じです。
http://inet-lab.naist.jp/~taichi-a/3n.png
それでは。

  │ └ありがとうございました 会社員 2005/12/19 21:15:58  ツリーへ

Re: 会社員さんのコードをちょっと書き換えまし... 返事を書く
会社員 2005/12/19 21:15:58
ありがとうございました


時分割が少なすぎたのかもしれません。
青木太一の案の位置の更新より速度の更新を先にしました。

併せて
・色をつけ
・○表示で物体らしくしました


!******3体問題の実験 **********
!******画面の準備********************
LET mado=1000
SET window -mado,mado,-mado,mado
SET TEXT COLOR 4
!************************************

!■■■初期設定■■■■■■■■■■
LET K=1 !場の係数
LET dt=1/5 !時間の分割数
DIM X(3),Y(3),XV(3),YV(3),XG(3),YG(3)
!*****Aの初期位置と速度**********
LET X(1)=0.3*mado
LET Y(1)=-0.1*mado
!*****Bの初期位置と速度**********
LET X(2)=-0.35*mado
LET Y(2)=0.25*mado
!*****Cの初期位置と速度**********
LET X(3)=0.2*mado
LET Y(3)=0.35*mado
!********************************
!*****初期速度*************
FOR I=1 TO 3
LET XV(I)=0
LET YV(I)=0
NEXT I
!**************************


!******メインルーチン***************
FOR T=0 TO 10000000
DRAW grid
PLOT TEXT ,AT -0.8*mado,0.8*mado:"TEST"
GOSUB 800 !表示
NEXT T
!**********************************

stop


!****サブルーチン**********************
800
!■場の計算 距離の2乗に反比例
FOR I=0 TO 2
LET A=MOD(I,3)+1
LET B=MOD(I+1,3)+1
LET C=MOD(I+2,3)+1
LET XG(A)=-K/((X(A)-X(B))^2+(Y(A)-Y(B))^2)^1.5*(X(A)-X(B)) !X成分
LET XG(A)=-K/((X(A)-X(C))^2+(Y(A)-Y(C))^2)^1.5*(X(A)-X(C))+XG(A) !X成分
LET YG(A)=-K/((X(A)-X(B))^2+(Y(A)-Y(B))^2)^1.5*(Y(A)-Y(B)) !Y成分
LET YG(A)=-K/((X(A)-X(C))^2+(Y(A)-Y(C))^2)^1.5*(Y(A)-Y(C))+YG(A) !Y成分
NEXT I

!■軌跡をプロット
FOR I=1 TO 3
SET POINT COLOR I+1 ! 白0黒1青2緑3赤4緑5黄6
SET POINT STYLE 4 ! 1・2+3*4○5×
PLOT POINTS:X(I),Y(I)
NEXT I

!■単位時間後の速度
FOR I=1 TO 3
LET XV(I)=XV(I)+XG(I)*dt
LET YV(I)=YV(I)+YG(I)*dt
NEXT I

!■単位時間後の位置
FOR I=1 TO 3
LET X(I)=X(I)+XV(I)*dt
LET Y(I)=Y(I)+YV(I)*dt
NEXT I

!■移動後の位置をプロット
SET POINT COLOR 1 ! 白0黒1青2緑3赤4緑5黄6
SET POINT STYLE 4 ! 1・2+3*4○5×
FOR I=1 TO 3
PLOT POINTS:X(I),Y(I)
NEXT I
RETURN

END

  エネルギー保存の法則を使って 会社員 2005/12/24 01:56:49  ツリーへ

Re: 3体問題の実験がうまくいきません 返事を書く
会社員 2005/12/24 01:56:49
エネルギー保存の法則を使って
計算量を減らす目的で
エネルギー変化の大きい場合だけ
精度を10倍100倍1000倍・・に上げて再計算させてみました。

計算量が減りません。

何かよいアイデアありませんか?

   ├前半コード(1/2) 会社員 2005/12/24 02:00:15  ツリーへ

Re: エネルギー保存の法則を使って 返事を書く
会社員 2005/12/24 02:00:15
前半コード(1/2)

!3体問題の実験
!画面の準備
LET mado=1000
SET window -mado,mado,-mado,mado
SET TEXT COLOR 4
!

!■■■初期設定■■■■■■■■■■
LET K=1 !場の係数
LET dt0=1/5 !時間の分割数
LET err_hi=10^(-5)


DIM X(3),Y(3),XV(3),YV(3),XG(3),YG(3)
DIM TMP_X(3),TMP_Y(3),TMP_XV(3),TMP_YV(3)
!*Aの初期位置と速度
LET X(1)=0.3*mado
LET Y(1)=-0.1*mado
!*Bの初期位置と速度
LET X(2)=-0.35*mado
LET Y(2)=0.25*mado
!*Cの初期位置と速度
LET X(3)=0.2*mado
LET Y(3)=0.35*mado
!
!初期速度
FOR I=1 TO 3
LET XV(I)=0
LET YV(I)=0
NEXT I
!
CALL E_SUM !エネルギー総和
PRINT "E_SUM=";E_SUM

!メインルーチン*
FOR T=0 TO 1000000000
DRAW grid
PLOT TEXT ,AT -0.8*mado,0.8*mado:"TEST"
LET dt=dt0
CALL main_loop !表示
NEXT T
!


!サブルーチン
SUB main_loop
CALL ST_SAVE !位置と速度とエネルギーのセーブ TMP_X(I)<=X(I)
CALL PLT_CLOR !軌跡をプロット

LET N=1
DO
CALL DLOAD !データをロード TMP_X(I)=>X(I)
! PRINT "N=";N
FOR H=1 TO N
CALL GRAVTY !場の計算
CALL v_POS !単位時間後の速度・位置
NEXT H
CALL E_SUM !エネルギーの計算
! PRINT "ABS((E_SUM-TMP_E_SUM)/E_SUM)=";ABS((E_SUM-TMP_E_SUM)/E_SUM)
IF ABS((E_SUM-TMP_E_SUM)/E_SUM)<err_hi THEN
! PRINT "○ ";
ELSE
PRINT "×";E_SUM
LET N=10*N
LET dt=dt/N
END IF
LOOP UNTIL ABS((E_SUM-TMP_E_SUM)/E_SUM)<err_hi !誤差以内

CALL PLT_BLK !先端の位置をプロット

!置き換え処理
LET TMP_E_SUM=E_SUM
FOR I=1 TO 3
LET TMP_X(I)=X(I)
LET TMP_Y(I)=Y(I)
LET TMP_XV(I)=XV(I)
LET TMP_YV(I)=YV(I)
NEXT I


END SUB

   ├後半コード(2/2) 会社員 2005/12/24 02:01:31  ツリーへ

Re: エネルギー保存の法則を使って 返事を書く
会社員 2005/12/24 02:01:31
後半コード(2/2)

SUB DLOAD
!置き換え処理
LET E_SUM=TMP_E_SUM
FOR I=1 TO 3
LET X(I)=TMP_X(I)
LET Y(I)=TMP_Y(I)
LET XV(I)=TMP_XV(I)
LET YV(I)=TMP_YV(I)
NEXT I
END SUB

SUB GRAVTY !距離の2乗に反比例
FOR I=0 TO 2
LET A=MOD(I,3)+1
LET B=MOD(I+1,3)+1
LET C=MOD(I+2,3)+1
LET XG(A)=-K/((X(A)-X(B))^2+(Y(A)-Y(B))^2)^1.5*(X(A)-X(B)) !X成分
LET XG(A)=-K/((X(A)-X(C))^2+(Y(A)-Y(C))^2)^1.5*(X(A)-X(C))+XG(A) !X成分
LET YG(A)=-K/((X(A)-X(B))^2+(Y(A)-Y(B))^2)^1.5*(Y(A)-Y(B)) !Y成分
LET YG(A)=-K/((X(A)-X(C))^2+(Y(A)-Y(C))^2)^1.5*(Y(A)-Y(C))+YG(A) !Y成分
NEXT I
END SUB

SUB v_POS
!■単位時間後の速度・位置
FOR I=1 TO 3
LET XV(I)=XV(I)+XG(I)*dt
LET YV(I)=YV(I)+YG(I)*dt
NEXT I
FOR I=1 TO 3
LET X(I)=X(I)+XV(I)*dt
LET Y(I)=Y(I)+YV(I)*dt
NEXT I
END SUB

SUB E_SUM !■総運動エネルギーの計算
LET SUM_mvv=0
FOR I=1 TO 3
LET SUM_mvv=SUM_mvv+1/2*1*1*(SQR(XV(I)^2+YV(I)^2))^2
NEXT I
!総位置エネルギー
LET SUM_ichi=0
LET SUM_ichi=-K*1*1/SQR((X(1)-X(2))^2+(Y(1)-Y(2))^2)
LET SUM_ichi=-K*1*1/SQR((X(2)-X(3))^2+(Y(2)-Y(3))^2)+SUM_ichi
LET SUM_ichi=-K*1*1/SQR((X(3)-X(1))^2+(Y(3)-Y(1))^2)+SUM_ichi
LET E_SUM=SUM_mvv+SUM_ichi
! PRINT "合計=";E_SUM;"運動E=";SUM_mvv;"位置E=";SUM_ichi
END SUB

SUB ST_SAVE !計算前の状態保存
LET TMP_E_SUM=E_SUM
FOR I=1 TO 3
LET TMP_X(I)=X(I)
LET TMP_Y(I)=Y(I)
LET TMP_XV(I)=XV(I)
LET TMP_YV(I)=YV(I)
NEXT I
END SUB

SUB PLT_BLK !■先端の位置をプロット
SET POINT COLOR 1 ! 白0黒1青2緑3赤4緑5黄6
SET POINT STYLE 4 ! 1・2+3*4○5×
FOR I=1 TO 3
PLOT POINTS:X(I),Y(I)
NEXT I
END SUB

SUB PLT_CLOR
!■軌跡をプロット
FOR I=1 TO 3
SET POINT COLOR I+1 ! 白0黒1青2緑3赤4緑5黄6
SET POINT STYLE 4 ! 1・2+3*4○5×
PLOT POINTS:X(I),Y(I)
NEXT I
END SUB

END

   └計算量が減りません 青木太一 2005/12/26 21:42:31  ツリーへ

Re: エネルギー保存の法則を使って 返事を書く
青木太一 2005/12/26 21:42:31
>計算量が減りません
「時間刻みdt0の間の、力学的エネルギーの変化率をerr_hiに抑える」という条件を満たした状態で計算量を抑えたいということでしょうか?

あまりいいアイディアはないのですが、
・細かい最適化を行う
たとえば重力の相互計算ですが、二体間に働く力は同じなのに、会社員さんのコードではわざわざ二体の立場を入れ違えた場合も再計算しています。
三体問題のとき、会社員さんのコードでは6回重力計算がありますが、私のコードなら3回ですみます。
http://freebbs.around.ne.jprdeggo/ufspkc.html#ufspkc
ここを私の用に二重のfor文にするとか。
また、速度エネルギーの計算でSQRかけたあと二乗していあすが、これは無駄な処理ではないでしょうか。
どちらも、全体の計算量のうちどのていどを占めているの調べていないので、効果的かどうかはわかりませんが。
・もっとよい数値計算アルゴリズムに変更する
たとえばルンゲ・クッタ法とか。

ところでエネルギー変化率が大きいときのNとdtの更新に疑問があります。

会社員さんのコードでは、変化率が大きいとき
> LET N=10*N
> LET dt=dt/N
を行いますが、これですと

一回目
N=1
dt=dt0
失敗すると二回目は
N=10
dt=dt0/10
さらに失敗すると三回目が
N=100
dt=dt0/10/100
となってしまいます。
もし、全体的にdt0時間がたつようにFOR H=1 TO Nを回しているのでしたら、これでは三回目以降のdtの値が小さすぎます。

> LET N=10*N
> LET dt=dt/N

> LET N=10*N
> LET dt=dt0/N

> LET N=10*N
> LET dt=dt/10
のように計算するべきではないでしょうか。

会社員さんのコードの意図を読み違えていたらすいません。

    └三回目以降のdtの値が小さすぎます。 会社員 2005/12/29 15:50:50  ツリーへ

Re: 計算量が減りません 返事を書く
会社員 2005/12/29 15:50:50
>三回目以降のdtの値が小さすぎます。
気づいてませんでした。
LET N=10*N
LET dt=dt0/N
が正解です。
ありがとうございました。


インデックスへ EXIT
新規発言を反映させるにはブラウザの更新ボタンを押してください。