Talbot carpets




The classic effect

When monochromatic coherent light passes through a diffraction grating, the diffraction pattern replicates the structure of the grating at distances given by integral multiples of certain length, the Talbot length, while at fractional multiples one gets shifted or scaled copies of this structure. In general terms, this phenomenon is called the Talbot effect because it was firstly vaguely mentioned by H. F. Talbot in a purely descriptive paper published in 1836 about early experiments on diffraction. Many years later, in 1881, Lord Rayleigh (J. W. Strutt) wrote "On copying diffraction-gratings..." including a theoretical explanation.

The plane diagram combining the 1D diffraction wave intensity patterns at each distance is called the Talbot carpet and it possesses a fractal-like looking structure. Observing real optical Talbot carpets (as well as many other diffraction light phenomena) is not easy. However, a classroom experiment can be devised to visualize the Talbot effect with water waves. Here we show images of artificial Talbot carpets based on the exponential sums coming from diffraction theory that are usually introduced to explain the phenomenon. The images have been generated with the matlab/octave code below (there is also a not very advisable older sagemath version).

Let us consider the slits in a periodic diffraction grating as holes at integers values of the Y-axis. If a monochromatic plane wave of frequency ν and wavelength λ1 enters the diffraction grating from the left half plane, each hole acts as a source of a spherical wave (Huygens-Fresnel principle) and, using the abbreviation e(x)=e2πix, we can model the diffracted wave as u(x,t)=ke(kxνt)with|k|=λ1 and k2Z. Here k is the wave vector as used in crystallography and it differs in a factor 2π from the standard one in physics. The condition k2Z comes from the grating equation.

In reality, the slits in the grating have certain width w and there are many sources of close interacting waves. According to Fraunhofer diffraction, the waves in the preceding sum are affected by the Fourier transform of the characteristic function of an interval (the sinc function). Then, the theoretical diffraction intensity pattern corresponds to the square of F(x,y)=|u(x,y,t)|=||n|λ1sin(nπw)nπe(xλ2n2+ny)|.

The usual explanation of the Talbot effect is that the main contribution to the sum comes from small values of n and the paraxial approximation of the geometrical optics suggests that we can substitute the square root for its first order Taylor expansion in n2. After this substitution, u(x,y,t)e(λ1x) and u(x+2λ1,y,t) are close and we see a periodicity in the diffraction pattern for distances differing in integral multiples of the Talbot length 2λ1. For the case of fractional multiples, we have to take into account the cancellation encoded in the quadratic Gauss sums, which gives a nice relation to number theory.


From the physical perspective, it is natural to consider a density plot of F2 (related to the intensity) rather than of F, but it is visually less appealing. In fact, depending on your taste, plotting Fα with 0<α<1 could give more information. In the following, we plot F all the time. This has nothing to do with Physics, it is more like the histogram equalization in image processing. An aesthetic point is that we use the jet color map (instead of a grayscale) in which blue is for small values and red for larger ones (see a graphic table of several color maps at the end of this page in the Matlab documentation).

Our basic example is:
talb1
λ1=100, w=0.1, resolution 300

The resolution mentioned in the caption is the number of nodes in the X and Y axes to do the evaluations. This means that there are 90000 evaluations of F.

If we change the sinc window function in F by another with exponential decay, the result is in practice as the superposition of few waves, but one still distinguishes the same structure in the Talbot carpet.
talb2
Window =wexp(π2w2x2) with w=0.1

Recovering the original sinc window, if w is decreased, then we have a superposition of many waves and the result tends to be more homogeneous. Usually, we see mainly a blue background because we have very large invisible isolated peaks.

In the following figure corresponding to w=0.03, to avoid the shift of the colormap due to their contribution and observe a less monotone Talbot carpet, we only plot here the points in which the value is below 80% of the maximum.
talb3
λ1=100, w=0.03

Let us increase the value of w equating in the modeled diffraction the width of the slits and the separation between then. It corresponds to the Ronchi grating. In this case, F is more wave like because in the sum we do not have highly oscillation terms with noticeable relative amplitude which could give an approximation to rays in their interference. The plot is in this case:
talb4
λ1=100, w=0.5

If w1 is not much smaller than λ1 then the assumptions of the paraxial approximation are not fulfilled. This is an example with very low frequency:
talb5
λ1=5, w=0.1

The points at which F is very small from what is called here, in a related setting, the "valleys of the shadows". The following figure shows in black the points with values smaller than 10% of the maximum.
talb6
λ1=100, w=0.1, resolution 500
The resolution here is an issue and it has been increased.



The quantum effect

The related setting mentioned in the last paragraph corresponds to the density plots of solutions of the Schrödinger equation. This is called the quantum Talbot effect. The axes of the carpet are time and position. For a circle or a sphere, the Talbot effect considered as a periodicity in time is trivial, as well as in any example with commensurable energy levels. In a broader context this is named quantum revival.

