Vectors must be the same length error - matlab

I'm trying to plot an integral L, with respect to Xdot, but I keep getting vectors must be the same length error, I don't know how to fix it however. My code is shown below. You can see at the bottom, the loop for the sum only goes up to 99, while the x_1 goes up to 100. If I change the loop however, I get an error "index exceeds matrix dimensions"
% The solution for this part is based on the Euler method
f=0; %initializing the force row vector
f_1=0.5; %initializing the first derivative of force
x=1; % intializing the mass displacement%
x_1(1)=0; % initializing the first derivative of mass displacement
t=0; % initializing the time row vector
j=1; % initializing a`enter code here`n index used in iterations
a=0;
b=10;
N=100;
h=(b-a)/N;
for j = 0:N-1
f_2=-1*sin(f); %obtain the second derivative of the force
f_1=f_1+f_2*h; %obtain the first derivative of the force
f=f+f_1*h; % obtain the value of force and concatenate it with
%preceding force row vector the element
x_2=f-0.1*x_1-x-x^3; %obtain the second derivative of the mass displacement
x_1=x_1+x_2*h; % obtain the first derivative of the mass displacement
x=x+x_1*h; % obtain the current value of mass displacement and
%concatenate it with preceding mass displacement row vector the element
t=t+h; % obtain the current value of time and concatenate it with
%preceding time row vector the element
j=j+1; %increment the index iterator by one
v(j)=x;
w(j)=t;
m(j)=x_1
end
sum = 0; %%Trapezoidal method to find L, sum is L, put this at the end of your script
for i = 1:size(m,2)-1
sum = sum + h*(m(i+1)^2+m(i)^2)/2;
L(i) = sum
end
plot (m,L, 'r')

How about you shorten your x by one when plotting?
plot (m(1:end-1),L, 'r')

Related

Encoding system of differential equations into a vector and approximate solutions

I am trying to solve a system of differential equations by the Euler's method. First, I have encoded my system into a vector. Then I pass the initial conditions to the function ode_Euler.
However, there's somehting wrong about my attempt. I am getting this error:
>> nm06p03a
Unable to perform assignment because the size of the left side is 1-by-2 and the size of the right side is 2-by-2.
Error in ode_Euler (line 11)
y(k+1,:)= y(k,:) +h*feval(f,t(k),y(k,:));
Error in nm06p03a (line 12)
tic, [tE,xE]=ode_Euler(f,tspan,x0,N); t_Euler=toc;
This is my code so far:
clear, clf
f=#(t,x)[-x(2)+x(1)*x(2); x(1)-(0.5.*x(1).^2)+(0.5.*x(2).^2)]; %Encoding system of differential equations into a vector
t0=0; tf=10;
tspan=[t0 tf];
N=100;
x0s=[0.2 0]; % A matrix consisting of initial points
for iter=1:size(x0s,1)
x0=x0s(iter,:);
tic, [tE,xE]=ode_Euler(f,tspan,x0,N); t_Euler=toc;
subplot(220+iter),
plot(tE,xE,'r:')
legend('ode_ Euler')
end
Here is the Euler's method:
function [t,y]=ode_Euler(f,tspan,y0,N)
if nargin<4|N<=0, N=100; end
if nargin<3, y0=0; end
h=(tspan(2)-tspan(1))/N;
t=tspan(1)+[0:N]'*h;
y(1,:)=y0(:)'; %make it a row vector
for k=1:N
y(k+1,:)= y(k,:) +h*feval(f,t(k),y(k,:));
end
When I use this other method ode_Heun, I get the same error:
function [t,y]=ode_Heun(f,tspan,y0,N)
if nargin<4|N<=0, N=100; end
if nargin<3, y0=0; end
h=(tspan(2)-tspan(1))/N; % Step-size
t=tspan(1)+[0:N]'*h; % Time vector
y(1,:)=y0(:)'; % make the initial value a row vector
for k=1:N
fk= feval(f,t(k),y(k,:)); y(k+1,:)= y(k,:)+h*fk; % Eq.(6.2.3)
y(k+1,:)= y(k,:) +h/2*(fk +feval(f,t(k+1),y(k+1,:))); % Eq.(6.2.4)
end
Can I get some help to understand the problem with my code?
y(k,:) is a row vector, while the return value of f is a column vector. Per broadcasting rules the sum of a row and a column vector is a matrix as the sum of the matrices of repeated row and column vectors.
This is not very logical in the context of vector and matrix operations, but can make sense in the processing of (finite) sequences of vectors. Unfortunately that distinction is not realized and enforced in the type system.

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.

