Make a S-shaped AWG

This simple example illustrates how to make an S-shaped AWG and how to run a Caphe simulation on it. For this example, we use the IPKISS AWG Designer module.

Getting started

We start by importing the technology with other required modules:

from si_fab import all as pdk  # noqa: F401
from ipkiss3 import all as i3
import numpy as np
import pylab as plt
import time

import awg_designer.all as awg
from si_fab_awg import all as awg_pdk

Template for the free propagation region This defines the layers, slab modes, etc.

slab_t = awg_pdk.SiSlabTemplate()
slab_t.Layout()
slab_t.SlabModes(modes=[awg.SimpleSlabMode(name="TE0", n_eff=2.8, n_g=3.2, polarization="TE")])

N = 44  # number of arms
R = 150.0  # radius of the star couplers
W = 2.0  # aperture width
M = 8  # outputs

The aperture

Make virtual aperture

ap = awg_pdk.SiRibAperture(
    slab_template=slab_t,
    aperture_core_width=W,
    aperture_cladding_width=1.0,
)
ap_lo = ap.Layout()
ap_sm = ap.FieldModelFromCamfr()
ap_cm = ap.CircuitModel(simulation_wavelengths=[1.55])

The input star coupler

Make a multi-aperture for the arms consisting of N apertures like these, arranged in a circle and get the transformations of the individual apertures.

angle_step = i3.RAD2DEG * (W + 0.2) / R
angles_arms = np.linspace(-angle_step * (N - 1) / 2.0, angle_step * (N - 1) / 2.0, N)
ap_arms_in, _, trans_arms_in, trans_ports_in = awg.get_star_coupler_apertures(
    apertures_arms=[ap] * N,
    apertures_ports=[ap],
    angles_arms=angles_arms,
    angles_ports=[0],
    radius=R,
    mounting="confocal",
    input=True,
)

Make the input star coupler

sc_in = awg.StarCoupler(aperture_in=ap, aperture_out=ap_arms_in)

sc_in_lo = sc_in.Layout(
    contour=awg.get_star_coupler_extended_contour(
        apertures_in=[ap],
        apertures_out=[ap] * N,
        trans_in=trans_ports_in,
        trans_out=trans_arms_in,
        radius_in=R,
        radius_out=R,
        extension_angles=(10, 5),
    )
)
sc_in_lo.visualize()
plot S awg
/bbotworker/DEPLOY_IPKISSDOC/build/_ftb/awg_designer/components/star_coupler/layout.py:425: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
  front_shapes = np.array([fs[::-1] for fs in front_shapes])

<Figure size 640x480 with 1 Axes>

The output star coupler

Make the multi-apertures for the outputs and get the transformations for the individual apertures.

angle_step = i3.RAD2DEG * (4.7) / R
angles_ports = np.linspace(angle_step * (M - 1) / 2.0, -angle_step * (M - 1) / 2.0, M)
ap_arms_out, ap_out, trans_arms_out, trans_ports_out = awg.get_star_coupler_apertures(
    apertures_arms=[ap] * N,
    apertures_ports=[ap] * M,
    angles_arms=angles_arms,
    angles_ports=angles_ports,
    radius=R,
    mounting="rowland",
    input=False,
)

Make the output star coupler

sc_out = awg.StarCoupler(aperture_in=ap_arms_out, aperture_out=ap_out)
sc_out_lo = sc_out.Layout(
    contour=awg.get_star_coupler_extended_contour(
        apertures_in=[ap] * N,
        apertures_out=[ap] * M,
        trans_in=trans_arms_out,
        trans_out=trans_ports_out,
        radius_in=R,
        radius_out=R / 2,
        extension_angles=(10, 10),
    )
)
sc_out_lo.visualize()
plot S awg
/bbotworker/DEPLOY_IPKISSDOC/build/_ftb/awg_designer/components/star_coupler/layout.py:425: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
  front_shapes = np.array([fs[::-1] for fs in front_shapes])

<Figure size 640x480 with 1 Axes>

The S shaped waveguide array

Choose the waveguide template

from picazzo3.traces.wire_wg.trace import WireWaveguideTemplate  # noqa: E402

