Photonics Examples

Examples of the application in silicon photonics design


A simple IPKISS script : generation of circular and elliptic arcs on GDS layer 0 and export of the structure to GDSII.

from ipkiss.all import *
import sys
from math import *

class ElementsExample(Structure):
         
     def define_elements(self, elems):
         for i in range (5, 50, 5):
                #circular arc
              elems += ArcPath(layer = Layer(0), center = (0,0), 
                           radius  = i, start_angle = 0, 
                           end_angle = 120, line_width = 1.0)

                #elliptical_arc
              elems += EllipseArcPath(layer = Layer(0), center = (120,0), 
                           box_size = (2 * i, i) , start_angle = 45, 
                           end_angle = 270, line_width = 1.0)

         return elems

layout = ElementsExample(name = "layout")
my_lib = Library(name = "ELEMENTS", unit = 1E-6, grid = 5E-9)
my_lib += layout
o= FileOutputGdsii("example_elements.gds")
o.write(my_lib)



The GDSII file looks as follows :
Elliptical paths in IPKISS


Definition of a simple ring resonator with access waveguide using the IPKISS photonics plug-in :
from ipkiss.plugins.photonics.technology.default import *
from ipkiss.plugins.photonics.wg.basic import *
from ipkiss.plugins.photonics.port import *
from ipkiss.all import *

class MyRing(Structure):
radius = PositiveNumberProperty(default = TECH.WG.BEND_RADIUS)
spacing = PositiveNumberProperty(default = TECH.WG.WIRE_WIDTH * 4.0)
wg_definition = WgDefProperty(default = TECH.WGDEF.WIRE)


#specify the elements making up the layout
def define_elements(self, elems):

#the ring
c = ShapeCircle(center = (0.0, 0.0), radius = self.radius,
start_face_angle = 90.0, end_face_angle = 90.0)

#the access waveguide
(w_y_co, w_half_length) = self.get_access_waveguide_specs()
w = Shape([(-w_half_length, w_y_co), (w_half_length, w_y_co)])

#compose to the elements
elems += self.wg_definition(shape = c)
elems += self.wg_definition(shape = w)
return elems

#define the input/output ports
def
define_ports(self, ports):

(w_y_co, w_half_length) = self.get_access_waveguide_specs()
ports += InOpticalPort(position = (-w_half_length, w_y_co),
angle = 180.0,
wg_definition = self.wg_definition)
ports += OutOpticalPort(position = (w_half_length, w_y_co),
angle = 0.0,
wg_definition = self.wg_definition)
return ports


  #'w_y_co' and 'w_half_length' are needed in both
#'define_elements' and 'define_ports'
. Therefore make seperate function.
def get_access_waveguide_specs(self):
w_y_co = -self.radius - self.spacing
w_half_length = self.radius + self.wg_definition.trench_width
return (w_y_co, w_half_length)


wg_def = WgElDefinition(wg_width = 0.60, trench_width = 0.8)
r = MyRing(radius = 5.0, wg_definition = wg_def)
r.write_gdsii("my_ring.gds") 


 


The GDSII file looks as follows :



Manhattan routing between two MMI's and a ring resonator from the Picazzo component library. Virtual fabrication and 2D visualizationof the this structure.

from technologies.si_photonics.picazzo.default import *
from ipkiss.all import *
from ipkiss.plugins.photonics.routing import *
from ipkiss.plugins.photonics.wg import *
from ipkiss.plugins.vfabrication import *
from picazzo.filters.mmi import Mmi1x2Tapered
from picazzo.filters.ring import RingRectNotchFilter


class MyDesign(Structure):
     position_mmi_1 = Coord2Property(required = True)

     position_mmi_2 = Coord2Property(required = True)
     position_ring = Coord2Property(required = True)

     def define_elements(self, elems):
            #create the two MMI's
          mmi_1 = SRef(reference = Mmi1x2Tapered(width = 2.8,
                        length = 8.98, 
                        wg_offset = 0.67, taper_width = 0.8), 

                        position = self.position_mmi_1)
          mmi_2 = SRef(reference = Mmi1x2Tapered(width = 4.8, 
                        length = 12.14, 
                        wg_offset = 0.50, taper_width = 0.7), 

          position = self.position_mmi_2)
          elems += mmi_1
          elems += mmi_2
 

            #create the route from the 1st MMI to the 2nd MMI
          route_mmi =  RouteManhattan(input_port = mmi_1.ports["E1"], 
                                      output_port = mmi_2.ports["W0"])

          elems += RouteConnectorRoundedExpanded(route_mmi)    

            #create the ring resonator
          ring = SRef(
             reference = RingRectNotchFilter(
                ring_wg_definition = WgElDefinition(wg_width = 0.5),

                coupler_wg_definitions = [WgElDefinition(wg_width = 0.4)],
                coupler_spacings = [0.65], 
                straights=(TECH.WG.SHORT_STRAIGHT,TECH.WG.SHORT_STRAIGHT+3.0),),
             position = self.position_ring)
          elems += ring 

            #create the route from the 1st MMI to the ring resonator
          route_ring = RouteManhattan(input_port = mmi_1.ports["E0"], 
                                      output_port = ring.ports["W0"])

          elems += RouteConnectorRoundedExpanded(route_ring)        
          return elems

d = MyDesign(position_mmi_1 = (0.0,50.0),
position_mmi_2 = (60.0,70.0),
position_ring = (60.0,30.0))
d.write_gdsii("design.gds")
d.visualize_2d()


Virtual fabrication (2D) the looks as follows :

Layout multiple components


    Simulation 
    of an MMI aperture in Meep FDTD : Ipkiss is used to export a geometry specification to Meep and launch the simulation in a convenient way with the correct parameters.


From the IPKISS script, we can export a GDSII mask layout :

Mask layout of an MMI aperture


Secondly, we run a virtual fabrication. Using Pysimul, we add a source and fluxplanes. The mode profile of the source is shaped according to the ground mode of the input port (calculated with CAMFR): 

Refractive index landscape for MEEP simulation


We then export
 the geometry to Meep :
Aperture index profile in MEEP.


Finally, we launch an FDTD simulation in Meep with the necessary parameters. 

Animated field of Aperture.