Hydrogen transport: advanced#
This section discusses how to implement advanced boundary conditions (BCs) for hydrogen transport problems.
Objectives:
Choose solubility laws (Henry’s or Siervert’s)
Implement surface reaction boundary conditions
Model isotopic exchange as a recombination flux
Understanding background for solubility laws and surface reactions#
Solubility laws#
A solubility law prescribes the equilibrium relationship between the hydrogen concentration in a solid and the surrounding environment. Two common solubility laws for hydrogen are Henry’s law and Sieverts’ law:
Henry’s law#
Henry’s law assumes a linear relationship between the hydrogen concentration in the solid and the partial pressure of hydrogen in the gas:
where:
\(c_s\) is the surface concentration,
\(P_H\) is the hydrogen partial pressure in the surrounding environment,
\(k_H\) is the Henry’s law constant (material and temperature-dependent).
Tip
Users interested in molten salt interactions with hydrogen will usually need to use Henry’s Law.
Sieverts’ law#
Sieverts’ law applies when hydrogen dissolves in metals as atomic hydrogen. The solubility is proportional to the square root of the hydrogen partial pressure (due to diatomic hydrogen dissociating into atoms in the solid):
where:
\(k_S\) is the Sieverts’ constant (which depends on temperature and the metal)
Tip
Users interested in liquid metal interactions with hydrogen will usually need to use Sievert’s Law.
Imposing a solubility law#
Users can define the surface concentration using either Sieverts’ law. For Sieverts’ law of solubility, we can use SievertsBC:
import festim as F
boundary = F.SurfaceSubdomain(id=1)
H = F.Species(name="Hydrogen")
custom_pressure_value = lambda t: 2 + t
my_sieverts_bc = F.SievertsBC(subdomain=3, S_0=2, E_S=0.1, species=H, pressure=custom_pressure_value)
/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
Similarly, for Henry’s law of solubility, we can use HenrysBC:
pressure_value = lambda t: 5 * t
my_henrys_bc = F.HenrysBC(subdomain=3, H_0=1.5, E_H=0.2, species=H, pressure=pressure_value)
To use these BCs in your simulation, add them to boundary_conditions:
my_model = F.HydrogenTransportProblem()
my_model.boundary_conditions = [my_sieverts_bc, my_henrys_bc]
Note
Using HenrysBC or SievertsBC is just a convenient way for users to define a FixedConcentrationBC, using the solubility law to calculate the concentration.
Simple surface reaction#
Surface reactions between adsorbed species and gas-phase products can be represented using the SurfaceReactionBC class. This boundary condition defines a reversible reaction of the form:
where:
\(\mathrm{A}, \mathrm{B}\) are surface reactants
\(\mathrm{C}\) is the product species in the gas phase
\(\mathrm{K}_r\) and \(\mathrm{K}_d\) are forward and backward reaction rates, respectively
Mathematical formulation#
Let:
\(c_A, c_B\) be the surface concentrations of \(\mathrm{A}\) and \(\mathrm{B}\)
\(P_C\) be the partial pressure of \(\mathrm{C}\)
\(T\) the surface temperature
\(k_B\) the Boltzmann constant
The forward and backward reaction rates follow Arrhenius laws:
The net surface reaction rate is:
The resulting flux of species \(\mathrm{A}\) into the surface is:
If \(\mathrm{A=B}\), the total flux becomes:
where \(\mathbf{n}\) is the outward normal vector at the surface.
Recombination and dissociation#
If \(\text{Species A = Species B}\), recombination or dissociation can also be modeled with SurfaceReactionBC, e.g.:
where
and corresponding flux of atomic hydrogen is:
Implementing surface reaction boundary conditions#
Users can impose a surface reaction on a boundary using SurfaceReactionBC.
First, create a boundary to impose the BC and the reactant species:
Now, we add these as arguments to the SurfaceReactionBC class. We’ll also need to assign a gas_pressure (corresponding to the partial pressure of the product species), and the forward/backward rate (k_r0, k_d0) and energy (E_kr, E_kd) coefficients (see above to learn more about these parameters):
my_bc = F.SurfaceReactionBC(
reactant=[A, B],
gas_pressure=1e5,
k_r0=1,
E_kr=0.1,
k_d0=0,
E_kd=0,
subdomain=boundary,
)
Finally, add the BC to your problem’s boundary_conditions attribute using a list:
my_model = F.HydrogenTransportProblem()
my_model.boundary_conditions = [my_bc]
Note
Using SurfaceReactionBC is just a convenient way for users to define surface fluxes, which can be done manually (as shown below in the isotopic exchange example).
Isotopic exchange#
Isotopic exchange occurs when hydrogenic isotopes swap positions, for example:
Mathematical formulation#
Let:
\(c_T\) be the surface concentrations of tritium
\(P_\mathrm{H_2}, P_\mathrm{HT}\) the partial pressures of \(\mathrm{H_2}\) and \(\mathrm{HT}\)
\(K_{r}\) the rate coefficient of reaction (1)
\(K_{r}^\ast\) the rate coefficient of reaction (2)
If \(c_{H_2} \gg c_{HT}\), the flux of tritium is approximated as:
with $\( \phi_\mathrm{recombination} = - K_{r} c_T^2 \\ \phi_\mathrm{exchange} = - K_{r}^\ast P_{H_2} c_T \)$
These fluxes can be implemented in FESTIM using ParticleFluxBC with user-defined expressions for each reaction term, as shown below.
Note
\(K_{r0}^\ast\) and \(K_{r0}\) have different dimensions since \(P_\mathrm{H_2}\) is a pressure.
Note
This example is not tracking the dissolution and transport of protium in the metal. And assumes that the partial presure of \(\mathrm{H_2}\) is constant.
Note
For more complex isotopic exchanges, we can also use SurfaceReactionBC add other reactions. See modeling isotopic exchange for multiple species to learn more.
Implementation#
Let’s work through a 1D example to illustrate the effect of isotopic exchange. We’ll consider tritium diffusion from left to right, with a large partial pressure of \(H_2\) at the right boundary (where isotopic exchange can occur).
First, we’ll set up our mesh and materials:
import numpy as np
my_model = F.HydrogenTransportProblem()
my_model.mesh = F.Mesh1D(vertices=np.linspace(0, 1, 100))
right_subdomain = F.SurfaceSubdomain1D(id=2, x=1)
left_subdomain = F.SurfaceSubdomain1D(id=3, x=0)
material = F.Material(D_0=1e-2, E_D=0)
vol = F.VolumeSubdomain1D(id=5, material=material, borders=[0, 1])
my_model.subdomains = [vol, left_subdomain, right_subdomain]
Isotopic exchange reactions can be modeled as user-defined expressions using ufl.
Now we’ll add our species tritium to our model and define a custom flux to represent isotopic exchange. We use ParticleFluxBC and the custom flux function we defined above to define this BC on the right boundary:
tritium = F.Species("T")
my_model.species = [tritium]
isotopic_exchange_flux = F.ParticleFluxBC(
value=isotopic_exchange_flux_func,
subdomain=right_subdomain,
species_dependent_value={"c": tritium},
species=tritium,
)
t2_recomb = F.SurfaceReactionBC(
reactant=[tritium, tritium],
gas_pressure=0,
k_r0=1e-22,
E_kr=0,
k_d0=0,
E_kd=0,
subdomain=right_subdomain,
)
For diffusion across the mesh, we also define a fixed concentration on the left surface:
my_model.boundary_conditions = [
isotopic_exchange_flux,
t2_recomb,
F.FixedConcentrationBC(subdomain=left_subdomain, value=1e20, species=tritium),
]
We’ll export the flux using SurfaceFlux (see exporting derived quantities to learn more) and save this data to a variable data_with_H2. We also create a Profile1DExport to be able to plot the concentration profile later:
surface_flux = F.SurfaceFlux(field=tritium, surface=right_subdomain)
profile = F.Profile1DExport(field=tritium, subdomain=vol)
my_model.temperature = 300
my_model.settings = F.Settings(atol=1e-10, rtol=1e-8, stepsize=1, final_time=120)
my_model.exports = [surface_flux, profile]
my_model.initialise()
my_model.run()
data_with_H2 = surface_flux.data.copy()
Let’s plot the evolution of the tritium concentration profile: