pyTDGL Logo

Getting Started

  • Installation
  • Quickstart
  • Theoretical Background

Tutorials

  • Working with polygons
  • Generating the pyTDGL logo
    • Define the letter geometries
    • Make the Device
    • Generate the mesh
    • Solve the model
    • Plot the order parameter
    • Plot the supercurrent density
    • Create an animation

API Reference

  • Device Interface
  • Solver
  • Post-Processing
  • Finite Volume Methods
  • Visualization

About pyTDGL

  • Change Log
  • Contributing
  • License
pyTDGL
  • Generating the pyTDGL logo
  • Edit on GitHub

Generating the pyTDGL logo

pytdgl logo

In this notebook, we generate the pyTDGL logo (pictured above) by simulating a mesoscopic superconducting film patterned into the letters “py” and subject to a uniform out-of-plane applied field.

[1]:
%config InlineBackend.figure_formats = {"retina", "png"}
%matplotlib inline

import os
import tempfile
from typing import List, Tuple

os.environ["OPENBLAS_NUM_THREADS"] = "1"

import numpy as np
import matplotlib as mpl
from matplotlib.path import Path
from matplotlib.textpath import TextPath
from matplotlib.font_manager import FontProperties
import matplotlib.pyplot as plt

plt.rcParams["figure.figsize"] = (5, 4)
plt.rcParams["font.size"] = 11

import tdgl
from tdgl.geometry import box, ensure_unique, close_curve

SAVE = False
USE_TEMPDIR = True
image_path = os.path.join(os.pardir, "images")
[2]:
MAKE_ANIMATIONS = False
[3]:
if USE_TEMPDIR:
    tempdir = tempfile.TemporaryDirectory()
    output_path = tempdir.name
else:
    output_path = "."

Define the letter geometries

[4]:
# Letters that have loops will require more than one Polygon to define.
loops_uppercase = "ABDOPQR"
loops_lowercase = "abdegopq"
[5]:
def interp_path(path: Path, points_per_segment: int = 11) -> np.ndarray:
    """Generate polygon coordinates for a given matplotlib Path"""
    # The paths are defined in terms of Bezier curves, so we need to
    # evaluate the curves at many points.
    t = np.linspace(0, 1, points_per_segment)
    segments = [
        bezier(t) for bezier, code in path.iter_bezier() if code != Path.MOVETO
    ]
    points = np.concatenate(segments)
    return ensure_unique(points)

def make_polygons(
    letter: str,
    fontsize: int,
    fontprops: FontProperties,
    resample_points: Tuple[int, int] = (251, 101),
) -> List[tdgl.Polygon]:
    path = TextPath((0, 0), letter, size=fontsize, prop=fontprops)
    if letter in loops_lowercase + loops_uppercase:
        # If the letter has holes in it, split the overall outline and
        # all holes into separate paths.
        jumps = np.where(path.codes == TextPath.MOVETO)[0][1:]
        vertices = np.split(path.vertices, jumps)
        codes = np.split(path.codes, jumps)
        paths = [Path(v[:-1], c[:-1]) for v, c in zip(vertices, codes)]
    else:
        # If the letter doesn't have holes in it, we only need one path.
        paths = [Path(path.vertices[:-1], path.codes[:-1])]
    polygons = [tdgl.Polygon(points=interp_path(p)) for p in paths]
    # Sort the polygons by area in descending order so that the outline
    # will be first.
    polygons = sorted(polygons, key=lambda p: p.area, reverse=True)
    polygons = (
        [polygons[0].resample(resample_points[0]).buffer(2e-3)]
        + [p.resample(resample_points[1]) for p in polygons[1:]]
    )
    # Name the polygons
    for i, p in enumerate(polygons):
        if i == 0:
            p.name = letter
        else:
            p.name = f"{letter}_hole{i}"
    return polygons

Make the Device

