AWG generation: Synthesis

Now that we have established and reviewed the subcomponents (slab template, apertures and waveguide model), we can start the synthesis of the AWG.

We will formulate the high-level specifications and translate them into AWG implementation parameters. The inputs required are:

  • The functional specifications: center frequency, number of channels, channel spacing, FSR, …

  • The subcomponents: slab template, apertures, waveguide template

  • Some independent physical specifications that impact optical performance, such as the minimum spacing of the output waveguides

Note

The synthesis algorithm used here is provided by the Luceda AWG Designer and reflect best design practices. It is possible to write your own synthesis algorithm if finer control is needed.

Functional specifications

As mentioned during the introduction, for each AWG project, generate_awg executes all the steps for the AWG generation and returns an AWG PCell. In this project this function is defined in rect_awg/generate.py. Let’s have a look at the function signature.

luceda-academy/training/topical_training/cwdm_awg/rect_awg/generate.py
def generate_awg(fsr, wg_width=0.4, plot=True, save_dir=None, tag=""):
    """Custom AWG generating function. If you make an AWG, you should write one of your own.
    Parameters are the things you want to vary as well as options to control if you
    plot and where you save your data.

    Parameters
    ----------
    fsr : float
          FSR of the AWG in Hz
    wg_width : float, default: 0.4, optional
               Width of the waveguides in the array
    plot : bool, default: True, optional
           If true the AWG is plotted
    save_dir: str, default: None, optional
              If specified, a GDSII file is saved in this directory
    tag: str, optional
         String used to give a name to saved files

    Returns
    -------
    cwdm_awg : i3.PCell
               AWG PCell
    """

    center_frequency = 232200.0  # GHz
    n_channels = 9
    channel_spacing = 800.0  # GHz

The target application uses 8 channels centered around 232.2 THz frequency. The channels are spaced 800 GHz, except around the center where the center frequency itself is not used.

../../../_images/cwdm_awg_channels.png

In this example, we will keep the center channel at 232.2 THz and use it as a monitor output of the AWG. Therefore, we will synthesize the AWG with 9 channels.

Channels

Since we have an AWG with equidistantly spaced frequency channels, we will start by specifying the center frequency, the channel spacing (in Hz) and an array of channel frequencies. Because we will use the center channel as a monitor, we have included it in the specifications.

Free Spectral Range

A second specification is the free spectral range (FSR) of the device. Since this device functions as a demultiplexer and we only utilize one FSR, we make the FSR wider than the span of the channels. This is beneficial so as to reduce the insertion loss non-uniformity. If we had chosen the FSR equal to the number of channels times their spacing, the outer channels would incur about 3 dB of excess loss compared to the center channel, as predicted from AWG theory. If we increase the FSR, the channels will be more uniform. However, if we make the FSR very large, the delay length between the waveguides will become increasingly small, to the extent that it may be difficult to route the waveguide array.

For this reason, here we choose to make the FSR parametric so that benefits and drawbacks of increasing the FSR can be balanced against eachother.

Physical specifications

Now we need to supply a few physical specifications to the synthesis algorithm.

The first specification is how wide we want the angular coverage of the waveguide array to be. This is expressed as an alpha factor parameter, by which the \(1/e^2\) optical beam divergence angle in the star coupler is multiplied. Typically, a value of 1.4-1.6 is used to ensure nearly all diffracted light is captured by the waveguide array.

The second specification is how far we want the output apertures to be spaced. A spacing that is too small will give rise to crosstalk. We prefer the apertures to be sufficiently decoupled, so we want to make this spacing large enough. However, a larger spacing will also require the star coupler to become larger (with constant angular dispersion by the grating and free propagation region). The output spacing chosen will therefore not only affect nearest neighbour crosstalk but also set a minimum for the star coupler diameter. In this case, we choose a minimum center-to-center spacing of 7 um, which should be enough to decouple apertures with a width of 2 um.

luceda-academy/training/topical_training/cwdm_awg/rect_awg/generate.py
    # Physical specifications
    output_aperture_spacing = 7.0
    fpr_alpha_factor = 1.6

Subcomponents

Next, we instantiate the subcomponents. We have already reviewed their definition and model in the previous step, thus we simply construct them.

luceda-academy/training/topical_training/cwdm_awg/rect_awg/generate.py
    # Subcomponents
    print("Instantiating subcomponents...\n")
    slab = SiSlabTemplate()
    simulation_wavelengths = np.linspace(1.25, 1.35, 101)
    slab.SlabModesFromCamfr(wavelengths=simulation_wavelengths)
    aperture = SiRibAperture(slab_template=slab, wire_width=wg_width)
    aperture.CircuitModel(simulation_wavelengths=[1.3])
    aperture_mmi = SiRibMMIAperture(slab_template=slab, wire_width=wg_width)
    aperture_mmi.CircuitModel(simulation_wavelengths=[1.3])
    wg_tmpl = pdk.SiWireWaveguideTemplate()
    wg_tmpl.Layout(core_width=wg_width)

Automated Synthesis

