Hydrogen diffusion along grain boundaries#

This tutorial shows how to use FESTIM to simulate hydrogen diffusion in metal microstructures.

We’ll show how to generate a microstructure using Voronoi cells, mesh it with GMSH, and solve a transport problem with FESTIM.

Geometry#

Generating the microstructure#

First, we use scipy to make a Voronoi diagram mimicking a microstructure.

import numpy as np
from scipy.spatial import Voronoi, voronoi_plot_2d
import matplotlib.pyplot as plt
import gmsh


np.random.seed(1)

# N random seeds in [0,size]x[0,size]
size = 1.5
N_seeds = 150
points = np.random.rand(N_seeds, 2) * size

# centre everything on 0.5, 0.5
points -= size / 2
points += 0.5

vor = Voronoi(points)

voronoi_plot_2d(vor, show_vertices=False, show_points=True)
plt.show()
../../_images/82e89dc5af79125ecd88cd001371af8b76633800aa7811c83d76d9dffbde4c02.png

Now that we have vertices for each Voronoi cell, we can use shapely to turn them into shapely.Polygon objects for easy manipulation. We then shrink the Voronoi cells to make grain boundaries appear. Note that the grain boundary thickness is arbitrary here.

from shapely.geometry import Polygon
from shapely import difference, union_all
from shapely.plotting import plot_polygon, plot_points

gap = 0.01  # thickness of grain boundary

grains = []
for region_idx in vor.point_region:
    region = vor.regions[region_idx]
    if -1 in region or len(region) == 0:
        continue  # skip infinite regions
    poly = Polygon([vor.vertices[i] for i in region])
    poly = poly.intersection(
        Polygon([(0, 0), (1, 0), (1, 1), (0, 1)])
    )  # clip to domain
    if not poly.is_empty:
        grains.append(poly.buffer(-gap / 2))  # shrink each grain inward

print("Number of grains:", len(grains))

plt.figure(figsize=(8, 8))
# plot grains
for polygon in grains:
    plot_polygon(polygon=polygon, add_points=False)
    plot_points(polygon, markersize=2, color="tab:blue")
plt.show()
Number of grains: 79
../../_images/e51d6604ceedeb78e3cec27992b6e47738fb59cdc6f82b28444f4b18c5284906.png

We can make a new Polygon for our grain boundaries by subtracting all the grains from a square polygon.

# Grain boundary = everything not covered by grains
eps = gap / 2
domain = Polygon(
    [(0 + eps, 0 + eps), (1 - eps, 0 + eps), (1 - eps, 1 - eps), (0 + eps, 1 - eps)]
)
grain_union = union_all(grains)
grain_boundaries = difference(domain, grain_union)

plt.figure(figsize=(8, 8))
for polygon in grains:
    plot_polygon(polygon=polygon, add_points=False)
plot_polygon(polygon=grain_boundaries, facecolor="tab:orange", add_points=False)
plt.show()
../../_images/9dd899c53105ae5ba8cd7a902041cfb771806042d61aeecac071e30ab7e0f5d0.png

Mesh with GMSH#

We can now pass this geometry to GMSH for meshing. We tag the grains, grain boundaries, and the left and right surfaces as different subdomains.

gmsh.initialize()
gmsh.model.add("voronoi")

lc = 0.01  # mesh size


def add_polygon_occ(poly):
    """Add polygon using OpenCASCADE kernel for better Boolean operations"""
    if poly.is_empty:
        return []

    # Handle MultiPolygon recursively
    if poly.geom_type == "MultiPolygon":
        surfaces = []
        for p in poly.geoms:
            surfaces.extend(add_polygon_occ(p))
        return surfaces

    # Ensure polygon is valid
    poly = poly.buffer(0)
    if not poly.is_valid:
        return []

    # exterior coords
    coords = list(poly.exterior.coords)[:-1]  # remove duplicate last point
    if len(coords) < 3:
        return []

    # Create wire from points using OCC
    points = []
    for x, y in coords:
        points.append(gmsh.model.occ.addPoint(x, y, 0))

    # Create lines connecting the points
    lines = []
    for i in range(len(points)):
        next_i = (i + 1) % len(points)
        lines.append(gmsh.model.occ.addLine(points[i], points[next_i]))

    # Create curve loop and surface
    wire = gmsh.model.occ.addWire(lines)

    # Handle holes if any
    holes = []
    if len(poly.interiors) > 0:
        for interior in poly.interiors:
            int_coords = list(interior.coords)[:-1]
            if len(int_coords) < 3:
                continue

            # Create hole wire
            hole_points = []
            for x, y in int_coords:
                hole_points.append(gmsh.model.occ.addPoint(x, y, 0))

            hole_lines = []
            for i in range(len(hole_points)):
                next_i = (i + 1) % len(hole_points)
                hole_lines.append(
                    gmsh.model.occ.addLine(hole_points[i], hole_points[next_i])
                )

            hole_wire = gmsh.model.occ.addWire(hole_lines)
            holes.append(hole_wire)

    # Create surface
    if holes:
        surface = gmsh.model.occ.addPlaneSurface([wire] + holes)
    else:
        surface = gmsh.model.occ.addPlaneSurface([wire])

    return [surface]


# Add grains using OCC kernel
grain_surfaces = []
for i, poly in enumerate(grains):
    grain_surfaces.extend(add_polygon_occ(poly))

gb_surfaces = []
if not grain_boundaries.is_empty:
    gb_surfaces.extend(add_polygon_occ(grain_boundaries))

# Synchronize OCC before fragmentation
gmsh.model.occ.synchronize()

# Fragment all surfaces together
gmsh.model.occ.fragment([(2, tag) for tag in grain_surfaces], [(2, gb_surfaces[0])])
gmsh.model.occ.synchronize()

# Create physical groups with all fragmented surfaces

gmsh.model.addPhysicalGroup(2, grain_surfaces, 1, name="grains")
gmsh.model.addPhysicalGroup(2, gb_surfaces, 2, name="grain_boundaries")