[6]:
fontsize = 10
fontprops = FontProperties(weight="bold")
xi = 0.4
layer = tdgl.Layer(london_lambda=4, coherence_length=xi, thickness=0.1)
[7]:
p_outer, p_inner  = make_polygons("p", fontsize, fontprops)
y_outer,  = make_polygons("y", fontsize, fontprops)
# Merge the "p" and the "y" into a single "Polygon"
film = p_outer.union(y_outer.translate(dx=5.75))

device = tdgl.Device("py", layer=layer, film=film, holes=[p_inner])
[8]:
fig, ax = device.draw(legend=False)
../_images/notebooks_logo_11_0.png

Generate the mesh

[9]:
fig, ax = plt.subplots()
device.make_mesh(max_edge_length=xi / 2, smooth=100)
_ = device.plot(ax=ax, mesh=True, legend=False)
../_images/notebooks_logo_13_0.png

Solve the model

[10]:
options = tdgl.SolverOptions(
    solve_time=800,
    field_units="mT",
    output_file=os.path.join(output_path, "py.h5"),
)
applied_vector_potential = 1.8

solution = tdgl.solve(
    device,
    options,
    applied_vector_potential=applied_vector_potential,
)
Simulating: 100%|█████████████████▉| 800/800 [00:48<00:00, 16.51tau/s ]

Plot the order parameter

[11]:
fig, ax = solution.plot_order_parameter(figsize=(7, 2))
../_images/notebooks_logo_17_0.png
[12]:
fig, ax = plt.subplots(figsize=(3, 1), facecolor="none")
ax.set_aspect("equal")
ax.axis("off")

device = solution.device
xs, ys = device.points.T
triangles = device.triangles
psi = solution.tdgl_data.psi
ax.tripcolor(xs, ys, triangles, np.abs(psi), vmin=0, cmap="viridis", shading="gouraud")

if SAVE:
    fig.set_size_inches(3, 1)
    fig.savefig(os.path.join(image_path, "logo-transparent-small.png"), dpi=300)
    fig.set_size_inches(4, 3)
    fig.savefig(os.path.join(image_path, "logo-transparent-large.png"), dpi=300, bbox_inches="tight")
../_images/notebooks_logo_18_0.png

Plot the supercurrent density

[13]:
fig, ax = solution.plot_currents(
    dataset="supercurrent",
    figsize=(6, 3),
    vmin=0,
    vmax=3,
    streamplot=False,
)
../_images/notebooks_logo_20_0.png

Create an animation

[14]:
from IPython.display import display, HTML
import h5py
from tdgl.visualization.animate import create_animation
[15]:
def make_video_from_solution(solution, **kwargs):
    """Generates an HTML5 video from a tdgl.Solution."""
    with tdgl.non_gui_backend():
        with h5py.File(solution.path, "r") as h5file:
            anim = create_animation(h5file, **kwargs)
            video = anim.to_html5_video()
        return HTML(video)
[16]:
if MAKE_ANIMATIONS:
    video = make_video_from_solution(
        solution,
        quantities=["order_parameter", "phase"],
        dpi=100,
        fps=50,
        title_off=True,
        axes_off=True,
        max_frame=600,
        max_cols=1,
        figure_kwargs=dict(figsize=(4.5, 6)),
    )
    display(video)
Your browser does not support the video tag.
[17]:
if USE_TEMPDIR:
    tempdir.cleanup()
[18]:
tdgl.version_table()
[18]:
SoftwareVersion
tdgl0.2.1
Numpy1.23.3
SciPy1.9.1
matplotlib3.6.0
jax0.3.18
IPython8.5.0
Python3.9.13 | packaged by conda-forge | (main, May 27 2022, 17:01:00) [Clang 13.0.1 ]
OSposix [darwin]
Number of CPUsPhysical: 10, Logical: 10
BLAS InfoOPENBLAS
Tue Feb 07 12:43:13 2023 PST
[ ]:

Previous Next

© Copyright 2022, Logan Bishop-Van Horn. Revision 332daac7.

Built with Sphinx using a theme provided by Read the Docs.
Read the Docs v: latest
Versions
latest
stable
Downloads
On Read the Docs
Project Home
Builds