We focus on the example of the sphere, the solution of iΨt=S22ΨwithΨ(θ,0)=fr(θ) where fr is a certain regular function depending on the parameter 0<r<1 and |fr|2 tend to the Dirac δ at the north pole of the sphere as r1. Here, as usual, θ is the polar angle.

Namely, we define for 0<r<1 fr(θ)=crF(r,θ)withF(r,θ)=1(rcosθ)2+sin2θandcr=(2πrlog1+r1r)1/2. A calculation proves that it is normalized as a function on the sphere: S2|fr|2=2π0π|fr(θ)|2sinθdθ=1. Note that cr0 and fr(θ) remains bounded when r1 and 0<θπ. Then |fr|2 tends to the Dirac delta on the north pole of the sphere. As a matter of fact, these calculations are very similar to those showing that the Poisson kernel is an approximation of the identity.

This is the quantum Talbot carpet corresponding to plot the square root of |Ψ(θ,t)|2sinθ for r=0.95. The horizontal axis represents time and the vertical axis represents polar angle. The value of N is the number of terms employed in the eigenfunction expansion. Experimentally, taking it higher does not change substantially the result for this choice of r. Values of r closer to 1 require more terms in the eigenfunction expansion.
talb7
r=0.95, N=1000

If r is reduced, the peaks are not so sharp, as this figure reveals:
talb8
r=0.8, N=1000

For the case r=0.95, these are the "valleys of the shadows" corresponding to points with values smaller than 15% of the maximum.
talb9
r=0.95, N=1000
The figure seems to suggests a fractal like structure


Perfect relativistic revivals

Consider particles confined in a flat torus obtained identifying the opposite sides of [2πR1,0]×[0,2πR2]×{0}. In this situation the cartesian coordinates may be parameterized as x=R1ϕ1, y=R2ϕ2, z=0 with ϕ1 and ϕ2 two 2π-periodic angles. For a fermionic particle ruled by Dirac equation the plane wave solutions are of the form Ψn=12(1+qn2+q2)1/2(100n1+in2q+n2+q2)ei(n1ϕ1+n2ϕ2n2+q2ct/R), where q=McR. The 1-dimensional case corresponds to set n1=0 (so, the state does not depend on ϕ1) and the 2-dimensional case to leave it free.

Up to a rotation, a generic state having a discrete, finite and nonnegative energy spectrum is a superposition of the form Φ=nNλnΨnwithλnC{0} where N={n0,n1,,nN}, nj=(kj,lj)Z2 and kj=0 in the one dimensional model. The energy spectrum is related to the squared norm of the nj. It is the set E={cRkj2+j2+q2:(kj,j)N}. We want to characterize the possible sets N containing n0 such that quantum revivals appear. More concretely, given n0 we want to determine the maximal set of quantum numbers N0 including n0, such that Φ is periodic in t if and only if N is a finite subset of N0.

The set N0 is infinite if and only if q2Q except for 02+q2 being a square in the 1-dimensional case.

Let us start with a 1D example having a finite N0. Consider 0=3 and q=3221. Then N0={(0,±3),(0,±5),(0,±15),(0,±47)}. The corresponding carpet is:
tf1
Full N0 with λn=1.
Matlab/Octave generating code
and omitting the last element
tf2
N0{(0,±47)} with λn=1.
Matlab/Octave generating code

For 0=5, q=2 it can be proved N0={(0,±cn) where n+1=4nn1 with 1=1, 0=5}. Due to the exponential growth of n, even for fairly small cardinalities of N, the state Φ shows large variations for tiny changes of ϕ2 and t and the density plot is close to be a cloud of random points. In this context it is natural to let λn to decay with |n|.

This is the result choosing the six j with smallest absolute values and λn=|n|1/4=|j|1/4.
tf3
j=±1,±5,±19, λn=|j|1/4.
Matlab/Octave generating code
and this is the result adding two more j
tf4
j=±1,±5,±19,±71, λn=|j|1/4.
Matlab/Octave generating code
In these and other examples, it is apparent an underlying structure based on interwoven straight lines with 2 different slopes. The explanation is that in the plane waves, due to the exponential growth, n2+q2/n2 is very early close to the sign of n2 and the pairs of lines correspond to the light cones. In fact if all the j are chosen to be positive, commonly the density plot looks like a dull collection of oblique parallel bands.

To mask the light cones, a possibility is to take q2 large to avoid j2+q2/|j| to be close to 1, at least for the first values of j. With this idea in mind consider the example n0=(0,3) and q=791.

With six values of j it is obtained
tf5
j=±3,±19,±39, q2=791.
Matlab/Octave generating code
and with eight values:
tf6
j=±3,±19,±39,±71, q2=791.
Matlab/Octave generating code