# Set mesh size for all points
gmsh.option.setNumber("Mesh.MeshSizeMax", lc)
gmsh.option.setNumber("Mesh.MeshSizeMin", lc)

# find lines on the boundaries
# Get all line entities (dimension = 1)
lines = gmsh.model.getEntities(1)

# List to store the tags of the lines on the boundaries
lines_on_left = []
lines_on_right = []

for line_tag_pair in lines:
    dim = line_tag_pair[0]  # Dimension of the entity (1 for lines)
    tag = line_tag_pair[1]  # Tag of the entity

    # Get the bounding points (dimension = 0) for the current line
    bounding_points = gmsh.model.getBoundary([line_tag_pair])

    # Get the coordinates for each bounding point
    point_coords = []
    for point_tag_pair in bounding_points:
        coords = gmsh.model.getValue(point_tag_pair[0], point_tag_pair[1], [])
        point_coords.append(coords)

    # Check if both bounding points are on the left boundary (x ≈ eps)
    is_on_left = True
    for coords in point_coords:
        x_coord = coords[0]
        if abs(x_coord - eps) > 1e-9:
            is_on_left = False
            break

    # Check if both bounding points are on the right boundary (x ≈ 1-eps)
    is_on_right = True
    for coords in point_coords:
        x_coord = coords[0]
        if abs(x_coord - (1 - eps)) > 1e-9:
            is_on_right = False
            break

    if is_on_left:
        lines_on_left.append(tag)
    if is_on_right:
        lines_on_right.append(tag)

print("Lines on left boundary:", lines_on_left)
print("Lines on right boundary:", lines_on_right)

if lines_on_left:
    gmsh.model.addPhysicalGroup(1, lines_on_left, name="left_boundary")
if lines_on_right:
    gmsh.model.addPhysicalGroup(1, lines_on_right, name="right_boundary")

gmsh.model.mesh.generate(2)
# gmsh.fltk.run()
gmsh.write("voronoi_grains.msh")

gmsh.finalize()

Hide code cell output

