Interoperability

Export a scene to Tidy3D for cross-checking, and import or export planar layout geometry through GDS files.

Maxwell can hand a scene to Tidy3D and read or write planar layouts as GDS. Both adapters need a package that Maxwell does not install, and both live in witwin.maxwell.adapters. Arguments and the full mapping tables are on the Adapters API page.

Install the optional packages#

pip install gdstk     # GDS import and export
pip install tidy3d    # Tidy3D export

If a package is missing, the adapter call raises ImportError with the install command.

Import a GDS layout#

from_gds reads one layer of a GDS file and returns one extruded PolySlab per polygon, with vertices in metres:

import witwin.maxwell as mw
from witwin.maxwell.adapters.gds import from_gds
 
slabs = from_gds("layout.gds", layer=1, bounds=(0.0, 220e-9))   # extrude from z = 0 to 220 nm
silicon = mw.Material(eps_r=12.0)
for index, slab in enumerate(slabs):
    scene.add_structure(mw.Structure(name=f"wg{index}", geometry=slab, material=silicon))
  • bounds is the extrusion range along axis (default "z"), in metres.
  • GDS user units are converted with the file's unit (usually 1 µm). Pass length_scale= (metres per user unit) to override it.
  • Cell references are flattened. If the file has more than one top-level cell, name one with cell=.
  • Select a datatype with datatype= (default 0).

Export geometry to GDS#

to_gds_file writes the cross-sections of PolySlab geometries, for example an optimized layout, to a GDS file in micrometre units:

from witwin.maxwell.adapters.gds import to_gds_file
 
slab = mw.PolySlab(
    vertices=((0.0, 0.0), (2e-6, 0.0), (2e-6, 0.5e-6), (0.0, 0.5e-6)),
    bounds=(0.0, 220e-9),
)
to_gds_file([slab], "waveguide.gds", layer=1)

GDS stores only 2D polygons, so the extrusion bounds and sidewall angle are dropped. Rotated geometry raises ValueError. Reading the file back with from_gds(..., layer=1, bounds=(0.0, 220e-9)) returns the same rectangle.

Export a scene to Tidy3D#

Scene.to_tidy3d(...) builds a tidy3d.Simulation from the scene, so you can run the same problem in Tidy3D and compare:

td_sim = scene.to_tidy3d(frequencies=[1e9])
  • Lengths are converted from metres to micrometres (length_scale=1e6), the Tidy3D convention. Frequencies stay in hertz.
  • frequencies is required for frequency-domain monitors without their own frequencies, for scenes with ports, and for lossy metals.
  • run_time defaults to ten light-crossing times of the largest domain extent. Any other keyword argument is passed to tidy3d.Simulation.

The export maps geometry, materials, most sources, monitors, ports and boundaries one to one. It raises NotImplementedError instead of approximating for features Tidy3D cannot represent, such as magnetic materials, chi2 nonlinearity and density-filtered material regions. Running the result (for example with tidy3d.web.run) needs your own Tidy3D account.

Note

Recent Tidy3D releases print a deprecation warning for RF-scale monitors when the exported scene uses microwave wavelengths. The export still returns a valid tidy3d.Simulation.