Skip to content

interference pattern with a focused x-ray beam (spherical coordinates propagation & Steps) #79

@nimloth-a

Description

@nimloth-a

Hello,

In the first place I would like to thank you very much for the LightPipes package. It is very useful!

I am currently using it to simulate the propagation of a soft X-ray gaussian beam (1.42 nm). We focus the beam with a pair KB mirrors at f=3m. I want to simulate the intensity distribution around the focus with and without a spatial mask and I have a few questions.

I use the spherical coordinates. Without spatial mask and propagating with LensFresnel or lensForvard I get a similar result, a very tight focus, as expected.

This is my code:

from LightPipes import *
import matplotlib.pyplot as plt
from matplotlib import cm as colormap
%matplotlib widget
import numpy as np
from tqdm.notebook import tqdm	#(to have progress bars)

grid_dimension = 2000
wavelength = 1.42*nm;
grid_size = 20*mm;
beamsize = 2.2/1.18*mm; 
focal_length = 3*m;

F = Begin(grid_size, wavelength, grid_dimension)
F = GaussBeam(F, beamsize, n=0, m=0, x_shift=0, y_shift=0, tx=0, ty=0, doughnut=False, LG=False)

I = Intensity(0,F);
P = Phase(F);

x=[]
for i in range(grid_dimension):
    x.append((-grid_size/2+i*grid_size/grid_dimension)/mm)
x = np.asarray(x)
X, Y = np.meshgrid(x, x)

fig = plt.figure(figsize=(12,4))
plt.suptitle('Incoming gaussian beam')
ax1 =  fig.add_subplot(131, projection='3d')
ax1.set_xlabel('x (mm)');
ax1.set_ylabel('y (mm)');
ax1.set_zlabel('Intensity (a.u.)');
# ax1.imshow(I_aperture, cmap='rainbow'); 
ax1.plot_surface(X, Y, I, cmap=colormap.coolwarm, linewidth=0, antialiased=False)
ax2 = fig.add_subplot(132)
ax2.plot(x, I[int(grid_dimension/2)], marker = '.'); 
ax2.set_xlabel('x (mm)');
ax2.set_ylabel('Intensity (a.u.)')
ax2.grid('on')
ax3 = fig.add_subplot(133)
ax3.plot(x,P[int(grid_dimension/2)]); 
plt.tight_layout()
plt.show()

image

F_m = F
prop_distance = focal_length
f1 = 3000*m
f2 = f1*focal_length/(f1-focal_length)
frac = focal_length/f1
newsize = frac*grid_size

print('focal_length=',focal_length,'f1=',f1,'f2=',f2,'; grid narrowing=',1/frac)
print('new pixel size = ', newsize/grid_dimension, 'm')
print('expected focus diameter = ', (4*wavelength*focal_length/(np.pi*2*beamsize)), 'm') 

### Single-step propagation
F_m = Lens(F_m, f1, 0, 0);
F_m = LensFresnel(F_m, f2, prop_distance);
#F_m = LensForvard(F_m, f2, prop_distance);
F_m = Convert(F_m);
I_m = Intensity(0, F_m)

x2 = []
for i in range(grid_dimension):
    x2.append((-newsize/2+i*newsize/grid_dimension)/mm)
x2 = np.asarray(x2)
X2, Y2 = np.meshgrid(x2, x2)

### Plotting
fig = plt.figure(figsize=(9,4))
ax1 =  fig.add_subplot(121)
ax1.pcolormesh(X2, Y2, I_m[:,:], cmap=colormap.coolwarm, linewidth=0, antialiased=False)
ax2 = fig.add_subplot(122)
ax2.plot(x2, I_m[int(grid_dimension/2),:], marker = '.',label = 'lensForvard')#, color = color);
ax2.set_xlabel('x [mm]');
ax2.set_ylabel('Intensity [a.u.]')
plt.tight_layout()
plt.show()

The only difference in the results using LensFresnel or LensForvard comes in the beam size (calculated as FWHM).

sx_m, sy_m = D4sigma(F_m)
FWHMx_m = (sx_m/4)*2.35
FWHMy_m = (sy_m/4)*2.35
print('FWHM = ',FWHMx_m, 'm', FWHMy_m, 'm')

Fresnel gives systematically larger values than Forvard. I tested it with optical beams and non-spherical coordinates, and it seems to happen always. However, their intensities at the focus overlap (see figure below). I don’t really understand why this happens, any idea? It seems that Forvard gives the correct value, according to the intensity distribution plot. In my case the beamsize in the focus (FWHM) is 1.15e-06 m according to lensFresnel and 8.55e-07 m according to lensForvard.

image

For the spatial mask I just add these lines to the code before the propagation:

F_m = F
R=0.5*mm; # radius of the holes
d=2*mm; # distance between apertures
F1 = CircAperture(R,-d/2,d/2,F_m);
F2 = CircAperture(R,-d/2,-d/2,F_m);
F3 = CircAperture(R,d/2,d/2,F_m);
F4 = CircAperture(R,d/2,-d/2,F_m);
F_m = BeamMix(BeamMix(BeamMix(F1,F2),F3),F4);

image

Single-step propagation to the focus gives also similar results with both methods:

image

Then I try to explore what happens around the focus, so I propagate to different points close to the focus. To do so, I change the propagation section by the following:

steps_focus = np.arange(2.9*m,3.001*m,0.001*m) 
I_m_focus = np.zeros((len(steps_focus),I_m.shape[0], I_m.shape[1]))

F_ml = Lens(F_m, f1, 0, 0);
for k in tqdm(range(len(steps_focus))):
    F_m_temp = LensFresnel(F_ml, f2, steps_focus[k]);
    # F_m_temp = LensForvard(F_ml, f2, steps_focus[k]);
    F_m_temp = Convert(F_m_temp);
    I_m_temp = Intensity(1, F_m_temp)
    I_m_focus[k,:,:] = I_m_temp

Here already the issue is that I don’t see the focusing of the beam for most of the steps, only when getting really close to the focus.

With No mask, LensFresnel or No mask, lensForvard I get similar results:

image

The beam focusing is only visible when we are very close to the focus. Further away from it, we are not really simulating the focusing, looks like a collimated beam. Any idea why?
Is the idea to simulate the approach to the focus incorrect? I don’t really understand why it does not work… The final grid size is fixed and the same in all cases since it is given by the choice of f1 and f.
The intensity, if not normalized, does change, but the beam diameter does not.

With mask and lensFresnel or lendForvard I get:

image

Which seems to be rather diverging than focusing. For Fresnel I cannot go after the focus, so I use lensForvard to simulate the beam across the focus (steps_focus = np.arange(2.95m,3.05m,0.001*m) ):

No mask, with lensForvard:

image

With mask:

image

I understand the weird behavior in the focus happens because of what is mentioned in the manual “ As the coordinates follow the geometrical section of the light beam, operator LensForvard(10,10,Field) will produce floating exception because the calculations can not be conducted in a grid with zero size (that is so in the geometrical approximation of a focal point).”

But then my question is until which point the simulation is correct? Until the propagation distance is equal to f? without the mask the beam is converging, but with the mask it starts to diverge already when approaching the focus.
And from where is it correct? From where we do observe focusing of the beam? because far from the focus, no focusing is observed.

Then to propagate across the focus, I thought I could do something like propagate close to the focus with spherical coordinates and then around the focus, go back to normal coordinates and use Steps.
So I tried the following:

prop_distance = 2.990*m
F_m = Lens(F_m, f1, 0, 0);
F_m = LensFresnel(F_m, f2, prop_distance);
# F_m = LensForvard(F_m, f2, prop_distance);
F_m = Convert(F_m);
I_m = Intensity(0, F_m)

F_m_steps = F_m
prop_distance_steps = 0.020*m
dz = 0.001*m; 
n=(1+0.00000000001*1j)*np.ones((grid_dimension,grid_dimension)) 
steps = prop_distance_steps/dz;

print('prop_distance = ', prop_distance, 'm; Step = ', dz, 'm; #steps = ', steps )

Icross = np.zeros((int(steps), grid_dimension))

for i in tqdm(range(0, int(steps))):
    F_m_steps = Steps(dz, 1, n, F_m_steps); # Steps(Fin, z, nstep=1, refr=1.0, save_ram=False, use_scipy=False)
    I_m_steps = Intensity(1, F_m_steps);
    if i ==10:
        I_m_steps_d = I_m_steps
    Icross[i][:grid_dimension] = I_m_steps[int(grid_dimension/2)][:grid_dimension]


fig = plt.figure(figsize=(9,4))
ax1 =  fig.add_subplot(121)
ax1.pcolormesh(X2, Y2, I_m_steps_d[:,:], cmap=colormap.coolwarm, linewidth=0, antialiased=False)
ax2 = fig.add_subplot(122)
ax2.pcolormesh(Icross, cmap=colormap.coolwarm, linewidth=0, antialiased=False)
ax2.set_ylabel('steps')
plt.tight_layout()
plt.show()

image

The propagation across the focus looks reasonable and the interference pattern in the focus is actually similar as before. However, the size of the features is significantly smaller (approx. 100 nm vs. 1 micron) than with mask and lensFresnel or lendForvard (see above). I am a bit puzzled why. Any idea? I would assume this last case is more correct but why the other fails and is so different in the simulated size?

Is this propagation scheme consistent?

Sorry for the very long question, and thanks a lot in advance for any help!!!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions