Exemple #1
0
    def _setup_equation(self, biomass_height):
        height = biomass_height + self._layer_height
        size = height * self._layer
        mesh = self.space.construct_mesh(height)
        variables, terms = [], []
        phi = CellVariable(name=self.solute.name, mesh=mesh, hasOld=True)
        for r in self.reactions:
            variables.append(
                CellVariable(name=f"{r.bacteria.name}_rate",
                             mesh=mesh,
                             value=0.0))
            terms.append(
                ImplicitSourceTerm(coeff=(variables[-1] / (phi + self._sr))))
        equation = DiffusionTerm(coeff=self.diffusivity) - sum(terms)
        phi.constrain(1, where=mesh.facesTop)

        for var, coef in zip(
                variables,
            [r.rate_coefficient()[:size] for r in self.reactions]):
            try:
                var.setValue(coef / self.space.dV)
            except ValueError as err:
                print("Boundary layer height greater than system size")
                raise err
        phi.setValue(self.solute.value.reshape(-1)[:size])
        return equation, phi, size
Exemple #2
0
    def setup(self, ncell):
        m = Grid1D(nx=ncell, Lx=1.)


        v = CellVariable(mesh=m, hasOld=True, value=[[0.5], [0.5]], elementshape=(2,))

        v.constrain([[0], [1]], m.facesLeft)
        v.constrain([[1], [0]], m.facesRight)

        eqn = TransientTerm([[1,0], [0,1]]) == DiffusionTerm([[[0.01, -1], [1, 0.01]]])

        self.v = v
        self.eqn = eqn
        for step in range(2):
            self.time_step()
Exemple #3
0
def solve_pde(
        xmin,  # domain min
        xmax,  # domain max
        Tmax,  # time max
        theta=1,  # dynamics drift
        mu=0,  # dynamics stable level
        sigma=1,  # dynamics noise
        dx=0.01,  # space discretization
        dt=0.01,  # time discretization
        gbm=False):  # state-dependent drift

    mesh = Grid1D(dx=dx, nx=(xmax - xmin) / dx) + xmin
    Tsteps = int(Tmax / dt) + 1

    x_face = mesh.faceCenters
    x_cell = mesh.cellCenters[0]
    V = CellVariable(name="V", mesh=mesh, value=0.)

    # PDE
    if gbm:
        eq = TransientTerm(
            var=V) == (DiffusionTerm(coeff=float(sigma) * sigma / 2, var=V) -
                       UpwindConvectionTerm(
                           coeff=float(theta) * (x_face - float(mu)), var=V) +
                       V * (float(theta) - x_cell))
    else:
        eq = TransientTerm(
            var=V) == (DiffusionTerm(coeff=float(sigma) * sigma / 2, var=V) -
                       UpwindConvectionTerm(coeff=float(theta) *
                                            (x_face - float(mu)),
                                            var=V) + V * float(theta))

    # Boundary conditions
    V.constrain(1., mesh.facesRight)
    V.faceGrad.constrain([0.], mesh.facesLeft)

    # Solve by stepping in time
    sol = np.zeros((Tsteps, mesh.nx))
    for step in range(Tsteps):
        eq.solve(var=V, dt=dt)
        sol[step] = V.value

    X = mesh.cellCenters.value[0]
    T = dt * np.arange(Tsteps)
    return T, X, sol
Exemple #4
0
potential = CellVariable(mesh=mesh, name='Potential', value=y03(mesh.x))
Jp = CellVariable(mesh=mesh, name='Positive ion Current Density', value=0.)
Jn = CellVariable(mesh=mesh, name='Negative ion Current Density', value=0.)

Jp.value = -mu_p * Pion * potential.arithmeticFaceValue.divergence + Dn * Pion.arithmeticFaceValue.divergence
Jn.value = -mu_n * Nion * potential.arithmeticFaceValue.divergence + Dn * Pion.arithmeticFaceValue.divergence

Pion.equation = TransientTerm(
    coeff=1,
    var=Pion) == -k_rec * Pion * Nion + (Jp.arithmeticFaceValue).divergence
Nion.equation = TransientTerm(
    coeff=1,
    var=Nion) == -k_rec * Pion * Nion - (Jn.arithmeticFaceValue).divergence
potential.equation = DiffusionTerm(coeff=epsilon, var=potential) == Pion - Nion

Pion.constrain(0., where=mesh.facesLeft)
Pion.constrain(0., where=mesh.facesRight)
Nion.constrain(0., where=mesh.facesLeft)
Nion.constrain(0., where=mesh.facesRight)
potential.constrain(0., where=mesh.facesLeft)
potential.constrain(0., where=mesh.facesRight)

eq = Pion.equation & Nion.equation & potential.equation

steps = 253
dt = 6

if __name__ == "__main__":
    viewer = Viewer(vars=(Nion, ), datamin=-1e15, datamax=1e15)

for steps in range(steps):
Exemple #5
0
Plane Surface(3) = {3};