Now that all the necessary inputs are generated, we are ready to derive the implementation parameters. For an equifrequency channel design, this is done using the get_layout_params_1xM_demux_ghz function in the Luceda AWG Designer. This function goes through the whole process of deriving low-level implementation parameters from the functional specifications, subcomponents and physical specifications.

luceda-academy/training/topical_training/cwdm_awg/rect_awg/generate.py
    # Synthesis
    print("Deriving implementation parameters...\n")
    design_params = awg.get_layout_params_1xM_demux_ghz(
        aperture_in=aperture,
        aperture_arms=aperture,
        aperture_out=aperture,
        waveguide_template=wg_tmpl,
        output_spacing=output_aperture_spacing,
        alpha_factor=fpr_alpha_factor,
        M=n_channels,
        center_frequency=center_frequency,
        channel_spacing=channel_spacing,
        FSR=fsr,
        verbose=True,
    )

In addition to returning a Python dictionary with implementation parameters, the synthesis function also prints the relevant parameters and calculations:

Data extracted from slab / waveguide model
------------------------------------------
Channels (in um): [ 1.30913737  1.30457989  1.30005402  1.29555946  1.29109586  1.28666291 1.2822603   1.27788772  1.27354485]
Channels (in GHz): [ 229000.  229800.  230600.  231400.  232200.  233000.  233800.  234600. 235400.]
Effective indices of the waveguide at channels: [array(2.566451906841001), array(2.572459055828688), array(2.5784135232713354), array(2.5843160589299594), array(2.59016721323884), array(2.595967488320401), array(2.6017174289497054), array(2.607417596940138), array(2.6130685399918905)]
Effective index at center wavelength: 2.59016721324
Waveguide group index at center wavelength: 4.28105602782
Effective index of the slab at channels: [ 2.99574066  2.99848965  3.00122092  3.00393478  3.00663138  3.00931078 3.01197315  3.01461861  3.01724732]
Calculated aperture period for the grating = 2.2 um
Radius for input circle: 478.646859193 um (same as R_grating because use_same_radius=True)
Actual delay length (using delay_length_from_FSR): 6.47998556057 um
Specified FSR = 10400.0 GHz
FSR (after snapping the delay length, and approximated at center frequency) = 10806.7661344 GHz
f_min: 227000.0, f_max: 237400.0
Spreading angle of the output aperture (alpha_out) = 36.713402734 degrees
Radius for grating circle of the output star coupler (using get_R_grating): 478.646859193 um
Number of grating elements: 139
Effective # channels in actual FSR = 13.508457668
Angles for the outputs: [ -3.37690610e+00  -2.51997833e+00  -1.67172484e+00  -8.31829409e-01 -3.16175780e-14   8.24040859e-01   1.64056203e+00   2.44982305e+00 3.25207306e+00] (degrees)

Parameters review

The design_params returned by the Luceda AWG Designer are:

  • delay_length: delay length between consecutive waveguides

  • R_grating: the radius of the grating circle at the output star coupler

  • R_input: the radius of the grating circle at the input star coupler

  • N_arms: number of arms in the waveguide array

  • angles_arms_out: angles of the waveguide array apertures at the output star coupler

  • angles_out: angles of the output apertures (at the output star coupler)

  • angles_arms_in: angles of the waveguide array apertures at the input star coupler

We can easily review them by printing the design_params dictionary:

luceda-academy/training/topical_training/cwdm_awg/rect_awg/generate.py
    # Print output
    print("\nDesign parameters:\n")

    if plot:
        print(design_params)