Problem in 2D heat equation solution using FDM in Matlab

I am trying to solve the 2D time dependent heat equation using finite difference method in Matlab. The code is below:
%Spatial variable on x direction
Lx=1;
delta=0.1;
xmin=-Lx/2;
xmax=Lx/2;
Nx=(xmax-xmin)/delta;
x=linspace(xmin,xmax,Nx);
%Spatial variable on y direction
Ly=1;
delta=0.1;
ymin=-Ly/2;
ymax=Ly/2;
Ny=(ymax-ymin)/delta;
y=linspace(ymin,ymax,Ny);
%Total matrix size
N = (Nx * Ny);
%Time variable
dt=0.002;
tmin=0;
tmax=1;
nt=(tmax-tmin)/dt;
tspan=linspace(tmin,tmax,nt);
%Create a meshgrid
[X,Y] = meshgrid(x,y);
% Defining initial state:
T0=exp(-(X.^2+Y.^2));
%reshape the initial condition to a vector
T_reshape = reshape(T0,N,1);
% Constructing the 1D spatial matrix
A=zeros(N,N);
I = eye(N);
%the diagonal elements
for m=1:N %the number of rows
for n=1:N %the number of columns
if (m==n)
A(m,n)=-2/delta^2;
end
%Boundary conditions: A(1,N)==A(N,1)
if(n==N)&&(m==1)
A(m,n)=1;
end
if(n==1)&&(m==N)
A(m,n)=1;
end
end
end
%the off-diagonal elements
for n=1:N-1
A(n+1,n)=1/delta^2; %the value of each lower off-diagonal elements
end
for n=2:N
A(n-1,n)=1/delta^2; %the value of each upper off-diagonal element
end
%create the 2D matrix
B = kron(A,I)+kron(I,A);
% Solve the equation
[Time,Tem]=ode45('dTDistribution',tspan,T_reshape,[],B,delta);
The function that is being called here is as following:
%Define the function
function dT=dTDistribution(tspan,T_reshape,dummy,B,delta)
dT = B.*T_reshape;
end
My problem is that the dimension of my matrix B is different than the dimensions of the initial condition T_reshape, therefore, the multiplication of B.*T_reshape won't be possible. I'm wondering how can I change the dimension of T_reshape to make the multiplication valid. Hope anyone could help.
Thank you.
Thank you for looking at my problem, but I have figured out the mistake in the code. Since A is the 1D matrix, then its size should be either (Nx,Nx) or (Ny,Ny) and then when taking the tensor product to get B the 2D matrix its size will be (N,N). However in the code, A has the size of (N,N) and as a result B is blowing up making the multiplication afterwards not possible.
Thanks.

rewrite the seqneighjoin function in matlab