This is a plot of the nodal lines of the first coordinate of the state Φ for N0 with k02+02=1105, q2Q and λn=1 in the range ϕ1,ϕ2[π/2,π/2].
tf7
Nodal lines k02+02=1105, λn=1.
Matlab/Octave generating code

This is the corresponding density plot of |Φ|0.5. As eiEt/ is constant, |Φ| does not depend on t. The exponent 0.5 is only for visualization purposes. It has been introduced to mollify the effect of the peak at ϕ1=ϕ2=0.
tf8
|Φ(ϕ1,ϕ2)|0.5, λn=1.
Matlab/Octave generating code

Consider now the example (k0,0)=(1,2) with q2=3 and take N={(±1,±2),(±2,±1),(±2,±5),(±5,±2),(±2,±11),(±11,±2),(±5,±10),(±10,±5)}. The density plot of the associated state Φ is not feasible because there are three variables (ϕ1,ϕ2,t). To illustrate the situation, the following figure is composed by 4 images showing the density plots in (ϕ1,ϕ2) for t=0,T\rm rev/10,T\rmrev/5 and T\rmrev/10.
tf9
|Φ(ϕ1,ϕ2,kT\rmrev/10)| for k=0,1,2,3, ϕ1,ϕ2[π,π], with λn=1.
Matlab/Octave generating code

The linked codes have been tested with Octave in https://sagecell.sagemath.org/.






The code

This is the Matlab code for the images in the two first sections. There are two programs calling two functions. The first program is:

% Classic Talbot
% Density plot of sqr( |F|^2 )
%

linv = 100; % lambda inverse
w = 0.1; % width
wf = @(x) w*sinc(w*x); % width function
pr = 300; % precision
tol = -1; % tolerance

[X,Y,R] = density_F(linv,wf,pr,tol);
% This is the basic example.
% All the examples have linv = 100

figure(1)
surf(X,Y,R)
colormap(jet(256));
shading interp;
view(0,90)
colorbar
grid off
saveas(gcf,'talb1.png')


w = 0.1; % width
wf = @(x) w*exp(-(pi*w*x)^2); % width function
[X,Y,R] = density_F(linv,wf,pr,tol);


figure(2)
surf(X,Y,R)
colormap(jet(256));
shading interp;
view(0,90)
colorbar
grid off
saveas(gcf,'talb2.png')


w = 0.03; % width
wf = @(x) w*sinc(w*x); % width function
[X,Y,R] = density_F(linv,wf,pr,tol);
R = R.*(R<max(max(R))*0.8);

figure(3)
surf(X,Y,R)
colormap(jet(256));
shading interp;
view(0,90)
colorbar
grid off
saveas(gcf,'talb3.png')


% Ronchi
w = 0.5; % width
wf = @(x) w*sinc(w*x); % width function
[X,Y,R] = density_F(linv,wf,pr,tol);

figure(4)
surf(X,Y,R)
colormap(jet(256));
shading interp;
view(0,90)
colorbar
grid off
saveas(gcf,'talb4.png')

linv = 5;
w = 0.1; % width
wf = @(x) w*sinc(w*x); % width function
[X,Y,R] = density_F(linv,wf,pr,tol);

figure(5)
surf(X,Y,R)
colormap(jet(256));
shading interp;
view(0,90)
colorbar
grid off
saveas(gcf,'talb5.png')


linv = 100;
w = 0.1; % width
wf = @(x) w*sinc(w*x); % width function
pr = 500;
tol = 0.1;
[X,Y,R] = density_F(linv,wf,pr,tol);
% Valley of shadows for the initial example


figure(6)
surf(X,Y,R)
colormap(gray(2));
shading interp;
view(0,90)
grid off
saveas(gcf,'talb6.png')

% colormaps: https://www.mathworks.com/help/matlab/ref/colormap.html
It calls the following function:
function [X,Y,R] = density_F( linv, wf, pr, tol)

  % linv = lambda inverse
  % wf = width function
  % pr = precision
  % tol = tolerance (tol >0 => output clamped to [0, max*tol] )

  % R = Matrix sqr( |F|^2 )

  [X,Y] = meshgrid(linspace(0,2*linv,pr),linspace(-1,1,pr));

  R = 0;
    
  for n = [-linv:linv]
    amp = wf(n);
    R = R + amp * exp( 2*pi*i*(X*sqrt(linv^2-n^2) + n*Y) );
  end

  R = abs(R);

  if tol>0
    M = max(max(R))*tol;
    R = sign(R-M);
  end

end

The second program is:

% Talbot on the sphere with matlab

% v_{ik} = P_k(\cos\theta_i)r^k\sqrt{\sin\theta_i}
% w_{kj} = exp(-i*k*(k+1)*t_j)

