Find positive solutions in undetermined system of equations (revisited) - matlab

I tried to apply the method posted in Find positive solutions to undetermined linear system of equations to the set
A=[0 0.0992 0.315 0.619 1; 0 0.248 0.315 0.248 0]; b=[0.1266 0.4363].
It is supposed that there exists a positive and constrained solution to this problem. The worst thing is that I have an answer code but I can't make it work because my Matlab version doesn`t recognize the anonymous function call and some instructions are obscure for me.
Here is the code:
% example_pt_source_atmos_setup.m
% determine geometry
D2 = 0.5; % diameter of the observation aperture [m]
wvl = 1e-6; % optical wavelength [m]
k = 2*pi / wvl; % optical wavenumber [rad/m]
Dz = 50e3; % propagation distance [m]
% use sinc to model pt source
DROI = 4 * D2; % diam of obs-plane region of interest [m]
D1 = wvl*Dz / DROI; % width of central lobe [m]
R = Dz; % wavefront radius of curvature [m]
% atmospheric properties
Cn2 = 1e-16; % structure parameter [m^-2/3], constant
% SW and PW coherence diameters [m]
r0sw = (0.423 * k^2 * Cn2 * 3/8 * Dz)^(-3/5);
r0pw = (0.423 * k^2 * Cn2 * Dz)^(-3/5);
p = linspace(0, Dz, 1e3);
% log-amplitude variance
rytov = 0.563 * k^(7/6) * sum(Cn2 * (1-p/Dz).^(5/6) ...
.* p.^(5/6) * (p(2)-p(1)));
% screen properties
nscr = 11; % number of screens
A = zeros(2, nscr); % matrix
alpha = (0:nscr-1) / (nscr-1);
A(1,:) = alpha.^(5/3);
A(2,:) = (1 - alpha).^(5/6) .* alpha.^(5/6);
b = [r0sw.^(-5/3); rytov/1.33*(k/Dz)^(5/6)];
% initial guess
x0 = (nscr/3*r0sw * ones(nscr, 1)).^(-5/3);
% objective function
fun = #(X) sum((A*X(:) - b).^2);
% constraints
x1 = zeros(nscr, 1);
rmax = 0.1; % maximum Rytov number per partial prop
x2 = rmax/1.33*(k/Dz)^(5/6) ./ A(2,:);
x2(A(2,:)==0) = 50^(-5/3)
[X,fval,exitflag,output] ...
= fmincon(fun,x0,[],[],[],[],x1,x2)
% check screen r0s
r0scrn = X.^(-3/5)
r0scrn(isinf(r0scrn)) = 1e6;
% check resulting r0sw & rytov
bp = A*X(:); [bp(1)^(-3/5) bp(2)*1.33*(Dz/k)^(5/6)]
[r0sw rytov]
Thanks for your attention.
Carolina Rickenstorff

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

How to draw multiple surface plots at the same mesh in MATLAB?

I use this code to draw a Gaussian normal distribution. I want to plot several distributions at an equal distance from the original one (like the figure).
lambda = 1; % wavelength
E0 = 1; % max value of E-field amplitude
% ==================================================================
% prepare the coordinates mesh
% ----------------------------
zLin = linspace(-201,201,400) * lambda; % z-coordinate (horizontal)
rLin = linspace(-65,65,100) * lambda; % radius-coordinate (vertical)
[z,r] = meshgrid(zLin,rLin); % create mesh
% ===================================================================
wFactor = 4;
w0 = wFactor * lambda; % minimal waist
zR = pi* w0^2 / lambda; % Rayleigh length
w = w0 * sqrt( 1 + (z / zR) .^2 ); % Beam radius at any arbitrary distance (equ. 3)
% Irradiance
eta = 377; % for free space
I0 = abs(E0)^2/eta;
I = I0 .* (w0 ./ w).^2 .* exp( -2*(r./w).^2 );
surf(z,r,I); shading interp

Slow time integration of system ODE under specific conditions

