MATLAB: Huge performance issues when running a nested for loop - matlab

I am solving a problem that involves multiple combinations of spring mass damper systems. When I run a single for loop, the code runs perfectly, however the nested for loops will not run. I am not receiving any errors. The code is just incapable of solving the ode45 function. Any tips on how I can remedy this issue?
%% Project Parameters
%{
Isolation mats use 5% of the floor area (A_mat=.05A)
%}
clc,clear
time=linspace(0,3,5001); %Time in seconds
A = (8*12*.0254)^2; %Area of floor
A_mat = .05*A; %Area of mat
m_plywood = (1200)*(A)*(3*.0254); %Mass of plywood
m = 550/9.81; %Mass of runner
m0 = 1e-3*min([m_plywood m]); %Mass seperating isolation mats
m=158.757; % kg of person and weight
% impact velocity is 4.89 m/s for 200 lb object dropped from 48 inches
% by impulse momentum theorem, we have ( 90.7 kg )*( 4.89 m/s) = ( M=158.757 kg ) * ( inital velocity )
% solving for initial velocity, we get 2.7937 m/s
xdot0=90.7*4.89/158.757; % 2.7937 m/s initial velocity of floor
%Parameters for rubber mat
m_rubber = (1800)*A*(1*.0254); %Rubber mat mass
k_rubber = (12e6)*A/(1*.0254); %Rubber mat stiffness
zeta_rubber = .08; %Rubber mat damping ratio
c_rubber = zeta_rubber*2*sqrt(k_rubber*m_rubber); %Rubber mat damping coefficient
%Parameters for SPX
m_spx = (1200)*A_mat*(1*.0254); %SPX mat mass
k_spx = (1e6)*A/(1*.0254); %SPX mat stiffness
zeta_spx = .08; %SPX mat damping ratio
c_spx = zeta_spx*2*sqrt(k_spx*m_spx); %SPX mat damping coefficient
%Parameters for DMP
m_dmp = (1500)*A_mat*(1*.0254); %DMP mat mass
k_dmp = (10e6)*A/(1*.0254); %DMP mat stiffness
zeta_dmp = .22; %DMP mat damping ratio
c_dmp = zeta_dmp*2*sqrt(k_dmp*m_dmp); %DMP mat damping coefficient
%Parameters for FRX
m_frx = (1800)*A_mat*(1*.0254); %FRX mat mass
k_frx = (8e6)*A/(1*.0254); %FRX mat stiffness
zeta_frx = .15; %FRX mat damping ratio
c_frx = zeta_frx*2*sqrt(k_frx*m_frx); %FRX mat damping coefficient
%Parameters for BPX
m_bpx = (1200)*A_mat*(1*.0254); %BPX mat mass
k_bpx = (6e6)*A/(1*.0254); %BPX mat stiffness
zeta_bpx = .06; %BPX mat damping ratio
c_bpx = zeta_bpx*2*sqrt(k_bpx*m_bpx); %BPX mat damping coefficient
k = [k_bpx, k_frx, k_dmp, k_spx]'; %Setting stiffness vector to loop through
c = [c_bpx, c_frx, c_dmp, c_spx]'; %Setting damping vector to loop through
%% Dynamic System Modeling, Scenario 1: 1 inch of ioslation mats
clc
for j = 1:length(k)
[t,y1]=ode45(#(t,z)[z(2); ...
k_rubber/m_plywood*z(3)+c_rubber/m_plywood*z(4)-(c_rubber+c(j))/m_plywood*z(2)-(k_rubber+k(j))/m_plywood*z(1); ...
z(4); ...
c_rubber/m*z(2)+k_rubber/m*z(1)-c_rubber/m*z(4)-k_rubber/m*z(3)],time,[0;xdot0;0;0]);
end
%% Dynamic System Modeling, Scenario 2: 2 inches of isolation mats
clc
for j = 1:length(k)
for jj = 1:length(k)
[t,y2]=ode45(#(t,z)[z(2); ...
c(jj)/m0*z(4)+k(jj)/m0*z(3)-(c(jj)+c(j))/m0*z(2)-(k(jj)+k(j))/m0*z(2); ...
z(4); ...
c_rubber/m_plywood*z(6)+k_rubber/m_plywood*z(5)-(c_rubber+c(jj))/m_plywood*z(4)-(k_rubber+k(jj))/m_plywood*z(3); ...
z(6); ...
c_rubber/m*z(4)+k_rubber/m*z(3)-c_rubber/m*z(6)-k_rubber/m*z(5); ...
],[0:15],[0;xdot0;0;0;0;0]);
end
end
%% Dynamic System Modeling, Scenario 3: 3 inches of isolation mats
clc
for j = 1:length(k)
for jj = 1:length(k)
for jjj = 1:length(k)
[t,y3]=ode45(#(t,z)[z(2); ...
c(jj)/m0*z(4)+k(jj)/m0*z(3)-(c(jj)+c(j))/m0*z(2)-(k(jj)+k(j))/m0*z(1); ...
z(4); ...
c(jjj)/m0*z(6)+k(jjj)/m0*z(5)-(c(jjj)+c(jj))/m0*z(4)-(k(jjj)+k(jj))/m0*z(3); ...
z(6); ...
c_rubber/m_plywood*z(8)+k_rubber/m_plywood*z(7)-(c_rubber+c(jjj))/m_plywood*z(6)-(k_rubber+k(jjj))/m_plywood; ...
z(8); ...
c_rubber/m*z(6)+k_rubber/m*z(5)-c_rubber/m*z(8)-k_rubber/m*z(7); ...
],time,[0;xdot0;0;0;0;0;0;0]);
end
end

