Sources#

Sources describe the production (or removal) of particles or heat inside the simulated domain, as opposed to boundary conditions which act on its surfaces.

All sources in FESTIM require a volume subdomain, defined with the festim.VolumeSubdomain class. See the Volume Subdomains section for more information on how to define subdomains.

Sources are passed to the problem as a list in its sources attribute.

my_model = F.HydrogenTransportProblem()

my_model.sources = [
    F.ParticleSource(value=1e20, volume=my_vol, species=H),
]

Particle sources#

Volumetric sources of a species are set with the festim.ParticleSource class. A source is defined by its value (in \(\mathrm{m}^{-3}\,\mathrm{s}^{-1}\)), the volume subdomain where it is applied and the species it applies to.

from festim import ParticleSource

my_source = ParticleSource(value=1e20, volume=my_vol, species=H)

The value can be dependent on space, time and temperature:

from festim import ParticleSource

my_custom_value = lambda x, t, T: 1e20 * x[0] + 1e18 * t + T

my_source = ParticleSource(value=my_custom_value, volume=my_vol, species=H)

Note

When defining custom functions for values, only the arguments x, t and T can be defined (plus the species concentrations described below). Spatial coordinates can be referred to by their indices, such as x[0], x[1], and x[2], regardless of the coordinate system used. Time dependence must use t, and T for temperature dependence.

Species-dependent sources#

The value of a particle source can also depend on the concentration of one or several species. As for festim.ParticleFluxBC, the species_dependent_value argument maps the names of the arguments of the custom function to the corresponding festim.Species objects:

from festim import ParticleSource, Species

A = Species(name="A")
B = Species(name="B")

my_custom_value = lambda c_A, c_B: 2 * c_A - 3 * c_B

my_source = ParticleSource(
    value=my_custom_value,
    volume=my_vol,
    species=A,
    species_dependent_value={"c_A": A, "c_B": B},
)

This is the mechanism used internally by FESTIM to expand reactions into sources. For reactions between species (trapping, radioactive decay, hydride formation…), prefer the dedicated reaction classes described in the Species page.

Implantation flux#

Hydrogen implanted in a material can be simulated by a Gaussian-shaped volumetric source. Unlike FESTIM 1.x, there is no dedicated class for it in FESTIM 2: the profile is simply given as a function of space. For an implantation flux \(\varphi\) (in \(\mathrm{m}^{-2}\,\mathrm{s}^{-1}\)), an implantation depth \(R_p\) and a width \(\sigma\):

\[S(x) = \frac{\varphi}{\sigma \sqrt{2 \pi}} \exp \left( - \frac{(x - R_p)^2}{2 \sigma^2} \right)\]
import numpy as np
import ufl
from festim import ParticleSource

flux = 1e20  # H/m2/s
imp_depth = 1e-9  # m
width = 1e-9  # m

def gaussian(x):
    return (
        flux
        / (width * np.sqrt(2 * np.pi))
        * ufl.exp(-0.5 * ((x[0] - imp_depth) / width) ** 2)
    )

my_source = ParticleSource(value=gaussian, volume=my_vol, species=H)

Note

The function above is evaluated symbolically on the mesh coordinates, so the mathematical functions must come from ufl (ufl.exp, ufl.sin…) rather than from numpy or math. Plain arithmetic operations (+, *, **…) and numpy constants are fine.

The implantation flux can be made time dependent by adding t to the arguments of the function.

Heat sources#

Volumetric heat sources (in \(\mathrm{W}\,\mathrm{m}^{-3}\)) are set with the festim.HeatSource class and are passed to a festim.HeatTransferProblem (see Temperature).

from festim import HeatSource

my_heat_source = HeatSource(value=1e6, volume=my_vol)

As for particle sources, the value can be dependent on space and time:

from festim import HeatSource

my_custom_value = lambda x, t: 1e6 * x[0] + 1e4 * t

my_heat_source = HeatSource(value=my_custom_value, volume=my_vol)

Note

Heat sources cannot be temperature dependent.

Radioactive decay#

In FESTIM 1.x, radioactive decay was a source (festim.RadioactiveDecay). In FESTIM 2 it is a reaction, defined with the festim.DecayReaction class and passed to the reactions attribute of the problem (see Reactions).

from festim import DecayReaction, Species

tritium = Species(name="T")

my_model.species = [tritium]
my_model.reactions = [
    DecayReaction(reactant=tritium, half_life=3.888e8, volume=my_vol),
]