% \Psi\sqrt{\sin\theta_i} = c_r \sum_k v_{ik}w_{kj}
% Density plot of sqr( |\Psi|^2\sin\theta )
% = the abs of the previous function

%

r = 0.95; % value of r
N = 1000; % Number of terms in the series
NT = 1024; % Number of nodes in time and angle
tol = -1; % tolerance (tol>0 => valley of shadows)

[TH, T, R] = density_FQ( r, N, NT, tol);

figure(1)
surf(T,TH,R)
colormap(jet(256));
shading interp;
view(0,90)
colorbar
axis([0 pi 0 pi])
grid off
saveas(gcf,'talb7.png')


r = 0.8;
[TH, T, R] = density_FQ( r, N, NT, tol);

figure(2)
surf(T,TH,R)
colormap(jet(256));
shading interp;
view(0,90)
colorbar
axis([0 pi 0 pi])
grid off
saveas(gcf,'talb8.png')

r = 0.95;
tol = 0.15;
[TH, T, R] = density_FQ( r, N, NT, tol);

figure(3)
surf(T,TH,R)
colormap(gray(2));
shading interp;
view(0,90)
axis([0 pi 0 pi])
grid off
saveas(gcf,'talb9.png')
It calls the following function:
function [TH,T,R] = density_FQ( r, N, NT, tol)

  % r = value of r
  % N = Number of terms in the series
  % NT = Number of nodes in time and angle
  % tol = tolarence (tol>0 => valley of shadows)

  th_r = linspace(0,pi,NT);
  t_r = linspace(0,pi,NT);
  [T,K] = meshgrid(t_r,0:N-1);
  W = exp(-i*K.*(K+1).*T);

  % Make v_{ik}

  V = zeros(NT,N);
  ic = 1;
  for th = th_r
    % Fixed theta, Lv = Legendre vector P_k(\cos\theta)
    c = cos(th);
    Lv = [1,c];
    for k = 2:N-1
      res = (2-1/k)*c*Lv(k) + (1/k-1)*Lv(k-1);
      Lv = [Lv,res];
    end

    % Vector r^kP_k(\cos\theta)\sqrt{\sin\theta}
    Lvm = sqrt(sin(th)) * Lv.*(r.^[0:N-1]);

    % Put it in the i-th row
    V(ic,:) = Lvm;
    ic = ic+1;
  end

  % Result
  c_r = ( 2*pi/r * log( (1+r)/(1-r) ) )^-0.5;
  R = abs(c_r*V*W);

  [T,TH] = meshgrid(t_r,th_r);

  if tol>0
    M = max(max(R))*tol;
    R = sign(R-M);
  end

end



This is a previous sagemath code for the classic Talbot carpets. In a standard modern laptop, the plot_carpet commands took 677.6+667.5+676.2+2724+669.3+2623+1451+665.1 seconds, this makes a little less than 3 hours.

import time

y = var('y')


def F(x,y,lamb,w):
  S = w
  K = floor( 1/lamb )
  for k in srange(1,K+1):
    t = 2*pi*(k*y+(sqrt(1/lamb^2-k^2)-1/lamb)*x)
    S += sin(pi*w*k)/(k*pi)*(cos(t)+i*sin(t) + cos(t-4*pi*k*y)+i*sin(t-4*pi*k*y))

  return (S.real_part())^2+ (S.imag_part())^2


def plot_carpet(linv, wi, fname, fsqr, pr, cm='jet'):
  print '====================================='
  l = (1/linv).n()
  print 'l =',l.n(digits=3),' w =',wi.n(digits=3)
  print 'sqr', fsqr, ', pr =',pr,', cmap =',cm
  t = time.time()
  F1 = F(x=x,y=y,lamb=l,w=wi)
  if fsqr: F1 = sqrt(F1)
  P = density_plot(F1, (x,0,2/l), (y,-1.1,1.1), cmap=cm, plot_points=pr)
  print 'elapsed time =', RDF(time.time()-t).n(digits=4)
  print 'saved as:',fname
  print

  P.fontsize(20)
  P.axes(False)
  #P.set_aspect_ratio(1)
  P.save(fname)


plot_carpet(100, 0.1, 't_1.png', False, 200, 'gray')

plot_carpet(100, 0.1, 't_2.png', True, 200, 'gray')

plot_carpet(100, 0.1, 't_3.png', True, 200, 'jet')

plot_carpet(400, 0.1, 't_4.png', True, 200, 'jet')

plot_carpet(100, 0.025, 't_5.png', True, 200, 'jet')

plot_carpet(400, 0.025, 't_6.png', True, 200, 'jet')

plot_carpet(100, 0.1, 't_7.png', True, 300, 'jet')

plot_carpet(100, 0.5, 't_8.png', True, 200, 'jet')