I am trying to solve the system of ODEs below. I am applying the finite differences to z, so I get a system of ODE that I can solve with a solver like ode45.
The problem is that under the conditions that interest me integration is too slow (time step is very small) and I get no result. I would like to know what is the underlying problem and if there is any way to solve it. I have tried:
using different solvers (tried all of them)
using dimensionless variables
using the pdepe function of Matlab to solve the PDE system directly without applying finite differences myself. Same problem occurs.
Full code (using the parameters that do not work)
function transport_model()
global parameter L Di epsb Q Cfeed K tfinal npz npt F ui h
parameter = [0.044511*432.75 432.75]; % isotherm parameters
L = 0.4; % m, column length
epsb = 0.367; % column bulk porosity
ui = 4e4; % m/s, velocity
Cfeed = 200; % feed concentration
K = 0.0782 % s-1, mass transfer coefficient
tfinal = 400; % min, final time for calculation
npz = 50; % number of discretization points in z
npt = 20;
F = (1-epsb)/epsb;
tspan = 0:tfinal/(npt-1):tfinal;
y0 = zeros(2*npz,1);
h = L/(npz-1);
sol = ode15s(#sedo, tspan, y0);
t = sol.x;
C1 = sol.y(1:npz,:);
q1 = sol.y((npz+1):end,:);
plot(t, C1(end,:))
xlim([0 tfinal])
ylim([0 Cfeed])
function DyDt = sedo(t,y)
global Cfeed K npz F ui h
N = npz;
y(1) = Cfeed;
DyDt = zeros(2*N,1);
% Forward finite differences
DyDt(1) = -ui * 1/(2*h)*(-y(3)+4*y(2)-3*y(1)) - F * K * (y(1) - ilangmuir(y(N+1)));
DyDt(N+1) = K * (y(1) - ilangmuir(y(N+1)));
% Central finite differences
for i=2:N-1
DyDt(i) = -ui * 1/(2*h)*(y(i+1)-y(i-1)) - F * K * (y(i) - ilangmuir(y(N+i)));
DyDt(N+i) = K * (y(i) - ilangmuir(y(N+i)));
end
% Backward finite differences
DyDt(N) = -ui * 1/(2*h)*(3*y(N)-4*y(N-1)+y(N-2)) - F * K * (y(N) - ilangmuir(y(N+N)));
DyDt(2*N) = K * (y(N) - ilangmuir(y(N+N)));
function c = ilangmuir(q)
% langmuir solved for c
global parameter
a = parameter(1);
b = parameter(2);
c = q /(a - b * q);
However, if I try to model a different case (different conditions) I get the correct response. So I am assuming this is a numerical problem caused by the conditions I am trying to model and not an error in the model. For instance, if I use the conditions below I get the correct response.
parameter = [0.044511*432.75 432.75]; % isotherm parameters
L = 0.4; % m, column length
epsb = 0.367; % column bulk porosity
ui = 0.0056; % m/s, velocity
Cfeed = 0.0025; % feed concentration
K = 0.0782 % s-1, mass transfer coefficient
tfinal = 4000; % min, final time for calculation
npz = 50; % number of discretization points in z
npt = 20;

How can I best represent a speed bump with heaviside?

%% numerical values
% speed & time
v = 5; % m/s
t_end =10; % s
% Runge Kutta
dt = 0.001;
n = t_end/dt;
% suspended mass
ms = 300*0.7; % mass (70% of the mass moto + rider)
ks = 85000; % spring N/m
mus = 4000; % damping
% wheel
mw = 50; % mass
kw = 180000; % spring N/m
% frame
L = 0.55; % m
l = 0.15; % m
%% Bump
hs = 0.1 %height m side walk
hb = 0.05; %height m speed bump
w = 0.20; %width m
How to add the c?
%a) side walk
%r = #(t) hs*(v*t>0);
%b) speed bump
r = #(t) -4*hb/w^2*v*t.*(v*t-w).*(v*t>0 & v*t<w);
%% variables
% x(0)= position suspended mass (x_s)
% x(1) = position non-suspended mass (x_u)
% x(2) = velocity suspended mass (dx_s/dt)
% x(3) = velocity non-suspended mass (dx_u/dt)
%% differential equation
dx = #(t, x) [ x(3);
x(4);
1/ms*(-ks*(x(1)-l/L*x(2)) - mus*(x(3)-l/L*x(4)));
1/mw*(-kw*(x(2)-r(t)) - ks*(x(2)-L/l*x(1))-mus*(x(4)-L/l*x(3)))];
%% ode 45
[tt, y] = ode45(dx, [0 t_end], x0);
%% Runge-Kutta
x = zeros(n+1,4);
t = 0 : dt : t_end;
for i=1:n
k1 = dx(t(i), x(i,:))';
k2 = dx(t(i)+dt/2, x(i,:)+0.5*k1*dt)';
k3 = dx(t(i)+dt/2, x(i,:)+0.5*k2*dt)';
k4 = dx(t(i+1),x(i,:)+k3*dt)';
x(i+1,:) = x(i,:) + (0.5*k1+k2+k3+0.5*k4)/3.*dt;
end

