Long running time with loops, is it possible to cancel the loops?

1 view (last 30 days)
Hi
I have a code with many loops but it runs forever.
Could you please take a look and let me know if somehow i can change to make it different?
% Clear variables and command window
clear
clc
% Constants and Parameters
c = 299792458; % Speed of light [m/s]
twidth = 500e-15; % Time window [s]
%twidth = 30e-12;
n = 2^14; % Number of points
lambda0 = 795e-9; % Center wavelength [m]
W0 = 2*pi*c/lambda0; % Center frequency [rad/s]
FWHM = 34e-15; % Initial pulse duration [s]
Epsilon_0 = 8.8541878128*1e-12;
% Time domain
T = linspace(-twidth/2, twidth/2, n); % Time grid
dt = T(2) - T(1);
Dnu = 1/dt;
delta_T = twidth/n; % Time interval [s]
% Gaussian pulse in time domain
y = exp(1i*W0*T); % Carrier
sigma = FWHM/((2*log(2))^0.5);
gaussian = exp(-T.^2/sigma^2);
N = sqrt(sum(gaussian.^2)*dt);
gaussian = gaussian/N;
fin_t = y.*gaussian; % Electric field in time domain
% Spatial domain
x = linspace(-5e-3, 5e-3, 256);
dx = x(2) - x(1);
w0 = 13e-3/2;
w0 = 2e-3/2;
[X, Y] = meshgrid(x);
gaussian_space = exp(-(X.^2 + Y.^2)/w0^2);
N = sqrt(sum(sum(gaussian_space.^2))*(dx)^2);
gaussian_space = gaussian_space / N;
Average_power = 14; % watt
Laser_operation_freq = 5e3; % Laser operation freq
Pulse_energy = Average_power / Laser_operation_freq;
Total_initial_energy = 0.5*c*Epsilon_0*(sum(sum(gaussian_space.^2))*(dx)^2) * (sum(gaussian.^2)*dt);
Normalization = sqrt(Total_initial_energy/Pulse_energy);
% Electric field in spatial and time domain
E_x_y_t = zeros(length(x), length(x), length(T));
for i = 1:length(x)
for j = 1:length(x)
for k = 1:length(T)
E_x_y_t(i, j, k) = (1/Normalization)*gaussian_space(i, j) * fin_t(k);
end
end
end
% Create frequency grids
frequencies = linspace(-Dnu/2, Dnu/2, n); % Frequency grid (time dimension)
n_x = length(x);
dfx = 1/(x(end)-x(1));
dfy = 1/(x(end)-x(1));
fx = linspace(-dfx*(n_x/2), dfx*(n_x/2), n_x); % Frequency grid (x dimension)
fy = linspace(-dfy*(n_x/2), dfy*(n_x/2), n_x); % Frequency grid (y dimension)
% Sellmier equetion for fused silica
B1 = 0.6961663;
C1 = 0.0684043^2;
B2 = 0.4079426;
C2 = 0.1162414^2;
B3 = 0.8974794;
C3 = 9.896161^2;
wavelength_freq_um = 1e6*c./frequencies; %wavelength in um
n_square_silica = 1 + B1 .* wavelength_freq_um.^2 ./ (wavelength_freq_um.^2 - C1) + B2 .* wavelength_freq_um.^2 ./ (wavelength_freq_um.^2 - C2) + B3 .* wavelength_freq_um.^2 ./ (wavelength_freq_um.^2 - C3);
n_silica = sqrt(n_square_silica);
k_w = 2.*pi*frequencies.*n_silica./c;
n2_silica = 2.19*1e-20;
Length_fused_sil = 10e-3; % fused silica length
dz = 100e-6;
Number_of_steps = round(Length_fused_sil/dz);
% step number = 0
E_f = fftshift(fft(E_x_y_t, [], 3),3); % Frequency domain signal
spectrum = abs(E_f(length(x)/2,length(x)/2,:)).^2; % Spectrum
spectrum = reshape(spectrum, 1, []);
Spectra(: , 1) = spectrum;
for step_number = 1:Number_of_steps
% Perform FFT along the time dimension
E_x_y_f = fft(E_x_y_t, [], 3);
% Perform FFT along the spatial dimensions
E_fx_fy_f = fft2(E_x_y_f);
% Shift the data for intuitive frequency arrangement
E_fx_fy_f_shifted = fftshift(fftshift(fftshift(E_fx_fy_f, 1),2), 3);
% Define phase shift, for example linearly dependent on frequency
% Apply phase shift
Vg = c / 1.4673 ; % 1.4673 is the group index for 795nm in fused silica
for i = 1:length(fx)
for j = 1:length(fy)
for k = 1:length(frequencies)
phase_shift = sqrt(k_w(k)^2 - (2*pi*fx(i))^2 - (2*pi*fy(j))^2)*dz; % phase shift
delta_f = frequencies(k) - c/lambda0; %freq shift for Vgroup compensation
%delta_f = 0;
E_fx_fy_f_shifted(i,j,k) = E_fx_fy_f_shifted(i,j,k) .* exp(1i * phase_shift)*exp(-1i*2*pi*delta_f *dz/Vg); %with group time delay compensation
end
end
end
% Unshift the data before inverse FFT
E_fx_fy_f = ifftshift(ifftshift(ifftshift(E_fx_fy_f_shifted, 1), 2),3);
% Perform inverse FFT along the spatial dimensions
E_x_y_f_back = ifft2(E_fx_fy_f);
% Perform inverse FFT along the time dimension
E_x_y_t_back = ifft(E_x_y_f_back, [], 3);
for i = 1:length(x)
for j = 1:length(x)
for k = 1:length(T)
Intensity = 0.5*c*Epsilon_0*1.4534*abs(E_x_y_t_back(i,j,k))^2; % 1.4534 refractive index for center freq. - need to addapt later
phase_shift = (2*pi/lambda0)*n2_silica*Intensity*dz; % phase shift
E_x_y_t_back(i,j,k) = E_x_y_t_back(i,j,k) .* exp(1i * phase_shift);
end
end
end
E_x_y_t = E_x_y_t_back;
% Calculate and store the spectrum at this step
E_f = fftshift(fft(E_x_y_t, [], 3),3); % Frequency domain signal
spectrum = abs(E_f(length(x)/2,length(x)/2,:)).^2; % Spectrum
spectrum = reshape(spectrum, 1, []);
% Store the spectrum for this step in the Spectra array
Spectra(: , step_number+1) = spectrum;
end
% After the loop, plot the Spectra array as a color image
figure(1);
imagesc(1:step_number+1, frequencies, 10*log10(Spectra));
colorbar; % Add a colorbar to the figure
xlabel('Step'); % Label the x-axis
ylabel('Frequency'); % Label the y-axis
title('Spectrum evolution');
ylim([1 7]*1e14)
% % Verify that E_x_y_t and E_x_y_t_back are equal (within a numerical tolerance)
% diff = E_x_y_t - E_x_y_t_back;
% tol = 1e-12;
% disp(['Maximum absolute difference between E_x_y_t and E_x_y_t_back: ', num2str(max(abs(diff(:))))]);
% if max(abs(diff(:))) < tol
% disp('E_x_y_t and E_x_y_t_back are equal within the specified tolerance.');
% else
% disp('E_x_y_t and E_x_y_t_back are NOT equal within the specified tolerance.');
% end
Also, for some reason the next line doesn't work, I assume that's because of the 'y' here
imagesc(1:step_number, c./frequencies, 10*log10(Spectra));
Thanks

