FDTD Lumerical#
gdsfactory provides you with a Lumerical FDTD interface to calculate Sparameters automatically (without you having to click around the Lumerical GUI)
The function gplugins.lumerical.write_sparameters_lumerical
brings up a GUI, runs simulation and then writes the Sparameters both in .CSV and .DAT (Lumerical interconnect / simphony) file formats, as well as the simulation settings in YAML format.
In the CSV format each Sparameter will have 2 columns, o1@0,o2@0
where m
stands for magnitude and s12a
where a
stands for angle in radians.
For the simulation to work well, your components need to have ports, that will be extended automatically to go over the PML.
The script internally calls the lumerical python API lumapi
so you will need to make sure that you can run this from python.
import lumapi
session = lumapi.FDTD()
In linux that may require you to export the PYTHONPATH variable in your shell environment.
You can add one line into your .bashrc
in your Linux machine.
[ -d "/opt/lumerical" ] && export PATH=$PATH:/opt/lumerical/$(ls /opt/lumerical)/bin && export PYTHONPATH=/opt/lumerical/$(ls /opt/lumerical)/api/python
Finally, You can chain the Sparameters to calculate solve of larger circuits using a circuit solver such as
Lumerical interconnect
import gdsfactory as gf
from gdsfactory.generic_tech import LAYER_STACK, get_generic_pdk
import gplugins.lumerical as sim
gf.config.rich_output()
PDK = get_generic_pdk()
PDK.activate()
sim.write_sparameters_lumerical?
import lumapi
s = lumapi.FDTD()
gf.components.cells.keys()
components = [
"bend_euler",
"bend_s",
"coupler",
"coupler_ring",
"crossing",
"mmi1x2",
"mmi2x2",
"taper",
"straight",
]
need_review = []
for component_name in components:
component = gf.components.cells[component_name]()
sim.write_sparameters_lumerical(component, run=False, session=s)
response = input(f"does the simulation for {component_name} look good? (y/n)")
if response.upper()[0] == "N":
need_review.append(component_name)
Modify layer stack#
All layers information is passed to the Lumerical simulator through the layer_stack
Layer thickness#
You can modify the thickness of any specific layer of the stack. For example lets increase the core thickness to 230 nm
LAYER_STACK
layer_stack2 = LAYER_STACK
nm = 1e-3
layer_stack2["core"].thickness = 230 * nm
layer_stack2["core"].thickness
sim.write_sparameters_lumerical(
gf.components.mmi1x2(), layer_stack=layer_stack2, run=False, session=s
)
You will be able to see the layer thickness increase in the lumerical GUI
Layer material or index#
You can also modify the material refractive index or material name from the Lumerical Material database
material: material spec, can be
a string from lumerical database materials.
a complex for n, k materials.
a float or int, representing refractive index.
LAYER_STACK
material_name_to_lumerical = dict(si=3.6)
sim.write_sparameters_lumerical(
gf.components.mmi1x2(),
layer_stack=layer_stack2,
run=False,
session=s,
material_name_to_lumerical=material_name_to_lumerical,
)
component = gf.components.mmi1x2()
material_name_to_lumerical = dict(si=(3.45, 2)) # or dict(si=3.45+2j)
r = sim.write_sparameters_lumerical(
component=component,
material_name_to_lumerical=material_name_to_lumerical,
run=False,
session=s,
)
material_name_to_lumerical = dict(si="InP - Palik")
sim.write_sparameters_lumerical(
gf.components.mmi1x2(),
layer_stack=layer_stack2,
run=False,
session=s,
material_name_to_lumerical=material_name_to_lumerical,
)
gdsfactory can also compute the Sparameters of a component that have not been simulated before.
sim.write_sparameters_lumerical(gf.components.mmi1x2())
sim.plot.plot_sparameters(gf.components.mmi1x2(), keys=["S23m", "S13m"], logscale=True)
As well as a group of components
components = [
gf.components.coupler_ring(gap=gap, radius=radius)
for gap in [0.15, 0.2, 0.3]
for radius in [5, 10]
]
for c in components:
c.show()
print(c)
sim.write_sparameters_lumerical(c)
To debug a simulation you can create a Lumerical session outside the simulator, pass it to the simulator, and use run=False
flag
s = lumapi.FDTD()
c = gf.components.straight()
sim.write_sparameters_lumerical(c, run=False, session=s)
By default gdsfactory uses the generic LayerStack for 0.22um height silicon layer.
You can also define any LayerStack
def get_layer_stack():
return gf.tech.LayerStack(
wg=gf.tech.LayerLevel(layer=(1, 0), thickness=400e-3, zmin=0.0, material="sin")
)
layer_stack = get_layer_stack()
c = gf.components.straight()
s = sim.write_sparameters_lumerical(c, layer_stack=layer_stack, run=False, session=s)