I have the task to rewrite the seqneighjoin function in matlab by adding the frequency of all the sequences. After searching, I understand that this function returns a phylogenetic tree object obtained by seqences neighbor joinn method from the wiki http://en.wikipedia.org/wiki/Neighbor_joining
Now, I have the following two questions.
(1): what is the data structure of this phytree object obtained by this function? How to express it? For example, for the similar linkage function, it also returns a phylogenetic tree, and the data structure is very clear there, i.e., it is a matrix with three columns, where the i-th column indicates which nodes are combined and the corresponding distance when they are combined. Thanks very much for your time and attention.
(2): Based on wiki, how am I supposed to add frequency to the function seqneighjoin? I am totally confused.
Thanks so much for your time and attention. I truly appreciate that.
EDIT: the following is the code.
function z = seqneighjoin(D_all, freq)
n = size (D_all, 2);
m=(1+sqrt(8*n+1))/2;
z=zeros(m-1,3);
q=zeros(m,m);
str = zeros (m,m);
% initialize the distance matrix d
d=ones(m,m);
d(tril(d,-1)==1)=D_all;
d(triu(d,1)==1)=D_all;
d(eye(m,m)==1) = 1:m; % the diagonal entries of the matrix d is the indices of the clusters
% initialize the matrix str
for r=1:m
for c=1:m
str(r,c)=freq(r)*freq(c)*d(r,c);
str(c,r)=freq(r)*freq(c);
end
end
% loop through for m-1 times to create the matrix z
for k = 1:m-1
% initialize (for the first time) or update (for all other times)
% the matrix q
colSum = sum(d, 1);
rowSum=sum(d,2);
a=size(colSum, 2);
colSumM=colSum(ones(a,1),:);
rowSunM=rowSum(:,ones(1,a));
q=(a-2)*d-colSumM-rowSumM;
% find the minimum element in the matrix q
u=min(q);
v=min(u);
[i,j]=find(q==v);
r=i(1);
c=j(1);
% combine d(r,r) and d(c,c) to get a new node m+k
z(k,:)=[d(r,r), d(c,c), v];
% calculate the distance between the new node m+k and all other node
% which are not m+k
d(r,:) = (d(r,:) + d(c,:) - d(r,c) )/2;
d(r,r) = m+k;
d(c,:)=[]; d(:,c)=[];
end
Here, D_all is the vector representation of a distance matrix returned by the seqpdist function in matlab, and freq is the vector indicating the frequency of all the sequences.

matrix dimensions wont agree when elements match/matlab

I am having a problem at the final calculation of my code, the very last part, where log is the natural log, I need RD=facs.*log(log(facs)) to divide sigmafac, or robin=sigmafac./RD. My RD goes from 1 to 100, so does my sigmafac. why is there a matrix dimension mismatch?
I want the corresponding number (numbas) of RD to divide the correspoding number of sigmafac, the all have the same dimension, so I do not see where the problem is coming from. I realize that RD(1)=-inf, is that is what causing the problem? and how do I fix it?
code:
n=100;
primlist=2; % starting the prime number list
for numba=1:n;
if mod(2+numba,primlist)~=0
primlist=[primlist;2+numba]; %generating the prime number list
end
end
fac=1; %initializing the factorials
RD=0;
for numbas=2:n
%preallocating vectors for later use
prims=zeros(size(primlist));
pprims=zeros(size(primlist));
pow=prims;
for i=1:length(primlist) % identifying each primes in the primlist
for k=1:10
if mod(numbas,primlist(i).^k)==0
prims(i)=primlist(i); % sum of all the powers of prims, such that prims divide numbas
pow(i)=k; % collecting the exponents of primes
end
end
if primlist(i)<=numbas
pprims(i)=primlist(i); % primes less than or equal to numbas
end
end
% converting column vectors to row vector
PPRIMS=pprims';
PRIMS=prims';
POW=pow';
%Creating the vectors
PLN(numbas,:)=PPRIMS; % vector of primes less than or equal to number
PPV(numbas,:)=PRIMS; % prime divisor vector
PVE(numbas,:)=POW; % highest power of each primes for every number
RVE=cumsum(PVE); % the cummulative sum of the exponents
RVE(RVE~=0)=RVE(RVE~=0)+1; %selects each non zero element then add 1
%factorial
fac=fac*numbas;
facs(numbas)=fac; %storing the factorials
if facs==1
RD==1; % log(log(facs1))) does not exist
else RD=facs.*log(log(facs));
end
end
% setting up sum of divisor vector
NV=PLN.^RVE-1; % numerator part of sum of divisors vector
DV=PLN-1; % denominator part of sum of divisors
NV(NV==0)=1; % getting rid of 0 for elementwise product
DV(DV==-1)=1; % getting rid of -1 for elementwise product
sigmafac=prod(NV,2)./prod(DV,2); %sum of divisors
robin=(sigmafac)./(RD)
Whenever you get such an error, your first check should be to test
size(sigmafac)
size(RD)
In this case, you'll get
ans =
100 1
ans =
1 100
So they are NOT the same size. You need to take the transpose of one or the other and then your division will work fine.
Your sigmafac is 100x1 but your RD is 1x100 which is producing the error. If you want this to work just change
robin=(sigmafac)./(RD)
to
robin=(sigmafac)'./(RD)
This will make sigmafac a 1x100 (transpose) and then your vectors will have the same dimension and you will be able to do the division.