I have a problem with this code. some idea? - matlab

I have the next code: BD_MACRO, but when rum, I obtain this answer in command window in matlab
BD_MACROPA
Subscript indices must either be real positive integers or
logicals.
Error in BD_MACROPA (line 27)
dH = betaH((aH - bH) * H(i-1) + phi * h(i-1)) -
alphaH * Z(i-1);
[![% MODELO BASICO
dt=0.01; % pasos en el tiempo
tiempo=2000; % anos de evolucion
%CONDICIONES INICIALES
H(1)=100; h(1)=250; Z(1)=200; t(1)=0;
%PARAMETROS
%ADULTOS Y PREADULTOS
aH = 147.9;
ah = 34.25;
bh = 0.20;
bH = 0.20;
phi= 0.25;
ro = 34.24;
muZ = 0.15;
H0 = 10.0;
alphaH = 0.000001;
alphah = 0.000001;
lambda = 6.0;
betaH = 0.095;
betah = 0.095;
rand('state',sum(100*clock)); % semilla de generador de numeros aleatorios,
%
numreps=5000; % numero de realizaciones
for j=1:numreps
for i=2:tiempo
dH = betaH((aH - bH) * H(i-1) + phi * h(i-1)) - alphaH * Z(i-1);
dh = betah((ah - bh) * h(i-1) + ro * H(i-1)) - alphah * Z(i-1);
dZ = Z(i-1) * (lambda * H(i-1)./(H0 + H(i-1)) + (r - mu + (bH + bh)) - alpha * (H(i-1) + Z(i-1))./H(i-1));
H(i) = H(i-1) + dt * dH;
h(i) = h(i-1) + dt * dh;
Z(i) = Z(i-1) + dt * dZ;
t(i) = t(i-1) + dt;
end
end
% Create figure
figure1 = figure;
% Create axes
axes1 = axes('Parent',figure1);
hold(axes1,'on');
% Create multiple lines using matrix input to plot
plot1 = plot(t,H,t,P,t,Z,'LineWidth',2);
set(plot1(1),'DisplayName','H');
set(plot1(2),'DisplayName','P','LineStyle','--');
set(plot1(3),'DisplayName','Z','LineStyle','.-');
%plot(t,H,t,P)
% Create xlabel
xlabel('Tiempo');
% Create ylabel
ylabel('Tamaño de la Población');
box(axes1,'on');
grid(axes1,'on');
% Set the remaining axes properties
set(axes1,'FontSize',12);
% Create legend
legend1 = legend(axes1,'show');
set(legend1,'FontSize',20);
legend('Hospederos Adultos', 'Hospederos Preadultos','Zoosporas');][1]][1]

You are probably missing a * sign in the statement
dH = betaH((aH - bH) * H(i-1) + phi * h(i-1)) - alphaH * Z(i-1);
Right now, this is trying to access 14833-th element of dH whereas you define dH as a scalar. I think what you want is
dH = betaH*((aH - bH) * H(i-1) + phi * h(i-1)) - alphaH * Z(i-1);
Same issue with dH. You also have undeclared variables alpha, mu and r in the statement
dZ = Z(i-1) * (lambda * H(i-1)./(H0 + H(i-1)) + (r - mu + (bH + bh)) - alpha * (H(i-1) + Z(i-1))./H(i-1));

Related

Why does changing the boundary conditions cause the finite difference algorithm to diverge?