Answers (1)

Steven Lord
Steven Lord on 16 May 2023
Let's look at the number of iterations you perform in each loop. Pulling out appropriate sections of your code to define the variables used to create the data over which you iterate (leaving it commented out because we don't actually need to run it, just to refer to it):
%{
twidth = 500e-15; % Time window [s]
%twidth = 30e-12;
n = 2^14; % Number of points
lambda0 = 795e-9; % Center wavelength [m]
W0 = 2*pi*c/lambda0; % Center frequency [rad/s]
FWHM = 34e-15; % Initial pulse duration [s]
Epsilon_0 = 8.8541878128*1e-12;
% Time domain
T = linspace(-twidth/2, twidth/2, n); % Time grid
% Spatial domain
x = linspace(-5e-3, 5e-3, 256);
E_x_y_t = zeros(length(x), length(x), length(T));
for i = 1:length(x)
for j = 1:length(x)
for k = 1:length(T)
E_x_y_t(i, j, k) = (1/Normalization)*gaussian_space(i, j) * fin_t(k);
end
end
end
%}
So your outer loop runs 256 times as does your middle loop. Your innermost loop runs 2^14 times. That's:
format longg
numInnermostExecutions = 256*256*(2^14)
numInnermostExecutions =
1073741824
just over a billion executions of the innermost loop. You haven't showed us what your fin_t function is doing, but I'd execute that function once on the T vector (if it's vectorized, or once per element of T if it's not) and then compute E_x_y_t using implicit expansion. No loops required. As an example of a similar operation:
M = magic(4)
M = 4×4
16 2 3 13 5 11 10 8 9 7 6 12 4 14 15 1
fin_t_vector = (1:3).^2 % Let's say your function was fin_t = @(t) t.^2
fin_t_vector = 1×3
1 4 9
E = M .* reshape(fin_t_vector, 1, 1, [])
E =
E(:,:,1) = 16 2 3 13 5 11 10 8 9 7 6 12 4 14 15 1 E(:,:,2) = 64 8 12 52 20 44 40 32 36 28 24 48 16 56 60 4 E(:,:,3) = 144 18 27 117 45 99 90 72 81 63 54 108 36 126 135 9
I haven't looked too closely at the later loops but I suspect you may be able to use a similar approach to avoid executing your functions billions of times.
See this documentation page for more information on implicit expansion and how it may allow you to avoid performing scalar operations over and over and over again.
  5 Comments
Steven Lord
Steven Lord on 19 May 2023
Have you run your code through MATLAB Profiler to identify the bottlenecks?
Does Code Analyzer offer any suggestions for places and ways where you could improve performance?
elis02
elis02 on 27 May 2023
Hi
I used the beam profiler tp optimized but still need more memory (larger 3d matrixes - more dense x, and larger t) and ofcourse for it to run faster.
Attaching the updated code.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!