Tutorial: Own field generators

01/2021: updated to pyGDM v1.1+

In this quick tutorial we demonstrate how to implement a user-defined fundamental field. We will do this at the example of two focused beams with different focal spot and relative phase. All other parameters will be equal for both beams (spotsize, amplitude, phase …)

We first load some modules

import numpy as np
import matplotlib.pyplot as plt

from pyGDM2 import fields
from pyGDM2 import tools
from pyGDM2 import visu

Implement the field generator

We implement the own field generator function calle “double_gaussian”. Internally, it will call gaussian twice with different focal positions and an optional relative phase.

For some processing routines like linear.nearfield, the field generators need to accept a kwarg returnField, which is either “E” or “B” and tells the function wether the electric or magnetic field of the incident field is to be returned. In our case, we simply pass this argument through to the gaussian generator without actively using it.

## ---------- Setup incident field generator, coherent sum of two gaussians
def double_gaussian(pos, env_dict, wavelength,
                   theta_polar1, theta_polar2,
                   xSpot1, ySpot1, zSpot1,
                   xSpot2, ySpot2, zSpot2,
                   spotsize=-1, returnField='E'):
    """Two focused beams, based on `fields.gaussian`

    theta_xxx are linear polarization angles in degrees, 0deg --> X
    relative phase in degrees,
    from pyGDM2 import fields

    ## --- evaluate focused beam twice using the two focal positions
    ## note: we have to pass the 'returnField' argument so automatic electric/magnetic
    ## field calculations will work correctly
    Efield1 = fields.gaussian(pos, env_dict, wavelength,
                              xSpot=xSpot1, ySpot=ySpot1, zSpot=zSpot1,
    Efield2 = fields.gaussian(pos, env_dict, wavelength,
                              xSpot=xSpot2, ySpot=ySpot2, zSpot=zSpot2,
                              phase=relative_phase,     # additional phase on second beam

    ## --- get the complex x/y/z field components as individual arrays for summation
    Ex1, Ey1, Ez1 = Efield1.T
    Ex2, Ey2, Ez2 = Efield2.T

    ## --- add both beams
    Ex = Ex1 + Ex2
    Ey = Ey1 + Ey2
    Ez = Ez1 + Ez2

    ## --- return as fortran array to avoid copying of arrays in memory
    return np.asfortranarray(np.transpose([Ex, Ey, Ez]))

Evaluate the new field generator in a test frame

Now we setup a test-frame in which we evaluate the new double-spot field as well as a single focused plane wave for comparison. We will plot the X-polarized field in the XZ plane.

## --- single focused beam
field_generator_1beam = fields.gaussian
kwargs1 = dict(theta=0,
               spotsize=150, xSpot=0, ySpot=0, zSpot=0)

## --- double beam
field_generator_2beams = double_gaussian
kwargs2 = dict(theta_polar1=0.0, theta_polar2=0.0,
               spotsize=150, relative_phase=180,
               xSpot1=-500, ySpot1=0, zSpot1=0,
               xSpot2=500, ySpot2=0, zSpot2=200)

## --- test-setting for field-evaluation
n3 = 1.0
n2 = 1.0
n1 = 1.0
spacing = 5000.0
env_dict = dict(eps1=n1**2, eps2=n2**2, eps3=n3**2, spacing=spacing)

## --- 2D evaluation volume (plane)
projection = 'XZ'
r_probe = tools.generate_NF_map(-1000,1000,50, -500,1000,50,0, projection=projection)

## --- evaluate the field-generators on the test XZ-map
wavelength = 400
NF_1beam = field_generator_1beam(r_probe, env_dict, wavelength, **kwargs1)
NF_2beams = field_generator_2beams(r_probe, env_dict, wavelength, **kwargs2)

Plot the result of the field-generator

plt.subplot(121, aspect='equal')
v = visu.vectorfield(NF_1beam, r_probe, complex_part='real', projection=projection,
                     tit=projection+' real part, 1 beam', show=0)

plt.subplot(122, aspect='equal')
v = visu.vectorfield(NF_2beams, r_probe, complex_part='real', projection=projection,
                     tit=projection+' real part, 2 beams of opposite phase', show=0)