Code of the Angular Spectrum Method

Click For Summary

Discussion Overview

The discussion revolves around the implementation of the Angular Spectrum Method in MATLAB for simulating diffraction patterns. Participants explore issues related to the persistence of diffraction patterns at increasing distances and the correctness of the code provided by the original poster.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Mathematical reasoning

Main Points Raised

  • The original poster expresses confusion about why the diffraction pattern does not disappear as the distance increases, contrary to their expectations.
  • Some participants suggest debugging the code by stepping through computations to identify where issues may arise.
  • Concerns are raised about the naming of the variable "gamma," which conflicts with a built-in MATLAB function, potentially leading to confusion.
  • One participant notes that the condition for setting elements of "gamma" to zero appears to be ineffective, as all values remain non-zero in their execution.
  • Another participant proposes an alternative approach to the Angular Spectrum Method, using a different formulation for the electric field propagation.
  • One participant modifies the original code to improve clarity and functionality, suggesting changes to the handling of the Fourier transform and the visualization of results.

Areas of Agreement / Disagreement

Participants do not reach a consensus on the original poster's issue with the diffraction pattern. Multiple viewpoints and proposed solutions are presented, indicating ongoing debate and exploration of the topic.

Contextual Notes

Participants highlight potential limitations in the original code, including the handling of spatial frequency coordinates and the need for clearer variable definitions. The discussion reflects uncertainty regarding the effectiveness of certain code segments and their impact on the diffraction pattern.

Who May Find This Useful

This discussion may be useful for individuals interested in computational optics, specifically those working with diffraction simulations and the Angular Spectrum Method in MATLAB.

ecastro
Messages
249
Reaction score
8
I constructed my code of the Angular Spectrum Method. However, as the distance between the object and the plane of interest increases, the diffraction pattern never disappears; there is still some sort of a diffraction pattern, and I am expecting that it disappears as distance increases.

Here is the code:

Matlab:
clear; clc;

layer = zeros(499, 499);
diameter = 100*10^(-6);
radius = diameter/2;
wavelength = 500*10^(-9);
altitude = 2*10^(-3);
img_width = 1*10^(-3);
img_length = 1*10^(-3);

lambda = wavelength;                          % wavelength (meters)
z = altitude;                                 % altitude (meters)
k = 2*pi/lambda;                              % wavenumber
phy_x = img_width;                            % physical width (meters)
phy_y = img_length;                           % physical length (meters)
obj_size = size(layer);

% alpha and beta (wavenumber components)
dx = linspace(-phy_x/2, phy_x/2, obj_size(2));
dx = dx(1:length(dx));
dy = linspace(-phy_y/2, phy_y/2, obj_size(1));
dy = dy(1:length(dy));

for i = 1:obj_size(2);
    for j = 1:obj_size(1)
        if sqrt(dx(i)^2 + dy(j)^2) <= radius;
            layer(j, i) = 1;
        end;
    end;
end;

U0 = fftshift(fft2(layer));

Fs_x = obj_size(2)/img_width; 
Fs_y = obj_size(1)/img_length;

dx2 = Fs_x^(-1); 
dy2 = Fs_y^(-1);

x2 = dx2*(0:(obj_size(2) - 1))'; 
y2 = dy2*(0:(obj_size(1) - 1))';

dFx = Fs_x/obj_size(2); 
dFy = Fs_y/obj_size(1);

Fx = (-Fs_x/2:dFx:(Fs_x/2 - dFx)); 
Fy = (-Fs_y/2:dFy:(Fs_y/2 - dFy));

alpha = lambda.*Fx; beta = lambda.*Fy;

% gamma
gamma = zeros(length(beta), length(alpha));
for j = 1:length(beta);
    for i = 1:length(alpha);
        if (alpha(i)^2 + beta(j)^2) > 1;
            gamma(j, i) = 0;
        else
            gamma(j, i) = sqrt(1 - alpha(i)^2 - beta(j)^2);
        end;
    end;
end;

U1 = ifft2(fftshift(fft2(layer)).*exp(1i*k.*gamma.*z));
I1 = (1/(16*pi)).*(U1.*conj(U1));

I think my error came from the calculation of the alpha and beta components. I just don't know where...

Thank you in advance.
 
Physics news on Phys.org
I adjusted your post as it looked like MATLAB code and I split some lines where you did assignements like somex = some_expression; somey=some_expression;

Have you tried stepping through the computation to see where things go astray?
 
Everything seems to be working fine at very small distances, where diffraction is expected to occur. However, as I increase the distance ##z##, the diffraction never disappears.
 
Aside: gamma is a built-in MATLAB function, so you probably shouldn't name your variable with the same name as it will interfere with that functionality for you and anyone that runs your program.