Info    : [  0%] Fragments                                                                                  
Info    : [ 10%] Fragments                                                                                  
Info    : [ 20%] Fragments                                                                                  
Info    : [ 30%] Fragments                                                                                  
Info    : [ 40%] Fragments                                                                                  
Info    : [ 50%] Fragments                                                                                  
Info    : [ 60%] Fragments                                                                                  
Info    : [ 70%] Fragments - Filling splits of vertices                                                                                
Info    : [ 80%] Fragments - Filling splits of edges                                                                                
Info    : [ 90%] Fragments - Splitting faces                                                                                
Lines on left boundary: [10, 34, 71, 96, 137, 176, 192, 248, 268, 272, 371, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417]
Lines on right boundary: [144, 154, 158, 168, 276, 286, 313, 343, 431, 432, 433, 434, 435, 436, 437]
Info    : Meshing 1D...
Info    : [  0%] Meshing curve 1 (Line)
Info    : [ 10%] Meshing curve 2 (Line)
Info    : [ 10%] Meshing curve 3 (Line)
Info    : [ 10%] Meshing curve 4 (Line)
Info    : [ 10%] Meshing curve 5 (Line)
Info    : [ 10%] Meshing curve 6 (Line)
Info    : [ 10%] Meshing curve 7 (Line)
Info    : [ 10%] Meshing curve 8 (Line)
Info    : [ 10%] Meshing curve 9 (Line)
Info    : [ 10%] Meshing curve 10 (Line)
Info    : [ 10%] Meshing curve 11 (Line)
Info    : [ 10%] Meshing curve 12 (Line)
Info    : [ 10%] Meshing curve 13 (Line)
Info    : [ 10%] Meshing curve 14 (Line)
Info    : [ 10%] Meshing curve 15 (Line)
Info    : [ 10%] Meshing curve 16 (Line)
Info    : [ 10%] Meshing curve 17 (Line)
Info    : [ 10%] Meshing curve 18 (Line)
Info    : [ 10%] Meshing curve 19 (Line)
Info    : [ 10%] Meshing curve 20 (Line)
Info    : [ 10%] Meshing curve 21 (Line)
Info    : [ 10%] Meshing curve 22 (Line)
Info    : [ 10%] Meshing curve 23 (Line)
Info    : [ 10%] Meshing curve 24 (Line)
Info    : [ 10%] Meshing curve 25 (Line)
Info    : [ 10%] Meshing curve 26 (Line)
Info    : [ 10%] Meshing curve 27 (Line)
Info    : [ 10%] Meshing curve 28 (Line)
Info    : [ 10%] Meshing curve 29 (Line)
Info    : [ 10%] Meshing curve 30 (Line)
Info    : [ 10%] Meshing curve 31 (Line)
Info    : [ 10%] Meshing curve 32 (Line)
Info    : [ 10%] Meshing curve 33 (Line)
Info    : [ 10%] Meshing curve 34 (Line)
Info    : [ 10%] Meshing curve 35 (Line)
Info    : [ 10%] Meshing curve 36 (Line)
Info    : [ 10%] Meshing curve 37 (Line)
Info    : [ 10%] Meshing curve 38 (Line)
Info    : [ 10%] Meshing curve 39 (Line)
Info    : [ 10%] Meshing curve 40 (Line)
Info    : [ 10%] Meshing curve 41 (Line)
Info    : [ 10%] Meshing curve 42 (Line)
Info    : [ 10%] Meshing curve 43 (Line)
Info    : [ 10%] Meshing curve 44 (Line)
Info    : [ 10%] Meshing curve 45 (Line)
Info    : [ 20%] Meshing curve 46 (Line)
Info    : [ 20%] Meshing curve 47 (Line)
Info    : [ 20%] Meshing curve 48 (Line)
Info    : [ 20%] Meshing curve 49 (Line)
Info    : [ 20%] Meshing curve 50 (Line)
Info    : [ 20%] Meshing curve 51 (Line)
Info    : [ 20%] Meshing curve 52 (Line)
Info    : [ 20%] Meshing curve 53 (Line)
Info    : [ 20%] Meshing curve 54 (Line)
Info    : [ 20%] Meshing curve 55 (Line)
Info    : [ 20%] Meshing curve 56 (Line)
Info    : [ 20%] Meshing curve 57 (Line)
Info    : [ 20%] Meshing curve 58 (Line)
Info    : [ 20%] Meshing curve 59 (Line)
Info    : [ 20%] Meshing curve 60 (Line)
Info    : [ 20%] Meshing curve 61 (Line)
Info    : [ 20%] Meshing curve 62 (Line)
Info    : [ 20%] Meshing curve 63 (Line)
Info    : [ 20%] Meshing curve 64 (Line)
Info    : [ 20%] Meshing curve 65 (Line)
Info    : [ 20%] Meshing curve 66 (Line)
Info    : [ 20%] Meshing curve 67 (Line)
Info    : [ 20%] Meshing curve 68 (Line)
Info    : [ 20%] Meshing curve 69 (Line)
Info    : [ 20%] Meshing curve 70 (Line)
Info    : [ 20%] Meshing curve 71 (Line)
Info    : [ 20%] Meshing curve 72 (Line)
Info    : [ 20%] Meshing curve 73 (Line)
Info    : [ 20%] Meshing curve 74 (Line)
Info    : [ 20%] Meshing curve 75 (Line)
Info    : [ 20%] Meshing curve 76 (Line)
Info    : [ 20%] Meshing curve 77 (Line)
Info    : [ 20%] Meshing curve 78 (Line)
Info    : [ 20%] Meshing curve 79 (Line)
Info    : [ 20%] Meshing curve 80 (Line)
Info    : [ 20%] Meshing curve 81 (Line)
Info    : [ 20%] Meshing curve 82 (Line)
Info    : [ 20%] Meshing curve 83 (Line)
Info    : [ 20%] Meshing curve 84 (Line)
Info    : [ 20%] Meshing curve 85 (Line)
Info    : [ 20%] Meshing curve 86 (Line)
Info    : [ 20%] Meshing curve 87 (Line)
Info    : [ 20%] Meshing curve 88 (Line)
Info    : [ 20%] Meshing curve 89 (Line)
Info    : [ 30%] Meshing curve 90 (Line)
Info    : [ 30%] Meshing curve 91 (Line)
Info    : [ 30%] Meshing curve 92 (Line)
Info    : [ 30%] Meshing curve 93 (Line)
Info    : [ 30%] Meshing curve 94 (Line)
Info    : [ 30%] Meshing curve 95 (Line)
Info    : [ 30%] Meshing curve 96 (Line)
Info    : [ 30%] Meshing curve 97 (Line)
Info    : [ 30%] Meshing curve 98 (Line)
Info    : [ 30%] Meshing curve 99 (Line)
Info    : [ 30%] Meshing curve 100 (Line)
Info    : [ 30%] Meshing curve 101 (Line)
Info    : [ 30%] Meshing curve 102 (Line)
Info    : [ 30%] Meshing curve 103 (Line)
Info    : [ 30%] Meshing curve 104 (Line)
Info    : [ 30%] Meshing curve 105 (Line)
Info    : [ 30%] Meshing curve 106 (Line)
Info    : [ 30%] Meshing curve 107 (Line)
Info    : [ 30%] Meshing curve 108 (Line)
Info    : [ 30%] Meshing curve 109 (Line)
Info    : [ 30%] Meshing curve 110 (Line)
Info    : [ 30%] Meshing curve 111 (Line)
Info    : [ 30%] Meshing curve 112 (Line)
Info    : [ 30%] Meshing curve 113 (Line)
Info    : [ 30%] Meshing curve 114 (Line)
Info    : [ 30%] Meshing curve 115 (Line)
Info    : [ 30%] Meshing curve 116 (Line)
Info    : [ 30%] Meshing curve 117 (Line)
Info    : [ 30%] Meshing curve 118 (Line)
Info    : [ 30%] Meshing curve 119 (Line)
Info    : [ 30%] Meshing curve 120 (Line)
Info    : [ 30%] Meshing curve 121 (Line)
Info    : [ 30%] Meshing curve 122 (Line)
Info    : [ 30%] Meshing curve 123 (Line)
Info    : [ 30%] Meshing curve 124 (Line)
Info    : [ 30%] Meshing curve 125 (Line)
Info    : [ 30%] Meshing curve 126 (Line)
Info    : [ 30%] Meshing curve 127 (Line)
Info    : [ 30%] Meshing curve 128 (Line)
Info    : [ 30%] Meshing curve 129 (Line)
Info    : [ 30%] Meshing curve 130 (Line)
Info    : [ 30%] Meshing curve 131 (Line)
Info    : [ 30%] Meshing curve 132 (Line)
Info    : [ 30%] Meshing curve 133 (Line)
Info    : [ 30%] Meshing curve 134 (Line)
Info    : [ 40%] Meshing curve 135 (Line)
Info    : [ 40%] Meshing curve 136 (Line)
Info    : [ 40%] Meshing curve 137 (Line)
Info    : [ 40%] Meshing curve 138 (Line)
Info    : [ 40%] Meshing curve 139 (Line)
Info    : [ 40%] Meshing curve 140 (Line)
Info    : [ 40%] Meshing curve 141 (Line)
Info    : [ 40%] Meshing curve 142 (Line)
Info    : [ 40%] Meshing curve 143 (Line)
Info    : [ 40%] Meshing curve 144 (Line)
Info    : [ 40%] Meshing curve 145 (Line)
Info    : [ 40%] Meshing curve 146 (Line)
Info    : [ 40%] Meshing curve 147 (Line)
Info    : [ 40%] Meshing curve 148 (Line)
Info    : [ 40%] Meshing curve 149 (Line)
Info    : [ 40%] Meshing curve 150 (Line)
Info    : [ 40%] Meshing curve 151 (Line)
Info    : [ 40%] Meshing curve 152 (Line)
Info    : [ 40%] Meshing curve 153 (Line)
Info    : [ 40%] Meshing curve 154 (Line)
Info    : [ 40%] Meshing curve 155 (Line)
Info    : [ 40%] Meshing curve 156 (Line)
Info    : [ 40%] Meshing curve 157 (Line)
Info    : [ 40%] Meshing curve 158 (Line)
Info    : [ 40%] Meshing curve 159 (Line)
Info    : [ 40%] Meshing curve 160 (Line)
Info    : [ 40%] Meshing curve 161 (Line)
Info    : [ 40%] Meshing curve 162 (Line)
Info    : [ 40%] Meshing curve 163 (Line)
Info    : [ 40%] Meshing curve 164 (Line)
Info    : [ 40%] Meshing curve 165 (Line)
Info    : [ 40%] Meshing curve 166 (Line)
Info    : [ 40%] Meshing curve 167 (Line)
Info    : [ 40%] Meshing curve 168 (Line)
Info    : [ 40%] Meshing curve 169 (Line)
Info    : [ 40%] Meshing curve 170 (Line)
Info    : [ 40%] Meshing curve 171 (Line)
Info    : [ 40%] Meshing curve 172 (Line)
Info    : [ 40%] Meshing curve 173 (Line)
Info    : [ 40%] Meshing curve 174 (Line)
Info    : [ 40%] Meshing curve 175 (Line)
Info    : [ 40%] Meshing curve 176 (Line)
Info    : [ 40%] Meshing curve 177 (Line)
Info    : [ 40%] Meshing curve 178 (Line)
Info    : [ 50%] Meshing curve 179 (Line)
Info    : [ 50%] Meshing curve 180 (Line)
Info    : [ 50%] Meshing curve 181 (Line)
Info    : [ 50%] Meshing curve 182 (Line)
Info    : [ 50%] Meshing curve 183 (Line)
Info    : [ 50%] Meshing curve 184 (Line)
Info    : [ 50%] Meshing curve 185 (Line)
Info    : [ 50%] Meshing curve 186 (Line)
Info    : [ 50%] Meshing curve 187 (Line)
Info    : [ 50%] Meshing curve 188 (Line)
Info    : [ 50%] Meshing curve 189 (Line)
Info    : [ 50%] Meshing curve 190 (Line)
Info    : [ 50%] Meshing curve 191 (Line)
Info    : [ 50%] Meshing curve 192 (Line)
Info    : [ 50%] Meshing curve 193 (Line)
Info    : [ 50%] Meshing curve 194 (Line)
Info    : [ 50%] Meshing curve 195 (Line)
Info    : [ 50%] Meshing curve 196 (Line)
Info    : [ 50%] Meshing curve 197 (Line)
Info    : [ 50%] Meshing curve 198 (Line)
Info    : [ 50%] Meshing curve 199 (Line)
Info    : [ 50%] Meshing curve 200 (Line)
Info    : [ 50%] Meshing curve 201 (Line)
Info    : [ 50%] Meshing curve 202 (Line)
Info    : [ 50%] Meshing curve 203 (Line)
Info    : [ 50%] Meshing curve 204 (Line)
Info    : [ 50%] Meshing curve 205 (Line)
Info    : [ 50%] Meshing curve 206 (Line)
Info    : [ 50%] Meshing curve 207 (Line)
Info    : [ 50%] Meshing curve 208 (Line)
Info    : [ 50%] Meshing curve 209 (Line)
Info    : [ 50%] Meshing curve 210 (Line)
Info    : [ 50%] Meshing curve 211 (Line)
Info    : [ 50%] Meshing curve 212 (Line)
Info    : [ 50%] Meshing curve 213 (Line)
Info    : [ 50%] Meshing curve 214 (Line)
Info    : [ 50%] Meshing curve 215 (Line)
Info    : [ 50%] Meshing curve 216 (Line)
Info    : [ 50%] Meshing curve 217 (Line)
Info    : [ 50%] Meshing curve 218 (Line)
Info    : [ 50%] Meshing curve 219 (Line)
Info    : [ 50%] Meshing curve 220 (Line)
Info    : [ 50%] Meshing curve 221 (Line)
Info    : [ 50%] Meshing curve 222 (Line)
Info    : [ 60%] Meshing curve 223 (Line)
Info    : [ 60%] Meshing curve 224 (Line)
Info    : [ 60%] Meshing curve 225 (Line)
Info    : [ 60%] Meshing curve 226 (Line)
Info    : [ 60%] Meshing curve 227 (Line)
Info    : [ 60%] Meshing curve 228 (Line)
Info    : [ 60%] Meshing curve 229 (Line)
Info    : [ 60%] Meshing curve 230 (Line)
Info    : [ 60%] Meshing curve 231 (Line)
Info    : [ 60%] Meshing curve 232 (Line)
Info    : [ 60%] Meshing curve 233 (Line)
Info    : [ 60%] Meshing curve 234 (Line)
Info    : [ 60%] Meshing curve 235 (Line)
Info    : [ 60%] Meshing curve 236 (Line)
Info    : [ 60%] Meshing curve 237 (Line)
Info    : [ 60%] Meshing curve 238 (Line)
Info    : [ 60%] Meshing curve 239 (Line)
Info    : [ 60%] Meshing curve 240 (Line)
Info    : [ 60%] Meshing curve 241 (Line)
Info    : [ 60%] Meshing curve 242 (Line)
Info    : [ 60%] Meshing curve 243 (Line)
Info    : [ 60%] Meshing curve 244 (Line)
Info    : [ 60%] Meshing curve 245 (Line)
Info    : [ 60%] Meshing curve 246 (Line)
Info    : [ 60%] Meshing curve 247 (Line)
Info    : [ 60%] Meshing curve 248 (Line)
Info    : [ 60%] Meshing curve 249 (Line)
Info    : [ 60%] Meshing curve 250 (Line)
Info    : [ 60%] Meshing curve 251 (Line)
Info    : [ 60%] Meshing curve 252 (Line)
Info    : [ 60%] Meshing curve 253 (Line)
Info    : [ 60%] Meshing curve 254 (Line)
Info    : [ 60%] Meshing curve 255 (Line)
Info    : [ 60%] Meshing curve 256 (Line)
Info    : [ 60%] Meshing curve 257 (Line)
Info    : [ 60%] Meshing curve 258 (Line)
Info    : [ 60%] Meshing curve 259 (Line)
Info    : [ 60%] Meshing curve 260 (Line)
Info    : [ 60%] Meshing curve 261 (Line)
Info    : [ 60%] Meshing curve 262 (Line)
Info    : [ 60%] Meshing curve 263 (Line)
Info    : [ 60%] Meshing curve 264 (Line)
Info    : [ 60%] Meshing curve 265 (Line)
Info    : [ 60%] Meshing curve 266 (Line)
Info    : [ 60%] Meshing curve 267 (Line)
Info    : [ 70%] Meshing curve 268 (Line)
Info    : [ 70%] Meshing curve 269 (Line)
Info    : [ 70%] Meshing curve 270 (Line)
Info    : [ 70%] Meshing curve 271 (Line)
Info    : [ 70%] Meshing curve 272 (Line)
Info    : [ 70%] Meshing curve 273 (Line)
Info    : [ 70%] Meshing curve 274 (Line)
Info    : [ 70%] Meshing curve 275 (Line)
Info    : [ 70%] Meshing curve 276 (Line)
Info    : [ 70%] Meshing curve 277 (Line)
Info    : [ 70%] Meshing curve 278 (Line)
Info    : [ 70%] Meshing curve 279 (Line)
Info    : [ 70%] Meshing curve 280 (Line)
Info    : [ 70%] Meshing curve 281 (Line)
Info    : [ 70%] Meshing curve 282 (Line)
Info    : [ 70%] Meshing curve 283 (Line)
Info    : [ 70%] Meshing curve 284 (Line)
Info    : [ 70%] Meshing curve 285 (Line)
Info    : [ 70%] Meshing curve 286 (Line)
Info    : [ 70%] Meshing curve 287 (Line)
Info    : [ 70%] Meshing curve 288 (Line)
Info    : [ 70%] Meshing curve 289 (Line)
Info    : [ 70%] Meshing curve 290 (Line)
Info    : [ 70%] Meshing curve 291 (Line)
Info    : [ 70%] Meshing curve 292 (Line)
Info    : [ 70%] Meshing curve 293 (Line)
Info    : [ 70%] Meshing curve 294 (Line)
Info    : [ 70%] Meshing curve 295 (Line)
Info    : [ 70%] Meshing curve 296 (Line)
Info    : [ 70%] Meshing curve 297 (Line)
Info    : [ 70%] Meshing curve 298 (Line)
Info    : [ 70%] Meshing curve 299 (Line)
Info    : [ 70%] Meshing curve 300 (Line)
Info    : [ 70%] Meshing curve 301 (Line)
Info    : [ 70%] Meshing curve 302 (Line)
Info    : [ 70%] Meshing curve 303 (Line)
Info    : [ 70%] Meshing curve 304 (Line)
Info    : [ 70%] Meshing curve 305 (Line)
Info    : [ 70%] Meshing curve 306 (Line)
Info    : [ 70%] Meshing curve 307 (Line)
Info    : [ 70%] Meshing curve 308 (Line)
Info    : [ 70%] Meshing curve 309 (Line)
Info    : [ 70%] Meshing curve 310 (Line)
Info    : [ 70%] Meshing curve 311 (Line)
Info    : [ 80%] Meshing curve 312 (Line)
Info    : [ 80%] Meshing curve 313 (Line)
Info    : [ 80%] Meshing curve 314 (Line)
Info    : [ 80%] Meshing curve 315 (Line)
Info    : [ 80%] Meshing curve 316 (Line)
Info    : [ 80%] Meshing curve 317 (Line)
Info    : [ 80%] Meshing curve 318 (Line)
Info    : [ 80%] Meshing curve 319 (Line)
Info    : [ 80%] Meshing curve 320 (Line)
Info    : [ 80%] Meshing curve 321 (Line)
Info    : [ 80%] Meshing curve 322 (Line)
Info    : [ 80%] Meshing curve 323 (Line)
Info    : [ 80%] Meshing curve 324 (Line)
Info    : [ 80%] Meshing curve 325 (Line)
Info    : [ 80%] Meshing curve 326 (Line)
Info    : [ 80%] Meshing curve 327 (Line)
Info    : [ 80%] Meshing curve 328 (Line)
Info    : [ 80%] Meshing curve 329 (Line)
Info    : [ 80%] Meshing curve 330 (Line)
Info    : [ 80%] Meshing curve 331 (Line)
Info    : [ 80%] Meshing curve 332 (Line)
Info    : [ 80%] Meshing curve 333 (Line)
Info    : [ 80%] Meshing curve 334 (Line)
Info    : [ 80%] Meshing curve 335 (Line)
Info    : [ 80%] Meshing curve 336 (Line)
Info    : [ 80%] Meshing curve 337 (Line)
Info    : [ 80%] Meshing curve 338 (Line)
Info    : [ 80%] Meshing curve 339 (Line)
Info    : [ 80%] Meshing curve 340 (Line)
Info    : [ 80%] Meshing curve 341 (Line)
Info    : [ 80%] Meshing curve 342 (Line)
Info    : [ 80%] Meshing curve 343 (Line)
Info    : [ 80%] Meshing curve 344 (Line)
Info    : [ 80%] Meshing curve 345 (Line)
Info    : [ 80%] Meshing curve 346 (Line)
Info    : [ 80%] Meshing curve 347 (Line)
Info    : [ 80%] Meshing curve 348 (Line)
Info    : [ 80%] Meshing curve 349 (Line)
Info    : [ 80%] Meshing curve 350 (Line)
Info    : [ 80%] Meshing curve 351 (Line)
Info    : [ 80%] Meshing curve 352 (Line)
Info    : [ 80%] Meshing curve 353 (Line)
Info    : [ 80%] Meshing curve 354 (Line)
Info    : [ 80%] Meshing curve 355 (Line)
Info    : [ 80%] Meshing curve 356 (Line)
Info    : [ 90%] Meshing curve 357 (Line)
Info    : [ 90%] Meshing curve 358 (Line)
Info    : [ 90%] Meshing curve 359 (Line)
Info    : [ 90%] Meshing curve 360 (Line)
Info    : [ 90%] Meshing curve 361 (Line)
Info    : [ 90%] Meshing curve 362 (Line)
Info    : [ 90%] Meshing curve 363 (Line)
Info    : [ 90%] Meshing curve 364 (Line)
Info    : [ 90%] Meshing curve 365 (Line)
Info    : [ 90%] Meshing curve 366 (Line)
Info    : [ 90%] Meshing curve 367 (Line)
Info    : [ 90%] Meshing curve 368 (Line)
Info    : [ 90%] Meshing curve 369 (Line)
Info    : [ 90%] Meshing curve 370 (Line)
Info    : [ 90%] Meshing curve 371 (Line)
Info    : [ 90%] Meshing curve 372 (Line)
Info    : [ 90%] Meshing curve 373 (Line)
Info    : [ 90%] Meshing curve 374 (Line)
Info    : [ 90%] Meshing curve 375 (Line)
Info    : [ 90%] Meshing curve 376 (Line)
Info    : [ 90%] Meshing curve 377 (Line)
Info    : [ 90%] Meshing curve 378 (Line)
Info    : [ 90%] Meshing curve 379 (Line)
Info    : [ 90%] Meshing curve 380 (Line)
Info    : [ 90%] Meshing curve 381 (Line)
Info    : [ 90%] Meshing curve 382 (Line)
Info    : [ 90%] Meshing curve 383 (Line)
Info    : [ 90%] Meshing curve 384 (Line)
Info    : [ 90%] Meshing curve 385 (Line)
Info    : [ 90%] Meshing curve 386 (Line)
Info    : [ 90%] Meshing curve 387 (Line)
Info    : [ 90%] Meshing curve 388 (Line)
Info    : [ 90%] Meshing curve 389 (Line)
Info    : [ 90%] Meshing curve 390 (Line)
Info    : [ 90%] Meshing curve 391 (Line)
Info    : [ 90%] Meshing curve 392 (Line)
Info    : [ 90%] Meshing curve 393 (Line)
Info    : [ 90%] Meshing curve 394 (Line)
Info    : [ 90%] Meshing curve 395 (Line)
Info    : [ 90%] Meshing curve 396 (Line)
Info    : [ 90%] Meshing curve 397 (Line)
Info    : [ 90%] Meshing curve 398 (Line)
Info    : [ 90%] Meshing curve 399 (Line)
Info    : [ 90%] Meshing curve 400 (Line)
Info    : [100%] Meshing curve 401 (Line)
Info    : [100%] Meshing curve 402 (Line)
Info    : [100%] Meshing curve 403 (Line)
Info    : [100%] Meshing curve 404 (Line)
Info    : [100%] Meshing curve 405 (Line)
Info    : [100%] Meshing curve 406 (Line)
Info    : [100%] Meshing curve 407 (Line)
Info    : [100%] Meshing curve 408 (Line)
Info    : [100%] Meshing curve 409 (Line)
Info    : [100%] Meshing curve 410 (Line)
Info    : [100%] Meshing curve 411 (Line)
Info    : [100%] Meshing curve 412 (Line)
Info    : [100%] Meshing curve 413 (Line)
Info    : [100%] Meshing curve 414 (Line)
Info    : [100%] Meshing curve 415 (Line)
Info    : [100%] Meshing curve 416 (Line)
Info    : [100%] Meshing curve 417 (Line)
Info    : [100%] Meshing curve 418 (Line)
Info    : [100%] Meshing curve 419 (Line)
Info    : [100%] Meshing curve 420 (Line)
Info    : [100%] Meshing curve 421 (Line)
Info    : [100%] Meshing curve 422 (Line)
Info    : [100%] Meshing curve 423 (Line)
Info    : [100%] Meshing curve 424 (Line)
Info    : [100%] Meshing curve 425 (Line)
Info    : [100%] Meshing curve 426 (Line)
Info    : [100%] Meshing curve 427 (Line)
Info    : [100%] Meshing curve 428 (Line)
Info    : [100%] Meshing curve 429 (Line)
Info    : [100%] Meshing curve 430 (Line)
Info    : [100%] Meshing curve 431 (Line)
Info    : [100%] Meshing curve 432 (Line)
Info    : [100%] Meshing curve 433 (Line)
Info    : [100%] Meshing curve 434 (Line)
Info    : [100%] Meshing curve 435 (Line)
Info    : [100%] Meshing curve 436 (Line)
Info    : [100%] Meshing curve 437 (Line)
Info    : [100%] Meshing curve 438 (Line)
Info    : [100%] Meshing curve 439 (Line)
Info    : [100%] Meshing curve 440 (Line)
Info    : [100%] Meshing curve 441 (Line)
Info    : [100%] Meshing curve 442 (Line)
Info    : [100%] Meshing curve 443 (Line)
Info    : [100%] Meshing curve 444 (Line)
Info    : Done meshing 1D (Wall 0.0221882s, CPU 0.018358s)
Info    : Meshing 2D...
Info    : [  0%] Meshing surface 1 (Plane, Frontal-Delaunay)
Info    : [ 10%] Meshing surface 2 (Plane, Frontal-Delaunay)
Info    : [ 10%] Meshing surface 3 (Plane, Frontal-Delaunay)
Info    : [ 10%] Meshing surface 4 (Plane, Frontal-Delaunay)
Info    : [ 10%] Meshing surface 5 (Plane, Frontal-Delaunay)
Info    : [ 10%] Meshing surface 6 (Plane, Frontal-Delaunay)
Info    : [ 10%] Meshing surface 7 (Plane, Frontal-Delaunay)
Info    : [ 10%] Meshing surface 8 (Plane, Frontal-Delaunay)
Info    : [ 20%] Meshing surface 9 (Plane, Frontal-Delaunay)
Info    : [ 20%] Meshing surface 10 (Plane, Frontal-Delaunay)
Info    : [ 20%] Meshing surface 11 (Plane, Frontal-Delaunay)
Info    : [ 20%] Meshing surface 12 (Plane, Frontal-Delaunay)
Info    : [ 20%] Meshing surface 13 (Plane, Frontal-Delaunay)
Info    : [ 20%] Meshing surface 14 (Plane, Frontal-Delaunay)
Info    : [ 20%] Meshing surface 15 (Plane, Frontal-Delaunay)
Info    : [ 20%] Meshing surface 16 (Plane, Frontal-Delaunay)
Info    : [ 30%] Meshing surface 17 (Plane, Frontal-Delaunay)
Info    : [ 30%] Meshing surface 18 (Plane, Frontal-Delaunay)
Info    : [ 30%] Meshing surface 19 (Plane, Frontal-Delaunay)
Info    : [ 30%] Meshing surface 20 (Plane, Frontal-Delaunay)
Info    : [ 30%] Meshing surface 21 (Plane, Frontal-Delaunay)
Info    : [ 30%] Meshing surface 22 (Plane, Frontal-Delaunay)
Info    : [ 30%] Meshing surface 23 (Plane, Frontal-Delaunay)
Info    : [ 40%] Meshing surface 24 (Plane, Frontal-Delaunay)
Info    : [ 40%] Meshing surface 25 (Plane, Frontal-Delaunay)
Info    : [ 40%] Meshing surface 26 (Plane, Frontal-Delaunay)
Info    : [ 40%] Meshing surface 27 (Plane, Frontal-Delaunay)
Info    : [ 40%] Meshing surface 28 (Plane, Frontal-Delaunay)
Info    : [ 40%] Meshing surface 29 (Plane, Frontal-Delaunay)
Info    : [ 40%] Meshing surface 30 (Plane, Frontal-Delaunay)
Info    : [ 40%] Meshing surface 31 (Plane, Frontal-Delaunay)
Info    : [ 50%] Meshing surface 32 (Plane, Frontal-Delaunay)
Info    : [ 50%] Meshing surface 33 (Plane, Frontal-Delaunay)
Info    : [ 50%] Meshing surface 34 (Plane, Frontal-Delaunay)
Info    : [ 50%] Meshing surface 35 (Plane, Frontal-Delaunay)
Info    : [ 50%] Meshing surface 36 (Plane, Frontal-Delaunay)
Info    : [ 50%] Meshing surface 37 (Plane, Frontal-Delaunay)
Info    : [ 50%] Meshing surface 38 (Plane, Frontal-Delaunay)
Info    : [ 60%] Meshing surface 39 (Plane, Frontal-Delaunay)
Info    : [ 60%] Meshing surface 40 (Plane, Frontal-Delaunay)
Info    : [ 60%] Meshing surface 41 (Plane, Frontal-Delaunay)
Info    : [ 60%] Meshing surface 42 (Plane, Frontal-Delaunay)
Info    : [ 60%] Meshing surface 43 (Plane, Frontal-Delaunay)
Info    : [ 60%] Meshing surface 44 (Plane, Frontal-Delaunay)
Info    : [ 60%] Meshing surface 45 (Plane, Frontal-Delaunay)
Info    : [ 60%] Meshing surface 46 (Plane, Frontal-Delaunay)
Info    : [ 70%] Meshing surface 47 (Plane, Frontal-Delaunay)
Info    : [ 70%] Meshing surface 48 (Plane, Frontal-Delaunay)
Info    : [ 70%] Meshing surface 49 (Plane, Frontal-Delaunay)
Info    : [ 70%] Meshing surface 50 (Plane, Frontal-Delaunay)
Info    : [ 70%] Meshing surface 51 (Plane, Frontal-Delaunay)
Info    : [ 70%] Meshing surface 52 (Plane, Frontal-Delaunay)
Info    : [ 70%] Meshing surface 53 (Plane, Frontal-Delaunay)
Info    : [ 70%] Meshing surface 54 (Plane, Frontal-Delaunay)
Info    : [ 80%] Meshing surface 55 (Plane, Frontal-Delaunay)
Info    : [ 80%] Meshing surface 56 (Plane, Frontal-Delaunay)
Info    : [ 80%] Meshing surface 57 (Plane, Frontal-Delaunay)
Info    : [ 80%] Meshing surface 58 (Plane, Frontal-Delaunay)
Info    : [ 80%] Meshing surface 59 (Plane, Frontal-Delaunay)
Info    : [ 80%] Meshing surface 60 (Plane, Frontal-Delaunay)
Info    : [ 80%] Meshing surface 61 (Plane, Frontal-Delaunay)
Info    : [ 90%] Meshing surface 62 (Plane, Frontal-Delaunay)
Info    : [ 90%] Meshing surface 63 (Plane, Frontal-Delaunay)
Info    : [ 90%] Meshing surface 64 (Plane, Frontal-Delaunay)
Info    : [ 90%] Meshing surface 65 (Plane, Frontal-Delaunay)
Info    : [ 90%] Meshing surface 66 (Plane, Frontal-Delaunay)
Info    : [ 90%] Meshing surface 67 (Plane, Frontal-Delaunay)
Info    : [ 90%] Meshing surface 68 (Plane, Frontal-Delaunay)
Info    : [ 90%] Meshing surface 69 (Plane, Frontal-Delaunay)
Info    : [100%] Meshing surface 70 (Plane, Frontal-Delaunay)
Info    : [100%] Meshing surface 71 (Plane, Frontal-Delaunay)
Info    : [100%] Meshing surface 72 (Plane, Frontal-Delaunay)
Info    : [100%] Meshing surface 73 (Plane, Frontal-Delaunay)
Info    : [100%] Meshing surface 74 (Plane, Frontal-Delaunay)
Info    : [100%] Meshing surface 75 (Plane, Frontal-Delaunay)
Info    : [100%] Meshing surface 76 (Plane, Frontal-Delaunay)
Info    : Done meshing 2D (Wall 0.298913s, CPU 0.28687s)
Info    : 13269 nodes 29927 elements
Info    : Writing 'voronoi_grains.msh'...
Info    : Done writing 'voronoi_grains.msh'