I wrote a finite difference algorithm to solve the wave equation which is derived here.
When I ran my code, the plotted graphs of the numerical and analytical solution deviated, which is the problem I am trying to solve. The finite difference algorithm is given in the snippet.
t_min = 0;
t_max = 10;
rps = 400; % Resolution per second
nt = t_max * rps;
t = linspace(t_min, t_max, nt);
dt = t(2) - t(1);
x_min = 0;
x_max = 8;
rpm = 100; % Resolution per menter
nx = x_max * rpm;
x = linspace(x_min, x_max, nx);
dx = x(2) - x(1);
c = 3; % Wave speed
A = pi; % Amplitude
L = x_max; % Rod lenght
w_o = 1; % Circular frequency
Cn = c * (dt / dx); % Courrant number
if Cn > 1 % Stability criteria
error('The stability condition is not satisfied.');
end
U = zeros(nx, nt);
U(:, 1) = zeros(nx, 1);
U(:, 2) = zeros(nx, 1);
U(1, :) = A * sin(w_o * t);
U(end, :) = zeros(1, nt);
for j = 2 : (nt - 1)
for i = 2 : (nx - 1)
U(i, j + 1) = Cn^2 * ( U(i + 1, j) - 2 * U(i, j) + U(i - 1, j) ) + 2 * U(i, j) - U(i, j - 1);
end
end
figure('Name', 'Numeric solution');
surface(t, x, U, 'edgecolor', 'none');
grid on
colormap(jet(256));
colorbar;
xlabel('t ({\its})');
ylabel('x ({\itm})');
title('U(t, x) ({\itm})');
To find the bug, I tryed to change the boundary conditions and see if my graph would look better. It turned out that it did, which means that the code in my double for loop is ok. The boundary conditions are the problem. However, I do not know why the code works with the new boundary conditions and does not with the old ones. I am hoping that somebody will point this out to me. The code I ran is given in the snippet.
t_min = 0;
t_max = 1;
rps = 400; % Resolution per second
nt = t_max * rps;
t = linspace(t_min, t_max, nt);
dt = t(2) - t(1);
x_min = 0;
x_max = 1;
rpm = 100; % Resolution per menter
nx = x_max * rpm;
x = linspace(x_min, x_max, nx);
dx = x(2) - x(1);
c = 3; % Wave speed
A = pi; % Amplitude
L = x_max; % Rod lenght
w_o = 1; % Circular frequency
Cn = c * (dt / dx); % Courrant number
if Cn > 1 % Stability criteria
error('The stability condition is not satisfied.');
end
U = zeros(nx, nt);
U(:, 1) = sin(pi*x);
U(:, 2) = sin(pi*x) * (1 + dt);
U(1, :) = zeros(1, nt);
U(end, :) = zeros(1, nt);
for j = 2 : (nt - 1)
for i = 2 : (nx - 1)
U(i, j + 1) = Cn^2 * ( U(i + 1, j) - 2 * U(i, j) + U(i - 1, j) ) + 2 * U(i, j) - U(i, j - 1);
end
end
figure('Name', 'Numeric solution');
surface(t, x, U, 'edgecolor', 'none');
grid on
colormap(jet(256));
colorbar;
xlabel('t ({\its})');
ylabel('x ({\itm})');
title('U(t, x) ({\itm})');

Matlab: resize with custom interpolation kernel Mitchell-Netravali

