Calculations/Estimations/GaussianABCDCalculator.m

301 lines
8.6 KiB
Mathematica
Raw Normal View History

%% Define a beam and visualize it propagating
% Define "optical system" using matrices. For this first example, we will just use a free space propagation matrix, and let the beam propagate a distance
w0 = 1E-3; % 1mm beam waist
lam = 421E-9; % wavelength
zR = Zr(w0, lam); % Rayleigh range in m
z0 = 0; % location of waist in m
syms d; % Define 'd' as a symbolic variable
M = propagator(d);
[R, w] = q1_inv_func(0, w0, lam, M); % Do all the ABCD and q-parameter math, and return the waist and radius of curvature functions
plotResult(w, d, linspace(0,10))
%% Add a lens to the system
w0 = 1E-3; % 1mm beam waist
lam = 421E-9; % wavelength
zR = Zr(w0, lam); % Rayleigh range in m
z0 = 0; % location of waist in m
syms d; % Define 'd' as a symbolic variable
M = matmultiplier(propagator(d), lens(.5), propagator(1));
[R, w] = q1_inv_func(0, w0, lam, M);
plotResult(w, d, linspace(0,1,50))
%% Add another to make a beam expander, that enlarges the beam waist by a factor 5 and then collimates it
w0 = 1E-3; % 1mm beam waist
lam = 421E-9; % wavelength
zR = Zr(w0, lam); % Rayleigh range in m
z0 = 0; % location of waist in m
expansion_factor = 5;
syms d1 d2 d3 f1 f2
M = matmultiplier(propagator(d3), lens(f2), propagator(d2), lens(f1), propagator(d1));
[R, w] = q1_inv_func(0, w0, lam, M);
% Substitute values into w
w = subs(w, {d1, d3}, {1, 0});
% Solve for f1
f1_eq = solve(w - expansion_factor*w0 == 0, f1);
f1_eq_subs = subs(f1_eq, d2, 1);
% Convert solutions to numeric values
f1_val_numeric = double(f1_eq_subs);
fprintf('f1 = %.2f m or %.2f m, for a lens separation of 1 meter\n', f1_val_numeric(1), f1_val_numeric(2))
for i = 1:length(f1_val_numeric)
f1_val = f1_val_numeric(i);
R = subs(R, {d1, d2, d3, f1}, {1, 1, 0, f1_val});
f2_val = solve(1/R == 0, f2);
fprintf('f2 = %.2f, for a collimated beam, 5x the original waist, after propagating 1m to the first lens of f1 = %.2f, and propagating another 1m to the second lens\n', double(f2_val), double(f1_val))
end
chosen_f1_val = f1_val_numeric(1);
fprintf('Chosen f1 = %.2f m \n', chosen_f1_val)
M = matmultiplier(propagator(d3), lens(f2_val), propagator(1), lens(chosen_f1_val), propagator(1));
[R, w] = q1_inv_func(0, w0, lam, M);
plotResult(w,d3)
estimated_expansion_factor = subs(w, d3, 0)/ w0;
fprintf('beam is w = %.2f x w0\n', double(estimated_expansion_factor))
beam_size_change = ((subs(w,d3,10) - subs(w,d3,0)) / subs(w,d3,0)) * 100;
fprintf('Over 10 m after second lens, beam changes by %.5f percent\n', double(beam_size_change))
%% Function definitions
% Input Ray parameter, i.e. height and angle
function ret = ray(y, theta)
% Parameters
% ----------
% y : float or integer in meters
% The vertical height of a ray.
% theta : float or integer in radians
% The angle of divergence of the ray.
%
% Returns
% -------
% mat : 2x1 matrix
% [
% [y],
% [theta]
% ]
ret = [y; theta];
end
% Ray Transfer Matrix for ideal lens with focal length f
function ret = lens(f)
% Parameters
% ----------
% f : float or integer in meters
% Thin lens focal length in meters
%
% Returns
% -------
% mat : 2x2 matrix
% [
% [ 1, 0],
% [-1/f, 1]
% ]
ret = [1, 0; -1/f, 1];
end
% Ray Transfer Matrix for propagation over a distance d
function ret = propagator(d)
% Parameters
% ----------
% d : float or integer
% Distance light is propagating along the z-axis.
%
% Returns
% -------
% mat: 2x2 matrix
% [
% [1, d],
% [0, 1]
% ]
ret = [1, d; 0, 1];
end
% Multiplying the matrices together. mat1 is the last matrix the light interacts with.
function ret = matmultiplier(mat, varargin)
% Parameters
% ----------
% mat1 : 2x2 ABCD matrix
% Last matrix light interacts with.
% varargin : 2x2 ABCD matrices
% From left to right, the matrices should be entered such that the leftmost matrix interacts
% with light temporally after the rightmost matrix.
%
% Returns
% -------
% Mat : 2x2 matrix
% The ABCD matrix describing the whole optical system.
ret = mat;
for i = 1:length(varargin)
ret = ret * varargin{i};
end
end
% Adding Gaussian beam parameters
function zr = Zr(wo, lam)
% Parameters
% ----------
% wo : float or integer
% Beam waist radius in meters.
% lam : float or integer
% Wavelength of light in meters.
%
% Returns
% -------
% zr : float or integer
% Rayleigh range for given beam waist and wavelength.
zr = pi * wo^2 / lam;
end
% Calculate beam waist radius
function w0 = W0(zr, lam)
% Parameters
% ----------
% zr : float or integer
% Rayleigh range in meters.
% lam : float or integer
% Wavelength of light in meters.
%
% Returns
% -------
% w0 : float or integer
% Beam waist radius in meters.
w0 = sqrt(lam * zr / pi);
end
function [z_out, zr_out] = q1_func(z, w0, lam, mat)
% Parameters
% ----------
% z : float or integer
% Position of the beam waist in meters.
% w0 : float or integer
% Radial waist size in meters (of the embedded Gaussian, i.e. W0/M).
% lam : float or integer
% Wavelength of light in meters.
% mat : 2x2 matrix
% The ABCD matrix describing the optical system.
%
% Returns
% -------
% z_out : float or integer
% Position of the beam waist after the optical system.
% zr_out : float or integer
% Rayleigh range of the beam after the optical system.
A = mat(1, 1);
B = mat(1, 2);
C = mat(2, 1);
D = mat(2, 2);
% Calculate Rayleigh range for the given beam waist and wavelength
zr = Zr(w0, lam);
% Calculate real and imaginary parts
real_part = (A * C * (z^2 + zr^2) + z * (A * D + B * C) + B * D) / (C^2 * (z^2 + zr^2) + 2 * C * D * z + D^2);
imag_part = (zr * (A * D - B * C)) / (C^2 * (z^2 + zr^2) + 2 * C * D * z + D^2);
% Output the new position and Rayleigh range
z_out = real_part;
zr_out = imag_part;
end
function [R, w] = q1_inv_func(z, w0, lam, mat)
% Parameters
% ----------
% z : float or integer
% Position of the beam waist in meters.
% w0 : float or integer
% Radial waist size in meters (of the embedded Gaussian, i.e. W0/M).
% lam : float or integer
% Wavelength of light in meters.
% mat : 2x2 matrix
% The ABCD matrix describing the optical system.
%
% Returns
% -------
% R : float or integer
% Radius of curvature of the wavefront in meters.
% w : float or integer
% Radius of the beam in meters.
A = mat(1, 1);
B = mat(1, 2);
C = mat(2, 1);
D = mat(2, 2);
% Calculate Rayleigh range for the given beam waist and wavelength
zr = Zr(w0, lam);
% Calculate real and imaginary parts
real_part = (A * C * (z^2 + zr^2) + z * (A * D + B * C) + B * D) / (A^2 * (z^2 + zr^2) + 2 * A * B * z + B^2);
imag_part = -zr * ((A * D) - (B * C)) / (A^2 * (z^2 + zr^2) + (2 * A * B * z) + B^2);
% Calculate radius of curvature and beam radius
R = 1/real_part;
w = sqrt(-lam / imag_part / pi);
end
function plotResult(func, var, rang)
% Parameters
% ----------
% func : symfun (symbolic function of one variable)
% Symbolic function defining the beam width after the last optical element.
% var : symbolic variable
% Variable in func that will be plotted.
% rang : array (optional)
% Array of values along the optical axis to be plotted. Default range is 0 to 3 with step size 0.01.
% Set default range if not provided
if nargin < 3
rang = 0:0.01:3;
end
% Create a numeric function from the symbolic function
func_handle = matlabFunction(func, 'Vars', var);
% Compute the values of the function and its negative
y_vals = func_handle(rang) * 1E3; % in mm
y_neg_vals = -y_vals;
% Create a figure
figure;
set(gcf, 'Position', [100 100 950 750]);
% Plot the function and its negative
plot(rang, y_vals, 'b'); hold on;
plot(rang, y_neg_vals, 'b');
% Fill the area between the curves with translucent blue color
fill([rang, fliplr(rang)], [y_vals, fliplr(y_neg_vals)], 'b', 'FaceAlpha', 0.2, 'EdgeColor', 'none');
% Add grid and labels
grid on;
xlabel('Optical Axis (m)', 'FontSize', 16);
ylabel('Beam size (mm)', 'FontSize', 16);
end