8. WPM algorithm in X frame for big masks

Propagation algorithms for wave optics usually allows masks with a small size, since the propagation step is around the wavelength. When big masks, with long propagation distances is required, the involved matrices are huge and cannot be properly stored.

For this case, we have developed WPM function in X frame, where only a small quantity of data are stored:

  • Field at the end of the simulation.

  • Field at the focus, that is, at position z with the maximum concentration of intensity.

  • Field at an axis.

  • Field at a z axis.

  • Global XZ field, with reduced sampling.

  • XZ field, in a small region of interest.

For this case, we have implemented WPM in X and XY schemes. The refraction index in the XZ or XYZ space is not stored in a matrix, but a function is required.

[27]:
from diffractio import np, plt, sp, um, mm, degrees
from diffractio.scalar_fields_XZ import Scalar_field_XZ
from diffractio.scalar_masks_XZ import Scalar_mask_XZ

from diffractio.scalar_masks_X import Scalar_mask_X
from diffractio.scalar_sources_X import Scalar_source_X

8.1. X scheme

[28]:
# Parameters

x = np.linspace(-3 * mm, 3 * mm, 1024 * 16)
z = np.linspace(-1 * mm, 21 * mm, 1024 * 8)
wavelength = 10 * um

[29]:
dx = x[1] - x[0]
dz = z[1] - z[0]

print("x = {:2.5f}, z = {:2.2f}".format(dx, dz))
print("x/wavelength = {:2.5f}, z/wavelength = {:2.2f}".format(
    dx / wavelength, dz / wavelength))

x = 0.36623, z = 2.69
x/wavelength = 0.03662, z/wavelength = 0.27
[30]:
u0 = Scalar_source_X(x, wavelength)
u0.plane_wave(A=1, theta=0.0, z0=0.0)

[31]:
def fn(x, z, wavelength):
    """refraction index definition for a given example.

    Args:
        x (np.array): x positions
        z (np.array): z positions
        wavelength (float): wavelength

    Returns:
        (np.array): XZ array with refraction index
    """

    u = Scalar_mask_XZ(x, z, wavelength)
    u.sphere(r0=(0, 6 * mm), radius=6 * mm, refractive_index=1.32, angle=0)
    return np.squeeze(u.n)

[32]:
# This would be the standard code, defining huge matrices for refraction index and u field.

if False:
    u_3d = Scalar_mask_XZ(x, z, wavelength)
    u_3d.n = fn(x, z, wavelength)
    u_3d.draw_refractive_index(scale='scaled')
    u_3d.incident_field(u0)
    u_3d.WPM(has_edges=False, matrix=False, verbose=True)
    u_3d.draw(logarithm=True, draw_borders=True, scale='scaled')

[33]:
# Region of interest (ROI)

xout_roi = np.linspace(-500 * um, 500 * um, 256)
zout_roi = np.linspace(15 * mm, 21 * mm, 256)
ROI = (xout_roi, zout_roi)

[34]:
# Execution

u_final_x, u_out_gv, u_out_roi, u_axis_x, u_axis_z, u_max, z_max = u0.WPM(
    fn,
    z,
    ROI=ROI,
    num_sampling=(1024, 1024),
    x_pos=0. * um,
    z_pos=12 * mm,
    get_u_max=True,
    has_edges=False,
    verbose=True)

Time = 39.93 s, time/loop = 4.874 ms

8.2. Output data

[35]:
# Global region

print(u_out_gv)
u_out_gv.draw(logarithm=1e1, draw_borders=True, scale='scaled')

Scalar_mask_XZ
 - x:  (1024,),   z:  (1024,),   u:  (1024, 1024)
 - xmin:       -3000.00 um,  xmax:      3000.00 um,  Dx:   5.87 um
 - zmin:       -1000.00 um,  zmax:      21000.00 um,  Dz:   21.51 um
 - Imin:       0.00,     Imax:      139.19
 - phase_min:  -180.00 deg, phase_max: 180.00 deg
 - wavelength: 10.00 um
 - date:       2022-11-20_18_17_26
 - info:       from WPM_no_storage_1D

../../_images/source_functioning_WPM_ws_11_1.png
[36]:
# Region of interest

print(u_out_roi)
u_out_roi.draw(logarithm=1e-1)

Scalar_mask_XZ
 - x:  (256,),   z:  (256,),   u:  (256, 256)
 - xmin:       -500.00 um,  xmax:      500.00 um,  Dx:   3.92 um
 - zmin:       15000.00 um,  zmax:      21000.00 um,  Dz:   23.53 um
 - Imin:       0.00,     Imax:      142.92
 - phase_min:  -179.99 deg, phase_max: 180.00 deg
 - wavelength: 10.00 um
 - date:       2022-11-20_18_17_27
 - info:       from WPM_no_storage_1D

