def _solve_(self, L, x, b): diag = L.takeDiagonal() maxdiag = max(numerix.absolute(diag)) L = L * (1 / maxdiag) b = b * (1 / maxdiag) LU = superlu.factorize(L.matrix.to_csr()) if DEBUG: import sys print >> sys.stderr, L.matrix error0 = numerix.sqrt(numerix.sum((L * x - b)**2)) for iteration in range(self.iterations): errorVector = L * x - b if (numerix.sqrt(numerix.sum(errorVector**2)) / error0) <= self.tolerance: break xError = numerix.zeros(len(b),'d') LU.solve(errorVector, xError) x[:] = x - xError if 'FIPY_VERBOSE_SOLVER' in os.environ: from fipy.tools.debug import PRINT PRINT('iterations: %d / %d' % (iteration+1, self.iterations)) PRINT('residual:', numerix.sqrt(numerix.sum(errorVector**2)))
def _solve_(self, L, x, b): diag = L.takeDiagonal() maxdiag = max(numerix.absolute(diag)) L = L * (1 / maxdiag) b = b * (1 / maxdiag) LU = superlu.factorize(L.matrix.to_csr()) if DEBUG: import sys print(L.matrix, file=sys.stderr) error0 = numerix.sqrt(numerix.sum((L * x - b)**2)) for iteration in range(self.iterations): errorVector = L * x - b if (numerix.sqrt(numerix.sum(errorVector**2)) / error0) <= self.tolerance: break xError = numerix.zeros(len(b), 'd') LU.solve(errorVector, xError) x[:] = x - xError if 'FIPY_VERBOSE_SOLVER' in os.environ: from fipy.tools.debug import PRINT PRINT('iterations: %d / %d' % (iteration+1, self.iterations)) PRINT('residual:', numerix.sqrt(numerix.sum(errorVector**2)))
def _solve_(self, L, x, b): diag = L.takeDiagonal() maxdiag = max(numerix.absolute(diag)) L = L * (1 / maxdiag) b = b * (1 / maxdiag) LU = splu(L.matrix.asformat("csc"), diag_pivot_thresh=1., relax=1, panel_size=10, permc_spec=3) error0 = numerix.sqrt(numerix.sum((L * x - b)**2)) for iteration in range(min(self.iterations, 10)): errorVector = L * x - b if (numerix.sqrt(numerix.sum(errorVector**2)) / error0) <= self.tolerance: break xError = LU.solve(errorVector) x[:] = x - xError if 'FIPY_VERBOSE_SOLVER' in os.environ: from fipy.tools.debug import PRINT PRINT('iterations: %d / %d' % (iteration+1, self.iterations)) PRINT('residual:', numerix.sqrt(numerix.sum(errorVector**2))) return x
def _buildMatrix(self, var, SparseMatrix, boundaryCondtions=(), dt=None, equation=None): oldArray = var.getOld() mesh = var.getMesh() NCells = mesh.getNumberOfCells() NCellFaces = mesh._getMaxFacesPerCell() cellValues = numerix.repeat(oldArray[numerix.newaxis, ...], NCellFaces, axis = 0) cellIDs = numerix.repeat(numerix.arange(NCells)[numerix.newaxis, ...], NCellFaces, axis = 0) cellToCellIDs = mesh._getCellToCellIDs() if NCells > 0: cellToCellIDs = MA.where(MA.getmask(cellToCellIDs), cellIDs, cellToCellIDs) adjacentValues = numerix.take(oldArray, cellToCellIDs) differences = self._getDifferences(adjacentValues, cellValues, oldArray, cellToCellIDs, mesh) differences = MA.filled(differences, 0) minsq = numerix.sqrt(numerix.sum(numerix.minimum(differences, numerix.zeros((NCellFaces, NCells)))**2, axis=0)) maxsq = numerix.sqrt(numerix.sum(numerix.maximum(differences, numerix.zeros((NCellFaces, NCells)))**2, axis=0)) coeff = numerix.array(self._getGeomCoeff(mesh)) coeffXdiffereneces = coeff * ((coeff > 0.) * minsq + (coeff < 0.) * maxsq) else: coeffXdiffereneces = 0. return (SparseMatrix(mesh=var.getMesh()), -coeffXdiffereneces * mesh.getCellVolumes())
def _buildMatrix(self, var, SparseMatrix, boundaryConditions=(), dt=None, equation=None, transientGeomCoeff=None, diffusionGeomCoeff=None): oldArray = var.old mesh = var.mesh NCells = mesh.numberOfCells NCellFaces = mesh._maxFacesPerCell cellValues = numerix.repeat(oldArray[numerix.newaxis, ...], NCellFaces, axis = 0) cellIDs = numerix.repeat(numerix.arange(NCells)[numerix.newaxis, ...], NCellFaces, axis = 0) cellToCellIDs = mesh._cellToCellIDs if NCells > 0: cellToCellIDs = MA.where(MA.getmask(cellToCellIDs), cellIDs, cellToCellIDs) adjacentValues = numerix.take(oldArray, cellToCellIDs) differences = self._getDifferences(adjacentValues, cellValues, oldArray, cellToCellIDs, mesh) differences = MA.filled(differences, 0) minsq = numerix.sqrt(numerix.sum(numerix.minimum(differences, numerix.zeros((NCellFaces, NCells), 'l'))**2, axis=0)) maxsq = numerix.sqrt(numerix.sum(numerix.maximum(differences, numerix.zeros((NCellFaces, NCells), 'l'))**2, axis=0)) coeff = numerix.array(self._getGeomCoeff(var)) coeffXdiffereneces = coeff * ((coeff > 0.) * minsq + (coeff < 0.) * maxsq) else: coeffXdiffereneces = 0. return (var, SparseMatrix(mesh=var.mesh), -coeffXdiffereneces * mesh.cellVolumes)
def _buildMatrix(self, var, SparseMatrix, boundaryConditions=(), dt=None, equation=None, transientGeomCoeff=None, diffusionGeomCoeff=None): oldArray = var.old mesh = var.mesh NCells = mesh.numberOfCells NCellFaces = mesh._maxFacesPerCell cellValues = numerix.repeat(oldArray[numerix.newaxis, ...], NCellFaces, axis = 0) cellIDs = numerix.repeat(numerix.arange(NCells)[numerix.newaxis, ...], NCellFaces, axis = 0) cellToCellIDs = mesh._cellToCellIDs if NCells > 0: cellToCellIDs = MA.where(MA.getmask(cellToCellIDs), cellIDs, cellToCellIDs) adjacentValues = numerix.take(oldArray, cellToCellIDs) differences = self._getDifferences(adjacentValues, cellValues, oldArray, cellToCellIDs, mesh) differences = MA.filled(differences, 0) minsq = numerix.sqrt(numerix.sum(numerix.minimum(differences, numerix.zeros((NCellFaces, NCells), 'l'))**2, axis=0)) maxsq = numerix.sqrt(numerix.sum(numerix.maximum(differences, numerix.zeros((NCellFaces, NCells), 'l'))**2, axis=0)) coeff = numerix.array(self._getGeomCoeff(var)) coeffXdifferences = coeff * ((coeff > 0.) * minsq + (coeff < 0.) * maxsq) else: coeffXdifferences = 0. return (var, SparseMatrix(mesh=var.mesh), -coeffXdifferences * mesh.cellVolumes)
def _solve_(self, L, x, b): diag = L.takeDiagonal() maxdiag = max(numerix.absolute(diag)) L = L * (1 / maxdiag) b = b * (1 / maxdiag) LU = splu(L.matrix.asformat("csc"), diag_pivot_thresh=1., drop_tol=0., relax=1, panel_size=10, permc_spec=3) error0 = numerix.sqrt(numerix.sum((L * x - b)**2)) for iteration in range(min(self.iterations, 10)): errorVector = L * x - b if (numerix.sqrt(numerix.sum(errorVector**2)) / error0) <= self.tolerance: break xError = LU.solve(errorVector) x[:] = x - xError if 'FIPY_VERBOSE_SOLVER' in os.environ: from fipy.tools.debug import PRINT PRINT('iterations: %d / %d' % (iteration + 1, self.iterations)) PRINT('residual:', numerix.sqrt(numerix.sum(errorVector**2))) return x
def _calcValue(self): flag = MA.filled( numerix.take(self.distanceVar._interfaceFlag, self.mesh.cellFaceIDs), 0) flag = numerix.sum(flag, axis=0) return numerix.where( numerix.logical_and(self.distanceVar.value > 0, flag > 0), 1, 0)
def _calcValuePy(self): ids = self.mesh._getCellFaceIDs() contributions = numerix.take(self.faceVariable, ids) # FIXME: numerix.MA.filled casts away dimensions return numerix.MA.filled(numerix.sum(contributions * self.mesh._getCellFaceOrientations(), 0)) / self.mesh.getCellVolumes()
def cellCenters(self): """Defined outside of a geometry class since we need the `CellVariable` version of `cellCenters`; that is, the `cellCenters` defined in fipy.meshes.mesh and not in any geometry (since a `CellVariable` requires a reference to a mesh).""" return super(PeriodicGrid1D, self).cellCenters \ % numerix.sum(self.globalNumberOfCells * self.args['dx'])
def _ao(self): """Application Ordering to relate FiPy matrix rows to PETSc matrix rows FiPy naturally blocks matrix rows, one set of Equations (or Variables) at a time. PETSc requires that all rows pertaining to a particular MPI node be contiguous. This PETSc `AO` (Application Ordering) object converts between them. Only needed for FiPy to PETSc. We can efficiently slice from PETSc to FiPy, but PETSc requires us to know the row IDs. """ if not hasattr(self, "_ao_"): comm = self.mesh.communicator from mpi4py import MPI fipyIDs = self._globalNonOverlappingColIDs N = len(fipyIDs) count = numerix.zeros((comm.Nproc, ), dtype=int) count[comm.procID] = N comm.mpi4py_comm.Allreduce(sendbuf=MPI.IN_PLACE, recvbuf=count, op=MPI.MAX) petscIDs = numerix.arange(N) + numerix.sum(count[:comm.procID]) self._ao_ = PETSc.AO().createBasic(petsc=petscIDs.astype('int32'), app=fipyIDs.astype('int32'), comm=comm.petsc4py_comm) return self._ao_
def __init__(self, dx=1., nx=None, overlap=2, communicator=parallel): self.args = { 'dx': dx, 'nx': nx, 'overlap': overlap } from fipy.tools.dimensions.physicalField import PhysicalField self.dx = PhysicalField(value=dx) scale = PhysicalField(value=1, unit=self.dx.getUnit()) self.dx /= scale nx = self._calcNumPts(d=self.dx, n=nx) (self.nx, self.overlap, self.offset) = self._calcParallelGridInfo(nx, overlap, communicator) if numerix.getShape(self.dx) is not (): Xoffset = numerix.sum(self.dx[0:self.offset]) self.dx = self.dx[self.offset:self.offset + self.nx] else: Xoffset = self.dx * self.offset vertices = self._createVertices() + ((Xoffset,),) self.numberOfVertices = len(vertices[0]) faces = self._createFaces() self.numberOfFaces = len(faces[0]) cells = self._createCells() Mesh1D.__init__(self, vertices, faces, cells, communicator=communicator) self.setScale(value = scale)
def calcDOffsets(ds, ns, offset): """ :Parameters: - `ds`: A list, e.g. [dx, dy] - `ns`: A list, e.g. [nx, ny, nz] - `offset` :Returns: - `offsetList`: a list which contains the analogous scalars to `XOffset`, `YOffset`, and `ZOffset`, whichever are applicable for the dimensionality. - `newDs`: a list containing proper [dx, [dy, ...]] values """ offsetList = [] newDs = [] if type(offset) in [int, float]: offset = [offset] for d, n, i in zip(ds, ns, list(range(len(ds)))): if numerix.getShape(d) is not (): offsetList.append(numerix.sum(d[0:offset[i]])) newDs.append(d[offset[i]:offset[i] + n]) else: if len(offset) == 1: offsetList.append(d * offset[0]) else: offsetList.append(d * offset[i]) newDs.append(d) return offsetList, newDs
def _calcValue(self): Nfaces = self.mesh.numberOfFaces M = self.mesh._maxFacesPerCell dim = self.mesh.dim cellFaceIDs = self.mesh.cellFaceIDs faceNormalAreas = self.distanceVar._levelSetNormals * self.mesh._faceAreas cellFaceNormalAreas = numerix.array(MA.filled(numerix.take(faceNormalAreas, cellFaceIDs, axis=-1), 0)) norms = numerix.array(MA.filled(MA.array(self.mesh._cellNormals), 0)) alpha = numerix.dot(cellFaceNormalAreas, norms) alpha = numerix.where(alpha > 0, alpha, 0) alphasum = numerix.sum(alpha, axis=0) alphasum += (alphasum < 1e-100) * 1.0 alpha = alpha / alphasum phi = numerix.repeat(self.distanceVar[numerix.newaxis, ...], M, axis=0) alpha = numerix.where(phi > 0., 0, alpha) volumes = numerix.array(self.mesh.cellVolumes) alpha = alpha * volumes * norms value = numerix.zeros((dim, Nfaces), 'd') vector._putAdd(value, cellFaceIDs, alpha, mask=MA.getmask(MA.array(cellFaceIDs))) ## value = numerix.reshape(value, (dim, Nfaces, dim)) return -value / self.mesh._faceAreas
def _calcValueNoInline(self): dAP = self.mesh._cellDistances id1, id2 = self.mesh._adjacentCellIDs N2 = numerix.take(self.var.value, id2, axis=-1) faceMask = numerix.array(self.mesh.exteriorFaces) ## The following conditional is required because empty ## indexing is not altogether functional. This ## numpy.empty((0,))[[]] and this numpy.empty((0,))[...,[]] ## both work, but this numpy.empty((3, 0))[...,[]] is ## broken. if self.var.faceValue.shape[-1] != 0: s = (Ellipsis, faceMask) else: s = (faceMask, ) N2[s] = self.var.faceValue[s] N = (N2 - numerix.take(self.var, id1, axis=-1)) / dAP normals = self.mesh._orientedFaceNormals tangents1 = self.mesh._faceTangents1 tangents2 = self.mesh._faceTangents2 cellGrad = self.var.grad.numericValue grad1 = numerix.take(cellGrad, id1, axis=-1) grad2 = numerix.take(cellGrad, id2, axis=-1) s = (slice(0, None, None), ) + (numerix.newaxis, ) * (len(grad1.shape) - 2) + ( slice(0, None, None), ) t1grad1 = numerix.sum(tangents1[s] * grad1, 0) t1grad2 = numerix.sum(tangents1[s] * grad2, 0) t2grad1 = numerix.sum(tangents2[s] * grad1, 0) t2grad2 = numerix.sum(tangents2[s] * grad2, 0) T1 = (t1grad1 + t1grad2) / 2. T2 = (t2grad1 + t2grad2) / 2. return normals[s] * N[numerix.newaxis] + tangents1[s] * T1[ numerix.newaxis] + tangents2[s] * T2[numerix.newaxis]
def getCellInterfaceAreas(self): """ Returns the length of the interface that crosses the cell A simple 1D test: >>> from fipy.meshes.grid1D import Grid1D >>> mesh = Grid1D(dx = 1., nx = 4) >>> distanceVariable = DistanceVariable(mesh = mesh, ... value = (-1.5, -0.5, 0.5, 1.5)) >>> answer = CellVariable(mesh=mesh, value=(0, 0., 1., 0)) >>> print numerix.allclose(distanceVariable.getCellInterfaceAreas(), ... answer) True A 2D test case: >>> from fipy.meshes.grid2D import Grid2D >>> from fipy.variables.cellVariable import CellVariable >>> mesh = Grid2D(dx = 1., dy = 1., nx = 3, ny = 3) >>> distanceVariable = DistanceVariable(mesh = mesh, ... value = (1.5, 0.5, 1.5, ... 0.5,-0.5, 0.5, ... 1.5, 0.5, 1.5)) >>> answer = CellVariable(mesh=mesh, ... value=(0, 1, 0, 1, 0, 1, 0, 1, 0)) >>> print numerix.allclose(distanceVariable.getCellInterfaceAreas(), answer) True Another 2D test case: >>> mesh = Grid2D(dx = .5, dy = .5, nx = 2, ny = 2) >>> from fipy.variables.cellVariable import CellVariable >>> distanceVariable = DistanceVariable(mesh = mesh, ... value = (-0.5, 0.5, 0.5, 1.5)) >>> answer = CellVariable(mesh=mesh, ... value=(0, numerix.sqrt(2) / 4, numerix.sqrt(2) / 4, 0)) >>> print numerix.allclose(distanceVariable.getCellInterfaceAreas(), ... answer) True Test to check that the circumfrence of a circle is, in fact, :math:`2\pi r`. >>> mesh = Grid2D(dx = 0.05, dy = 0.05, nx = 20, ny = 20) >>> r = 0.25 >>> x, y = mesh.getCellCenters() >>> rad = numerix.sqrt((x - .5)**2 + (y - .5)**2) - r >>> distanceVariable = DistanceVariable(mesh = mesh, value = rad) >>> print distanceVariable.getCellInterfaceAreas().sum() 1.57984690073 """ normals = numerix.array(MA.filled(self._getCellInterfaceNormals(), 0)) areas = numerix.array(MA.filled(self.mesh._getCellAreaProjections(), 0)) return CellVariable(mesh=self.mesh, value=numerix.sum(abs(numerix.dot(normals, areas)), axis=0))
def _calcValueNoInline(self): dAP = self.mesh._cellDistances id1, id2 = self.mesh._adjacentCellIDs N2 = numerix.take(self.var.value, id2, axis=-1) faceMask = numerix.array(self.mesh.exteriorFaces) ## The following conditional is required because empty ## indexing is not altogether functional. This ## numpy.empty((0,))[[]] and this numpy.empty((0,))[...,[]] ## both work, but this numpy.empty((3, 0))[...,[]] is ## broken. if self.var.faceValue.shape[-1] != 0: s = (Ellipsis, faceMask) else: s = (faceMask,) N2[s] = self.var.faceValue[s] N = (N2 - numerix.take(self.var, id1, axis=-1)) / dAP normals = self.mesh._orientedFaceNormals tangents1 = self.mesh._faceTangents1 tangents2 = self.mesh._faceTangents2 cellGrad = self.var.grad.numericValue grad1 = numerix.take(cellGrad, id1, axis=-1) grad2 = numerix.take(cellGrad, id2, axis=-1) s = (slice(0, None, None),) + (numerix.newaxis,) * (len(grad1.shape) - 2) + (slice(0, None, None),) t1grad1 = numerix.sum(tangents1[s] * grad1, 0) t1grad2 = numerix.sum(tangents1[s] * grad2, 0) t2grad1 = numerix.sum(tangents2[s] * grad1, 0) t2grad2 = numerix.sum(tangents2[s] * grad2, 0) T1 = (t1grad1 + t1grad2) / 2. T2 = (t2grad1 + t2grad2) / 2. return normals[s] * N[numerix.newaxis] + tangents1[s] * T1[numerix.newaxis] + tangents2[s] * T2[numerix.newaxis]
def _solve_(self, L, x, b): diag = L.takeDiagonal() maxdiag = max(numerix.absolute(diag)) L = L * (1 / maxdiag) b = b * (1 / maxdiag) LU = superlu.factorize(L._getMatrix().to_csr()) error0 = numerix.sqrt(numerix.sum((L * x - b)**2)) for iteration in range(self.iterations): errorVector = L * x - b if (numerix.sqrt(numerix.sum(errorVector**2)) / error0) <= self.tolerance: break xError = numerix.zeros(len(b),'d') LU.solve(errorVector, xError) x[:] = x - xError
def _calcValue(self): dAP = self.mesh._cellDistances id1, id2 = self.mesh._adjacentCellIDs N = (numerix.take(self.var,id2) - numerix.take(self.var,id1)) / dAP normals = self.mesh._orientedFaceNormals tangents1 = self.mesh._faceTangents1 tangents2 = self.mesh._faceTangents2 cellGrad = self.var.grad.numericValue grad1 = numerix.take(cellGrad, id1, axis=1) grad2 = numerix.take(cellGrad, id2, axis=1) t1grad1 = numerix.sum(tangents1*grad1,0) t1grad2 = numerix.sum(tangents1*grad2,0) t2grad1 = numerix.sum(tangents2*grad1,0) t2grad2 = numerix.sum(tangents2*grad2,0) T1 = (t1grad1 + t1grad2) / 2. T2 = (t2grad1 + t2grad2) / 2. return normals * N + tangents1 * T1 + tangents2 * T2
def _calcValue(self): dAP = self.mesh._cellDistances id1, id2 = self.mesh._adjacentCellIDs N = (numerix.take(self.var, id2) - numerix.take(self.var, id1)) / dAP normals = self.mesh._orientedFaceNormals tangents1 = self.mesh._faceTangents1 tangents2 = self.mesh._faceTangents2 cellGrad = self.var.grad.numericValue grad1 = numerix.take(cellGrad, id1, axis=1) grad2 = numerix.take(cellGrad, id2, axis=1) t1grad1 = numerix.sum(tangents1 * grad1, 0) t1grad2 = numerix.sum(tangents1 * grad2, 0) t2grad1 = numerix.sum(tangents2 * grad1, 0) t2grad2 = numerix.sum(tangents2 * grad2, 0) T1 = (t1grad1 + t1grad2) / 2. T2 = (t2grad1 + t2grad2) / 2. return normals * N + tangents1 * T1 + tangents2 * T2
def _calcFaceCellToCellNormals(self): faceCellCentersUp = numerix.take(self._cellCenters, self.faceCellIDs[1], axis=1) faceCellCentersDown = numerix.take(self._cellCenters, self.faceCellIDs[0], axis=1) faceCellCentersUp = numerix.where(MA.getmaskarray(faceCellCentersUp), self._faceCenters, faceCellCentersUp) diff = faceCellCentersDown - faceCellCentersUp mag = numerix.sqrt(numerix.sum(diff**2)) faceCellToCellNormals = diff / numerix.resize(mag, (self.dim, len(mag))) orientation = 1 - 2 * (numerix.dot(self.faceNormals, faceCellToCellNormals) < 0) return faceCellToCellNormals * orientation
def _calcFaceAreas(self): faceVertexIDs = MA.filled(self.faceVertexIDs, -1) substitute = numerix.repeat(faceVertexIDs[numerix.newaxis, 0], faceVertexIDs.shape[0], axis=0) faceVertexIDs = numerix.where(MA.getmaskarray(self.faceVertexIDs), substitute, faceVertexIDs) faceVertexCoords = numerix.take(self.vertexCoords, faceVertexIDs, axis=1) faceOrigins = numerix.repeat(faceVertexCoords[:,0], faceVertexIDs.shape[0], axis=0) faceOrigins = numerix.reshape(faceOrigins, MA.shape(faceVertexCoords)) faceVertexCoords = faceVertexCoords - faceOrigins left = range(faceVertexIDs.shape[0]) right = left[1:] + [left[0]] cross = numerix.sum(numerix.cross(faceVertexCoords, numerix.take(faceVertexCoords, right, 1), axis=0), 1) self.faceAreas = numerix.sqrtDot(cross, cross) / 2.
def _calcValuePy(self): dAP = self.mesh._getCellDistances() id1, id2 = self.mesh._getAdjacentCellIDs() ## N = self.mod(numerix.take(self.var,id2) - numerix.take(self.var,id1)) / dAP N = (numerix.take(self.var,id2) - numerix.take(self.var,id1)) / dAP normals = self.mesh._getOrientedFaceNormals() tangents1 = self.mesh._getFaceTangents1() tangents2 = self.mesh._getFaceTangents2() cellGrad = self.var.getGrad().getNumericValue() grad1 = numerix.take(cellGrad, id1, axis=1) grad2 = numerix.take(cellGrad, id2, axis=1) t1grad1 = numerix.sum(tangents1*grad1,0) t1grad2 = numerix.sum(tangents1*grad2,0) t2grad1 = numerix.sum(tangents2*grad1,0) t2grad2 = numerix.sum(tangents2*grad2,0) T1 = (t1grad1 + t1grad2) / 2. T2 = (t2grad1 + t2grad2) / 2. return normals * N + tangents1 * T1 + tangents2 * T2
def _calcValue(self): cellToCellDistances = self.mesh._cellToCellDistances cellNormals = self.mesh._cellNormals neighborValue = self._neighborValue value = numerix.array(self.var) cellDistanceNormals = cellToCellDistances * cellNormals N = self.mesh.numberOfCells M = self.mesh._maxFacesPerCell D = self.mesh.dim mat = numerix.zeros((D, D, M, N), 'd') ## good god! numpy.outer should have an axis argument!!! for i in range(D): for j in range(D): mat[i, j] = cellDistanceNormals[i] * cellDistanceNormals[j] mat = numerix.sum(mat, axis=2) vec = numerix.array( numerix.sum((neighborValue - value) * cellDistanceNormals, axis=1)) if D == 1: vec[0] = vec[0] / mat[0, 0] elif D == 2: divisor = mat[0, 0] * mat[1, 1] - mat[0, 1] * mat[1, 0] gradx = (vec[0] * mat[1, 1] - vec[1] * mat[1, 0]) / divisor grady = (vec[1] * mat[0, 0] - vec[0] * mat[0, 1]) / divisor vec[0] = gradx vec[1] = grady else: ## very stuppy! numerix.linalg.solve should have an axis argument!!! for i in range(N): vec[..., i] = numerix.linalg.solve(mat[..., i], vec[..., i]) return vec
def _calcValue(self): cellToCellDistances = self.mesh._getCellToCellDistances() cellNormals = self.mesh._getCellNormals() neighborValue = self._getNeighborValue() value = numerix.array(self.var) cellDistanceNormals = cellToCellDistances * cellNormals N = self.mesh.getNumberOfCells() M = self.mesh._getMaxFacesPerCell() D = self.mesh.getDim() mat = numerix.zeros((D, D, M, N), 'd') ## good god! numpy.outer should have an axis argument!!! for i in range(D): for j in range(D): mat[i,j] = cellDistanceNormals[i] * cellDistanceNormals[j] mat = numerix.sum(mat, axis=2) vec = numerix.array(numerix.sum((neighborValue - value) * cellDistanceNormals, axis=1)) if D == 1: vec[0] = vec[0] / mat[0, 0] elif D == 2: divisor = mat[0,0] * mat[1,1] - mat[0,1] * mat[1,0] gradx = (vec[0] * mat[1,1] - vec[1] * mat[1,0]) / divisor grady = (vec[1] * mat[0,0] - vec[0] * mat[0,1]) / divisor vec[0] = gradx vec[1] = grady else: ## very stuppy! numerix.linalg.solve should have an axis argument!!! for i in range(N): vec[...,i] = numerix.linalg.solve(mat[...,i],vec[...,i]) return vec
def _calcFaceAreas(self): faceVertexIDs = MA.filled(self.faceVertexIDs, -1) substitute = numerix.repeat(faceVertexIDs[numerix.newaxis, 0], faceVertexIDs.shape[0], axis=0) faceVertexIDs = numerix.where(MA.getmaskarray(self.faceVertexIDs), substitute, faceVertexIDs) faceVertexCoords = numerix.take(self.vertexCoords, faceVertexIDs, axis=1) faceOrigins = numerix.repeat(faceVertexCoords[:,0], faceVertexIDs.shape[0], axis=0) faceOrigins = numerix.reshape(faceOrigins, MA.shape(faceVertexCoords)) faceVertexCoords = faceVertexCoords - faceOrigins left = range(faceVertexIDs.shape[0]) right = left[1:] + [left[0]] cross = numerix.sum(numerix.cross(faceVertexCoords, numerix.take(faceVertexCoords, right, 1), axis=0), 1) return numerix.sqrtDot(cross, cross) / 2.
def _dot(a, b, index): """ Workhorse method to calculate the scalar product .. math:: \mathsf{a} \cdot \mathsf{b} for all but the last index of `a` and `b`. Both `a` and `b` can be of arbitrary rank, but at this point, both must be appropriately broadcast `array` objects. """ rankA = len(a.shape) - 1 rankB = len(b.shape) - 1 if rankA <= 0 or rankB <= 0: # if either a or b is scalar, then just do multiplication return a[index] * b else: return numerix.sum(a[index] * b, axis=rankA - 1)
def _getCellInterfaceFlag(self): """ Returns 1 for those cells on the interface: >>> from fipy.meshes.grid2D import Grid2D >>> from fipy.variables.cellVariable import CellVariable >>> mesh = Grid2D(dx = .5, dy = .5, nx = 2, ny = 2) >>> distanceVariable = DistanceVariable(mesh = mesh, ... value = (-0.5, 0.5, 0.5, 1.5)) >>> answer = CellVariable(mesh=mesh, value=(0, 1, 1, 0)) >>> print numerix.allclose(distanceVariable._getCellInterfaceFlag(), answer) True """ flag = MA.filled(numerix.take(self._getInterfaceFlag(), self.cellFaceIDs), 0) flag = numerix.sum(flag, axis=0) return numerix.where(numerix.logical_and(self.value > 0, flag > 0), 1, 0)
def _getCoefficientMatrix(self, SparseMatrix, mesh, coeff): interiorCoeff = numerix.array(coeff) interiorCoeff[mesh.getExteriorFaces().getValue()] = 0 interiorCoeff = numerix.take(interiorCoeff, mesh._getCellFaceIDs()) coefficientMatrix = SparseMatrix(mesh=mesh, bandwidth = mesh._getMaxFacesPerCell() + 1) coefficientMatrix.addAtDiagonal(numerix.sum(interiorCoeff, 0)) del interiorCoeff interiorFaces = mesh.getInteriorFaceIDs() interiorFaceCellIDs = mesh.getInteriorFaceCellIDs() 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 _cellVertexIDs(self): ## Get all the vertices from all the faces for each cell cellFaceVertices = numerix.take(self.faceVertexIDs, self.cellFaceIDs, axis=1) ## get a sorted list of vertices for each cell cellVertexIDs = numerix.reshape(cellFaceVertices, (-1, self.numberOfCells)) cellVertexIDs = MA.sort(cellVertexIDs, axis=0, fill_value=-1) cellVertexIDs = MA.sort(MA.concatenate((cellVertexIDs[-1, numerix.newaxis], MA.masked_where(cellVertexIDs[:-1] == cellVertexIDs[1:], cellVertexIDs[:-1]))), axis=0, fill_value=-1) ## resize the array to remove extra masked values if cellVertexIDs.shape[-1] == 0: length = 0 else: length = min(numerix.sum(MA.getmaskarray(cellVertexIDs), axis=0)) return cellVertexIDs[length:][::-1]
def calcDOffsets(ds, ns, offset): """ Parameters ---------- ds : list Spacing in each grid direction, e.g. `[dx, dy]` ns : list Number of grid spacings in each direction, e.g. `[nx, ny]` offset : list Displacement of grid spacings, e.g., `[Ox, Oy]` Returns ------- offsetList : list Contains the analogous scalars to `XOffset`, `YOffset`, and `ZOffset`, whichever are applicable for the dimensionality. newDs : list proper `[dx, [dy, ...]]` values """ offsetList = [] newDs = [] if type(offset) in [int, float]: offset = [offset] for d, n, i in zip(ds, ns, list(range(len(ds)))): if numerix.getShape(d) is not (): offsetList.append(numerix.sum(d[0:offset[i]])) newDs.append(d[offset[i]:offset[i] + n]) else: if len(offset) == 1: offsetList.append(d * offset[0]) else: offsetList.append(d * offset[i]) newDs.append(d) return offsetList, newDs
surfactantViewer.plot() velocityViewer.plot() totalTime = 0 for step in range(steps): print('step', step) velocity.setValue(surfactantVariable.interfaceVar * k) distanceVariable.extendVariable(velocity) timeStepDuration = cfl * dx / velocity.max() distanceVariable.updateOld() advectionEquation.solve(distanceVariable, dt=timeStepDuration) surfactantEquation.solve(surfactantVariable, dt=1) totalTime += timeStepDuration velocityViewer.plot() distanceViewer.plot() surfactantViewer.plot() finalRadius = numerix.sqrt(2 * k * initialRadius * initialSurfactantValue * totalTime + initialRadius**2) answer = initialSurfactantValue * initialRadius / finalRadius coverage = surfactantVariable.interfaceVar error = (coverage / answer - 1)**2 * (coverage > 1e-3) print('error', numerix.sqrt(numerix.sum(error) / numerix.sum(error > 0))) input('finished')
def _calcValueNoInline(self, N, M, ids, orientations, volumes): contributions = numerix.take(self.faceGradientContributions, ids, axis=-1) grad = numerix.array(numerix.sum(orientations * contributions, -2)) return grad / volumes
def sum(self, axis=None): return self._axisOperator(opname="sumVar", op=lambda a: numerix.sum(a, axis=axis), axis=axis)
print('----------------------------------------------------------') print(i) print('Phi = ' + str(phi[iphi] * conv_fac) + ' to ' + str(phi[iphi + 1] * conv_fac)) print('Theta = ' + str(theta[ith] * conv_fac) + ' to ' + str(theta[ith + 1] * conv_fac)) phi_min = phi[iphi] phi_max = phi[iphi + 1] theta_min = theta[ith] theta_max = theta[ith + 1] #prob=prob_val.remote(phi_min,phi_max,theta_min,theta_max,rho) #prob_id.append(prob) #probability=numerix.append(probability,ray.get(prob)) probability[ith] = prob_val.remote(phi_min, phi_max, theta_min, theta_max, rho) # ray.get(prob) #probability.append(prob_val.remote(phi_min,phi_max,theta_min,theta_max,rho)) #i=i+1 prob_mid = ray.get(probability) prob_phi[iphi] = numerix.sum(prob_mid) #file.write('\n-----------------------------------------------------------------') probability_all = numerix.sum(prob_phi) #prob_all=ray.get(prob_id) print('Probability = ' + str(probability_all)) #file.write('Total Probability = ' + str(total_probability)) #file.close()
where=((x0 < x) & (x < x1)) & ((x0 < y) & (y < x1))) surfactantVariable = SurfactantVariable(distanceVar=distanceVariable, value=1.) from fipy.variables.surfactantConvectionVariable import SurfactantConvectionVariable surfactantEquation = TransientTerm() - \ ExplicitUpwindConvectionTerm(SurfactantConvectionVariable(distanceVariable)) advectionEquation = TransientTerm() + AdvectionTerm(velocity) if __name__ == '__main__': distanceViewer = Viewer(vars=distanceVariable, datamin=-.001, datamax=.001) surfactantViewer = Viewer(vars=surfactantVariable, datamin=0., datamax=2.) distanceVariable.calcDistanceFunction() for step in range(steps): print numerix.sum(surfactantVariable) distanceVariable.updateOld() surfactantEquation.solve(surfactantVariable, dt=1) advectionEquation.solve(distanceVariable, dt=timeStepDuration) distanceViewer.plot() surfactantViewer.plot() surfactantEquation.solve(surfactantVariable, dt=1) distanceViewer.plot() surfactantViewer.plot() print surfactantVariable raw_input('finished')
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 _calcValue(self): normals = numerix.array( MA.filled(self.distanceVar._cellInterfaceNormals, 0)) areas = numerix.array(MA.filled(self.mesh._cellAreaProjections, 0)) return numerix.sum(abs(numerix.dot(normals, areas)), axis=0)
def __init__(self, dx=1., dy=1., nx=None, ny=None, overlap=2, parallelModule=parallel): self.args = { 'dx': dx, 'dy': dy, 'nx': nx, 'ny': ny, 'overlap': overlap, 'parallelModule': parallelModule } self.dx = PhysicalField(value = dx) scale = PhysicalField(value=1, unit=self.dx.getUnit()) self.dx /= scale nx = self._calcNumPts(d=self.dx, n=nx, axis="x") self.dy = PhysicalField(value = dy) if self.dy.getUnit().isDimensionless(): self.dy = dy else: self.dy /= scale ny = self._calcNumPts(d=self.dy, n=ny, axis="y") (self.nx, self.ny, self.overlap, self.offset) = self._calcParallelGridInfo(nx, ny, overlap, parallelModule) if numerix.getShape(self.dx) is not (): Xoffset = numerix.sum(self.dx[0:self.offset[0]]) self.dx = self.dx[self.offset[0]:self.offset[0] + self.nx] else: Xoffset = 0 if numerix.getShape(self.dy) is not (): Yoffset = numerix.sum(self.dy[0:self.offset[1]]) self.dy = self.dy[self.offset[1]:self.offset[1] + self.ny] else: Yoffset = 0 if self.nx == 0: self.ny = 0 if self.ny == 0: self.nx = 0 if self.nx == 0 or self.ny == 0: self.numberOfHorizontalRows = 0 self.numberOfVerticalColumns = 0 else: self.numberOfHorizontalRows = (self.ny + 1) self.numberOfVerticalColumns = (self.nx + 1) self.numberOfVertices = self.numberOfHorizontalRows * self.numberOfVerticalColumns vertices = self._createVertices() + ((Xoffset,), (Yoffset,)) faces = self._createFaces() self.numberOfFaces = len(faces[0]) cells = self._createCells() Mesh2D.__init__(self, vertices, faces, cells) self.setScale(value = scale)
def _calcTrialValue(self, id, evaluatedFlag, extensionVariable): adjIDs = self.cellToCellIDs[...,id] adjEvaluatedFlag = numerix.take(evaluatedFlag, adjIDs) adjValues = numerix.take(self.value, adjIDs) adjValues = numerix.where(adjEvaluatedFlag, adjValues, 1e+10) try: indices = numerix.argsort(abs(adjValues)) except TypeError: # numpy 1.1 raises a TypeError when using argsort function indices = abs(adjValues).argsort() sign = (self.value[id] > 0) * 2 - 1 d0 = self.cellToCellDistances[indices[0], id] v0 = self.value[..., adjIDs[indices[0]]] e0 = extensionVariable[..., adjIDs[indices[0]]] N = numerix.sum(adjEvaluatedFlag) index0 = indices[0] index1 = indices[1] index2 = indices[self.mesh.getDim()] if N > 1: n0 = self.cellNormals[..., index0, id] n1 = self.cellNormals[..., index1, id] if self.mesh.getDim() == 2: cross = (n0[0] * n1[1] - n0[1] * n1[0]) else: cross = 0.0 if abs(cross) < 0.1: if N == 2: N = 1 elif N == 3: index1 = index2 if N == 0: raise Exception elif N == 1: return v0 + sign * d0, e0 else: d1 = self.cellToCellDistances[index1, id] n0 = self.cellNormals[..., index0, id] n1 = self.cellNormals[..., index1, id] v1 = self.value[..., adjIDs[index1]] crossProd = d0 * d1 * (n0[0] * n1[1] - n0[1] * n1[0]) dotProd = d0 * d1 * numerix.dot(n0, n1) dsq = d0**2 + d1**2 - 2 * dotProd top = -v0 * (dotProd - d1**2) - v1 * (dotProd - d0**2) sqrt = crossProd**2 *(dsq - (v0 - v1)**2) sqrt = numerix.sqrt(max(sqrt, 0)) dis = (top + sign * sqrt) / dsq ## extension variable e1 = extensionVariable[..., adjIDs[index1]] a0 = self.cellAreas[index0, id] a1 = self.cellAreas[index1, id] if self.value[id] > 0: phi = max(dis, 0) else: phi = min(dis, 0) n0grad = a0 * abs(v0 - phi) / d0 n1grad = a1 * abs(v1 - phi) / d1 return dis, (e0 * n0grad + e1 * n1grad) / (n0grad + n1grad)
surfactantEquation = TransientTerm() - \ ExplicitUpwindConvectionTerm(SurfactantConvectionVariable(distanceVariable)) if __name__ == '__main__': distanceViewer = Viewer(vars=distanceVariable, datamin=-initialRadius, datamax=initialRadius) surfactantViewer = Viewer(vars=surfactantVariable, datamin=-1., datamax=100.) distanceViewer.plot() surfactantViewer.plot() print('total surfactant before:', numerix.sum(surfactantVariable * mesh.cellVolumes)) for step in range(steps): distanceVariable.updateOld() surfactantEquation.solve(surfactantVariable, dt=1.) advectionEquation.solve(distanceVariable, dt=timeStepDuration) distanceViewer.plot() surfactantViewer.plot() surfactantEquation.solve(surfactantVariable, dt=1.) print('total surfactant after:', numerix.sum(surfactantVariable * mesh.cellVolumes)) areas = (distanceVariable.cellInterfaceAreas < 1e-6) * 1e+10 + distanceVariable.cellInterfaceAreas answer = initialSurfactantValue * initialRadius / (initialRadius +
surfactantEquation = SurfactantEquation( distanceVar = distanceVariable) advectionEquation = buildHigherOrderAdvectionEquation( advectionCoeff = velocity) if __name__ == '__main__': import fipy.viewers distanceViewer = fipy.viewers.make(vars = distanceVariable, limits = {'datamin': -.001, 'datamax': .001}) surfactantViewer = fipy.viewers.make(vars = surfactantVariable, limits = {'datamin': 0., 'datamax': 2.}) distanceVariable.calcDistanceFunction() for step in range(steps): print numerix.sum(surfactantVariable) surfactantVariable.updateOld() distanceVariable.updateOld() surfactantEquation.solve(surfactantVariable) advectionEquation.solve(distanceVariable, dt = timeStepDuration) distanceViewer.plot() surfactantViewer.plot() surfactantEquation.solve(surfactantVariable) distanceViewer.plot() surfactantViewer.plot() print surfactantVariable raw_input('finished')
def __init__(self, dx = 1., dy = 1., dz = 1., nx = None, ny = None, nz = None, overlap=2, communicator=parallel): self.args = { 'dx': dx, 'dy': dy, 'dz' :dz, 'nx': nx, 'ny': ny, 'nz': nz, 'overlap': overlap, 'communicator': communicator } self.dx = PhysicalField(value = dx) scale = PhysicalField(value = 1, unit = self.dx.getUnit()) self.dx /= scale nx = self._calcNumPts(d = self.dx, n = nx, axis = "x") self.dy = PhysicalField(value = dy) if self.dy.getUnit().isDimensionless(): self.dy = dy else: self.dy /= scale ny = self._calcNumPts(d = self.dy, n = ny, axis = "y") self.dz = PhysicalField(value = dz) if self.dz.getUnit().isDimensionless(): self.dz = dz else: self.dz /= scale nz = self._calcNumPts(d = self.dz, n = nz, axis = "z") (self.nx, self.ny, self.nz, self.overlap, self.offset) = self._calcParallelGridInfo(nx, ny, nz, overlap, communicator) if numerix.getShape(self.dx) is not (): Xoffset = numerix.sum(self.dx[0:self.offset[0]]) self.dx = self.dx[self.offset[0]:self.offset[0] + self.nx] else: Xoffset = 0 if numerix.getShape(self.dy) is not (): Yoffset = numerix.sum(self.dy[0:self.offset[1]]) self.dy = self.dy[self.offset[1]:self.offset[1] + self.ny] else: Yoffset = 0 if numerix.getShape(self.dy) is not (): Zoffset = numerix.sum(self.dz[0:self.offset[2]]) self.dz = self.dz[self.offset[2]:self.offset[2] + self.nz] else: Zoffset = 0 if self.nx == 0 or self.ny == 0 or self.nz == 0: self.nx = 0 self.ny = 0 self.nz = 0 if self.nx == 0 or self.ny == 0 or self.nz == 0: self.numberOfHorizontalRows = 0 self.numberOfVerticalColumns = 0 self.numberOfLayersDeep = 0 else: self.numberOfHorizontalRows = (self.ny + 1) self.numberOfVerticalColumns = (self.nx + 1) self.numberOfLayersDeep = (self.nz + 1) self.numberOfVertices = self.numberOfHorizontalRows * self.numberOfVerticalColumns * self.numberOfLayersDeep vertices = self._createVertices() + ((Xoffset,), (Yoffset,), (Zoffset,)) faces = self._createFaces() cells = self._createCells() Mesh.__init__(self, vertices, faces, cells) self.setScale(value = scale)
errorViewer.plot() finalRadius = initialRadius + totalTime * velocity + distanceVariable answer = initialSurfactantValue * initialRadius / finalRadius coverage = surfactantVariable.getInterfaceVar() error.setValue(numerix.where((coverage > 1e-3) & (distanceVariable > 0), abs(coverage - answer), 0)) adjDistanceVariables = numerix.take(distanceVariable, mesh._getCellToCellIDs()) adjCoverages = numerix.take(coverage, mesh._getCellToCellIDs()) flag = (adjDistanceVariables < 0) & (adjCoverages > 1e-6) error.setValue(0, where=numerix.sum(flag, index=1) > 0) del L1[0] del L2[0] del Linf[0] L1.append(numerix.array(numerix.sum(error)/nx)) L2.append(numerix.array(numerix.sqrt(numerix.sum(error**2)/nx))) Linf.append(numerix.array(max(error))) ## argmax = numerix.argmax(error) ## del errorList[0] ## errorList.append(max(error))
def _calcValue(self): normals = numerix.array(MA.filled(self.distanceVar._cellInterfaceNormals, 0)) areas = numerix.array(MA.filled(self.mesh._cellAreaProjections, 0)) return numerix.sum(abs(numerix.dot(normals, areas)), axis=0)
surfactantViewer.plot() velocityViewer.plot() totalTime = 0 for step in range(steps): print 'step',step velocity.setValue(surfactantVariable.interfaceVar * k) distanceVariable.extendVariable(velocity) timeStepDuration = cfl * dx / velocity.max() distanceVariable.updateOld() advectionEquation.solve(distanceVariable, dt = timeStepDuration) surfactantEquation.solve(surfactantVariable, dt=1) totalTime += timeStepDuration velocityViewer.plot() distanceViewer.plot() surfactantViewer.plot() finalRadius = numerix.sqrt(2 * k * initialRadius * initialSurfactantValue * totalTime + initialRadius**2) answer = initialSurfactantValue * initialRadius / finalRadius coverage = surfactantVariable.interfaceVar error = (coverage / answer - 1)**2 * (coverage > 1e-3) print 'error', numerix.sqrt(numerix.sum(error) / numerix.sum(error > 0)) raw_input('finished')
advectionEquation = TransientTerm() + AdvectionTerm(velocity) from fipy.variables.surfactantConvectionVariable import SurfactantConvectionVariable surfactantEquation = TransientTerm() - \ ExplicitUpwindConvectionTerm(SurfactantConvectionVariable(distanceVariable)) if __name__ == '__main__': distanceViewer = Viewer(vars=distanceVariable, datamin=-initialRadius, datamax=initialRadius) surfactantViewer = Viewer(vars=surfactantVariable, datamin=-1., datamax=100.) distanceViewer.plot() surfactantViewer.plot() print 'total surfactant before:', numerix.sum(surfactantVariable * mesh.cellVolumes) for step in range(steps): distanceVariable.updateOld() surfactantEquation.solve(surfactantVariable, dt=1.) advectionEquation.solve(distanceVariable, dt = timeStepDuration) distanceViewer.plot() surfactantViewer.plot() surfactantEquation.solve(surfactantVariable, dt=1.) print 'total surfactant after:', numerix.sum(surfactantVariable * mesh.cellVolumes) areas = (distanceVariable.cellInterfaceAreas < 1e-6) * 1e+10 + distanceVariable.cellInterfaceAreas answer = initialSurfactantValue * initialRadius / (initialRadius + distanceToTravel) coverage = surfactantVariable * mesh.cellVolumes / areas