Suggestion to solve 'NaN' in matlab. Dealing with large and small numbers in Matlab - matlab

I am trying to make a model of planets' movement plot it in 3d using Matlab.
I used Newton's law with the gravitational force between two objects and I got the differential equation below:
matlab code:
function dy=F(t,y,CurrentPos,j)
m=[1.98854E+30 3.302E+23 4.8685E+24 5.97219E+24 6.4185E+23 1.89813E+27 5.68319E+26 8.68103E+25 1.0241E+26 1.307E+22];
G=6.67E-11;
dy = zeros(6,1);
dy(1) = y(4);
dy(2) = y(5);
dy(3) = y(6);
for i=1:10
if i~=j
deltaX=(CurrentPos(j,1)-CurrentPos(i,1));
deltaY=(CurrentPos(j,2)-CurrentPos(i,2));
deltaZ=(CurrentPos(j,3)-CurrentPos(i,3));
ray=sqrt((deltaX^2)+(deltaY^2)+(deltaZ^2));
dy(4) = dy(4) + G*m(i)*(deltaX/(ray^3));
dy(5) = dy(5) + G*m(i)*(deltaY/(ray^3));
dy(6) = dy(6) + G*m(i)*(deltaZ/(ray^3));
end
end
where the 'm' array is the planet masses.
then I used the numerical method Runge-Kutta-4 to solve it, and here's the code:
function [y,t]=RK4(F,intPos,a,b,N)
h=(b-a)/N;
t=zeros(N,1);
y = zeros(10*N,6);
y(1,:)=intPos(1,:);
y(2,:)=intPos(2,:);
y(3,:)=intPos(3,:);
y(4,:)=intPos(4,:);
y(5,:)=intPos(5,:);
y(6,:)=intPos(6,:);
y(7,:)=intPos(7,:);
y(8,:)=intPos(8,:);
y(9,:)=intPos(9,:);
y(10,:)=intPos(10,:);
t(1)=a;
for i=1:N
t(i+1)=a+i*h;
CurrentPos=y((i*10)-9:i*10,:);
% CurrentPos(1,:)=intPos(1,:);
y((i*10)+1,:)=intPos(1,:);
for j=2:10
k1=F(t(i),y(((i-1)*10)+j,:),CurrentPos,j);
k2=F(t(i)+h/2,y(((i-1)*10)+j,:)+(h/2).*k1',CurrentPos,j);
k3=F(t(i)+h/2,y(((i-1)*10)+j,:)+(h/2).*k2',CurrentPos,j);
k4=F(t(i)+h,y(((i-1)*10)+j,:)+h.*k3',CurrentPos,j);
y((i*10)+j,:)=y(((i-1)*10)+j,:)+(h/6)*(k1+2*k2+2*k3+k4)';
end
end
Finally applied the function for the Initial States from JPL HORIZONS System:
format short
intPos=zeros(10,6);
intPos(1,:)=[1.81899E+08 9.83630E+08 -1.58778E+07 -1.12474E+01 7.54876E+00 2.68723E-01];
intPos(2,:)=[-5.67576E+10 -2.73592E+10 2.89173E+09 1.16497E+04 -4.14793E+04 -4.45952E+03];
intPos(3,:)=[4.28480E+10 1.00073E+11 -1.11872E+09 -3.22930E+04 1.36960E+04 2.05091E+03];
intPos(4,:)=[-1.43778E+11 -4.00067E+10 -1.38875E+07 7.65151E+03 -2.87514E+04 2.08354E+00];
intPos(5,:)=[-1.14746E+11 -1.96294E+11 -1.32908E+09 2.18369E+04 -1.01132E+04 -7.47957E+02];
intPos(6,:)=[-5.66899E+11 -5.77495E+11 1.50755E+10 9.16793E+03 -8.53244E+03 -1.69767E+02];
intPos(7,:)=[8.20513E+10 -1.50241E+12 2.28565E+10 9.11312E+03 4.96372E+02 -3.71643E+02];
intPos(8,:)=[2.62506E+12 1.40273E+12 -2.87982E+10 -3.25937E+03 5.68878E+03 6.32569E+01];
intPos(9,:)=[4.30300E+12 -1.24223E+12 -7.35857E+10 1.47132E+03 5.25363E+03 -1.42701E+02];
intPos(10,:)=[1.65554E+12 -4.73503E+12 2.77962E+10 5.24541E+03 6.38510E+02 -1.60709E+03];
[yy,t]=RK4(#F,intPos,0,1e8,1e3);
x=zeros(101,1);
y=zeros(101,1);
z=zeros(101,1);
for i=1:1e3
x(i,:)=yy((i-1)*10+4,1);
y(i,:)=yy((i-1)*10+4,2);
z(i,:)=yy((i-1)*10+4,3);
end
plot3(x,y,z)
Finally, the result wasn't satisfying at all and I got many 'NAN', then I did some adjustment on the RK4 method and started to get numbers, but when I plotted them it turned out I'm plotting a line instead of an orbit.
Any help would be appreciated.
Thanks in advance.

Two errors: One physical: The alpha in the formula is the j in the code, the running index j in the formulas is the loop index i in the formula. In total this makes a sign error, transforming the attracting gravity force into a repelling force like between electrons. Thus the physics dictates that the bodies move away from each other almost linearly, as long as their paths don't cross.
Second, you are applying the RK4 method in such a way that in total it is an order 1 method. These also tend to behave un-physically rather quickly. You need to update first all positions to the first stage in a temporary StagePos variable, then use that to compute all position updates for the second stage etc. The difference to the current implementation may be small in each step, but such systematic errors quickly sum up.

Related

How to use for loop with series in MATLAB

I have here an equation that is in the image
I'm trying to make the plot where y-axis is this equation, and x-axis is time - just a vector.
All the initials I have:
%Initials
Beta=[24 123 117 262 108 45]*10^-5; %pcm
Lambda=[0.0127 0.0317 0.1160 0.3106 1.4006 3.8760]; %1/s
LAMBDA=10^-4 ; %s
W=[ 0.376 -0.0133 -0.0426 -0.153 -0.972 -3.38 -29.5]
Rho=400*10^-5
t=linspace(1,30,7)
This is the code I'm using:
for n=1:7
for j=1:6
S1=Rho*sum(exp(W(n)'.*t)/(W(n)'.*(LAMBDA+(sum(Beta(j).*Lambda(j)./(W(n)+Lambda(j))^2)))))
end
end
semilogy(t,S1,'b','linewidth',2);
And S1 returns too much answers, and as I undestand it should give only 7...
And I am new to matlab and coding in general, so if the answer is obviuos I still don't know how to make it work :D
Let's clarify a few things first.
In order to do a 2D plot (of any kind), you need two vectors in Matlab. They should be of equal length. One for all the x-coordinates. Another for all the y-coordinates.
You get the x-coordinates in t=linspace(1,30,7). However, you do not have the corresponding y-coordinates.
In your case, it is best to phrase your formula as a function of t. And let's break down the sums for clarity. For example,
function num = oscillation_modes_of_sort(t)
outer_sum = 0;
for j=1:numel(W)
inner_sum = 0;
for i=1:numel(Beta)
inner_sum = inner_sum + Beta(i)*Lambda(i)/(W(j)+Lambda(i))^2;
end
outer_sum = out_sum + exp(W(j)*t)/(W(j)*(LAMBDA+inner_sum));
end
num = Rho * outer_sum;
end
Now, your y-coordinates will be oscillation_modes_of_sort(t).
There are ways to either make the code more brief or make it more friendly if W and Beta are much much longer. But let's do those at a future time.

Matlab implementation of Perceptron - can't seem to fix plotting

This is my first go with ML (and Matlab) and I'm following "Learning From Data" by Yaser S. Abu-Mostafa.
I'm trying to implement the Perceptron algorithm, after trying to go through the pseudocode, using other people's solutions I can't seem to fix my problem (I went through other threads too).
The algorithm separates the data fine, it works. However, I want to plot a single line, but it seems as it separates them in a way so the '-1' cluster is divided to a second cluster or more.
This is the code:
iterations = 100;
dim = 3;
X1=[rand(1,dim);rand(1,dim);ones(1,dim)]; % class '+1'
X2=[rand(1,dim);1+rand(1,dim);ones(1,dim)]; % class '-1'
X=[X1,X2];
Y=[-ones(1,dim),ones(1,dim)];
w=[0,0,0]';
% call perceptron
wtag=weight(X,Y,w,iterations);
% predict
ytag=wtag'*X;
% plot prediction over origianl data
figure;hold on
plot(X1(1,:),X1(2,:),'b.')
plot(X2(1,:),X2(2,:),'r.')
plot(X(1,ytag<0),X(2,ytag<0),'bo')
plot(X(1,ytag>0),X(2,ytag>0),'ro')
legend('class -1','class +1','pred -1','pred +1')
%Why don't I get just one line?
plot(X,Y);
The weight function (Perceptron):
function [w] = weight(X,Y,w_init,iterations)
%WEIGHT Summary of this function goes here
% Detailed explanation goes here
w = w_init;
for iteration = 1 : iterations %<- was 100!
for ii = 1 : size(X,2) %cycle through training set
if sign(w'*X(:,ii)) ~= Y(ii) %wrong decision?
w = w + X(:,ii) * Y(ii); %then add (or subtract) this point to w
end
end
sum(sign(w'*X)~=Y)/size(X,2); %show misclassification rate
end
I don't think the problem is in the second function but I added it regardless
I'm pretty sure the algorithm separates it to more than one cluster but I can't tell why most of the learning I've done so far was math and theory and not actual coding so I'm probably missing something obvious..

matlab ode45 retrieving parameters

I'm experimenting with ode45 in Matlab. I've learned how to pass parameters to the ode function but I still have a question. Let's suppose that I want to compute the trajectory (speed profile) of a Car and I have a function, e.g. getAcceleration, that gives me the acceleration of the car but also the right gear: [acceleration, gear] = getAcceleration(speed,modelStructure) where modelStructure represents the model of the car.
The ode function would be:
function [dy] = car(t,y,modelStructure)
dy = zeros(2,1);
dy(1) = y(2);
[dy(2),gear] = getAcceleration(y(1),modelStructure);
Then I call the Ode45 integrator in this way:
tInit = 0;
tEnd = 5,
[t,y] = ode45(#car,[tInit tEnd], [speedInitial,accelerationInitial],options,modelStructure);
The problem is: how do I get the vector storing gears? Should I have something like [t,y,gear]=ode45(....) or should gear be within the y vector?
I've been working on my code and using the events function I'm now able to get the car 'gears' changes (as events).
Now I have a new problem related to the same code.
Imagine that when I evaluate de 'dy' vector I'm able to get a further value Z which let me to have a massive speed up calling the acceleration computation (getAcceleration):
function [dy] = car(t,y,modelStructure)
dy = zeros(2,1);
dy(1) = y(2);
[dy(2),Z(t)] = getAcceleration(y(1),modelStructure,Z(t-1));
and suppose that I'm also able to compute Z at the initial condition. The problem is that I'm not able to compute the Z derivative.
Is there a way to pass Z value throw the stepping without integrating it?
Thanks guys.
First off: why are the initial values to the differential equation the initial speed (speedInitial) and the initial acceleration (accelerationInitial)? That means that the differential equation car will be computing the acceleration (y(1)) and the jerk (y(2)), the time-derivative of the acceleration, at each time t. That seems incorrect...I would say the initial values should be the initial position (positionInitial) and the initial speed (speedInitial). But, I don't know your model, I could be wrong.
Now, getting the gear in the solution directlty: you can't, not without hacking ode45. This is also logical; you also cannot get dy at all times directly, can you? That's just not how ode45 is set up.
There's two ways out I see here:
Global variable
DISCLAIMER: don't use this method. It's only here to show what most people would do as a first attempt.
You can store gear in a global variable. It's probably the least amount of coding, but also the least convenient outcome:
global ts gear ii
ii = 1;
tInit = 0;
tEnd = 5,
[t,y] = ode45(...
#(t,y) car(t,y,modelStructure), ...
[tInit tEnd], ...
[speedInitial, accelerationInitial], options);
...
function [dy] = car(t,y,modelStructure)
global ts gear ii
dy = zeros(2,1);
dy(1) = y(2);
[dy(2),gear(ii)] = getAcceleration(y(1),modelStructure);
ts(ii) = t;
ii = ii + 1;
But, due to the nature of ode45, this will get you an array of times ts and associated gear which contains intermediate points and/or points that got rejected by ode45. So, you'll have to filter for those afterwards:
ts( ~ismember(ts, t) ) = [];
I'll say it again: this is NOT the method I'd recommend. Only use global variables when testing or doing some quick-n-dirty stuff, but always very quickly shift towards other solutions. Also, the global variables grow at each (sub-)iteration of ode45, which is an unacceptable performance penalty.
It's better to use the next method:
Post-solve call
This is also not too hard for your case, and the way I'd recommend you to go. First, modify the differential equation as below, and solve as normal:
tInit = 0;
tEnd = 5,
[t,y] = ode45(...
#(t,y) car(t,y,modelStructure), ...
[tInit tEnd], ...
[speedInitial, accelerationInitial], options);
...
function [dy, gear] = car(t,y,modelStructure)
dy = [0;0];
dy(1) = y(2);
[dy(2),gear] = getAcceleration(y(1),modelStructure);
and then after ode45 completes, do this:
gear = zeros(size(t));
for ii = 1:numel(t)
[~, gear(ii)] = car(t(ii), y(ii,:).', modelStructure);
end
That will get you all the gears the car would have at times t.
The only drawback that I can see here is that you'll have many more function evaluations of car than ode45 would use by itself. But this is only a real problem if each evaluation of car takes in the order of seconds or longer, which I suspect is not the case in your setup.

Getting unexpected results while using ode45

I am trying to solve a system of differential equations by writing code in Matlab. I am posting on this forum, hoping that someone might be able to help me in some way.
I have a system of 10 coupled differential equations. It is a vector-host epidemic model, which captures the transmission of a disease between human population and insect population. Since it is a simple system of differential equations, I am using solvers (ode45) for non-stiff problem type.
There are 10 differential equations, each representing 10 different state variables. There are two functions which have the same system of 10 coupled ODEs. One is called NoEffects_derivative_6_15_2012.m which contains the original system of ODEs. The other function is called OnlyLethal_derivative_6_15_2012.m which contains the same system of ODEs with an increased withdrawal rate starting at time, gamma=32 %days and that withdrawal rate decays exponentially with time.
I use ode45 to solve both the systems, using the same initial conditions. Time vector is also the same for both systems, going from t0 to tfinal. The vector tspan contains the time values going from t0 to tfinal, each with a increment of 0.25 days, making a total of 157 time values.
The solution values are stored in matrices ye0 and yeL. Both these matrices contain 157 rows and 10 columns (for the 10 state variable values). When I compare the value of the 10th state variable, for the time=tfinal, in the matrix ye0 and yeL by plotting the difference, I find it to be becoming negative for some time values. (using the command: plot(te0,ye0(:,10)-yeL(:,10))). This is not expected. For all time values from t0 till tfinal, the value of the 10 state variable, should be greater, as it is the solution obtained from a system of ODEs which did not have an increased withdrawal rate applied to it.
I am told that there is a bug in my matlab code. I am not sure how to find out that bug. Or maybe the solver in matlab I am using (ode45) is not efficient and does give this kind of problem. Can anyone help.
I have tried ode23 and ode113 as well, and yet get the same problem. The figure (2), shows a curve which becomes negative for time values 32 and 34 and this is showing a result which is not expected. This curve should have a positive value throughout, for all time values. Is there any other forum anyone can suggest ?
Here is the main script file:
clear memory; clear all;
global Nc capitalambda muh lambdah del1 del2 p eta alpha1 alpha2 muv lambdav global dims Q t0 tfinal gamma Ct0 b1 b2 Ct0r b3 H C m_tilda betaHV bitesPERlanding IC global tspan Hs Cs betaVH k landingARRAY muARRAY
Nhh=33898857; Nvv=2*Nhh; Nc=21571585; g=354; % number of public health centers in Bihar state %Fix human parameters capitalambda= 1547.02; muh=0.000046142; lambdah= 0.07; del1=0.001331871263014; del2=0.000288658; p=0.24; eta=0.0083; alpha1=0.044; alpha2=0.0217; %Fix vector parameters muv=0.071428; % UNIT:2.13 SANDFLIES DEAD/SAND FLY/MONTH, SOURCE: MUBAYI ET AL., 2010 lambdav=0.05; % UNIT:1.5 TRANSMISSIONS/MONTH, SOURCE: MUBAYI ET AL., 2010
Ct0=0.054;b1=0.0260;b2=0.0610; Ct0r=0.63;b3=0.0130;
dimsH=6; % AS THERE ARE FIVE HUMAN COMPARTMENTS dimsV=3; % AS THERE ARE TWO VECTOR COMPARTMENTS dims=dimsH+dimsV; % THE TOTAL NUMBER OF COMPARTMENTS OR DIFFERENTIAL EQUATIONS
gamma=32; % spraying is done of 1st feb of the year
Q=0.2554; H=7933615; C=5392890;
m_tilda=100000; % assumed value 6.5, later I will have to get it for sand flies or mosquitoes betaHV=66.67/1000000; % estimated value from the short technical report sent by Anuj bitesPERlanding=lambdah/(m_tilda*betaHV); betaVH=lambdav/bitesPERlanding; IC=zeros(dims+1,1); % CREATES A MATRIX WITH DIMS+1 ROWS AND 1 COLUMN WITH ALL ELEMENTS AS ZEROES
t0=1; tfinal=40; for j=t0:1:(tfinal*4-4) tspan(1)= t0; tspan(j+1)= tspan(j)+0.25; end clear j;
% INITIAL CONDITION OF HUMAN COMPARTMENTS q1=0.8; q2=0.02; q3=0.0005; q4=0.0015; IC(1,1) = q1*Nhh; IC(2,1) = q2*Nhh; IC(3,1) = q3*Nhh; IC(4,1) = q4*Nhh; IC(5,1) = (1-q1-q2-q3-q4)*Nhh; IC(6,1) = Nhh; % INTIAL CONDITIONS OF THE VECTOR COMPARTMENTS IC(7,1) = 0.95*Nvv; %80 PERCENT OF TOTAL ARE ASSUMED AS SUSCEPTIBLE VECTORS IC(8,1) = 0.05*Nvv; %20 PRECENT OF TOTAL ARE ASSUMED AS INFECTED VECTORS IC(9,1) = Nvv; IC(10,1)=0;
Hs=2000000; Cs=3000000; k=1; landingARRAY=zeros(tfinal*50,2); muARRAY=zeros(tfinal*50,2);
[te0 ye0]=ode45(#NoEffects_derivative_6_15_2012,tspan,IC); [teL yeL]=ode45(#OnlyLethal_derivative_6_15_2012,tspan,IC);
figure(1) subplot(4,3,1); plot(te0,ye0(:,1),'b-',teL,yeL(:,1),'r-'); xlabel('time'); ylabel('S'); legend('susceptible humans'); subplot(4,3,2); plot(te0,ye0(:,2),'b-',teL,yeL(:,2),'r-'); xlabel('time'); ylabel('I'); legend('Infectious Cases'); subplot(4,3,3); plot(te0,ye0(:,3),'b-',teL,yeL(:,3),'r-'); xlabel('time'); ylabel('G'); legend('Cases in Govt. Clinics'); subplot(4,3,4); plot(te0,ye0(:,4),'b-',teL,yeL(:,4),'r-'); xlabel('time'); ylabel('T'); legend('Cases in Private Clinics'); subplot(4,3,5); plot(te0,ye0(:,5),'b-',teL,yeL(:,5),'r-'); xlabel('time'); ylabel('R'); legend('Recovered Cases');
subplot(4,3,6);plot(te0,ye0(:,6),'b-',teL,yeL(:,6),'r-'); hold on; plot(teL,capitalambda/muh); xlabel('time'); ylabel('Nh'); legend('Nh versus time');hold off;
subplot(4,3,7); plot(te0,ye0(:,7),'b-',teL,yeL(:,7),'r-'); xlabel('time'); ylabel('X'); legend('Susceptible Vectors');
subplot(4,3,8); plot(te0,ye0(:,8),'b-',teL,yeL(:,8),'r-'); xlabel('time'); ylabel('Z'); legend('Infected Vectors');
subplot(4,3,9); plot(te0,ye0(:,9),'b-',teL,yeL(:,9),'r-'); xlabel('time'); ylabel('Nv'); legend('Nv versus time');
subplot(4,3,10);plot(te0,ye0(:,10),'b-',teL,yeL(:,10),'r-'); xlabel('time'); ylabel('FS'); legend('Total number of human infections');
figure(2) plot(te0,ye0(:,10)-yeL(:,10)); xlabel('time'); ylabel('FS(without intervention)-FS(with lethal effect)'); legend('Diff. bet. VL cases with and w/o intervention:ode45');
The function file: NoEffects_derivative_6_15_2012
function dx = NoEffects_derivative_6_15_2012( t , x )
global Nc capitalambda muh del1 del2 p eta alpha1 alpha2 muv global dims m_tilda betaHV bitesPERlanding betaVH
dx = zeros(dims+1,1); % t % dx
dx(1,1) = capitalambda-(m_tilda)*bitesPERlanding*betaHV*x(1,1)*x(8,1)/(x(7,1)+x(8,1))-muh*x(1,1);
dx(2,1) = (m_tilda)*bitesPERlanding*betaHV*x(1,1)*x(8,1)/(x(7,1)+x(8,1))-(del1+eta+muh)*x(2,1);
dx(3,1) = p*eta*x(2,1)-(del2+alpha1+muh)*x(3,1);
dx(4,1) = (1-p)*eta*x(2,1)-(del2+alpha2+muh)*x(4,1);
dx(5,1) = alpha1*x(3,1)+alpha2*x(4,1)-muh*x(5,1);
dx(6,1) = capitalambda -del1*x(2,1)-del2*x(3,1)-del2*x(4,1)-muh*x(6,1);
dx(7,1) = muv*(x(7,1)+x(8,1))-bitesPERlanding*betaVH*x(7,1)*x(2,1)/(x(6,1)+Nc)-muv*x(7,1);
%dx(8,1) = lambdav*x(7,1)*x(2,1)/(x(6,1)+Nc)-muvIOFt(t)*x(8,1);
dx(8,1) = bitesPERlanding*betaVH*x(7,1)*x(2,1)/(x(6,1)+Nc)-muv*x(8,1);
dx(9,1) = (muv-muv)*x(9,1);
dx(10,1) = (m_tilda)*bitesPERlanding*betaHV*x(1,1)*x(8,1)/x(9,1);
The function file: OnlyLethal_derivative_6_15_2012
function dx=OnlyLethal_derivative_6_15_2012(t,x)
global Nc capitalambda muh del1 del2 p eta alpha1 alpha2 muv global dims m_tilda betaHV bitesPERlanding betaVH k muARRAY
dx=zeros(dims+1,1);
% the below code saves some values into the second column of the two arrays % t muARRAY(k,1)=t; muARRAY(k,2)=artificialdeathrate1(t); k=k+1;
dx(1,1)= capitalambda-(m_tilda)*bitesPERlanding*betaHV*x(1,1)*x(8,1)/(x(7,1)+x(8,1))-muh*x(1,1);
dx(2,1)= (m_tilda)*bitesPERlanding*betaHV*x(1,1)*x(8,1)/(x(7,1)+x(8,1))-(del1+eta+muh)*x(2,1);
dx(3,1)=p*eta*x(2,1)-(del2+alpha1+muh)*x(3,1);
dx(4,1)=(1-p)*eta*x(2,1)-(del2+alpha2+muh)*x(4,1);
dx(5,1)=alpha1*x(3,1)+alpha2*x(4,1)-muh*x(5,1);
dx(6,1)=capitalambda -del1*x(2,1)-del2*( x(3,1)+x(4,1) ) - muh*x(6,1);
dx(7,1)=muv*( x(7,1)+x(8,1) )- bitesPERlanding*betaVH*x(7,1)*x(2,1)/(x(6,1)+Nc) - (artificialdeathrate1(t) + muv)*x(7,1);
dx(8,1)= bitesPERlanding*betaVH*x(7,1)*x(2,1)/(x(6,1)+Nc)-(artificialdeathrate1(t) + muv)*x(8,1);
dx(9,1)= -artificialdeathrate1(t) * x(9,1);
dx(10,1)= (m_tilda)*bitesPERlanding*betaHV*x(1,1)*x(8,1)/x(9,1);
The function file: artificialdeathrate1
function art1=artificialdeathrate1(t)
global Q Hs H Cs C
art1= Q*Hs*iOFt(t)/H + (1-Q)*Cs*oOFt(t)/C ;
The function file: iOFt
function i = iOFt(t)
global gamma tfinal Ct0 b1
if t>=gamma && t<=tfinal
i = Ct0*exp(-b1*(t-gamma));
else
i =0;
end
The function file: oOFt
function o = oOFt(t)
global gamma Ct0 b2 tfinal
if (t>=gamma && t<=tfinal)
o = Ct0*exp(-b2*(t-gamma));
else
o = 0;
end
If your working code is even remotely as messy as the code you posted, then that should IMHO the first thing you should address.
I cleaned up iOFt, oOFt a bit for you, since those were quite easy to handle. I tried my best at NoEffects_derivative_6_15_2012. What I'd personally change to your code is using decent indexes. You have 10 variables, there is no way that if you let your code rest for a few weeks or months, that you will remember what state 7 is for example. So instead of using (7,1), you might want to rewrite your ODE either using verbose names and then retrieving/storing them in the x and dx vectors. Or use indexes that make it clear what is happening.
E.g.
function ODE(t,x)
insectsInfected = x(1);
humansInfected = x(2);
%etc
dInsectsInfected = %some function of the rest
dHumansInfected = %some function of the rest
% etc
dx = [dInsectsInfected; dHumansInfected; ...];
or
function ODE(t,x)
iInsectsInfected = 1;
iHumansInfected = 2;
%etc
dx(iInsectsInfected) = %some function of x(i...)
dx(iHumansInfected) = %some function of x(i...)
%etc
When you don't do such things, you might end up using x(6,1) instead of e.g. x(3,1) in some formulas and it might take you hours to spot such a thing. If you use verbose names, it takes a bit longer to type, but it makes debugging a lot easier and if you understand your equations, it should be more obvious when such an error happens.
Also, don't hesitate to put spaces inside your formulas, it makes reading much easier. If you have some sub-expressions that are meaningful (e.g. if (1-p)*eta*x(2,1) is the number of insects that are dying of the disease, just put it in a variable dyingInsects and use that everywhere it occurs). If you align your assignments (as I've done above), this might add to code that is easier to read and understand.
With regard to the ODE solver, if you are sure your implementation is correct, I'd also try a solver for stiff problems (unless you are absolutely sure you don't have a stiff system).

Matlab: Optimizing speed of function call and cosine sign-finding in a loop

The code in question is here:
function k = whileloop(odefun,args)
...
while (sign(costheta) == originalsign)
y=y(:) + odefun(0,y(:),vars,param)*(dt); % Line 4
costheta = dot(y-normpt,normvec);
k = k + 1;
end
...
end
and to clarify, odefun is F1.m, an m-file of mine. I pass it into the function that contains this while-loop. It's something like whileloop(#F1,args). Line 4 in the code-block above is the Euler method.
The reason I'm using a while-loop is because I want to trigger upon the vector "y" crossing a plane defined by a point, "normpt", and the vector normal to the plane, "normvec".
Is there an easy change to this code that will speed it up dramatically? Should I attempt learning how to make mex files instead (for a speed increase)?
Edit:
Here is a rushed attempt at an example of what one could try to test with. I have not debugged this. It is to give you an idea:
%Save the following 3 lines in an m-file named "F1.m"
function ydot = F1(placeholder1,y,placeholder2,placeholder3)
ydot = y/10;
end
%Run the following:
dt = 1.5e-12 %I do not know about this. You will have to experiment.
y0 = [.1,.1,.1];
normpt = [3,3,3];
normvec = [1,1,1];
originalsign = sign(dot(y0-normpt,normvec));
costheta = originalsign;
y = y0;
k = 0;
while (sign(costheta) == originalsign)
y=y(:) + F1(0,y(:),0,0)*(dt); % Line 4
costheta = dot(y-normpt,normvec);
k = k + 1;
end
disp(k);
dt should be sufficiently small that it takes hundreds of thousands of iterations to trigger.
Assume I must use the Euler method. I have a stochastic differential equation with state-dependent noise if you are curious as to why I tell you to take such an assumption.
I would focus on your actual ODE integration. The fewer steps you have to take, the faster the loop will run. I would only worry about the speed of the sign check after you've optimized the actual integration method.
It looks like you're using the first-order explicit Euler method. Have you tried a higher-order integrator or an implicit method? Often you can increase the time step significantly.