Solving ring laser equations in MATLAB using ode - matlab

I have written a Matlab code which is a simulation of NOT gate implementation using ring lasers. Si variable is input in my code. But my code works only for Si = 0. for any other non zero value it doesn't show output.
%-----------Rate Equation MATLAB code ---------
function dydt = requations(t,y)
dydt = zeros(size(y));
%prompt = 'Sinput???';
%Si = input(prompt);
Si = 0; %MY INPUT
q = 1.6e-19; % charge of electron
tau_e = 1e-9; % carrier lifetime
No = 3.3e18; % # No of carriers at transparency
a = 1e-15; % Linear gain coefficient
Vg = 7.5e9; % group velocity
Vp = 3e-11; %Photon reservoir volume
V = 1e-11; %Carrier reservoir Volume
tau_p = 1.7e-12; % photon lifetime
beta = 1e-5; % spontateous emission coefficient
eps = 7.5e-17; % Nonlinear gain suppression coefficient
Ni = 0.8; %Internal quantum efficiency
w = 2*pi*10e5;
Io = 10e-3;
%I = Io*sin(w*t);
I = 2.5*Io; %for test purposes
tp = 1/tau_p;
te = 1/tau_e;
Aint = 6; %Internal losses inside cavity waveguides
%G = ((a/Vp)* (N-(V*No)))/(1-eps*(Sc + Scc));
alpha = -2; %alpha factor
L = 76e-4 ;%size of the ring
wcb = 2*pi*70;
%R = 0.25;
Wcb = wcb*1000000;
%r = 1/R;
tpcw = Vg*(Aint + ((1/L)*log(4)));
Tpcw = 1/tpcw;
%------Rate equations-------
N = y(1);
Sc = y(2); %Clock wise photon number
yc = y(3);
Scc = y(4); %anti clockwise photon number
ycc = y(5);
G = ((a/Vp)* (N-(V*No)))/(1-eps*(Sc + Scc));
dydt(1) = (Ni*I)/q - y(1)*te - Vg*G*(y(2) + y(4)); %dN/dt
dydt(2) = (Vg*G-Tpcw)*y(2) + beta*y(1)*te; %dSc/dt
dydt(3) = -(alpha/2)*(Vg*G-Tpcw); %dyc/dt
dydt(4) = (Vg*G-Tpcw)*y(4) + beta*y(1)*te + ((2*Vg)/L)*cos(y(5))*(sqrt(Si*y(4))); %dScc/dt
dydt(5) = -Wcb - ((alpha/2)*(Vg*G-Tpcw)) - ((Vg/L)*sin(y(5))*(sqrt(Si/y(4)))); %dycc/dt
Below is the Ode file
%------Rate equations for requation file------
format bank;
close all;
clear all;
clc;
%time interval
ti=0;
tf=200;
tspan=[ti tf];
x0 = [3.75e7, 2.25e6, 0, 2.25e6, 0]; %initial vectors
%options= odeset('RelTol',100, 'AbsTol',[3.75e7, 2.25e6]);
[t,y]= ode23t(#requations,tspan,x0);
%Plotting the graphs:
figure
subplot(5,1,1), plot(t,y(:,1),'r'),grid on;
title('Laserrate equations'),ylabel('N');
subplot(5,1,2), plot(t,y(:,2),'b'),grid on;
ylabel('Scw'); xlabel('t');
subplot(5,1,3), plot(t,y(:,3),'g'),grid on;
ylabel('ycw');xlabel('t');
subplot(5,1,4), plot(t,y(:,3),'g'),grid on;
ylabel('Sccw');xlabel('t');
subplot(5,1,5), plot(t,y(:,3),'g'),grid on;
ylabel('yccw');xlabel('t');

Related

MATLAB: Linear Poisson Solver using iterative method

I am in the process of writing a 2D non-linear Poisson's solver. One intermediate test I performed is using my non-linear solver to solve for a "linear" Poisson equation. Unfortunately, my non-linear solver is giving me incorrect results, unlike if I try to solve it directly in MATLAB using the backslash ""
non-linear solver iteratively code: "incorrect results"
clearvars; clc; close all;
Nx = 20;
Ny = 20;
Lx = 2*pi;
x = (0:Nx-1)/Nx*2*pi; % x coordinate in Fourier, equally spaced grid
kx = fftshift(-Nx/2:Nx/2-1); % wave number vector
kx(kx==0) = 1; %helps with error: matrix ill scaled because of 0s
ygl = -cos(pi*(0:Ny)/Ny)'; %Gauss-Lobatto chebyshev points
%make mesh
[X,Y] = meshgrid(x,ygl);
%Chebyshev matrix:
VGL = cos(acos(ygl(:))*(0:Ny));
dVGL = diag(1./sqrt(1-ygl.^2))*sin(acos(ygl)*(0:Ny))*diag(0:Ny);
dVGL(1,:) = (-1).^(1:Ny+1).*(0:Ny).^2;
dVGL(Ny+1,:) = (0:Ny).^2;
%Diferentiation matrix for Gauss-Lobatto points
Dgl = dVGL/VGL;
D = Dgl; %first-order derivative matrix
D2 = Dgl*Dgl;
%linear Poisson solved iteratively
Igl = speye(Ny+1);
Ig = speye(Ny);
ZNy = diag([0 ones(1,Ny-1) 0]);
div_x_act_on_grad_x = -Igl; % must be multiplied with kx(m)^2 for each Fourier mode
div_y_act_on_grad_y = D * ZNy *D;
u = Y.^2 .* sin( (2*pi / Lx) * X);
uh = fft(u,[],2);
uold = ones(size(u));
uoldk = fft(uold,[],2);
max_iter = 500;
err_max = 1e-5; %change to 1e-8;
for iterations = 1:max_iter
for m = 1:length(kx)
L = div_x_act_on_grad_x * (kx(m)^2) + div_y_act_on_grad_y;
d2xk = div_x_act_on_grad_x * (kx(m)^2) * uoldk;
d2x = real(ifft(d2xk,[],2));
d2yk = div_y_act_on_grad_y *uoldk;
d2y = real(ifft(d2yk,[],2));
ffh = d2xk + d2yk;
phikmax_old = max(max(abs(uoldk)));
unewh(:,m) = L\(ffh(:,m));
end
phikmax = max(max(abs(unewh)));
if phikmax == 0 %norm(unewh,inf) == 0
it_error = err_max /2;
else
it_error = abs( phikmax - phikmax_old) / phikmax;
end
if it_error < err_max
break;
end
end
unew = real(ifft(unewh,[],2));
DEsol = unew - u;
figure
surf(X, Y, unew);
colorbar;
title('Numerical solution of \nabla^2 u = f');
figure
surf(X, Y, u);
colorbar;
title('Exact solution of \nabla^2 u = f');
Direct solver
ubar = Y.^2 .* sin( (2*pi / Lx) * X);
uh = fft(ubar,[],2);
for m = 1:length(kx)
L = div_x_act_on_grad_x * (kx(m)^2) + div_y_act_on_grad_y;
d2xk = div_x_act_on_grad_x * (kx(m)^2) * uh;
d2x = real(ifft(d2xk,[],2));
d2yk = div_y_act_on_grad_y *uh;
d2y = real(ifft(d2yk,[],2));
ffh = d2xk + d2yk;
%----------------
unewh(:,m) = L\(ffh(:,m));
end
How can I fix code 1 to get the same results as code 2?

Triangle Pulse with fourier transformation

I have a basic exercise for telecommunications with matlab, and i must plot a triangle pulse with (-c,0) to (c,0) with c = 6 and Amplitude = 1 in a for loop for M pulses and approach the periodic pulse using N Fourier series terms. I can't find something on the internet that can help me so far.
A similar code for rect pulse that I made and works is this:
a = 1;
b = 3;
N = 1000;
t = linspace(a-2*a,b+2*b,N);
A = 1;
y = rect_pulse(A,a,b,t);
plot(t,y);
grid on
axis([a-2*a b+2*b 0 2*A]);
M = 5;
T=7;
t_new = linspace(a-2*a,b+(M-1)*T+2*b,N);
y_new = zeros(1,N);
for index = 1:1:M
temp_y = rect_pulse(A,a+(index-1)*T,b+(index-1)*T,t_new);
y_new = y_new + temp_y;
end
figure;
plot(t_new,y_new);
grid on;
axis([a-2*a b+(M-1)*T+2*b 0 2*A]);
Where rect_pulse is this:
function y = rect_pulse (A,a,b,t)
N=length(t);
y = zeros(1,N);
for index = 1:1:N
if(t(1,index)>=a) && (t(1,index)<=b)
y(1,index) = A;
end
end
And fourier series is this:
function y_fourier = fourier_series_rect_pulse(a,b,To,N,t)
y_fourier = 0;
wo = (2*pi)/To;
for n = -N:1:N
f_real = #(x) cos(n*wo*x);
f_imag = #(x) sin(n*wo*x);
cn = (1/To)*(quad(f_real,a,b)) - j*quad(f_imag,a,b));
y_fourier = y_fourier + cn*exp(j*n*wo*t);
end
y_fourier = real(y_fourier);
Any ideas how to make this in to triangle pulse?
This probably deviates significantly from your approach but if you're curious here is a script I came up with to generate a triangular pulse train that can be adjusted. This method, unfortunately, uses the fft() function which may or may not be off-limits in your case. Most of the script uses indexing and manipulating vectors. Additional spectral components may be seen due to the DC offset of the alternating triangular wave and the limited number of cycles available in the vector representation of the triangular wave.
Triangular Pulses and Fourier Transforms:
Triangular Pulse with Duty-Off Period:
Higher frequency spectral components present due to the abrupt corners that occur at the transition states of the triangle pulse and duty-off period.
%******************************************************%
%PROPERTIES THAT CAN BE CHANGED%
%******************************************************%
Plotting_Interval = 0.01; %0.01 seconds%
Pulse_Width = 1/20; %6 seconds%
Period = 1/20; %10 seconds (should be at least the pulse width)%
Start_Time = 0;
End_Time = Pulse_Width*1000; %(1000 pulses)%
%******************************************************%
if(Period < Pulse_Width)
Period = Pulse_Width;
end
Time_Vector = (Start_Time: Plotting_Interval: End_Time);
Points_Per_Unit_Time = 1/Plotting_Interval;
Half_Pulse = Pulse_Width/2;
Number_Of_Points = Pulse_Width/Plotting_Interval;
Rising_Slope = linspace(0,1,floor(Number_Of_Points/2) + 1);
Falling_Slope = 1 - Rising_Slope;
Triangular_Pulse = [Rising_Slope Falling_Slope(2:end)];
t = (0: Plotting_Interval: Pulse_Width);
Periodic_Triangular_Pulse = zeros(1,length(Time_Vector));
for Cycle = 1: +Period/Plotting_Interval: End_Time/Plotting_Interval
Periodic_Triangular_Pulse(1,Cycle:Cycle+length(Triangular_Pulse)-1) = Triangular_Pulse(1,1:end);
end
Periodic_Triangular_Pulse = Periodic_Triangular_Pulse(1,1:length(Time_Vector));
subplot(1,2,1); plot(Time_Vector,Periodic_Triangular_Pulse);
Triangle_Frequency = 1/Period;
title("Triangular Pulse Train " + num2str(Triangle_Frequency) + "Hz (first 10 cycles)");
axis([0 Period*10 0 1]);
xlabel("Time (s)"); ylabel("Amplitude");
Signal_Length = length(Periodic_Triangular_Pulse);
Fourier_Transform = fft(Periodic_Triangular_Pulse);
Fs = 1/Plotting_Interval;
P2 = abs(Fourier_Transform/Signal_Length);
P1 = P2(1:floor(Signal_Length/2)+1);
P1(2:end-1) = 2*P1(2:end-1);
f = Fs*(0:(Signal_Length/2))/Signal_Length;
subplot(1,2,2); plot(f,P1)
title("Single-Sided Fourier Transform");
xlabel("Frequency (Hz)"); ylabel("Magnitude");
Ran using MATLAB R2019b

