Using the CrossRCW module

In this notebook, we demonstrate the CrossRCW model, which implements rigorous coupled wave (RCW) analysis for cross gratings. First, import the modules we will need:

In [1]:
import matplotlib.pyplot as plt
import numpy as np
from pySCATMECH.crossrcw import *

We will use a cross grating consisting of a square grid of cylindrical holes to demonstrate the use of the module. We set up the grating below and feed it to the RCW solver. I have a file named “fusedsilica” that contains the index of refraction of fused silica as a function of wavelength.

In [2]:
period = 0.5
order = 5
theta = 70

gratingParameters = {
    None : 'Cylinder_CrossGrating',
              'medium_i' : 1,
              'medium_t' : "fusedsilica",
              'zeta' : 0,
              'd1' : period,
              'd2' : period,
              'grid1' : 256,
              'grid2' : 256,
              'rtop' : 0.1,
              'rbottom' : 0.1,
              'thickness' : 0.1,
              'nlevels' : 1,
              'inside' : 1,
              'outside' : "fusedsilica"}

rcwParameters = {
    'thetai' : theta,
    'rotation' : 0,
    'lambda' : 0.532,
    'type' : '0',
    'order1' : order,
    'order2' : order,
    'grating' : gratingParameters
    }

model = CrossRCW_Model(rcwParameters)

Let’s show the NCS parameters (NCS refering to the unique elements of the non-depolarizing Mueller matrix: 01, 22, and 23) for the 0th order diffraction (specular) as a function of wavelength:

In [3]:
wavelengths = np.linspace(0.2, 1.5, 100)

def rcw(wavelength):
    model.setParameter('lambda',wavelength)
    return model.DiffractionEfficiency(0,0)

muellerMatrices = [rcw(wavelength) for wavelength in wavelengths]

N = [m[0,1] for m in muellerMatrices]
C = [m[2,2] for m in muellerMatrices]
S = [m[2,3] for m in muellerMatrices]

plt.figure()
plt.plot(wavelengths*1000, N, label="N")
plt.plot(wavelengths*1000, C, label="C")
plt.plot(wavelengths*1000, S, label="S")
plt.xlabel('$\lambda$/nm')
plt.legend()
plt.show()
Graph showing results of preceding Python code: Three complicated curves labeled N, C, and S as a function of wavelength.

Let’s do the same thing, but rotate the sample 22.5 degrees. The Mueller matrices are no longer block diagonal.

In [4]:
um2eV = 1.239841775
energies = np.linspace(um2eV/0.2,um2eV/1.5,10)

rcwParameters['rotation'] = 22.5

def rcwA(energy):
    rcwParameters["lambda"] = um2eV/energy
    model.setParameters(rcwParameters)
    m = model.DiffractionEfficiency(0,0)
    m, m[0,0] = m/m[0,0],m[0,0] # Normalize the matrix, keeping the m[0,0] element
    return m

muellerMatrices = [rcwA(E) for E in energies]

plt.figure(figsize = [13,13])
for element in range(16):
    plt.subplot(4,4,element+1)
    plt.ylim(-1,1)
    plt.plot(energies,[muellerMatrices[i][element//4,element%4] for i in range(len(energies))],'b:')

plt.show()
Graph showing results of preceding Python code: Four by four array of panes, each with one curve.

Finally, let’s visualize the diffraction pattern from a hexagonal grating having a large period.

In [5]:
period = 2
order = 10
theta = 25

gratingParameters = {
    None : 'Cylinder_CrossGrating',
              'medium_i' : 1,
              'medium_t' : 1, # Free standing
              'zeta' : 30,    # Hexagonal pattern
              'd1' : period,
              'd2' : period,
              'grid1' : 256,
              'grid2' : 256,
              'rtop' : period/4,
              'rbottom' : period/4,
              'thickness' : 100, # Very deep
              'nlevels' : 1,
              'inside' : 1,     # Holes in
              'outside' : 1.5   # glass
            }

rcwParameters = {
    'thetai' : theta,
    'rotation' : 0,
    'lambda' : 0.532,
    'type' :   1,  # in transmission
    'order1' : order,
    'order2' : order,
    'grating' : gratingParameters
    }

model.setParameters(rcwParameters)

def plotDiffractionPattern(model):
    order1 = int(model.getParameter("order1"))
    order2 = int(model.getParameter("order2"))
    x, y, I = [], [], []
    for i in range(-order1,order1):
        for j in range(-order2,order2):
            # Direction() function gets the direction
            direction = model.Direction(i,j)
            if direction[2] != 0 :
                x.append(direction[0])
                y.append(direction[1])
                I.append(model.DiffractionEfficiency(i,j)[0,0])

    thetas = np.linspace(0, 2*pi, 100)
    circlex = np.cos(thetas)
    circley = np.sin(thetas)

    plt.figure(figsize = (10,10))
    ax = plt.subplot(111)
    ax.scatter(x, y, s=np.array(I)*2000) # You may need to adjust this size scaling
    ax.plot(circlex, circley, c = 'r')
    plt.show()

plotDiffractionPattern(model)
Graph showing results of preceding Python code: The unit circle with circles of different sizes on hexagonal grid.