from festim import FluxBC
from fenics import *
import sympy as sp
[docs]
class SurfaceKinetics(FluxBC):
r"""
FluxBC subclass allowing to include surface processes in 1D H transport simulations:
.. math::
\dfrac{d c_{\mathrm{s}}}{dt} = J_{\mathrm{bs}} - J_{\mathrm{sb}} + J_{\mathrm{vs}};
.. math::
-D \nabla c_\mathrm{m} \cdot \mathbf{n} = \lambda_{\mathrm{IS}} \dfrac{\partial c_{\mathrm{m}}}{\partial t}
+ J_{\mathrm{bs}} - J_{\mathrm{sb}},
where :math:`c_{\mathrm{m}}` is the concentration of mobile hydrogen (:math:`\mathrm{H \ m}^{-3}`),
:math:`c_{\mathrm{s}}` is the surface concentration of adsorbed hydrogen (:math:`\mathrm{H \ m}^{-2}`),
the H flux from subsurface to surface :math:`J_{\mathrm{bs}}` (in :math:`\mathrm{m}^{-2} \ \mathrm{s}^{-1}`) is:
.. math::
J_{\mathrm{bs}} = k_{\mathrm{bs}} c_{\mathrm{m}} \left(1 - \dfrac{c_\mathrm{s}}{n_{\mathrm{surf}}}\right),
the H flux from surface to subsurface :math:`J_{\mathrm{sb}}` (in :math:`\mathrm{m}^{-2} \ \mathrm{s}^{-1}`) is:
.. math::
J_{\mathrm{sb}} = k_{\mathrm{sb}} c_{\mathrm{s}} \left(1 - \dfrac{c_{\mathrm{m}}}{n_\mathrm{IS}}\right),
For more details see:
E.A. Hodille et al 2017 Nucl. Fusion 57 056002; Y. Hamamoto et al 2020 Nucl. Mater. Energy 23 100751
.. warning::
The SurfaceKinetics boundary condition can be used only in 1D simulations!
Args:
k_sb (float or callable): rate constant for the surface-to-subsurface transition (:math:`\mathrm{s}^{-1}`),
can accept additional parameters (see example)
k_bs (float or callable): rate constant for the subsurface-to-surface transition (:math:`\mathrm{m} \ \mathrm{s}^{-1}`),
can accept additional parameters (see example)
lambda_IS (float): characteristic distance between two iterstitial sites (:math:`\mathrm{m}`)
n_surf (float): surface concentration of adsorption sites (:math:`\mathrm{m}^{-2}`)
n_IS (float): bulk concentration of interstitial sites (:math:`\mathrm{m}^{-3}`)
J_vs (float or callable): the net adsorption flux from vacuum to surface (:math:`\mathrm{m}^{-2} \ \mathrm{s}^{-1}`),
can accept additional parameters (see example)
surfaces (int or list): the surfaces for which surface processes are considered
initial_condition (int or float): the initial value of the H surface concentration (:math:`\mathrm{m}^{-2}`)
Attributes:
previous_solutions (list): list containing solutions (fenics.Function or ufl.Indexed)
on each surface for "previous" timestep
test_functions (list): list containing test functions (fenics.TestFunction or ufl.Indexed)
for each surface
post_processing_solutions (list): list containing solutions (fenics.Function or ufl.Indexed)
on each surface used for post-processing
Example::
def K_sb(T, surf_conc, mobile_conc, prm1, prm2):
return 1e13 * f.exp(-2.0/F.k_B/T) + mobile_conc
def K_bs(T, surf_conc, mobile_conc, prm1, prm2):
return 1e13 * f.exp(-0.2/F.k_B/T)
def J_vs(T, surf_conc, mobile_conc, prm1, prm2):
return (1-surf_conc/5) ** 2 * fenics.exp(-2/F.k_B/T) + prm1 * prm2
my_surf_model = SurfaceKinetics(
k_sb=K_sb,
k_bs=K_bs,
lambda_IS=110e-12,
n_surf=2e19,
n_IS=6e28,
J_vs=J_vs,
surfaces=[1, 2],
initial_condition=0,
prm1=2e16,
prm2=F.t
)
"""
def __init__(
self,
k_sb,
k_bs,
lambda_IS,
n_surf,
n_IS,
J_vs,
surfaces,
initial_condition,
**prms,
) -> None:
super().__init__(surfaces=surfaces, field=0)
self.k_sb = k_sb
self.k_bs = k_bs
self.J_vs = J_vs
self.lambda_IS = lambda_IS
self.n_surf = n_surf
self.n_IS = n_IS
self.J_vs = J_vs
self.initial_condition = initial_condition
self.prms = prms
self.convert_prms()
self.solutions = [None] * len(self.surfaces)
self.previous_solutions = [None] * len(self.surfaces)
self.test_functions = [None] * len(self.surfaces)
self.post_processing_solutions = [None] * len(self.surfaces)
def convert_prms(self):
# create Expressions or Constant for all parameters
for key, value in self.prms.items():
if isinstance(value, (int, float)):
self.prms[key] = Constant(value)
else:
self.prms[key] = Expression(sp.printing.ccode(value), t=0, degree=1)