利用matlab實現三體問題(雙星、3星、多星運動)

利用matlab實現3體問題(雙星、3星、多星運動)

這篇文章隨便水一下,寫一個簡單的3體問題,權當娛樂
在這裏插入圖片描述

1地月系統模擬

萬有引力的公式爲:
F=GMmR2 F=-G\frac{Mm}{R^2}
查詢地月系統的參數,可以得到:

參數 數值
引力常數 G 6.67e-11
地球質量 M 5.965e+24 Kg
近地點距離 r 363300000 m
遠地點距離 R 405493000 m
近地點月球速度 Vnear 1074.82 m/s
軌道離心率 0.0549

其中近地點月球的速度通過下面公式求得:
Vnear2=GM2R(R+r)r V_{near}^{2}=GM\frac{2R}{\left( R+r \right) r}
在已知初始條件和參數後,我們開始建立模型,對月球的運行軌道建立方程,可以得到在任意時刻月球的加速度a爲:
ax=GMx2+y2xx2+y2 a_x=-\frac{GM}{x^2+y^2}\frac{x}{\sqrt{x^2+y^2}}
ay=GMx2+y2yx2+y2 a_y=-\frac{GM}{x^2+y^2}\frac{y}{\sqrt{x^2+y^2}}
其中ax爲x軸方向上的加速度,ay爲y軸方向上的加速度。該方程屬於典型的常微分方程ODE,整理爲一階微分方程的形式:
[xyuv]=[uvaxay]=[uvGMx2+y2xx2+y2GMx2+y2yx2+y2] \left[ \begin{array}{c} x\\ y\\ u\\ v\\ \end{array} \right] ^{'}=\left[ \begin{array}{c} u\\ v\\ ax\\ ay\\ \end{array} \right] =\left[ \begin{array}{c} u\\ v\\ -\frac{GM}{x^2+y^2}\frac{x}{\sqrt{x^2+y^2}}\\ -\frac{GM}{x^2+y^2}\frac{y}{\sqrt{x^2+y^2}}\\ \end{array} \right]
其中上式的uv爲x方向上的速度和y方向上的速度。爲了提高精度,將方程帶入到4階RK求解器中,即可求解得到月球的軌跡。

matlab代碼如下:

clear
clc
close all
%初始化
x0=363300*10^3;%初始近地位置
y0=0;
u0=0;
v0=1074.82;%初始近地速度
%設置計算時間
h=0.5*60*60;%步長爲0.5個小時
t=0:h:27.5*24*60*60;%計算總時間維27.5天

y=ODE_RK4_hyh(t,h,[x0;y0;u0;v0]);

plot(y(1,:),y(2,:))%繪圖

a=(max(y(1,:))-min(y(1,:)))/2;%橢圓半長軸
b=(max(y(2,:))-min(y(2,:)))/2;%橢圓半短軸
e=sqrt(a^2-b^2)/a;%橢圓軌道離心率

function y=ODE_RK4_hyh(x,h,y0)
%4階RK方法
%h間隔爲常數的算法
y=zeros(size(y0,1),size(x,2));
y(:,1)=y0;
for ii=1:length(x)-1
    yn=y(:,ii);
    xn=x(ii);
    K1=Fdydx(xn,yn);
    K2=Fdydx(xn+h/2,yn+h/2*K1);
    K3=Fdydx(xn+h/2,yn+h/2*K2);
    K4=Fdydx(xn+h,yn+h*K3);
    y(:,ii+1)=yn+h/6*(K1+2*K2+2*K3+K4);
end
end

function dydx=Fdydx(x,y)
%將原方程整理爲dy/dx=F(y,x)的形式
G=6.67E-11;%引力常數
M=5.965E24;%地球質量
ax=-G*M*y(1)/(y(1).^2+y(2).^2)^1.5;
ay=-G*M*y(2)/(y(1).^2+y(2).^2)^1.5/1;
dydx=[y(3);y(4);ax;ay];
end

驗證得到的週期大概小於27.5天(這個我沒細算)。驗證得到的偏心率爲0.0549,和百度百科上完全一致,證明該方法完全可以用在定量計算上。下圖爲平平無奇的月球軌道,我沒有用axis equal調整x軸和y軸比例,所以看上去離心率有點大。
在這裏插入圖片描述
我之後爲了效果,也爲了計算省事,不再設置真實的G、M等參數。

2雙星問題模型

上一章由於地球質量遠遠大於月球質量,所以假設地球不動,只建立月球的模型。
但是當兩個星球質量比較接近時,就不能忽略兩個星球間的相互作用了。

所以對於雙星問題,原先的常微分方程需要更改爲:
[m1x1y1u1v1m2x2y2u2v2]=[0u1v1ax1ay10u2v2ax2ay2]=[0u1v1Gm2(x1x2)((x1x2)2+(x1x2)2)1.5Gm2(y1y2)((x1x2)2+(x1x2)2)1.50u2v2Gm1(x2x1)((x2x1)2+(x2x1)2)1.5Gm1(y2y1)((x2x1)2+(x2x1)2)1.5] \left[ \begin{array}{c} m_{1}\\ x_{1}\\ y_{1}\\ u_{1}\\ v_{1}\\ m_{2}\\ x_{2}\\ y_{2}\\ u_{2}\\ v_{2}\\ \end{array} \right] ^{'}=\left[ \begin{array}{c} 0\\ u_{1}\\ v_{1}\\ ax_{1}\\ ay_{1}\\ 0\\ u_{2}\\ v_{2}\\ ax_{2}\\ ay_{2}\\ \end{array} \right] =\left[ \begin{array}{c} 0\\ u_{1}\\ v_{1}\\ -\frac{Gm_{2}(x_{1}-x_{2})}{((x_{1}-x_{2})^2+(x_{1}-x_{2})^2)^{1.5}}\\ -\frac{Gm_{2}(y_{1}-y_{2})}{((x_{1}-x_{2})^2+(x_{1}-x_{2})^2)^{1.5}}\\ 0\\ u_{2}\\ v_{2}\\ -\frac{Gm_{1}(x_{2}-x_{1})}{((x_{2}-x_{1})^2+(x_{2}-x_{1})^2)^{1.5}}\\ -\frac{Gm_{1}(y_{2}-y_{1})}{((x_{2}-x_{1})^2+(x_{2}-x_{1})^2)^{1.5}}\\ \end{array} \right]
每一個行星有5個信息,分別爲質量、位置xy、速度uv。其中質量不發生改變,位置的導數爲速度,速度的導數爲加速度。

在matlab編程中,由於在計算引力過程中,兩個行星還可以窮舉,但是多個行星之後,就要考慮循環,第一層循環遍歷每一個行星,第二層循環計算每一個行星與其它行星之間的引力之和。這種雙循環在matlab中可能會導致計算速度太慢,所以我利用matlab裏的meshgrid方法,避免了使用循環,這也相當於向量加速。

代碼如下:

clear
clc
close all

%計算雙星系統,定性計算,沒有代入實際物理參數
mxyuv1=rand(5,1);%行星1,所有參數都隨機
mxyuv2=rand(5,1);%行星2,所有參數都隨機
h=1e-5;%步長
t=0:h:1;%時間

y=ODE_RK4_hyh(t,h,[mxyuv1;mxyuv2]);

plot(y(2,:),y(3,:),y(7,:),y(8,:))%繪軌跡圖

function y=ODE_RK4_hyh(x,h,y0)
%4階RK方法
%h間隔爲常數的算法
y=zeros(size(y0,1),size(x,2));
y(:,1)=y0;
for ii=1:length(x)-1
    yn=y(:,ii);
    xn=x(ii);
    K1=Fdydx(xn,yn);
    K2=Fdydx(xn+h/2,yn+h/2*K1);
    K3=Fdydx(xn+h/2,yn+h/2*K2);
    K4=Fdydx(xn+h,yn+h*K3);
    y(:,ii+1)=yn+h/6*(K1+2*K2+2*K3+K4);
end
end

function dydx=Fdydx(x,y)
%將原方程整理爲dy/dx=F(y,x)的形式
N=numel(y)/5;%N個球體
G=1;%引力系數,這裏只做展示,不做定量計算
%計算兩個星球之間的引力
m=y(1:5:end);
x0=y(2:5:end);
y0=y(3:5:end);
[x1,x2]=meshgrid(x0,x0);
[y1,y2]=meshgrid(y0,y0);
[m1,m2]=meshgrid(m,m);
dx=x1-x2;
dy=y1-y2;
ax=-G.*dx./(dx.^2+dy.^2).^(1.5).*m2;
ay=-G.*dy./(dx.^2+dy.^2).^(1.5).*m2;
for k=1:N
    ax(k,k)=0;
    ay(k,k)=0;
end

%建立dydx
dydx=zeros(size(y));
%1 質量不變
dydx(1:5:N*5-4)=0;
%2 x導數
dydx(2:5:N*5-3)=y(4:5:N*5-1);
%3 y導數
dydx(3:5:N*5-2)=y(5:5:N*5-0);
%4 x加速度
dydx(4:5:N*5-1)=sum(ax,1);
%3 y加速度
dydx(5:5:N*5-0)=sum(ay,1);
end

雙星的軌跡如下(參數時隨機的,所以不一樣很正常):
在這裏插入圖片描述
可以看到,兩個行星在相互吸引後在不到一個週期內又快速互相甩出,當然之後可能還會再次吸引再次重複這個週期,但是我這裏時間設置比較少。

3多星問題模擬

2維平面

代碼還是以上一章的代碼爲主,星球的增加參考上一章節的即可,然後對最終演示做了億點優化。

clear
clc
close all

%計算雙星系統,不停循環,只顯示一部分點
%初始條件
Mn=3;%更改星星數量

h=5e-5;%步長
Nn=5000;%線段長度
%t=0:h:1;

% y0=rand(Mn*5,1);%隨機

% y0=[100,0   ,0  ,0  ,0  ,...
%     1  ,1.1,0.05  ,2.1,9  ,...
%     1  ,1.1,-0.05  ,-2.1  ,9  ]';%3星,雙星加恆星

% y0=[100,0   ,0  ,0  ,0  ,...
%     0.1,0.2 ,0  ,0  ,22 ,...
%     0.5,0.35,0  ,0  ,17 ,...
%     1  ,0.6 ,0  ,0  ,13 ,...
%     0.4  ,0.9 ,0  ,0  ,10]';%5星,恆星加4個行星

y0=[11,0    ,0    ,4.5  ,4  ,...
    11,0.5 ,-0.132,-2  ,-1.8 ,...
    11,-0.5,0.132 ,-2  ,-1.8]';%3星,8字形運動,沒調試好


y1=zeros(size(y0,1),Nn);


T=1;t=T*h;
y1(:,T)=y0;

while true
    T=T+1;
    t=T*h;
    %計算下一步
    if T<=Nn
        y=ODE_RK4_hyh2(t,h,y1(:,T-1));
        y1(:,T)=y;
    else
        y2=y1;
        y=ODE_RK4_hyh2(t,h,y1(:,end));
        y1=[y2(:,2:end),y];
    end
    

    
    %繪圖
    if mod(T,100)==1
        ax=figure(1);
        ax.Color=[0 0 0.1];
        clf
        x_medium=0;y_medium=0;
        if T<=Nn
            %初始還沒有超過線條點數
            hold on
            for k=1:Mn
                %計算顏色
                color_hsv=colormap(hsv);
                color_N=length(color_hsv);
                F_color=color_hsv(round(color_N/Mn*k),:);
                F_color=F_color*0.6+[1,1,1]*0.4;
                cdata=[linspace(0,F_color(1),T+1)',linspace(0,F_color(2),T+1)',linspace(0.1,F_color(3),T+1)'];
                cdata=reshape(cdata,T+1,1,3);
                %繪製線條
                patch([y1(k*5-5+2,1:T),NaN],[y1(k*5-5+3,1:T),NaN],1:T+1,'EdgeColor','interp','Marker','none',...
                    'MarkerFaceColor','flat','CData',cdata,'LineWidth',1);
                x_medium=x_medium+y1(k*5-5+2,T);
                y_medium=y_medium+y1(k*5-5+3,T);
            end
            hold off
            x_medium=x_medium/Mn;
            y_medium=y_medium/Mn;
        else
            %超過線條點數後
            hold on
            for k=1:Mn
                %計算顏色
                color_hsv=colormap(hsv);
                color_N=length(color_hsv);
                F_color=color_hsv(round(color_N/Mn*k),:);
                F_color=F_color*0.6+[1,1,1]*0.4;
                cdata=[linspace(0,F_color(1),Nn+1)',linspace(0,F_color(2),Nn+1)',linspace(0.1,F_color(3),Nn+1)'];
                cdata=reshape(cdata,Nn+1,1,3);
                %繪製線條
                patch([y1(k*5-5+2,:),NaN],[y1(k*5-5+3,:),NaN],1:Nn+1,'EdgeColor','interp','Marker','none',...
                    'MarkerFaceColor','flat','CData',cdata,'LineWidth',1);
                x_medium=x_medium+y1(k*5-5+2,end);
                y_medium=y_medium+y1(k*5-5+3,end);
            end
            hold off
            x_medium=x_medium/Mn;
            y_medium=y_medium/Mn;
        end
        xlim([x_medium-1,x_medium+1]);
        ylim([y_medium-1,y_medium+1]);
        
        
        %W_deta=Gravity_Energy(y)/W
        axis off
        pause(0.1)
        
    end
end



function y1=ODE_RK4_hyh2(x0,h,y0)
%4階RK方法
%只向後計算1步h
%y1=zeros(size(y0,1),1);
K1=Fdydx(x0,y0);
K2=Fdydx(x0+h/2,y0+h/2*K1);
K3=Fdydx(x0+h/2,y0+h/2*K2);
K4=Fdydx(x0+h,y0+h*K3);
y1=y0+h/6*(K1+2*K2+2*K3+K4);
end

function dydx=Fdydx(x,y)
%將原方程整理爲dy/dx=F(y,x)的形式
N=numel(y)/5;%N個球體
G=1;%引力系數,這裏只做展示,不做定量計算
%計算兩個星球之間的引力
m=y(1:5:end);
x0=y(2:5:end);
y0=y(3:5:end);
[x1,x2]=meshgrid(x0,x0);
[y1,y2]=meshgrid(y0,y0);
[m1,m2]=meshgrid(m,m);
dx=x1-x2;
dy=y1-y2;
ax=-G.*dx./(dx.^2+dy.^2).^(1.5).*m2;
ay=-G.*dy./(dx.^2+dy.^2).^(1.5).*m2;
for k=1:N
    ax(k,k)=0;
    ay(k,k)=0;
end

%建立dydx
dydx=zeros(size(y));
%1 質量不變
dydx(1:5:N*5-4)=0;
%2 x導數
dydx(2:5:N*5-3)=y(4:5:N*5-1);
%3 y導數
dydx(3:5:N*5-2)=y(5:5:N*5-0);
%4 x加速度
dydx(4:5:N*5-1)=sum(ax,1);
%3 y加速度
dydx(5:5:N*5-0)=sum(ay,1);

end

在文章最開頭,我已經演示了8字形雙星的運動(感覺軌道有誤差,結果越修正越歪)。下面演示一個5星運動(恆星加行星)

在這裏插入圖片描述

代碼本身還是有很多bug的,比如
1遇到兩個行星特別近的時候,就會出現差分步長太大導致的數值誤差,表現爲兩個行星突然朝相反的方向快速飛出。如果設計爲變步長的差分算法,或者設定一個碰撞機制,可以避免這個問題。
2視角問題,遇到多個行星的移動、拉近、遠離等視角自動跟蹤的方法還不是太滿意,有時候表現爲晃來晃去的。如果能夠做到交互式視角的話,可以避免這個問題,但是交互界面需要GUI或者appdesigner,比較複雜。

3維空間

在方程上,增加了z方向的位置,以及對應的速度w。每一個行星的信息爲7個。計算量上有所增加,但是具體算法沒有什麼變化。但是3維的視角問題更爲嚴重,所以我暫時還沒想好怎麼演示,如果之後寫關於交互的話,可能會把這一塊補上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章