Solving the Damped Harmonic Oscillator ODE as a first order system using midpoint methods

The exact solution of the damped harmonic oscillator
$$x'' + 2\gamma x' + \omega^2 x = 0, \quad x(0)=x_0, \quad x'(0)=-\gamma x_0$$
with $0 < \gamma < \omega$ is
$$x(t)= x_0 e^{-\gamma t} \cos(\beta t) \quad \text{where} \quad \beta:=\sqrt{\omega^2 - \gamma^2}$$
Notice that this second order ODE can be written as a first order system by making the substitutions:
$x' = y$ and,
$y' = -2\gamma y - \omega^2 x$
I want to solve the system using the method:
$$\dfrac{ x_{n+1} - x_{n-1} }{2h} = y_n \quad \quad \dfrac{y_{n+1} - y_{n-1}}{2h} = -2\gamma y_n - \omega^2 x_n.$$
which is an explicit midpoint rule. This is the code that I constructed for the problem, but it is not giving me the correct result. My plot has no harmonic behavior as I would anticipate.
function resonance
omega = 1; % resonant frequency = sqrt(k/m)
a = 0.2; % drag coeficient per unit mass
b = 0.1; % driving amplitude per unit mass
omega0 = 1.2; % driving frequency
tBegin = 0; % time begin
tEnd = 80; % time end
x0 = 0.2; % initial position
v0 = 0.8; % initial velocity
a = omega^2; % calculate a coeficient from resonant frequency
% Use Runge-Kutta 45 integrator to solve the ODE
[t,w] = ode45(#derivatives, [tBegin tEnd], [x0 v0]);
x = w(:,1); % extract positions from first column of w matrix
v = w(:,2); % extract velocities from second column of w matrix
plot(t,x);
title('Damped, Driven Harmonic Oscillator');
ylabel('position (m)');
xlabel('time (s)');
% Function defining derivatives dx/dt and dv/dt
% uses the parameters a, b, A, omega0 in main program but changeth them not
function derivs = derivatives(tf,wf)
xf = wf(1); % wf(1) stores x
vf = wf(2); % wf(2) stores v
dxdt = vf; % set dx/dt = velocity
dvdt = xf + 2 * b * vf + a * tf; % set dv/dt = acceleration
derivs = [dxdt; dvdt]; % return the derivatives
end
end
Also, my apologies about the formatting. I am use to math stackexchange, and the LaTeX style formatting doesn't seem to be applicable here and I do not know how to put my math in the math environment.
You missed a sign, it should be
dvdt = - ( xf + 2 * b * vf + a * tf ); % set dv/dt = acceleration
However, the whole expression is at odds with the previously stated equation,
x'' + 2*b*x' * a*x = 0
should result in
dvdt = - ( 2*b*vf + a*xf ); % set dv/dt = acceleration
But then again you have defined a twice, so change w2=omega^2 to get
dvdt = - ( 2*b*vf + w2*xf + a ); % set dv/dt = acceleration