def __init__(self, vertexCoords, faceVertexIDs, cellFaceIDs, communicator=serialComm, _RepresentationClass=_MeshRepresentation, _TopologyClass=_MeshTopology): super(Mesh, self).__init__(communicator=communicator, _RepresentationClass=_RepresentationClass, _TopologyClass=_TopologyClass) """faceVertexIds and cellFacesIds must be padded with minus ones.""" self.vertexCoords = vertexCoords self.faceVertexIDs = MA.masked_values(faceVertexIDs, -1) self.cellFaceIDs = MA.masked_values(cellFaceIDs, -1) self.dim = self.vertexCoords.shape[0] if not hasattr(self, "numberOfFaces"): self.numberOfFaces = self.faceVertexIDs.shape[-1] if not hasattr(self, "numberOfCells"): self.numberOfCells = self.cellFaceIDs.shape[-1] if not hasattr(self, "globalNumberOfCells"): self.globalNumberOfCells = self.numberOfCells if not hasattr(self, "globalNumberOfFaces"): self.globalNumberOfFaces = self.numberOfFaces self.faceCellIDs = self._calcFaceCellIDs() self._setTopology() self._setGeometry(scaleLength = 1.)
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 _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 deleteIslands(self): cellToCellIDs = self.mesh._cellToCellIDs 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 = numerix.array(MA.where(tmp, -1, self.value))
def __init__(self, mesh, name = '', value = 0., unit = None, hasOld = 0, narrowBandWidth = 1e+10): """ Creates a `distanceVariable` object. :Parameters: - `mesh`: The mesh that defines the geometry of this variable. - `name`: The name of the variable. - `value`: The initial value. - `unit`: the physical units of the variable - `hasOld`: Whether the variable maintains an old value. - `narrowBandWidth`: The width of the region about the zero level set within which the distance function is evaluated. """ CellVariable.__init__(self, mesh, name = name, value = value, unit = unit, hasOld = hasOld) self._markStale() self.narrowBandWidth = narrowBandWidth self.cellToCellDistances = MA.filled(self.mesh._getCellToCellDistances(), 0) self.cellNormals = MA.filled(self.mesh._getCellNormals(), 0) self.cellAreas = MA.filled(self.mesh._getCellAreas(), 0) ## self.cellToCellDistances = numerix.array(MA.array(self.mesh._getCellToCellDistances()).filled(0)) ## self.cellNormals = numerix.array(MA.array(self.mesh._getCellNormals()).filled(0)) ## self.cellAreas = numerix.array(MA.array(self.mesh._getCellAreas()).filled(0)) self.cellToCellIDs = numerix.array(self.mesh._getCellToCellIDsFilled()) self.adjacentCellIDs = self.mesh._getAdjacentCellIDs() self.exteriorFaces = self.mesh.getExteriorFaces() self.cellFaceIDs = self.mesh._getCellFaceIDs()
def _calcFaceToCellDistances(self): tmp = MA.repeat(self.faceCenters[...,numerix.NewAxis,:], 2, 1) # array -= masked_array screws up masking for on numpy 1.1 tmp = tmp - numerix.take(self.cellCenters, self.faceCellIDs, axis=1) self.cellToFaceDistanceVectors = tmp self.faceToCellDistances = MA.sqrt(MA.sum(tmp * tmp,0))
def _getDifferences(self, adjacentValues, cellValues, oldArray, cellToCellIDs, mesh): dAP = mesh._cellToCellDistances ## adjacentGradient = numerix.take(oldArray.grad, cellToCellIDs) adjacentGradient = numerix.take(oldArray.grad, mesh._cellToCellIDs, axis=-1) adjacentNormalGradient = numerix.dot(adjacentGradient, mesh._cellNormals) adjacentUpValues = cellValues + 2 * dAP * adjacentNormalGradient cellIDs = numerix.repeat(numerix.arange(mesh.numberOfCells)[numerix.newaxis, ...], mesh._maxFacesPerCell, axis=0) cellIDs = MA.masked_array(cellIDs, mask = MA.getmask(mesh._cellToCellIDs)) cellGradient = numerix.take(oldArray.grad, cellIDs, axis=-1) cellNormalGradient = numerix.dot(cellGradient, mesh._cellNormals) cellUpValues = adjacentValues - 2 * dAP * cellNormalGradient cellLaplacian = (cellUpValues + adjacentValues - 2 * cellValues) / dAP**2 adjacentLaplacian = (adjacentUpValues + cellValues - 2 * adjacentValues) / dAP**2 adjacentLaplacian = adjacentLaplacian.filled(0) cellLaplacian = cellLaplacian.filled(0) mm = numerix.where(cellLaplacian * adjacentLaplacian < 0., 0., numerix.where(abs(cellLaplacian) > abs(adjacentLaplacian), adjacentLaplacian, cellLaplacian)) return FirstOrderAdvectionTerm._getDifferences(self, adjacentValues, cellValues, oldArray, cellToCellIDs, mesh) - mm * dAP / 2.
def faceCellIDs(self): XYids = MA.zeros((2, self.nx, self.ny, self.nz + 1), 'l') indices = numerix.indices((self.nx, self.ny, self.nz + 1)) XYids[1] = indices[0] + (indices[1] + indices[2] * self.ny) * self.nx XYids[0] = XYids[1] - self.nx * self.ny XYids[0, ..., 0] = XYids[1, ..., 0] XYids[1, ..., 0] = MA.masked XYids[1, ..., -1] = MA.masked XZids = MA.zeros((2, self.nx, self.ny + 1, self.nz), 'l') indices = numerix.indices((self.nx, self.ny + 1, self.nz)) XZids[1] = indices[0] + (indices[1] + indices[2] * self.ny) * self.nx XZids[0] = XZids[1] - self.nx XZids[0,:, 0,:] = XZids[1,:, 0,:] XZids[1,:, 0,:] = MA.masked XZids[1,:, -1,:] = MA.masked YZids = MA.zeros((2, self.nx + 1, self.ny, self.nz), 'l') indices = numerix.indices((self.nx + 1, self.ny, self.nz)) YZids[1] = indices[0] + (indices[1] + indices[2] * self.ny) * self.nx YZids[0] = YZids[1] - 1 YZids[0, 0] = YZids[1, 0] YZids[1, 0] = MA.masked YZids[1, -1] = MA.masked return MA.concatenate((XYids.swapaxes(1, 3).reshape((2, self.numberOfXYFaces)), XZids.swapaxes(1, 3).reshape((2, self.numberOfXZFaces)), YZids.swapaxes(1, 3).reshape((2, self.numberOfYZFaces))), axis=1)
def __init__(self, vertexCoords, faceVertexIDs, cellFaceIDs, communicator=serialComm, _RepresentationClass=_MeshRepresentation, _TopologyClass=_MeshTopology): super(Mesh, self).__init__(communicator=communicator, _RepresentationClass=_RepresentationClass, _TopologyClass=_TopologyClass) """faceVertexIds and cellFacesIds must be padded with minus ones.""" self.vertexCoords = vertexCoords self.faceVertexIDs = MA.masked_values(faceVertexIDs, -1) self.cellFaceIDs = MA.masked_values(cellFaceIDs, -1) self.dim = self.vertexCoords.shape[0] if not hasattr(self, "numberOfFaces"): self.numberOfFaces = self.faceVertexIDs.shape[-1] if not hasattr(self, "numberOfCells"): self.numberOfCells = self.cellFaceIDs.shape[-1] if not hasattr(self, "globalNumberOfCells"): self.globalNumberOfCells = self.numberOfCells if not hasattr(self, "globalNumberOfFaces"): self.globalNumberOfFaces = self.numberOfFaces self.faceCellIDs = self._calcFaceCellIDs() self._setTopology() self._setGeometry(scaleLength=1.)
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 faceCellIDs(self): XYids = MA.zeros((2, self.nx, self.ny, self.nz + 1), 'l') indices = numerix.indices((self.nx, self.ny, self.nz + 1)) XYids[1] = indices[0] + (indices[1] + indices[2] * self.ny) * self.nx XYids[0] = XYids[1] - self.nx * self.ny XYids[0,..., 0] = XYids[1,..., 0] XYids[1,..., 0] = MA.masked XYids[1,...,-1] = MA.masked XZids = MA.zeros((2, self.nx, self.ny + 1, self.nz), 'l') indices = numerix.indices((self.nx, self.ny + 1, self.nz)) XZids[1] = indices[0] + (indices[1] + indices[2] * self.ny) * self.nx XZids[0] = XZids[1] - self.nx XZids[0, :, 0, :] = XZids[1, :, 0, :] XZids[1, :, 0, :] = MA.masked XZids[1, :,-1, :] = MA.masked YZids = MA.zeros((2, self.nx + 1, self.ny, self.nz), 'l') indices = numerix.indices((self.nx + 1, self.ny, self.nz)) YZids[1] = indices[0] + (indices[1] + indices[2] * self.ny) * self.nx YZids[0] = YZids[1] - 1 YZids[0, 0] = YZids[1, 0] YZids[1, 0] = MA.masked YZids[1,-1] = MA.masked return MA.concatenate((XYids.swapaxes(1,3).reshape((2, self.numberOfXYFaces)), XZids.swapaxes(1,3).reshape((2, self.numberOfXZFaces)), YZids.swapaxes(1,3).reshape((2, self.numberOfYZFaces))), axis=1)
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 _calcCellDistAndVec(self): tmp = numerix.take(self._cellCenters, self.faceCellIDs, axis=1) tmp = tmp[..., 1, :] - tmp[..., 0, :] tmp = MA.filled( MA.where(MA.getmaskarray(tmp), self._cellToFaceDistanceVectors[:, 0], tmp)) cellDistanceVectors = tmp return self._cellDistances, cellDistanceVectors
def _calcFaceToCellDistAndVec(self): tmp = MA.repeat(self._faceCenters[..., numerix.NewAxis, :], 2, 1) # array -= masked_array screws up masking for on numpy 1.1 tmp = tmp - numerix.take(self._cellCenters, self.faceCellIDs, axis=1) cellToFaceDistanceVectors = tmp faceToCellDistances = MA.sqrt(MA.sum(tmp * tmp, 0)) return faceToCellDistances, cellToFaceDistanceVectors
def _cellToCellIDsFilled(self): N = self.numberOfCells M = self._maxFacesPerCell cellIDs = numerix.repeat(numerix.arange(N)[numerix.newaxis, ...], M, axis=0) cellToCellIDs = self._cellToCellIDs return MA.where(MA.getmaskarray(cellToCellIDs), cellIDs, cellToCellIDs)
def __init__(self, vertexCoords, faceVertexIDs, cellFaceIDs): """faceVertexIds and cellFacesIds must be padded with minus ones.""" self.vertexCoords = vertexCoords self.faceVertexIDs = MA.masked_values(faceVertexIDs, -1) self.cellFaceIDs = MA.masked_values(cellFaceIDs, -1) _CommonMesh.__init__(self)
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 _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 _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 _cellToCellIDs(self): ids = MA.zeros((4, self.nx, self.ny), 'l') indices = numerix.indices((self.nx, self.ny)) ids[0] = indices[0] + (indices[1] - 1) * self.nx ids[1] = (indices[0] + 1) + indices[1] * self.nx ids[2] = indices[0] + (indices[1] + 1) * self.nx ids[3] = (indices[0] - 1) + indices[1] * self.nx if self.ny > 0: ids[0, ..., 0] = MA.masked ids[2, ..., -1] = MA.masked if self.nx > 0: ids[1, -1, ...] = MA.masked ids[3, 0, ...] = MA.masked return MA.reshape(ids.swapaxes(1, 2), (4, self.numberOfCells))
def _cellToCellDistances(self): distances = MA.zeros((2, self.numberOfCells), 'd') distances[:] = self.dx if self.numberOfCells > 0: distances[0, 0] = self.dx / 2. distances[1, -1] = self.dx / 2. return distances
def _numberOfFacesPerCell(self): cellFaceIDs = self.cellFaceIDs if isinstance(cellFaceIDs, type(MA.array(0))): ## bug in count returns float values when there is no mask return numerix.array(cellFaceIDs.count(axis=0), 'l') else: return self._maxFacesPerCell * numerix.ones(cellFaceIDs.shape[-1], 'l')
def _calcInteriorAndExteriorFaceIDs(self): from fipy.variables.faceVariable import FaceVariable mask = MA.getmask(self.faceCellIDs[1]) self.exteriorFaces = FaceVariable(mesh=self, value=mask) self.interiorFaces = FaceVariable(mesh=self, value=numerix.logical_not(mask))
def _cellInterfaceNormals(self): """ Returns the interface normals over the cells. >>> from fipy.meshes 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)) >>> v = 1 / numerix.sqrt(2) >>> answer = CellVariable(mesh=mesh, ... value=(((0, 0, v, 0), ... (0, 0, 0, 0), ... (0, 0, 0, 0), ... (0, v, 0, 0)), ... ((0, 0, v, 0), ... (0, 0, 0, 0), ... (0, 0, 0, 0), ... (0, v, 0, 0)))) >>> print(numerix.allclose(distanceVariable._cellInterfaceNormals, answer)) True """ dim = self.mesh.dim valueOverFaces = numerix.repeat(self._cellValueOverFaces[numerix.newaxis, ...], dim, axis=0) cellFaceIDs = self.mesh.cellFaceIDs if cellFaceIDs.shape[-1] > 0: interfaceNormals = self._interfaceNormals[..., cellFaceIDs] else: interfaceNormals = 0 return MA.where(valueOverFaces < 0, 0, interfaceNormals)
def _getCellToCellIDs(self): c1 = numerix.arange(self.numberOfCells) ids = MA.array((c1 - 1, c1 + 1)) if self.numberOfCells > 0: ids[0, 0] = MA.masked ids[1, -1] = MA.masked return ids
def _cellToCellIDs(self): c1 = numerix.arange(self.numberOfCells) ids = MA.array((c1 - 1, c1 + 1)) if self.numberOfCells > 0: ids[0, 0] = MA.masked ids[1, -1] = MA.masked return ids
def _getCellToCellDistances(self): distances = MA.zeros((2, self.numberOfCells), "d") distances[:] = self.dx if self.numberOfCells > 0: distances[0, 0] = self.dx / 2.0 distances[1, -1] = self.dx / 2.0 return distances
def _getNumberOfFacesPerCell(self): cellFaceIDs = self._getCellFaceIDs() if type(cellFaceIDs) is type(MA.array(0)): ## bug in count returns float values when there is no mask return numerix.array(cellFaceIDs.count(axis=0), 'l') else: return self._getMaxFacesPerCell() * numerix.ones(cellFaceIDs.shape[-1], 'l')
def _cellFaceIDs(self): return MA.array(_Grid3DBuilder.createCells(self.nx, self.ny, self.nz, self.numberOfXYFaces, self.numberOfXZFaces, self.numberOfYZFaces))
def _calcInteriorAndExteriorFaceIDs(self): from fipy.variables.faceVariable import FaceVariable mask = MA.getmask(self.faceCellIDs[1]) exteriorFaces = FaceVariable(mesh=self, value=mask) interiorFaces = FaceVariable(mesh=self, value=numerix.logical_not(mask)) return interiorFaces, exteriorFaces
def _calcCellToCellIDs(self): cellToCellIDs = numerix.take(self.faceCellIDs, self.cellFaceIDs, axis=1) cellToCellIDs = MA.where(self._cellToFaceOrientations == 1, cellToCellIDs[1], cellToCellIDs[0]) return cellToCellIDs
def _cellInterfaceNormals(self): """ Returns the interface normals over the cells. >>> from fipy.meshes 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)) >>> v = 1 / numerix.sqrt(2) >>> answer = CellVariable(mesh=mesh, ... value=(((0, 0, v, 0), ... (0, 0, 0, 0), ... (0, 0, 0, 0), ... (0, v, 0, 0)), ... ((0, 0, v, 0), ... (0, 0, 0, 0), ... (0, 0, 0, 0), ... (0, v, 0, 0)))) >>> print numerix.allclose(distanceVariable._cellInterfaceNormals, answer) True """ dim = self.mesh.dim valueOverFaces = numerix.repeat(self._cellValueOverFaces[numerix.newaxis, ...], dim, axis=0) cellFaceIDs = self.mesh.cellFaceIDs if cellFaceIDs.shape[-1] > 0: interfaceNormals = self._interfaceNormals[...,cellFaceIDs] else: interfaceNormals = 0 return MA.where(valueOverFaces < 0, 0, interfaceNormals)
def _calcValue(self): ids = self.mesh.cellFaceIDs contributions = numerix.take(self.faceVariable, ids, axis=-1) s = (numerix.newaxis, ) * (len(contributions.shape) - 2) + (slice( 0, None, None), ) + (slice(0, None, None), ) faceContributions = contributions * self.mesh._cellToFaceOrientations[ s] #just changes sign temp = faceContributions.copy() maskedValues = np.vstack( ([not isinstance(xi, float) for xi in temp[0] ], [not isinstance(xi, float) for xi in temp[1] ], [not isinstance(xi, float) for xi in temp[2]], [not isinstance(xi, float) for xi in temp[3]])) faceAreas = np.take(self.mesh._faceAreas, ids) faceAreas = MA.masked_where(maskedValues, faceAreas) if (len(temp) > 1): temp = temp * faceAreas temp[2] = numerix.MA.filled(temp[2], temp[0]) temp[3] = numerix.MA.filled(temp[3], temp[1]) faceAreas[2] = numerix.MA.filled(faceAreas[2], faceAreas[0]) faceAreas[3] = numerix.MA.filled(faceAreas[3], faceAreas[1]) faceAreas[0] = (faceAreas[0] + faceAreas[2]) faceAreas[1] = (faceAreas[1] + faceAreas[3]) temp[0] = (temp[0] + temp[2]) / faceAreas[0] temp[1] = (temp[1] + temp[3]) / faceAreas[1] temp = numerix.vstack( (numerix.array(temp[0]), numerix.array(temp[1]))) return numerix.tensordot(numerix.ones(temp.shape[-2], 'd'), temp, (0, -2)) / self.mesh.cellVolumes
def faceCellIDs(self): Hids = numerix.zeros((2, self.nx, self.numberOfHorizontalRows), 'l') indices = numerix.indices((self.nx, self.numberOfHorizontalRows)) Hids[1] = indices[0] + indices[1] * self.nx Hids[0] = Hids[1] - self.nx if self.numberOfHorizontalRows > 0: Hids[0, ..., 0] = Hids[1, ..., 0] Hids[1, ..., 0] = -1 Hids[1, ..., -1] = -1 Vids = numerix.zeros((2, self.numberOfVerticalColumns, self.ny), 'l') indices = numerix.indices((self.numberOfVerticalColumns, self.ny)) Vids[1] = indices[0] + indices[1] * self.nx Vids[0] = Vids[1] - 1 if self.numberOfVerticalColumns > 0: Vids[0, 0] = Vids[1, 0] Vids[1, 0] = -1 Vids[1, -1] = -1 return MA.masked_values(numerix.concatenate( (Hids.reshape( (2, self.numberOfHorizontalFaces), order="FORTRAN"), Vids.reshape( (2, self.numberOfFaces - self.numberOfHorizontalFaces), order="FORTRAN")), axis=1), value=-1)
def faceCellIDs(self): c1 = numerix.arange(self.numberOfFaces) ids = MA.array((c1 - 1, c1)) if self.numberOfFaces > 0: ids[0, 0] = ids[1, 0] ids[1, 0] = MA.masked ids[1, -1] = MA.masked return ids
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 getFaceCellIDs(self): c1 = numerix.arange(self.numberOfFaces) ids = MA.array((c1 - 1, c1)) if self.numberOfFaces > 0: ids[0, 0] = ids[1, 0] ids[1, 0] = MA.masked ids[1, -1] = MA.masked return ids
def _cellToCellIDs(self): ids = MA.zeros((6, self.nx, self.ny, self.nz), 'l') indices = numerix.indices((self.nx, self.ny, self.nz)) ids[0] = indices[0] + (indices[1] + indices[2] * self.ny) * self.nx - 1 ids[1] = indices[0] + (indices[1] + indices[2] * self.ny) * self.nx + 1 ids[2] = indices[0] + (indices[1] + indices[2] * self.ny - self.nz) * self.nx ids[3] = indices[0] + (indices[1] + indices[2] * self.ny + self.nz) * self.nx ids[4] = indices[0] + (indices[1] + (indices[2] - 1) * self.ny) * self.nx ids[5] = indices[0] + (indices[1] + (indices[2] + 1) * self.ny) * self.nx ids[0, 0, ...] = MA.masked ids[1,-1, ...] = MA.masked ids[2,..., 0,...] = MA.masked ids[3,...,-1,...] = MA.masked ids[4,..., 0] = MA.masked ids[5,..., -1] = MA.masked return MA.reshape(ids.swapaxes(1,3), (6, self.numberOfCells))
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 _calcOrderedCellVertexIDs(self): from fipy.tools.numerix import take NFac = self._maxFacesPerCell # numpy 1.1's MA.take doesn't like FlatIter. Call ravel() instead. cellVertexIDs0 = take(self.faceVertexIDs[0], self.cellFaceIDs.ravel()) cellVertexIDs1 = take(self.faceVertexIDs[1], self.cellFaceIDs.ravel()) cellVertexIDs = MA.where(self._cellToFaceOrientations.ravel() > 0, cellVertexIDs0, cellVertexIDs1) cellVertexIDs = numerix.reshape(cellVertexIDs, (NFac, -1)) return cellVertexIDs
def _getDifferences(self, adjacentValues, cellValues, oldArray, cellToCellIDs, mesh): dAP = mesh._cellToCellDistances ## adjacentGradient = numerix.take(oldArray.grad, cellToCellIDs) adjacentGradient = numerix.take(oldArray.grad, mesh._cellToCellIDs, axis=-1) adjacentNormalGradient = numerix.dot(adjacentGradient, mesh._cellNormals) adjacentUpValues = cellValues + 2 * dAP * adjacentNormalGradient cellIDs = numerix.repeat(numerix.arange( mesh.numberOfCells)[numerix.newaxis, ...], mesh._maxFacesPerCell, axis=0) cellIDs = MA.masked_array(cellIDs, mask=MA.getmask(mesh._cellToCellIDs)) cellGradient = numerix.take(oldArray.grad, cellIDs, axis=-1) cellNormalGradient = numerix.dot(cellGradient, mesh._cellNormals) cellUpValues = adjacentValues - 2 * dAP * cellNormalGradient cellLaplacian = (cellUpValues + adjacentValues - 2 * cellValues) / dAP**2 adjacentLaplacian = (adjacentUpValues + cellValues - 2 * adjacentValues) / dAP**2 adjacentLaplacian = adjacentLaplacian.filled(0) cellLaplacian = cellLaplacian.filled(0) mm = numerix.where( cellLaplacian * adjacentLaplacian < 0., 0., numerix.where( abs(cellLaplacian) > abs(adjacentLaplacian), adjacentLaplacian, cellLaplacian)) return FirstOrderAdvectionTerm._getDifferences( self, adjacentValues, cellValues, oldArray, cellToCellIDs, mesh) - mm * dAP / 2.
def _calcCellDistAndVec(self): tmp = numerix.take(self._cellCenters, self.faceCellIDs, axis=1) tmp = tmp[...,1,:] - tmp[...,0,:] tmp = MA.filled(MA.where(MA.getmaskarray(tmp), self._cellToFaceDistanceVectors[:,0], tmp)) cellDistanceVectors = tmp cellDistances = MA.filled(MA.sqrt(MA.sum(tmp * tmp, 0))) return cellDistances, cellDistanceVectors
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 _rightHandOrientation(self): faceVertexIDs = MA.filled(self.faceVertexIDs, 0) faceVertexCoords = numerix.take(self.vertexCoords, faceVertexIDs, axis=1) t1 = faceVertexCoords[:,1,:] - faceVertexCoords[:,0,:] t2 = faceVertexCoords[:,2,:] - faceVertexCoords[:,1,:] norm = numerix.cross(t1, t2, axis=0) ## reordering norm's internal memory for inlining norm = norm.copy() norm = norm / numerix.sqrtDot(norm, norm) faceNormals = -norm return 1 - 2 * (numerix.dot(faceNormals, self.cellDistanceVectors) < 0)
def _cellToCellIDs(self): ids = MA.zeros((6, self.nx, self.ny, self.nz), 'l') indices = numerix.indices((self.nx, self.ny, self.nz)) nxy = self.nx * self.ny same = indices[0] + indices[1] * self.nx + indices[2] * nxy ids[0] = same - 1 ids[1] = same + 1 ids[2] = same - self.nx ids[3] = same + self.nx ids[4] = same - nxy ids[5] = same + nxy if self.nx > 0: ids[0, 0, ...] = MA.masked ids[1, -1, ...] = MA.masked if self.ny > 0: ids[2,:, 0,:] = MA.masked ids[3,:, -1,:] = MA.masked if self.nz > 0: ids[4, ..., 0] = MA.masked ids[5, ..., -1] = MA.masked return MA.reshape(ids.swapaxes(1, 3), (6, self.numberOfCells))
def _cellToCellIDs(self): ids = MA.zeros((6, self.nx, self.ny, self.nz), 'l') indices = numerix.indices((self.nx, self.ny, self.nz)) nxy = self.nx * self.ny same = indices[0] + indices[1] * self.nx + indices[2] * nxy ids[0] = same - 1 ids[1] = same + 1 ids[2] = same - self.nx ids[3] = same + self.nx ids[4] = same - nxy ids[5] = same + nxy if self.nx > 0: ids[0, 0, ...] = MA.masked ids[1,-1, ...] = MA.masked if self.ny > 0: ids[2, :, 0, :] = MA.masked ids[3, :,-1, :] = MA.masked if self.nz > 0: ids[4, ..., 0] = MA.masked ids[5, ..., -1] = MA.masked return MA.reshape(ids.swapaxes(1,3), (6, self.numberOfCells))
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 _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 _calcFaceCenters(self): maskedFaceVertexIDs = MA.filled(self.faceVertexIDs, 0) faceVertexCoords = numerix.take(self.vertexCoords, maskedFaceVertexIDs, axis=1) if MA.getmask(self.faceVertexIDs) is False: faceVertexCoordsMask = numerix.zeros(numerix.shape(faceVertexCoords), 'l') else: faceVertexCoordsMask = \ numerix.repeat(MA.getmaskarray(self.faceVertexIDs)[numerix.newaxis,...], self.dim, axis=0) faceVertexCoords = MA.array(data=faceVertexCoords, mask=faceVertexCoordsMask) return MA.filled(MA.average(faceVertexCoords, axis=1))
def faceCellIDs(self): faceCellIDs = numerix.zeros((2, self.numberOfFaces), 'l') mask = numerix.zeros((2, self.numberOfFaces), 'l') inline._runInline(""" int ID = j * ni + i; int rowlength = ni * nj + Nhor + nj; faceCellIDs[ID + 0 * rowlength] = ID - ni; faceCellIDs[ID + 1 * rowlength] = ID; faceCellIDs[ID + Nhor + j + 0 * rowlength] = ID - 1; faceCellIDs[ID + Nhor + j + 1 * rowlength] = ID; if (j == 0) { faceCellIDs[ID + 0 * rowlength] = ID; mask[ID + 1 * rowlength] = 1; } if (j == nj - 1) { faceCellIDs[ID + ni + 0 * rowlength] = ID; mask[ID + ni + 1 * rowlength] = 1; } if (i == 0) { faceCellIDs[ID + Nhor + j + 0 * rowlength] = ID; mask[ID + Nhor + j + 1 * rowlength] = 1; } if ( i == ni - 1 ) { faceCellIDs[ID + Nhor + j + 1 + 0 * rowlength] = ID; mask[ID + Nhor + j + 1 + 1 * rowlength] = 1; } """, Nhor=self.numberOfHorizontalFaces, mask=mask, faceCellIDs=faceCellIDs, ni=self.nx, nj=self.ny) return MA.masked_where(mask, faceCellIDs)