This page contains the surfactant Package documentation.
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.grid2D import Grid2D
>>> dx = .5
>>> dy = 2.3
>>> dt = 0.25
>>> k = 0.56
>>> initialValue = 0.1
>>> c = 0.2
>>> from fipy.meshes.grid2D 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.getInterfaceVar(),
... 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.grid2D import Grid2D
>>> dx = 0.5
>>> dy = 2.73
>>> dt = 0.001
>>> k0 = 1.
>>> k1 = 10.
>>> theta0 = 0.
>>> theta1 = 0.
>>> c0 = 1.
>>> c1 = 1.
>>> totalSteps = 100
>>> 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.getInterfaceVar(),
... numerix.array((0, 0, answer0, 0, 0)), rtol = 1e-2)
1
>>> print numerix.allclose(var1.getInterfaceVar(),
... 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.getCellCenters()
>>> check = var0.getInterfaceVar() + var1.getInterfaceVar()
>>> 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.getInterfaceVar())
>>> answer[x==1.25] = 0.
>>> print var0.getInterfaceVar().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.getCellCenters()
>>> 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.getInterfaceVar())
>>> from fipy.models.levelSet.advection.higherOrderAdvectionEquation \
... import buildHigherOrderAdvectionEquation
>>> advEq = buildHigherOrderAdvectionEquation(advectionCoeff = extVar)
>>> dt = 0.1
>>> for i in range(50):
... disVar.calcDistanceFunction()
... extVar.setValue(numerix.array(accVar.getInterfaceVar()))
... 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 : |
|
---|
Bases: fipy.viewers.matplotlibViewer.matplotlibViewer._MatplotlibViewer
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.getCellCenters()
>>> 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.getCellCenters()
>>> 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 : |
|
---|
Bases: fipy.viewers.viewer._Viewer
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.getCellCenters()
>>> 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 : |
|
---|
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 : |
|
---|
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.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.grid1D 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.grid2D 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 : |
|
---|
Returns the SurfactantVariable rendered as an _InterfaceSurfactantVariable which evaluates the surfactant concentration as an area concentration the interface rather than a volumetric concentration.