Bases: fipy.variables.cellVariable.CellVariable
A DistanceVariable object calculates
so it satisfies,

using the fast marching method with an initial condition defined by the zero level set.
Currently the solution is first order, This suffices for initial conditions with straight edges (e.g. trenches in electrodeposition). The method should work for unstructured 2D grids but testing on unstructured grids is untested thus far. This is a 2D implementation as it stands. Extending to 3D should be relatively simple.
Here we will define a few test cases. Firstly a 1D test case
>>> from fipy.meshes import Grid1D
>>> from fipy.tools import serial
>>> mesh = Grid1D(dx = .5, nx = 8, communicator=serial)
>>> from distanceVariable import DistanceVariable
>>> var = DistanceVariable(mesh = mesh, value = (-1, -1, -1, -1, 1, 1, 1, 1))
>>> var.calcDistanceFunction()
>>> answer = (-1.75, -1.25, -.75, -0.25, 0.25, 0.75, 1.25, 1.75)
>>> print var.allclose(answer)
1
A 1D test case with very small dimensions.
>>> dx = 1e-10
>>> mesh = Grid1D(dx = dx, nx = 8, communicator=serial)
>>> var = DistanceVariable(mesh = mesh, value = (-1, -1, -1, -1, 1, 1, 1, 1))
>>> var.calcDistanceFunction()
>>> answer = numerix.arange(8) * dx - 3.5 * dx
>>> print var.allclose(answer)
1
A 2D test case to test _calcTrialValue for a pathological case.
>>> dx = 1.
>>> dy = 2.
>>> from fipy.meshes import Grid2D
>>> mesh = Grid2D(dx = dx, dy = dy, nx = 2, ny = 3)
>>> var = DistanceVariable(mesh = mesh, value = (-1, 1, 1, 1, -1, 1))
>>> var.calcDistanceFunction()
>>> vbl = -dx * dy / numerix.sqrt(dx**2 + dy**2) / 2.
>>> vbr = dx / 2
>>> vml = dy / 2.
>>> crossProd = dx * dy
>>> dsq = dx**2 + dy**2
>>> top = vbr * dx**2 + vml * dy**2
>>> sqrt = crossProd**2 *(dsq - (vbr - vml)**2)
>>> sqrt = numerix.sqrt(max(sqrt, 0))
>>> vmr = (top + sqrt) / dsq
>>> answer = (vbl, vbr, vml, vmr, vbl, vbr)
>>> print var.allclose(answer)
1
The extendVariable method solves the following equation for a given extensionVariable.

using the fast marching method with an initial condition defined at the zero level set. Essentially the equation solves a fake distance function to march out the velocity from the interface.
>>> from fipy.variables.cellVariable import CellVariable
>>> mesh = Grid2D(dx = 1., dy = 1., nx = 2, ny = 2)
>>> var = DistanceVariable(mesh = mesh, value = (-1, 1, 1, 1))
>>> var.calcDistanceFunction()
>>> extensionVar = CellVariable(mesh = mesh, value = (-1, .5, 2, -1))
>>> tmp = 1 / numerix.sqrt(2)
>>> print var.allclose((-tmp / 2, 0.5, 0.5, 0.5 + tmp))
1
>>> var.extendVariable(extensionVar)
>>> print extensionVar.allclose((1.25, .5, 2, 1.25))
1
>>> mesh = Grid2D(dx = 1., dy = 1., nx = 3, ny = 3)
>>> var = DistanceVariable(mesh = mesh, value = (-1, 1, 1,
... 1, 1, 1,
... 1, 1, 1))
>>> var.calcDistanceFunction()
>>> extensionVar = CellVariable(mesh = mesh, value = (-1, .5, -1,
... 2, -1, -1,
... -1, -1, -1))
>>> v1 = 0.5 + tmp
>>> v2 = 1.5
>>> tmp1 = (v1 + v2) / 2 + numerix.sqrt(2. - (v1 - v2)**2) / 2
>>> tmp2 = tmp1 + 1 / numerix.sqrt(2)
>>> print var.allclose((-tmp / 2, 0.5, 1.5, 0.5, 0.5 + tmp,
... tmp1, 1.5, tmp1, tmp2))
1
>>> answer = (1.25, .5, .5, 2, 1.25, 0.9544, 2, 1.5456, 1.25)
>>> var.extendVariable(extensionVar)
>>> print extensionVar.allclose(answer, rtol = 1e-4)
1
Test case for a bug that occurs when initializing the distance variable at the interface. Currently it is assumed that adjacent cells that are opposite sign neighbors have perpendicular normal vectors. In fact the two closest cells could have opposite normals.
>>> mesh = Grid1D(dx = 1., nx = 3)
>>> var = DistanceVariable(mesh = mesh, value = (-1, 1, -1))
>>> var.calcDistanceFunction()
>>> print var.allclose((-0.5, 0.5, -0.5))
1
For future reference, the minimum distance for the interface cells can be calculated with the following functions. The trial cell values will also be calculated with these functions. In essence it is not difficult to calculate the level set distance function on an unstructured 3D grid. However a lot of testing will be required. The minimum distance functions will take the following form.