../../_images/source_functioning_WPM_ws_12_1.png
[37]:
# Field at focus

u_max.draw()
plt.xlim(-10 * wavelength, 10 * wavelength)
plt.ylim(ymin=0)
plt.grid('on')

../../_images/source_functioning_WPM_ws_13_0.png
[38]:
# Field at a x given axis

print("pos focus = {:2.3f} mm".format(z_max / mm))

u_axis_x.draw(z_scale='mm')

plt.ylim(ymin=0)
plt.xlim(z[0] / mm, z[-1] / mm)
plt.grid('on')
pos focus = 18.051 mm
../../_images/source_functioning_WPM_ws_14_1.png
[39]:
# Final field

u_final_x.draw()
plt.ylim(ymin=0)
plt.grid('on')

../../_images/source_functioning_WPM_ws_15_0.png
[40]:
# Field at a z distance

u_axis_z.draw()
plt.grid('on')

../../_images/source_functioning_WPM_ws_16_0.png

8.3. XZ Scheme

[41]:
from diffractio import np, plt, sp, um, mm, degrees
from diffractio.scalar_fields_XYZ import Scalar_field_XYZ

from diffractio.scalar_masks_XY import Scalar_mask_XY
from diffractio.scalar_sources_XY import Scalar_source_XY
from diffractio.scalar_fields_XY import Scalar_field_XY
from diffractio.scalar_masks_XYZ import Scalar_mask_XYZ

[42]:
# Parameters

num_z = 256
x = np.linspace(-50 * um, 50 * um, 512)
y = np.linspace(-50 * um, 50 * um, 512)
z = np.linspace(-10, 150 * um, num_z)
wavelength = 2 * um

dx = x[1] - x[0]
dy = y[1] - y[0]
dz = z[1] - z[0]

print("x = {:2.5f}, x = {:2.5f}, z = {:2.2f}".format(dx, dy, dz))
print("x/l = {:2.2f}, y/l = {:2.2f}, z/l = {:2.2f}".format(
    dx / wavelength, dy / wavelength, dz / wavelength))

x = 0.19569, x = 0.19569, z = 0.63
x/l = 0.10, y/l = 0.10, z/l = 0.31
[43]:
u0 = Scalar_source_XY(x, y, wavelength)
u0.plane_wave(A=1)

[44]:
def fn(x, y, z, wavelegth):
    u = Scalar_mask_XYZ(x, y, z, wavelength)
    u.sphere(r0=(0, 0, 50),
             radius=40 * um,
             refractive_index=1.33,
             angles=(0, 0, 0))
    index = u.n
    del u
    return np.squeeze(index)

[45]:
xout_roi = np.linspace(-20 * um, 20 * um, 128)
yout_roi = np.linspace(-20 * um, 20 * um, 128)
zout_roi = np.linspace(90 * um, 140 * um, 64)
ROI = (xout_roi, yout_roi, zout_roi)

num_sampling = (128, 128, 64)

[46]:
z_pos = 0.1 * mm

[47]:
# Execution

u_final_x, u_out_gv, u_out_roi, u_axis_x, u_axis_z, u_max, z_max = u0.WPM(
    fn,
    zs=z,
    ROI=ROI,
    num_sampling=num_sampling,
    r_pos=(0. * um, 0. * um),
    z_pos=z_pos,
    get_u_max=True,
    has_edges=False,
    verbose=True)

Time = 25.73 s, time/loop = 100.5 ms
[48]:
### Field at axis

u_axis_x.draw()
plt.grid('on')

../../_images/source_functioning_WPM_ws_25_0.png
[49]:
# Field at z distance

u_axis_z.draw(logarithm=1e-1)
plt.title("z={:2.2f} mm".format(z_pos / 100))

../../_images/source_functioning_WPM_ws_26_0.png
[50]:
# Field at focus
u_max.draw(logarithm=1e-1, has_colorbar='vertical')
plt.title("z={:2.2f} mm".format(z_max / 100))

../../_images/source_functioning_WPM_ws_27_0.png
[51]:
#Global view
uxz_gv = u_out_gv.draw_XZ(y0=0, logarithm=1e0)

<Figure size 432x288 with 0 Axes>
../../_images/source_functioning_WPM_ws_28_1.png
[52]:
# Region of interest

u_out_roi.draw_XZ(logarithm=1e-1)

<Figure size 432x288 with 0 Axes>
../../_images/source_functioning_WPM_ws_29_1.png