straight_tmpl = WireWaveguideTemplate()
straight_tmpl.Layout(core_width=i3.TECH.WG.WIRE_WIDTH)
straight_tmpl.CircuitModel(n_eff=2.81, n_g=4.2)
<WireWaveguideTemplate.CircuitModel view 'WIRE_WG_TEMPLATE_2:circuitmodel'>

Make the SWaveguideArray

delays = [10 * i for i in range(N)]
wg_array = awg.SWaveguideArray(start_ports=sc_in_lo.east_ports, end_ports=sc_out_lo.west_ports, delay_lengths=delays)
wg_array_lo = wg_array.Layout(offset_output_ports_south=15)
wg_array_lo.visualize(annotate=False)
plot S awg
<Figure size 640x480 with 1 Axes>

The Arrayed Waveguide Grating

Make an AWG with the 3 building blocks

s_awg = awg.ArrayedWaveguideGrating(star_coupler_in=sc_in, star_coupler_out=sc_out, waveguide_array=wg_array)
awg_lo = s_awg.Layout()
awg_lo.visualize()
plot S awg
<Figure size 640x480 with 1 Axes>

Running the Caphe simulation

print("Running Caphe simulation (with wavelength-independent star couplers)")
sc_in.CircuitModel(simulation_wavelengths=[1.55])
sc_out.CircuitModel(simulation_wavelengths=[1.55])
awg_cm = s_awg.CircuitModel()
wavelengths = np.linspace(1.52, 1.58, 401)

t0 = time.time()
S = awg_cm.get_smatrix(wavelengths)
print("Calculation time:", time.time() - t0)

for i in range(1, M + 1):
    plt.plot(wavelengths, 10 * np.log10(np.abs(S["in1", "out{}".format(i)]) ** 2), label="out{}".format(i))

plt.xlabel("wavelength")
plt.ylabel("transmission [dB]")
plt.legend()
plt.ylim([-80, 0])
plt.show()
plot S awg
Running Caphe simulation (with wavelength-independent star couplers)
/bbotworker/DEPLOY_IPKISSDOC/build/ipkiss/boolean_ops/boolean_ops_elements.py:132: ShapelyDeprecationWarning: The 'cascaded_union()' function is deprecated. Use 'unary_union()' instead.
  shapely_polygon = cascaded_union(MultiPolygon(shapely_polygons))
/bbotworker/DEPLOY_IPKISSDOC/build/ipkiss/boolean_ops/boolean_ops_elements.py:227: ShapelyDeprecationWarning: The array interface is deprecated and will no longer work in Shapely 2.0. Convert the '.coords' to a numpy array instead.
  shape = shapely_geom_to_shape(geom)
/bbotworker/DEPLOY_IPKISSDOC/build/dependencies/shapely_wrapper.py:112: ShapelyDeprecationWarning: The 'cascaded_union()' function is deprecated. Use 'unary_union()' instead.
  up = cascaded_union(mp)
/bbotworker/DEPLOY_IPKISSDOC/build/ipkiss/plugins/vfabrication/geometry.py:144: ShapelyDeprecationWarning: The array interface is deprecated and will no longer work in Shapely 2.0. Convert the '.coords' to a numpy array instead.
  shape = shapely_geom_to_shape(geom)
/bbotworker/DEPLOY_IPKISSDOC/build/ipkiss3/algorithms/shape_cutting.py:50: ShapelyDeprecationWarning: STRtree will be changed in 2.0.0 and will not be compatible with versions < 2.
  tree = STRtree(polys)
/bbotworker/DEPLOY_IPKISSDOC/build/ipkiss3/algorithms/shape_cutting.py:53: ShapelyDeprecationWarning: The array interface is deprecated and will no longer work in Shapely 2.0. Convert the '.coords' to a numpy array instead.
  interiors = [np.array(interior) for interior in g.interiors]
/bbotworker/DEPLOY_IPKISSDOC/build/ipkiss/boolean_ops/boolean_ops_shapely.py:77: ShapelyDeprecationWarning: The array interface is deprecated and will no longer work in Shapely 2.0. Convert the '.coords' to a numpy array instead.
  s = shapely_geom_to_shape(poly)
Calculation time: 63.56149911880493