and in 3D,

where the vectors
,
and
represent the
vectors from the cell of interest to the neighboring cell.
Creates a distanceVariable object.
| Parameters : |
|
|---|
Calculates the distanceVariable as a distance function.
| Parameters : |
|
|---|
Returns the length of the interface that crosses the cell
A simple 1D test:
>>> from fipy.meshes import Grid1D
>>> mesh = Grid1D(dx = 1., nx = 4)
>>> distanceVariable = DistanceVariable(mesh = mesh,
... value = (-1.5, -0.5, 0.5, 1.5))
>>> answer = CellVariable(mesh=mesh, value=(0, 0., 1., 0))
>>> print numerix.allclose(distanceVariable.cellInterfaceAreas,
... answer)
True
A 2D test case:
>>> from fipy.meshes import Grid2D
>>> from fipy.variables.cellVariable import CellVariable
>>> mesh = Grid2D(dx = 1., dy = 1., nx = 3, ny = 3)
>>> distanceVariable = DistanceVariable(mesh = mesh,
... value = (1.5, 0.5, 1.5,
... 0.5,-0.5, 0.5,
... 1.5, 0.5, 1.5))
>>> answer = CellVariable(mesh=mesh,
... value=(0, 1, 0, 1, 0, 1, 0, 1, 0))
>>> print numerix.allclose(distanceVariable.cellInterfaceAreas, answer)
True
Another 2D test case:
>>> mesh = Grid2D(dx = .5, dy = .5, nx = 2, ny = 2)
>>> from fipy.variables.cellVariable import CellVariable
>>> distanceVariable = DistanceVariable(mesh = mesh,
... value = (-0.5, 0.5, 0.5, 1.5))
>>> answer = CellVariable(mesh=mesh,
... value=(0, numerix.sqrt(2) / 4, numerix.sqrt(2) / 4, 0))
>>> print numerix.allclose(distanceVariable.cellInterfaceAreas,
... answer)
True
Test to check that the circumfrence of a circle is, in fact,
.
>>> mesh = Grid2D(dx = 0.05, dy = 0.05, nx = 20, ny = 20)
>>> r = 0.25
>>> x, y = mesh.cellCenters
>>> rad = numerix.sqrt((x - .5)**2 + (y - .5)**2) - r
>>> distanceVariable = DistanceVariable(mesh = mesh, value = rad)
>>> print numerix.allclose(distanceVariable.cellInterfaceAreas.sum(), 1.57984690073)
1
Takes a cellVariable and extends the variable from the zero to the region encapuslated by the narrowBandWidth.
| Parameters : |
|
|---|
Deprecated since version 3.0: use the cellInterfaceAreas property instead
Bases: fipy.variables.cellVariable.CellVariable
The SurfactantVariable maintains a conserved volumetric concentration on cells adjacent to, but in front of, the interface. The value argument corresponds to the initial concentration of surfactant on the interface (moles divided by area). The value held by the SurfactantVariable is actually a volume density (moles divided by volume).
A simple 1D test:
>>> from fipy.meshes import Grid1D
>>> mesh = Grid1D(dx = 1., nx = 4)
>>> from fipy.models.levelSet.distanceFunction.distanceVariable import DistanceVariable
>>> distanceVariable = DistanceVariable(mesh = mesh,
... value = (-1.5, -0.5, 0.5, 941.5))
>>> surfactantVariable = SurfactantVariable(value = 1,
... distanceVar = distanceVariable)
>>> print numerix.allclose(surfactantVariable, (0, 0., 1., 0))
1
A 2D test case:
>>> from fipy.meshes import Grid2D
>>> mesh = Grid2D(dx = 1., dy = 1., nx = 3, ny = 3)
>>> distanceVariable = DistanceVariable(mesh = mesh,
... value = (1.5, 0.5, 1.5,
... 0.5,-0.5, 0.5,
... 1.5, 0.5, 1.5))
>>> surfactantVariable = SurfactantVariable(value = 1,
... distanceVar = distanceVariable)
>>> print numerix.allclose(surfactantVariable, (0, 1, 0, 1, 0, 1, 0, 1, 0))
1
Another 2D test case:
>>> mesh = Grid2D(dx = .5, dy = .5, nx = 2, ny = 2)
>>> distanceVariable = DistanceVariable(mesh = mesh,
... value = (-0.5, 0.5, 0.5, 1.5))
>>> surfactantVariable = SurfactantVariable(value = 1,
... distanceVar = distanceVariable)
>>> print numerix.allclose(surfactantVariable,
... (0, numerix.sqrt(2), numerix.sqrt(2), 0))
1
| Parameters : |
|
|---|
Deprecated since version 3.0: use the interfaceVar property instead
Returns the SurfactantVariable rendered as an _InterfaceSurfactantVariable which evaluates the surfactant concentration as an area concentration the interface rather than a volumetric concentration.
A SurfactantEquation aims to evolve a surfactant on an interface defined by the zero level set of the distanceVar. The method should completely conserve the total coverage of surfactant. The surfactant is only in the cells immediately in front of the advancing interface. The method only works for a positive velocity as it stands.
Creates a SurfactantEquation object.
| Parameters : |
|
|---|
Builds and solves the SurfactantEquation‘s linear system once.
| Parameters : |
|
|---|
Builds and solves the Term‘s linear system once. This method also recalculates and returns the residual as well as applying under-relaxation.
| Parameters : |
|
|---|
Bases: fipy.models.levelSet.surfactant.surfactantEquation.SurfactantEquation
The AdsorbingSurfactantEquation object solves the SurfactantEquation but with an adsorbing species from some bulk value. The equation that describes the surfactant adsorbing is given by,