FESTIM model#

We can now define our hydrogen transport problem.

\[ \frac{\partial c}{\partial t} = \nabla \cdot (D \nabla c) \]

where \(D=D_\mathrm{GB}\) and \(D=D_\mathrm{grain}\) in the grain boundary and grain, respectively.

Boundary conditions:

  • \( c = 0 \) on the left surface

  • \( c = 1 \) on the right surface

Interface condition:

  • We assume continuity of concentration at the GB/grain interfaces.

Simulation time: \(t_f = 1.5\)

Convert mesh to dolfinx#

from dolfinx.io import gmsh as gmshio
from mpi4py import MPI


model_rank = 0
mesh_data = gmshio.read_from_msh(
    "voronoi_grains.msh", MPI.COMM_WORLD, 0, gdim=2
)
mesh = mesh_data.mesh
assert mesh_data.facet_tags is not None
facet_tags = mesh_data.facet_tags
facet_tags.name = "Facet markers"

assert mesh_data.cell_tags is not None
cell_tags = mesh_data.cell_tags
cell_tags.name = "Cell markers"
Info    : Reading 'voronoi_grains.msh'...
Info    : 927 entities
Info    : 13269 nodes
Info    : 26318 elements
Info    : Done reading 'voronoi_grains.msh'

Hide code cell source

