[英]Solar System Mapping, ODE45 trouble
以下代碼旨在通過將每個重要的身體的影響結合到其他人身上來繪制太陽系。 當然它應該導致預期的軌道。 在最終的嵌入式函數GravityDE
它無法讀取PlanetVec
的值,因此,每次都無法生成正確的新結果。 我們得到了錯誤
??? Undefined function 'GravityDE' for input arguments of type double.
任何有關如何解決這個問題的建議都是最受歡迎的!
function Gravity1()
clear;
format long eng;
load('solar_system_data.mat');
StartTime = 0;
TimeStep = 24 * 3600 * 10;
EndTime = 24 * 3600 * 100;
TVec = StartTime:TimeStep:EndTime;
TimeStepMin = StartTime:2:TimeStep;
%Column Vectors for initial conditions
SunVec = [xposition(1), yposition(1), vx(1), vy(1),mass(1),1];
MercuryVec = [xposition(2), yposition(2), vx(2), vy(2),mass(2),2];
VenusVec = [xposition(3), yposition(3), vx(3), vy(3),mass(3),3];
EarthVec = [xposition(4), yposition(4),vx(4), vy(4),mass(4),4];
MoonVec = [xposition(10), yposition(10), vx(10), vy(10),mass(10),10];
MarsVec = [xposition(5), yposition(5), vx(5), vy(5),mass(5),5];
JupiterVec = [xposition(6), yposition(6), vx(6), vy(6),mass(6),6];
SaturnVec = [xposition(7), yposition(7), vx(7), vy(7),mass(7),7];
UranusVec = [xposition(8), yposition(8), vx(8), vy(8),mass(8),8];
NeptuneVec = [xposition(9), yposition(9), vx(9), vy(9),mass(9),9];
PlanetVec=[SunVec(1),SunVec(2),SunVec(3),SunVec(4),SunVec(5),SunVec(6);MercuryVec(1), MercuryVec(2), MercuryVec(3), MercuryVec(4),MercuryVec(5),MercuryVec(6);VenusVec(1), VenusVec(2), VenusVec(3), VenusVec(4),VenusVec(5),VenusVec(6);EarthVec(1), EarthVec(2), EarthVec(3), EarthVec(4),EarthVec(5),EarthVec(6);MoonVec(1),MoonVec(2),MoonVec(3),MoonVec(4),MoonVec(5),MoonVec(6);MarsVec(1), MarsVec(2), MarsVec(3), MarsVec(4),MarsVec(5),MarsVec(6);JupiterVec(1), JupiterVec(2), JupiterVec(3), JupiterVec(4),JupiterVec(5),JupiterVec(6);SaturnVec(1), SaturnVec(2), SaturnVec(3), SaturnVec(4),SaturnVec(5),SaturnVec(6);UranusVec(1), UranusVec(2),UranusVec(3), UranusVec(4),UranusVec(5),UranusVec(6);NeptuneVec(1), NeptuneVec(2), NeptuneVec(3), NeptuneVec(4),NeptuneVec(5),NeptuneVec(6)];
n=0;
while n<EndTime;
%Built in solver
[TimeVec, SunMat] = ode45(@GravityDE, TimeStepMin, SunVec);
[TimeVec, MercuryMat] = ode45(@GravityDE, TimeStepMin, MercuryVec);
[TimeVec, VenusMat] = ode45(@GravityDE, TimeStepMin, VenusVec);
[TimeVec, EarthMat] = ode45(@GravityDE, TimeStepMin, EarthVec);
[TimeVec, MoonMat] = ode45(@GravityDE, TimeStepMin, MoonVec);
[TimeVec, MarsMat] = ode45(@GravityDE, TimeStepMin, MarsVec);
[TimeVec, JupiterMat] = ode45(@GravityDE, TimeStepMin, JupiterVec);
[TimeVec, SaturnMat] = ode45(@GravityDE, TimeStepMin, SaturnVec);
[TimeVec, UranusMat] = ode45(@GravityDE, TimeStepMin, UranusVec);
[TimeVec, NeptuneMat] = ode45(@GravityDE, TimeStepMin, NeptuneVec);
SunXVec = SunMat (end,1);
SunYVec = SunMat (end,2);
SunVXVec = SunMat(end,3);
SunVYVec = SunMat(end,4);
MercuryXVec = MercuryMat (end,1);
MercuryYVec = MercuryMat (end,2);
MercuryVXVec = MercuryMat(end,3);
MercuryVYVec = MercuryMat(end,4);
VenusXVec = VenusMat (end,1);
VenusYVec = VenusMat (end,2);
VenusVXVec = VenusMat(end,3);
VenusVYVec = VenusMat(end,4);
EarthXVec = EarthMat (end,1);
EarthYVec = EarthMat (end,2);
EarthVXVec = EarthMat(end,3);
EarthVYVec = EarthMat(end,4);
MoonXVec = MoonMat (end,1);
MoonYVec = MoonMat (end,2);
MoonVXVec = MoonMat(end,3);
MoonVYVec =MoonMat(end,4);
MarsXVec = MarsMat (end,1);
MarsYVec = MarsMat (end,2);
MarsVXVec = MarsMat(end,3);
MarsVYVec = MarsMat(end,4);
JupiterXVec = JupiterMat (end,1);
JupiterYVec = JupiterMat (end,2);
JupiterVXVec = JupiterMat(end,3);
JupiterVYVec =JupiterMat(end,4);
SaturnXVec = SaturnMat (end,1);
SaturnYVec = SaturnMat (end,2);
SaturnVXVec = SaturnMat(end,3);
SaturnVYVec =SaturnMat(end,4);
UranusXVec = UranusMat (end,1);
UranusYVec = UranusMat (end,2);
UranusVXVec = UranusMat(end,3);
UranusVYVec =UranusMat(end,4);
NeptuneXVec = NeptuneMat (end,1);
NeptuneYVec = NeptuneMat (end,2);
NeptuneVXVec = NeptuneMat(end,3);
NeptuneVYVec =NeptuneMat(end,4);
SunVec=[SunXVec,SunYVec,SunVXVec,SunVYVec,mass(1),1];
MercuryVec = [MercuryXVec, MercuryYVec, MercuryVXVec, MercuryVYVec,mass(2),2];
VenusVec = [VenusXVec, VenusYVec, VenusVXVec, VenusVYVec,mass(3),3];
EarthVec = [EarthXVec, EarthYVec, EarthVXVec, EarthVYVec,mass(4),4];
MoonVec = [MoonXVec,MoonYVec,MoonVXVec,MoonVYVec,mass(10),10];
MarsVec = [MarsXVec, MarsYVec, MarsVXVec, MarsVYVec,mass(5),5];
JupiterVec = [JupiterXVec, JupiterYVec, JupiterVXVec, JupiterVYVec,mass(6),6];
SaturnVec = [SaturnXVec, SaturnYVec, SaturnVXVec, SaturnVYVec,mass(7),7];
UranusVec = [UranusXVec, UranusYVec,UranusVXVec, UranusVYVec,mass(8),8];
NeptuneVec = [NeptuneXVec, NeptuneYVec, NeptuneVXVec, NeptuneVYVec,mass(9),9];
PlanetVec=[SunVec(1),SunVec(2),SunVec(3),SunVec(4),SunVec(5),SunVec(6);MercuryVec(1), MercuryVec(2), MercuryVec(3), MercuryVec(4),MercuryVec(5),MercuryVec(6);VenusVec(1), VenusVec(2), VenusVec(3), VenusVec(4),VenusVec(5),VenusVec(6);EarthVec(1), EarthVec(2), EarthVec(3), EarthVec(4),EarthVec(5),EarthVec(6);MoonVec(1),MoonVec(2),MoonVec(3),MoonVec(4),MoonVec(5),MoonVec(6);MarsVec(1), MarsVec(2), MarsVec(3), MarsVec(4),MarsVec(5),MarsVec(6);JupiterVec(1), JupiterVec(2), JupiterVec(3), JupiterVec(4),JupiterVec(5),JupiterVec(6);SaturnVec(1), SaturnVec(2), SaturnVec(3), SaturnVec(4),SaturnVec(5),SaturnVec(6);UranusVec(1), UranusVec(2),UranusVec(3), UranusVec(4),UranusVec(15),UranusVec(6);NeptuneVec(1), NeptuneVec(2), NeptuneVec(3), NeptuneVec(4),NeptuneVec(5),NeptuneVec(6)];
plot (SunXVec,SunYVec,'.','Color','yellow');
hold on;
plot (MercuryXVec,MercuryYVec,'.','Color','green');
hold on;
plot (VenusXVec,VenusYVec,'.','Color','blue');
hold on;
plot (EarthXVec,EarthYVec, '.','Color', 'red');
hold on;
plot (MoonXVec,MoonYVec, '.','Color','black');
hold on;
plot (MarsXVec,MarsYVec, '.','Color','black');
hold on;
plot (JupiterXVec,JupiterYVec,'.','Color','green');
hold on;
plot (SaturnXVec,SaturnYVec, '.','Color','blue');
hold on;
plot (UranusXVec,UranusYVec, '.','Color','red');
hold on;
plot (NeptuneXVec,NeptuneYVec, '.','Color','blue');
hold on;
n=n+TimeStep;
end
function dYVec = GravityDE (TimeStep, YVec,PlanetVec)
load('solar_system_data.mat');
GravConst = 6.67259e-11;
Xi = YVec(1);
Yi = YVec(2);
VXi = YVec(3);
VYi = YVec(4);
Massi=YVec(5);
BodyName=YVec(6);
AccXtotal=0;
AccYtotal=0;
j=1;
while j<=10
Massj=PlanetVec(j,5);
Yj=PlanetVec(j,2);
Xj=PlanetVec(j,1);
RangeSq = (Xi-Xj).^2 + (Yi-Yj).^2;
if RangeSq==0
AccMag=0;
Theta = atan2(Yi-Yj,Xi-Xj);
AccX = -AccMag .* cos (Theta);
AccY = -AccMag .* sin (Theta);
j=j+1;
AccXtotal=AccXtotal+AccX;
AccYtotal=AccYtotal+AccY;
else
Theta = atan2(Yi-Yj,Xi-Xj);
AccMag = (GravConst .* Massj ./ RangeSq);
AccX = -AccMag .* cos (Theta);
AccY = -AccMag .* sin (Theta);
j=j+1;
AccXtotal=AccXtotal+AccX;
AccYtotal=AccYtotal+AccY;
VXi=VXi+AccXtotal.*TimeStep;
VYi=VYi+AccYtotal.*TimeStep;
end
dYVec = [VXi; VYi; AccXtotal; AccYtotal;Massi;BodyName];
end
謝謝!!
好的,我們走了。 這將是一個很長的答案,它可能會過於完整,但我認為它對未來的訪問者也很有價值。
由於另一個質量為m的天體,質量為M的天體上的力等於
F = -GMm /r²
其中r是兩個物體之間的距離。 這就是我們在高中學習牛頓方程式的方法(我希望,無論如何......)。 由於我在上面的評論中指出的原因,上面的基本等式存在一些缺陷。 而且,在超過兩個天體的背景下,它是不完整的。
首先, GM被實際可以測量的東西取代, μ--身體的標准引力參數 。 其次,在任意坐標系中都需要很容易進行計算。 第三,力的方向不包括在上面的等式中。 第四,天體的加速通常是重要的,而不是力。
所有這些都可以通過將等式重新表述為包括在內
R I =ΣĴ≠我 μĴ 率 R ij / | r ij |³
其中粗體字母表示向量, r是某個任意坐標系的位置向量, r ij = r i - r j是從身體i到身體j的向量,雙點是牛頓的雙流量(等於Leibniz' D²/dt²)。
在詞:身體的i由於所有其他機構j的引力效應瞬時方向上的加速度,是重力參數的總和μĴ,由身體狀況之間的平方距離除以i和j,並且通過這兩者之間的矢量乘以在系統中所有其他身體j上的身體縮小為統一(你知道為什么我們發明了數學符號嗎?:)
該等式描述了j個二階微分方程的系統,其不能通過分析求解(無論如何以易於計算的閉合形式)並且因此必須在數值上求解。 Matlab的ode45
可以做到這一點,雖然如果你想模擬幾十年或更長時間的行星軌道(特別是汞的軌道很難用數字精確計算),它的准確性還有待提高。
無論如何,你用ode45
解決這個ode45
如下。 限定
ÿ0 = [R 1 R 1 R 2 R 2 ...řĴ - [R j]的 Ť
這是所有j體的初始狀態向量的集合。 在代碼中(與輸入大小無關):
y0 = [xposition(:) yposition(:) vx(:) vy(:)].';
y0 = y0(:);
請注意,您不需要把所有的狀態矢量個人的名字。 我也強烈反對; 你會如何整合小行星帶? 你真的會給所有單個狀態向量提供~500.000個變量名嗎? 不 - 使用Matlab的矢量/矩陣特性對您有利。
你可以通過不單獨定義xposition
和yposition
(和速度)來防止上面的混亂,但是在一個向量中一起定義。
ode45
集成商通過計算工作
Y = [R 1 R 1 R 2 R 2 ...řĴ - [R j]的 Ť
從每次迭代的輸入y開始。 正是在這里,上面修改過的牛頓方程起作用了; 計算雙fluxions [R 學家 在代碼中:
% collect data
r = [y(1:4:end) y(2:4:end)]; % X/Y positions
V = [y(3:4:end) y(4:4:end)]; % Vx/Vy speeds
% initialize output
ydotdot = zeros(size(y));
ydotdot(1:4:end) = V(:,1); % we already know the first half;
ydotdot(2:4:end) = V(:,2); % it's simply equal to the speeds
% Compute all accelerations.
% This is where ALL the computational burden is -- when optimizing
% for speed, this is where to start!
sz = size(r,1);
accx = zeros(sz);
accy = zeros(sz);
for ii = 1:sz
ri = r(ii,:);
for jj = ii+1:sz
rij = ri - r(jj,:);
sc = (rij*rij.')^(-3/2);
accx(jj,ii) = rij(1) * sc;
accy(jj,ii) = rij(2) * sc;
end
end
accx = bsxfun(@times, -mu(:), accx-accx.');
accy = bsxfun(@times, -mu(:), accy-accy.');
% insert accelerations
ydotdot(3:4:end) = sum(accx);
ydotdot(4:4:end) = sum(accy);
你這樣做的方法是計算行星位置的雙重流動,而其他行星處於初始位置; 你想把PlanetVec
,初始狀態向量(我稱之為y 0 )的集合傳遞給GravityDE
,並計算該向量的行星距離和加速度。
這當然是不正確的 - 這只會移動一個行星,同時保持其他行星不動。 這不是太陽系的工作原理:p現在你可能會認為它並不重要,因為行星移動的速度很慢,但這只適用於外行星; 例如,水星對金星軌道的影響嚴重錯誤估計。
現在你知道了一般原則。 免責聲明 :我在沒有太多檢查的情況下從內存中寫下這些內容,所以我可能會在這里和那里錯過一個減號。 我認為這是一個很好的練習,讓你理解並檢查我在這里所做的一切。
現在,一個完整的,功能性的,可復制的摘要:
function Gravity1
% NOTE: 'clear' has no meaning at the start of a function; a function
% has its own variable space, meaning it is empty to begin with.
% NOTE: this assumes you put have all the planetary mu's inside this datafile
load('solar_system_data.mat');
% NOTE: ode45 chooses its own time steps; its an adaptive method.
% Passing it custom time steps is hopelessly inefficient.
t0 = 0;
tend = 24 * 3600 * 100;
% re-format initial vectors
y0 = [xposition(:) yposition(:) vx(:) vy(:)].';
y0 = y0(:);
% perform integration
[t y] = ode45(@d2ydt2, [t0 tend], y0);
% and do plot
h = figure; hold on % NOTE: only a single 'hold on' is needed to turn it on :)
plot(y(:,1),y(:,2), 'y.'); % Sun
plot(y(:,1),y(:,2), 'g.'); % Mercury
plot(y(:,1),y(:,2), 'b.'); % Venus
plot(y(:,1),y(:,2), 'r.'); % Earth
plot(y(:,1),y(:,2), 'k.'); % Mars
plot(y(:,1),y(:,2), 'g.'); % Jupiter
plot(y(:,1),y(:,2), 'b.'); % Saturn
plot(y(:,1),y(:,2), 'r.'); % Uranus
plot(y(:,1),y(:,2), 'b.'); % Neptune
% It's easiest to put the differential equation in a nested function
function ydotdot = d2ydt2(~,y)
% rename data
r = [y(1:4:end) y(2:4:end)]; % X/Y positions
V = [y(3:4:end) y(4:4:end)]; % Vx/Vy speeds
% initialize output
ydotdot = zeros(size(y));
ydotdot(1:4:end) = V(:,1); % we already know the first half;
ydotdot(2:4:end) = V(:,2); % it's simply equal to the speeds
% Compute all accelerations.
% This is where ALL the computational burden is -- when optimizing
% for speed, this is where to start!
sz = size(r,1);
accx = zeros(sz);
accy = zeros(sz);
for ii = 1:sz
ri = r(ii,:);
for jj = ii+1:sz
rij = ri - r(jj,:);
sc = (rij*rij.')^(-3/2);
accx(jj,ii) = rij(1) * sc;
accy(jj,ii) = rij(2) * sc;
end
end
accx = bsxfun(@times, -mu(:), accx-accx.');
accy = bsxfun(@times, -mu(:), accy-accy.');
% insert accelerations
ydotdot(3:4:end) = sum(accx);
ydotdot(4:4:end) = sum(accy);
end
end
請注意,我甚至沒有看到為什么你的原始功能無法運行。 我敢打賭,一旦你開始運行,它就不再重要了。
沒有solar_system_data.mat
,很難調試你的代碼,但問題是你沒有將PlanetVec
傳遞給你的函數
如果我的記憶很好,你應該試試
[TimeVec, SunMat] = ode45(@(t,y)GravityDE(t,y,PlanetVec), TimeStepMin, SunVec);
請閱讀有關參數化功能的信息
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.