where
,
,
,
,
,
and
represent the surfactant coverage, the curvature,
the interface normal velocity, the adsorption rate, the concentration in the
bulk at the interface, the consumption rate and an exponent of consumption,
respectively. The
subscript refers to another
surfactant with greater surface affinity.
The terms on the RHS of the above equation represent conservation of
surfactant on a non-uniform surface, Langmuir adsorption, removal of
surfactant due to adsorption of the other surfactant onto non-vacant sites
and consumption of the surfactant respectively. The adsorption term is added
to the source by setting :math:` S_c = k c (1 - theta_{text{other}})` and
. The other terms are added to the source in a similar
way.
The following is a test case:
>>> from fipy.models.levelSet.distanceFunction.distanceVariable \
... import DistanceVariable
>>> from fipy.models.levelSet.surfactant.surfactantVariable \
... import SurfactantVariable
>>> from fipy.meshes import Grid2D
>>> dx = .5
>>> dy = 2.3
>>> dt = 0.25
>>> k = 0.56
>>> initialValue = 0.1
>>> c = 0.2
>>> from fipy.meshes import Grid2D
>>> mesh = Grid2D(dx = dx, dy = dy, nx = 5, ny = 1)
>>> distanceVar = DistanceVariable(mesh = mesh,
... value = (-dx*3/2, -dx/2, dx/2,
... 3*dx/2, 5*dx/2),
... hasOld = 1)
>>> surfactantVar = SurfactantVariable(value = (0, 0, initialValue, 0 ,0),
... distanceVar = distanceVar)
>>> bulkVar = CellVariable(mesh = mesh, value = (c , c, c, c, c))
>>> eqn = AdsorbingSurfactantEquation(surfactantVar = surfactantVar,
... distanceVar = distanceVar,
... bulkVar = bulkVar,
... rateConstant = k)
>>> eqn.solve(surfactantVar, dt = dt)
>>> answer = (initialValue + dt * k * c) / (1 + dt * k * c)
>>> print numerix.allclose(surfactantVar.interfaceVar,
... numerix.array((0, 0, answer, 0, 0)))
1
The following test case is for two surfactant variables. One has more surface affinity than the other.
>>> from fipy.models.levelSet.distanceFunction.distanceVariable \
... import DistanceVariable
>>> from fipy.models.levelSet.surfactant.surfactantVariable \
... import SurfactantVariable
>>> from fipy.meshes import Grid2D
>>> dx = 0.5
>>> dy = 2.73
>>> dt = 0.001
>>> k0 = 1.
>>> k1 = 10.
>>> theta0 = 0.
>>> theta1 = 0.
>>> c0 = 1.
>>> c1 = 1.
>>> totalSteps = 10
>>> mesh = Grid2D(dx = dx, dy = dy, nx = 5, ny = 1)
>>> distanceVar = DistanceVariable(mesh = mesh,
... value = dx * (numerix.arange(5) - 1.5),
... hasOld = 1)
>>> var0 = SurfactantVariable(value = (0, 0, theta0, 0 ,0),
... distanceVar = distanceVar)
>>> var1 = SurfactantVariable(value = (0, 0, theta1, 0 ,0),
... distanceVar = distanceVar)
>>> bulkVar0 = CellVariable(mesh = mesh, value = (c0, c0, c0, c0, c0))
>>> bulkVar1 = CellVariable(mesh = mesh, value = (c1, c1, c1, c1, c1))
>>> eqn0 = AdsorbingSurfactantEquation(surfactantVar = var0,
... distanceVar = distanceVar,
... bulkVar = bulkVar0,
... rateConstant = k0)
>>> eqn1 = AdsorbingSurfactantEquation(surfactantVar = var1,
... distanceVar = distanceVar,
... bulkVar = bulkVar1,
... rateConstant = k1,
... otherVar = var0,
... otherBulkVar = bulkVar0,
... otherRateConstant = k0)
>>> for step in range(totalSteps):
... eqn0.solve(var0, dt = dt)
... eqn1.solve(var1, dt = dt)
>>> answer0 = 1 - numerix.exp(-k0 * c0 * dt * totalSteps)
>>> answer1 = (1 - numerix.exp(-k1 * c1 * dt * totalSteps)) * (1 - answer0)
>>> print numerix.allclose(var0.interfaceVar,
... numerix.array((0, 0, answer0, 0, 0)), rtol = 1e-2)
1
>>> print numerix.allclose(var1.interfaceVar,
... numerix.array((0, 0, answer1, 0, 0)), rtol = 1e-2)
1
>>> dt = 0.1
>>> for step in range(10):
... eqn0.solve(var0, dt = dt)
... eqn1.solve(var1, dt = dt)
>>> x, y = mesh.cellCenters
>>> check = var0.interfaceVar + var1.interfaceVar
>>> answer = CellVariable(mesh=mesh, value=check)
>>> answer[x==1.25] = 1.
>>> print check.allequal(answer)
True
The following test case is to fix a bug where setting the adosrbtion coefficient to zero leads to the solver not converging and an eventual failure.
>>> var0 = SurfactantVariable(value = (0, 0, theta0, 0 ,0),
... distanceVar = distanceVar)
>>> bulkVar0 = CellVariable(mesh = mesh, value = (c0, c0, c0, c0, c0))
>>> eqn0 = AdsorbingSurfactantEquation(surfactantVar = var0,
... distanceVar = distanceVar,
... bulkVar = bulkVar0,
... rateConstant = 0)
>>> eqn0.solve(var0, dt = dt)
>>> eqn0.solve(var0, dt = dt)
>>> answer = CellVariable(mesh=mesh, value=var0.interfaceVar)
>>> answer[x==1.25] = 0.
>>> print var0.interfaceVar.allclose(answer)
True
The following test case is to fix a bug that allows the accelerator to become negative.
>>> nx = 5
>>> ny = 5
>>> dx = 1.
>>> dy = 1.
>>> mesh = Grid2D(dx=dx, dy=dy, nx = nx, ny = ny)
>>> x, y = mesh.cellCenters
>>> disVar = DistanceVariable(mesh=mesh, value=1., hasOld=True)
>>> disVar[y < dy] = -1
>>> disVar[x < dx] = -1
>>> disVar.calcDistanceFunction()
>>> levVar = SurfactantVariable(value = 0.5, distanceVar = disVar)
>>> accVar = SurfactantVariable(value = 0.5, distanceVar = disVar)
>>> levEq = AdsorbingSurfactantEquation(levVar,
... distanceVar = disVar,
... bulkVar = 0,
... rateConstant = 0)
>>> accEq = AdsorbingSurfactantEquation(accVar,
... distanceVar = disVar,
... bulkVar = 0,
... rateConstant = 0,
... otherVar = levVar,
... otherBulkVar = 0,
... otherRateConstant = 0)
>>> extVar = CellVariable(mesh = mesh, value = accVar.interfaceVar)
>>> from fipy.models.levelSet.advection.higherOrderAdvectionEquation \
... import buildHigherOrderAdvectionEquation
>>> advEq = buildHigherOrderAdvectionEquation(advectionCoeff = extVar)
>>> dt = 0.1
>>> for i in range(50):
... disVar.calcDistanceFunction()
... extVar.value = (numerix.array(accVar.interfaceVar))
... disVar.extendVariable(extVar)
... disVar.updateOld()
... advEq.solve(disVar, dt = dt)
... levEq.solve(levVar, dt = dt)
... accEq.solve(accVar, dt = dt)
>>> print (accVar >= -1e-10).all()
True
Create a AdsorbingSurfactantEquation object.
| Parameters : |
|
|---|
Builds and solves the AdsorbingSurfactantEquation‘s linear system once.
| Parameters : |
|
|---|
Builds and solves the AdsorbingSurfactantEquation‘s linear system once. This method also recalculates and returns the residual as well as applying under-relaxation.
| Parameters : |
|
|---|
The buildSurfactantBulkDiffusionEquation function returns a bulk diffusion of a species with a source term for the jump from the bulk to an interface. The governing equation is given by,

