opticspy / lightpipes

LightPipes for Python, "Pure Python version"
https://opticspy.github.io/lightpipes/
BSD 3-Clause "New" or "Revised" License
227 stars 52 forks source link

Airy Beam #70

Open abbarreto opened 2 years ago

abbarreto commented 2 years ago

Could anyone code a function to create a 2-dim Airy Beam?

FredvanGoor commented 2 years ago

Hi Abbarreto, A good idea! I am working on it, it will be added to the next version of LightPipes. Here is the command, please comment on it:

def AiryBeam(Fin, x0 = 0.001, y0 = 0.001, a1 = 100, a2 = 100):
    """
    *Creates a nonspreading Airy beam.*

        :math:`F(x,y,z=0) = Ai\\left(\\dfrac{x}{x_0}\\right)Ai\\left(\\dfrac{y}{y_0}\\right)e^{a_1x+a_2y}`

    :param Fin: input field
    :type Fin: Field
    :param x0: scale x (default = 1*mm)
    :type x0: int, float
    :param y0: scale y (default = 1*mm)
    :type y0: int, float
    :param a1: degree of apodization x (default = 0.1/mm)
    :type a1: int, float
    :param a2: degree of apodization y (default = 0.1/mm)
    :type a2: int, float

    :return: output field (N x N square array of complex numbers).
    :rtype: `LightPipes.field.Field`
    :Example:

    .. code-block::

        from LightPipes import *
        import matplotlib.pyplot as plt
        wavelength = 1500*nm
        size = 25*mm
        N = 500
        F = Begin(size,wavelength,N)
        F = AiryBeam(F, x0 = 100*um, y0 = 100*um, a1 = 1/mm, a2 = 1/mm)
        F = Fresnel(F, 900*cm)
        I = Intensity(F)
        plt.imshow(I,cmap='jet')
        plt.show()

    .. plot:: ./Examples/Commands/AiryBeam.py

    ref: M. V. Berry and N. L. Balazs, “Nonspreading wave packets,” Am. J. Phys. 47, 264–267 (1979).
    """
    Fout = Field.copy(Fin)
    Y, X = Fout.mgrid_cartesian
    Fout.field = special.airy(X/x0)[0]*special.airy(-Y/y0)[0]*_np.exp(X*a1)*_np.exp(-Y*a2)
    Fout._IsGauss=False
    return Fout

If you want to share a nice application of an Airy beam, please show us a python script... Fred van Goor.

abbarreto commented 2 years ago

Great! It looks better than I tried because regards the finite-energy Airy beam case.

As soon as possible I will share my application with you. We're trying to realize optical simulations of gravitational systems by using Airy Beams.

Thank you so much for your help

abbarreto commented 2 years ago

I thought about define the 1D and 2D versions of Airy Beam. The one you wrote above is 2D. I think that in case 1D we would have:

Fout.field = special.airy(X/x0)[0]*_np.exp(X*a1)*_np.exp(-Y*Y/y0**2)

and the parameter a2 is no longer needed.

FredvanGoor commented 2 years ago

Hi Abbarreto, The minus signs in the AiryBeam2D command were there for plotting the Airy beam in the lower-left quadrant. That was done because of the MatplotLib imshow function has the default origin at the upper left and I want the Airy beam in the lower-left quadrant. I have removed the minus signs in the command and added the origin='lower' option to the imshow command. This is the correct way I believe....

I also made the AiryBeam1D command. The new commands are now:

