gmsh and FreeFem++#
[1]:
import matplotlib.pyplot as plt
%matplotlib inline
%config InlineBackend.figure_format='retina'
[2]:
from zeroheliumkit import Structure, Rectangle, Square, Ring, Circle, Layer
from zeroheliumkit.src.settings import GRAY, BLUE, YELLOW2
from zeroheliumkit.src.plotting import ColorHandler
[3]:
save_dir = "dump"
[4]:
### Creating geometry
[5]:
device = Structure()
device.add(Layer("wafer", Square(20)))
device.add(Layer("gnd", Square(20)))
device.gnd.cut(Rectangle(3, 9))
device.gnd.cut(Rectangle(9, 3))
device.gnd.cut(Rectangle(9, 3, (0,5)))
device.add(Layer("bottom", Circle(3)))
device.bottom.add(Ring(3.5, 8))
device.add(Layer("etch", Square(20)))
device.etch.cut(device.gnd.polygons)
device.bottom.remove_holes()
device.gnd.remove_holes()
device.colors = ColorHandler({
"wafer": GRAY,
"bottom": YELLOW2,
"gnd": (BLUE, 0.85)
})
device.quickplot(size="medium", show_idx=True)
[5]:
<Axes: >
[6]:
### Creating Mesh
[7]:
from zeroheliumkit.fem import GMSHmaker, ExtrudeSettings, MeshSettings, PECSettings, BoxFieldMeshSettings
[8]:
# extrude parameters
d_wafer = 10
d_metal1 = 0.2
d_metal2 = 0.1
d_diel = 1.5
d_vac = 20
d_He = d_diel + d_metal2
[9]:
Volumes = {
'wafer': ExtrudeSettings(device.wafer.polygons, -d_wafer, d_wafer, 'DIELECTRIC'),
'trap': ExtrudeSettings(device.bottom.polygons, 0, d_metal1, 'METAL'),
'dielectric': ExtrudeSettings(device.gnd.polygons, 0, d_diel, 'DIELECTRIC', ('trap',)),
'top': ExtrudeSettings(device.gnd.polygons, d_diel, d_metal2, 'METAL'),
'helium': ExtrudeSettings(device.wafer.polygons, 0, d_He, 'HELIUM', ('trap', 'dielectric','top')),
'vacuum': ExtrudeSettings(device.wafer.polygons, d_He, d_vac, 'VACUUM', ('dielectric', 'top'))
}
PECs = {
'mid': PECSettings(device.bottom.polygons, [0], volume=Volumes['trap']),
'out': PECSettings(device.bottom.polygons, [1,2], volume=Volumes['trap']),
'top': PECSettings(device.gnd.polygons, [0,1], volume=Volumes['top']),
}
scale = 4 # scaling factor for meshing. default 1.8
mesh = MeshSettings(
dim = 3,
fields = {
"Box": [BoxFieldMeshSettings(Thickness=4, VIn=scale * 0.2, VOut=scale * 2, box=[-10, 10, 10, 10, -5, 5]),
BoxFieldMeshSettings(Thickness=2, VIn=scale * 0.1, VOut=scale * 2, box=[-8, 8, -8, 8, -2, 2])]
}
)
[10]:
meshMKR = GMSHmaker(
extrude = Volumes,
surfaces = None,
pecs = PECs,
mesh = mesh,
save = {"dir": save_dir, "filename": "dot"},
open_gmsh = False,
debug_mode = False
)
on 0: mesh is constructed
on 0: mesh saved
Gmsh generation |███| 1/1 [100%] in 2.8s (0.36/s)
Below is an example of created geometry and a mesh using GMSH.