where,

The jump condition at the interface is defined by Langmuir adsorption. Langmuir adsorption essentially states that the ability for a species to jump from an electrolyte to an interface is proportional to the concentration in the electrolyte, available site density and a jump coefficient. The boundary condition at the interface is given by

| Parameters : |
|
|---|
Bases: fipy.viewers.viewer.AbstractViewer
The MayaviSurfactantViewer creates a viewer with the Mayavi python plotting package that displays a DistanceVariable.
Create a MayaviSurfactantViewer.
>>> from fipy import *
>>> dx = 1.
>>> dy = 1.
>>> nx = 11
>>> ny = 11
>>> Lx = ny * dy
>>> Ly = nx * dx
>>> mesh = Grid2D(dx = dx, dy = dy, nx = nx, ny = ny)
>>> # from fipy.models.levelSet.distanceFunction.distanceVariable import DistanceVariable
>>> var = DistanceVariable(mesh = mesh, value = -1)
>>> x, y = mesh.cellCenters
>>> var.setValue(1, where=(x - Lx / 2.)**2 + (y - Ly / 2.)**2 < (Lx / 4.)**2)
>>> var.calcDistanceFunction()
>>> viewer = MayaviSurfactantViewer(var, smooth = 2)
>>> viewer.plot()
>>> viewer._promptForOpinion()
>>> del viewer
>>> var = DistanceVariable(mesh = mesh, value = -1)
>>> var.setValue(1, where=(y > 2. * Ly / 3.) | ((x > Lx / 2.) & (y > Ly / 3.)) | ((y < Ly / 6.) & (x > Lx / 2)))
>>> var.calcDistanceFunction()
>>> viewer = MayaviSurfactantViewer(var)
>>> viewer.plot()
>>> viewer._promptForOpinion()
>>> del viewer
>>> viewer = MayaviSurfactantViewer(var, smooth = 2)
>>> viewer.plot()
>>> viewer._promptForOpinion()
>>> del viewer
| Parameters : |
|
|---|
Bases: fipy.viewers.matplotlibViewer.matplotlibViewer.AbstractMatplotlibViewer
The MatplotlibSurfactantViewer creates a viewer with the Matplotlib python plotting package that displays a DistanceVariable.
Create a MatplotlibSurfactantViewer.
>>> from fipy import *
>>> m = Grid2D(nx=100, ny=100)
>>> x, y = m.cellCenters
>>> v = CellVariable(mesh=m, value=x**2 + y**2 - 10**2)
>>> s = CellVariable(mesh=m, value=sin(x / 10) * cos(y / 30))
>>> viewer = MatplotlibSurfactantViewer(distanceVar=v, surfactantVar=s)
>>> for r in range(1,200):
... v.setValue(x**2 + y**2 - r**2)
... viewer.plot()
>>> from fipy import *
>>> dx = 1.
>>> dy = 1.
>>> nx = 11
>>> ny = 11
>>> Lx = ny * dy
>>> Ly = nx * dx
>>> mesh = Grid2D(dx = dx, dy = dy, nx = nx, ny = ny)
>>> # from fipy.models.levelSet.distanceFunction.distanceVariable import DistanceVariable
>>> var = DistanceVariable(mesh = mesh, value = -1)
>>> x, y = mesh.cellCenters
>>> var.setValue(1, where=(x - Lx / 2.)**2 + (y - Ly / 2.)**2 < (Lx / 4.)**2)
>>> var.calcDistanceFunction()
>>> viewer = MatplotlibSurfactantViewer(var, smooth = 2)
>>> viewer.plot()
>>> viewer._promptForOpinion()
>>> del viewer
>>> var = DistanceVariable(mesh = mesh, value = -1)
>>> var.setValue(1, where=(y > 2. * Ly / 3.) | ((x > Lx / 2.) & (y > Ly / 3.)) | ((y < Ly / 6.) & (x > Lx / 2)))
>>> var.calcDistanceFunction()
>>> viewer = MatplotlibSurfactantViewer(var)
>>> viewer.plot()
>>> viewer._promptForOpinion()
>>> del viewer
>>> viewer = MatplotlibSurfactantViewer(var, smooth = 2)
>>> viewer.plot()
>>> viewer._promptForOpinion()
>>> del viewer
| Parameters : |
|
|---|
The buildAdvectionEquation function constructs and returns an advection equation. The advection equation is given by:

