examples.elphf.diffusion.mesh1Ddimensional

In this example, we present the same three-component diffusion problem introduced in examples/elphf/diffusion/mesh1D.py but we demonstrate FiPy’s facility to use dimensional quantities.

>>> import warnings
>>> warnings.warn("\n\n\tSupport for physical dimensions is incomplete.\n\tIt is not possible to solve dimensional equations.\n")
>>> from fipy import CellVariable, FaceVariable, PhysicalField, Grid1D, TransientTerm, DiffusionTerm, PowerLawConvectionTerm, LinearLUSolver, Viewer
>>> from fipy.tools import numerix

We solve the problem on a 40 mm long 1D mesh

>>> nx = 40
>>> dx = PhysicalField(1., "mm")
>>> L = nx * dx
>>> mesh = Grid1D(dx = dx, nx = nx)

Again, one component in this ternary system will be designated the “solvent”

>>> class ComponentVariable(CellVariable):
...     def __init__(self, mesh, value = 0., name = '',
...                  standardPotential = 0., barrier = 0.,
...                  diffusivity = None, valence = 0, equation = None):
...         CellVariable.__init__(self, mesh = mesh, value = value,
...                               name = name)
...         self.standardPotential = Variable(standardPotential)
...         self.barrier = Variable(barrier)
...         self.diffusivity = Variable(diffusivity)
...         self.valence = valence
...         self.equation = equation
...
...     def copy(self):
...         return self.__class__(mesh = self.mesh,
...                               value = self.value,
...                               name = self.name,
...                               standardPotential =
...                                   self.standardPotential,
...                               barrier = self.barrier,
...                               diffusivity = self.diffusivity,
...                               valence = self.valence,
...                               equation = self.equation)
>>> solvent = ComponentVariable(mesh = mesh, name = 'Cn', value = "1 mol/m**3")

We can create an arbitrary number of components, simply by providing a Tuple or list of components

>>> substitutionals = [
...     ComponentVariable(mesh = mesh, name = 'C1', diffusivity = "1e-9 m**2/s",
...                       standardPotential = 1., barrier = 1., value = "0.3 mol/m**3"),
...     ComponentVariable(mesh = mesh, name = 'C2', diffusivity = "1e-9 m**2/s",
...                       standardPotential = 1., barrier = 1., value = "0.6 mol/m**3"),
...     ]
>>> interstitials = []
>>> for component in substitutionals:
...     solvent -= component

We separate the solution domain into two different concentration regimes

>>> x = mesh.cellCenters[0]
>>> substitutionals[0].setValue("0.3 mol/m**3")
>>> substitutionals[0].setValue("0.6 mol/m**3", where=x > L / 2)
>>> substitutionals[1].setValue("0.6 mol/m**3")
>>> substitutionals[1].setValue("0.3 mol/m**3", where=x > L / 2)

We create one diffusion equation for each substitutional component

>>> for Cj in substitutionals:
...     CkSum = ComponentVariable(mesh = mesh, value = 0.)
...     CkFaceSum = FaceVariable(mesh = mesh, value = 0.)
...     for Ck in [Ck for Ck in substitutionals if Ck is not Cj]:
...         CkSum += Ck
...         CkFaceSum += Ck.harmonicFaceValue
...
...     convectionCoeff = CkSum.faceGrad \
...                       * (Cj.diffusivity / (1. - CkFaceSum))
...
...     Cj.equation = (TransientTerm()
...                    == DiffusionTerm(coeff=Cj.diffusivity)
...                    + PowerLawConvectionTerm(coeff = convectionCoeff))

If we are running interactively, we create a viewer to see the results

>>> if __name__ == '__main__':
...     viewer = Viewer(vars=[solvent] + substitutionals,
...                     datamin=0, datamax=1)
...     viewer.plot()

Now, we iterate the problem to equilibrium, plotting as we go

>>> solver = LinearLUSolver()
>>> from builtins import range
>>> for i in range(40):
...     for Cj in substitutionals:
...         Cj.updateOld()
...     for Cj in substitutionals:
...         Cj.equation.solve(var = Cj,
...                           dt = "1000 s",
...                           solver = solver)
...     if __name__ == '__main__':
...         viewer.plot()

Since there is nothing to maintain the concentration separation in this problem, we verify that the concentrations have become uniform

>>> print(substitutionals[0].scaled.allclose("0.45 mol/m**3",
...     atol = "1e-7 mol/m**3", rtol = 1e-7))
1
>>> print(substitutionals[1].scaled.allclose("0.45 mol/m**3",
...     atol = "1e-7 mol/m**3", rtol = 1e-7))
1

Note

The absolute tolerance atol must be in units compatible with the value to be checked, but the relative tolerance rtol is dimensionless.

Last updated on Jun 26, 2024. Created using Sphinx 7.1.2.