Skip to content

odak.wave.adaptive_sampling_angular_spectrum

A definition to calculate adaptive sampling angular spectrum based beam propagation. For more Zhang, Wenhui, Hao Zhang, and Guofan Jin. "Adaptive-sampling angular spectrum method with full utilization of space-bandwidth product." Optics Letters 45.16 (2020): 4416-4419.

Parameters:

Name Type Description Default
field np.complex

Complex field (MxN).

required
k odak.wave.wavenumber

Wave number of a wave, see odak.wave.wavenumber for more.

required
distance float

Propagation distance.

required
dx float

Size of one single pixel in the field grid (in meters).

required
wavelength float

Wavelength of the electric field.

required

Returns:

Type Description
np.complex

Final complex field (MxN).

Source code in odak/wave/classical.py
def adaptive_sampling_angular_spectrum(field, k, distance, dx, wavelength):
    """
    A definition to calculate adaptive sampling angular spectrum based beam propagation. For more Zhang, Wenhui, Hao Zhang, and Guofan Jin. "Adaptive-sampling angular spectrum method with full utilization of space-bandwidth product." Optics Letters 45.16 (2020): 4416-4419.

    Parameters
    ----------
    field            : np.complex
                       Complex field (MxN).
    k                : odak.wave.wavenumber
                       Wave number of a wave, see odak.wave.wavenumber for more.
    distance         : float
                       Propagation distance.
    dx               : float
                       Size of one single pixel in the field grid (in meters).
    wavelength       : float
                       Wavelength of the electric field.

    Returns
    -------
    result           : np.complex
                       Final complex field (MxN).
    """
    iflag = -1
    eps = 10**(-12)
    nv, nu = field.shape
    l = nu*dx
    x = np.linspace(-l/2, l/2, nu)
    y = np.linspace(-l/2, l/2, nv)
    X, Y = np.meshgrid(x, y)
    fx = np.linspace(-1./2./dx, 1./2./dx, nu)
    fy = np.linspace(-1./2./dx, 1./2./dx, nv)
    FX, FY = np.meshgrid(fx, fy)
    forig = 1./2./dx
    fc2 = 1./2*(nu/wavelength/np.abs(distance))**0.5
    ss = np.abs(fc2)/forig
    zc = nu*dx**2/wavelength
    K = nu/2/np.amax(np.abs(fx))
    m = 2
    nnu2 = m*nu
    nnv2 = m*nv
    fxn = np.linspace(-1./2./dx, 1./2./dx, nnu2)
    fyn = np.linspace(-1./2./dx, 1./2./dx, nnv2)
    if np.abs(distance) > zc*2:
        fxn = fxn*ss
        fyn = fyn*ss
    FXN, FYN = np.meshgrid(fxn, fyn)
    Hn = np.exp(1j*k*distance*(1-(FXN*wavelength)**2-(FYN*wavelength)**2)**0.5)
    FX = FXN/np.amax(FXN)*np.pi
    FY = FYN/np.amax(FYN)*np.pi
    t_2 = nufft2(field, FX*ss, FY*ss, size=[nnv2, nnu2], sign=iflag, eps=eps)
    FX = FX/np.amax(FX)*np.pi
    FY = FY/np.amax(FY)*np.pi
    result = nuifft2(Hn*t_2, FX*ss, FY*ss, size=[nv, nu], sign=-iflag, eps=eps)
    return result

See also