This solution method for the _AdvectionTerm is set up specifically to evolve var while preserving var as a distance function. This equation is used in conjunction with the DistanceFunction object. Further details of the numerical method can be found in “Level Set Methods and Fast Marching Methods” by J.A. Sethian, Cambridge University Press, 1999. Testing for the advection equation is in examples.levelSet.advection
| Parameters : |
|
|---|
The buildHigherOrderAdvectionEquation function returns an advection equation that uses the _HigherOrderAdvectionTerm. The advection equation is given by,

| Parameters : |
|
|---|
The MetalIonDiffusionEquation solves the diffusion of the metal species with a source term at the electrolyte interface. The governing equation is given by,

where,

The velocity of the interface generally has a linear dependence on ion concentration. The following boundary condition applies at the zero level set,

where

The test case below is for a 1D steady state problem. The solution is given by:

This is the test case,
>>> from fipy.meshes import Grid1D
>>> nx = 11
>>> dx = 1.
>>> from fipy.tools import serial
>>> mesh = Grid1D(nx = nx, dx = dx, communicator=serial)
>>> x, = mesh.cellCenters
>>> from fipy.variables.cellVariable import CellVariable
>>> ionVar = CellVariable(mesh = mesh, value = 1.)
>>> from fipy.models.levelSet.distanceFunction.distanceVariable \
... import DistanceVariable
>>> disVar = DistanceVariable(mesh = mesh,
... value = (x - 0.5) - 0.99,
... hasOld = 1)
>>> v = 1.
>>> diffusion = 1.
>>> omega = 1.
>>> cinf = 1.
>>> eqn = buildMetalIonDiffusionEquation(ionVar = ionVar,
... distanceVar = disVar,
... depositionRate = v * ionVar,
... diffusionCoeff = diffusion,
... metalIonMolarVolume = omega)
>>> ionVar.constrain(cinf, mesh.facesRight)
>>> for i in range(10):
... eqn.solve(ionVar, dt = 1000)
>>> L = (nx - 1) * dx - dx / 2
>>> gradient = cinf / (omega * diffusion / v + L)
>>> answer = gradient * (x - L - dx * 3 / 2) + cinf
>>> answer[x < dx] = 1
>>> print ionVar.allclose(answer)
1
| Parameters : |
|
|---|
Bases: fipy.models.levelSet.electroChem.gapFillMesh.GapFillMesh
The trench mesh takes the parameters generally used to define a trench region and recasts then for the general GapFillMesh.
The following test case tests for diffusion across the domain.
>>> cellSize = 0.05e-6
>>> trenchDepth = 0.5e-6
>>> boundaryLayerDepth = 50e-6
>>> domainHeight = 10 * cellSize + trenchDepth + boundaryLayerDepth
>>> mesh = TrenchMesh(trenchSpacing = 1e-6,
... cellSize = cellSize,
... trenchDepth = trenchDepth,
... boundaryLayerDepth = boundaryLayerDepth,
... aspectRatio = 1.)
>>> import fipy.tools.dump as dump
>>> (f, filename) = dump.write(mesh)
>>> mesh = dump.read(filename, f)
>>> mesh.numberOfCells - len(numerix.nonzero(mesh.electrolyteMask)[0])
150
>>> from fipy.variables.cellVariable import CellVariable
>>> var = CellVariable(mesh = mesh, value = 0.)
>>> from fipy.terms.diffusionTerm import DiffusionTerm
>>> eq = DiffusionTerm()
>>> var.constrain(0., mesh.facesBottom)
>>> var.constrain(domainHeight, mesh.facesTop)
>>> eq.solve(var)
Evaluate the result:
>>> centers = mesh.cellCenters[1].copy()
Note
the copy makes the array contiguous for inlining
>>> localErrors = (centers - var)**2 / centers**2
>>> globalError = numerix.sqrt(numerix.sum(localErrors) / mesh.numberOfCells)
>>> argmax = numerix.argmax(localErrors)
>>> print numerix.sqrt(localErrors[argmax]) < 0.051
1
>>> print globalError < 0.02
1
trenchDepth - Depth of the trench.
trenchSpacing - The distance between the trenches.
boundaryLayerDepth - The depth of the hydrodynamic boundary layer.
cellSize - The cell Size.
aspectRatio - trenchDepth / trenchWidth
angle - The angle for the taper of the trench.
bowWidth - The maximum displacement for any bow in the trench shape.
overBumpWidth - The width of the over bump.
overBumpRadius - The radius of the over bump.
Deprecated since version 3.0: use the electrolyteMask property instead