Plot Population growth function with different values of b using for loop in Matlab - matlab

I need to plot population growth model with different values of b
where b>d
and b=d
using for loops. Both results should be visible on the same graph with different colors.
Here is my function and intial value, but I am not getting how to get the plot .
[T,Y]=ode45(H,[0:1:time],[N0]);
Intitial value
b= 0.1 0.001
d=0.001
N0=400````
I need two line for each b on the same plot.
```***
Intitial value
b= 0.1 0.001;
d=0.001;
N0=400;
H=#(t,N)[b*N-d*N];
[T,Y]=ode45(H,[0:1:time],[N0]);
plot(T,Y)
***```

First, you need to put the code in a proper format, now you copied the initial value block twice (I guess you had some issue putting the code format. I hope you can focus on that when asking new questions.
The current code gives an error on the definition of b as you did not define it as a vector. To have two lines, it is best to store the output Y as a matrix of two columns (each column being one vector). MATLAB then outputs each column as a line in the plot.
The following code solves your issue:
% Initial value
b = [0.1, 0.001];
d = 0.001;
N0= 400;
simTime = 0:1:300;
% Preallocate output for the loop
Y = zeros(length(simTime), length(b));
% Run for loop
for i = 1:length(b)
b_i = b(i);
H=#(t,N)[b_i*N-d*N];
[T,y]=ode45(H, simTime, [N0]);
Y(:,i) = y;
end
% Plot output
plot(T,Y)

Related

how to replace the ode45 method with the runge-kutta in this matlab?

I tried everything and looked everywhere but can't find any solution for my question.
clc
clear all
%% Solving the Ordinary Differential Equation
G = 6.67408e-11; %Gravitational constant
M = 10; %Mass of the fixed object
r = 1; %Distance between the objects
tspan = [0 100000]; %Time Progression from 0 to 100000s
conditions = [1;0]; %y0= 1m apart, v0=0 m/s
F=#(t,y)var_r(y,G,M,r);
[t,y]=ode45(F,tspan,conditions); %ODE solver algorithm
%%part1: Plotting the Graph
% plot(t,y(:,1)); %Plotting the Graph
% xlabel('time (s)')
% ylabel('distance (m)')
%% part2: Animation of Results
plot(0,0,'b.','MarkerSize', 40);
hold on %to keep the first graph
for i=1:length(t)
k = plot(y(i,1),0,'r.','MarkerSize', 12);
pause(0.05);
axis([-1 2 -2 2]) %Defining the Axis
xlabel('X-axis') %X-Axis Label
ylabel('Y-axis') %Y-Axis Label
delete(k)
end
function yd=var_r(y,G,M,r) %function of variable r
g = (G*M)/(r + y(1))^2;
yd = [y(2); -g];
end
this is the code where I'm trying to replace the ode45 with the runge kutta method but its giving me errors. my runge kutta function:
function y = Runge_Kutta(f,x0,xf,y0,h)
n= (xf-x0)/h;
y=zeros(n+1,1);
x=(x0:h:xf);
y(1) = y0;
for i=1:n
k1 = f(x(i),y(i));
k2= f(x(i)+ h/2 , y(i) +h*(k1)/2);
y(i+1) = y(i)+(h*k2);
end
plot(x,y,'-.M')
legend('RKM')
title ('solution of y(x)');
xlabel('x');
ylabel('y(x)')
hold on
end
Before converting your ode45( ) solution to manually written RK scheme, it doesn't even look like your ode45( ) solution is correct. It appears you have a gravitational problem set up where the initial velocity is 0 so a small object will simply fall into a large mass M on a line (rectilinear motion), and that is why you have scalar position and velocity.
Going with this assumption, r is something you should be calculating on the fly, not using as a fixed input to the derivative function. E.g., I would have expected something like this:
F=#(t,y)var_r(y,G,M); % get rid of r
:
function yd=var_r(y,G,M) % function of current position y(1) and velocity y(2)
g = (G*M)/y(1)^2; % gravity accel based on current position
yd = [y(2); -g]; % assumes y(1) is positive, so acceleration is negative
end
The small object must start with a positive initial position for the derivative code to be valid as you have it written. As the small object falls into the large mass M, the above will only hold until it hits the surface or atmosphere of M. Or if you model M as a point mass, then this scheme will become increasingly difficult to integrate correctly because the acceleration becomes large without bound as the small mass gets very close to the point mass M. You would definitely need a variable step size approach in this case. The solution becomes invalid if it goes "through" mass M. In fact, once the speed gets too large the whole setup becomes invalid because of relativistic effects.
Maybe you could explain in more detail if your system is supposed to be set up this way, and what the purpose of the integration is. If it is really supposed to be a 2D or 3D problem, then more states need to be added.
For your manual Runge-Kutta code, you completely forgot to integrate the velocity so this is going to fail miserably. You need to carry a 2-element state from step to step, not a scalar as you are currently doing. E.g., something like this:
y=zeros(2,n+1); % 2-element state as columns of the y variable
x=(x0:h:xf);
y(:,1) = y0; % initial state is the first 2-element column
% change all the scalar y(i) to column y(:,i)
for i=1:n
k1 = f(x(i),y(:,i));
k2= f(x(i)+ h/2 , y(:,i) +h*(k1)/2);
y(:,i+1) = y(:,i)+(h*k2);
end
plot(x,y(1,:),'-.M') % plot the position part of the solution
This is all assuming the f that gets passed in is the same F you have in your original code.
y(1) is the first scalar element in the data structure of y (this counts in column-first order). You want to generate in y a list of column vectors, as your ODE is a system with state dimension 2. Thus you need to generate y with that format, y=zeros(length(x0),n+1); and then address the list entries as matrix columns y(:,1)=x0 and the same modification in every place where you extract or assign a list entry.
Matlab introduce various short-cuts that, if used consequently, lead to contradictions (I think the script-hater rant (german) is still valid in large parts). Essentially, unlike in other systems, Matlab gives direct access to the underlying data structure of matrices. y(k) is the element of the underlying flat array (that is interpreted column-first in Matlab like in Fortran, unlike, e.g., Numpy where it is row-first).
Only the two-index access is to the matrix with its dimensions. So y(:,k) is the k-th matrix column and y(k,:) the k-th matrix row. The single-index access is nice for row or column vectors, but leads immediately to problems when collecting such vectors in lists, as these lists are automatically matrices.

plot a curve for each parameter in a figure by recalling mat file

I am doing something similar to the following example:
t=linspace(0,1);
z=rand(1);
theta=pi*rand(1);
a_range=[1,2,3];
for nplot=1:3
a=a_range(nplot);
x=z*t.^2+a*sin(theta);
end
fname=['xsin.mat'];
save(fname)
the parameter a has three different values. For each value of a, I want to plot the function in one single figure. So at the end I will have three figures. I can do it using subplot but this will generate three plots in one figure which is not what I want.
In a new script, I load the mat file:
load('xsin.mat')
for nplot=1:3
figure(nplot)
plot(t,x)
end
but I get one figure not three as I should have. I mean for a=1, I should plot the curve in figure 1; for a=2, I should plot the curve in figure 2 and so on. How can I do this? Any help is appreciated.
You are overwriting x in every iteration; you could modify your code by saving each x for the respective nplot in a separate column of a matrix X (with minimal changes to your code):
t=linspace(0,1);
z=rand(1);
theta=pi*rand(1);
a_range=[1,2,3];
X = NaN(length(t), length(a_range)); % Create matrix to hold x values
for nplot=1:3
a = a_range(nplot);
x = z * t.^2 + a * sin(theta);
X(:,nplot) = x; % Store x in column of X
end
fname=['xsin.mat'];
save(fname)
Then, to create the figures:
load('xsin.mat')
for nplot=1:3
x = X(:,nplot); % Retrieve x from column of X
figure(nplot)
plot(t,x)
end

matlab plotting a family of functions

Generate a plot showing the graphs of
y=(2*a+1)*exp(-x)-(a+1)*exp(2*x)
in the range x ∈ <-2, 4> for all integer values of a between -3 and 3
I know how to make typical plot for 2 values and set a range on the axes, but how to draw the graph dependent on the parameter a?
To elaborate on Ben Voigt's comment: A more advanced technique would be to replace the for-loop with a call to bsxfun to generate a matrix of evaluations of M(i,j) = f(x(i),a(j)) and call plot with this matrix. Matlab will then use the columns of the matrix and plot each column with individual colors.
%%// Create a function handle of your function
f = #(x,a) (2*a+1)*exp(-x)-(a+1)*exp(2*x);
%%// Plot the data
x = linspace(-2, 4);
as = -3:3;
plot(x, bsxfun(f,x(:),as));
%%// Add a legend
legendTexts = arrayfun(#(a) sprintf('a == %d', a), as, 'uni', 0);
legend(legendTexts, 'Location', 'best');
You could also create the evaluation matrix using ndgrid, which explicitly returns all combinations of the values of x and as. Here you have to pay closer attention on properly vectorizing the code. (We were lucky that the bsxfun approach worked without having to change the original f.)
f = #(x,a) (2*a+1).*exp(-x)-(a+1).*exp(2*x); %// Note the added dots.
[X,As] = ndgrid(x,as);
plot(x, f(X,As))
However for starters, you should get familiar with loops.
You can do it using a simple for loop as follows. You basically loop through each value of a and plot the corresponding y function.
clear
clc
close all
x = -2:4;
%// Define a
a = -3:3;
%// Counter for legend
p = 1;
LegendText = cell(1,numel(a));
figure;
hold on %// Important to keep all the lines on the same plot.
for k = a
CurrColor = rand(1,3);
y= (2*k+1).*exp(-x)-(k+1).*exp(2.*x);
plot(x,y,'Color',CurrColor);
%// Text for legend
LegendText{p} = sprintf('a equals %d',k);
p = p+1;
end
legend(LegendText,'Location','best')
Which gives something like this:
You can customize the graph as you like. Hope that helps get you started!

Symbolic gradient differing wildly from analytic gradient

I am trying to simulate a network of mobile robots that uses artificial potential fields for movement planning to a shared destination xd. This is done by generating a series of m-files (one for each robot) from a symbolic expression, as this seems to be the best way in terms of computational time and accuracy. However, I can't figure out what is going wrong with my gradient computation: the analytical gradient that is being computed seems to be faulty, while the numerical gradient is calculated correctly (see the image posted below). I have written a MWE listed below, which also exhibits this problem. I have checked the file generating part of the code, and it does return a correct function file with a correct gradient. But I can't figure out why the analytic and numerical gradient are so different.
(A larger version of the image below can be found here)
% create symbolic variables
xd = sym('xd',[1 2]);
x = sym('x',[2 2]);
% create a potential function and a gradient function for both (x,y) pairs
% in x
for i=1:size(x,1)
phi = norm(x(i,:)-xd)/norm(x(1,:)-x(2,:)); % potential field function
xvector = reshape(x.',1,size(x,1)*size(x,2)); % reshape x to allow for gradient computation
grad = gradient(phi,xvector(2*i-1:2*i)); % compute the gradient
gradx = grad(1);grady=grad(2); % split the gradient in two components
% create function file names
gradfun = strcat('GradTester',int2str(i),'.m');
phifun = strcat('PotTester',int2str(i),'.m');
% generate two output files
matlabFunction(gradx, grady,'file',gradfun,'outputs',{'gradx','grady'},'vars',{xvector, xd});
matlabFunction(phi,'file',phifun,'vars',{xvector, xd});
end
clear all % make sure the workspace is empty: the functions are in the files
pause(0.1) % ensure the function file has been generated before it is called
% these are later overwritten by a specific case, but they can be used for
% debugging
x = 0.5*rand(2);
xd = 0.5*rand(1,2);
% values for the Stackoverflow case
x = [0.0533 0.0023;
0.4809 0.3875];
xd = [0.4087 0.4343];
xp = x; % dummy variable to keep x intact
% compute potential field and gradient for both (x,y) pairs
for i=1:size(x,1)
% create a grid centered on the selected (x,y) pair
xGrid = (x(i,1)-0.1):0.005:(x(i,1)+0.1);
yGrid = (x(i,2)-0.1):0.005:(x(i,2)+0.1);
% preallocate the gradient and potential matrices
gradx = zeros(length(xGrid),length(yGrid));
grady = zeros(length(xGrid),length(yGrid));
phi = zeros(length(xGrid),length(yGrid));
% generate appropriate function handles
fun = str2func(strcat('GradTester',int2str(i)));
fun2 = str2func(strcat('PotTester',int2str(i)));
% compute analytic gradient and potential for each position in the xGrid and
% yGrid vectors
for ii = 1:length(yGrid)
for jj = 1:length(xGrid)
xp(i,:) = [xGrid(ii) yGrid(jj)]; % select the position
Xvec = reshape(xp.',1,size(x,1)*size(x,2)); % turn the input into a vector
[gradx(ii,jj),grady(ii,jj)] = fun(Xvec,xd); % compute gradients
phi(jj,ii) = fun2(Xvec,xd); % compute potential value
end
end
[FX,FY] = gradient(phi); % compute the NUMERICAL gradient for comparison
%scale the numerical gradient
FX = FX/0.005;
FY = FY/0.005;
% plot analytic result
subplot(2,2,2*i-1)
hold all
xlim([xGrid(1) xGrid(end)]);
ylim([yGrid(1) yGrid(end)]);
quiver(xGrid,yGrid,-gradx,-grady)
contour(xGrid,yGrid,phi)
title(strcat('Analytic result for position ',int2str(i)));
xlabel('x');
ylabel('y');
subplot(2,2,2*i)
hold all
xlim([xGrid(1) xGrid(end)]);
ylim([yGrid(1) yGrid(end)]);
quiver(xGrid,yGrid,-FX,-FY)
contour(xGrid,yGrid,phi)
title(strcat('Numerical result for position ',int2str(i)));
xlabel('x');
ylabel('y');
end
The potential field I am trying to generate is defined by an (x,y) position, in my code called xd. x is the position matrix of dimension N x 2, where the first column represents x1, x2, and so on, and the second column represents y1, y2, and so on. Xvec is simply a reshaping of this vector to x1,y1,x2,y2,x3,y3 and so on, as the matlabfunction I am generating only accepts vector inputs.
The gradient for robot i is being calculated by taking the derivative w.r.t. x_i and y_i, these two components together yield a single derivative 'vector' shown in the quiver plots. The derivative should look like this, and I checked that the symbolic expression for [gradx,grady] indeed looks like that before an m-file is generated.
To fix the particular problem given in the question, you were actually calculating phi in such a way that meant you doing gradient(phi) was not giving the correct results compared to the symbolic gradient. I'll try and explain. Here is how you created xGrid and yGrid:
% create a grid centered on the selected (x,y) pair
xGrid = (x(i,1)-0.1):0.005:(x(i,1)+0.1);
yGrid = (x(i,2)-0.1):0.005:(x(i,2)+0.1);
But then in the for loop, ii and jj were used like phi(jj,ii) or gradx(ii,jj), but corresponding to the same physical position. This is why your results were different. Another problem you had was you used gradient incorrectly. Matlab assumes that [FX,FY]=gradient(phi) means that phi is calculated from phi=f(x,y) where x and y are matrices created using meshgrid. You effectively had the elements of phi arranged differently to that, an so gradient(phi) gave the wrong answer. Between reversing the jj and ii, and the incorrect gradient, the errors cancelled out (I suspect you tried doing phi(jj,ii) after trying phi(ii,jj) first and finding it didn't work).
Anyway, to sort it all out, on the line after you create xGrid and yGrid, put this in:
[X,Y]=meshgrid(xGrid,yGrid);
Then change the code after you load fun and fun2 to:
for ii = 1:length(xGrid) %// x loop
for jj = 1:length(yGrid) %// y loop
xp(i,:) = [X(ii,jj);Y(ii,jj)]; %// using X and Y not xGrid and yGrid
Xvec = reshape(xp.',1,size(x,1)*size(x,2));
[gradx(ii,jj),grady(ii,jj)] = fun(Xvec,xd);
phi(ii,jj) = fun2(Xvec,xd);
end
end
[FX,FY] = gradient(phi,0.005); %// use the second argument of gradient to set spacing
subplot(2,2,2*i-1)
hold all
axis([min(X(:)) max(X(:)) min(Y(:)) max(Y(:))]) %// use axis rather than xlim/ylim
quiver(X,Y,gradx,grady)
contour(X,Y,phi)
title(strcat('Analytic result for position ',int2str(i)));
xlabel('x');
ylabel('y');
subplot(2,2,2*i)
hold all
axis([min(X(:)) max(X(:)) min(Y(:)) max(Y(:))])
quiver(X,Y,FX,FY)
contour(X,Y,phi)
title(strcat('Numerical result for position ',int2str(i)));
xlabel('x');
ylabel('y');
I have some other comments about your code. I think your potential function is ill-defined, which is causing all sorts of problems. You say in the question that x is an Nx2 matrix, but you potential function is defined as
norm(x(i,:)-xd)/norm(x(1,:)-x(2,:));
which means if N was three, you'd have the following three potentials:
norm(x(1,:)-xd)/norm(x(1,:)-x(2,:));
norm(x(2,:)-xd)/norm(x(1,:)-x(2,:));
norm(x(3,:)-xd)/norm(x(1,:)-x(2,:));
and I don't think the third one makes sense. I think this could be causing some confusion with the gradients.
Also, I'm not sure if there is a reason to create the .m file functions in your real code, but they are not necessary for the code you posted.

evaluating a self made function for a cector and then plotting in matlab

i have created a function that represents a triangle sign.
this function does not work on vectors. i want to evaluate a vector x:
x=[-2:0.01:2]
and save the answer in vector y, for this purpose i came up with the following code:
for i=1:400, y(i) = triangle(x(i))
after i got the ans i plotted is using plot. in this case it worked ok but i am interested on observing the influence of time shifting and shrinking so when i try to use lets say:
for i=1:200, y(i) = triangle(x(2*i))
i get a vector y not the same length as vector x and i cant even plot them... is there any easy way to achieve it? and how should i plot the answer?
here is my function:
function [ out1 ] = triangle( input1 )
if abs(input1) < 1,
out1 = 1 - abs(input1);
else
out1 = 0;
end
end
y is a different length in each for loop because each loop iterated a different number of times. In the example below, I use the same for loops and plot y2 with the corresponding values of x. i is already defined in matlab so I've changed it to t in the example below.
clear all
x=[-2:0.01:2];
for t=1:400
y(t) = triangle(x(t));
end
for t=1:200
y2(t) = triangle(x(2*t));
end
Or, if you want to see y2 plotted over the same range you can increase the size of x:
clear all
x=[-2:0.01:8];
for t=1:400
y(t) = triangle(x(t));
end
for t=1:400
y2(t) = triangle(x(2*t));
end
plot(x(1:length(y)),y,'r')
hold on
plot(x(1:length(y2)),y2,'b')