Matlab can't solve the collocation equations. Encountered a singular jacobian - matlab

function bvp()
solinit = bvpinit(linspace(0,1,10),[0, 0.3, 0, 0.5]);
sol = bvp4c(#myprojec,#mybounds, solinit);
plot(sol.x,sol.y(1,:),'.');
%Hold on can be used to suspend the graph so as to plot another graph on
%the same axis with different parameters
xlabel('\c');
ylabel('\theta');
function dydx = myprojec(x,y)
% enter the parameter
% x represents c
% y(i) represents f,theta
% f = y(1), f' = y(2), theta = y(4), theta' = y(5)
% star (*) replaced by 0
% infinity =5
% Max infinity = 10
% B = input('input the value of Beta:');
B = 5;
% M = input('input the value of M:');
M = 1;
% Km = input('input the value of Km:');
Km = 1.5;
% Br = input ('input the value of Br:');
Br = 12;
dydx=[ y(2);(B^2-M)*y(1)-Km;y(4);Br*((M- B^2)*y(1)-y(2)^2)];
% Now d bcs
function res = mybounds(ya,yb)
% where to denote initial values of y at zero(0)
% finf denotes initial vlue of y at infinity (5 or 10)
% n = input('input the value of n:');
res = [ya(1)
yb(1)-1
ya(4)
yb(4)-(1)];
The error I got is that Matlab cannot solve the collocation equations. A singular Jacobian encountered. I would appreciate your suggestions.

Related

Applying ode15s to solve a spatial discretization using finite difference for multiple variables

I am trying to run the following ode15s with three variables, C1, q1 and phi1. However, I keep on receiving the following warning:
Warning: Failure at t=1.163115e-13. Unable to meet integration
tolerances without reducing the step size below the smallest value
allowed (4.038968e-28) at time t.
The simulation runs correctly if I do not include the dq1_over_dt term in the ode15s solver, so issue is definitely there. If the simulation runs correctly, the result is a Y matrix of 486X360 dimensions.
Any practical advice is welcomed.
%-------------------------------------------------------------------------%
% Chromatography Simulation 1
% By Santiago Taguado
% Chromatogram Simulation
%-------------------------------------------------------------------------%
close all; clear variables; clc;
% Global variables (meaning reported below)
global u Dax N h isopar K eps v Dphi phi_in Cin mod_gradient
%-------------------------------------------------------------------------%
% Chromatography with variable boundaries
%-------------------------------------------------------------------------%
L = 25; % Length (cm)
Q = 2.513; % Flow Rate (mL/min)
D = 0.8; % Diameter of Column (cm)
S = pi()*(D/2)^2; % Column Cross Section (cm2)
eps = 0.7; % Void Fraction
u = Q/S; % superficial velocity (cm/min)
v = u/eps; %intersitial velocity
Dax = 0.039/u; % axial dispersion (cm)
Dphi = 0.039/u; % axial dispersion (cm)
N = 120; % number of grid points (-)
alpha1 = 149421.036; % Parameter 1
alpha2 = -3.054; % Sensibility variable 1
alpha3 = 500; % Parameter 2
alpha4 = 500; % Sensibility variable 2
isopar = [alpha1 alpha2 alpha3 alpha4];
K = 3; % Linear Driving Force
eps = 0.7; % Void Fraction
%-------------------------------------------------------------------------%
% Preprocessing
%-------------------------------------------------------------------------%
h = L/(N-1); % grid spacing (cm)
nt = 3000; % number of time steps
t_load = 8; % loading time,min
t_tot = 49;
dt = t_tot/(nt-1);
%-------------------------------------------------------------------------%
% Solution via ode15s solver for Loading Phase
%-------------------------------------------------------------------------%
C1 = [0; zeros(N-1,1)]; % Initial Conditions
q1 = [0;zeros(N-1,1)];
phi = [0;zeros(N-1,1)];
Y = [C1;q1;phi];
phi_in = 0.02;
Cin = 1.085; % initial concentration (mg/mL)
mod_gradient = 0;
tspan = 0:dt:t_load;
[t, Y] = ode15s(#ODESystem, tspan, Y);
%-------------------------------------------------------------------------%
% ODE system
%-------------------------------------------------------------------------%
function dY = ODESystem(t,Y)
global u Dax N h Dphi v phi_in Cin mod_gradient eps isopar
C1 = Y(1:N);
q1 = Y(N+1:N*2);
phi = Y(N*2+1:N*3);
dC1_over_dt = zeros(N,1);
dq1_over_dt = zeros(N,1);
dphi_over_dt = zeros(N,1);
% Boundary # x=0
dC1_over_dt(1) = (Cin(1) + Dax/u/h*C1(2))/(1+Dax/u/h);
dq1_over_dt(1) = 0;
dphi_over_dt(1) = (phi_in + mod_gradient*t + Dphi/v/h*phi(2))/(1+Dphi/v/h);
% Internal points
for i=2:N-1
% Isotherm Value
H1 = isopar(1)*phi(i)^isopar(2); H1(isinf(H1)) = 0;
q_inf1 = isopar(3)*H1/(1+H1); q_inf1(isnan(q_inf1)) = 0;
denom = 1 + C1(i)*H1/q_inf1; denom(isnan(denom)) = 1;
qstar1 = C1(i)*H1/denom;
dq1_over_dt(i) = eps/(1-eps)*(qstar1 - q1(i));
% Species, 1
dC1_over_dx = (C1(i-1)-C1(i))/(h);
d2C1_over_dx2 = (C1(i+1)-2.*C1(i)+C1(i-1))/h^2;
% Modifier,1
dphi_over_dx = (phi(i-1)-phi(i))/(h);
d2phi_over_dx2 = (phi(i+1)-2.*phi(i)+phi(i-1))/h^2;
dphi_over_dt(i) = u*dphi_over_dx + ...
Dphi*d2phi_over_dx2;
dC1_over_dt(i) = v*dC1_over_dx + Dax*d2C1_over_dx2;
end
% Boundary # x=L
dC1_over_dt(N) = dC1_over_dt(N-1);
dq1_over_dt(N) = dq1_over_dt(N-1);
dphi_over_dt(N) = dphi_over_dt(N-1);
dY = [dC1_over_dt;dq1_over_dt;dphi_over_dt];
end

NaN response in ode45 Matlab

I'm using ode45 to solve position variables against time, but after the initial conditions, I only get NaN response for all the 4 variables.
Here is my function code:
function dxdt = ode(t,x)
global m b a x_teta k_lin k_tor Ip U Pinf gama
m = 5; % Mass
b = 1.5; % Semi-chord
a = 0; % Reference point to displacement -1 <= a <= 1
x_teta = 0; % Static unbalanced parameter -> e - a
k_lin = 10; % Linear stiffness
k_tor = 10; % Torsional stiffness
Ip = 5; % Inertia
U = 10; % Velocity
Pinf = 1.184; % Air density
gama = 2*pi*Pinf*b*U^2; % Constant numbers from L
% x(1) = h % x(2) = dh/dt % x(3) = teta % x(4) = dteta/dt
dxdt = [x(2);(-gama*x(3)-k_lin*x(1)-m*b*x_teta*(1/Ip)*(b*(.5+a)*gama*x(3)-k_tor*x(3)))/(m+(m^2*b^2*x_teta^2)/Ip);x(4);(-gama*x(3)-k_lin*x(1)-(b*(.5+a)*gama*x(3)-k_tor*x(3))/(b*x_teta))/(m*b*x_teta-(Ip)/(b*x_teta))]
And the implementation code:
tspan = 0:.01:20; x0 = [60; 0; 5; 0];
[t,x] = ode45(#ode,tspan,x0)
I suspect there's something wrong about the physics for setting up this ODE.
In this expression for the 4th element of dxdt, there is a division by x_teta, which is set to zero.
dxdt(4) = (-gama*x(3)-k_lin*x(1)-(b*(.5+a)*gama*x(3)-k_tor*x(3))/(b*x_teta))/(m*b*x_teta-(Ip)/(b*x_teta))
This division by zero leads to one NaN, and propagates to the other elements as the ODE is iteratively solved.

Finite difference - wave equation - boundary conditions and setting things up

I am working on a project that has to do with solving the wave equation in 2D (x, y, t) numericaly using the central difference approximation in MATLAB with the following boundary conditions:
The general assembly formula is:
I understand some of the boundary conditions (BC), like
du/dy=0 at j=m,
,
but I am not sure how to implement these boundary conditions in MATLAB.
A friend has given me these equations:
Here is my try with the MATLAB code,
but I am not able to progress any further:
% The wave function
% Explicit
% Universal boundary conditions for all 3 cases:
% u=0 at t=0
% du/dt=0 at t=0
% Case 1 boundary conditions
% At x=0, u=2sin(2*pi*t/5);
% At y=0, du/dy=0;
% At y=2, du/dy=0;
% At x=5, du/dx=0;
% u=0 and du/dt=0 at t=0;
%-------------------------------------------------------------------------%
% Setting up
clc; clear all; close all;
% length, time, height
L = 5; % [m]
h = 2; % [m]
T = 10; % [s]
% Constants
c_x = 1; % arbitrary
c_y = 1; % arbitrary
dx = 0.1; % <x> increment
dy = 0.1; % <y> increment
dt = 0.1; % time increment
nx = L/dx + 1; % number of <x> samples
ny = h/dy + 1; % number of <y> samples
nt = T/dt + 1; % number of time samples
t(:,1) = linspace(0, T, nt);
theta_x = c_x*(dt^2)/(dx^2);
theta_y = c_y*(dt^2)/(dy^2);
% theta_x = theta_y
theta = theta_x;
%-------------------------------------------------------------------------%
% The matrix
U = zeros(nt, nx, ny);
% Setting up the <U> matrix with the boundary conditions - case 1
U(1, :, :) = 0; % U=0 at t=0
for tt=1:nt % U=2sin(2pi/5*t) at x=0
for jj=1:ny
U(tt, 1, jj)=2*sin(2*pi/5.*t(tt));
end
end
for it=2:t
for ix=2:nx-1
for iy=2:ny-1
% Boundary conditions
% General case (internal):
U1 = -U(it-1, ix, iy);
U2 = 2*(1-2*theta)*u(it, ix, iy);
U3 = theta*U(it, ix-1, iy);
U4 = theta*U(it, ix+1, iy);
U5 = theta*U(it, ix, iy-1);
U6 = theta*U(it, ix, iy+1);
end
end
end
The general assembly formula you have kind of applies to the boundaries as well.
The complication is that when you apply the formula when j = 1 and j = m, you have j = 0 and j = m+1 term that are off of your grid.
To ameliorate this problem, boundary conditions give you a relationship between the points off the grid and on the grid.
As you have indicated, the dudy = 0 condition has given you the relation that u(i,m-1) == u(u,m+1) on the boundary. So you use the general assembly formula and replace all of the m+1 terms with m-1 on the boundary. You'll have a similar relation for the lower boundary as well.

Implement finite difference method in matlab

I am trying to implement the finite difference method in matlab. I did some calculations and I got that y(i) is a function of y(i-1) and y(i+1), when I know y(1) and y(n+1). However, I don't know how I can implement this so the values of y are updated the right way. I tried using 2 fors, but it's not going to work that way.
EDIT
This is the script and the result isn't right
n = 10;
m = n+1;
h = 1/m;
x = 0:h:1;
y = zeros(m+1,1);
y(1) = 4;
y(m+1) = 6;
s = y;
for i=2:m
y(i) = y(i-1)*(-1+(-2)*h)+h*h*x(i)*exp(2*x(i));
end
for i=m:-1:2
y(i) = (y(i) + (y(i+1)*(2*h-1)))/(3*h*h-2);
end
The equation is:
y''(x) - 4y'(x) + 3y(x) = x * e ^ (2x),
y(0) = 4,
y(1) = 6
Thanks.
Consider the following code. The central differential quotient is discretized.
% Second order diff. equ.
% y'' - 4*y' + 3*y = x*exp(2*x)
% (y(i+1)-2*y(i)+y(i-1))/h^2-4*(y(i+1)-y(i-1))/(2*h) + 3*y(i) = x(i)*exp(2*x(i));
The solution region is specified.
x = (0:0.01:1)'; % Solution region
h = min(diff(x)); % distance
As said in my comment, using this method, all points have to be solved simultaneously. Therefore, above numerical approximation of the equation is transformed in a linear system of euqations.
% System of equations
% Matrix of coefficients
A = zeros(length(x));
A(1,1) = 1; % known solu for first point
A(end,end) = 1; % known solu for last point
% y(i) y'' y
A(2:end-1,2:end-1) = A(2:end-1,2:end-1)+diag(repmat(-2/h^2+3,[length(x)-2 1]));
% y(i-1) y'' -4*y'
A(1:end-1,1:end-1) = A(1:end-1,1:end-1)+diag(repmat(1/h^2+4/(2*h),[length(x)-2 1]),-1);
% y(i+1) y'' -4*y'
A(2:end,2:end) = A(2:end,2:end)+diag(repmat(1/h^2-4/(2*h),[length(x)-2 1]),+1);
With the rhs of the differential equation. Note that the known values are calculated by 1 in the matrix and the actual value in the solution vector.
Y = x.*exp(2*x);
Y(1) = 4; % known solu for first point
Y(end) = 6; % known solu for last point
y = A\Y;
Having an equation to approximate the first order derivative (see above) you can verify the solution. (note, ddx2 is an own function)
f1 = ddx2(x,y); % first derivative (own function)
f2 = ddx2(x,f1); % second derivative (own function)
figure;
plot(x,y);
saveas(gcf,'solu1','png');
figure;
plot(x,f2-4*f1+3*y,x,x.*exp(2*x),'ko');
ylim([0 10]);
legend('lhs','rhs','Location','nw');
saveas(gcf,'solu2','png');
I hope the solution shown below is correct.

MATLAB - Matrix dimensions must agree (although they are "agreed"!)

Here is the code:
fs = 22050;
x = rand(fs,1);
x = x - mean(x); % get rid of DC offeset
% set comb-filter coefficients
f = 220; % fundamental
L = round(fs/f); % delay length
coef = 0.99; % IIR coefficient
% build delay vector and filter
b = [1 zeros(1,L-1) coef];
y = filter(1, b, x);
% create amplitude envelope for output
decay = 8;
expEnv = exp ((0:(length(y)-1))/length(y));
expEnv = (1./expEnv).^ decay;
fprintf('%d\n',length(expEnv));
fprintf('%d\n', length(y));
% envelope output signal
z = y .* expEnv;
sound(z , fs); % play sound
It refuses to execute the z = y.*expEnv line. The printf lines shows that both y and expEnv have the same length (22050)
Yes...the dangers of the length command.
although they have the same number of elements, they do not have the same shape:
>> size(y)
ans =
22050 1
>> size(expEnv)
ans =
1 22050
This will fix that:
z = y .* expEnv.';