from dolfinx import plot
import pyvista

pyvista.set_jupyter_backend("html")

tdim = mesh.topology.dim

mesh.topology.create_connectivity(tdim, tdim)
fdim = mesh.topology.dim - 1
tdim = mesh.topology.dim
mesh.topology.create_connectivity(fdim, tdim)

topology, cell_types, x = plot.vtk_mesh(mesh, tdim, cell_tags.indices)
p = pyvista.Plotter()
grid = pyvista.UnstructuredGrid(topology, cell_types, x)
grid.cell_data["Cell Marker"] = cell_tags.values
grid.set_active_scalars("Cell Marker")
p.add_mesh(grid, show_edges=False)
if pyvista.OFF_SCREEN:
    figure = p.screenshot("cell_marker.png")
p.show()
2026-05-22 15:16:43.202 (   1.413s) [    7B94F2825740]vtkXOpenGLRenderWindow.:1458  WARN| bad X server connection. DISPLAY=

Case 1: GBs are more diffusive#

In this first case, \(D_\mathrm{GB}= 1000 \ D_\mathrm{grain}\)

import festim as F

grain_mat = F.Material(D_0=0.001, E_D=0)
gb_mat = F.Material(D_0=1, E_D=0)


grain_vol = F.VolumeSubdomain(id=1, material=grain_mat)
gb_vol = F.VolumeSubdomain(id=2, material=gb_mat)

