def _calcInteriorAndExteriorCellIDs(self): try: import sets self.exteriorCellIDs = sets.Set(self.faceCellIDs[0, self.getExteriorFaces().getValue()]) self.interiorCellIDs = list(sets.Set(range(self.numberOfCells)) - self.exteriorCellIDs) self.exteriorCellIDs = list(self.exteriorCellIDs) except: self.exteriorCellIDs = self.faceCellIDs[0, self.getExteriorFaces().getValue()] tmp = numerix.zeros(self.numberOfCells) numerix.put(tmp, self.exteriorCellIDs, numerix.ones(len(self.exteriorCellIDs))) self.exteriorCellIDs = numerix.nonzero(tmp) self.interiorCellIDs = numerix.nonzero(numerix.logical_not(tmp))
def _calcInteriorAndExteriorCellIDs(self): try: import sys if sys.version_info < (2, 6): from sets import Set as set exteriorCellIDs = set(self.faceCellIDs[0, self._exteriorFaces.value]) interiorCellIDs = list(set(range(self.numberOfCells)) - self._exteriorCellIDs) exteriorCellIDs = list(self._exteriorCellIDs) except: exteriorCellIDs = self.faceCellIDs[0, self._exteriorFaces.value] tmp = numerix.zeros(self.numberOfCells, 'l') numerix.put(tmp, exteriorCellIDs, numerix.ones(len(exteriorCellIDs), 'l')) exteriorCellIDs = numerix.nonzero(tmp) interiorCellIDs = numerix.nonzero(numerix.logical_not(tmp)) return interiorCellIDs, exteriorCellIDs
def _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 _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 _connectFaces(self, faces0, faces1): """ Merge faces on the same mesh. This is used to create periodic meshes. The first list of faces, `faces1`, will be the faces that are used to add to the matrix diagonals. The faces in `faces2` will not be used. They aren't deleted but their adjacent cells are made to point at `faces1`. The list `faces2` are not altered, they still remain as members of exterior faces. >>> from fipy.meshes.nonUniformGrid2D import NonUniformGrid2D >>> mesh = NonUniformGrid2D(nx = 2, ny = 2, dx = 1., dy = 1.) >>> print((mesh.cellFaceIDs == [[0, 1, 2, 3], ... [7, 8, 10, 11], ... [2, 3, 4, 5], ... [6, 7, 9, 10]]).flatten().all()) # doctest: +PROCESSOR_0 True >>> mesh._connectFaces(numerix.nonzero(mesh.facesLeft), numerix.nonzero(mesh.facesRight)) >>> print((mesh.cellFaceIDs == [[0, 1, 2, 3], ... [7, 6, 10, 9], ... [2, 3, 4, 5], ... [6, 7, 9, 10]]).flatten().all()) # doctest: +PROCESSOR_0 True """ ## check for errors ## check that faces are members of exterior faces from fipy.variables.faceVariable import FaceVariable faces = FaceVariable(mesh=self, value=False) faces[faces0] = True faces[faces1] = True assert (faces | self.exteriorFaces == self.exteriorFaces).all() ## following assert checks number of faces are equal, normals are opposite and areas are the same assert numerix.allclose(numerix.take(self._areaProjections, faces0, axis=1), numerix.take(-self._areaProjections, faces1, axis=1)) ## extract the adjacent cells for both sets of faces faceCellIDs0 = self.faceCellIDs[0] faceCellIDs1 = self.faceCellIDs[1] ## set the new adjacent cells for `faces0` MA.put(faceCellIDs1, faces0, MA.take(faceCellIDs0, faces0)) MA.put(faceCellIDs0, faces0, MA.take(faceCellIDs0, faces1)) self.faceCellIDs[0] = faceCellIDs0 self.faceCellIDs[1] = faceCellIDs1 ## extract the face to cell distances for both sets of faces faceToCellDistances0 = self._faceToCellDistances[0] faceToCellDistances1 = self._faceToCellDistances[1] ## set the new faceToCellDistances for `faces0` MA.put(faceToCellDistances1, faces0, MA.take(faceToCellDistances0, faces0)) MA.put(faceToCellDistances0, faces0, MA.take(faceToCellDistances0, faces1)) self._faceToCellDistances[0] = faceToCellDistances0 self._faceToCellDistances[1] = faceToCellDistances1 ## calculate new cell distances and add them to faces0 numerix.put(self._cellDistances, faces0, MA.take(faceToCellDistances0 + faceToCellDistances1, faces0)) ## change the direction of the face normals for faces0 for dim in range(self.dim): faceNormals = self.faceNormals[dim].copy() numerix.put(faceNormals, faces0, MA.take(faceNormals, faces1)) self.faceNormals[dim] = faceNormals ## Cells that are adjacent to faces1 are changed to point at faces0 ## get the cells adjacent to faces1 faceCellIDs = MA.take(self.faceCellIDs[0], faces1) ## get all the adjacent faces for those particular cells cellFaceIDs = numerix.take(self.cellFaceIDs, faceCellIDs, axis=1) for i in range(cellFaceIDs.shape[0]): ## if the faces is a member of faces1 then change the face to point at ## faces0 cellFaceIDs[i] = MA.where(cellFaceIDs[i] == faces1, faces0, cellFaceIDs[i]) ## add those faces back to the main self.cellFaceIDs numerix.put(self.cellFaceIDs[i], faceCellIDs, cellFaceIDs[i]) ## calculate new topology self._setTopology() ## calculate new geometry self._handleFaceConnection() self.scale = self.scale['length']
def _getStructure(self): ##maxX = self.distanceVar.mesh.faceCenters[0].max() ##minX = self.distanceVar.mesh.faceCenters[0].min() IDs = numerix.nonzero(self.distanceVar._cellInterfaceFlag)[0] coordinates = numerix.take(numerix.array(self.distanceVar.mesh.cellCenters).swapaxes(0, 1), IDs) coordinates -= numerix.take(numerix.array(self.distanceVar.grad * self.distanceVar).swapaxes(0, 1), IDs) coordinates *= self.zoomFactor shiftedCoords = coordinates.copy() shiftedCoords[:, 0] = -coordinates[:, 0] ##+ (maxX - minX) coordinates = numerix.concatenate((coordinates, shiftedCoords)) from .lines import _getOrderedLines lines = _getOrderedLines(list(range(2 * len(IDs))), coordinates, thresholdDistance = self.distanceVar.mesh._cellDistances.min() * 10) data = numerix.take(self.surfactantVar, IDs) data = numerix.concatenate((data, data)) tmpIDs = numerix.nonzero(data > 0.0001)[0] if len(tmpIDs) > 0: val = numerix.take(data, tmpIDs).min() else: val = 0.0001 data = numerix.where(data < 0.0001, val, data) for line in lines: if len(line) > 2: for smooth in range(self.smooth): for arr in (coordinates, data): tmp = numerix.take(arr, line) tmp[1:-1] = tmp[2:] * 0.25 + tmp[:-2] * 0.25 + tmp[1:-1] * 0.5 if len(arr.shape) > 1: for i in range(len(arr[0])): arrI = arr[:, i].copy() numerix.put(arrI, line, tmp[:, i]) arr[:, i] = arrI else: numerix.put(arrI, line, tmp) name = self.title name = name.strip() if name == '': name = None coords = numerix.zeros((coordinates.shape[0], 3), 'd') coords[:, :coordinates.shape[1]] = coordinates import pyvtk ## making lists as pyvtk doesn't know what to do with numpy arrays coords = list(coords) coords = [[float(coord[0]), float(coord[1]), float(coord[2])] for coord in coords] data = list(data) data = [float(item) for item in data] return (pyvtk.UnstructuredGrid(points = coords, poly_line = lines), pyvtk.PointData(pyvtk.Scalars(data, name = name)))
def _getStructure(self): ##maxX = self.distanceVar.mesh.faceCenters[0].max() ##minX = self.distanceVar.mesh.faceCenters[0].min() IDs = numerix.nonzero(self.distanceVar._cellInterfaceFlag)[0] coordinates = numerix.take( numerix.array(self.distanceVar.mesh.cellCenters).swapaxes(0, 1), IDs) coordinates -= numerix.take( numerix.array(self.distanceVar.grad * self.distanceVar).swapaxes( 0, 1), IDs) coordinates *= self.zoomFactor shiftedCoords = coordinates.copy() shiftedCoords[:, 0] = -coordinates[:, 0] ##+ (maxX - minX) coordinates = numerix.concatenate((coordinates, shiftedCoords)) from lines import _getOrderedLines lines = _getOrderedLines( range(2 * len(IDs)), coordinates, thresholdDistance=self.distanceVar.mesh._cellDistances.min() * 10) data = numerix.take(self.surfactantVar, IDs) data = numerix.concatenate((data, data)) tmpIDs = numerix.nonzero(data > 0.0001)[0] if len(tmpIDs) > 0: val = numerix.take(data, tmpIDs).min() else: val = 0.0001 data = numerix.where(data < 0.0001, val, data) for line in lines: if len(line) > 2: for smooth in range(self.smooth): for arr in (coordinates, data): tmp = numerix.take(arr, line) tmp[1:-1] = tmp[2:] * 0.25 + tmp[:-2] * 0.25 + tmp[ 1:-1] * 0.5 if len(arr.shape) > 1: for i in range(len(arr[0])): arrI = arr[:, i].copy() numerix.put(arrI, line, tmp[:, i]) arr[:, i] = arrI else: numerix.put(arrI, line, tmp) name = self.title name = name.strip() if name == '': name = None coords = numerix.zeros((coordinates.shape[0], 3), 'd') coords[:, :coordinates.shape[1]] = coordinates import pyvtk ## making lists as pyvtk doesn't know what to do with numpy arrays coords = list(coords) coords = map( lambda coord: [float(coord[0]), float(coord[1]), float(coord[2])], coords) data = list(data) data = map(lambda item: float(item), data) return (pyvtk.UnstructuredGrid(points=coords, poly_line=lines), pyvtk.PointData(pyvtk.Scalars(data, name=name)))
def putIntoCellVariable(c, C): nxyz = C[0].shape[0] for i in range(len(C)): numerix.put(C[i], np.arange(nxyz), c[i * nxyz:(i + 1) * nxyz]) return C
def _connectFaces(self, faces0, faces1): """ Merge faces on the same mesh. This is used to create periodic meshes. The first list of faces, `faces1`, will be the faces that are used to add to the matrix diagonals. The faces in `faces2` will not be used. They aren't deleted but their adjacent cells are made to point at `faces1`. The list `faces2` are not altered, they still remain as members of exterior faces. >>> from fipy.meshes.numMesh.grid2D import Grid2D >>> mesh = Grid2D(nx = 2, ny = 2, dx = 1., dy = 1.) >>> from fipy.tools import parallel >>> print parallel.procID != 0 or (mesh._getCellFaceIDs() == [[0, 1, 2, 3], ... [7, 8, 10, 11], ... [2, 3, 4, 5], ... [6, 7, 9, 10]]).flatten().all() True >>> mesh._connectFaces(numerix.nonzero(mesh.getFacesLeft()), numerix.nonzero(mesh.getFacesRight())) >>> print parallel.procID != 0 or (mesh._getCellFaceIDs() == [[0, 1, 2, 3], ... [7, 6, 10, 9], ... [2, 3, 4, 5], ... [6, 7, 9, 10]]).flatten().all() True """ ## check for errors ## check that faces are members of exterior faces from fipy.variables.faceVariable import FaceVariable faces = FaceVariable(mesh=self, value=False) faces[faces0] = True faces[faces1] = True assert (faces | self.getExteriorFaces() == self.getExteriorFaces()).all() ## following assert checks number of faces are equal, normals are opposite and areas are the same assert numerix.alltrue(numerix.take(self.areaProjections, faces0, axis=1) == numerix.take(-self.areaProjections, faces1, axis=1)) ## extract the adjacent cells for both sets of faces faceCellIDs0 = self.faceCellIDs[0] faceCellIDs1 = self.faceCellIDs[1] ## set the new adjacent cells for `faces0` MA.put(faceCellIDs1, faces0, MA.take(faceCellIDs0, faces0)) MA.put(faceCellIDs0, faces0, MA.take(faceCellIDs0, faces1)) self.faceCellIDs[0] = faceCellIDs0 self.faceCellIDs[1] = faceCellIDs1 ## extract the face to cell distances for both sets of faces faceToCellDistances0 = self.faceToCellDistances[0] faceToCellDistances1 = self.faceToCellDistances[1] ## set the new faceToCellDistances for `faces0` MA.put(faceToCellDistances1, faces0, MA.take(faceToCellDistances0, faces0)) MA.put(faceToCellDistances0, faces0, MA.take(faceToCellDistances0, faces1)) self.faceToCellDistances[0] = faceToCellDistances0 self.faceToCellDistances[1] = faceToCellDistances1 ## calculate new cell distances and add them to faces0 numerix.put(self.cellDistances, faces0, MA.take(faceToCellDistances0 + faceToCellDistances1, faces0)) ## change the direction of the face normals for faces0 for dim in range(self.getDim()): faceNormals = self.faceNormals[dim].copy() numerix.put(faceNormals, faces0, MA.take(faceNormals, faces1)) self.faceNormals[dim] = faceNormals ## Cells that are adjacent to faces1 are changed to point at faces0 ## get the cells adjacent to faces1 faceCellIDs = MA.take(self.faceCellIDs[0], faces1) ## get all the adjacent faces for those particular cells cellFaceIDs = numerix.take(self.cellFaceIDs, faceCellIDs, axis=1) for i in range(cellFaceIDs.shape[0]): ## if the faces is a member of faces1 then change the face to point at ## faces0 cellFaceIDs[i] = MA.where(cellFaceIDs[i] == faces1, faces0, cellFaceIDs[i]) ## add those faces back to the main self.cellFaceIDs tmp = self.cellFaceIDs[i] numerix.put(tmp, faceCellIDs, cellFaceIDs[i]) self.cellFaceIDs[i] = tmp ## calculate new topology _CommonMesh._calcTopology(self) ## calculate new geometry self._calcFaceToCellDistanceRatio() self._calcCellToCellDistances() self._calcScaledGeometry() self._calcFaceAspectRatios()
def put(self, indices, value): if self.value is None: self.getValue() numerix.put(self.value, indices, value) self._markFresh()