Related

MATLAB error in ode45, says that it must return a column vector

Error using odearguments
#(T,Z)[Z(2),K_RUBBER/M_PLYWOODZ(3)+C_RUBBER/M_PLYWOODZ(4)-(C_RUBBER+C(J))/M_PLYWOODZ(2)-(K_RUBBER+K(J))/M_PLYWOODZ(1),Z(4),FORCING/M+C_RUBBER/MZ(2)+K_RUBBER/MZ(1)-C_RUBBER/MZ(4)-K_RUBBER/MZ(3)]
must return a column vector.
%% Project Parameters
%{
Isolation mats use 5% of the floor area (A_mat=.05A)
%}
clc,clear
time=linspace(0,3,5001); %Time in seconds
A = (8*12*.0254)^2; %Area of floor
A_mat = .05*A; %Area of mat
m_plywood = (1200)*(A)*(3*.0254); %Mass of plywood
m = 550/9.81; %Mass of runner
m0 = 1e-3*min([m_plywood m]); %Mass separating isolation mats
%Parameters for Harmonic Forcing
T =72/60; %Period of forcing from runner
f = 1/T; %Frequency of forcing from runner
omega = f*2*pi; %Frequency in radians of forcing from runner
F = -m*9.81; %Force runner applies to floor
Forcing = F*cos(omega*time);
%Parameters for rubber mat
m_rubber = (1800)*A*(1*.0254); %Rubber mat mass
k_rubber = (12e6)*A/(1*.0254); %Rubber mat stiffness
zeta_rubber = .08; %Rubber mat damping ratio
c_rubber = zeta_rubber*2*sqrt(k_rubber*m_rubber); %Rubber mat damping coefficient
%Parameters for SPX
m_spx = (1200)*A_mat*(1*.0254); %SPX mat mass
k_spx = (1e6)*A/(1*.0254); %SPX mat stiffness
zeta_spx = .08; %SPX mat damping ratio
c_spx = zeta_spx*2*sqrt(k_spx*m_spx); %SPX mat damping coefficient
%Parameters for DMP
m_dmp = (1500)*A_mat*(1*.0254); %DMP mat mass
k_dmp = (10e6)*A/(1*.0254); %DMP mat stiffness
zeta_dmp = .22; %DMP mat damping ratio
c_dmp = zeta_dmp*2*sqrt(k_dmp*m_dmp); %DMP mat damping coefficient
%Parameters for FRX
m_frx = (1800)*A_mat*(1*.0254); %FRX mat mass
k_frx = (8e6)*A/(1*.0254); %FRX mat stiffness
zeta_frx = .15; %FRX mat damping ratio
c_frx = zeta_frx*2*sqrt(k_frx*m_frx); %FRX mat damping coefficient
%Parameters for BPX
m_bpx = (1200)*A_mat*(1*.0254); %BPX mat mass
k_bpx = (6e6)*A/(1*.0254); %BPX mat stiffness
zeta_bpx = .06; %BPX mat damping ratio
c_bpx = zeta_bpx*2*sqrt(k_bpx*m_bpx); %BPX mat damping coefficient
k = [k_bpx, k_frx, k_dmp, k_spx]'; %Setting stiffness vector to loop through
c = [c_bpx, c_frx, c_dmp, c_spx]'; %Setting damping vector to loop through
%% Dynamic System Modeling, Scenario 1: 1 inch of ioslation mats
clc
for j = 1:length(k)
[t,y]=ode45(#(t,z)[z(2),k_rubber/m_plywood*z(3)+c_rubber/m_plywood*z(4)-(c_rubber+c(j))/m_plywood*z(2)-(k_rubber+k(j))/m_plywood*z(1),z(4),Forcing/m+c_rubber/m*z(2)+k_rubber/m*z(1)-c_rubber/m*z(4)-k_rubber/m*z(3)],time,[0;0;0;0]);
end
This function handle returns a row vector since you use commas as separators:
#(t,z)[z(2),k_rubber/m_plywood*z(3)+c_rubber/m_plywood*z(4)-(c_rubber+c(j))/m_plywood*z(2)-(k_rubber+k(j))/m_plywood*z(1),z(4),Forcing/m+c_rubber/m*z(2)+k_rubber/m*z(1)-c_rubber/m*z(4)-k_rubber/m*z(3)]
Use semi-colons instead to make this return a column vector:
#(t,z)[z(2);k_rubber/m_plywood*z(3)+c_rubber/m_plywood*z(4)-(c_rubber+c(j))/m_plywood*z(2)-(k_rubber+k(j))/m_plywood*z(1);z(4);Forcing/m+c_rubber/m*z(2)+k_rubber/m*z(1)-c_rubber/m*z(4)-k_rubber/m*z(3)]
For code readability, it would probably be better to define this function handle outside of your ode45( ) call.

Model Predictive Control (MPC) for electromechanical system

So I want to create an MPC controller for my seesaw-cart system. All the "grunt work" (getting equations of motion, state-space representation etc.) has been done, so I went into coding into MATLAB.
Here's the following:
clc; clear all; close all;
yalmip('clear')
%% Parameters
a = 0.116553; % height of center mass of the pendulum, [m]
b = 0; % position of the weight B on the vertical rod (not taken into consideration)
c = 0.180047; % height of the center of mass of the cart, [m]
mA = 4.839; % mass of the pendulum, [kg]
mB = 0; % not taken into consideration
mC = 1; % mass of the cart, [kg]
g = 9.81; % gravity factor, [m/s^2]
kappa = 0.1; % coefficient of the viscous damping in the rotational joint
J = 0.68; % moment of inertia of the pendulum, [kgm^2]
Ke = 0.077; % motor constant of the EM force, [Vs^-1]
Kt = 0.077; % proportional moment motor constant, [NmA^-1]
Ra = 2.6; % electrical resistance, [ohm]
p = 1/3.71; % motor gearbox ratio
r = 7.7*10^(-3); % effective radius of the motor shaft, [m]
%% Defining the continuous system
A = [0 1 0 0;
(a*mA*g+b*mB*g)/(J+mB*b^2), -kappa/(J+mB*b^2), -mC*g/(J+mB*b^2), -Ke*Kt/(mC*(J+mB*b^2)*Ra*p^2*r^2);
0 0 0 1;
(a*mA*g+b*mB*g)/(J+mB*b^2)-g, -kappa*c/(J+mB*b^2), -c*mC*g/(J+mB*b^2), -(J+mB*b^2+mC*c^2)*Ke*Kt/(mC*(J+mB*b^2)*Ra*p^2*r^2)];
B = [0;
Kt/(mC*(J+mB*b^2)*Ra*p^2*r^2);
0;
(J+mB*b^2+mC*c^2)*Kt/(mC*(J+mB*b^2)*Ra*p^2*r^2)];
C = eye(4); % check
D = 0;
sysC = ss(A, B, C, D);
%% Defining the discrete system
Ts = 10e-3; % sample time
sysD = c2d(sysC,Ts); % discrete time
Ad = sysD.A;
Bd = sysD.B;
%% Formulation of the MPC problem
[nx, nu] = size(B);
Q = eye(nx);
R = eye(nu);
N = 1000;
% Input constraints, maximum and minimum voltage
umin = -6;
umax = 6;
% Still have to find this
xmin = [-deg2rad(10); -deg2rad(50); -0.5; -10];
xmax = [deg2rad(10); deg2rad(50); 0.5; 10];
uVar = sdpvar(repmat(nu,1,N),ones(1,N));
xVar = sdpvar(repmat(nx,1,N+1),ones(1,N+1));
constraints = [];
objective = 0;
ops = sdpsettings('verbose',0,'solver','quadprog');
for k = 1:N
objective = objective + xVar{k}'*Q*xVar{k} + uVar{k}*R*uVar{k};
constraints = [constraints, xVar{k+1} == Ad*xVar{k} + Bd*uVar{k}];
constraints = [constraints , umin <= uVar{k} <= umax , xmin <= xVar{k+1} <= xmax];
end
controller = optimizer(constraints, objective,ops,xVar{1},[uVar{:}]);
%% Simulation of the linearized model
nSim = 1000;
x0 = [0; 0; 0; 0.05]; % initial values, check
time = 0:Ts:nSim*Ts;
x = zeros(nx,nSim+1);
u = zeros(nu,nSim);
x(:,1) = x0;
for i = 2:nSim+1
disp(strcat(['Sim iter: ', num2str(i-1)]));
uOpt = controller{x(:,i-1)};
u(:,i-1) = uOpt(:,1);
x(:,i) = Ad*x(:,i-1) + Bd*u(:,i-1);
end
%% Plot
figure;
subplot(4,1,1);
plot(time,x(1,:), 'LineWidth', 2, 'Color', 'red'); grid; ylabel('{\theta} (rad)'); title('States');
subplot(4,1,2);
plot(time,x(2,:), 'LineWidth', 2, 'Color', [0.6350, 0.0780, 0.1840]); grid; ylabel('$\dot{\theta}$ (rad/s)', 'Interpreter', 'latex');
subplot(4,1,3);
plot(time,x(3,:), 'LineWidth', 2, 'Color', [0.4940, 0.1840, 0.5560]); grid; ylabel('s (m)');
subplot(4,1,4);
plot(time,x(4,:), 'LineWidth', 2, 'Color',[0, 0.7, 0.9]); grid; ylabel('$\dot{s}$ (m/s)', 'Interpreter', 'latex'); xlabel('t (s)');
figure;
stairs(time(1:end-1),u, 'LineWidth', 2, 'Color',[1, 0.647, 0]); grid; ylabel('Ua (V)'); xlabel('t (s)'); title('Input');
So I was wondering for any suggestions on improvements. What can I do to make my regulator more robust?
Here are my outputs for this particular code:
Note: I'm using YALMIP for the optimization part of the MPC.
You lose feasibility after a few iterations,
sol =
struct with fields:
yalmipversion: '20210331'
matlabversion: '9.9.0.1524771 (R2020b) Update 2'
yalmiptime: 0.1159
solvertime: 0.2331
info: 'Infeasible problem (QUADPROG))'
problem: 1
K>> i
i =
4
Your MPC controller is thus badly tuned (too short horizon being the obvious start)
Also, your definition of u is weird as it has length 4 instead of length N (thus meaning you have two trailing variables in u which never are used, leading to them having value Nan when you look at them)
There are numerous MPC-examples in the tutorials which you should be able to use directly
https://yalmip.github.io/example/standardmpc/
YALMIP-specific question are better asked at
https://github.com/yalmip/YALMIP/discussions
https://groups.google.com/g/yalmip

How to plot decision boundary from linear SVM after PCA in Matlab?

I have conducted a linear SVM on a large dataset, however in order to reduce the number of dimensions I performed a PCA, than conducted the SVM on a subset of the component scores (the first 650 components which explained 99.5% of the variance). Now I want to plot the decision boundary in the original variable space using the beta weights and bias from the SVM created in PCA space. But I can't figure out how to project the bias term from the SVM into the original variable space. I've written a demo using the fisher iris data to illustrate:
clear; clc; close all
% load data
load fisheriris
inds = ~strcmp(species,'setosa');
X = meas(inds,3:4);
Y = species(inds);
mu = mean(X)
% perform the PCA
[eigenvectors, scores] = pca(X);
% train the svm
SVMModel = fitcsvm(scores,Y);
% plot the result
figure(1)
gscatter(scores(:,1),scores(:,2),Y,'rgb','osd')
title('PCA space')
% now plot the decision boundary
betas = SVMModel.Beta;
m = -betas(1)/betas(2); % my gradient
b = -SVMModel.Bias; % my y-intercept
f = #(x) m.*x + b; % my linear equation
hold on
fplot(f,'k')
hold off
axis equal
xlim([-1.5 2.5])
ylim([-2 2])
% inverse transform the PCA
Xhat = scores * eigenvectors';
Xhat = bsxfun(#plus, Xhat, mu);
% plot the result
figure(2)
hold on
gscatter(Xhat(:,1),Xhat(:,2),Y,'rgb','osd')
% and the decision boundary
betaHat = betas' * eigenvectors';
mHat = -betaHat(1)/betaHat(2);
bHat = b * eigenvectors';
bHat = bHat + mu; % I know I have to add mu somewhere...
bHat = bHat/betaHat(2);
bHat = sum(sum(bHat)); % sum to reduce the matrix to a single value
% the correct value of bHat should be 6.3962
f = #(x) mHat.*x + bHat;
fplot(f,'k')
hold off
axis equal
title('Recovered feature space')
xlim([3 7])
ylim([0 4])
Any guidance on how I'm calculating bHat incorrectly would be much appreciated.
Just in case anyone else comes across this problem, the solution is the bias term can be used to find the y-intercept, b = -SVMModel.Bias/betas(2). And the y-intercept is just another point in space [0 b] which can be recovered/unrotated by inverse transforming it through the PCA. This new point can then be used to solve the linear equation y = mx + b (i.e., b = y - mx). So the code should be:
% and the decision boundary
betaHat = betas' * eigenvectors';
mHat = -betaHat(1)/betaHat(2);
yint = b/betas(2); % y-intercept in PCA space
yintHat = [0 b] * eigenvectors'; % recover in original space
yintHat = yintHat + mu;
bHat = yintHat(2) - mHat*yintHat(1); % solve the linear equation
% the correct value of bHat is now 6.3962

Plotting 2D equation with infinite sum

I'm trying to plot the following equation (let's call it "Equation 1"):
This is the code I'm testing:
clear all;
xl=0; xr=1; % x domain [xl,xr]
J = 10; % J: number of division for x
dx = (xr-xl) / J; % dx: mesh size
tf = 0.1; % final simulation time
Nt = 60; % Nt: number of time steps
dt = tf/Nt/4;
x = xl : dx : xr; % generate the grid point
u_ex = zeros(J+1,Nt);
for n = 1:Nt
t = n*dt; % current time
for j=1:J+1
xj = xl + (j-1)*dx;
suma = zeros(100 , 1);
for k= 1:100
suma(k) = 4/(((2*k-1)^2) *pi*pi);
suma(k) = suma(k) * exp(-((2*k-1)^2) *pi*pi*t) * cos(2*k-1)*pi*xj;
end
m = sum(suma);
u_ex(j, n)= 0.5 - m;
end
end
tt = dt : dt : Nt*dt;
figure(1)
surf(x,tt, u_ex'); % 3-D surface plot
xlabel('x')
ylabel('t')
zlabel('u')
The problem is that all I get is a flat surface:
Equation 1 is suppossed to be the solution of the following parabolic partial differential equation with boundary values:
And after getting the numerical solution, it should look like this:
This plot gets the right values at the boundaries x = 0 and x = 1. The plot of Equation 1 doesn't have those values at the boundaries.
My complete .m code (that plots both the numerical solution and Equation 1) is:
clear all; % clear all variables in memory
xl=0; xr=1; % x domain [xl,xr]
J = 10; % J: number of division for x
dx = (xr-xl) / J; % dx: mesh size
tf = 0.1; % final simulation time
Nt = 60; % Nt: number of time steps
dt = tf/Nt/4;
mu = dt/(dx)^2;
if mu > 0.5 % make sure dt satisy stability condition
error('mu should < 0.5!')
end
% Evaluate the initial conditions
x = xl : dx : xr; % generate the grid point
% store the solution at all grid points for all time steps
u = zeros(J+1,Nt);
u_ex = zeros(J+1,Nt);
% Find the approximate solution at each time step
for n = 1:Nt
t = n*dt; % current time
% boundary condition at left side
gl = 0;
% boundary condition at right side
gr = 0;
for j=2:J
if n==1 % first time step
u(j,n) = j;
else % interior nodes
u(j,n)=u(j,n-1) + mu*(u(j+1,n-1) - 2*u(j,n-1) + u(j-1,n-1));
end
end
u(1,n) = gl; % the left-end point
u(J+1,n) = gr; % the right-end point
% calculate the analytic solution
for j=1:J+1
xj = xl + (j-1)*dx;
suma = zeros(100 , 1);
for k= 1:100
suma(k) = 4/(((2*k-1)^2) *pi*pi);
suma(k) = suma(k) * exp(-((2*k-1)^2) *pi*pi*t) * cos(2*k-1)*pi*xj;
end
m = sum(suma);
u_ex(j, n)= 0.5 - m;
end
end
% Plot the results
tt = dt : dt : Nt*dt;
figure(1)
colormap(gray); % draw gray figure
surf(x,tt, u'); % 3-D surface plot
xlabel('x')
ylabel('t')
zlabel('u')
title('Numerical solution of 1-D parabolic equation')
figure(2)
surf(x,tt, u_ex'); % 3-D surface plot
xlabel('x')
ylabel('t')
zlabel('u')
title('Analytic solution of 1-D parabolic equation')
maxerr=max(max(abs(u-u_ex))),
The code is taken from the book "Computational Partial Differential Equations Using MATLAB" by Yi-Tung Chen, Jichun Li, chapter 2, exercise 3.
In short: I'm not asking about the differential equation or the boundary problem, I want to know is: Why am I getting a flat surface when plotting Equation 1? Am I missing a parenthesis?
I do not want to use the symsum function because it never stop the script execution and I want to learn how to plot Equation 1 with no using symsum.
I've tested this code with Matlab R2008b and Octave 4.2.1. I got the same results (even with sums of 1000, 10000 and 50000 terms in the for loop with the k variable).
Edit!
Thanks, Steve!
I was missing a couple of parenthesis near the cosine, the right code is:
clear all; % clear all variables in memory
xl=0; xr=1; % x domain [xl,xr]
J = 10; % J: number of division for x
dx = (xr-xl) / J; % dx: mesh size
tf = 0.1; % final simulation time
Nt = 60; % Nt: number of time steps
dt = tf/Nt/4;
mu = dt/(dx)^2;
if mu > 0.5 % make sure dt satisy stability condition
error('mu should < 0.5!')
end
% Evaluate the initial conditions
x = xl : dx : xr; % generate the grid point
% store the solution at all grid points for all time steps
u = zeros(J+1,Nt);
u_ex = zeros(J+1,Nt);
% Find the approximate solution at each time step
for n = 1:Nt
t = n*dt; % current time
% boundary condition at left side
gl = 0;
% boundary condition at right side
gr = 0;
for j=2:J
if n==1 % first time step
u(j,n) = j;
else % interior nodes
u(j,n)=u(j,n-1) + mu*(u(j+1,n-1) - 2*u(j,n-1) + u(j-1,n-1));
end
end
u(1,n) = gl; % the left-end point
u(J+1,n) = gr; % the right-end point
% calculate the analytic solution
for j=1:J+1
xj = xl + (j-1)*dx;
suma = zeros(1000 , 1);
for k= 1:1000
suma(k) = 4/(((2*k-1)^2) *pi*pi);
suma(k) *= exp(-((2*k-1)^2) *pi*pi*t) * cos((2*k-1)*pi*xj);
end
m = sum(suma);
u_ex(j, n)= 0.5 - m;
end
end
% Plot the results
tt = dt : dt : Nt*dt;
figure(1)
colormap(gray); % draw gray figure
surf(x,tt, u'); % 3-D surface plot
xlabel('x')
ylabel('t')
zlabel('u')
title('Numerical solution of 1-D parabolic equation')
figure(2)
surf(x,tt, u_ex'); % 3-D surface plot
xlabel('x')
ylabel('t')
zlabel('u')
title('Analytic solution of 1-D parabolic equation')
Now my Equation 1 looks much better:
Also Steve was right when pointing out that my numerical solution may be wrong. I didn't notice that the boundary values are for the derivatives of my function, not the actual values of the function. I'll ask my teacher about this.
Edit2!
Ok, I got it. To calculate the derivatives at the boundaries you have to use hint 2.21 in the same book:
% hint 2.21 given by the book
% it is better to calculate the boundary values after calculating the inner points inside the for j = 1:m loop because you will need them:
u(1, n) = u(2, n) - dx * gl; % the left-end point
u(J+1,n) = u(J, n) + dx * gr; % the right-end point
Now my numerical solution looks like my analytic solution :D
Matlab R2008b can't recognize the *= operator that Octave does. I'm not tested this operator in other versions of Matlab because I'm too poor.
Yvon: I think the analytical solution formula comes from the real part of a Fourier expansion, but authors don't tell how they got it.

visualization of light waves superposition in matlab

I wrote some quick code for visualization of superposition of two waves with different amplitudes in space, point source geometry. this works at khanacademy CS platform. http://www.khanacademy.org/cs/superposition/1245709541 but i cant reproduce the exact phenomena in matlab. all i get is a noisy image. Is this something to do with difference in random number generation? I have no idea how different random(0,1)(in JS) and rand(in matlab) are.
here is the matlab code
A wave superposition function for a point x,y on image plane
function S = Super(refamp,objamp,x,y,a,lambda)
r1 = sqrt(a*a+x*x+y*y); %a is in z-axis
S = refamp+(objamp*cos(2*pi*r1/(lambda/(10^6))));
The test script
close all;
clear all;
clc;
a=10; %distance from source to image plane
width = 1024;
height =1024;
im = zeros(width); % the image
x=1;
y=1;
A0 = 3; % amplitude of reference wave
A1 = 1; % amplitude of object wave A0>>A1: A0/A1>=3
lambda = 632; % wavelength in nanometers
% generate the superposition in space width*height at a along z-axis
for y=1:height
for x=1:width
s = Super(A0,A1,x-(width/2),y-(height/2),a, lambda);
r=rand;
if(r<(s/(A0+A1)))
im(x,y) = 1;
end
end
%display the image
figure
imshow(im,[])
title('test image')
The main problem is that your scales are off, so you aren't seeing the interference pattern. If you play around with how big/far everything is, it will work out right and you can see the pattern.
The second problem is that your code would really benefit from vectorization. I've shown this below - doing it this way speeds up the execution dramatically.
function Interference
a=1000 * 10^-9; #% distance from source to image plane
width = 10000 * 10^-9;
height= 10000 * 10^-9;
size = 700;
A0 = 3; %# amplitude of reference wave
A1 = 1; %# amplitude of object wave A0>>A1: A0/A1>=3
lambda = 632 * 10^-9; #% wavelength in nanometers
x=linspace(0,width,size); #% vector from 0 to width
y=linspace(0,height,size); #% vector from 0 to height
[X,Y]=meshgrid(x,y); #% matrices of x and y values at each position
s=Super(A0, A1, X-(width/2), Y-(height/2), a, lambda); #% size-by-size (700x700)
r=rand(size); #% 700x700 matrix of random values on [0 1]
im = zeros(size);
im(r<(s/(A0+A1))) = 1; %# do this all at once instead of pixel-by-pixel
#% display the image
figure
imshow(im,[])
title('test image')
end #% end of function Interference
#% Super is now vectorized, so you can give it a matrix of values for x and y
function S = Super(refamp,objamp,x,y,a,lambda)
r1 = sqrt(a.*a+x.*x+y.*y); #% dot notation: multiply element-wise
S = refamp+(objamp*cos(2*pi*r1/(lambda)));
end #% end of function Super
function i = Interference(width, height, sizeh,sizev,z)
% parameters explained
% width: is the horizontal pixel pitch in microns
% height: is the vertical pixel pitch in microns
% size is the width=height of the CCD in number of pixels
% z is distance from source to image plane
A0 = 3; %# amplitude of reference wave
A1 = 1; %# amplitude of object wave A0>>A1: A0/A1>=3
lambda = 635 * 10^-9; % wavelength in nanometers
%the linspace was wrong
x=linspace(0,width*sizeh,sizeh); % vector from 0 to width of size 'size'
y=linspace(0,height*sizev,sizev); % vector from 0 to height of size 'size'
[X,Y]=meshgrid(x,y); % matrices of x and y values at each position
s=Super(A0, A1, X-((width*sizeh)/2), Y-((height*sizev)/2), z, lambda); % size-by-size (1024x1024)
r=rand(size); % 1024x1024 matrix of random values on [0 1]
%i=s;
im = zeros(size);
im(r<(s/(A0+A1))) = 1; %# do this all at once instead of pixel-by-pixel
i=im;
end % end of function Interference
% Super is now vectorized, so you can give it a matrix of values for x and y
function S = Super(refamp,objamp,x,y,a,lambda)
r1 = sqrt(a.*a+x.*x+y.*y); % dot notation: multiply element-wise
S = refamp+(objamp*cos(2*pi*r1/(lambda)));
end % end of function Super
usage of the function
width = 2.8 * 10^-6;
height= 2.8 * 10^-6; %pixel size
% sizeh = 16; %image size in pixels
% sizev = 16;
sizeh = 1600; %image size in pixels
sizev = 1200;
int_z = 100*10^-3; % z dist in m
% xes1 = 100;
%xes2 = ;
int_im = Interference(width,height,sizeh, sizev,int_z);
int_im = int_im/max(max(int_im)); % normalize
int_im = (int_im-0.5)*2; % enhance visualy
% display the image
figure
imshow(int_im,[])