left_surf = F.SurfaceSubdomain(id=3)
right_surf = F.SurfaceSubdomain(id=4)

my_model = F.HydrogenTransportProblem()

my_model.mesh = F.Mesh(mesh)

# we need to pass the meshtags to the model directly
my_model.facet_meshtags = facet_tags
my_model.volume_meshtags = cell_tags

my_model.subdomains = [left_surf, right_surf, grain_vol, gb_vol]

H = F.Species("H")
my_model.species = [H]

my_model.temperature = 400

my_model.boundary_conditions = [
    F.FixedConcentrationBC(subdomain=left_surf, value=0, species=H),
    F.FixedConcentrationBC(subdomain=right_surf, value=1, species=H),
]

my_model.settings = F.Settings(atol=1e-10, rtol=1e-20, final_time=1.5)
my_model.settings.stepsize = 0.01

my_model.exports = [F.VTXSpeciesExport(filename="out.bp", field=H)]

my_model.initialise()
my_model.run()
/home/docs/checkouts/readthedocs.org/user_builds/festim-workshop/conda/latest/lib/python3.12/site-packages/festim/coupled_heat_hydrogen_problem.py:1: TqdmExperimentalWarning: Using `tqdm.autonotebook.tqdm` in notebook mode. Use `tqdm.tqdm` instead to force console mode (e.g. in jupyter console)
  import tqdm.autonotebook

