我正在尝试编写一个使用ode45
的脚本,以便将卫星的运动方程式(strong)整合到火星附近的双曲线轨迹上。
我需要整合整个行星的整个通道:从SOI半径(576000km
开始,朝着行星前进,然后穿过大气层,直到卫星到达“ opposite
”大气层边界(从表面250km
开始设置)。
当它收到的输入tspan
高于200000
秒(我需要大约400000
秒)时,Matlab会显示以下消息:
'无法执行分配,因为左侧的尺寸为 4乘2,右侧尺寸为4乘5。它说
error happens in line 488 of Ode45
。
我搜索了一些类似的案例,但找不到任何东西,而且我不知道如何使用条件断点来找出诸如ode45之类的复杂函数中的某些内容。我还尝试了使用“ odeset
”的其他选项,但没有任何变化。我不知道错误可能在哪里。
这是脚本,在其中我使用两个附加函数来获取一些参数:
Vinf=[2.7 4 6 8];
mu_m=42828;
R_msoi=.576e6;
[afas,efas,pfas]=parasint(Vinf);
an_vera0=zeros(1,length(Vinf));
Vr0=zeros(1,length(Vinf));
Vt0=zeros(1,length(Vinf));
for j=1:length(Vinf)
c_tstar0=(1/efas(j))*((pfas(j)/R_msoi)-1);
an_vera0(j)=-acos(c_tstar0);
s_tstar0=sin(an_vera0(j));
Vr0(j)=sqrt(mu_m/pfas(j))*efas(j)*s_tstar0;
Vt0(j)=sqrt(mu_m/pfas(j))*(1+efas(j)*c_tstar0);
end
ti=time(an_vera0,efas,afas,mu_m);
for n=1:length(ti)
I=(0:3600:ti(n));
options=odeset('Vectorized','on','RelTol',1e-8,'AbsTol',1e-9);
[t,Y]=ode45(@(t,y) eqMotoCur(t,y),I,y0,options);
end
这是“ parasint
”功能:
function [afas,efas,pfas]=parasint(Vinf)
mu_m=42828;
R_m=3396.2;
Rp0=R_m+400;
Rpf=R_m+50;
a0=zeros(1,length(Vinf));
e0=zeros(1,length(Vinf));
p0=zeros(1,length(Vinf));
afas=zeros(1,length(Vinf));
efas=zeros(1,length(Vinf));
pfas=zeros(1,length(Vinf));
for j=1:length(Vinf)
a0(j)=(-mu_m)/(Vinf(j)^2);
e0(j)=1-Rp0/a0(j);
p0(j)=a0(j)*(1-e0(j)^2);
c(1)=p0(j);
c(2)=Rpf*(1-e0(j)^2);
c(3)=Rpf*(1-e0(j)^2)-p0(j);
Efas=roots(c);
ind=(Efas>1 & isreal(Efas));
efas(j)=Efas(ind);
afas(j)=Rpf/(1-efas(j));
pfas(j)=afas(j)*(1-efas(j)^2);
end
这是“ time
”功能:
function [ti] = time(an_vera0,efas,afas,mu_m)
ti=zeros(1,length(an_vera0));
for j=1:length(an_vera0)
F=2*atanh(sqrt((efas(j)-1)/(efas(j)+1))*tan(an_vera0(j)/2));
T=sqrt((-afas(j))^3/mu_m)*(efas(j)*sinh(F) - F);
ti(j)=-2*T;
end
这是ode45的输入功能:
function [dydt] = eqMotoCur(t,y)
R_m=3396.2;
mu_m=42828;
Cd=2.2;
S=7.065e-6;
m=3699.046;
wE=0.24117/R_m;
if abs(y(1))>R_m+250 && y(3)>0
dydt(1:4)=0;
else
dydt=zeros(4,1);
dydt(1)=y(3);
dydt(2)=y(4)/y(1);
dydt(3)=(-mu_m/(y(1)^2))+((y(4)^2)/y(1))-(.5*Cd)*(S/m)*...
(dens(y(1)-R_m))*(sqrt((y(3)^2)+(y(4)-(wE*y(1)))^2))*y(3);
dydt(4)=-(y(4)*(y(3)/y(1)))-(.5*Cd)*(S/m)*...
(dens(y(1)-R_m))*(sqrt((y(3)^2)+(y(4)-(wE*y(1)))^2))*...
(y(4)-(wE*y(1)));
end
end
这是用于通过大气插值数据的“ dens
”功能:
function [rho] = dens(z)
load Density.mat h d
d=d*10^9;
if any(h)==abs(z)
j=h==abs(z);
rho=d(j);
elseif abs(z)<250
c_tot=(find(h>=abs(z)));
c=c_tot(1);
H=-(h(c)-h(c-1))/(log(d(c)/d(c-1)));
rho=d(c-1)*exp(-(abs(z)-h(c-1))/H);
else
rho=0;
end
end
这是Matlab给我的错误:
无法执行分配,因为左侧的尺寸为 4 x 2,右侧尺寸是4 x 5。
ode45 (line 488)
中的错误yout(:,idx) = yout_new
;
MainCur (line 59)
中的错误[t,Y]=ode45(@(t,y) eqMotoCur(t,y),I,y0,options)
;
谢谢。
答案 0 :(得分:1)
ode45(@(t,y) eqMotoCur(t,y),I,y0,options)
返回一个5 by 4
矩阵[t,Y]
是2 by 4
矩阵5 by 4 # 2 by 4
[t,Y]
替换为[t,Y, ~,~, ~]
~
[t,Y, ~,~, ~]=ode45(@(t,y) eqMotoCur(t,y),I,y0,options);
确保先定义y0
,然后再运行ode45
函数dens(z)
应该在eqMotoCur(t,y)
内定义,因为您需要它在eqMotoCur(t,y)
内执行一些计算
function [dydt] = eqMotoCur(t,y)
%% define dens here
function [rho] = dens(z)
load Density.mat h d
d=d*10^9;
if any(h)==abs(z)
j=h==abs(z);
rho=d(j);
elseif abs(z)<250
c_tot=(find(h>=abs(z)));
c=c_tot(1);
H=-(h(c)-h(c-1))/(log(d(c)/d(c-1)));
rho=d(c-1)*exp(-(abs(z)-h(c-1))/H);
else
rho=0;
end
end
%% Now start eqMotoCur
R_m=3396.2;
mu_m=42828;
Cd=2.2;
S=7.065e-6;
m=3699.046;
wE=0.24117/R_m;
if (abs(y(1))>R_m+250 && y(3)>0) ||y(1)==0
dydt(1:4)=0;
else
dydt=zeros(4,1);
dydt(1)=y(3);
dydt(2)=y(4)/y(1);
dydt(3)=(-mu_m/(y(1)^2))+((y(4)^2)/y(1))-(.5*Cd)*(S/m)*...
(dens(y(1)-R_m))*(sqrt((y(3)^2)+(y(4)-(wE*y(1)))^2))*y(3);
dydt(4)=-(y(4)*(y(3)/y(1)))-(.5*Cd)*(S/m)*...
(dens(y(1)-R_m))*(sqrt((y(3)^2)+(y(4)-(wE*y(1)))^2))*...
(y(4)-(wE*y(1)));
end
end
主要问题是时间
t
,如果以 秒,这就是ode45卡住的地方。
或者将秒转换为小时(以3600为单位),它将起作用。也是结果 获得的是struct数据类型,其中x表示t,y表示y。让我们 说t = sol{1}.x
和y = sol{1}.y
因为数组将是 更改每次迭代时,我都使用cell
将其分开保存
Vinf=[2.7 4 6 8];
mu_m=42828;
R_msoi=.576e6;
[afas,efas,pfas]=parasint(Vinf);
an_vera0=zeros(1,length(Vinf));
Vr0=zeros(1,length(Vinf));
Vt0=zeros(1,length(Vinf));
for j=1:length(Vinf)
c_tstar0=(1/efas(j))*((pfas(j)/R_msoi)-1);
an_vera0(j)=-acos(c_tstar0);
s_tstar0=sin(an_vera0(j));
Vr0(j)=sqrt(mu_m/pfas(j))*efas(j)*s_tstar0;
Vt0(j)=sqrt(mu_m/pfas(j))*(1+efas(j)*c_tstar0);
end
ti=time(an_vera0,efas,afas,mu_m);
ti = ti/3600;
sol = cell(1,4);
for n=1:length(ti)
y0=[.576e6; an_vera0(n); Vr0(n) ;Vt0(n)];
I=0:1:ti(n);
options=odeset('Vectorized','on','RelTol',1e-8,'AbsTol',1e-9);
sol{n} = ode45(@eqMotoCur,I, y0,options);
end
答案 1 :(得分:0)
我发现问题是,正如您所说,是我在EqMotoCur
函数中手动编写的停止条件,但是考虑到我的目的,我无法按照您的建议进行纠正:计算会在半径变为零的那一刻已经停止。
因此,我删除了该条件,并编写了一个事件函数用作停止条件。我的修改没有解决“可能的零除”问题,因此我在dydt
中切换了y
和EqMotoCur
的前两个元素。这样,“计算半径”(y(2)
或sol{1}.y
中的第二行)将永远不会变为零,也不会低于火星半径,并且将使用{{ 1}}(以秒为单位)。
如果有人感兴趣,这是我使用的事件函数(由于我没有时间去适应它,所以它不适合tspan
表单):
cell
如果没有您的帮助和时间,我永远做不到,非常感谢!