gds2openEMS: FDTD simulation workflow for RFIC
The files provided here enable openEMS EM simulation with layouts created for the IHP SG13G2 RFIC technology.
Install
pip install gds2openEMS
Full documentation, installation guide, and usage walkthrough: https://github.com/VolkerMuehlhaus/gds2openEMS
Recent changes
03-Nov-2026 (0.7.0)
Bugfix: ports that excite nothing. A lumped port acts only on the mesh edges inside its box. A via port drawn as a zero-width line needs a mesh line exactly in its plane, and the xy mesh could lose it: lines closer than 0.8 × refined_cellsize are merged, and two port edges of equal weight were replaced by one line in the middle, e.g. the planes of two ports 0.1 µm apart. Such a port injected no energy, its probes stayed 0, and openEMS never reached energy_limit. Found with a 15-port export from the KLayout plug-in klayout_em_export, where 3 ports were dead at refined_cellsize 0.5. After the xy mesh, every port without a mesh line in x or y now gets one, at its center or in the plane of a zero-width port ("Port meshing: added N mesh line(s)"). Other ports and the rest of the mesh are unchanged.
Ports with different reference impedances: S-parameters are now ratios of power waves, S_ij = uf_ref_i / uf_inc_j · sqrt(Z0_j / Z0_i) (utilities.power_wave_ratio()). Before, the plain ratio of voltage waves gave wrong values when the ports had different port_Z0, e.g. S21 ≠ S12 for a plain connection between a 50 Ω and a 25 Ω port. With equal impedances nothing changes. simulation_ports.get_reference_impedance() returns one value as before when all ports have the same port_Z0, else the list of port impedances, and utilities.write_snp() then writes a Touchstone 2.0 file with a [Reference] line (Touchstone 1.0 has only one reference impedance). Before, get_reference_impedance() stopped the script with "All ports must use the same reference impedance". The Y and Z parameter functions still require equal impedances.
GDSII layers read once: in the SG13G2 stackups, GDS layer 36 makes two stackup layers (the MIM top plate and the MIM dielectric below it), and every polygon is given to both. read_gds() read such a layer once per stackup layer, so every MIM polygon was in the model twice, and openEMS warned "Unused primitive ... MIM_equiv" and "... TopVia1" for the second copies. Now each GDS layer number is read once. The S-parameters do not change (MIM capacitor example: identical). read_gds() also no longer adds gds_boundary_layers to the caller's layer list. more_examples/local_modules_copy is synced with workflow/modules again.
Tests: tests/test_port_meshing.py, tests/test_gds_reader_layers.py.
Stackup files moved: the XML stackup files from workflow/ are now in XML_stackup/legacy/, with the same file names and content. The workflow/ examples read them from there. Models that used a stackup from workflow/ by relative path need the new folder.
New stackup files: XML_stackup/latest/IHP/ has the latest openEMS stackups SG13G2_FDTD_300um.xml, SG13G2_FDTD_300um_passicut.xml and SG13CMOS5L_FDTD_300um.xml. Chip height and air height are <Variables> (total_thickness, air_thickness), so one file replaces the legacy files for different substrate heights. SUBGND is a PEC sheet on layer 250 (legacy: a LOWLOSS volume on layer 210), BACKSIDEGND a PEC sheet on layer 251, and the RSIL/RPPD/RHIGH resistors and the REF_FOR_TRANSISTOR sheet are included. The metal, via and MIM positions are the same as in the legacy files; the default total height is 300 µm, the same as the legacy SG13G2.xml and SG13CMOS5L.xml used by the workflow/ examples (for SG13G2 the substrate is 0.12 µm thicker, so the total height is exactly 300 µm). See the README for which file replaces each legacy file. The files are installed with the pip package: utilities.get_stackup_path('SG13G2_FDTD_300um.xml') returns the full path of one, utilities.get_stackup_path() without an argument prints the folder and the available files. Legacy stackups are not included in the package.
31-Oct-2026 (0.6.7)
Ports with several polygons: several separate polygons on one port layer are now the elements of one port, in parallel, e.g. for a terminal on several transistor fingers. Each element gets N·Z0, so the port is terminated with Z0; the port voltage is the mean of the element voltages, the port current their sum. Touching polygons are one element. Before, every polygon became a port of its own with the same number: openEMS stopped with "a probe named port_ut_1 already exists", or, in older openEMS versions, ran with the port terminated by Z0/N and wrong S-parameters. Resonance estimation and deembed_openEMS.py (element inductances in parallel) know the elements. See "Ports with several polygons" in the user's guide.
31-Oct-2026 (0.6.6)
Bugfix: direction='-z' did not reverse a via port: the sign only swapped the port's x and y extent, and the port
kept the polarity of 'z'. A via port with '-z' now runs from its upper to its lower metal, the opposite polarity of
'z'. In-plane ports ('-x', '-y') are unchanged. Models that use '-z' get the opposite sign for that port's
S-parameters than before.
The core_transistor_3port_bce example now explains how to use the 5-port result in a circuit simulator: the
transistor model at ports 3, 4 and 5, inductors for the DC bias, and the 0 Hz point. See
its README.
Full history: CHANGES.md
Note: the gds2openEMS PyPI package itself only requires:
- gdspy>1.6.0
- CSXCAD
- openEMS
- numpy
- shapely
- PySide6
(Other Python modules mentioned above are only needed to run the example/model scripts in this repository, not to use the installed package.)
Metadata
Release files for gds2openEMS 0.7.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| gds2openems-0.7.0.tar.gz | 245.4 kB | Without provenance | Details for gds2openems-0.7.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| gds2openems-0.7.0-py3-none-any.whl | Python 3 | none | any | Details for gds2openems-0.7.0-py3-none-any.whl |
Total release size: 487.1 kB
Release files / gds2openems-0.7.0.tar.gz
| Download URL | gds2openems-0.7.0.tar.gz |
|---|---|
| Size | 245.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
99007d774273e2a50fad6bbb97a5d2e924cc694490ceb8107442b4a6cc4ef128
|
|
BLAKE2b-256 checksum How to use checksums |
5de9fac666e42ddc493ddb9e14b7ce1b91d3b0ebb776cce314ddadb1532be91f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / gds2openems-0.7.0-py3-none-any.whl
| Download URL | gds2openems-0.7.0-py3-none-any.whl |
|---|---|
| Size | 241.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ac602f7c3e7d659263d3a0c1da2923c003d69ac5c62d866ed409ae21bba8e622
|
|
BLAKE2b-256 checksum How to use checksums |
560ccdd2f9b508f1fa7b487744f59b142ff6c111298ac2cac192c7533b4978ee
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Security for gds2openEMS 0.7.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.