Fast approach in matlab to estimate linear regression with AR terms

I am trying to estimate regression and AR parameters for (loads of) linear regressions with AR error terms. (You could also think of this as a MA process with exogenous variables):
, where
, with lags of length p
I am following the official matlab recommendations and use regArima to set up a number of regressions and extract regression and AR parameters (see reproducible example below).
The problem: regArima is slow! For 5 regressions, matlab needs 14.24sec. And I intend to run a large number of different regression models. Is there any quicker method around?
y = rand(100,1);
r2 = rand(100,1);
r3 = rand(100,1);
r4 = rand(100,1);
r5 = rand(100,1);
exo = [r2 r3 r4 r5];
tic
for p = 0:4
Mdl = regARIMA(3,0,0);
[EstMdl, ~, LogL] = estimate(Mdl,y,'X',exo,'Display','off');
end
toc
Unlike the regArima function which uses Maximum Likelihood, the Cochrane-Orcutt prodecure relies on an iteration of OLS regression. There are a few more particularities when this approach is valid (refer to the link posted). But for the aim of this question, the appraoch is valid, and fast!
I modified James Le Sage's code which covers only AR lags of order 1, to cover lags of order p.
function result = olsc(y,x,arterms)
% PURPOSE: computes Cochrane-Orcutt ols Regression for AR1 errors
%---------------------------------------------------
% USAGE: results = olsc(y,x)
% where: y = dependent variable vector (nobs x 1)
% x = independent variables matrix (nobs x nvar)
%---------------------------------------------------
% RETURNS: a structure
% results.meth = 'olsc'
% results.beta = bhat estimates
% results.rho = rho estimate
% results.tstat = t-stats
% results.trho = t-statistic for rho estimate
% results.yhat = yhat
% results.resid = residuals
% results.sige = e'*e/(n-k)
% results.rsqr = rsquared
% results.rbar = rbar-squared
% results.iter = niter x 3 matrix of [rho converg iteration#]
% results.nobs = nobs
% results.nvar = nvars
% results.y = y data vector
% --------------------------------------------------
% SEE ALSO: prt_reg(results), plt_reg(results)
%---------------------------------------------------
% written by:
% James P. LeSage, Dept of Economics
% University of Toledo
% 2801 W. Bancroft St,
% Toledo, OH 43606
% jpl#jpl.econ.utoledo.edu
% do error checking on inputs
if (nargin ~= 3); error('Wrong # of arguments to olsc'); end;
[nobs nvar] = size(x);
[nobs2 junk] = size(y);
if (nobs ~= nobs2); error('x and y must have same # obs in olsc'); end;
% ----- setup parameters
ITERMAX = 100;
converg = 1.0;
rho = zeros(arterms,1);
iter = 1;
% xtmp = lag(x,1);
% ytmp = lag(y,1);
% truncate 1st observation to feed the lag
% xlag = x(1:nobs-1,:);
% ylag = y(1:nobs-1,1);
yt = y(1+arterms:nobs,1);
xt = x(1+arterms:nobs,:);
xlag = zeros(nobs-arterms,arterms);
for tt = 1 : arterms
xlag(:,nvar*(tt-1)+1:nvar*(tt-1)+nvar) = x(arterms-tt+1:nobs-tt,:);
end
ylag = zeros(nobs-arterms,arterms);
for tt = 1 : arterms
ylag(:,tt) = y(arterms-tt+1:nobs-tt,:);
end
% setup storage for iteration results
iterout = zeros(ITERMAX,3);
while (converg > 0.0001) & (iter < ITERMAX),
% step 1, using intial rho = 0, do OLS to get bhat
ystar = yt - ylag*rho;
xstar = zeros(nobs-arterms,nvar);
for ii = 1 : nvar
tmp = zeros(1,arterms);
for tt = 1:arterms
tmp(1,tt)=ii+nvar*(tt-1);
end
xstar(:,ii) = xt(:,ii) - xlag(:,tmp)*rho;
end
beta = (xstar'*xstar)\xstar' * ystar;
e = y - x*beta;
% truncate 1st observation to account for the lag
et = e(1+arterms:nobs,1);
elagt = zeros(nobs-arterms,arterms);
for tt = 1 : arterms
elagt(:,tt) = e(arterms-tt+1:nobs-tt,:);
end
% step 2, update estimate of rho using residuals
% from step 1
res_rho = (elagt'*elagt)\elagt' * et;
rho_last = rho;
rho = res_rho;
converg = sum(abs(rho - rho_last));
% iterout(iter,1) = rho;
iterout(iter,2) = converg;
iterout(iter,3) = iter;
iter = iter + 1;
end; % end of while loop
if iter == ITERMAX
% error('ols_corc did not converge in 100 iterations');
print('ols_corc did not converge in 100 iterations');
end;
result.iter= iterout(1:iter-1,:);
% after convergence produce a final set of estimates using rho-value
ystar = yt - ylag*rho;
xstar = zeros(nobs-arterms,nvar);
for ii = 1 : nvar
tmp = zeros(1,arterms);
for tt = 1:arterms
tmp(1,tt)=ii+nvar*(tt-1);
end
xstar(:,ii) = xt(:,ii) - xlag(:,tmp)*rho;
end
result.beta = (xstar'*xstar)\xstar' * ystar;
e = y - x*result.beta;
et = e(1+arterms:nobs,1);
elagt = zeros(nobs-arterms,arterms);
for tt = 1 : arterms
elagt(:,tt) = e(arterms-tt+1:nobs-tt,:);
end
u = et - elagt*rho;
result.vare = std(u)^2;
result.meth = 'olsc';
result.rho = rho;
result.iter = iterout(1:iter-1,:);
% % compute t-statistic for rho
% varrho = (1-rho*rho)/(nobs-2);
% result.trho = rho/sqrt(varrho);
(I did not adapt in the last 2 lines the t-test for rho vectors of length p, but this should be straight forward to do..)

Matlab ODE to solve 2DOF vibrational systems

I'm currently learning Matlab's ODE-functions to solve simple vibration-problems.
For instance mx''+cx'+kx=F*sin(wt) can be solved using
function dx = fun(t,x)
m=0.02; % Mass - kg
k=25.0; % Stiffness - N/m
c=0.0125; % System damping - Ns/m
f=10; % Frequency
F=5;
dx= [x(2); (F*sin(2*pi*f*t)-c*x(2)-k*x(1))/m]
And then calling the ode45 function to get displacement and velocity
[t,x]=ode45(#fun,[0 10],[0.0;0.0])
My question, which I have not fully understood searching the web, is if it is possible to use ODE-function for a multiple degree of freedom system? For instance, if we have two masses, springs and dampers, which we excite att mass 1, we get the following equations:
m1*x1''+c1*x1'-c2*x2'+(k1+k2)*x1-k2*x2 = f1(t)
m2*x2''-c2*x1'+(c1+c2)*x2'-k2*x1+k2*x2 = 0
Here, the displacements x1 & x2 depend on each other, my question is how one should go about to solve these ODE's in Matlab?
There is no restriction that the inputs to the function solved by ODE45 be scalar. Just pass in an input matrix and expect out an output matrix. For example here is a function that solves the position of a 6 bar mechanism.
function zdot = cp_solve(t,z)
%% Constants
g = -9.81;
L1 = .2;
m0 = 0;
I0 = 0;
m1 = 1;
I1 = (1/3) * m1 * L1^2;
%% Inputs
q = z(1:6);
qdot = z(7:12);
%% Mass Matrix
M = zeros(6,6);
M(1,1) = m0;
M(2,2) = m0;
M(3,3) = I0;
M(4,4) = m1;
M(5,5) = m1;
M(6,6) = I1;
%% Constraint Matrix
Phiq = zeros(5,6);
Phiq(1,1) = 1;
Phiq(2,2) = 1;
Phiq(3,3) = 1;
Phiq(4,1) = 1;
Phiq(4,4) = -1;
Phiq(4,6) = (-L1/2)*sin(q(6));
Phiq(5,2) = 1;
Phiq(5,5) = -1;
Phiq(5,6) = (L1/2)*cos(q(6));
%% Generalized Forces
Q = zeros(6,1);
Q(5) = m1 * g;
%% Right Side Vector
rs = zeros(5,1);
rs(4) = (L1/2) * cos(q(6)) * qdot(6)^2;
rs(5) = (L1/2) * sin(q(6)) * qdot(6)^2;
%% Coefficient Matrix
C = [M Phiq'; Phiq zeros(5,5)];
R = [Q; rs];
%% Solution
Sol = C \ R;
zdot = [qdot; Sol(1:6)];
end
The inputs are the positions and velocities of the members. The outputs are the new positions and velocities.
You use it the same way you would any ODE45 problem. Setup the initial conditions, define a time and solve the problem.
%% Constants
L1 = .2;
C1 = L1/2;
theta1 = 30*pi/180;
theta_dot1 = 0;
tspan = 0:.001:2;
%% Initial Conditions
q = zeros(6,1);
q(6) = theta1;
q(4) = C1 * cos(q(6));
q(5) = C1 * sin(q(6));
qdot = zeros(6,1);
qdot(6) = theta_dot1;
z0 = [q; qdot];
%% Solve the problem
options = odeset('RelTol', 1.0e-9, 'AbsTol', 1.0e-6);
[Tout, Zout] = ode45(#cp_solve, tspan, z0, options);
In your case you have 2 equations and 2 unknowns. Set the problem up as a matrix problem and solve it simultaneously in your function. I would recommend the modal approach for your case.

The Euler-Maruyama uses timestep Dt multiple of a step size dt

I wonder if you could help me with this?
why the Euler-Maruyama uses timestep Dt multiple of a step size of the increment dt for the Brownian path ?
http://personal.strath.ac.uk/d.j.higham/em.m
%EM Euler-Maruyama method on linear SDE
%
% SDE is dX = lambda*X dt + mu*X dW, X(0) = Xzero,
% where lambda = 2, mu = 1 and Xzero = 1.
%
% Discretized Brownian path over [0,1] has dt = 2^(-8).
% Euler-Maruyama uses timestep R*dt.
randn('state',100)
lambda = 2; mu = 1; Xzero = 1; % problem parameters
T = 1; N = 2^8; dt = T/N;
dW = sqrt(dt)*randn(1,N); % Brownian increments
W = cumsum(dW); % discretized Brownian path
Xtrue = Xzero*exp((lambda-0.5*mu^2)*([dt:dt:T])+mu*W);
plot([0:dt:T],[Xzero,Xtrue],'m-'), hold on
R = 4; Dt = R*dt; L = N/R; % L EM steps of size Dt = R*dt
Xem = zeros(1,L); % preallocate for efficiency
Xtemp = Xzero;
for j = 1:L
Winc = sum(dW(R*(j-1)+1:R*j));
Xtemp = Xtemp + Dt*lambda*Xtemp + mu*Xtemp*Winc;
Xem(j) = Xtemp;
end
plot([0:Dt:T],[Xzero,Xem],'r--*'), hold off
xlabel('t','FontSize',12)
ylabel('X','FontSize',16,'Rotation',0,'HorizontalAlignment','right')
emerr = abs(Xem(end)-Xtrue(end))