Rémi Delaporte-Mathurin, on behalf of the whole FESTIM community
Simula 25 Years · FEniCS Workshop | Oslo | September 2026
Hydrogen isotopes in a solid: mobile, drifting, and repeatedly trapped in defects.
↑ drift: thermal, electric, advective
one equation per trap population
Why we care: tritium is the fuel, it is scarce, radioactive, and it leaks through everything.
We try to encapsulate every FEniCSx feature we adopt.
2019 – 2024 · FESTIM 1
2024 – today · FESTIM 2
FEniCSx made so many things possible...
At a material interface the concentration is discontinuous. Two conditions hold across it:
chemical potential continuous
flux continuous
Solve for θ = c/K: one continuous field, one space.
The cost: every source, BC, export and reaction rate rewritten in θ. Nonlinear in T. Didn't scale well.
One field per material, each on its own submesh.
Coupled by a condition we choose, not one baked into the function space.
Submeshes, MixedFunctionSpace, assembly over mixed domains. One field per subdomain, one block system:
… and the only thing tying the subdomains together is one term on the interface:
Our users write none of this.
Once the interface condition lives in the form rather than in the function space:
Continuity of chemical potential is just one choice; a flux condition, a kinetic law or a surface reaction work too
Which matters, because equilibrium is sometimes simply wrong.
Delaporte-Mathurin & Dark, When chemical potential continuity fails, arXiv:2608.26231
A subdomain doesn't need to be the same dimension as its parent mesh.
NEW SINCE JULY
A grain boundary is a fast path through a slow bulk. Meshing it as a thin volume is hopeless.
gb = F.VolumeSubdomain(
id=2,
material=F.Material(D_0=D_gb, E_D=0.0),
dim=1, # codimension 1 in a 2D mesh
locator=lambda x: np.isclose(x[0], 0.5),
)
dim. Everything else is the subdomain API users already know.Bulk on Ω (dim n), manifold on Γ (dim n−1), each carrying its own field:
↑ tangential gradient along the manifold
A real polycrystalline microstructure. Hydrogen enters at the top.
Two fields solved together:c_b in the grains (dim=2)c_gb on the boundaries (dim=1)
It reaches depth through the boundary network long before the bulk front arrives.
NEW SINCE JULY
Hydrogen permeates out of a wall into a sealed volume. The pressure obeys an ODE fed by the surface flux, and feeds straight back into the wall’s boundary condition.
One scalar unknown, coupled both ways to a PDE. Our previous answer was an operator splitting and a hand-rolled ODE loop.
We didn’t need one. DOLFINx has real-space elements: P becomes a single global degree of freedom in the same mixed space as the fields, and Newton solves the lot monolithically.
For the user: F.GasSpecies and F.Enclosure. Sieverts’ law then sets c from a pressure with no nodal values, so we impose it weakly, with Nitsche.
Two membranes with a pumped gap. The 1D mesh is discontiguous: no cell spans the gap, so the gas enclosure is the only path across.
c = c0
c = 0
layer 1
gap ↓ pump
layer 2
Enclosure via a surface reactionPump is an opening on it; a purge stream is the same objectPump on: enclosure pressure 25 Pa → 0, and the concentration reaching the second membrane falls by ~5 orders of magnitude.
Permeation flux
Hydrogen does not only follow its own gradient. It drifts: down temperature gradients, under electric fields, and with a moving coolant.
Soret / thermodiffusion; Q_star is the heat of transport
Several drift terms may act on one species; the velocities simply add. SoretTerm, ElectromigrationTerm, AdvectionTerm.
Because the residual is built in UFL, a drift term is literally one more term in the form. No new solver, no new time integrator, and it composes with submeshes and manifolds for free.
NEW SINCE AUGUST
NEW SINCE SEPT
Every feature above multiplies the number of meshes and fields. Users got a directory of .bp files and no way to restart.
F.SpeciesExport("state.bp", field=H, format="checkpoint")
state = F.read_function_from_file("state.bp", name="H", timestamp=10.0)
OpenMC: tritium source
OpenFOAM: velocity
FESTIM: tritium field
openmc2dolfinx and foam2dolfinx hand over DOLFINx functions, not files, so they compose with submeshes, manifolds and drift terms for free.
ARC breeding blanket · ~243 mg tritium inventory · Dark, Sircar, Bae, Dokken & Delaporte-Mathurin, arXiv:2608.05398
Every case is a runnable script. The report rebuilds from them, in public.
festim-vv-report.readthedocs.io
Independently cross-compared against MHIMS and mHIT (Nuclear Materials and Energy)
contributors
institutions
forum views / month
NumFOCUS affiliated
conda install -c conda-forge festim
Monthly dev meetings, open to anyone. A workshop with runnable tutorials for everything in this talk.
If you maintain a FEniCS-based code and want to compare notes on hiding FEM from users, come find me. 😉
Happy 25th, Simula, and thank you for DOLFINx.
github.com/festim-dev/FESTIM
festim.readthedocs.io · festim-workshop.readthedocs.io
Questions?