TDGL, London, and FEM normal-state analysis

In this set of tutorials, we will cover conversion of qnngds.Device to skfem.mesh.MeshTri1, tdgl.Device, and superscreen.Device for analysis of device properties.

First, let’s analyze a structure with femwell/skfem to visualize the current density of our device in the normal state.

 1import qnngds as qg
 2import matplotlib.pyplot as plt
 3from qnngds.analysis.fem import (
 4    make_mesh,
 5    solve_laplace,
 6    visualize_mesh,
 7    visualize_current,
 8)
 9
10snspd = qg.devices.snspd.basic(size=(3, 3))

we can create a mesh as so:

1mesh = make_mesh(device=snspd, layer=(1, 0), tolerance=0.01)
2visualize_mesh(mesh)
3plt.show()
../../../_images/qg_analysisfemmesh.png

Now, let’s analyze the current density by solving the laplace equation

1result = solve_laplace(mesh)
2visualize_current(result, ("1", "2"))
3plt.show()
../../../_images/qg_analysisfemj.png

The current density is normalized to the current density at the excitation ports.

Next, we will show how to generate a tdgl.Device

 1from qnngds.analysis.tdgl import make_tdgl_device
 2
 3device = make_tdgl_device(
 4    device=snspd,
 5    coherence_length=0.005,
 6    london_lambda=0.35,
 7    thickness=0.01,
 8    gamma=23.8,
 9    layer=(1, 0),
10)
11fig, ax = device.draw()
12plt.show()
../../../_images/qg_analysistdgldraw.png

We can use this object to do tdgl simulations, check out the py-tdgl docs for more info and examples.

In some cases, we may be interested in modeling screening effects and Meissner currents in multi-layer structures. Note that py-tdgl can simulate screening, but is limited to a single layer. In order to simulate screening on multiple layers, we can use superscreen.

First, let’s create a gated diode device with a 5 nm thick layer having \(\lambda = 0.33\) μm penetration depth and a 40 nm thick layer having \(\lambda = 0.4\) μm penetration depth, separated by 45 nm spacer.

 1import superscreen as sc
 2from qnngds.analysis.superscreen import make_superscreen_device
 3
 4qg.pdk.get_generic_pdk().activate()
 5diode = qg.devices.diode.gated(
 6    channel_spec=qg.devices.diode.basic(
 7        layer=(1, 0),
 8    ),
 9    gate_spec=qg.geometries.optimal_hairpin(
10        width=1,
11        pitch=3,
12        layer=(10, 0),
13    ),
14)
15scdev = make_superscreen_device(
16    diode,
17    london_lambda={(1, 0): 0.33, (10, 0): 0.4},
18    thickness={(1, 0): 0.005, (10, 0): 0.04},
19    z0={(1, 0): 0, (10, 0): 0.05},
20    min_refine_points=1000,
21)
22fig, ax = scdev.draw(figsize=(6, 4))
23_ = scdev.plot_polygons(ax=ax, legend=True)
24plt.show()
../../../_images/qg_analysissuperscreendev.png

Now, we can simulate a 1 mA bias current flowing through the upper hairpin “gate”

 1Ibias = "1 mA"
 2scdev.make_mesh(max_edge_length=0.25)
 3solutions = sc.solve(
 4    scdev,
 5    terminal_currents={
 6        "(10, 0)_0": {"port_(10, 0)_g1": Ibias, "port_(10, 0)_g2": f"-{Ibias}"}
 7    },
 8    iterations=10,
 9    progress_bar=True,
10)

Evaluating the solution at a distance of 10 nm (5 nm above the bottom film), we can plot the field distribution due to the current flowing through the upper layer.

1eval_region = sc.Polygon(points=sc.geometry.box(12, 6))
2eval_mesh = eval_region.make_mesh(min_points=2000)
3fig, ax = solutions[-1].plot_field_at_positions(
4    eval_mesh, zs=0.01, figsize=(6, 4), symmetric_color_scale=True, cmap="coolwarm"
5)
6for film in scdev.films.values():
7    film.plot(ax=ax, color="k", ls="--", lw=1)
8plt.show()
../../../_images/qg_analysissuperscreenhz.png

We can also use superscreen to compute the current density in a wire. Let’s reuse the same snspd device from earlier that we analyzed with femwell:

 1scdev = make_superscreen_device(
 2    device=snspd,
 3    london_lambda=0.33,
 4    thickness=0.005,
 5    min_refine_points=1000,
 6)
 7scdev.make_mesh(max_edge_length=0.25)
 8Ibias = f"{snspd.ports[1].width} uA"
 9solutions = sc.solve(
10    scdev,
11    terminal_currents={
12        "(1, 0)_0": {"port_(1, 0)_1": Ibias, "port_(1, 0)_2": f"-{Ibias}"}
13    },
14    iterations=10,
15    progress_bar=True,
16)
17fig, ax = solutions[-1].plot_currents(films=["(1, 0)_0"])
18_ = scdev.plot_polygons(ax=ax[0], color="w", ls="--", lw=1)
19plt.show()
../../../_images/qg_analysissuperscreenj.png