Euler method doesn't give correct output - matlab

I'm trying to write a MATLAB code for the Forward Euler method, but I don't think the output is completely correct.
This is my code:
function [t ,u] = Euler(f,tspan ,u0,n)
T = [tspan(1) :n: tspan(2)];
u = zeros(1,n);
u(n) = u0;
h = (tspan(2) - tspan(1))/n;
for i= 1: n
u(i+1) = u(i) + h*f(T(i),u(i));
t = [u(i+1)*T(i)];
u = [u(i+1)];
end
end

A minimal straightforward implementation could look like
function [tHist ,uHist] = ForwardEuler(f,tspan ,u0,nsteps)
tHist = linspace(tspan(1), tspan(2), nsteps+1);
h = tHist(2)-tHist(1);
uHist = zeros(nsteps+1,length(u0));
uHist(1,:)=u0;
for i = 1:nsteps
uHist(i+1,:) = uHist(i,:) + h*f(tHist(i),uHist(i,:));
end%for
end%function
Test the routine with the circle equation
[T,U] = ForwardEuler(#(t,u)[u(2), -u(1)], [0,6.5], [1,0], 60);
plot(U(:,1),U(:,2));
which produces the expected outward spiral.

Related

Numerical Analysis help in MatLab

I am in a numerical analysis class, and I am working on a homework question. This comes Timothy Sauer's Numerical Analysis, and is in the second suggested activity section. I have been talking with my professor about this code, and it seems the error and the approximation are wrong, but neither one of us are able to figure out why. The following code is what I am using, and this is in MatLab. Anyone know enough about Euler Bernoulli beams, and Matlab who can help out?
function ebbeamerror %This is for part three
disp(['tabe of errors at x=L for each n'])
disp([' n ',' Aprox ',' Actual value',' Error'])
disp(['======================================================='])
format bank
for k = 1:11
n = 10*(2^k);
D = sparse(1:n,1:n,6*ones(1,n),n,n);
G = sparse(2:n,1:n-1,-4*ones(1,n-1),n,n);
F = sparse(3:n,1:n-2,ones(1,n-2),n,n);
S = G+D+F+G'+F';
S(1,1) = 16;
S(1,2) = -9;
S(1,3) = 8/3;
S(1,4) = -1/4;
S(2,1) = -4;
S(2,2) = 6;
S(2,3) = -4;
S(2,4) = 1;
S(n-1,n-3)=16/17;
S(n-1,n-2)=-60/17;
S(n-1,n-1)=72/17;
S(n-1,n)=-28/17;
S(n,n-3)=-12/17;
S(n,n-2)=96/17;
S(n,n-1)=-156/17;
S(n,n)=72/17;
E = 1.3e10;
w = 0.3;
d = 0.03;
I = w*d^3/12;
g = -9.81;
f = 480*d*g*w;
h = 2/10;
L = 2;
x = (h^4)*f/(E*I);
x1 = ones(n ,1);
b = x*x1;
size (S);
size(b);
pause
y = S\b;
x=2;
a = (f/(24*E*I))*(x^2)*(x^2-4*L*x+6*L^2);
disp([n y(n) a abs(y(n)-a)])
end
end

Using the Runge-Kutta integration method in a system

h=0.005;
x = 0:h:40;
y = zeros(1,length(x));
y(1) = 0;
F_xy = ;
for i=1:(length(x)-1)
k_1 = F_xy(x(i),y(i));
k_2 = F_xy(x(i)+0.5*h,y(i)+0.5*h*k_1);
k_3 = F_xy((x(i)+0.5*h),(y(i)+0.5*h*k_2));
k_4 = F_xy((x(i)+h),(y(i)+k_3*h));
y(i+1) = y(i) + (1/6)*(k_1+2*k_2+2*k_3+k_4)*h;
end
I have the following code, I think it's right. I know there's parts missing on the F_xy because this is my follow up question.
I have dx/dt = = −x(2 − y) with t_0 = 0, x(t_0) = 1
and dy/dt = y(1 − 2x) with t_0 = 0, y(t_0) = 2.
My question is that I don't know how to get these equations in to the code. All help appreciated
You are using both t and x as independent variable in an inconsistent manner. Going from the actual differential equations, the independent variable is t, while the dependent variables of the 2-dimensional system are x and y. They can be combined into a state vector u=[x,y] Then one way to encode the system close to what you wrote is
h=0.005;
t = 0:h:40;
u0 = [1, 2]
u = [ u0 ]
function udot = F(t,u)
x = u(1); y = u(2);
udot = [ -x*(2 - y), y*(1 - 2*x) ]
end
for i=1:(length(t)-1)
k_1 = F(t(i) , u(i,:) );
k_2 = F(t(i)+0.5*h, u(i,:)+0.5*h*k_1);
k_3 = F(t(i)+0.5*h, u(i,:)+0.5*h*k_2);
k_4 = F(t(i)+ h, u(i,:)+ h*k_3);
u(i+1,:) = u(i,:) + (h/6)*(k_1+2*k_2+2*k_3+k_4);
end
with a solution output
Is F_xy your derivative function?
If so, simply write it as a helper function or function handle. For example,
F_xy=#(x,y)[-x*(2-y);y*(1-2*x)];
Also note that your k_1, k_2, k_3, k_4, y(i) are all two-dimensional. You need to re-size your y and rewrite the indices in your iterating steps accordingly.

Has fminsearch too many parameters?

I run this code in matlab to minimize the parameters of my function real_egarchpartial with fminsearch:
data = xlsread('return_cc_in.xlsx');
SPY = data(:,25);
dailyrange = xlsread('DR_in.xlsx');
drSPY= dailyrange(:,28);
startingVals = [mean(SPY); 0.041246; 0.70121; 0.05; 0.04; 0.45068; -0.1799; 1.0375; 0.06781; 0.070518];
T = size(SPY,1);
options = optimset('fminsearch');
options.Display = 'iter';
estimates = fminsearch(#real_egarchpartial, startingVals, options, SPY, drSPY);
[ll, lls, u]=real_egarchpartial(estimates, SPY, drSPY);
And I get this message:
Exiting: Maximum number of function evaluations has been exceeded
- increase MaxFunEvals option.
I put the original starting values. So I assumed they are corrects. I used fminsearch and not fmincon because my function hasn't constraints and with fminunc my function gets a lot of red messages.
the real_egarchpartial function is the following:
function [ll,lls,lh] = real_egarchpartial(parameters, data, x_rk)
mu = parameters(1);
omega = parameters(2);
beta = parameters(3);
tau1 = parameters(4);
tau2 = parameters(5);
gamma = parameters(6);
csi = parameters(7);
phi = parameters(8);
delta1 = parameters(9);
delta2 = parameters(10);
%Data and h are T by 1 vectors
T = size(data,1);
eps = data-mu;
lh = zeros(T,1);
h = zeros(T,1);
u = zeros(T,1);
%Must use a back Cast to start the algorithm
h(1)=var(data);
lh(1) = log(h(1));
z= eps/sqrt(h(1));
u(1) = rand(1);
lxRK = log(x_rk);
for t = 2:T;
lh(t) = omega + beta*lh(t-1) + tau1*z(t-1) + tau2*((z(t-1).^2)-1)+ gamma*u(t-1);
h(t)=exp(lh(t));
z = eps/sqrt(h(t));
end
for t = 2:T
u(t)= lxRK(t) - csi - phi*h(t) - delta1*z(t) - delta2*((z(t).^2)-1);
end
lls = 0.5*(log(2*pi) + lh + eps.^2./h);
ll = sum(lls);
Could someone explain what is wrong? Is there another function more efficient for my estimation? Any help will be appreciated! Thank you.

Matlab. Create a loop to change variable size with each iteration

I am currently trying to run a script that calls a particular function, but want to call the function inside a loop that halfs one of the input variables for roughly 4 iterations.
in the code below the function has been replaced for another for loop and the inputs stated above.
the for loop is running an Euler method on the function, and works fine, its just trying to run it with the repeated smaller step size im having trouble with.
any help is welcomed.
f = '3*exp(-x)-0.4*y';
xa = 0;
xb = 3;
ya = 5;
n = 2;
h=(xb-xa)/n;
x = xa:h:xb;
% h = zeros(1,4);
y = zeros(1,length(x));
F = inline(f);
y(1) = ya;
for j = 1:4
hOld = h;
hNew = hOld*0.5;
hOld = subs(y(1),'h',hNew);
for i = 1:(length(x)-1)
k1 = F(x(i),y(i));
y(i+1,j+1) = y(i) + h*k1;
end
end
disp(h)
after your comment, something like this
for j = 1:4
h=h/2;
x = xa:h:xb;
y = zeros(1,length(x));
y(1) = ya;
for i = 1:(length(x)-1)
k1 = F(x(i),y(i));
y(i+1,j+1) = y(i) + h*k1;
end
end

Fourth-order Runge–Kutta method (RK4) collapses after a few iterations

I'm trying to solve:
x' = 60*x - 0.2*x*y;
y' = 0.01*x*y - 100* y;
using the fourth-order Runge-Kutta algorithm.
Starting points: x(0) = 8000, y(0) = 300 range: [0,15]
Here's the complete function:
function [xx yy time r] = rk4_m(x,y,step)
A = 0;
B = 15;
h = step;
iteration=0;
t = tic;
xh2 = x;
yh2 = y;
rr = zeros(floor(15/step)-1,1);
xx = zeros(floor(15/step)-1,1);
yy = zeros(floor(15/step)-1,1);
AA = zeros(1, floor(15/step)-1);
while( A < B)
A = A+h;
iteration = iteration + 1;
xx(iteration) = x;
yy(iteration) = y;
AA(iteration) = A;
[x y] = rkstep(x,y,h);
for h2=0:1
[xh2 yh2] = rkstep(xh2,yh2,h/2);
end
r(iteration)=abs(y-yh2);
end
time = toc(t);
xlabel('Range');
ylabel('Value');
hold on
plot(AA,xx,'b');
plot(AA,yy,'g');
plot(AA,r,'r');
fprintf('Solution:\n');
fprintf('x: %f\n', x);
fprintf('y: %f\n', y);
fprintf('A: %f\n', A);
fprintf('Time: %f\n', time);
end
function [xnext, ynext] = rkstep(xcur, ycur, h)
kx1 = f_prim_x(xcur,ycur);
ky1 = f_prim_y(xcur,ycur);
kx2 = f_prim_x(xcur+0.5*h,ycur+0.5*h*kx1);
kx3 = f_prim_x(xcur+0.5*h,ycur+0.5*h*kx2);
kx4 = f_prim_x(xcur+h,ycur+h*kx3);
ky2 = f_prim_y(xcur+0.5*h*ky1,ycur+0.5*h);
ky3 = f_prim_y(xcur+0.5*h*ky2,ycur+0.5*h);
ky4 = f_prim_y(xcur+h*ky2,ycur+h);
xnext = xcur + (1/6)*h*(kx1 + 2*kx2 + 2*kx3 + kx4);
ynext = ycur + (1/6)*h*(ky1 + 2*ky2 + 2*ky3 + ky4);
end
function [fx] = f_prim_x(x,y)
fx = 60*x - 0.2*x*y;
end
function [fy] = f_prim_y(x,y)
fy = 0.01*x*y - 100*y;
end
And I'm running it by executing: [xx yy time] = rk4_m(8000,300,10)
The problem is that everything collapses after 2-3 iterations returning useless results. What am I doing wrong? Or is just this method not appropriate for this kind equation?
The semicolons are intentionally omitted.
Looks like I didn't pay attention to actual h size. It works now! Thanks!
Looks like some form of the Lotka-Volterra equation?
I'm not sure if if your initial condition is [300;8000] or [8000;300] (you specify it both ways above), but regardless, you have an oscillatory system that you're trying to integrate with a large fixed time step that is (much) greater than the period of oscillation. This is why your error explodes. If you try increasing n (say, 1e6), you'll find that eventually you'll get a stable solution (assuming that your Runge-Kutta implementation is otherwise correct).
Is there a reason why you're not using Matlab's builtin ODE solvers, e.g. ode45 or ode15s?
function ode45demo
[t,y]=odeode45(#f,[0 15],[300;8000]);
figure;
plot(t,y);
function ydot=f(t,y)
ydot(1,1) = 60*y(1) - 0.2*y(1)*y(2);
ydot(2,1) = 0.01*y(1)*y(2) - 100*y(2);
You'll find that adaptive step size solvers are much more efficient for these types of oscillatory problems. Because your system has such a high frequency and seems rather stiff, I suggest that you also look at what ode15s gives and/or adjust the 'AbsTol' and 'RelTol' options with odeset.
The immediate problem is that the RK4 code was not completely evolved from the scalar case to the case of two coupled equations. Note that there is no time parameter in the derivative funtions. x and y are both dependent variables and thus get the slope update defined by the derivative functions in every step. Then xcur gets the kx updates and ycur gets the ky updates.
function [xnext, ynext] = rkstep(xcur, ycur, h)
kx1 = f_prim_x(xcur,ycur);
ky1 = f_prim_y(xcur,ycur);
kx2 = f_prim_x(xcur+0.5*h*kx1,ycur+0.5*h*ky1);
ky2 = f_prim_y(xcur+0.5*h*kx1,ycur+0.5*h*ky1);
kx3 = f_prim_x(xcur+0.5*h*kx2,ycur+0.5*h*ky2);
ky3 = f_prim_y(xcur+0.5*h*kx2,ycur+0.5*h*ky2);
kx4 = f_prim_x(xcur+h*kx3,ycur+h*ky3);
ky4 = f_prim_y(xcur+h*kx3,ycur+h*ky3);
xnext = xcur + (1/6)*h*(kx1 + 2*kx2 + 2*kx3 + kx4);
ynext = ycur + (1/6)*h*(ky1 + 2*ky2 + 2*ky3 + ky4);
end