Electrostatic simulations with Palace¶
Here, we show how Palace may be used to perform electrostatic simulations. For a given geometry, one needs to specify the terminals where to apply potential, similar to {doc}./elmer_01_electrostatic.py.
This effectively solves the mutual capacitance matrix for the terminals and the capacitance to ground.
For details on the physics, see [@smolic_capacitance_2021].
Installation¶
See Palace – Installation for installation or compilation instructions. Gplugins assumes palace is available in your PATH environment variable.
Alternatively, Singularity / Apptainer containers may be used. Instructions for building and an example definition file are found at Palace – Build using Singularity/Apptainer.
Afterwards, an easy install method is to add a script to ~/.local/bin (or elsewhere in PATH) calling the Singularity container. For example, one may create a palace file containing
Geometry, layer config and materials¶
import os
from math import inf
from pathlib import Path
import gdsfactory as gf
import pyvista as pv
from gdsfactory.components.analog.interdigital_capacitor import (
interdigital_capacitor,
)
from gdsfactory.gpdk import LAYER, get_generic_pdk
from gdsfactory.technology import LayerStack
from gdsfactory.technology.layer_stack import LayerLevel
from IPython.display import display
from gplugins.common.types import RFMaterialSpec
from gplugins.palace import run_capacitive_simulation_palace
gf.config.rich_output()
PDK = get_generic_pdk()
PDK.activate()
We employ an example LayerStack used in superconducting circuits similar to [@marxer_long-distance_2023].
layer_stack = LayerStack(
layers=dict(
substrate=LayerLevel(
layer=LAYER.WAFER,
thickness=10,
zmin=0,
material="Si",
mesh_order=99,
),
bw=LayerLevel(
layer=LAYER.WG,
thickness=200e-3,
zmin=10,
material="Nb",
mesh_order=2,
),
)
)
material_spec: RFMaterialSpec = {
"Si": {"relative_permittivity": 11.45},
"Nb": {"relative_permittivity": inf},
"vacuum": {"relative_permittivity": 1},
}
simulation_box = [[-200, -200], [200, 200]]
c = gf.Component()
cap = c << interdigital_capacitor()
c.add_ports(cap.ports)
substrate = gf.components.bbox(c, layer=LAYER.WAFER)
c << substrate
c.plot()
Running the simulation¶
We use the function :func:`~run_capacitive_simulation_palace`. This runs the simulation and returns an instance of :class:`~ElectrostaticResults` containing the capacitance matrix and a path to the mesh and the field solutions.
.. note::
The meshing parameters and element order shown here are very lax. As such, the computed capacitances are not very accurate.
results = run_capacitive_simulation_palace(
c,
layer_stack=layer_stack,
material_spec=material_spec,
n_processes=1,
element_order=2,
simulation_folder=Path(os.getcwd()) / "temporary",
mesh_parameters=dict(
background_tag="vacuum",
background_padding=(0,) * 5 + (10,),
port_names=[port.name for port in c.ports],
default_characteristic_length=2,
resolutions={
"bw": {
"resolution": 2,
},
"substrate": {
"resolution": 2,
},
"vacuum": {
"resolution": 2,
},
**{
f"bw__{port.name}": { # `__` is used as the layer to port delimiter for Palace
"resolution": 10,
"DistMax": 30,
"DistMin": 10,
"SizeMax": 2,
"SizeMin": 1,
}
for port in c.ports
},
},
),
)
display(results)
if results.field_file_location:
field = pv.read(results.field_file_location)
field_slice = field.slice_orthogonal(z=layer_stack.layers["bw"].zmin)
p = pv.Plotter()
p.add_mesh(field_slice, scalars="E", cmap="turbo")
p.show_grid()
p.camera_position = "xy"
p.enable_parallel_projection()
p.show()
Bibliography¶
Bibliography
:style: unsrt :filter: docname in docnames