Plot two-dimensional array as elliptical orbit - matlab

I am attempting to plot an elliptical orbit based on a 2-D position array, beginning at p= [5 0]. The plot charts positions from a timeframe t, here between 0 and 100. The calculation uses the formula F = -(p/||p||)(m*M/(p^2) to approximate acceleration and velocity. The result should look like the following:
This is my current code. It plots a completely different shape. Is the problem in my way of interpreting the force equation?
Any other help and comments are much appreciated.
t = 0; p = [50 0]; v = [0 8]; %Initial conditions
dt = 0.05;
M = 10000; m= 1;
tmax = 100;
figure, hold on
d = 0.001
clf;
while t < tmax
F = -(p./norm(p)).*(m*M./(p*p'));
a = F./m - d*v;
v = v + a*dt;
p = p + v*dt;
t = t + dt;
plot(p(1),t,'o','MarkerSize',0.5);
hold on;
plot(p(2),t,'o','MarkerSize',0.5);
end

You want p(1) in the x axis and p(2) in the y axis, with t as a parameter. So you need to replace the two plot lines by plot(p(1),p(2),'o','MarkerSize',0.5); (keeping hold on):
t = 0; p = [50 0]; v = [0 8]; %Initial conditions
dt = 0.05;
M = 10000; m= 1;
tmax = 100;
figure, hold on
d = 0.001
clf;
while t < tmax
F = -(p./norm(p)).*(m*M./(p*p'));
a = F./m - d*v;
v = v + a*dt;
p = p + v*dt;
t = t + dt;
hold on
plot(p(1),p(2),'o','MarkerSize',0.5); %%% modified line
end

Related

Bifurcation diagram of discrete SIR model in MATLAB

I have a problem with my MATLAB code to display a figure of a Bifurcation diagram of discrete SIR model.
My model is:
S(n+1) = S(n) - h*(0.01+beta*S(n)*I(n)+d*S(n)-gamma*R(n))
I(n+1) = I(n) + h*beta*S(n)*I(n)-h*(d+r)*I(n)
R(n+1) = R(n) + h*(r*I(n)-gamma*R(n));
I tried out the code below but it keeps MATLAB busy for almost 30 mins and showed up no figure.
MATLAB code:
close all;
clear all;
clc;
%Model parameters
beta = 1/300;
gamma = 1/100;
D = 30; % Simulate for D days
N_t = floor(D*24/0.1); % Corresponding no of hours
d = 0.001;
r = 0.07;
%Time parameters
dt = 0.01;
N = 10000;
%Set-up figure and axes
figure;
ax(1) = subplot(2,1,1);
hold on
xlabel ('h');
ylabel ('S');
ax(2) = subplot(2,1,2);
hold on
xlabel ('h');
ylabel ('I');
%Main loop
for h = 2:0.01:3
S = zeros(N,1);
I = zeros(N,1);
R = zeros(N,1);
S(1) = 8;
I(1) = 5;
R(1) = 0;
for n = 1:N_t
S(n+1) = S(n) - h*(0.01+beta*S(n)*I(n)+d*S(n)-gamma*R(n));
I(n+1) = I(n) + h*beta*S(n)*I(n)-h*(d+r)*I(n);
R(n+1) = R(n) + h*(r*I(n)-gamma*R(n));
end
plot(ax(1),h,S,'color','blue','marker','.');
plot(ax(2),h,I,'color','blue','marker','.');
end
Any suggestions?
It was very slow because you were plotting a single value of h versus a vector S which had 7200 points. I assumed that you only want to plot the last value of S versus h. So replacing S with S(end) in the plot command changes everything. You really didn't need to use hold and it's better call plot once for each axis, so here is how I would do it:
beta = 1/300;
gamma = 1/100;
D = 30; % Simulate for D days
N_t = floor(D*24/0.1); % Corresponding no of hours
d = 0.001;
r = 0.07;
%%Time parameters
dt = 0.01;
N = 10000;
%%Main loop
h = 2:0.01:3;
S_end = zeros(size(h));
I_end = zeros(size(h));
for idx = 1:length(h)
S = zeros(N_t,1);
I = zeros(N_t,1);
R = zeros(N_t,1);
S(1) = 8;
I(1) = 5;
R(1) = 0;
for n=1:(N_t - 1)
S(n+1) = S(n) - h(idx)*(0.01+beta*S(n)*I(n)+d*S(n)-gamma*R(n));
I(n+1) = I(n) + h(idx)*beta*S(n)*I(n) - h(idx)*(d+r)*I(n);
R(n+1) = R(n) + h(idx)*(r*I(n)-gamma*R(n));
end
S_end(idx) = S(end);
I_end(idx) = I(end);
end
figure(1)
subplot(2,1,1);
plot(h,S_end,'color','blue','marker','.');
xlabel ('h');
ylabel ('S');
subplot(2,1,2);
plot(h,I_end,'color','blue','marker','.');xlabel ('h');
xlabel ('h');
ylabel ('I');
This now runs in 0.2 seconds on my computer.

MATLAB plotting trajectory

I would like to plot the angular velocity of point B by using MATLAB. However, there is some mistake in my code for angular velocity that I couldn't fix.
The length of the input link OA of the mechanism is r = 50 mm, length of AB is l = 150 mm. Fixed coordinates of point C are xC = d = 80 mm and yC = 0 mm.
Angular velocity of OA is ω = 15 rad/s.
%Full trajectory of B
%Linkage dimensions
clear
r = 50;
l = 150;
xC = 80;
yC = 0;
n = 361; % Number of position calculations
fii = linspace(0,2*pi,n);
omega = 15;
[xA,yA] = pol2cart(fii,r);
d = xA + xC;
alpha = atan(yA./(xC-xA));
lx = l*cos(alpha);
ly = l*sin(alpha);
xB = xA + lx;
yB = yA + ly;
plot(xB,yB) %Plots the trajectory
title('Full trajectory of AB')
% Angular velocity of AB
for ind = 1:n
omegaAB(ind) = (-(r^2-d*r*cos(fii))/(r^2 + d^2 - 2*d*r*cos(fii)))*omega;
end
figure(2)
plot(fii,omegaAB, 'linewidth', 2, 'color', 'red')
title('Angular velocity of AB')
ylabel('\omega_{AB} [1/s]')
xlabel('\phi [rad]')
I think there is just one mistake in your code when you compute alpha:
alpha = atan(yA./(xC-xA));
This gives the following trajectory:
Your code is partially vectorized but you're still looping over ind which is why you are getting matrix dimensions errors. You can either remove the loop and make it completely vectorized or you can make sure that all of your vectors with length n are indexed properly:
for ind = 1:n
omegaAB(ind) = (-(r^2-d*r*cos(fii(ind)))/(r^2 + d(ind)^2 - 2*d*r*cos(fii(ind))))*omega;
end

Finding x intercept in MATLAB

I am trying to find the x intercept of a parabola of a plot using
x0 = interp1(y,x,0)
However because my parabola starts at the origin it returns 0.
How do I find the x intercept that lies away from the origin? At the moment I am estimating by eye-ball.
Code for the plot:
global k g
g = 10;
v0 = 150;
theta = pi/4;
m = 1;
k = 0.001;
tspan = [0 22];
IC = [0; v0*cos(theta); 0; v0*sin(theta)];
[t, oput] = ode45(#dataODE, tspan, IC);
x = oput(:,1);
vx = oput(:,2);
y = oput(:,3);
vy = oput(:,4);
figure(1); clf;
plot(x,y)
where
function [p] = dataODE( t, x)
global k g
p = zeros(4,1);
p(1) = x(2);
p(2) = -k*sqrt(x(2)^2 + x(4)^2)* x(2);
p(3) = x(4);
p(4) = -g -k*sqrt(x(2)^2 + x(4)^2)* x(4);
You could just restrict x and y to only contain the one intercept:
x0 = interp1(y(a:b),x(a:b),0)
but how do you find a and b? One way would be to just use the points before and after y crosses zero (on the way down):
a = find(diff(y > 0) == -1)
b = a+1

Graphically represent density of iterations

Kind all,
I am working in MATLAB and I'm using Monte Carlo techniques to fit a model. Basically, if we assume that my model is a simple function such as
y=m*x^2+c
And that both my parameters m and c vary between 0.5 and 10, I may randomly draw from such a parameter space and obtain each time a new y. If I plot all my realizations of y I obtain something similar to the following figure:
Is there a way to represent the DENSITY of the realizations? I mean, is there a way (instead of plotting all the realizations) to obtain some kind of contour plot that lies between the minimum of my iterations and the maximum for which its color represents the amount of realizations that fall within a certain interval?
Thanks all!
This isn't very pretty, but you could vary the parameters and play with the scatter/plotting, to make it a bit more visually appealing.
Also I assumed a gaussian distribution instead of your random one (totally random coloring will give you a uniform density). Also this code could be optimized for speed.
n = 1000;
l = 100;
x = linspace(1, 10, l);
y = repmat(x.^2, n, 1);
c = repmat(normrnd(1, 1, n, 1), 1, l);
m = repmat(normrnd(1, 1, n, 1), 1, l);
y = y.*m + c;
p = plot(y', '.');
figure; hold on;
for i = 1:l
[N,edges,bin] = histcounts(y(:, i));
density = N./sum(N);
c = zeros(n, 3);
for j = 1:n
c(j, :) = [1-density(bin(j))/max(density), 1-density(bin(j))/max(density), 1-density(bin(j))/max(density)];
end
scatter(ones(n, 1)*x(i),y(:, i),[],c,'filled');
end
Gives
This creates a histogram of y values for every position in x, then calculates the probability density for each y-value and colors in the points. Here, the y-values for every position x are normalized individually, to color the points according to the overall density of the plot you need to renormalize.
You can calculate y for discrete points of x, while setting random values for c and m. Then using hist function you can find a "not-normalized density" of function values for a given x. You can then normalize it to get a real density of the values, so that the overall area under the distribution curve sums up to 1.
In order to visualize it, you construct a mesh grid [X, Y] along the values of x and y and put the density values as Z. Now you can either plot the surf or its contour plot.
Here is the code:
clear;
n = 1000000; %number of simulation steps
%parameter ranges
m_min = 0.5; m_max = 10;
c_min = 0.5; c_max = 10;
%x points
x_min = 1; x_max = 4; x_count = 100;
x = linspace(x_min, x_max, x_count);
x2 = x.^2;
y_min = 0; y_max = m_max*x_max*x_max + c_max; y_step = 1;
m = rand(n, 1)*(m_max - m_min) + m_min;
c = rand(n, 1)*(c_max - c_min) + c_min;
c = repmat(c, 1, x_count);
y = m*x2 + c;
x_step = (x_max- x_min)/(x_count-1);
[X, Y] = meshgrid(x_min:x_step:x_max, y_min-y_step:y_step:y_max+y_step);
Z = zeros(size(X));
bins = y_min:y_step:y_max;
for i=1:x_count
[n_hist,y_hist] = hist(y(:, i), bins);
%add zeros on both sides to close the profile
n_hist = [0 n_hist 0];
y_hist = [y_min-y_step y_hist y_max+y_step];
%normalization
S = trapz(y_hist,n_hist); %area under the bow
n_hist = n_hist/S; %scaling of the bow
Z(:, i) = n_hist';
end
surf(X, Y, Z, 'EdgeColor','none');
colormap jet;
xlim([x_min x_max]);
ylim([y_min y_max]);
xlabel('X');
ylabel('Y');
figure
contour(X,Y,Z, 20);
colormap jet;
colorbar;
grid on;
title('Density as function of X');
xlabel('X');
ylabel('Y');
Another interesting view is a plot of each section depending on the x value:
Here is the code for this plot:
clear;
n = 1000000; %number of simulation steps
%parameter ranges
m_min = 0.5; m_max = 10;
c_min = 0.5; c_max = 10;
%x points
x_min = 1; x_max = 4; x_count = 12;
x = linspace(x_min, x_max, x_count);
x2 = x.^2;
m = rand(n, 1)*(m_max - m_min) + m_min;
c = rand(n, 1)*(c_max - c_min) + c_min;
c = repmat(c, 1, x_count);
y = m*x2 + c;
%colors for the plot
colors = ...
[ 0 0 1; 0 1 0; 1 0 0; 0 1 1; 1 0 1; 0 0.75 0.75; 0 0.5 0; 0.75 0.75 0; ...
1 0.50 0.25; 0.75 0 0.75; 0.7 0.7 0.7; 0.8 0.7 0.6; 0.6 0.5 0.4; 1 1 0; 0 0 0 ];
%container for legend entries
legend_list = cell(1, x_count);
for i=1:x_count
bin_number = 30; %number of histogramm bins
[n_hist,y_hist] = hist(y(:, i), bin_number);
n_hist(1) = 0; n_hist(end) = 0; %set first and last values to zero
%normalization
S = trapz(y_hist,n_hist); %area under the bow
n_hist = n_hist/S; %scaling of the bow
plot(y_hist,n_hist, 'Color', colors(i, :), 'LineWidth', 2);
hold on;
legend_list{i} = sprintf('Plot of x = %2.2f', x(i));
end
xlabel('y');
ylabel('pdf(y)');
legend(legend_list);
title('Density depending on x');
grid on;
hold off;

In matlab, how to use k means to make 30 clusters with circle around each cluster and mark the center?

In matlab, if I have a code which draws a circle and generates 100 random points inside it. I want to use k means to cluster these 100 points into 30 clusters with a circle around each cluster to differentiate between the clusters and i want to mark the center if each cluster.this is the code of the circle and the 100 random points inside it . Any help please ?
%// Set parameters
R =250; %// radius
C = [0 0]; %// center [x y]
N = 100; %// number of points inside circle
%// generate circle boundary
t = linspace(0, 2*pi,100);
x = R*cos(t) + C(1);
y = R*sin(t) + C(2);
%// generate random points inside it
th = 2*pi*rand(N,1);
r = R*randnlimit(0, 1, 0.5, 1, [N 1]);
xR = r.*cos(th) + C(1);
yR = r.*sin(th) + C(2);
%// Plot everything
figure(1), clf, hold on
% subplot(1,N0,1);
plot(x,y,'b');
hold on
text(0,0,'C')
plot(xR,yR,'p')
axis equal
zR=cell(N,1);
for i=1:N
zR{i,1}= [xR(i) yR(i)];
end
m=cell2mat(zR);
function clusterCircle()
%// Set parameters
R = 250; %// radius
C = [0 0]; %// center [x y]
N = 100; %// number of points inside circle
k = 30; %// number of clusters
%// generate circle boundary
t = linspace(0, 2*pi, 100);
x = R*cos(t) + C(1);
y = R*sin(t) + C(2);
%// generate random points inside it
th = 2*pi*rand(N,1);
r = R*randnlimit(0, 1, 0.5, 1, [N 1]);
xR = r.*cos(th) + C(1);
yR = r.*sin(th) + C(2);
%// some simple k-means:
% initial centroids:
% -> use different method, if k > N
% -> can be done more reasonable (e.g. run k-Means for different
% seeds, select seeds equidistant, etc.)
xC = xR(1:k)';
yC = yR(1:k)';
% run:
clusters = zeros(N,1);
clusters_old = ones(N,1);
while sum((clusters - clusters_old).^2) > 0
clusters_old = clusters;
[~,clusters] = min((bsxfun(#minus,xR,xC)).^2 + ...
(bsxfun(#minus,yR,yC)).^2 , [] , 2);
for kIdx = 1:k
xC(kIdx) = mean(xR(clusters==kIdx));
yC(kIdx) = mean(yR(clusters==kIdx));
end
end
%// Plot everything
figure(1);
clf;
hold on;
% -> plot circle and center
text(C(1),C(2),'C');
plot(x,y,'k');
% -> plot clusters
co = hsv(k);
for kIdx = 1:k
% plot cluster points
plot(xR(clusters==kIdx),yR(clusters==kIdx),'p','Color',co(kIdx,:));
% plot cluster circle
maxR = sqrt(max((xR(clusters==kIdx)-xC(kIdx)).^2 + ...
(yR(clusters==kIdx)-yC(kIdx)).^2));
x = maxR*cos(t) + xC(kIdx);
y = maxR*sin(t) + yC(kIdx);
plot(x,y,'Color',co(kIdx,:));
% plot cluster center
text(xC(kIdx),yC(kIdx),num2str(kIdx));
end
axis equal
end
%// creates random numbers, not optimized!
function rn = randnlimit(a,b,mu,sigma,sz)
rn = zeros(sz);
for idx = 1:prod(sz)
searchOn = true;
while searchOn
rn_loc = randn(1) * sigma + mu;
if rn_loc >= a && rn_loc <= b
searchOn = false;
end
end
rn(idx) = rn_loc;
end
end