I have seen that there was an interest in custom interpolation kernels for resize (MATLAB imresize with a custom interpolation kernel). Did anyone implemented the parametric Mitchell-Netravali kernel [1] that is used as default in ImageMagick and is willing to share the Matlab code? Thank you very much!
[1] http://developer.download.nvidia.com/books/HTML/gpugems/gpugems_ch24.html
// Mitchell Netravali Reconstruction Filter
// B = 0 C = 0 - Hermite B-Spline interpolator
// B = 1, C = 0 - cubic B-spline
// B = 0, C = 1/2 - Catmull-Rom spline
// B = 1/3, C = 1/3 - recommended
float MitchellNetravali(float x, float B, float C)
{
float ax = fabs(x);
if (ax < 1) {
return ((12 - 9 * B - 6 * C) * ax * ax * ax +
(-18 + 12 * B + 6 * C) * ax * ax + (6 - 2 * B)) / 6;
} else if ((ax >= 1) && (ax < 2)) {
return ((-B - 6 * C) * ax * ax * ax +
(6 * B + 30 * C) * ax * ax + (-12 * B - 48 * C) *
ax + (8 * B + 24 * C)) / 6;
} else {
return 0;
}
}
Here I got another approach with vectorization; according to my tests with upscaling (1000x1000 -> 3000x3000) this is faster than the standard bicubic even with a large Mitchell radius = 6:
function [outputs] = Mitchell_vect(x,M_B,M_C)
outputs= zeros(size(x,1),size(x,2));
ax = abs(x);
temp = ((12-9*M_B-6*M_C) .* ax.^3 + (-18+12*M_B+6*M_C) .* ax.^2 + (6-2*M_B))./6;
temp2 = ((-M_B-6*M_C) .* ax.^3 + (6*M_B+30*M_C) .* ax.^2 + (-12*M_B-48*M_C) .* ax + (8*M_B + 24*M_C))./6;
index = find(ax<1);
outputs(index)=temp(index);
index = find(ax>=1 & ax<2);
outputs(index)=temp2(index);
end
I got the following proposal for the Mitchel kernel called by imresize with the parameters B and C and a kernel radius using for-loops (and preallocation):
img_resize = imresize(img, [h w], {#(x)Mitchell(x,B,C),radius});
function [outputs] = Mitchell(x,B,C)
outputs= zeros(size(x,1),size(x,2));
for i = 1 : size(x,1)
for j = 1 : size(x,2)
ax = abs(x(i,j));
if ax < 1
outputs(i,j) = ((12-9*B-6*C) * ax^3 + (-18+12*B+6*C) * ax^2 + (6-2*B))/6;
elseif (ax >= 1) && (ax < 2)
outputs(i,j) = ((-B-6*C) * ax^3 + (6*B+30*C) * ax^2 + (-12*B-48*C) * ax + (8*B + 24*C))/6;
else
outputs(i,j) = 0;
end
end
end
end

MATLAB orbit of earth and moon about the sun

We are trying to plot the orbit of the moon around the earth, which in turn is orbiting the sun. We are employing the Euler-Cromer method. This code works for a simulation of the planets. And it should work given the right initial conditions, for a more complicated set up such as what we are trying now with three bodies. Our code is this:
function [xe, ye, xm, ym] = earth_moon(me, mm)
% Constants
ms = 2e30;
ntsteps = 12;
dt = 0.001;
% Variables: Earth
xe = 1 : dt : ntsteps;
xe(1) = 1; % Initial x pos (AU)
ye = 1 : dt : ntsteps;
ye(1) = 0; % Initial y pos (AU)
vex = 0;
vey = 6.27; % AU/yr
% Variables: Moon
xm = 1 : dt : ntsteps;
xm(1) = 1.0027; % Initial x pos (AU)
ym = 1 : dt : ntsteps;
ym(1) = 0; % Initial y pos (AU)
vmx = 0;
vmy = 0.215 + vey; % AU/yr
% Calculations
for i = 1 : ntsteps / dt
rm = sqrt(xm(i)^2 + ym(i)^2);
re = sqrt(xe(i)^2 + ye(i)^2);
rme = sqrt((xm(i) - xe(i))^2 + (ym(i) - ye(i))^2);
vex = vex - 4 * pi^2 * xe(i) / re^3 * dt - 4 * pi^2 * (mm / ms) * (xe(i) - xm(i))/rme^3 * dt;
vey = vey - 4 * pi^2 * ye(i) / re^3 * dt - 4 * pi^2 * (mm / ms) * (ye(i) - xm(i))/rme^3 * dt;
vmx = vmx - 4 * pi^2 * xm(i) / rm^3 * dt - 4 * pi^2 * (me / ms) * (xm(i) - xe(i))/rme^3 * dt;
vmy = vmy - 4 * pi^2 * ym(i) / rm^3 * dt - 4 * pi^2 * (me / ms) * (ym(i) - ye(i))/rme^3 * dt;
xm(i + 1) = xm(i) + vmx * dt;
ym(i + 1) = ym(i) + vmy * dt;
xe(i + 1) = xe(i) + vex * dt;
ye(i + 1) = ye(i) + vey * dt;
end
end
And the script is as follows:
clear
clc
me = 5.97237e24;
mm = 7.3477e22;
[xe, ye, xm, ym] = earth_moon(me, mm);
hold on;
plot(xm, ym, 'r');
plot(xe, ye, 'b');
plot(0, 0, 'r.', 'Markersize', 50);
plot(0, 0, 'y.', 'Markersize', 40);
grid on;
axis square;
xlabel('X position (AU)');
ylabel('Y position (AU)');
ylim([-2, 2])
xlim([-2, 2])
title('Three-body orbit: Sun, Earth, Moon');
text(2, 5.5, strcat('Earth: ', num2str(me), ' kg'));
text(3.5, 4.5, strcat('Moon: ', num2str(mm), ' kg'));
legend('Moon', 'Earth', 'Location', 'eastoutside');
But we just cant get the moon to cooperate. Any suggestions?
Thanks!

Matlab error in ode45 or fourth-order Runge-Kutta method to solve a system of coupled ODEs

I am a beginner at Matlab programming and with the Runge-Kutta method as well.
I'm trying to solve a system of coupled ODEs using a 4th-order Runge-Kutta method for my project work.
here is my problem...
G = 1.4;
g = 1.4;
k = 0;
z = 0;
b = 0.166667;
syms n;
x2 = symfun(sym('x2(n)'),[n]);
x1 = symfun(sym('x1(n)'),[n]);
x3 = symfun(sym('x3(n)'),[n]);
x4 = symfun(sym('x4(n)'),[n]);
x5 = symfun(sym('x5(n)'),[n]);
k1 = [x2 * x1 *n *(1 - z * x2)*(x1 - n) - 2 * x3 * n *(1 - z * x2) - x4^2 * x2 *(1 - z * x2)- G *x3 *x2 ]./ [( G * x3 - (x1 - n)^2 * x2 *(1 - z * x2)) * n];
k2 = [x2 * (1 - z * x2)*(x1 * x2 * ( x1 - 2 *n)*( x1 - n) + 2* x3 * n + x4^2 * x2 ) ]./ [( G * x3 - (x1 - n)^2 * x2 *(1 - z * x2)) * n * (x1 - n)];
k3 = [x3 * x2 * (2 * n * x1 - n)^2 * ( 1 - z * x2) + G * x1 * (x1 - 2 *n)* (x1 - n) + x4^2 * G]./ [( G * x3 - (x1 - n)^2 * x2 *(1 - z * x2)) * n * (x1 - n)];
k4 = [x4 * ( x1 + n)] ./ [n * (x1- n)];
k5 = - [x5] ./ [n * (x1- n)];
f = #(n,x) [k1; k2; k3; k4; k5];
[n,xa] = ode45(f,[0 1],[1-b 1/b 1-b 0.01 0.02]);
errors are
Error using odearguments (line 93)
#(N,X)[K1;K2;K3;K4;K5] returns a vector of length 1, but the length
of initial conditions vector is 5. The vector returned by
#(N,X)[K1;K2;K3;K4;K5] and the initial conditions vector must have
the same number of elements.
Error in ode45 (line 114)
[neq, tspan, ntspan, next, t0, tfinal, tdir, y0, f0, odeArgs,
odeFcn, ...
Please guide me how can I solve the above problem with fourth-order Runge-Kutta method...
The error stems from using symbolic functions (mixed with a function handle) with a numeric solver.
You need to create numeric functions for ode45 to function properly (I also replaced all of the [ and ] with ( and ) for grouping):
G = 1.4;
g = 1.4;
k = 0;
z = 0;
b = 0.166667;
k1 = #(n,x) (x(2) * x(1)*n *(1 - z * x(2))*(x(1) - n) - 2 * x(3) * n *(1 - z * x(2)) - x(4)^2 * x(2) *(1 - z * x(2))- G *x(3) *x(2)) ./ (( G * x(3) - (x(1) - n)^2 * x(2) *(1 - z * x(2))) * n);
k2 = #(n,x) (x(2) * (1 - z * x(2))*(x(1) * x(2) * ( x(1) - 2 *n)*( x(1) - n) + 2* x(3) * n + x(4)^2 * x(2) )) ./ (( G * x(3) - (x(1) - n)^2 * x(2) *(1 - z * x(2))) * n * (x(1) - n));
k3 = #(n,x) (x(3) * x(2) * (2 * n * x(1) - n)^2 * ( 1 - z * x(2)) + G * x(1) * (x(1) - 2 *n)* (x(1) - n) + x(4)^2 * G)./ (( G * x(3) - (x(1) - n)^2 * x(2) *(1 - z * x(2))) * n * (x(1) - n));
k4 = #(n,x) (x(4) * (x(1) + n)) ./ (n * (x(1)- n));
k5 = #(n,x) - x(5) ./ (n * (x(1)- n));
f = #(n,x) [k1(n,x); k2(n,x); k3(n,x); k4(n,x); k5(n,x)];
[n,xa] = ode45(f,[0 1],[1-b 1/b 1-b 0.01 0.02]);
This runs for my install of Matlab.
However, the output is all NaNs since the function produce Infs; I may have introduced errors by replacing the brackets, but I don't know what the actual equations are so I'm going to leave that to you. :)
In general, you consult first the documentation. If not available, use the search engine of you choice, for instance https://www.google.de/search?q=matlab+ode45+example to find as first result https://de.mathworks.com/help/matlab/ref/ode45.html
There you find a multidimensional example
function dy = rigid(t,y)
dy = zeros(3,1); % a column vector
dy(1) = y(2) * y(3);
dy(2) = -y(1) * y(3);
dy(3) = -0.51 * y(1) * y(2);
end
options = odeset('RelTol',1e-4,'AbsTol',[1e-4 1e-4 1e-5]);
[T,Y] = ode45(#rigid,[0 12],[0 1 1],options);
plot(T,Y(:,1),'-',T,Y(:,2),'-.',T,Y(:,3),'.')
that could be used as a blueprint. In the related page https://de.mathworks.com/help/matlab/math/ordinary-differential-equations.html they use a different syntax closer to yours for the van der Pol Equation in the first example
function dydt = vdp1(t,y)
dydt = [y(2); (1-y(1)^2)*y(2)-y(1)];
end
[t,y] = ode45(#vdp1,[0 20],[2; 0]);
plot(t,y(:,1),'-',t,y(:,2),'--')
title('Solution of van der Pol Equation, \mu = 1');
xlabel('time t');
ylabel('solution y');
legend('y_1','y_2')
Following these examples, rewrite your code as
G = 1.4;
g = 1.4;
k = 0;
z = 0;
b = 0.166667;
function dotx = dxdn(n,x)
t1 = n*(x1-n)
t2 = x(2)*(1 - z * x(2))
den123 = ( G * x(3) - (x(1) - n)^2 * t2)
k1 = ( x(1)*t1*t2 - 2 * x(3) * n *(1 - z * x(2)) - x(4)^2 * t2- G *x(3) *x(2) ) / (den123*n);
k2 = ( t2*(x(1) * x(2) * ( x(1) - 2 *n)*( x(1) - n) + 2* x(3) * n + x(4)^2 * x(2) ) ) / (den123 * t1);
k3 = ( x(3) * (2 * n * x(1) - n)^2 * t2 + G * x(1) * (x(1) - 2 *n)* (x(1) - n) + x(4)^2 * G ) / (den123*t1);
k4 = ( x(4) * ( x(1) + n) ) / t1;
k5 = - x(5) / t1;
dotx = [k1; k2; k3; k4; k5];
end
[n,xa] = ode45(#dxdn,[0.001 1],[1-b; 1/b; 1-b; 0.01; 0.02]);
Because of the division by zero at n=0 you can not start the iteration in that singularity. In the code above, this is mitigated by starting with some (very) small positive n, you can also try starting with n=1e-8 or smaller. The slope will be very large in all components, so the integration may be slow, and the result might be not overly exact close to zero. For the correct handling of singular ODE ask in the math.stackexchange forum.

Using NonNegative setting in Matlab odeset()

I'm trying to solve some ODEs in MatLab and seeing as the variables in the equations are populations they need to be constrained to being positive. So I tried using odeset() before calling the equation solver to make them non-negative but on plotting the values afterwards they are actually negative at times (in the code below it is the magenta line). What am I doing wrong?
Here's some code:
%Lots of variables
includeJ=1;
cullLIRate=1/2000;
cullDIRate=1/2000;
N = 16800;
beta = 2e-7;
delta = 0.5;
gamma = 1/50;
sigma = 1/400;
mu = 1/365;
maxTime = 30*365;
kappa = N;
gR = 0.05;
mJ = 1/3650;
initJPerAdult = 10;
numInitE = 1000;
TSpan = [0,maxTime];
initState = [N-numInitE,numInitE,0,0,0,initJPerAdult*N];
%IMPORTANT BIT HERE
options = odeset('NonNegative', 1:6)
scirSoln = ode45(#equation,TSpan,initState,[],beta,delta,gamma,sigma,mu,kappa,gR,mJ,cullLIRate,cullDIRate,includeJ);
scirVals = deval(scirSoln,timeToPlot);
plot(timeToPlot,scirVals(1,:));
hold on;
plot(timeToPlot,scirVals(3,:),'k');
plot(timeToPlot,scirVals(4,:),'g');
plot(timeToPlot,scirVals(6,:),'m');
timeToPlot = [0:max(TSpan)/1000:max(TSpan)];
The code for equation(...) is:
function retVal = equation(t,y,beta,delta,gamma,sigma,mu,kappa,gR,mJ,cullLIRate,cullDIRate,includeJ)
retVal = zeros(6,1);
S = y(1);
E = y(2);
LI = y(3);
DI = y(4);
R = y(5);
J = y(6);
retVal(1)= mJ * J - beta * S * (delta * LI + DI);
retVal(2) = beta * S * (delta * LI + DI) - gamma * E;
retVal(3) = gamma * E - (cullLIRate + sigma) * LI;
retVal(4) = sigma * LI - (mu + cullDIRate) * DI;
retVal(5) = mu * DI + cullLIRate* LI + cullDIRate * DI;
retVal(6) = gR * S * (1 - S / kappa) - mJ * J;
end
You are not passing your defined odeset (options variable) to the ODE45 - solver.
The syntax for the ODE45 is: [T,Y] = ODE45(ODEFUN,TSPAN,Y0,OPTIONS,P1,P2...)
Glad it worked! :)