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 _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 _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 _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 _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 _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 _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 _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 _calcFaceCellIDs(self): array = MA.array(MA.indices(self.cellFaceIDs.shape, 'l')[1], mask=MA.getmask(self.cellFaceIDs)) faceCellIDs = MA.zeros((2, self.numberOfFaces), 'l') ## Nasty bug: MA.put(arr, ids, values) fills its ids and ## values arguments when masked! This was not the behavior ## that was assumed when used below. It was only working ## because the old fill value was 0 and the first element of ## the array needed to be 0 since the cell's face was ## 0. numerix.put() has been changed to deal with this ## properly. ## MA.put(firstRow, cellFaceIDsFlat[::-1], array[::-1]) ## MA.put(secondRow, cellFaceIDsFlat, array) firstRow = faceCellIDs[0] secondRow = faceCellIDs[1] numerix.put(firstRow, self.cellFaceIDs[::-1, ::-1], array[::-1, ::-1]) numerix.put(secondRow, self.cellFaceIDs, array) mask = ((False, ) * self.numberOfFaces, (firstRow == secondRow)) return MA.sort(MA.array(faceCellIDs, mask=mask), axis=0)
def _calcFaceCellIDs(self): array = MA.array(MA.indices(self.cellFaceIDs.shape, 'l')[1], mask=MA.getmask(self.cellFaceIDs)) self.faceCellIDs = MA.zeros((2, self.numberOfFaces), 'l') ## Nasty bug: MA.put(arr, ids, values) fills its ids and ## values arguments when masked! This was not the behavior ## that was assumed when used below. It was only working ## because the old fill value was 0 and the first element of ## the array needed to be 0 since the cell's face was ## 0. numerix.put() has been changed to deal with this ## properly. ## MA.put(firstRow, cellFaceIDsFlat[::-1], array[::-1]) ## MA.put(secondRow, cellFaceIDsFlat, array) firstRow = self.faceCellIDs[0] secondRow = self.faceCellIDs[1] numerix.put(firstRow, self.cellFaceIDs[::-1,::-1], array[::-1,::-1]) numerix.put(secondRow, self.cellFaceIDs, array) mask = ((False,) * self.numberOfFaces, (firstRow == secondRow)) self.faceCellIDs = MA.sort(MA.array(self.faceCellIDs, mask = mask), axis=0)
def _getAddedMeshValues(self, other, smallNumber): """ Returns a `dictionary` with 3 elements: the new mesh vertexCoords, faceVertexIDs, and cellFaceIDs. """ other = other._getConcatenableMesh() selfNumFaces = self.faceVertexIDs.shape[-1] selfNumVertices = self.vertexCoords.shape[-1] otherNumFaces = other.faceVertexIDs.shape[-1] otherNumVertices = other.vertexCoords.shape[-1] ## check dimensions if(self.vertexCoords.shape[0] != other.vertexCoords.shape[0]): raise MeshAdditionError, "Dimensions do not match" ## compute vertex correlates vertexCorrelates = {} for i in range(selfNumVertices): for j in range(otherNumVertices): diff = self.vertexCoords[...,i] - other.vertexCoords[...,j] diff = numerix.array(diff) if (sum(diff ** 2) < smallNumber): vertexCorrelates[j] = i if (self._getNumberOfVertices() > 0 and other._getNumberOfVertices() > 0 and vertexCorrelates == {}): raise MeshAdditionError, "Vertices are not aligned" ## compute face correlates faceCorrelates = {} for i in range(otherNumFaces): ## Seems to be overwriting other.faceVertexIDs with new numpy ## currFace = other.faceVertexIDs[i] ## currFace = other.faceVertexIDs[...,i].copy() ## Changed this again as numpy 1.0.4 seems to have no copy method for ## masked arrays. try: currFace = other.faceVertexIDs[...,i].copy() except: currFace = MA.array(other.faceVertexIDs[...,i], mask=MA.getmask(other.faceVertexIDs[...,i])) keepGoing = 1 currIndex = 0 for item in currFace: if(vertexCorrelates.has_key(item)): currFace[currIndex] = vertexCorrelates[item] currIndex = currIndex + 1 else: keepGoing = 0 if(keepGoing == 1): for j in range(selfNumFaces): if (self._equalExceptOrder(currFace, self.faceVertexIDs[...,j])): faceCorrelates[i] = j if (self._getNumberOfFaces() > 0 and other._getNumberOfFaces() > 0 and faceCorrelates == {}): raise MeshAdditionError, "Faces are not aligned" faceIndicesToAdd = () for i in range(otherNumFaces): if(not faceCorrelates.has_key(i)): faceIndicesToAdd = faceIndicesToAdd + (i,) vertexIndicesToAdd = () for i in range(otherNumVertices): if(not vertexCorrelates.has_key(i)): vertexIndicesToAdd = vertexIndicesToAdd + (i,) ##compute the full face and vertex correlation list a = selfNumFaces for i in faceIndicesToAdd: faceCorrelates[i] = a a = a + 1 b = selfNumVertices for i in vertexIndicesToAdd: vertexCorrelates[i] = b b = b + 1 ## compute what the cells are that we need to add cellsToAdd = numerix.ones((self.cellFaceIDs.shape[0], other.cellFaceIDs.shape[-1])) cellsToAdd = -1 * cellsToAdd for j in range(other.cellFaceIDs.shape[-1]): for i in range(other.cellFaceIDs.shape[0]): cellsToAdd[i, j] = faceCorrelates[other.cellFaceIDs[i, j]] cellsToAdd = MA.masked_values(cellsToAdd, -1) ## compute what the faces are that we need to add facesToAdd = numerix.take(other.faceVertexIDs, faceIndicesToAdd, axis=1) for j in range(facesToAdd.shape[-1]): for i in range(facesToAdd.shape[0]): facesToAdd[i, j] = vertexCorrelates[facesToAdd[i, j]] ## compute what the vertices are that we need to add verticesToAdd = numerix.take(other.vertexCoords, vertexIndicesToAdd, axis=1) return { 'vertexCoords': numerix.concatenate((self.vertexCoords, verticesToAdd), axis=1), 'faceVertexIDs': numerix.concatenate((self.faceVertexIDs, facesToAdd), axis=1), 'cellFaceIDs': MA.concatenate((self.cellFaceIDs, cellsToAdd), axis=1) }
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)