Physical Line("Ground") = {4, 5, 6};
Physical Surface("Field") = {1};
Physical Surface("Anode") = {2};
Physical Surface("Cathode") = {3};
"""
for refinement in range(10):
    mesh = Gmsh2D(geo, background=monitor)

    charge = CellVariable(mesh=mesh, name=r"$\rho$", value=0.)
    charge.setValue(+1, where=mesh.physicalCells["Anode"])
    charge.setValue(-1, where=mesh.physicalCells["Cathode"])

    potential = CellVariable(mesh=mesh, name=r"$\psi$")
    potential.constrain(0., where=mesh.physicalFaces["Ground"])

    eq = DiffusionTerm(coeff=1.) == -charge

    res0 = eq.sweep(var=potential)

    res = eq.justResidualVector(var=potential)

    res1 = numerix.L2norm(res)
    res1a = CellVariable(mesh=mesh, value=abs(res))

    res = CellVariable(mesh=mesh, name="residual", value=abs(res) / mesh.cellVolumes**(1./mesh.dim) / 1e-3)

    # want cells no bigger than 1 and no smaller than 0.001
    maxSize = 1.
    minSize = 0.001
potential.equation = DiffusionTerm(
    coeff=1, var=potential) == (-q / epsilon) * (Pion + Nion)

################################################################
##################''' BOUNDARY CONDITIONS '''###################
################################################################

Pion.faceGrad.constrain(
    0.,
    where=mesh.exteriorFaces)  #dPion/dx = 0 at the exterior faces of the mesh
Nion.faceGrad.constrain(
    0.,
    where=mesh.exteriorFaces)  #dNion/dx = 0 at the exterior faces of the mesh
potential.constrain(
    0.,
    where=mesh.exteriorFaces)  #potential = 0 at the exterior faces of the mesh

################################################################
#################''' SOLVE EQUATIONS '''########################
################################################################

eq = Pion.equation & Nion.equation & potential.equation  #Couple all of the equations together

steps = 100  #How many time steps to take
dt = 1  #How long each time step is in seconds

if __name__ == "__main__":
    #viewer = Viewer(vars=(potential,),datamin=-1.1,datamax=1.1)  #Sets up viewer for the potential with y-axis limits
    viewer = Viewer(
        vars=(Pion, ), datamin=0, datamax=1e21
Exemple #7
0
mesh = Grid3D(dx=dx, dy=dy, dz=dz, nx=nx, ny=ny, nz=nz)

var = CellVariable(name="variable", mesh=mesh, value=valueSides)

##viewer1 = Grid3DPyxViewer(var, zvalue = 1.0)
##viewer3 = Grid3DPyxViewer(var, zvalue = 3.0)
##viewer5 = Grid3DPyxViewer(var, zvalue = 5.0)
##viewer7 = Grid3DPyxViewer(var, zvalue = 7.0)
##viewer9 = Grid3DPyxViewer(var, zvalue = 9.0)

## viewer = Viewer(vars = var)

## viewer.plot()

var.constrain(valueSides, mesh.facesLeft)
var.constrain(valueSides, mesh.facesRight)
var.constrain(valueSides, mesh.facesTop)
var.constrain(valueSides, mesh.facesBottom)
var.constrain(valueFront, mesh.facesFront)
var.constrain(valueBack, mesh.facesBack)

## viewer.plot()

if __name__ == '__main__':
    ##viewer1.plot(resolution = 0.2, xlabel = "X values (Z value = 1)", minval = valueFront, maxval = valueBack)
    ##raw_input("press enter to continue")
    ##viewer3.plot(resolution = 0.2, xlabel = "X values (Z value = 3)", minval = valueFront, maxval = valueBack)
    ##raw_input("press enter to continue")
    ##viewer5.plot(resolution = 0.2, xlabel = "X values (Z value = 5)", minval = valueFront, maxval = valueBack)
    ##raw_input("press enter to continue")
Exemple #8
0
distanceVar = DistanceVariable(mesh = mesh, value = value, hasOld = 1)

## Build the bulk diffusion equation

bulkVar = CellVariable(mesh = mesh, value = cinf)

surfactantVar = SurfactantVariable(distanceVar = distanceVar)

from .surfactantBulkDiffusionEquation import buildSurfactantBulkDiffusionEquation
bulkEqn = buildSurfactantBulkDiffusionEquation(bulkVar,
                                          distanceVar = distanceVar,
                                          surfactantVar = surfactantVar,
                                          diffusionCoeff = diffusion,
                                          rateConstant = rateConstant * siteDensity)

bulkVar.constrain(cinf, mesh.facesRight)

## Build the surfactant equation

surfEqn = AdsorbingSurfactantEquation(surfactantVar = surfactantVar,
                                      distanceVar = distanceVar,
                                      bulkVar = bulkVar,
                                      rateConstant = rateConstant)

## Build the analytical solutions,

x = mesh.cellCenters[0, 1:] - dx

def concentrationFunc(theta):
    tmp = (1 + rateConstant * siteDensity * (1 - theta) * L / diffusion)
    return cinf * (1 + rateConstant * siteDensity * (1 - theta) * x / diffusion) / tmp
Exemple #9
0
def runSimpleTrenchSystem(faradaysConstant=9.6e4,
                          gasConstant=8.314,
                          transferCoefficient=0.5,
                          rateConstant0=1.76,
                          rateConstant3=-245e-6,
                          catalystDiffusion=1e-9,
                          siteDensity=9.8e-6,
                          molarVolume=7.1e-6,
                          charge=2,
                          metalDiffusion=5.6e-10,
                          temperature=298.,
                          overpotential=-0.3,
                          metalConcentration=250.,
                          catalystConcentration=5e-3,
                          catalystCoverage=0.,
                          currentDensity0=0.26,
                          currentDensity1=45.,
                          cellSize=0.1e-7,
                          trenchDepth=0.5e-6,
                          aspectRatio=2.,
                          trenchSpacing=0.6e-6,
                          boundaryLayerDepth=0.3e-6,
                          numberOfSteps=5,
                          displayViewers=True):

    cflNumber = 0.2
    numberOfCellsInNarrowBand = 10
    cellsBelowTrench = 10

    yCells = cellsBelowTrench \
             + int((trenchDepth + boundaryLayerDepth) / cellSize)

    xCells = int(trenchSpacing / 2 / cellSize)

    from fipy.tools import serialComm
    mesh = Grid2D(dx = cellSize,
                  dy = cellSize,
                  nx = xCells,
                  ny = yCells,
                  communicator=serialComm)

    narrowBandWidth = numberOfCellsInNarrowBand * cellSize

    distanceVar = DistanceVariable(
        name = 'distance variable',
        mesh = mesh,
        value = -1.,
        hasOld = 1)

    bottomHeight = cellsBelowTrench * cellSize
    trenchHeight = bottomHeight + trenchDepth
    trenchWidth = trenchDepth / aspectRatio
    sideWidth = (trenchSpacing - trenchWidth) / 2

    x, y = mesh.cellCenters
    distanceVar.setValue(1., where=(y > trenchHeight) | ((y > bottomHeight) & (x < xCells * cellSize - sideWidth)))

    distanceVar.calcDistanceFunction(order=2)

    catalystVar = SurfactantVariable(
        name = "catalyst variable",
        value = catalystCoverage,
        distanceVar = distanceVar)

    bulkCatalystVar = CellVariable(
        name = 'bulk catalyst variable',
        mesh = mesh,
        value = catalystConcentration)

    metalVar = CellVariable(
        name = 'metal variable',
        mesh = mesh,
        value = metalConcentration)

    expoConstant = -transferCoefficient * faradaysConstant / (gasConstant * temperature)

    tmp = currentDensity1 * catalystVar.interfaceVar

    exchangeCurrentDensity = currentDensity0 + tmp

    expo = numerix.exp(expoConstant * overpotential)
    currentDensity = expo * exchangeCurrentDensity * metalVar / metalConcentration

    depositionRateVariable = currentDensity * molarVolume / (charge * faradaysConstant)

    extensionVelocityVariable = CellVariable(
        name = 'extension velocity',
        mesh = mesh,
        value = depositionRateVariable)

    surfactantEquation = AdsorbingSurfactantEquation(
        surfactantVar = catalystVar,
        distanceVar = distanceVar,
        bulkVar = bulkCatalystVar,
        rateConstant = rateConstant0 + rateConstant3 * overpotential**3)

    advectionEquation = TransientTerm() + AdvectionTerm(extensionVelocityVariable)

    metalEquation = buildMetalIonDiffusionEquation(
        ionVar = metalVar,
        distanceVar = distanceVar,
        depositionRate = depositionRateVariable,
        diffusionCoeff = metalDiffusion,
        metalIonMolarVolume = molarVolume,
    )

    metalVar.constrain(metalConcentration, mesh.facesTop)

    from .surfactantBulkDiffusionEquation import buildSurfactantBulkDiffusionEquation
    bulkCatalystEquation = buildSurfactantBulkDiffusionEquation(
        bulkVar = bulkCatalystVar,
        distanceVar = distanceVar,
        surfactantVar = catalystVar,
        diffusionCoeff = catalystDiffusion,
        rateConstant = rateConstant0 * siteDensity
    )

    bulkCatalystVar.constrain(catalystConcentration, mesh.facesTop)

    if displayViewers:
        try:
            from .mayaviSurfactantViewer import MayaviSurfactantViewer
            viewer = MayaviSurfactantViewer(distanceVar, catalystVar.interfaceVar, zoomFactor = 1e6, datamax=0.5, datamin=0.0, smooth = 1, title = 'catalyst coverage')
        except:
            viewer = MultiViewer(viewers=(
                Viewer(distanceVar, datamin=-1e-9, datamax=1e-9),
                Viewer(catalystVar.interfaceVar)))
    else:
        viewer = None

    levelSetUpdateFrequency = int(0.8 * narrowBandWidth \
                                  / (cellSize * cflNumber * 2))

    for step in range(numberOfSteps):

        if step>5 and step % 5 == 0 and viewer is not None:
            viewer.plot()

        if step % levelSetUpdateFrequency == 0:
            distanceVar.calcDistanceFunction(order=2)

        extensionVelocityVariable.setValue(depositionRateVariable())

        distanceVar.updateOld()

        distanceVar.extendVariable(extensionVelocityVariable, order=2)
        dt = cflNumber * cellSize / extensionVelocityVariable.max()

        advectionEquation.solve(distanceVar, dt = dt)
        surfactantEquation.solve(catalystVar, dt = dt)
        metalEquation.solve(metalVar, dt = dt)
        bulkCatalystEquation.solve(bulkCatalystVar, dt = dt, solver=GeneralSolver(tolerance=1e-15, iterations=2000))


    try:
        import os
        filepath = os.path.splitext(__file__)[0] + '.gz'
        print(catalystVar.allclose(numerix.loadtxt(filepath), rtol = 1e-4))
    except:
        return 0
Exemple #10
0
def solve_Te(Qe_tot=2e6,
             H0=0,
             Hw=0.1,
             Te_bc=100,
             chi=1,
             a0=1,
             R0=3,
             E0=1.5,
             b_pos=0.98,
             b_height=6e19,
             b_sol=2e19,
             b_width=0.01,
             b_slope=0.01,
             nr=100,
             dt=100,
             plots=True):
    """
    :param Qe_tot: heating power [W]
    :type Qe_tot: numpy float
    :param H0: position of Gaussian [-]
    :type H0: numpy float
    :param Hw: width of Gaussian [-]
    :type Hw: numpy float
    :param Te_bc: outer edge Te boundary condition [eV]
    :type Te_bc: numpy float
    :param chi: thermal diffusivity [?]
    :type chi: numpy float
    :param a0: minor radius [m]
    :type a0: numpy float
    :param R0: major radius [m]
    :type R0: numpy float
    :param E0: ellipticity
    :type E0: numpy float
    :param b_pos: position of density pedestal [-]
    :type b_pos:  numpy float
    :param b_height: height of density pedestal [m^-3]
    :type b_height: numpy float
    :param b_sol: sol value for density pedestal [m^-3]
    :type b_sol: numpy float
    :param b_width: width of density pedestal [-]
    :type b_width: numpy float
    :param b_slope: slope of density pedestal [?]
    :type b_slope: numpy float
    :param nr: number of radial grid points
    :type nr: inteher
    :param dt: time-step [s]
    :type dt: numpy float
    :param plots: enable plots
    :type plots: boolean
    :return: array of Te values [eV]
    :type: numpy float array
    :return: array of ne values [m^-3]
    :type: numpy float array
    :return: rho values corresponding to the Te and ne values [m]
    :type: numpy float array
    :return: rho_norm values corresponding to the Te and ne values [-]
    :type: numpy float array

    [email protected]
    """

    if plots:
        import os
        import matplotlib
        if not os.getenv("DISPLAY"):
            matplotlib.use('Agg')
        import matplotlib.pylab as plt

    import scipy.constants
    from fipy import Variable, FaceVariable, CellVariable, TransientTerm, DiffusionTerm, Viewer, meshes

    a = a0 * np.sqrt(E0)
    V = 2 * np.pi * 2 * np.pi * R0
    mesh = meshes.CylindricalGrid1D(nr=nr, Lr=a)
    Te = CellVariable(name="Te", mesh=mesh, value=1e3)
    ne = CellVariable(name="ne",
                      mesh=mesh,
                      value=F_ped(mesh.cellCenters.value[0] / a, b_pos,
                                  b_height, b_sol, b_width, b_slope))
    Qe = CellVariable(name="Qe",
                      mesh=mesh,
                      value=np.exp(-((mesh.cellCenters.value / a - H0) /
                                     (Hw))**2)[0])
    Qe = Qe * Qe_tot / ((mesh.cellVolumes * Qe.value).sum() * V)

    print('Volume = %s m^3' % (mesh.cellVolumes.sum() * V))
    print('Heating power = %0.3e W' % ((mesh.cellVolumes * Qe).sum() * V))

    Te.constrain(Te_bc, mesh.facesRight)
    eqI = TransientTerm(
        coeff=scipy.constants.e * ne *
        1.5) == DiffusionTerm(coeff=scipy.constants.e * ne * chi) + Qe

    if plots:
        viewer = Viewer(vars=(Te),
                        title='Heating power = %0.3e W\nchi = %s' %
                        (Qe.cellVolumeAverage.value * V, chi),
                        datamin=0,
                        datamax=5000)

    eqI.solve(var=Te, dt=dt)
    if plots:
        viewer.plot()

    return Te.value, ne.value, mesh.cellCenters.value[
        0], mesh.cellCenters.value[0] / a
Exemple #11
0
from fipy import Grid1D, CellVariable, TransientTerm, DiffusionTerm, Viewer

m = Grid1D(nx=100, Lx=1.)

v0 = CellVariable(mesh=m, hasOld=True, value=0.5)
v1 = CellVariable(mesh=m, hasOld=True, value=0.5)

v0.constrain(0, m.facesLeft)
v0.constrain(1, m.facesRight)

v1.constrain(1, m.facesLeft)
v1.constrain(0, m.facesRight)

eq0 = TransientTerm() == DiffusionTerm(coeff=0.01) - v1.faceGrad.divergence
eq1 = TransientTerm() == v0.faceGrad.divergence + DiffusionTerm(coeff=0.01)

vi = Viewer((v0, v1))

for t in range(100): 
	v0.updateOld()
	v1.updateOld()
	res0 = res1 = 1e100
	while max(res0, res1) > 0.1:
	res0 = eq0.sweep(var=v0, dt=1e-5)
	res1 = eq1.sweep(var=v1, dt=1e-5)
	if t % 10 == 0:
		vi.plot()

# eqn0 = TransientTerm(var=v0) == DiffusionTerm(0.01, var=v0) - DiffusionTerm(1, var=v1)
# eqn1 = TransientTerm(var=v1) == DiffusionTerm(1, var=v0) + DiffusionTerm(0.01, var=v1)
Exemple #12
0
 def icivir_cuboid_solve(self):
     # step 2: Equation
     phi = CellVariable(mesh=self.mesh, name='potential phi', value=0.)
     eqn = (DiffusionTerm(coeff=1.) == 0.)
     # step 3: Boundary conditions
     # compute flow of 8 vertexes
     # one vertex has 3 components of wind vector, (x, y, z)
     vertexWindVec = np.array([[0.0 for i in range(3)] for i in range(8)])
     for i in range(8):  # 8 vertexes
         for j in range(3):  # 3 components
             vertexWindVec[i, j] = self.mean_flow[j] \
                     + self.colored_noise(self.vertexWindVecRanInc[i][j])
     # save these 8 vector for interp wind of edge area for plume sim
     self.wind_at_vertex = vertexWindVec
     #print 'vertexWindVec = ' + str(vertexWindVec)
     # interpolate flow vector on sim area faces, and set neumann boundary
     #   conditions, because /grad /phi = V(x,y,z)
     # /grad /phi array, of points of mesh face centers
     #   grad_phi_bc[0, :]  /grad/phi_x
     #   grad_phi_bc[1, :]  /grad/phi_y
     #   grad_phi_bc[2, :]  /grad/phi_z
     grad_phi_bc = np.zeros_like(self.mesh.faceCenters())
     # p: points on one face to interpolate, 2 dimension
     # vx, vy: x&y components of interpolated wind vectors of points list p
     # vertex index, for interpolate bc on 6 faces
     # vertexIndex[0] = [0,1,4,5], down  face, 0<x<nx*dx, y=0, 0<z<nz*dz
     # vertexIndex[1] = [0,2,4,6], left  face, x=0, 0<y<ny*dy, 0<z<nz*dz
     # vertexIndex[2] = [2,3,6,7], up    face, 0<x<nx*dx, y=ny*dy, 0<z<nz*dz
     # vertexIndex[3] = [1,3,5,7], right face, x=nx*dx, 0<y<ny*dy, 0<z<nz*dz
     # vertexIndex[4] = [0,1,2,3], front face, 0<x<nx*dx, 0<y<ny*dy, z=0
     # vertexIndex[5] = [4,5,6,7], back  face, 0<x<nx*dx, 0<y<ny*dy, z=nz*dz
     # write vertexIndex as mask type
     vertexMask = np.array([ \
             [True, True, False, False, True, True, False, False],
             [True, False, True, False, True, False, True, False],
             [False, False, True, True, False, False, True, True],
             [False, True, False, True, False, True, False, True],
             [True, True, True, True, False, False, False, False],
             [False, False, False, False, True, True, True, True] ])
     xyz_index = np.array([[0, 2], [1, 2], [0, 2], [1, 2], [0, 1], [0, 1]])
     for i in range(6):  # 6 faces for 3D cuboid area
         p1, p2 = np.mgrid[self.gsize/2:self.gsize*self.xyz_n[xyz_index[i,0]]:self.gsize, \
                 self.gsize/2:self.gsize*self.xyz_n[xyz_index[i,1]]:self.gsize]
         vx = griddata(zip(\
                 [0, self.gsize*self.xyz_n[xyz_index[i,0]], 0, self.gsize*self.xyz_n[xyz_index[i,0]]],\
                 [0, 0, self.gsize*self.xyz_n[xyz_index[i,1]], self.gsize*self.xyz_n[xyz_index[i,1]]]),\
                 vertexWindVec[vertexMask[i],0], (p1, p2), method='linear').T.reshape(1,-1)[0]
         vy = griddata(zip(\
                 [0, self.gsize*self.xyz_n[xyz_index[i,0]], 0, self.gsize*self.xyz_n[xyz_index[i,0]]],\
                 [0, 0, self.gsize*self.xyz_n[xyz_index[i,1]], self.gsize*self.xyz_n[xyz_index[i,1]]]),\
                 vertexWindVec[vertexMask[i],1], (p1, p2), method='linear').T.reshape(1,-1)[0]
         vz = griddata(zip(\
                 [0, self.gsize*self.xyz_n[xyz_index[i,0]], 0, self.gsize*self.xyz_n[xyz_index[i,0]]],\
                 [0, 0, self.gsize*self.xyz_n[xyz_index[i,1]], self.gsize*self.xyz_n[xyz_index[i,1]]]),\
                 vertexWindVec[vertexMask[i],2], (p1, p2), method='linear').T.reshape(1,-1)[0]
         if i == 0:  # down boundary
             grad_phi_bc[:, self.mesh.facesDown()] = np.array([vx, vy, vz])
         elif i == 1:  # left boundary
             grad_phi_bc[:, self.mesh.facesLeft()] = np.array([vx, vy, vz])
         elif i == 2:  # up boundary
             grad_phi_bc[:, self.mesh.facesUp()] = np.array([vx, vy, vz])
         elif i == 3:  # right boundary
             grad_phi_bc[:, self.mesh.facesRight()] = np.array([vx, vy, vz])
         elif i == 4:  # front
             grad_phi_bc[:, self.mesh.facesFront()] = np.array([vx, vy, vz])
         elif i == 5:  # back
             grad_phi_bc[:, self.mesh.facesBack()] = np.array([vx, vy, vz])
     #print 'grad_phi_bc[ext] = ' + str(grad_phi_bc[:, self.mesh.exteriorFaces()])
     # set neumann boundary condition
     phi.faceGrad.constrain(
         ((grad_phi_bc[0]), (grad_phi_bc[1]), (grad_phi_bc[2])),
         where=self.mesh.exteriorFaces)
     # set dirichlet boundary condition
     # set /phi value on one point of a cell, to provide a init value for equaition solver
     #   get all points which lie on the center of faces of cells
     X, Y, Z = self.mesh.faceCenters
     mask = ((X == self.gsize / 2) & (Y == self.gsize / 2) & (Z == 0)
             )  # front face of cell 0
     phi.constrain(0, where=self.mesh.exteriorFaces & mask)
     # step 4: Solve
     eqn.solve(var=phi)
     # Post processing
     #   get /phi array
     self.wind_phi_field = np.array(phi).reshape(self.xyz_n[2], \
             self.xyz_n[1], self.xyz_n[0]).T
     #   convert /phi to wind vector
     self.wind_vector_field = np.array(
         np.gradient(self.wind_phi_field, self.gsize))
     #print 'wind_vector_field = ' + str(self.wind_vector_field)
     #   get cell centers
     self.wind_mesh_centers = self.mesh.cellCenters()
from fipy import Variable, FaceVariable, CellVariable, Grid1D, ExplicitDiffusionTerm, TransientTerm, DiffusionTerm, Viewer
from fipy.tools import numerix

nx = 50
dx = 1.
mesh = Grid1D(nx=nx, dx=dx)

phi = CellVariable(name='sol var', mesh=mesh, value=0., hasOld=False)

D = 1.

valueleft = 1
valueright = 0

phi.constrain(valueleft, mesh.facesLeft)
phi.constrain(valueright, mesh.facesRight)

eq = TransientTerm() == DiffusionTerm(coeff=D)

timeStepDuration = 1.
steps = 10

MAX_SWEEPS = 100
for step in range(steps):
    res = 0.0
    # phi.updateOld()
    for r in range(MAX_SWEEPS):
        resOld = res

        res = eq.sweep(var=phi, dt=timeStepDuration)
Exemple #14
0
Rim = 1.0    # immobile domain retardation coefficient

betaT = phiim*Rim/(phim*Rm)
DR = D/Rm

m = Grid1D(dx=dx, nx=nx)
c0 = np.zeros(nx, 'd')
c0[20:50] = 1.0

# mobile domain concentration
cm = CellVariable(name="$c_m$", mesh=m, value=c0)

# immobile domain concentration
cim = CellVariable(name="$c_{im}$", mesh=m, value=0.0)

cm.constrain(0, m.facesLeft)
cm.constrain(0, m.facesRight)

cim.constrain(0, m.facesLeft)
cim.constrain(0, m.facesRight)

# advective flow velocity 
u = FaceVariable(mesh=m, value=(0.0,), rank=1)

# 1D convection diffusion equation (mobile domain)
# version with \frac{\partial c_{im}}{\partial t}
eqM =  (TransientTerm(1.0,var=cm) + TransientTerm(betaT,var=cim) == 
       DiffusionTerm(DR,var=cm) - ExponentialConvectionTerm(u/(Rm*phim),var=cm))

# immobile domain (lumped approach)
eqIM = TransientTerm(Rim*phiim,var=cim) == beta/Rim*(cm - ImplicitSourceTerm(1.0,var=cim))
# Physical parameters
mm = 4.               # anisotropic symmetry
epsilon_m = 0.025     # degree of anisotropy
theta_0 = 0.0         # tilt w.r.t. x-axis
tau_0 = 1.            # numerical mobility
DD = 10.              # thermal diffusivity
W_0 = 1.              # isotropic well height
lamda = DD * tau_0 / 0.6267 / W_0**2
delta = 0.05          # undercooling

# Mesh and field variables
mesh = Grid2D(nx=nx, ny=ny, dx=dx, dy=dy)
phase = CellVariable(mesh=mesh, hasOld=True)
uu = CellVariable(mesh=mesh, hasOld=True)
uu.constrain(-delta, mesh.exteriorFaces)


def initialize():
    phase[:] = -1.0
    x, y = mesh.cellCenters
    radius = 2.0 # Initial r=1 collapses due to Gibbs-Thomson, r=2 slumps to phi=0.6, r=4 seems OK.
    center = (nx * dx / 2., ny * dy / 2.)
    mask = (x - center[0])**2 + (y - center[1])**2 < radius**2
    phase.setValue(1., where=mask)
    uu[:] = -delta

initialize()


def make_tau(phase_):
Exemple #16
0
nz = 3

dx = 1.
dy = 1.
dz = 1.

valueBottomTop = 0.
valueLeftRight = 1.

mesh = Grid3D(dx = dx, dy = dy, dz = dz, nx = nx, ny = ny, nz = nz)

var = CellVariable(name = "solution variable",
                   mesh = mesh,
                   value = valueBottomTop)

var.constrain(valueLeftRight, mesh.facesLeft)
var.constrain(valueLeftRight, mesh.facesRight)
var.constrain(valueBottomTop, mesh.facesTop)
var.constrain(valueBottomTop, mesh.facesBottom)

#do the 2D problem for comparison

nx = 8 # FIXME: downsized temporarily from 10 due to https://github.com/usnistgov/fipy/issues/622
ny = 5

dx = 1.
dy = 1.

mesh2 = Grid2D(dx = dx, dy = dy, nx = nx, ny = ny)

var2 = CellVariable(name = "solution variable 2D",
Exemple #17
0
def runGold(faradaysConstant=9.6e4,
            consumptionRateConstant=2.6e+6,
            molarVolume=10.21e-6,
            charge=1.0,
            metalDiffusion=1.7e-9,
            metalConcentration=20.0,
            catalystCoverage=0.15,
            currentDensity0=3e-2 * 16,
            currentDensity1=6.5e-1 * 16,
            cellSize=0.1e-7,
            trenchDepth=0.2e-6,
            aspectRatio=1.47,
            trenchSpacing=0.5e-6,
            boundaryLayerDepth=90.0e-6,
            numberOfSteps=10,
            taperAngle=6.0,
            displayViewers=True):

    cflNumber = 0.2
    numberOfCellsInNarrowBand = 20

    mesh = TrenchMesh(cellSize=cellSize,
                      trenchSpacing=trenchSpacing,
                      trenchDepth=trenchDepth,
                      boundaryLayerDepth=boundaryLayerDepth,
                      aspectRatio=aspectRatio,
                      angle=numerix.pi * taperAngle / 180.)

    narrowBandWidth = numberOfCellsInNarrowBand * cellSize

    distanceVar = GapFillDistanceVariable(name='distance variable',
                                          mesh=mesh,
                                          value=-1.)

    distanceVar.setValue(1., where=mesh.electrolyteMask)
    distanceVar.calcDistanceFunction()

    catalystVar = SurfactantVariable(name="catalyst variable",
                                     value=catalystCoverage,
                                     distanceVar=distanceVar)

    metalVar = CellVariable(name='metal variable',
                            mesh=mesh,
                            value=metalConcentration)

    exchangeCurrentDensity = currentDensity0 + currentDensity1 * catalystVar.interfaceVar

    currentDensity = metalVar / metalConcentration * exchangeCurrentDensity

    depositionRateVariable = currentDensity * molarVolume / charge / faradaysConstant

    extensionVelocityVariable = CellVariable(name='extension velocity',
                                             mesh=mesh,
                                             value=depositionRateVariable)

    catalystSurfactantEquation = AdsorbingSurfactantEquation(
        catalystVar,
        distanceVar=distanceVar,
        bulkVar=0,
        rateConstant=0,
        consumptionCoeff=consumptionRateConstant * extensionVelocityVariable)

    advectionEquation = TransientTerm() + FirstOrderAdvectionTerm(
        extensionVelocityVariable)

    metalEquation = buildMetalIonDiffusionEquation(
        ionVar=metalVar,
        distanceVar=distanceVar,
        depositionRate=depositionRateVariable,
        diffusionCoeff=metalDiffusion,
        metalIonMolarVolume=molarVolume)

    metalVar.constrain(metalConcentration, mesh.facesTop)

    if displayViewers:

        try:
            from .mayaviSurfactantViewer import MayaviSurfactantViewer
            viewer = MayaviSurfactantViewer(distanceVar,
                                            catalystVar.interfaceVar,
                                            zoomFactor=1e6,
                                            datamax=1.0,
                                            datamin=0.0,
                                            smooth=1,
                                            title='catalyst coverage',
                                            animate=True)

        except:

            class PlotVariable(CellVariable):
                def __init__(self, var=None, name=''):
                    CellVariable.__init__(self, mesh=mesh.fineMesh, name=name)
                    self.var = self._requires(var)

                def _calcValue(self):
                    return numerix.array(self.var(self.mesh.cellCenters))

            viewer = MultiViewer(
                viewers=(Viewer(
                    PlotVariable(
                        var=distanceVar), datamax=1e-9, datamin=-1e-9),
                         Viewer(PlotVariable(var=catalystVar.interfaceVar))))
    else:
        viewer = None

    levelSetUpdateFrequency = int(0.7 * narrowBandWidth / cellSize /
                                  cflNumber / 2)
    step = 0

    while step < numberOfSteps:

        if step % 10 == 0 and viewer is not None:
            viewer.plot()

        if step % levelSetUpdateFrequency == 0:

            distanceVar.calcDistanceFunction()

        extensionVelocityVariable.setValue(
            numerix.array(depositionRateVariable))

        dt = cflNumber * cellSize / max(extensionVelocityVariable.globalValue)
        distanceVar.extendVariable(extensionVelocityVariable)

        advectionEquation.solve(distanceVar, dt=dt)

        catalystSurfactantEquation.solve(catalystVar, dt=dt)

        metalEquation.solve(metalVar, dt=dt)

        step += 1

    point = ((5e-09, ), (1.15e-07, ))
    value = 1.45346701e-09
    return abs(float(distanceVar(point, order=1)) - value) < cellSize / 10.0
Exemple #18
0
D_Zohm.setValue((D_max + D_min) / 2.0 + ((D_max - D_min)*numerix.tanh(Z)) / 2.0)
# Stap's Model
alpha_sup = 0.5
D_Staps.setValue(D_min + (D_max - D_min) / (1.0 + alpha_sup*(Z.grad.mag)**2))
# Flow-Shear Model
a1, a2, a3 = 0.7, 1.25, 0.5
D_Shear.setValue(D_min + (D_max - D_min) / (1.0 + a1*Z**2 + a2*Z*(Z.grad) + a3*(Z.grad)**2))


# ----------------- Boundary Conditions -------------------
# Z Boundary Conditions:
#	d/dx(Z(0,t)) == Z / lambda_Z
#	mu*D/epsilon * d/dx(Z(L,t)) == 0
#	d^2/dx^2(Z(0,t)) == 0
Z.faceGrad.constrain(Z.faceValue / lambda_Z, mesh.facesLeft)
Z.constrain(0.0, mesh.facesRight)

Z.grad.faceGrad.constrain(0.0, mesh.facesLeft)


# ----------------- PDE Declarations ----------------------

#initial_viewer = MatplotlibViewer((D_Zohm, D_Staps, D_Shear), title=r"Diffusivity Models: FiPy", xmin=0.0, xmax=3.0)
#pyplot.grid(True)
#pyplot.axes().set_aspect('equal')

viewer = None
if __name__ == '__main__':
	try:
		viewer = Viewer(vars=D_Zohm, datamin=0.0, datamax=3.0)
		viewer.plotMesh()
Exemple #19
0
nz = 3

dx = 1.
dy = 1.
dz = 1.

valueBottomTop = 0.
valueLeftRight = 1.

mesh = Grid3D(dx = dx, dy = dy, dz = dz, nx = nx, ny = ny, nz = nz)

var = CellVariable(name = "solution variable",
                   mesh = mesh,
                   value = valueBottomTop)

var.constrain(valueLeftRight, mesh.facesLeft)
var.constrain(valueLeftRight, mesh.facesRight)
var.constrain(valueBottomTop, mesh.facesTop)
var.constrain(valueBottomTop, mesh.facesBottom)

#do the 2D problem for comparison

nx = 8 # FIXME: downsized temporarily from 10 due to https://github.com/usnistgov/fipy/issues/622
ny = 5

dx = 1.
dy = 1.

mesh2 = Grid2D(dx = dx, dy = dy, nx = nx, ny = ny)

var2 = CellVariable(name = "solution variable 2D",
Exemple #20
0
dx = 1
dy = dx
L = dx * nx
mesh = Grid2D(dx=dx, dy=dy, nx=nx, ny=ny)

phi = CellVariable(name="solution variable", mesh=mesh, value=0.)
D = 1
eq = TransientTerm() == DiffusionTerm(coeff=D)

valueTopLeft = 0
valueBottomRight = 1

X, Y = mesh.faceCenters
facesTopLeft = ((mesh.facesLeft & (Y > L / 2)) | (mesh.facesTop & (X < L / 2)))
facesBottomRight = ((mesh.facesRight & (Y < L / 2)) | (mesh.facesBottom &
                                                       (X > L / 2)))

phi.constrain(valueTopLeft, facesTopLeft)
phi.constrain(valueBottomRight, facesBottomRight)

if __name__ == '__main__':
    viewer = Viewer(vars=phi, datamin=0., datamax=1.)
    viewer.plot()

timeStepDuration = 10 * 0.9 * dx**2 / (2 * D)
steps = 10
for step in range(steps):
    eq.solve(var=phi, dt=timeStepDuration)
    if __name__ == '__main__':
        viewer.plot()
Exemple #21
0
    from fipy import SkewedGrid2D, CellVariable, Viewer, DiffusionTerm
    from fipy.tools import numerix

    valueLeft = 0.
    valueRight = 1.

    mesh = SkewedGrid2D(dx = 1.0, dy = 1.0, nx = 20, ny = 20, rand = 0.1)

    var = CellVariable(name = "solution variable",
                       mesh = mesh,
                       value = valueLeft)

    viewer = Viewer(vars = var)

    var.constrain(valueLeft, mesh.facesLeft)
    var.constrain(valueRight, mesh.facesRight)

    DiffusionTerm().solve(var)

    varArray = numerix.array(var)
    x = mesh.cellCenters[0]
    analyticalArray = valueLeft + (valueRight - valueLeft) * x / 20
    errorArray = varArray - analyticalArray
    errorVar = CellVariable(name = 'absolute error',
                            mesh = mesh,
                            value = abs(errorArray))
    errorViewer = Viewer(vars = errorVar)

    NonOrthoVar = CellVariable(name = "non-orthogonality",
                               mesh = mesh,
TIME_STRIDE = 10
chi_AB = 0.08
N_A = 1000
N_B = 1000


print ("Yay")

# # Define mesh
mesh = PeriodicGrid2D(nx=10.0, ny=10.0, dx=1.0, dy=1.0)
print ("mesh loaded")

x_a = CellVariable(name=r"x_a", mesh = mesh, hasOld=1)
xi = CellVariable(name=r"xi", mesh = mesh, hasOld=1)

x_a.constrain(x_a.faceValue, mesh.facesLeft)
x_a.constrain(x_a.faceValue, mesh.facesRight)

xi.constrain(xi.faceValue, mesh.facesLeft)
xi.constrain(xi.faceValue, mesh.facesRight)

# We need to introduce the noise
noise = GaussianNoiseVariable(mesh=mesh,
                              mean = A_RAW,
                              variance = NOISE_MAGNITUDE).value

x_a[:] = noise


dgdx_a = ((1.0/N_A) - (1.0/N_B)) + (1.0/N_A)*numerix.log(x_a) - (1.0/N_B)*numerix.log(1.0 - x_a) + chi_AB*(1.0 - 2*x_a)
Exemple #23
0
## Build the bulk diffusion equation

bulkVar = CellVariable(mesh=mesh, value=cinf)

surfactantVar = SurfactantVariable(distanceVar=distanceVar)

from .surfactantBulkDiffusionEquation import buildSurfactantBulkDiffusionEquation
bulkEqn = buildSurfactantBulkDiffusionEquation(bulkVar,
                                               distanceVar=distanceVar,
                                               surfactantVar=surfactantVar,
                                               diffusionCoeff=diffusion,
                                               rateConstant=rateConstant *
                                               siteDensity)

bulkVar.constrain(cinf, mesh.facesRight)

## Build the surfactant equation

surfEqn = AdsorbingSurfactantEquation(surfactantVar=surfactantVar,
                                      distanceVar=distanceVar,
                                      bulkVar=bulkVar,
                                      rateConstant=rateConstant)

## Build the analytical solutions,

x = mesh.cellCenters[0, 1:] - dx


def concentrationFunc(theta):
    tmp = (1 + rateConstant * siteDensity * (1 - theta) * L / diffusion)
Exemple #24
0
def runLeveler(kLeveler=0.018,
               bulkLevelerConcentration=0.02,
               cellSize=0.1e-7,
               rateConstant=0.00026,
               initialAcceleratorCoverage=0.0,
               levelerDiffusionCoefficient=5e-10,
               numberOfSteps=400,
               displayRate=10,
               displayViewers=True):

    kLevelerConsumption = 0.0005
    aspectRatio = 1.5
    faradaysConstant = 9.6485e4
    gasConstant = 8.314
    acceleratorDiffusionCoefficient = 4e-10
    siteDensity = 6.35e-6
    atomicVolume = 7.1e-6
    charge = 2
    metalDiffusionCoefficient = 4e-10
    temperature = 298.
    overpotential = -0.25
    bulkMetalConcentration = 250.
    bulkAcceleratorConcentration = 50.0e-3
    initialLevelerCoverage = 0.
    cflNumber = 0.2
    cellsBelowTrench = 10
    trenchDepth = 0.4e-6
    trenchSpacing = 0.6e-6
    boundaryLayerDepth = 98.7e-6
    i0Suppressor = 0.3
    i0Accelerator = 22.5
    alphaSuppressor = 0.5
    alphaAccelerator = 0.4
    alphaAdsorption = 0.62
    m = 4
    b = 2.65
    A = 0.3
    Ba = -40
    Bb = 60
    Vd = 0.098
    Bd = 0.0008

    etaPrime = faradaysConstant * overpotential / gasConstant / temperature

    mesh = TrenchMesh(cellSize=cellSize,
                      trenchSpacing=trenchSpacing,
                      trenchDepth=trenchDepth,
                      boundaryLayerDepth=boundaryLayerDepth,
                      aspectRatio=aspectRatio,
                      angle=numerix.pi * 4. / 180.)

    distanceVar = GapFillDistanceVariable(name='distance variable',
                                          mesh=mesh,
                                          value=-1.)

    distanceVar.setValue(1., where=mesh.electrolyteMask)

    distanceVar.calcDistanceFunction()
    levelerVar = SurfactantVariable(name="leveler variable",
                                    value=initialLevelerCoverage,
                                    distanceVar=distanceVar)

    acceleratorVar = SurfactantVariable(name="accelerator variable",
                                        value=initialAcceleratorCoverage,
                                        distanceVar=distanceVar)

    bulkAcceleratorVar = CellVariable(name='bulk accelerator variable',
                                      mesh=mesh,
                                      value=bulkAcceleratorConcentration)

    bulkLevelerVar = CellVariable(name='bulk leveler variable',
                                  mesh=mesh,
                                  value=bulkLevelerConcentration)

    metalVar = CellVariable(name='metal variable',
                            mesh=mesh,
                            value=bulkMetalConcentration)

    def depositionCoeff(alpha, i0):
        expo = numerix.exp(-alpha * etaPrime)
        return 2 * i0 * (expo - expo * numerix.exp(etaPrime))

    coeffSuppressor = depositionCoeff(alphaSuppressor, i0Suppressor)
    coeffAccelerator = depositionCoeff(alphaAccelerator, i0Accelerator)

    exchangeCurrentDensity = acceleratorVar.interfaceVar * (
        coeffAccelerator - coeffSuppressor) + coeffSuppressor

    currentDensity = metalVar / bulkMetalConcentration * exchangeCurrentDensity

    depositionRateVariable = currentDensity * atomicVolume / charge / faradaysConstant

    extensionVelocityVariable = CellVariable(name='extension velocity',
                                             mesh=mesh,
                                             value=depositionRateVariable)

    kAccelerator = rateConstant * numerix.exp(-alphaAdsorption * etaPrime)
    kAcceleratorConsumption = Bd + A / (numerix.exp(Ba *
                                                    (overpotential + Vd)) +
                                        numerix.exp(Bb * (overpotential + Vd)))
    q = m * overpotential + b

    levelerSurfactantEquation = AdsorbingSurfactantEquation(
        levelerVar,
        distanceVar=distanceVar,
        bulkVar=bulkLevelerVar,
        rateConstant=kLeveler,
        consumptionCoeff=kLevelerConsumption * depositionRateVariable)

    accVar1 = acceleratorVar.interfaceVar
    accVar2 = (accVar1 > 0) * accVar1
    accConsumptionCoeff = kAcceleratorConsumption * (accVar2**(q - 1))

    acceleratorSurfactantEquation = AdsorbingSurfactantEquation(
        acceleratorVar,
        distanceVar=distanceVar,
        bulkVar=bulkAcceleratorVar,
        rateConstant=kAccelerator,
        otherVar=levelerVar,
        otherBulkVar=bulkLevelerVar,
        otherRateConstant=kLeveler,
        consumptionCoeff=accConsumptionCoeff)

    advectionEquation = TransientTerm() + FirstOrderAdvectionTerm(
        extensionVelocityVariable)

    metalEquation = buildMetalIonDiffusionEquation(
        ionVar=metalVar,
        distanceVar=distanceVar,
        depositionRate=depositionRateVariable,
        diffusionCoeff=metalDiffusionCoefficient,
        metalIonMolarVolume=atomicVolume)

    metalVar.constrain(bulkMetalConcentration, mesh.facesTop)

    bulkAcceleratorEquation = buildSurfactantBulkDiffusionEquation(
        bulkVar=bulkAcceleratorVar,
        distanceVar=distanceVar,
        surfactantVar=acceleratorVar,
        otherSurfactantVar=levelerVar,
        diffusionCoeff=acceleratorDiffusionCoefficient,
        rateConstant=kAccelerator * siteDensity)

    bulkAcceleratorVar.constrain(bulkAcceleratorConcentration, mesh.facesTop)

    bulkLevelerEquation = buildSurfactantBulkDiffusionEquation(
        bulkVar=bulkLevelerVar,
        distanceVar=distanceVar,
        surfactantVar=levelerVar,
        diffusionCoeff=levelerDiffusionCoefficient,
        rateConstant=kLeveler * siteDensity)

    bulkLevelerVar.constrain(bulkLevelerConcentration, mesh.facesTop)

    eqnTuple = ((advectionEquation, distanceVar, (),
                 None), (levelerSurfactantEquation, levelerVar, (), None),
                (acceleratorSurfactantEquation, acceleratorVar, (),
                 None), (metalEquation, metalVar, (), None),
                (bulkAcceleratorEquation, bulkAcceleratorVar, (),
                 GeneralSolver()), (bulkLevelerEquation, bulkLevelerVar, (),
                                    GeneralSolver()))

    narrowBandWidth = 20 * cellSize
    levelSetUpdateFrequency = int(0.7 * narrowBandWidth / cellSize /
                                  cflNumber / 2)

    totalTime = 0.0

    if displayViewers:
        try:
            raise Exception
            from mayaviSurfactantViewer import MayaviSurfactantViewer
            viewers = (MayaviSurfactantViewer(distanceVar,
                                              acceleratorVar.interfaceVar,
                                              zoomFactor=1e6,
                                              datamax=0.5,
                                              datamin=0.0,
                                              smooth=1,
                                              title='accelerator coverage'),
                       MayaviSurfactantViewer(distanceVar,
                                              levelerVar.interfaceVar,
                                              zoomFactor=1e6,
                                              datamax=0.5,
                                              datamin=0.0,
                                              smooth=1,
                                              title='leveler coverage'))
        except:

            class PlotVariable(CellVariable):
                def __init__(self, var=None, name=''):
                    CellVariable.__init__(self, mesh=mesh.fineMesh, name=name)
                    self.var = self._requires(var)

                def _calcValue(self):
                    return numerix.array(self.var(self.mesh.cellCenters))

            viewers = (Viewer(PlotVariable(var=acceleratorVar.interfaceVar)),
                       Viewer(PlotVariable(var=levelerVar.interfaceVar)))

    for step in range(numberOfSteps):

        if displayViewers:
            if step % displayRate == 0:
                for viewer in viewers:
                    viewer.plot()

        if step % levelSetUpdateFrequency == 0:
            distanceVar.calcDistanceFunction()

        extensionVelocityVariable.setValue(depositionRateVariable)

        extOnInt = numerix.where(
            distanceVar.globalValue > 0,
            numerix.where(distanceVar.globalValue < 2 * cellSize,
                          extensionVelocityVariable.globalValue, 0), 0)

        dt = cflNumber * cellSize / extOnInt.max()

        distanceVar.extendVariable(extensionVelocityVariable)

        for eqn, var, BCs, solver in eqnTuple:
            eqn.solve(var, boundaryConditions=BCs, dt=dt, solver=solver)

        totalTime += dt

    point = ((1.25e-08, ), (3.125e-07, ))
    value = 2.02815779e-08
    return abs(float(distanceVar(point, order=1)) - value) < cellSize / 10.0
Exemple #25
0
def runSimpleTrenchSystem(faradaysConstant=9.6e4,
                          gasConstant=8.314,
                          transferCoefficient=0.5,
                          rateConstant0=1.76,
                          rateConstant3=-245e-6,
                          catalystDiffusion=1e-9,
                          siteDensity=9.8e-6,
                          molarVolume=7.1e-6,
                          charge=2,
                          metalDiffusion=5.6e-10,
                          temperature=298.,
                          overpotential=-0.3,
                          metalConcentration=250.,
                          catalystConcentration=5e-3,
                          catalystCoverage=0.,
                          currentDensity0=0.26,
                          currentDensity1=45.,
                          cellSize=0.1e-7,
                          trenchDepth=0.5e-6,
                          aspectRatio=2.,
                          trenchSpacing=0.6e-6,
                          boundaryLayerDepth=0.3e-6,
                          numberOfSteps=5,
                          displayViewers=True):

    cflNumber = 0.2
    numberOfCellsInNarrowBand = 10
    cellsBelowTrench = 10

    yCells = cellsBelowTrench \
             + int((trenchDepth + boundaryLayerDepth) / cellSize)

    xCells = int(trenchSpacing / 2 / cellSize)

    from fipy.tools import serialComm
    mesh = Grid2D(dx=cellSize,
                  dy=cellSize,
                  nx=xCells,
                  ny=yCells,
                  communicator=serialComm)

    narrowBandWidth = numberOfCellsInNarrowBand * cellSize

    distanceVar = DistanceVariable(name='distance variable',
                                   mesh=mesh,
                                   value=-1.,
                                   hasOld=1)

    bottomHeight = cellsBelowTrench * cellSize
    trenchHeight = bottomHeight + trenchDepth
    trenchWidth = trenchDepth / aspectRatio
    sideWidth = (trenchSpacing - trenchWidth) / 2

    x, y = mesh.cellCenters
    distanceVar.setValue(1.,
                         where=(y > trenchHeight) |
                         ((y > bottomHeight) &
                          (x < xCells * cellSize - sideWidth)))

    distanceVar.calcDistanceFunction(order=2)

    catalystVar = SurfactantVariable(name="catalyst variable",
                                     value=catalystCoverage,
                                     distanceVar=distanceVar)

    bulkCatalystVar = CellVariable(name='bulk catalyst variable',
                                   mesh=mesh,
                                   value=catalystConcentration)

    metalVar = CellVariable(name='metal variable',
                            mesh=mesh,
                            value=metalConcentration)

    expoConstant = -transferCoefficient * faradaysConstant \
                   / (gasConstant * temperature)

    tmp = currentDensity1 * catalystVar.interfaceVar

    exchangeCurrentDensity = currentDensity0 + tmp

    expo = numerix.exp(expoConstant * overpotential)
    currentDensity = expo * exchangeCurrentDensity * metalVar \
                     / metalConcentration

    depositionRateVariable = currentDensity * molarVolume \
                             / (charge * faradaysConstant)

    extensionVelocityVariable = CellVariable(name='extension velocity',
                                             mesh=mesh,
                                             value=depositionRateVariable)

    surfactantEquation = AdsorbingSurfactantEquation(
        surfactantVar=catalystVar,
        distanceVar=distanceVar,
        bulkVar=bulkCatalystVar,
        rateConstant=rateConstant0 + rateConstant3 * overpotential**3)

    advectionEquation = TransientTerm() + AdvectionTerm(
        extensionVelocityVariable)

    metalEquation = buildMetalIonDiffusionEquation(
        ionVar=metalVar,
        distanceVar=distanceVar,
        depositionRate=depositionRateVariable,
        diffusionCoeff=metalDiffusion,
        metalIonMolarVolume=molarVolume,
    )

    metalVar.constrain(metalConcentration, mesh.facesTop)

    from surfactantBulkDiffusionEquation import buildSurfactantBulkDiffusionEquation
    bulkCatalystEquation = buildSurfactantBulkDiffusionEquation(
        bulkVar=bulkCatalystVar,
        distanceVar=distanceVar,
        surfactantVar=catalystVar,
        diffusionCoeff=catalystDiffusion,
        rateConstant=rateConstant0 * siteDensity)

    bulkCatalystVar.constrain(catalystConcentration, mesh.facesTop)

    if displayViewers:
        try:
            from mayaviSurfactantViewer import MayaviSurfactantViewer
            viewer = MayaviSurfactantViewer(distanceVar,
                                            catalystVar.interfaceVar,
                                            zoomFactor=1e6,
                                            datamax=0.5,
                                            datamin=0.0,
                                            smooth=1,
                                            title='catalyst coverage')
        except:
            viewer = MultiViewer(
                viewers=(Viewer(distanceVar, datamin=-1e-9, datamax=1e-9),
                         Viewer(catalystVar.interfaceVar)))
    else:
        viewer = None

    levelSetUpdateFrequency = int(0.8 * narrowBandWidth \
                                  / (cellSize * cflNumber * 2))

    for step in range(numberOfSteps):

        if step > 5 and step % 5 == 0 and viewer is not None:
            viewer.plot()

        if step % levelSetUpdateFrequency == 0:
            distanceVar.calcDistanceFunction(order=2)

        extensionVelocityVariable.setValue(depositionRateVariable())

        distanceVar.updateOld()

        distanceVar.extendVariable(extensionVelocityVariable, order=2)
        dt = cflNumber * cellSize / extensionVelocityVariable.max()

        advectionEquation.solve(distanceVar, dt=dt)
        surfactantEquation.solve(catalystVar, dt=dt)
        metalEquation.solve(metalVar, dt=dt)
        bulkCatalystEquation.solve(bulkCatalystVar,
                                   dt=dt,
                                   solver=GeneralSolver(tolerance=1e-15,
                                                        iterations=2000))

    try:
        import os
        filepath = os.path.splitext(__file__)[0] + '.gz'
        print catalystVar.allclose(numerix.loadtxt(filepath), rtol=1e-4)
    except:
        return 0
#!/usr/bin/env python

from fipy import Grid1D, CellVariable, TransientTerm, DiffusionTerm, Viewer
#
m = Grid1D(nx=100, Lx=1.)
#
v0 = CellVariable(mesh=m, hasOld=True, value=0.5)
v1 = CellVariable(mesh=m, hasOld=True, value=0.5)
#
v0.constrain(0, m.facesLeft)
v0.constrain(1, m.facesRight)
#
v1.constrain(1, m.facesLeft)
v1.constrain(0, m.facesRight)
#
eq0 = TransientTerm() == DiffusionTerm(coeff=0.01) - v1.faceGrad.divergence
eq1 = TransientTerm() == v0.faceGrad.divergence + DiffusionTerm(coeff=0.01)
#
vi = Viewer((v0, v1))
#
for t in range(100): 
    v0.updateOld()
    v1.updateOld()
    res0 = res1 = 1e100
    while max(res0, res1) > 0.1:
        res0 = eq0.sweep(var=v0, dt=1e-5)
        res1 = eq1.sweep(var=v1, dt=1e-5)
    if t % 10 == 0:
        vi.plot()
Exemple #27
0
def runGold(faradaysConstant=9.6e4,
            consumptionRateConstant=2.6e+6,
            molarVolume=10.21e-6,
            charge=1.0,
            metalDiffusion=1.7e-9,
            metalConcentration=20.0,
            catalystCoverage=0.15,
            currentDensity0=3e-2 * 16,
            currentDensity1=6.5e-1 * 16,
            cellSize=0.1e-7,
            trenchDepth=0.2e-6,
            aspectRatio=1.47,
            trenchSpacing=0.5e-6,
            boundaryLayerDepth=90.0e-6,
            numberOfSteps=10,
            taperAngle=6.0,
            displayViewers=True):

    cflNumber = 0.2
    numberOfCellsInNarrowBand = 20

    mesh = TrenchMesh(cellSize = cellSize,
                      trenchSpacing = trenchSpacing,
                      trenchDepth = trenchDepth,
                      boundaryLayerDepth = boundaryLayerDepth,
                      aspectRatio = aspectRatio,
                      angle = numerix.pi * taperAngle / 180.)

    narrowBandWidth = numberOfCellsInNarrowBand * cellSize

    distanceVar = GapFillDistanceVariable(
       name = 'distance variable',
       mesh = mesh,
       value = -1.)

    distanceVar.setValue(1., where=mesh.electrolyteMask)
    distanceVar.calcDistanceFunction()

    catalystVar = SurfactantVariable(
        name = "catalyst variable",
        value = catalystCoverage,
        distanceVar = distanceVar)

    metalVar = CellVariable(
        name = 'metal variable',
        mesh = mesh,
        value = metalConcentration)

    exchangeCurrentDensity = currentDensity0 + currentDensity1 * catalystVar.interfaceVar

    currentDensity = metalVar / metalConcentration * exchangeCurrentDensity

    depositionRateVariable = currentDensity * molarVolume / charge / faradaysConstant

    extensionVelocityVariable = CellVariable(
        name = 'extension velocity',
        mesh = mesh,
        value = depositionRateVariable)

    catalystSurfactantEquation = AdsorbingSurfactantEquation(
        catalystVar,
        distanceVar = distanceVar,
        bulkVar = 0,
        rateConstant = 0,
        consumptionCoeff = consumptionRateConstant * extensionVelocityVariable)

    advectionEquation = TransientTerm() + FirstOrderAdvectionTerm(extensionVelocityVariable)

    metalEquation = buildMetalIonDiffusionEquation(
        ionVar = metalVar,
        distanceVar = distanceVar,
        depositionRate = depositionRateVariable,
        diffusionCoeff = metalDiffusion,
        metalIonMolarVolume = molarVolume)

    metalVar.constrain(metalConcentration, mesh.facesTop)

    if displayViewers:

        try:
            from .mayaviSurfactantViewer import MayaviSurfactantViewer
            viewer = MayaviSurfactantViewer(distanceVar, catalystVar.interfaceVar, zoomFactor = 1e6, datamax=1.0, datamin=0.0, smooth = 1, title = 'catalyst coverage', animate=True)

        except:

            class PlotVariable(CellVariable):
                def __init__(self, var = None, name = ''):
                    CellVariable.__init__(self, mesh = mesh.fineMesh, name = name)
                    self.var = self._requires(var)

                def _calcValue(self):
                    return numerix.array(self.var(self.mesh.cellCenters))

            viewer = MultiViewer(viewers=(
                    Viewer(PlotVariable(var = distanceVar), datamax=1e-9, datamin=-1e-9),
                    Viewer(PlotVariable(var = catalystVar.interfaceVar))))
    else:
        viewer = None

    levelSetUpdateFrequency = int(0.7 * narrowBandWidth / cellSize / cflNumber / 2)
    step = 0

    while step < numberOfSteps:

        if step % 10 == 0 and viewer is not None:
            viewer.plot()

        if step % levelSetUpdateFrequency == 0:

            distanceVar.calcDistanceFunction()

        extensionVelocityVariable.setValue(numerix.array(depositionRateVariable))

        dt = cflNumber * cellSize / max(extensionVelocityVariable.globalValue)
        distanceVar.extendVariable(extensionVelocityVariable)

        advectionEquation.solve(distanceVar, dt = dt)

        catalystSurfactantEquation.solve(catalystVar, dt = dt)

        metalEquation.solve(metalVar, dt = dt)

        step += 1

    point = ((5e-09,), (1.15e-07,))
    value = 1.45346701e-09
    return abs(float(distanceVar(point, order=1)) - value) < cellSize / 10.0
Exemple #28
0
    dx = 1.
    dy = dx
    L = dx * nx
    mesh = Grid2D(dx=dx, dy=dy, nx=nx, ny=ny)

#We create a :class:`~fipy.variables.cellVariable.CellVariable` and initialize it to zero:
phi = CellVariable(name="solution variable", mesh=mesh, value=0.)
#and then create a diffusion equation.  This is solved by default with an
#iterative conjugate gradient solver.
D = 1.
eq = TransientTerm() == DiffusionTerm(coeff=D)

X, Y = mesh.faceCenters

if doBlob:
    phi.constrain([random.random() for x in X], mesh.exteriorFaces)

elif doCirc:

    phi.constrain(X, mesh.exteriorFaces)
else:
    #We apply Dirichlet boundary conditions
    valueTopLeft = 0
    valueBottomRight = 1
    #to the top-left and bottom-right corners.  Neumann boundary conditions
    #are automatically applied to the top-right and bottom-left corners.

    facesTopLeft = ((mesh.facesLeft & (Y > L / 2))
                    | (mesh.facesTop & (X < L / 2)))
    facesBottomRight = ((mesh.facesRight & (Y < L / 2))
                        | (mesh.facesBottom & (X > L / 2)))
Physical Surface("inner") = {{30, 26}};
Physical Surface("outer") = {{37}};
Physical Volume("volume") = {{1}};

'''.format(cellSize, l1, l2,
           math.tan(beta) * (l2 - l1), l3,
           math.tan(alpha) * l3)

mesh = Gmsh3D(geometryTemplate)

# Enthaelt die Temperatur
phi = CellVariable(name="Temperature", mesh=mesh, value=T0)

# boundry conditions ----------------------------------------------------------

phi.constrain(Ti, where=mesh.physicalFaces["inner"])
phi.constrain(Te, where=mesh.physicalFaces["outer"])

# calculation -----------------------------------------------------------------

viewer = Viewer(vars=phi, datamin=200., datamax=Te * 1.01)

print "Calculation started"
started = time.clock()

# Loest die Stationaere Waermegleichung
DiffusionTerm(coeff=D).solve(var=phi)

print "Calculation finished, took {} seconds".format(time.clock() - started)

viewer.plot()
# Continuity Equation
Pion_equation = TransientTerm(coeff=1., var=Pion) == mu_p_1 * ConvectionTerm(coeff=potential.faceGrad, var=Pion) + Dp_1 * DiffusionTerm(coeff=1., var=Pion) - k_rec * Pion * Nion
# In English:  dNion/dt = 1/q * divergence.Jn(x,t) - k_rec * Nion(x,t) * Pion(x,t)   where
#             Jn = q * mu_n * E(x,t) * Nion(x,t) - q * Dn * grad.Nion(x,t)         and     E(x,t) = -grad.potential(x,t)
# Continuity Equation
Nion_equation = TransientTerm(coeff=1., var=Nion) == -mu_n_1 * ConvectionTerm(coeff=potential.faceGrad, var=Nion) + Dn_1 * DiffusionTerm(coeff=1., var=Nion) - k_rec * Pion * Nion
# Electron_equation = TransientTerm(coeff=1., var=Electron) == -mu_n_2 * ConvectionTerm(coeff=potential.faceGrad, var=Electron) + Dn_2 * DiffusionTerm(coeff=1., var=Electron) - k_rec * Electron * Hole
# Hole_equation = TransientTerm(coeff=1., var=Hole) == mu_p_2 * ConvectionTerm(coeff=potential.faceGrad, var=Hole) + Dp_2 * DiffusionTerm(coeff=1., var=Hole) - k_rec * Electron * Hole
# In English:  d^2potential/dx^2 = -q/epsilon * Charge_Density      and     Charge Density= Pion-Nion
# Poisson's Equation
potential_equation = DiffusionTerm(coeff=1., var=potential) == -(q / epsilon) * (Pion - Nion)
# potential_equation = DiffusionTerm(coeff=1., var=potential) == -(q / epsilon) * (Pion - Nion + Hole - Electron)
### Boundary conditions ###
# Fipy is defaulted to be no-flux, so we only need to constrain potential

potential.constrain(0., where=mesh.exteriorFaces)

# potential.constrain(9., where=mesh.facesLeft)
# potential.constrain(0., where=mesh.facesRight)
# potential.constrain(0., where=mesh.exteriorFaces)
### Solve Equations in a coupled manner ###
eq = Pion_equation & Nion_equation & potential_equation


steps = 2000
timestep = 0.2

Efield_save = np.empty([nx, steps])
potential_save = np.empty_like(Efield_save)
# Pion_save = np.empty_like(Efield_save)
# Nion_save = np.empty_like(Efield_save)
Exemple #31
0
cfl = 0.01
velocity = 1.
timeStepDuration = cfl * dx / abs(velocity)
steps = 1000

mesh = Grid1D(dx = dx, nx = nx)

startingArray = numerix.zeros(nx, 'd')
startingArray[50:90] = 1.

var = CellVariable(
    name = "advection variable",
    mesh = mesh,
    value = startingArray)

var.constrain(valueLeft, mesh.facesLeft)
var.constrain(valueRight, mesh.facesRight)

eq = TransientTerm() - PowerLawConvectionTerm(coeff = (velocity,))

if __name__ == '__main__':

    viewer = Viewer(vars=(var,))
    viewer.plot()
    raw_input("press key to continue")
    for step in range(steps):
        eq.solve(var,
                 dt = timeStepDuration,
                 solver = LinearLUSolver(tolerance = 1.e-15))
        viewer.plot()
    viewer.plot()
Exemple #32
0
def runLeveler(kLeveler=0.018,
               bulkLevelerConcentration=0.02,
               cellSize=0.1e-7,
               rateConstant=0.00026,
               initialAcceleratorCoverage=0.0,
               levelerDiffusionCoefficient=5e-10,
               numberOfSteps=400,
               displayRate=10,
               displayViewers=True):


    kLevelerConsumption = 0.0005
    aspectRatio = 1.5
    faradaysConstant = 9.6485e4
    gasConstant = 8.314
    acceleratorDiffusionCoefficient = 4e-10
    siteDensity = 6.35e-6
    atomicVolume = 7.1e-6
    charge = 2
    metalDiffusionCoefficient = 4e-10
    temperature = 298.
    overpotential = -0.25
    bulkMetalConcentration = 250.
    bulkAcceleratorConcentration = 50.0e-3
    initialLevelerCoverage = 0.
    cflNumber = 0.2
    cellsBelowTrench = 10
    trenchDepth = 0.4e-6
    trenchSpacing = 0.6e-6
    boundaryLayerDepth = 98.7e-6
    i0Suppressor = 0.3
    i0Accelerator = 22.5
    alphaSuppressor = 0.5
    alphaAccelerator = 0.4
    alphaAdsorption = 0.62
    m = 4
    b = 2.65
    A = 0.3
    Ba = -40
    Bb = 60
    Vd = 0.098
    Bd = 0.0008

    etaPrime = faradaysConstant * overpotential / gasConstant / temperature

    mesh = TrenchMesh(cellSize = cellSize,
                      trenchSpacing = trenchSpacing,
                      trenchDepth = trenchDepth,
                      boundaryLayerDepth = boundaryLayerDepth,
                      aspectRatio = aspectRatio,
                      angle = numerix.pi * 4. / 180.)

    distanceVar = GapFillDistanceVariable(
        name = 'distance variable',
        mesh = mesh,
        value = -1.)

    distanceVar.setValue(1., where=mesh.electrolyteMask)

    distanceVar.calcDistanceFunction()
    levelerVar = SurfactantVariable(
        name = "leveler variable",
        value = initialLevelerCoverage,
        distanceVar = distanceVar)

    acceleratorVar = SurfactantVariable(
        name = "accelerator variable",
        value = initialAcceleratorCoverage,
        distanceVar = distanceVar)

    bulkAcceleratorVar = CellVariable(name = 'bulk accelerator variable',
                                      mesh = mesh,
                                      value = bulkAcceleratorConcentration)

    bulkLevelerVar = CellVariable(
        name = 'bulk leveler variable',
        mesh = mesh,
        value = bulkLevelerConcentration)

    metalVar = CellVariable(
        name = 'metal variable',
        mesh = mesh,
        value = bulkMetalConcentration)

    def depositionCoeff(alpha, i0):
        expo = numerix.exp(-alpha * etaPrime)
        return 2 * i0 * (expo - expo * numerix.exp(etaPrime))

    coeffSuppressor = depositionCoeff(alphaSuppressor, i0Suppressor)
    coeffAccelerator = depositionCoeff(alphaAccelerator, i0Accelerator)

    exchangeCurrentDensity = acceleratorVar.interfaceVar * (coeffAccelerator - coeffSuppressor) + coeffSuppressor

    currentDensity = metalVar / bulkMetalConcentration * exchangeCurrentDensity

    depositionRateVariable = currentDensity * atomicVolume / charge / faradaysConstant

    extensionVelocityVariable = CellVariable(
        name = 'extension velocity',
        mesh = mesh,
        value = depositionRateVariable)

    kAccelerator = rateConstant * numerix.exp(-alphaAdsorption * etaPrime)
    kAcceleratorConsumption =  Bd + A / (numerix.exp(Ba * (overpotential + Vd)) + numerix.exp(Bb * (overpotential + Vd)))
    q = m * overpotential + b

    levelerSurfactantEquation = AdsorbingSurfactantEquation(
        levelerVar,
        distanceVar = distanceVar,
        bulkVar = bulkLevelerVar,
        rateConstant = kLeveler,
        consumptionCoeff = kLevelerConsumption * depositionRateVariable)

    accVar1 = acceleratorVar.interfaceVar
    accVar2 = (accVar1 > 0) * accVar1
    accConsumptionCoeff = kAcceleratorConsumption * (accVar2**(q - 1))

    acceleratorSurfactantEquation = AdsorbingSurfactantEquation(
        acceleratorVar,
        distanceVar = distanceVar,
        bulkVar = bulkAcceleratorVar,
        rateConstant = kAccelerator,
        otherVar = levelerVar,
        otherBulkVar = bulkLevelerVar,
        otherRateConstant = kLeveler,
        consumptionCoeff = accConsumptionCoeff)

    advectionEquation = TransientTerm() + FirstOrderAdvectionTerm(extensionVelocityVariable)

    metalEquation = buildMetalIonDiffusionEquation(
        ionVar = metalVar,
        distanceVar = distanceVar,
        depositionRate = depositionRateVariable,
        diffusionCoeff = metalDiffusionCoefficient,
        metalIonMolarVolume = atomicVolume)

    metalVar.constrain(bulkMetalConcentration, mesh.facesTop)

    bulkAcceleratorEquation = buildSurfactantBulkDiffusionEquation(
        bulkVar = bulkAcceleratorVar,
        distanceVar = distanceVar,
        surfactantVar = acceleratorVar,
        otherSurfactantVar = levelerVar,
        diffusionCoeff = acceleratorDiffusionCoefficient,
        rateConstant = kAccelerator * siteDensity)

    bulkAcceleratorVar.constrain(bulkAcceleratorConcentration, mesh.facesTop)

    bulkLevelerEquation = buildSurfactantBulkDiffusionEquation(
        bulkVar = bulkLevelerVar,
        distanceVar = distanceVar,
        surfactantVar = levelerVar,
        diffusionCoeff = levelerDiffusionCoefficient,
        rateConstant = kLeveler * siteDensity)

    bulkLevelerVar.constrain(bulkLevelerConcentration, mesh.facesTop)

    eqnTuple = ( (advectionEquation, distanceVar, (), None),
                 (levelerSurfactantEquation, levelerVar, (), None),
                 (acceleratorSurfactantEquation, acceleratorVar, (), None),
                 (metalEquation, metalVar,  (), None),
                 (bulkAcceleratorEquation, bulkAcceleratorVar, (), GeneralSolver()),
                 (bulkLevelerEquation, bulkLevelerVar, (), GeneralSolver()))

    narrowBandWidth = 20 * cellSize
    levelSetUpdateFrequency = int(0.7 * narrowBandWidth / cellSize / cflNumber / 2)

    totalTime = 0.0

    if displayViewers:
        try:
            raise Exception
            from .mayaviSurfactantViewer import MayaviSurfactantViewer
            viewers = (
                MayaviSurfactantViewer(distanceVar, acceleratorVar.interfaceVar, zoomFactor = 1e6, datamax=0.5, datamin=0.0, smooth = 1, title = 'accelerator coverage'),
                MayaviSurfactantViewer(distanceVar, levelerVar.interfaceVar, zoomFactor = 1e6, datamax=0.5, datamin=0.0, smooth = 1, title = 'leveler coverage'))
        except:
            class PlotVariable(CellVariable):
                def __init__(self, var = None, name = ''):
                    CellVariable.__init__(self, mesh = mesh.fineMesh, name = name)
                    self.var = self._requires(var)

                def _calcValue(self):
                    return numerix.array(self.var(self.mesh.cellCenters))

            viewers = (Viewer(PlotVariable(var=acceleratorVar.interfaceVar)),
                       Viewer(PlotVariable(var=levelerVar.interfaceVar)))


    for step in range(numberOfSteps):

        if displayViewers:
            if step % displayRate == 0:
                for viewer in viewers:
                    viewer.plot()

        if step % levelSetUpdateFrequency == 0:
            distanceVar.calcDistanceFunction()

        extensionVelocityVariable.setValue(depositionRateVariable)

        extOnInt = numerix.where(distanceVar.globalValue > 0,
                                 numerix.where(distanceVar.globalValue < 2 * cellSize,
                                               extensionVelocityVariable.globalValue,
                                               0),
                                 0)

        dt = cflNumber * cellSize / extOnInt.max()

        distanceVar.extendVariable(extensionVelocityVariable)

        for eqn, var, BCs, solver in eqnTuple:
            eqn.solve(var, boundaryConditions = BCs, dt = dt, solver=solver)

        totalTime += dt

    point = ((1.25e-08,), (3.125e-07,))
    value = 2.02815779e-08
    return abs(float(distanceVar(point, order=1)) - value) < cellSize / 10.0