At the end of the simulation, we can see on the concentration field the preferential diffusion along the grain boundaries!

Hide code cell source

hydrogen_concentration = H.post_processing_solution

topology, cell_types, geometry = plot.vtk_mesh(hydrogen_concentration.function_space)
u_grid = pyvista.UnstructuredGrid(topology, cell_types, geometry)
u_grid.point_data["c"] = hydrogen_concentration.x.array.real
u_grid.set_active_scalars("c")
u_plotter = pyvista.Plotter()
u_plotter.add_mesh(u_grid, show_edges=False)

u_plotter.add_title(f"D_GB/D_grain = {gb_mat.D_0/grain_mat.D_0: .4f}")


if not pyvista.OFF_SCREEN:
    u_plotter.show()
else:
    figure = u_plotter.screenshot("concentration.png")

Case 2: GBs are less diffusive#

We can also look at the opposite case with grain boundaries less diffusive the the grain themselves.

gb_mat.D_0 = 0.1
grain_mat.D_0 = 1

my_model.initialise()
my_model.run()

Hide code cell source

hydrogen_concentration = H.post_processing_solution

topology, cell_types, geometry = plot.vtk_mesh(hydrogen_concentration.function_space)
u_grid = pyvista.UnstructuredGrid(topology, cell_types, geometry)
u_grid.point_data["c"] = hydrogen_concentration.x.array.real
u_grid.set_active_scalars("c")
u_plotter = pyvista.Plotter()

u_plotter.add_mesh(u_grid, show_edges=False)

u_plotter.add_title(f"D_GB/D_grain = {gb_mat.D_0/grain_mat.D_0: .1f}")

if not pyvista.OFF_SCREEN:
    u_plotter.show()
else:
    figure = u_plotter.screenshot("concentration.png")