{'R_grating': 478.64685919252588,
 'angles_arms_out': array([
      18.49029633,  18.21283714,  17.93581935,  17.65923441,
      17.38307388,  17.10732943,  16.83199282,  16.55705592,
      16.28251069,  16.00834918,  15.73456353,  15.46114599,
      15.18808886,  14.91538456,  14.64302555,  14.3710044 ,
      14.09931374,  13.8279463 ,  13.55689485,  13.28615224,
      13.01571139,  12.7455653 ,  12.47570702,  12.20612966,
      11.93682639,  11.66779046,  11.39901514,  11.13049379,
      10.86221981,  10.59418665,  10.32638781,  10.05881685,
       9.79146735,   9.52433297,   9.2574074 ,   8.99068436,
       8.72415763,   8.45782102,   8.19166838,   7.9256936 ,
       7.65989061,   7.39425335,   7.12877582,   6.86345205,
       6.59827609,   6.33324201,   6.06834394,   5.803576  ,
       5.53893236,   5.27440721,   5.00999476,   4.74568923,
       4.48148489,   4.21737599,   3.95335684,   3.68942175,
       3.42556503,   3.16178102,   2.89806409,   2.63440858,
       2.37080889,   2.1072594 ,   1.84375451,   1.58028863,
       1.31685616,   1.05345154,   0.79006917,   0.52670351,
       0.26334897,   0.        ,  -0.26334897,  -0.52670351,
      -0.79006917,  -1.05345154,  -1.31685616,  -1.58028863,
      -1.84375451,  -2.1072594 ,  -2.37080889,  -2.63440858,
      -2.89806409,  -3.16178102,  -3.42556503,  -3.68942175,
      -3.95335684,  -4.21737599,  -4.48148489,  -4.74568923,
      -5.00999476,  -5.27440721,  -5.53893236,  -5.803576  ,
      -6.06834394,  -6.33324201,  -6.59827609,  -6.86345205,
      -7.12877582,  -7.39425335,  -7.65989061,  -7.9256936 ,
      -8.19166838,  -8.45782102,  -8.72415763,  -8.99068436,
      -9.2574074 ,  -9.52433297,  -9.79146735, -10.05881685,
     -10.32638781, -10.59418665, -10.86221981, -11.13049379,
     -11.39901514, -11.66779046, -11.93682639, -12.20612966,
     -12.47570702, -12.7455653 , -13.01571139, -13.28615224,
     -13.55689485, -13.8279463 , -14.09931374, -14.3710044 ,
     -14.64302555, -14.91538456, -15.18808886, -15.46114599,
     -15.73456353, -16.00834918, -16.28251069, -16.55705592,
     -16.83199282, -17.10732943, -17.38307388, -17.65923441,
     -17.93581935, -18.21283714, -18.49029633
 ]),
 'angles_out': array([
      -3.37690610e+00,  -2.51997833e+00,  -1.67172484e+00,
      -8.31829409e-01,  -3.16175780e-14,   8.24040859e-01,
       1.64056203e+00,   2.44982305e+00,   3.25207306e+00
 ]),
 'N_arms': 139,
 'angles_arms_in': array([
     -18.49029633, -18.21283714, -17.93581935, -17.65923441,
     -17.38307388, -17.10732943, -16.83199282, -16.55705592,
     -16.28251069, -16.00834918, -15.73456353, -15.46114599,
     -15.18808886, -14.91538456, -14.64302555, -14.3710044 ,
     -14.09931374, -13.8279463 , -13.55689485, -13.28615224,
     -13.01571139, -12.7455653 , -12.47570702, -12.20612966,
     -11.93682639, -11.66779046, -11.39901514, -11.13049379,
     -10.86221981, -10.59418665, -10.32638781, -10.05881685,
      -9.79146735,  -9.52433297,  -9.2574074 ,  -8.99068436,
      -8.72415763,  -8.45782102,  -8.19166838,  -7.9256936 ,
      -7.65989061,  -7.39425335,  -7.12877582,  -6.86345205,
      -6.59827609,  -6.33324201,  -6.06834394,  -5.803576  ,
      -5.53893236,  -5.27440721,  -5.00999476,  -4.74568923,
      -4.48148489,  -4.21737599,  -3.95335684,  -3.68942175,
      -3.42556503,  -3.16178102,  -2.89806409,  -2.63440858,
      -2.37080889,  -2.1072594 ,  -1.84375451,  -1.58028863,
      -1.31685616,  -1.05345154,  -0.79006917,  -0.52670351,
      -0.26334897,   0.        ,   0.26334897,   0.52670351,
       0.79006917,   1.05345154,   1.31685616,   1.58028863,
       1.84375451,   2.1072594 ,   2.37080889,   2.63440858,
       2.89806409,   3.16178102,   3.42556503,   3.68942175,
       3.95335684,   4.21737599,   4.48148489,   4.74568923,
       5.00999476,   5.27440721,   5.53893236,   5.803576  ,
       6.06834394,   6.33324201,   6.59827609,   6.86345205,
       7.12877582,   7.39425335,   7.65989061,   7.9256936 ,
       8.19166838,   8.45782102,   8.72415763,   8.99068436,
       9.2574074 ,   9.52433297,   9.79146735,  10.05881685,
      10.32638781,  10.59418665,  10.86221981,  11.13049379,
      11.39901514,  11.66779046,  11.93682639,  12.20612966,
      12.47570702,  12.7455653 ,  13.01571139,  13.28615224,
      13.55689485,  13.8279463 ,  14.09931374,  14.3710044 ,
      14.64302555,  14.91538456,  15.18808886,  15.46114599,
      15.73456353,  16.00834918,  16.28251069,  16.55705592,
      16.83199282,  17.10732943,  17.38307388,  17.65923441,
      17.93581935,  18.21283714,  18.49029633
 ]),
 'delay_length': 6.4799855605730938,
 'R_input': 478.64685919252588
}

Storing the result

In addition to visualizing them, we can also store these parameters in a file for later use. Using the JSON package, we can save the data in a platform-independent but human-readable format:

luceda-academy/training/topical_training/cwdm_awg/rect_awg/generate.py
    # Saving design parameters
    if save_dir:

        def serialize_ndarray(obj):
            return obj.tolist() if isinstance(obj, np.ndarray) else obj

        json_path = os.path.abspath(os.path.join(save_dir, "awg_design_params_{}.json".format(tag)))
        with open(json_path, "w") as f:
            json.dump(design_params, f, sort_keys=True, default=serialize_ndarray, indent=0)
        print("{} written".format(json_path))

Conclusion

Using the functionality provided by the Luceda AWG Designer, we have synthesized the AWG parameters from functional specifications, subcomponent models and a few physical specifications. In the next step, the derived implementation parameters will be turned into a complete AWG, with a layout and a circuit model.