.. THIS FILE WAS AUTOGENERATED BY GENERATE_TUTORIALS.PY. ANY CHANGES WILL BE OVERWRITTEN.
.. _tdgl_fem:
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.
.. code-block:: python
:linenos:
import qnngds as qg
import matplotlib.pyplot as plt
from qnngds.analysis.fem import (
make_mesh,
solve_laplace,
visualize_mesh,
visualize_current,
)
snspd = qg.devices.snspd.basic(size=(3, 3))
we can create a mesh as so:
.. code-block:: python
:linenos:
mesh = make_mesh(device=snspd, layer=(1, 0), tolerance=0.01)
visualize_mesh(mesh)
plt.show()
.. image:: qg_analysisfemmesh.png
Now, let's analyze the current density by solving the laplace equation
.. code-block:: python
:linenos:
result = solve_laplace(mesh)
visualize_current(result, ("1", "2"))
plt.show()
.. image:: 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``
.. code-block:: python
:linenos:
from qnngds.analysis.tdgl import make_tdgl_device
device = make_tdgl_device(
device=snspd,
coherence_length=0.005,
london_lambda=0.35,
thickness=0.01,
gamma=23.8,
layer=(1, 0),
)
fig, ax = device.draw()
plt.show()
.. image:: 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 :math:`\lambda = 0.33` μm penetration depth
and a 40 nm thick layer having :math:`\lambda = 0.4` μm penetration depth, separated by 45 nm spacer.
.. code-block:: python
:linenos:
import superscreen as sc
from qnngds.analysis.superscreen import make_superscreen_device
qg.pdk.get_generic_pdk().activate()
diode = qg.devices.diode.gated(
channel_spec=qg.devices.diode.basic(
layer=(1, 0),
),
gate_spec=qg.geometries.optimal_hairpin(
width=1,
pitch=3,
layer=(10, 0),
),
)
scdev = make_superscreen_device(
diode,
london_lambda={(1, 0): 0.33, (10, 0): 0.4},
thickness={(1, 0): 0.005, (10, 0): 0.04},
z0={(1, 0): 0, (10, 0): 0.05},
min_refine_points=1000,
)
fig, ax = scdev.draw(figsize=(6, 4))
_ = scdev.plot_polygons(ax=ax, legend=True)
plt.show()
.. image:: qg_analysissuperscreendev.png
Now, we can simulate a 1 mA bias current flowing through the upper hairpin "gate"
.. code-block:: python
:linenos:
Ibias = "1 mA"
scdev.make_mesh(max_edge_length=0.25)
solutions = sc.solve(
scdev,
terminal_currents={
"(10, 0)_0": {"port_(10, 0)_g1": Ibias, "port_(10, 0)_g2": f"-{Ibias}"}
},
iterations=10,
progress_bar=True,
)
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.
.. code-block:: python
:linenos:
eval_region = sc.Polygon(points=sc.geometry.box(12, 6))
eval_mesh = eval_region.make_mesh(min_points=2000)
fig, ax = solutions[-1].plot_field_at_positions(
eval_mesh, zs=0.01, figsize=(6, 4), symmetric_color_scale=True, cmap="coolwarm"
)
for film in scdev.films.values():
film.plot(ax=ax, color="k", ls="--", lw=1)
plt.show()
.. image:: 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:
.. code-block:: python
:linenos:
scdev = make_superscreen_device(
device=snspd,
london_lambda=0.33,
thickness=0.005,
min_refine_points=1000,
)
scdev.make_mesh(max_edge_length=0.25)
Ibias = f"{snspd.ports[1].width} uA"
solutions = sc.solve(
scdev,
terminal_currents={
"(1, 0)_0": {"port_(1, 0)_1": Ibias, "port_(1, 0)_2": f"-{Ibias}"}
},
iterations=10,
progress_bar=True,
)
fig, ax = solutions[-1].plot_currents(films=["(1, 0)_0"])
_ = scdev.plot_polygons(ax=ax[0], color="w", ls="--", lw=1)
plt.show()
.. image:: qg_analysissuperscreenj.png