The variable z only shows up in one place after it is defined: as an exponent to exp in the calculation of U1. I assume this U1 is the diffraction pattern that you want? (You might want to comment your code better so that it's clear what all the variables are.)

The only other quantity of exp that could change is gamma, which depends on alpha and beta. Upon looking at gamma, I realized that your section of code that sets elements of gamma to zero is "dead" (seemingly not used):

Code:
if (alpha(i)^2 + beta(j)^2) > 1;
            gamma(j, i) = 0;

When I ran your program, gamma has all nonzero values:

Code:
nnz(gamma)/numel(gamma)

ans =

     1

So there might be something up there, if you were expecting some elements of gamma to be zero. But ultimately, if gamma is unchanged and you vary z, then the exp term gets bigger and bigger. I would expect the exponent to be negative here if you wanted the exp term to disappear as z increases.
 
kreil said:
Aside: gamma is a built-in MATLAB function, so you probably shouldn't name your variable with the same name as it will interfere with that functionality for you and anyone that runs your program.


I forgot that ##\texttt{gamma}## is a built-in function!

kreil said:
The variable z only shows up in one place after it is defined: as an exponent to exp in the calculation of U1. I assume this U1 is the diffraction pattern that you want? (You might want to comment your code better so that it's clear what all the variables are.)


Yes, it is the diffraction pattern that I want. Sorry for not putting comments on my code.

kreil said:
The only other quantity of exp that could change is gamma, which depends on alpha and beta. Upon looking at gamma, I realized that your section of code that sets elements of gamma to zero is "dead" (seemingly not used):

Code:
if (alpha(i)^2 + beta(j)^2) > 1;
            gamma(j, i) = 0;

When I ran your program, gamma has all nonzero values:

Code:
nnz(gamma)/numel(gamma)

ans =

     1

So there might be something up there, if you were expecting some elements of gamma to be zero. But ultimately, if gamma is unchanged and you vary z, then the exp term gets bigger and bigger. I would expect the exponent to be negative here if you wanted the exp term to disappear as z increases.


The condition is to disregard evanescent waves as they do not contribute to the diffraction pattern. I guess these show-up at certain values of ##z##.
Anyway, I just resolved the issue by not using spatial frequency coordinates, thank you!
 
Ok, glad you were able to resolve the problem! Consider posting the solution here for the benefit of others.
 
kreil said:
Ok, glad you were able to resolve the problem! Consider posting the solution here for the benefit of others.

Instead of guessing the spatial frequency values of the Fourier transformed electric field, which is done after ##\texttt{U0}## and before the definition of ##\texttt{gamma}##, I consider this another form of the angular spectrum method:

##\mathbf{\hat{E}} \left(k_x, k_y; z\right) = \mathbf{\hat{E}} \left(k_x, k_y; 0\right) e^{\pm i k_z z}##

where ##k_z = \frac{k z}{\sqrt{x^2 + y^2 + z^2}}##, and ##k = \frac{2\pi}{\lambda}##. I then used the inverse Fourier transform to plot the electric field at ##x, y, z##.
 
Hi ecastro,

I modified your code, delete some unnecessary parts and add a figure show to visualize the results. And note that instead of
Code:
U1 = ifft2(fftshift(fft2(layer)).*exp(1i*k.*gamma_cust.*z));

you should use
Code:
U1 = ifft2(ifftshift(fftshift(fft2(layer)).*exp(1i*k.*gamma_cust.*z)));
instead, since you fftshift the spectrem first, you need to first iffshift it back then can you impose the fft2 on the scalar field. Although the results seem to be the same because the captured intensity is equals abs(U1.*conj(U1))

The modified code is following:
Code:
clc; clear; close all;

% parameters
layer = zeros(499, 499);
diameter = 100e-6;
radius = diameter/2;
lambda = 500e-9;            % wavelength (meters)
k = 2*pi/lambda;            % wavenumber
z = 2e-4;                      % altitude (meters)
phy_x = 1e-3;               % physical width (meters)
phy_y = 1e-3;               % physical length (meters)
obj_size = size(layer);

% generate meshgrid
dx = linspace(-phy_x/2, phy_x/2, obj_size(2));
dx = dx(1:length(dx));
dy = linspace(-phy_y/2, phy_y/2, obj_size(1));
dy = dy(1:length(dy));

% generate a circle aperture
for i = 1:obj_size(2)
    for j = 1:obj_size(1)
        if sqrt(dx(i)^2 + dy(j)^2) <= radius;
            layer(j, i) = 1;
        end
    end
end

Fs_x = obj_size(2)/phy_x;
Fs_y = obj_size(1)/phy_y;
dx2 = Fs_x^(-1);
dy2 = Fs_y^(-1);
dFx = Fs_x/obj_size(2);
dFy = Fs_y/obj_size(1);
Fx = (-Fs_x/2:dFx:(Fs_x/2 - dFx));
Fy = (-Fs_y/2:dFy:(Fs_y/2 - dFy));

% alpha and beta (wavenumber components)
alpha = lambda.*Fx;
beta = lambda.*Fy;

% gamma_cust
gamma_cust = zeros(length(beta), length(alpha));
for j = 1:length(beta)
    for i = 1:length(alpha)
        if (alpha(i)^2 + beta(j)^2) > 1
            gamma_cust(j, i) = 0;
        else
            gamma_cust(j, i) = sqrt(1 - alpha(i)^2 - beta(j)^2);
        end
    end
end

% angular spectrm based formula
U1 = ifft2(ifftshift(fftshift(fft2(layer)).*exp(1i*k.*gamma_cust.*z)));
I1 = (1/(16*pi)).*(U1.*conj(U1));

% show results
figure;     imshow(layer, []);      title('circular aperture');
figure;     imshow(I1, []);         title('angular spectrum based diffraction');
 

Similar threads

  • · Replies 1 ·
Replies
1
Views
6K
  • · Replies 4 ·
Replies
4
Views
2K
  • · Replies 5 ·
Replies
5
Views
2K
  • · Replies 7 ·
Replies
7
Views
3K
  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 1 ·
Replies
1
Views
4K
  • · Replies 1 ·
Replies
1
Views
19K
  • · Replies 2 ·
Replies
2
Views
3K
Replies
5
Views
8K
Replies
1
Views
2K