def __init__(self, dx = 1., dy = 1., nx = None, ny = None): Grid2D.__init__(self, dx = dx, dy = dy, nx = nx, ny = ny) self.nonPeriodicCellVertexIDs = Grid2D._getCellVertexIDs(self) self.nonPeriodicOrderedCellVertexIDs = Grid2D._getOrderedCellVertexIDs(self) from fipy.tools import numerix self._connectFaces(numerix.nonzero(self.getFacesBottom()), numerix.nonzero(self.getFacesTop()))
def __init__(self, dx = 1., nx = None): Grid1D.__init__(self, dx = dx, nx = nx) from fipy.tools import numerix if self.occupiedNodes == 1: self._connectFaces(numerix.nonzero(self.getFacesLeft()), numerix.nonzero(self.getFacesRight()))
def _calcInteriorAndExteriorCellIDs(self): try: import sets self.exteriorCellIDs = sets.Set(self.faceCellIDs[0, self.getExteriorFaces().getValue()]) self.interiorCellIDs = list(sets.Set(range(self.numberOfCells)) - self.exteriorCellIDs) self.exteriorCellIDs = list(self.exteriorCellIDs) except: self.exteriorCellIDs = self.faceCellIDs[0, self.getExteriorFaces().getValue()] tmp = numerix.zeros(self.numberOfCells) numerix.put(tmp, self.exteriorCellIDs, numerix.ones(len(self.exteriorCellIDs))) self.exteriorCellIDs = numerix.nonzero(tmp) self.interiorCellIDs = numerix.nonzero(numerix.logical_not(tmp))
def _calcInteriorAndExteriorCellIDs(self): try: import sys if sys.version_info < (2, 6): from sets import Set as set exteriorCellIDs = set(self.faceCellIDs[0, self._exteriorFaces.value]) interiorCellIDs = list(set(range(self.numberOfCells)) - self._exteriorCellIDs) exteriorCellIDs = list(self._exteriorCellIDs) except: exteriorCellIDs = self.faceCellIDs[0, self._exteriorFaces.value] tmp = numerix.zeros(self.numberOfCells, 'l') numerix.put(tmp, exteriorCellIDs, numerix.ones(len(exteriorCellIDs), 'l')) exteriorCellIDs = numerix.nonzero(tmp) interiorCellIDs = numerix.nonzero(numerix.logical_not(tmp)) return interiorCellIDs, exteriorCellIDs
def _getOldAdjacentValues(self, oldArray, id1, id2, dt): oldArray1, oldArray2 = ExplicitUpwindConvectionTerm._getOldAdjacentValues(self, oldArray, id1, id2, dt) mesh = oldArray.mesh interiorIDs = numerix.nonzero(mesh.interiorFaces)[0] interiorFaceAreas = numerix.take(mesh._faceAreas, interiorIDs) interiorFaceNormals = numerix.take(mesh._orientedFaceNormals, interiorIDs, axis=-1) # Courant-Friedrichs-Levy number interiorCFL = abs(numerix.take(self._getGeomCoeff(oldArray), interiorIDs)) * dt gradUpwind = (oldArray2 - oldArray1) / numerix.take(mesh._cellDistances, interiorIDs) vol1 = numerix.take(mesh.cellVolumes, id1) oldArray1 += 0.5 * self._getGradient(numerix.dot(numerix.take(oldArray.grad, id1, axis=-1), interiorFaceNormals), gradUpwind) \ * (vol1 - interiorCFL) / interiorFaceAreas vol2 = numerix.take(mesh.cellVolumes, id2) oldArray2 += 0.5 * self._getGradient(numerix.dot(numerix.take(oldArray.grad, id2, axis=-1), -interiorFaceNormals), -gradUpwind) \ * (vol2 - interiorCFL) / interiorFaceAreas return oldArray1, oldArray2
def _buildMatrix(self, var, SparseMatrix, boundaryConditions=(), dt=1., equation=None): """Implicit portion considers """ mesh = var.getMesh() id1, id2 = mesh._getAdjacentCellIDs() interiorFaces = numerix.nonzero(mesh.getInteriorFaces())[0] id1 = numerix.take(id1, interiorFaces) id2 = numerix.take(id2, interiorFaces) N = len(var) b = numerix.zeros((N),'d') L = SparseMatrix(size = N) if equation is not None: from fipy.tools.numerix import sign, add self._diagonalSign.setValue(sign(add.reduce(equation.matrix.takeDiagonal()))) else: self._diagonalSign.setValue(1) weight = self._getWeight(mesh, equation=equation) if weight.has_key('implicit'): self._implicitBuildMatrix(SparseMatrix, L, id1, id2, b, weight['implicit'], mesh, boundaryConditions, interiorFaces, dt) if weight.has_key('explicit'): self._explicitBuildMatrix(SparseMatrix, var.getOld(), id1, id2, b, weight['explicit'], mesh, boundaryConditions, interiorFaces, dt) return (L, b)
def _getOldAdjacentValues(self, oldArray, id1, id2, dt): oldArray1, oldArray2 = ExplicitUpwindConvectionTerm._getOldAdjacentValues(self, oldArray, id1, id2, dt) mesh = oldArray.getMesh() interiorIDs = numerix.nonzero(mesh.getInteriorFaces())[0] interiorFaceAreas = numerix.take(mesh._getFaceAreas(), interiorIDs) interiorFaceNormals = numerix.take(mesh._getOrientedFaceNormals(), interiorIDs, axis=-1) # Courant-Friedrichs-Levy number interiorCFL = abs(numerix.take(self._getGeomCoeff(mesh), interiorIDs)) * dt gradUpwind = (oldArray2 - oldArray1) / numerix.take(mesh._getCellDistances(), interiorIDs) vol1 = numerix.take(mesh.getCellVolumes(), id1) self.CFL = interiorCFL / vol1 oldArray1 += 0.5 * self._getGradient(numerix.dot(numerix.take(oldArray.getGrad(), id1, axis=-1), interiorFaceNormals), gradUpwind) \ * (vol1 - interiorCFL) / interiorFaceAreas vol2 = numerix.take(mesh.getCellVolumes(), id2) self.CFL = numerix.maximum(interiorCFL / vol2, self.CFL) oldArray2 += 0.5 * self._getGradient(numerix.dot(numerix.take(oldArray.getGrad(), id2, axis=-1), -interiorFaceNormals), -gradUpwind) \ * (vol2 - interiorCFL) / interiorFaceAreas return oldArray1, oldArray2
def _buildMatrix(self, var, SparseMatrix, boundaryConditions=(), dt=None, transientGeomCoeff=None, diffusionGeomCoeff=None): """Implicit portion considers """ mesh = var.mesh id1, id2 = mesh._adjacentCellIDs interiorFaces = numerix.nonzero(mesh.interiorFaces)[0] id1 = numerix.take(id1, interiorFaces) id2 = numerix.take(id2, interiorFaces) b = numerix.zeros(var.shape, 'd').ravel() L = SparseMatrix(mesh=mesh) weight = self._getWeight(var, transientGeomCoeff, diffusionGeomCoeff) if 'implicit' in weight: self._implicitBuildMatrix_(SparseMatrix, L, id1, id2, b, weight['implicit'], var, boundaryConditions, interiorFaces, dt) if 'explicit' in weight: self._explicitBuildMatrix_(SparseMatrix, var.old, id1, id2, b, weight['explicit'], var, boundaryConditions, interiorFaces, dt) return (var, L, b)
def __getCoefficientMatrix(self, SparseMatrix, var, coeff): mesh = var.mesh id1, id2 = mesh._adjacentCellIDs interiorFaces = numerix.nonzero(mesh.interiorFaces)[0] id1 = numerix.take(id1, interiorFaces) id2 = numerix.take(id2, interiorFaces) id1 = self._reshapeIDs(var, id1) id2 = self._reshapeIDs(var, id2) ## print 'id1',id1 ## print 'id2',id2 coefficientMatrix = SparseMatrix(mesh=mesh, bandwidth = mesh._maxFacesPerCell + 1) interiorCoeff = numerix.take(coeff, interiorFaces, axis=-1).ravel() coefficientMatrix.addAt(interiorCoeff, id1.ravel(), id1.swapaxes(0,1).ravel()) coefficientMatrix.addAt(-interiorCoeff, id1.ravel(), id2.swapaxes(0,1).ravel()) coefficientMatrix.addAt(-interiorCoeff, id2.ravel(), id1.swapaxes(0,1).ravel()) coefficientMatrix.addAt(interiorCoeff, id2.ravel(), id2.swapaxes(0,1).ravel()) ## print 'coefficientMatrix',coefficientMatrix ## raw_input('stopped') ## interiorCoeff = numerix.array(coeff) ## interiorCoeff[...,mesh.exteriorFaces.value] = 0 ## print 'interiorCoeff',interiorCoeff ## interiorCoeff = numerix.take(interiorCoeff, mesh.cellFaceIDs, axis=-1) ## ## print interiorCoeff.shape ## ## print interiorCoeff[:,:,0] ## ## print interiorCoeff[:,:,1] ## coefficientMatrix = SparseMatrix(mesh=mesh, bandwidth = mesh._maxFacesPerCell + 1) ## ## print 'numerix.sum(interiorCoeff, -2)',numerix.sum(interiorCoeff, -2) ## ## print numerix.sum(interiorCoeff, -2).ravel() ## ## raw_input('stopped') ## ## coefficientMatrix.addAtDiagonal(numerix.sum(interiorCoeff, -2).ravel()) ## ## print 'coefficientMatrix',coefficientMatrix ## del interiorCoeff ## interiorFaces = mesh.interiorFaceIDs ## interiorFaceCellIDs = mesh.interiorFaceCellIDs ## interiorCoeff = -numerix.take(coeff, interiorFaces, axis=-1) ## print 'interiorCoeff',interiorCoeff ## raw_input('stopped') ## coefficientMatrix.addAt(interiorCoeff, interiorFaceCellIDs[0], interiorFaceCellIDs[1]) ## interiorCoeff = -numerix.take(coeff, interiorFaces, axis=-1) ## coefficientMatrix.addAt(interiorCoeff, interiorFaceCellIDs[1], interiorFaceCellIDs[0]) return coefficientMatrix
def _makePeriodic(self): self._connectFaces(numerix.nonzero(self.facesLeft), numerix.nonzero(self.facesRight)) self._connectFaces(numerix.nonzero(self.facesBottom), numerix.nonzero(self.facesTop)) self._connectFaces(numerix.nonzero(self.facesFront), numerix.nonzero(self.facesBack))
def _getNonOrthogonality(self): exteriorFaceArray = numerix.zeros((self.faceCellIDs.shape[1],)) numerix.put(exteriorFaceArray, numerix.nonzero(self.getExteriorFaces()), 1) unmaskedFaceCellIDs = MA.filled(self.faceCellIDs, 0) ## what we put in for the "fill" doesn't matter because only exterior faces have anything masked, and exterior faces have their displacement vectors set to zero. ## if it's an exterior face, make the "displacement vector" equal to zero so the cross product will be zero. faceDisplacementVectors = numerix.where(numerix.array(zip(exteriorFaceArray, exteriorFaceArray)), 0.0, numerix.take(self._getCellCenters().swapaxes(0,1), unmaskedFaceCellIDs[1, :]) - numerix.take(self._getCellCenters().swapaxes(0,1), unmaskedFaceCellIDs[0, :])).swapaxes(0,1) faceCrossProducts = (faceDisplacementVectors[0, :] * self.faceNormals[1, :]) - (faceDisplacementVectors[1, :] * self.faceNormals[0, :]) faceDisplacementVectorLengths = numerix.maximum(((faceDisplacementVectors[0, :] ** 2) + (faceDisplacementVectors[1, :] ** 2)) ** 0.5, 1.e-100) faceWeightedNonOrthogonalities = abs(faceCrossProducts / faceDisplacementVectorLengths) * self.faceAreas cellFaceWeightedNonOrthogonalities = numerix.take(faceWeightedNonOrthogonalities, self.cellFaceIDs) cellFaceAreas = numerix.take(self.faceAreas, self.cellFaceIDs) cellTotalWeightedValues = numerix.add.reduce(cellFaceWeightedNonOrthogonalities, axis = 0) cellTotalFaceAreas = numerix.add.reduce(cellFaceAreas, axis = 0) return (cellTotalWeightedValues / cellTotalFaceAreas)
def prune(array, shift, start=0, axis=0): """ removes elements with indices i = start + shift * n where n = 0, 1, 2, ... >>> prune(numerix.arange(10), 3, 5) array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) >>> prune(numerix.arange(10), 3, 2) array([0, 1, 3, 4, 6, 7, 9]) >>> prune(numerix.arange(10), 3) array([1, 2, 4, 5, 7, 8]) >>> prune(numerix.arange(4, 7), 3) array([5, 6]) """ takeArray = numerix.nonzero(numerix.arange(array.shape[-1]) % shift != start)[0] return numerix.take(array, takeArray, axis=axis)
def _nonOrthogonality(self): exteriorFaceArray = numerix.zeros((self.faceCellIDs.shape[1], ), 'l') numerix.put(exteriorFaceArray, numerix.nonzero(self.exteriorFaces), 1) unmaskedFaceCellIDs = MA.filled(self.faceCellIDs, 0) # what we put in for the "fill" doesn't matter because only exterior # faces have anything masked, and exterior faces have their displacement # vectors set to zero. # # if it's an exterior face, make the "displacement vector" equal to zero # so the cross product will be zero. faceDisplacementVectors = \ numerix.where(numerix.array(zip(exteriorFaceArray, exteriorFaceArray)), 0.0, numerix.take(self._scaledCellCenters.swapaxes(0,1), unmaskedFaceCellIDs[1, :]) \ - numerix.take(self._scaledCellCenters.swapaxes(0,1), unmaskedFaceCellIDs[0, :])) faceDisplacementVectors = faceDisplacementVectors.swapaxes(0, 1) faceCrossProducts = (faceDisplacementVectors[0, :] * self.faceNormals[1,:]) \ - (faceDisplacementVectors[1, :] * self.faceNormals[0, :]) faceDisplacementVectorLengths = numerix.maximum(((faceDisplacementVectors[0, :] ** 2) \ + (faceDisplacementVectors[1, :] ** 2)) ** 0.5, 1.e-100) faceWeightedNonOrthogonalities = abs( faceCrossProducts / faceDisplacementVectorLengths) * self._faceAreas cellFaceWeightedNonOrthogonalities = numerix.take( faceWeightedNonOrthogonalities, self.cellFaceIDs) cellFaceAreas = numerix.take(self._faceAreas, self.cellFaceIDs) cellTotalWeightedValues = numerix.add.reduce( cellFaceWeightedNonOrthogonalities, axis=0) cellTotalFaceAreas = numerix.add.reduce(cellFaceAreas, axis=0) return (cellTotalWeightedValues / cellTotalFaceAreas)
def _getCoefficientMatrix(self, SparseMatrix, mesh, coeff): interiorCoeff = numerix.array(coeff) interiorCoeff[mesh.getExteriorFaces().getValue()] = 0 interiorCoeff = numerix.take(interiorCoeff, mesh._getCellFaceIDs()) coefficientMatrix = SparseMatrix(size = mesh.getNumberOfCells(), bandwidth = mesh._getMaxFacesPerCell()) coefficientMatrix.addAtDiagonal(numerix.sum(interiorCoeff, 0)) del interiorCoeff interiorFaces = numerix.nonzero(mesh.getInteriorFaces())[0] interiorFaceCellIDs = numerix.take(mesh.getFaceCellIDs(), interiorFaces, axis=1) interiorCoeff = -numerix.take(coeff, interiorFaces, axis=-1) coefficientMatrix.addAt(interiorCoeff, interiorFaceCellIDs[0], interiorFaceCellIDs[1]) interiorCoeff = -numerix.take(coeff, interiorFaces, axis=-1) coefficientMatrix.addAt(interiorCoeff, interiorFaceCellIDs[1], interiorFaceCellIDs[0]) return coefficientMatrix
def getCellIDsAboveFineRegion(self): return numerix.nonzero(self.getCellCenters()[1] > self.actualFineRegionHeight - self.cellSize)[0]
def _getStructure(self): ##maxX = self.distanceVar.mesh.faceCenters[0].max() ##minX = self.distanceVar.mesh.faceCenters[0].min() IDs = numerix.nonzero(self.distanceVar._cellInterfaceFlag)[0] coordinates = numerix.take(numerix.array(self.distanceVar.mesh.cellCenters).swapaxes(0, 1), IDs) coordinates -= numerix.take(numerix.array(self.distanceVar.grad * self.distanceVar).swapaxes(0, 1), IDs) coordinates *= self.zoomFactor shiftedCoords = coordinates.copy() shiftedCoords[:, 0] = -coordinates[:, 0] ##+ (maxX - minX) coordinates = numerix.concatenate((coordinates, shiftedCoords)) from .lines import _getOrderedLines lines = _getOrderedLines(list(range(2 * len(IDs))), coordinates, thresholdDistance = self.distanceVar.mesh._cellDistances.min() * 10) data = numerix.take(self.surfactantVar, IDs) data = numerix.concatenate((data, data)) tmpIDs = numerix.nonzero(data > 0.0001)[0] if len(tmpIDs) > 0: val = numerix.take(data, tmpIDs).min() else: val = 0.0001 data = numerix.where(data < 0.0001, val, data) for line in lines: if len(line) > 2: for smooth in range(self.smooth): for arr in (coordinates, data): tmp = numerix.take(arr, line) tmp[1:-1] = tmp[2:] * 0.25 + tmp[:-2] * 0.25 + tmp[1:-1] * 0.5 if len(arr.shape) > 1: for i in range(len(arr[0])): arrI = arr[:, i].copy() numerix.put(arrI, line, tmp[:, i]) arr[:, i] = arrI else: numerix.put(arrI, line, tmp) name = self.title name = name.strip() if name == '': name = None coords = numerix.zeros((coordinates.shape[0], 3), 'd') coords[:, :coordinates.shape[1]] = coordinates import pyvtk ## making lists as pyvtk doesn't know what to do with numpy arrays coords = list(coords) coords = [[float(coord[0]), float(coord[1]), float(coord[2])] for coord in coords] data = list(data) data = [float(item) for item in data] return (pyvtk.UnstructuredGrid(points = coords, poly_line = lines), pyvtk.PointData(pyvtk.Scalars(data, name = name)))
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 numberOfCellsInNarrowBand = 20 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 from fipy import TrenchMesh from fipy.tools import numerix mesh = TrenchMesh(cellSize=cellSize, trenchSpacing=trenchSpacing, trenchDepth=trenchDepth, boundaryLayerDepth=boundaryLayerDepth, aspectRatio=aspectRatio, angle=numerix.pi * 4. / 180., bowWidth=0., overBumpRadius=0., overBumpWidth=0.) narrowBandWidth = numberOfCellsInNarrowBand * cellSize from fipy.models.levelSet.distanceFunction.distanceVariable import DistanceVariable distanceVar = DistanceVariable(name='distance variable', mesh=mesh, value=-1, narrowBandWidth=narrowBandWidth) distanceVar.setValue(1, where=mesh.getElectrolyteMask()) distanceVar.calcDistanceFunction(narrowBandWidth=1e10) from fipy.models.levelSet.surfactant.surfactantVariable import SurfactantVariable levelerVar = SurfactantVariable(name="leveler variable", value=initialLevelerCoverage, distanceVar=distanceVar) acceleratorVar = SurfactantVariable(name="accelerator variable", value=initialAcceleratorCoverage, distanceVar=distanceVar) from fipy.variables.cellVariable import CellVariable 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.getInterfaceVar() * ( coeffAccelerator - coeffSuppressor) + coeffSuppressor currentDensity = metalVar / bulkMetalConcentration * exchangeCurrentDensity depositionRateVariable = currentDensity * atomicVolume / charge / faradaysConstant extensionVelocityVariable = CellVariable(name='extension velocity', mesh=mesh, value=depositionRateVariable) from fipy.models.levelSet.surfactant.adsorbingSurfactantEquation \ import AdsorbingSurfactantEquation 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.getInterfaceVar() 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) from fipy.models.levelSet.advection.higherOrderAdvectionEquation \ import buildHigherOrderAdvectionEquation advectionEquation = buildHigherOrderAdvectionEquation( advectionCoeff=extensionVelocityVariable) from fipy.boundaryConditions.fixedValue import FixedValue from fipy.models.levelSet.electroChem.metalIonDiffusionEquation \ import buildMetalIonDiffusionEquation metalEquation = buildMetalIonDiffusionEquation( ionVar=metalVar, distanceVar=distanceVar, depositionRate=depositionRateVariable, diffusionCoeff=metalDiffusionCoefficient, metalIonMolarVolume=atomicVolume) metalEquationBCs = FixedValue(mesh.getTopFaces(), bulkMetalConcentration) from fipy.models.levelSet.surfactant.surfactantBulkDiffusionEquation \ import buildSurfactantBulkDiffusionEquation bulkAcceleratorEquation = buildSurfactantBulkDiffusionEquation( bulkVar=bulkAcceleratorVar, distanceVar=distanceVar, surfactantVar=acceleratorVar, otherSurfactantVar=levelerVar, diffusionCoeff=acceleratorDiffusionCoefficient, rateConstant=kAccelerator * siteDensity) bulkAcceleratorEquationBCs = (FixedValue(mesh.getTopFaces(), bulkAcceleratorConcentration), ) bulkLevelerEquation = buildSurfactantBulkDiffusionEquation( bulkVar=bulkLevelerVar, distanceVar=distanceVar, surfactantVar=levelerVar, diffusionCoeff=levelerDiffusionCoefficient, rateConstant=kLeveler * siteDensity) bulkLevelerEquationBCs = (FixedValue(mesh.getTopFaces(), bulkLevelerConcentration), ) eqnTuple = ((advectionEquation, distanceVar, ()), (levelerSurfactantEquation, levelerVar, ()), (acceleratorSurfactantEquation, acceleratorVar, ()), (metalEquation, metalVar, metalEquationBCs), (bulkAcceleratorEquation, bulkAcceleratorVar, bulkAcceleratorEquationBCs), (bulkLevelerEquation, bulkLevelerVar, bulkLevelerEquationBCs)) levelSetUpdateFrequency = int(0.7 * narrowBandWidth / cellSize / cflNumber / 2) totalTime = 0.0 if displayViewers: from fipy.viewers.mayaviViewer.mayaviSurfactantViewer import MayaviSurfactantViewer viewers = (MayaviSurfactantViewer(distanceVar, acceleratorVar.getInterfaceVar(), zoomFactor=1e6, limits={ 'datamax': 0.5, 'datamin': 0.0 }, smooth=1, title='accelerator coverage'), MayaviSurfactantViewer(distanceVar, levelerVar.getInterfaceVar(), zoomFactor=1e6, limits={ 'datamax': 0.5, 'datamin': 0.0 }, smooth=1, title='leveler coverage')) for step in range(numberOfSteps): if displayViewers: if step % displayRate == 0: for viewer in viewers: viewer.plot() if step % levelSetUpdateFrequency == 0: distanceVar.calcDistanceFunction(deleteIslands=True) extensionVelocityVariable.setValue(depositionRateVariable) extOnInt = numerix.where( distanceVar > 0, numerix.where(distanceVar < 2 * cellSize, extensionVelocityVariable, 0), 0) dt = cflNumber * cellSize / numerix.max(extOnInt) id = numerix.max(numerix.nonzero(distanceVar._getInterfaceFlag())) distanceVar.extendVariable(extensionVelocityVariable, deleteIslands=True) extensionVelocityVariable[mesh.getFineMesh().getNumberOfCells():] = 0. for eqn, var, BCs in eqnTuple: var.updateOld() for eqn, var, BCs in eqnTuple: eqn.solve(var, boundaryConditions=BCs, dt=dt) totalTime += dt try: testFile = 'testLeveler.gz' import os import examples.levelSet.electroChem from fipy.tools import dump data = dump.read( os.path.join(examples.levelSet.electroChem.__path__[0], testFile)) N = mesh.getFineMesh().getNumberOfCells() print numerix.allclose(data[:N], levelerVar[:N], rtol=1e-3) except: return 0
def _getStructure(self): ##maxX = self.distanceVar.mesh.faceCenters[0].max() ##minX = self.distanceVar.mesh.faceCenters[0].min() IDs = numerix.nonzero(self.distanceVar._cellInterfaceFlag)[0] coordinates = numerix.take( numerix.array(self.distanceVar.mesh.cellCenters).swapaxes(0, 1), IDs) coordinates -= numerix.take( numerix.array(self.distanceVar.grad * self.distanceVar).swapaxes( 0, 1), IDs) coordinates *= self.zoomFactor shiftedCoords = coordinates.copy() shiftedCoords[:, 0] = -coordinates[:, 0] ##+ (maxX - minX) coordinates = numerix.concatenate((coordinates, shiftedCoords)) from lines import _getOrderedLines lines = _getOrderedLines( range(2 * len(IDs)), coordinates, thresholdDistance=self.distanceVar.mesh._cellDistances.min() * 10) data = numerix.take(self.surfactantVar, IDs) data = numerix.concatenate((data, data)) tmpIDs = numerix.nonzero(data > 0.0001)[0] if len(tmpIDs) > 0: val = numerix.take(data, tmpIDs).min() else: val = 0.0001 data = numerix.where(data < 0.0001, val, data) for line in lines: if len(line) > 2: for smooth in range(self.smooth): for arr in (coordinates, data): tmp = numerix.take(arr, line) tmp[1:-1] = tmp[2:] * 0.25 + tmp[:-2] * 0.25 + tmp[ 1:-1] * 0.5 if len(arr.shape) > 1: for i in range(len(arr[0])): arrI = arr[:, i].copy() numerix.put(arrI, line, tmp[:, i]) arr[:, i] = arrI else: numerix.put(arrI, line, tmp) name = self.title name = name.strip() if name == '': name = None coords = numerix.zeros((coordinates.shape[0], 3), 'd') coords[:, :coordinates.shape[1]] = coordinates import pyvtk ## making lists as pyvtk doesn't know what to do with numpy arrays coords = list(coords) coords = map( lambda coord: [float(coord[0]), float(coord[1]), float(coord[2])], coords) data = list(data) data = map(lambda item: float(item), data) return (pyvtk.UnstructuredGrid(points=coords, poly_line=lines), pyvtk.PointData(pyvtk.Scalars(data, name=name)))
def _makePeriodic(self): self._connectFaces(numerix.nonzero(self.facesBottom), numerix.nonzero(self.facesTop))
def _makePeriodic(self): self._connectFaces(numerix.nonzero(self.facesFront), numerix.nonzero(self.facesBack))
def _makePeriodic(self): if self.occupiedNodes == 1: self._connectFaces(numerix.nonzero(self.facesLeft), numerix.nonzero(self.facesRight))
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 numberOfCellsInNarrowBand = 20 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 from fipy import TrenchMesh from fipy.tools import numerix mesh = TrenchMesh(cellSize = cellSize, trenchSpacing = trenchSpacing, trenchDepth = trenchDepth, boundaryLayerDepth = boundaryLayerDepth, aspectRatio = aspectRatio, angle = numerix.pi * 4. / 180., bowWidth = 0., overBumpRadius = 0., overBumpWidth = 0.) narrowBandWidth = numberOfCellsInNarrowBand * cellSize from fipy.models.levelSet.distanceFunction.distanceVariable import DistanceVariable distanceVar = DistanceVariable( name = 'distance variable', mesh = mesh, value = -1, narrowBandWidth = narrowBandWidth) distanceVar.setValue(1, where=mesh.getElectrolyteMask()) distanceVar.calcDistanceFunction(narrowBandWidth = 1e10) from fipy.models.levelSet.surfactant.surfactantVariable import SurfactantVariable levelerVar = SurfactantVariable( name = "leveler variable", value = initialLevelerCoverage, distanceVar = distanceVar) acceleratorVar = SurfactantVariable( name = "accelerator variable", value = initialAcceleratorCoverage, distanceVar = distanceVar) from fipy.variables.cellVariable import CellVariable 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.getInterfaceVar() * (coeffAccelerator - coeffSuppressor) + coeffSuppressor currentDensity = metalVar / bulkMetalConcentration * exchangeCurrentDensity depositionRateVariable = currentDensity * atomicVolume / charge / faradaysConstant extensionVelocityVariable = CellVariable( name = 'extension velocity', mesh = mesh, value = depositionRateVariable) from fipy.models.levelSet.surfactant.adsorbingSurfactantEquation \ import AdsorbingSurfactantEquation 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.getInterfaceVar() 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) from fipy.models.levelSet.advection.higherOrderAdvectionEquation \ import buildHigherOrderAdvectionEquation advectionEquation = buildHigherOrderAdvectionEquation( advectionCoeff = extensionVelocityVariable) from fipy.boundaryConditions.fixedValue import FixedValue from fipy.models.levelSet.electroChem.metalIonDiffusionEquation \ import buildMetalIonDiffusionEquation metalEquation = buildMetalIonDiffusionEquation( ionVar = metalVar, distanceVar = distanceVar, depositionRate = depositionRateVariable, diffusionCoeff = metalDiffusionCoefficient, metalIonMolarVolume = atomicVolume) metalEquationBCs = FixedValue(mesh.getTopFaces(), bulkMetalConcentration) from fipy.models.levelSet.surfactant.surfactantBulkDiffusionEquation \ import buildSurfactantBulkDiffusionEquation bulkAcceleratorEquation = buildSurfactantBulkDiffusionEquation( bulkVar = bulkAcceleratorVar, distanceVar = distanceVar, surfactantVar = acceleratorVar, otherSurfactantVar = levelerVar, diffusionCoeff = acceleratorDiffusionCoefficient, rateConstant = kAccelerator * siteDensity) bulkAcceleratorEquationBCs = (FixedValue( mesh.getTopFaces(), bulkAcceleratorConcentration),) bulkLevelerEquation = buildSurfactantBulkDiffusionEquation( bulkVar = bulkLevelerVar, distanceVar = distanceVar, surfactantVar = levelerVar, diffusionCoeff = levelerDiffusionCoefficient, rateConstant = kLeveler * siteDensity) bulkLevelerEquationBCs = (FixedValue( mesh.getTopFaces(), bulkLevelerConcentration),) eqnTuple = ( (advectionEquation, distanceVar, ()), (levelerSurfactantEquation, levelerVar, ()), (acceleratorSurfactantEquation, acceleratorVar, ()), (metalEquation, metalVar, metalEquationBCs), (bulkAcceleratorEquation, bulkAcceleratorVar, bulkAcceleratorEquationBCs), (bulkLevelerEquation, bulkLevelerVar, bulkLevelerEquationBCs)) levelSetUpdateFrequency = int(0.7 * narrowBandWidth / cellSize / cflNumber / 2) totalTime = 0.0 if displayViewers: from fipy.viewers.mayaviViewer.mayaviSurfactantViewer import MayaviSurfactantViewer viewers = ( MayaviSurfactantViewer(distanceVar, acceleratorVar.getInterfaceVar(), zoomFactor = 1e6, limits = { 'datamax' : 0.5, 'datamin' : 0.0 }, smooth = 1, title = 'accelerator coverage'), MayaviSurfactantViewer(distanceVar, levelerVar.getInterfaceVar(), zoomFactor = 1e6, limits = { 'datamax' : 0.5, 'datamin' : 0.0 }, smooth = 1, title = 'leveler coverage')) for step in range(numberOfSteps): if displayViewers: if step % displayRate == 0: for viewer in viewers: viewer.plot() if step % levelSetUpdateFrequency == 0: distanceVar.calcDistanceFunction(deleteIslands = True) extensionVelocityVariable.setValue(depositionRateVariable) extOnInt = numerix.where(distanceVar > 0, numerix.where(distanceVar < 2 * cellSize, extensionVelocityVariable, 0), 0) dt = cflNumber * cellSize / numerix.max(extOnInt) id = numerix.max(numerix.nonzero(distanceVar._getInterfaceFlag())) distanceVar.extendVariable(extensionVelocityVariable, deleteIslands = True) extensionVelocityVariable[mesh.getFineMesh().getNumberOfCells():] = 0. for eqn, var, BCs in eqnTuple: var.updateOld() for eqn, var, BCs in eqnTuple: eqn.solve(var, boundaryConditions = BCs, dt = dt) totalTime += dt try: testFile = 'testLeveler.gz' import os import examples.levelSet.electroChem from fipy.tools import dump data = dump.read(os.path.join(examples.levelSet.electroChem.__path__[0], testFile)) N = mesh.getFineMesh().getNumberOfCells() print numerix.allclose(data[:N], levelerVar[:N], rtol = 1e-3) except: return 0
def _makePeriodic(self): self._connectFaces(numerix.nonzero(self.facesLeft), numerix.nonzero(self.facesRight))
def _calcDistanceFunction(self, extensionVariable = None, narrowBandWidth = None, deleteIslands = False): if narrowBandWidth == None: narrowBandWidth = self.narrowBandWidth ## calculate interface values cellToCellIDs = self.mesh._getCellToCellIDs() if deleteIslands: adjVals = numerix.take(self.value, cellToCellIDs) adjInterfaceValues = MA.masked_array(adjVals, mask = (adjVals * self.value) > 0) masksum = numerix.sum(numerix.logical_not(MA.getmask(adjInterfaceValues)), 0) tmp = MA.logical_and(masksum == 4, self.value > 0) self.value = MA.where(tmp, -1, self.value) adjVals = numerix.take(self.value, cellToCellIDs) adjInterfaceValues = MA.masked_array(adjVals, mask = (adjVals * self.value) > 0) dAP = self.mesh._getCellToCellDistances() distances = abs(self.value * dAP / (self.value - adjInterfaceValues)) indices = MA.argsort(distances, 0) sign = (self.value > 0) * 2 - 1 s = distances[indices[0], numerix.arange(indices.shape[1])] if self.mesh.getDim() == 2: t = distances[indices[1], numerix.arange(indices.shape[1])] u = distances[indices[2], numerix.arange(indices.shape[1])] if indices.shape[1] > 0: ns = self.cellNormals[..., indices[0], numerix.arange(indices.shape[1])] nt = self.cellNormals[..., indices[1], numerix.arange(indices.shape[1])] else: ns = MA.zeros(self.cellNormals.shape[:-1] + (0,)) nt = MA.zeros(self.cellNormals.shape[:-1] + (0,)) signedDistance = MA.where(MA.getmask(s), self.value, MA.where(MA.getmask(t), sign * s, MA.where(abs(numerix.dot(ns,nt)) < 0.9, sign * s * t / MA.sqrt(s**2 + t**2), MA.where(MA.getmask(u), sign * s, sign * s * u / MA.sqrt(s**2 + u**2) ) ) ) ) else: signedDistance = MA.where(MA.getmask(s), self.value, sign * s) self.value = signedDistance ## calculate interface flag masksum = numerix.sum(numerix.logical_not(MA.getmask(distances)), 0) interfaceFlag = (masksum > 0).astype('l') ## spread the extensionVariable to the whole interface flag = True if extensionVariable is None: extensionVariable = numerix.zeros(self.mesh.getNumberOfCells(), 'd') flag = False ext = numerix.zeros(self.mesh.getNumberOfCells(), 'd') positiveInterfaceFlag = numerix.where(self.value > 0, interfaceFlag, 0) negativeInterfaceIDs = numerix.nonzero(numerix.where(self.value < 0, interfaceFlag, 0))[0] for id in negativeInterfaceIDs: tmp, extensionVariable[...,id] = self._calcTrialValue(id, positiveInterfaceFlag, extensionVariable) if flag: self.value = self.tmpValue.copy() ## evaluate the trialIDs adjInterfaceFlag = numerix.take(interfaceFlag, cellToCellIDs) hasAdjInterface = (numerix.sum(MA.filled(adjInterfaceFlag, 0), 0) > 0).astype('l') trialFlag = numerix.logical_and(numerix.logical_not(interfaceFlag), hasAdjInterface).astype('l') trialIDs = list(numerix.nonzero(trialFlag)[0]) evaluatedFlag = interfaceFlag for id in trialIDs: self.value[...,id], extensionVariable[id] = self._calcTrialValue(id, evaluatedFlag, extensionVariable) while len(trialIDs): id = trialIDs[numerix.argmin(abs(numerix.take(self.value, trialIDs)))] if abs(self.value[...,id]) > narrowBandWidth / 2: break trialIDs.remove(id) evaluatedFlag[...,id] = 1 for adjID in MA.filled(cellToCellIDs[...,id], -1): if adjID != -1: if not evaluatedFlag[...,adjID]: self.value[...,adjID], extensionVariable[...,adjID] = self._calcTrialValue(adjID, evaluatedFlag, extensionVariable) if adjID not in trialIDs: trialIDs.append(adjID) self.value = numerix.array(self.value)
def interiorFaceIDs(self): if not hasattr(self, '_interiorFaceIDs'): self._interiorFaceIDs = numerix.nonzero(self.interiorFaces)[0] return self._interiorFaceIDs
def __getCoefficientMatrix(self, SparseMatrix, var, coeff): mesh = var.mesh id1, id2 = mesh._adjacentCellIDs interiorFaces = numerix.nonzero(mesh.interiorFaces)[0] id1 = numerix.take(id1, interiorFaces) id2 = numerix.take(id2, interiorFaces) id1 = self._reshapeIDs(var, id1) id2 = self._reshapeIDs(var, id2) ## print 'id1',id1 ## print 'id2',id2 coefficientMatrix = SparseMatrix(mesh=mesh, bandwidth=mesh._maxFacesPerCell + 1) interiorCoeff = numerix.take(coeff, interiorFaces, axis=-1).ravel() coefficientMatrix.addAt(interiorCoeff, id1.ravel(), id1.swapaxes(0, 1).ravel()) coefficientMatrix.addAt(-interiorCoeff, id1.ravel(), id2.swapaxes(0, 1).ravel()) coefficientMatrix.addAt(-interiorCoeff, id2.ravel(), id1.swapaxes(0, 1).ravel()) coefficientMatrix.addAt(interiorCoeff, id2.ravel(), id2.swapaxes(0, 1).ravel()) ## print 'coefficientMatrix',coefficientMatrix ## raw_input('stopped') ## interiorCoeff = numerix.array(coeff) ## interiorCoeff[...,mesh.exteriorFaces.value] = 0 ## print 'interiorCoeff',interiorCoeff ## interiorCoeff = numerix.take(interiorCoeff, mesh.cellFaceIDs, axis=-1) ## ## print interiorCoeff.shape ## ## print interiorCoeff[:,:,0] ## ## print interiorCoeff[:,:,1] ## coefficientMatrix = SparseMatrix(mesh=mesh, bandwidth = mesh._maxFacesPerCell + 1) ## ## print 'numerix.sum(interiorCoeff, -2)',numerix.sum(interiorCoeff, -2) ## ## print numerix.sum(interiorCoeff, -2).ravel() ## ## raw_input('stopped') ## ## coefficientMatrix.addAtDiagonal(numerix.sum(interiorCoeff, -2).ravel()) ## ## print 'coefficientMatrix',coefficientMatrix ## del interiorCoeff ## interiorFaces = mesh.interiorFaceIDs ## interiorFaceCellIDs = mesh.interiorFaceCellIDs ## interiorCoeff = -numerix.take(coeff, interiorFaces, axis=-1) ## print 'interiorCoeff',interiorCoeff ## raw_input('stopped') ## coefficientMatrix.addAt(interiorCoeff, interiorFaceCellIDs[0], interiorFaceCellIDs[1]) ## interiorCoeff = -numerix.take(coeff, interiorFaces, axis=-1) ## coefficientMatrix.addAt(interiorCoeff, interiorFaceCellIDs[1], interiorFaceCellIDs[0]) return coefficientMatrix