[11]:
meshMKR.print_physical()
Volume ID
---------- ----
METAL 1
DIELECTRIC 2
VACUUM 3
HELIUM 4
#-----------------------------------
Surface ID
--------- ----
mid 5
out 6
top 7
[12]:
### Helium Surface Displacement calculations
[13]:
s = Structure()
s.add(Layer('etch', device.etch.polygons, color=(BLUE,1)))
s.quickplot(size="medium", show_line_idx=True)
# We want to make boundary with line id 1 and 11 to be open boundary (Neumann boundary),
# at all other boundaries displacement is set to 0 (Dirichlet boundary)
[13]:
<Axes: >
[14]:
from zeroheliumkit.fem.heliumsurface import GMSHmaker2D, HeliumSurfaceFreeFEM
[15]:
gmshmkr = GMSHmaker2D(layout = s.etch,
electode_config = {"type": "polygon",
"bound": {"layer": ("etch", (0,)), "exclude": [1,11], "value": 0}},
mesh_config = [{"Thickness": 5, "VIn": 0.9, "VOut": 0.9, "box": [-20, -10, 20, 10]}],
filename = "heliumsurface",
savedir = save_dir)
gmshmkr.disable_consoleOutput()
gmshmkr.create_mesh()
#gmshmkr.open_gmsh()
gmshmkr.finalize()
Warning : Boolean fragments skipped - too few arguments
Gmsh generation |███| 1/1 [100%] in 0.1s (9.62/s)
[16]:
hsfreefem = HeliumSurfaceFreeFEM(fem_config=gmshmkr.export_physical(), save_edp=True)
res = hsfreefem.run_pyfreefem()
# plotting results of helium surface displacement for a bulk helium distance of 10 cm from the gnd surface
# note: the geometry units are in micrometers, so the bulk helium distance is set to 0.01 (10 cm)
hsfreefem.plot_results(res, bulk_helium_distance=0.01)
[17]:
curvature_config = hsfreefem.get_code_config(bulk_helium_distances=[0, 0.001, 0.01, 0.02], surface_helium_level=d_He)
# curvature_config
[ ]:
### Creating FreeFem configuration
[18]:
from zeroheliumkit.fem.freefemer import FFconfigurator, ExtractConfig, FreeFEM
[19]:
He_level = d_He
var_eps = {
'DIELECTRIC': 11.0,
'METAL': 1.0,
'HELIUM': 1.057,
'VACUUM': 1.0,
}
ffc = FFconfigurator(config_file="dump/dot.yaml",
dielectric_constants=var_eps,
ff_polynomial=2,
extract_opt=[ExtractConfig("result1", 'phi', 'xy', (-10,10,201), (-10,10,201), d_He),
ExtractConfig("result2", 'phi', 'xy', (-10,10,201), (-10,10,201), curvature_config),
ExtractConfig("result3", 'Ez', 'yz', (-10,10,101), (-2,2,101), 0.0)
],
msh_refinements=None
)
[20]:
pyff = FreeFEM(config_file="dump/dot.yaml")
[21]:
await pyff.run(cores=3, remove=True)
[ ]:
### Parsing FEM results
[22]:
from zeroheliumkit.fem.fieldreader import FreeFemResultParser, FieldAnalyzer
from zeroheliumkit.src.settings import BLACK, WHITE
[23]:
ffparser = FreeFemResultParser("dump/metadata.yaml")
result1 result2 result3
-------------- ------------- ---------------------- -------------
Quantity phi phi Ez
Plane xy xy yz
X Min -10 -10 -10
X Max 10 10 10
X Num 201 201 101
Y Min -10 -10 -2
Y Max 10 10 2
Y Num 201 201 101
Slices 1 4 1
Slice Values [1.6] [0, 0.001, 0.01, 0.02] [0.0]
Curved Surface False True False
Schema (1, 201, 201) (4, 201, 201) (1, 101, 101)
Control Electrodes: ['mid', 'out', 'top']
[24]:
ffparser.get_capacitance_matrix()
[24]:
[[-321.433, 266.481, 67.7825],
[258.134, -1859.7, 1725.85],
[63.2999, 1593.21, -1793.63]]
[25]:
ffparser.load_data("dump/results/", "result1")
cc1 = ffparser.get_coupling_constants(slice_value=1.6, round_with_decimals=6)
fa = FieldAnalyzer(cc1)
[ ]:
voltages = {
"mid": 1,
"out": 2,
"top": -0.1
}
fig = plt.figure(figsize=(6, 6))
ax = fig.add_subplot(111)
fa.set_voltages(voltages)
fa.plot2D_data(ax=ax, zero_line=False, cmap='RdYlBu')
device.gnd.plot(ax=ax, edgecolor=BLACK)
ax.set_aspect("equal")
plt.show()