def AiryBeam1D(Fin, x0 = 0.001, a = 100):
    """
    *Creates a 1D nonspreading Airy beam.*

        :math:`F(x,y,z=0) = Ai\\left(\\dfrac{x}{x_0}\\right)e^{ax}`

    :param Fin: input field
    :type Fin: Field
    :param x0: scale x (default = 1*mm)
    :type x0: int, float
    :param a: degree of apodization x (default = 0.1/mm)
    :type a: int, float

    :return: output field (N x N square array of complex numbers).
    :rtype: `LightPipes.field.Field`
    :Example:

    .. code-block::

        from LightPipes import *
        import matplotlib.pyplot as plt
        import numpy as np

        wavelength = 2.3*um
        size = 30*mm
        N = 500
        N2=N//2
        x0=0.3*mm
        a=0.1/mm
        dz=1.25*cm
        NZ=200

        F0=Begin(size,wavelength,N)
        F0=AiryBeam1D(F0,x0=x0, a=a)
        Ix=np.zeros(N)
        for k in range(0,NZ):
            F=Forvard(F0,dz*k)
            I=Intensity(F)
            Ix=np.vstack([Ix,I[N2]])
        plt.figure(figsize = (12,5))
        plt.imshow(Ix,
                   extent=[-size/2/mm, size/2/mm, 0, NZ*dz/cm],
                   aspect=0.08,
                   origin='lower',
                   cmap='jet',
                   )
        plt.xlabel('x [mm]')
        plt.ylabel('z [cm]')
        s = r'LightPipes for Python' + '\\n'+ '1D Airy beam' + '\\n\\n'\\
            r'$\\lambda = {:4.2f}$'.format(wavelength/um) + r' ${\\mu}m$' + '\\n'\\
            r'$size = {:4.2f}$'.format(size/mm) + r' $mm$' + '\\n'\\
            r'$N = {:4d}$'.format(N) + '\\n'\\
            r'$x_0 = {:4.2f}$'.format(x0/mm) + r' $mm$' + '\\n'\\
            r'$a = $' + '{:4.2f}'.format(a*mm) + r' $/mm$' + '\\n'\\
            r'${\\copyright}$ Fred van Goor, May 2022'
        plt.text(16, 50, s, bbox={'facecolor': 'white', 'pad': 5})
        plt.show()

    .. plot:: ./Examples/Commands/AiryBeam1D.py

    ref: M. V. Berry and N. L. Balazs, “Nonspreading wave packets,” Am. J. Phys. 47, 264–267 (1979).
    """
    Fout = Field.copy(Fin)
    Y, X = Fout.mgrid_cartesian
    Fout.field = special.airy(X/x0)[0]*_np.exp(X*a)
    Fout._IsGauss=False
    return Fout

AiryBeam1D

def AiryBeam2D(Fin, x0 = 0.001, y0 = 0.001, a1 = 100, a2 = 100):
    """
    *Creates a 2D nonspreading Airy beam.*

        :math:`F(x,y,z=0) = Ai\\left(\\dfrac{x}{x_0}\\right)Ai\\left(\\dfrac{y}{y_0}\\right)e^{a_1x+a_2y}`

    :param Fin: input field
    :type Fin: Field
    :param x0: scale x (default = 1*mm)
    :type x0: int, float
    :param y0: scale y (default = 1*mm)
    :type y0: int, float
    :param a1: degree of apodization x (default = 0.1/mm)
    :type a1: int, float
    :param a2: degree of apodization y (default = 0.1/mm)
    :type a2: int, float

    :return: output field (N x N square array of complex numbers).
    :rtype: `LightPipes.field.Field`
    :Example:

    .. code-block::

        from LightPipes import *
        import matplotlib.pyplot as plt
        import numpy as np

        wavelength = 2.3*um
        size = 30*mm
        N = 500
        x0=y0=1*mm
        a1=a2=0.1/mm
        z=900*cm

        F0=Begin(size,wavelength,N)
        F0=AiryBeam2D(F0,x0=x0, y0=y0, a1=a1, a2=a2)
        F=Fresnel(F0,z)
        I=Intensity(F)
        plt.figure(figsize = (9,5))
        plt.imshow(I,
                   extent=[-size/2/mm, size/2/mm, -size/2/mm, size/2/mm],
                   origin='lower',
                   cmap='jet',
                   )
        plt.title('2D Airy beam')
        plt.xlabel('x [mm]')
        plt.ylabel('y [mm]')
        s = r'LightPipes for Python' + '\\n'+ '2D Airy beam' + '\\n\\n'\\
            r'$\\lambda = {:4.2f}$'.format(wavelength/um) + r' ${\\mu}m$' + '\\n'\\
            r'$size = {:4.2f}$'.format(size/mm) + r' $mm$' + '\\n'\\
            r'$N = {:4d}$'.format(N) + '\\n'\\
            r'$x_0 = y_0 = {:4.2f}$'.format(x0/mm) + r' $mm$' + '\\n'\\
            r'$a1 = a2 =  $' + '{:4.2f}'.format(a1*mm) + r' $/mm$' + '\\n'\\
            r'$z = $' + '{:4.2f}'.format(z/cm) + r' $cm$' + '\\n'\\
            r'${\\copyright}$ Fred van Goor, May 2022'
        plt.text(16, -10, s, bbox={'facecolor': 'white', 'pad': 5})
        plt.show()

    .. plot:: ./Examples/Commands/AiryBeam2D.py

    ref: M. V. Berry and N. L. Balazs, “Nonspreading wave packets,” Am. J. Phys. 47, 264–267 (1979).
    """
    Fout = Field.copy(Fin)
    Y, X = Fout.mgrid_cartesian
    Fout.field = special.airy(X/x0)[0]*special.airy(Y/y0)[0]*_np.exp(X*a1)*_np.exp(Y*a2)
    Fout._IsGauss=False
    return Fout

AiryBeam2D

abbarreto commented 2 years ago

Perfect!

FredvanGoor commented 2 years ago

I just released version 2.1.3 with the new AiryBeam1D and AiryBeam2D commands. I also included an example of the generation of an Airy beam from a Gaussian laser beam.