def _calcGeomCoeff(self, var): self._checkCoeff(var) if var.rank != 0 and not isinstance(self.coeff, CellVariable): return self.coeff[..., numerix.newaxis] * numerix.resize( var.mesh.cellVolumes, var.shape) else: return self.coeff * numerix.resize(var.mesh.cellVolumes, var.shape)
def _createVertices(self): x = numerix.arange(self.nx + 1) * self.dx y = numerix.arange(self.ny + 1) * self.dy x = numerix.resize(x, (self.numberOfCornerVertices, )) y = numerix.repeat(y, self.nx + 1) boxCorners = numerix.array((x, y)) x = numerix.arange(0.5, self.nx + 0.5) * self.dx y = numerix.arange(0.5, self.ny + 0.5) * self.dy x = numerix.resize(x, (self.numberOfCenterVertices, )) y = numerix.repeat(y, self.nx) boxCenters = numerix.array((x, y)) return numerix.concatenate((boxCorners, boxCenters), axis=1)
def _createVertices(self): x = self._calcVertexCoordinates(self.dx, self.nx) x = numerix.resize(x, (self.numberOfVertices,)) y = self._calcVertexCoordinates(self.dy, self.ny) y = numerix.repeat(y, self.numberOfVerticalColumns) y = numerix.resize(y, (self.numberOfVertices,)) z = self._calcVertexCoordinates(self.dz, self.nz) z = numerix.repeat(z, self.numberOfHorizontalRows * self.numberOfVerticalColumns) z = numerix.resize(z, (self.numberOfVertices,)) return numerix.array((x, y, z))
def createVertices(dx, dy, dz, nx, ny, nz, numVertices, numHorizRows, numVertCols): x = _AbstractGridBuilder.calcVertexCoordinates(dx, nx) x = numerix.resize(x, (numVertices,)) y = _AbstractGridBuilder.calcVertexCoordinates(dy, ny) y = numerix.repeat(y, numVertCols) y = numerix.resize(y, (numVertices,)) z = _AbstractGridBuilder.calcVertexCoordinates(dz, nz) z = numerix.repeat(z, numHorizRows * numVertCols) z = numerix.resize(z, (numVertices,)) return numerix.array((x, y, z))
def _createVertices(self): x = numerix.arange(self.nx + 1) * self.dx y = numerix.arange(self.ny + 1) * self.dy x = numerix.resize(x, (self.numberOfCornerVertices,)) y = numerix.repeat(y, self.nx + 1) boxCorners = numerix.array((x, y)) x = numerix.arange(0.5, self.nx + 0.5) * self.dx y = numerix.arange(0.5, self.ny + 0.5) * self.dy x = numerix.resize(x, (self.numberOfCenterVertices,)) y = numerix.repeat(y, self.nx) boxCenters = numerix.array((x, y)) return numerix.concatenate((boxCorners, boxCenters), axis=1)
def createVertices(dx, dy, dz, nx, ny, nz, numVertices, numHorizRows, numVertCols): x = _AbstractGridBuilder.calcVertexCoordinates(dx, nx) x = numerix.resize(x, (numVertices, )) y = _AbstractGridBuilder.calcVertexCoordinates(dy, ny) y = numerix.repeat(y, numVertCols) y = numerix.resize(y, (numVertices, )) z = _AbstractGridBuilder.calcVertexCoordinates(dz, nz) z = numerix.repeat(z, numHorizRows * numVertCols) z = numerix.resize(z, (numVertices, )) return numerix.array((x, y, z))
def _reshapeIDs(self, var, ids): shape = (self._vectorSize(var), self._vectorSize(var), ids.shape[-1]) ids = numerix.resize(ids, shape) X, Y = numerix.indices(shape[:-1]) X *= var.mesh.numberOfCells ids += X[...,numerix.newaxis] return ids
def __mul__(self, factor): if numerix.shape(factor) is (): factor = numerix.resize(factor, (2, 1)) return UniformGrid2D(dx=self.args['dx'] * numerix.array(factor[0]), nx=self.args['nx'], dy=self.args['dy'] * numerix.array(factor[1]), ny=self.args['ny'], origin=numerix.array(self.args['origin']) * factor, overlap=self.args['overlap'])
def _getRotationTensor(self, mesh): if not hasattr(self, 'rotationTensor'): from fipy.variables.faceVariable import FaceVariable rotationTensor = FaceVariable(mesh=mesh, rank=2) rotationTensor[:, 0] = self._getNormals(mesh) if mesh.getDim() == 2: rotationTensor[:,1] = rotationTensor[:,0].dot((((0, 1), (-1, 0)))) elif mesh.getDim() ==3: epsilon = 1e-20 div = numerix.sqrt(1 - rotationTensor[2,0]**2) flag = numerix.resize(div > epsilon, (mesh.getDim(), mesh._getNumberOfFaces())) rotationTensor[0, 1] = 1 rotationTensor[:, 1] = numerix.where(flag, rotationTensor[:,0].dot((((0, 1, 0), (-1, 0, 0), (0, 0, 0)))) / div, rotationTensor[:, 1]) rotationTensor[1, 2] = 1 rotationTensor[:, 2] = numerix.where(flag, rotationTensor[:,0] * rotationTensor[2,0] / div, rotationTensor[:, 2]) rotationTensor[2, 2] = -div self.rotationTensor = rotationTensor return self.rotationTensor
def __getRotationTensor(self, mesh): if not hasattr(self, 'rotationTensor'): rotationTensor = FaceVariable(mesh=mesh, rank=2) rotationTensor[:, 0] = self._getNormals(mesh) if mesh.dim == 2: rotationTensor[:, 1] = rotationTensor[:, 0].dot( (((0, 1), (-1, 0)))) elif mesh.dim == 3: epsilon = 1e-20 div = numerix.sqrt(1 - rotationTensor[2, 0]**2) flag = numerix.resize(div > epsilon, (mesh.dim, mesh.numberOfFaces)) rotationTensor[0, 1] = 1 rotationTensor[:, 1] = numerix.where( flag, rotationTensor[:, 0].dot( (((0, 1, 0), (-1, 0, 0), (0, 0, 0)))) / div, rotationTensor[:, 1]) rotationTensor[1, 2] = 1 rotationTensor[:, 2] = numerix.where( flag, rotationTensor[:, 0] * rotationTensor[2, 0] / div, rotationTensor[:, 2]) rotationTensor[2, 2] = -div self.rotationTensor = rotationTensor return self.rotationTensor
def _reshapeIDs(self, var, ids): shape = (self._vectorSize(var), self._vectorSize(var), ids.shape[-1]) ids = numerix.resize(ids, shape) X, Y = numerix.indices(shape[:-1]) X *= var.mesh.numberOfCells ids += X[..., numerix.newaxis] return ids
def _createVertices(self): x = self._calcVertexCoordinates(self.dx, self.nx) x = numerix.resize(x, (self.numberOfVertices,)) y = self._calcVertexCoordinates(self.dy, self.ny) y = numerix.repeat(y, self.numberOfVerticalColumns) return numerix.array((x, y))
def createVertices(nx, ny, dx, dy, numVerts, numVertCols): x = _AbstractGridBuilder.calcVertexCoordinates(dx, nx) x = numerix.resize(x, (numVerts,)) y = _AbstractGridBuilder.calcVertexCoordinates(dy, ny) y = numerix.repeat(y, numVertCols) return numerix.array((x, y))
def createVertices(nx, ny, dx, dy, numVerts, numVertCols): x = _AbstractGridBuilder.calcVertexCoordinates(dx, nx) x = numerix.resize(x, (numVerts, )) y = _AbstractGridBuilder.calcVertexCoordinates(dy, ny) y = numerix.repeat(y, numVertCols) return numerix.array((x, y))
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 _makeValue(self, value, unit=None, array=None): ## --inline code often returns spurious results with noncontiguous ## arrays. A test case was put in _execInline(). The best fix turned out to ## be here. if (inline.doInline and hasattr(value, 'iscontiguous') and not value.iscontiguous()): value = value.copy() if isinstance(value, Variable): value = value.getValue() PF = physicalField.PhysicalField if not isinstance(value, PF): if getattr(self, 'value', None) is not None: v = self.value if isinstance(v, PF): v = self.value.value if type(value) in (type(1), type(1.)): if type(v) is type(numerix.array(1)): if v.shape is not (): ## if len(v) > 1: value = numerix.resize(value, v.shape).astype(v.dtype) if unit is not None or type(value) in [type(''), type(()), type([])]: value = PF(value=value, unit=unit, array=array) elif array is not None: array[:] = value value = array elif type(value) not in (type(None), type(numerix.array(1)), type(numerix.MA.array(1))): value = numerix.array(value) ## # numerix does strange things with really large integers. ## # Even though Python knows how to do arithmetic with them, ## # Numeric converts them to 'O' objects that it then doesn't understand. ## if value.typecode() == 'O': ## value = numerix.array(float(value)) if isinstance(value, PF) and value.getUnit().isDimensionless(): value = value.getNumericValue() return value
def _getNearestCellID(self, points): """ Test cases >>> from fipy import * >>> m0 = Grid2D(dx=(.1, 1., 10.), dy=(.1, 1., 10.)) >>> m1 = Grid2D(nx=2, ny=2, dx=5., dy=5.) >>> print m0._getNearestCellID(m1.getCellCenters().getGlobalValue()) [4 5 7 8] """ if self.globalNumberOfCells == 0: return numerix.arange(0) points = numerix.resize(points, (self.globalNumberOfCells, len(points), len(points[0]))).swapaxes(0,1) centers = self.getCellCenters().getGlobalValue()[...,numerix.newaxis] try: tmp = centers - points except TypeError: tmp = centers - PhysicalField(points) return numerix.argmin(numerix.dot(tmp, tmp, axis = 0), axis=0)
def _calcGeomCoeff(self, var): self._checkCoeff(var) if var.rank != 0 and not isinstance(self.coeff, CellVariable): return self.coeff[..., numerix.newaxis] * numerix.resize(var.mesh.cellVolumes, var.shape) else: return self.coeff * numerix.resize(var.mesh.cellVolumes, var.shape)
def _extrude(self, mesh, extrudeFunc, layers): ## should extrude cnahe self rather than creating a new mesh? ## the following allows the 2D mesh to be in 3D space, this can be the case for a ## Gmsh2DIn3DSpace which would then be extruded. oldVertices = mesh.vertexCoords if oldVertices.shape[0] == 2: oldVertices = numerix.resize(oldVertices, (3, len(oldVertices[0]))) oldVertices[2] = 0 NCells = mesh.numberOfCells NFac = mesh.numberOfFaces NFacPerCell = mesh._maxFacesPerCell ## set up the initial data arrays new_shape = (max(NFacPerCell, 4), (1 + layers)*NCells + layers*NFac) faces = numerix.MA.masked_values(-numerix.ones(new_shape, 'l'), value = -1) orderedVertices = mesh._orderedCellVertexIDs faces[:NFacPerCell, :NCells] = orderedVertices vertices = oldVertices vert0 = mesh.faceVertexIDs faceCount = NCells for layer in range(layers): ## need this later initialFaceCount = faceCount ## build the vertices newVertices = extrudeFunc(oldVertices) vertices = numerix.concatenate((vertices, newVertices), axis=1) ## build the faces along the layers faces[:NFacPerCell, faceCount: faceCount + NCells] = orderedVertices + len(oldVertices[0]) * (layer + 1) try: # numpy 1.1 doesn't copy right side before assigning slice # See: http://www.mail-archive.com/[email protected]/msg09843.html faces[:NFacPerCell, faceCount: faceCount + NCells] = faces[:NFacPerCell, faceCount: faceCount + NCells][::-1,:].copy() except: faces[:NFacPerCell, faceCount: faceCount + NCells] = faces[:NFacPerCell, faceCount: faceCount + NCells][::-1,:] faceCount = faceCount + NCells vert1 = (vert0 + len(oldVertices[0]))[::-1,:] ## build the faces between the layers faces[:4, faceCount: faceCount + NFac] = numerix.concatenate((vert0, vert1), axis = 0)[::-1,:] vert0 = vert0 + len(oldVertices[0]) NCells = mesh.numberOfCells ## build the cells, the first layer has slightly different ordering if layer == 0: c0 = numerix.reshape(numerix.arange(NCells), (1, NCells)) cells = numerix.concatenate((c0, c0 + NCells, mesh.cellFaceIDs + 2 * NCells), axis = 0) else: newCells = numerix.concatenate((c0, c0 + initialFaceCount, mesh.cellFaceIDs + faceCount), axis=0) newCells[0] = cells[1,-NCells:] cells = numerix.concatenate((cells, newCells), axis=1) ## keep a count of things for the next layer faceCount = faceCount + NFac oldVertices = newVertices ## return a new mesh, extrude could just as easily act on self return Mesh(vertices, faces, cells, communicator=mesh.communicator)
def _extrude(self, mesh, extrudeFunc, layers): ## should extrude self rather than creating a new mesh? ## the following allows the 2D mesh to be in 3D space, this can be the case for a ## Gmsh2DIn3DSpace which would then be extruded. oldVertices = mesh.vertexCoords if oldVertices.shape[0] == 2: oldVertices = numerix.resize(oldVertices, (3, len(oldVertices[0]))) oldVertices[2] = 0 NCells = mesh.numberOfCells NFac = mesh.numberOfFaces NFacPerCell = mesh._maxFacesPerCell ## set up the initial data arrays new_shape = (max(NFacPerCell, 4), (1 + layers)*NCells + layers*NFac) faces = numerix.MA.masked_values(-numerix.ones(new_shape, 'l'), value = -1) orderedVertices = mesh._orderedCellVertexIDs faces[:NFacPerCell, :NCells] = orderedVertices vertices = oldVertices vert0 = mesh.faceVertexIDs faceCount = NCells for layer in range(layers): ## need this later initialFaceCount = faceCount ## build the vertices newVertices = extrudeFunc(oldVertices) vertices = numerix.concatenate((vertices, newVertices), axis=1) ## build the faces along the layers faces[:NFacPerCell, faceCount: faceCount + NCells] = orderedVertices + len(oldVertices[0]) * (layer + 1) try: # numpy 1.1 doesn't copy right side before assigning slice # See: http://www.mail-archive.com/[email protected]/msg09843.html faces[:NFacPerCell, faceCount: faceCount + NCells] = faces[:NFacPerCell, faceCount: faceCount + NCells][::-1,:].copy() except: faces[:NFacPerCell, faceCount: faceCount + NCells] = faces[:NFacPerCell, faceCount: faceCount + NCells][::-1,:] faceCount = faceCount + NCells vert1 = (vert0 + len(oldVertices[0]))[::-1,:] ## build the faces between the layers faces[:4, faceCount: faceCount + NFac] = numerix.concatenate((vert0, vert1), axis = 0)[::-1,:] vert0 = vert0 + len(oldVertices[0]) NCells = mesh.numberOfCells ## build the cells, the first layer has slightly different ordering if layer == 0: c0 = numerix.reshape(numerix.arange(NCells), (1, NCells)) cells = numerix.concatenate((c0, c0 + NCells, mesh.cellFaceIDs + 2 * NCells), axis = 0) else: newCells = numerix.concatenate((c0, c0 + initialFaceCount, mesh.cellFaceIDs + faceCount), axis=0) newCells[0] = cells[1, -NCells:] cells = numerix.concatenate((cells, newCells), axis=1) ## keep a count of things for the next layer faceCount = faceCount + NFac oldVertices = newVertices ## return a new mesh, extrude could just as easily act on self return Mesh(vertices, faces, cells, communicator=mesh.communicator)
def _getAddedMeshValues(self, other, resolution=1e-2): """Calculate the parameters to define a concatenation of `other` with `self` :Parameters: - `other`: The :class:`~fipy.meshes.numMesh.Mesh` to concatenate with `self` - `resolution`: How close vertices have to be (relative to the smallest cell-to-cell distance in either mesh) to be considered the same :Returns: A `dict` with 3 elements: the new mesh vertexCoords, faceVertexIDs, and cellFaceIDs. """ selfc = self._getConcatenableMesh() other = other._getConcatenableMesh() selfNumFaces = selfc.faceVertexIDs.shape[-1] selfNumVertices = selfc.vertexCoords.shape[-1] otherNumFaces = other.faceVertexIDs.shape[-1] otherNumVertices = other.vertexCoords.shape[-1] ## check dimensions if(selfc.vertexCoords.shape[0] != other.vertexCoords.shape[0]): raise MeshAdditionError, "Dimensions do not match" ## compute vertex correlates ## only try to match exterior (X) vertices self_Xvertices = numerix.unique(selfc._getFaceVertexIDs().filled()[..., selfc.getExteriorFaces().getValue()].flatten()) other_Xvertices = numerix.unique(other._getFaceVertexIDs().filled()[..., other.getExteriorFaces().getValue()].flatten()) self_XvertexCoords = selfc.vertexCoords[..., self_Xvertices] other_XvertexCoords = other.vertexCoords[..., other_Xvertices] # lifted from Mesh._getNearestCellID() other_vertexCoordMap = numerix.resize(other_XvertexCoords, (self_XvertexCoords.shape[-1], other_XvertexCoords.shape[0], other_XvertexCoords.shape[-1])).swapaxes(0,1) tmp = self_XvertexCoords[..., numerix.newaxis] - other_vertexCoordMap closest = numerix.argmin(numerix.dot(tmp, tmp), axis=0) # just because they're closest, doesn't mean they're close tmp = self_XvertexCoords[..., closest] - other_XvertexCoords distance = numerix.sqrtDot(tmp, tmp) # only want vertex pairs that are 100x closer than the smallest # cell-to-cell distance close = distance < resolution * min(selfc._getCellToCellDistances().min(), other._getCellToCellDistances().min()) vertexCorrelates = numerix.array((self_Xvertices[closest[close]], other_Xvertices[close])) # warn if meshes don't touch, but allow it if (selfc._getNumberOfVertices() > 0 and other._getNumberOfVertices() > 0 and vertexCorrelates.shape[-1] == 0): import warnings warnings.warn("Vertices are not aligned", UserWarning, stacklevel=4) ## compute face correlates # ensure that both sets of faceVertexIDs have the same maximum number of (masked) elements self_faceVertexIDs = selfc.faceVertexIDs other_faceVertexIDs = other.faceVertexIDs diff = self_faceVertexIDs.shape[0] - other_faceVertexIDs.shape[0] if diff > 0: other_faceVertexIDs = numerix.append(other_faceVertexIDs, -1 * numerix.ones((diff,) + other_faceVertexIDs.shape[1:]), axis=0) other_faceVertexIDs = MA.masked_values(other_faceVertexIDs, -1) elif diff < 0: self_faceVertexIDs = numerix.append(self_faceVertexIDs, -1 * numerix.ones((-diff,) + self_faceVertexIDs.shape[1:]), axis=0) self_faceVertexIDs = MA.masked_values(self_faceVertexIDs, -1) # want self's Faces for which all faceVertexIDs are in vertexCorrelates self_matchingFaces = numerix.in1d(self_faceVertexIDs, vertexCorrelates[0]).reshape(self_faceVertexIDs.shape).all(axis=0).nonzero()[0] # want other's Faces for which all faceVertexIDs are in vertexCorrelates other_matchingFaces = numerix.in1d(other_faceVertexIDs, vertexCorrelates[1]).reshape(other_faceVertexIDs.shape).all(axis=0).nonzero()[0] # map other's Vertex IDs to new Vertex IDs, # accounting for overlaps with self's Vertex IDs vertex_map = numerix.empty(otherNumVertices, dtype=int) verticesToAdd = numerix.delete(numerix.arange(otherNumVertices), vertexCorrelates[1]) vertex_map[verticesToAdd] = numerix.arange(otherNumVertices - len(vertexCorrelates[1])) + selfNumVertices vertex_map[vertexCorrelates[1]] = vertexCorrelates[0] # calculate hashes of faceVertexIDs for comparing Faces if self_matchingFaces.shape[-1] == 0: self_faceHash = numerix.empty(self_matchingFaces.shape[:-1] + (0,), dtype="str") else: # sort each of self's Face's vertexIDs for canonical comparison self_faceHash = numerix.sort(self_faceVertexIDs[..., self_matchingFaces], axis=0) # then hash the Faces for comparison (NumPy set operations are only for 1D arrays) self_faceHash = numerix.apply_along_axis(str, axis=0, arr=self_faceHash) face_sort = numerix.argsort(self_faceHash) self_faceHash = self_faceHash[face_sort] self_matchingFaces = self_matchingFaces[face_sort] if other_matchingFaces.shape[-1] == 0: other_faceHash = numerix.empty(other_matchingFaces.shape[:-1] + (0,), dtype="str") else: # convert each of other's Face's vertexIDs to new IDs other_faceHash = vertex_map[other_faceVertexIDs[..., other_matchingFaces]] # sort each of other's Face's vertexIDs for canonical comparison other_faceHash = numerix.sort(other_faceHash, axis=0) # then hash the Faces for comparison (NumPy set operations are only for 1D arrays) other_faceHash = numerix.apply_along_axis(str, axis=0, arr=other_faceHash) face_sort = numerix.argsort(other_faceHash) other_faceHash = other_faceHash[face_sort] other_matchingFaces = other_matchingFaces[face_sort] self_matchingFaces = self_matchingFaces[numerix.in1d(self_faceHash, other_faceHash)] other_matchingFaces = other_matchingFaces[numerix.in1d(other_faceHash, self_faceHash)] faceCorrelates = numerix.array((self_matchingFaces, other_matchingFaces)) # warn if meshes don't touch, but allow it if (selfc._getNumberOfFaces() > 0 and other._getNumberOfFaces() > 0 and faceCorrelates.shape[-1] == 0): import warnings warnings.warn("Faces are not aligned", UserWarning, stacklevel=4) # map other's Face IDs to new Face IDs, # accounting for overlaps with self's Face IDs face_map = numerix.empty(otherNumFaces, dtype=int) facesToAdd = numerix.delete(numerix.arange(otherNumFaces), faceCorrelates[1]) face_map[facesToAdd] = numerix.arange(otherNumFaces - len(faceCorrelates[1])) + selfNumFaces face_map[faceCorrelates[1]] = faceCorrelates[0] other_faceVertexIDs = vertex_map[other.faceVertexIDs[..., facesToAdd]] # ensure that both sets of cellFaceIDs have the same maximum number of (masked) elements self_cellFaceIDs = selfc.cellFaceIDs other_cellFaceIDs = face_map[other.cellFaceIDs] diff = self_cellFaceIDs.shape[0] - other_cellFaceIDs.shape[0] if diff > 0: other_cellFaceIDs = numerix.append(other_cellFaceIDs, -1 * numerix.ones((diff,) + other_cellFaceIDs.shape[1:]), axis=0) other_cellFaceIDs = MA.masked_values(other_cellFaceIDs, -1) elif diff < 0: self_cellFaceIDs = numerix.append(self_cellFaceIDs, -1 * numerix.ones((-diff,) + self_cellFaceIDs.shape[1:]), axis=0) self_cellFaceIDs = MA.masked_values(self_cellFaceIDs, -1) # concatenate everything and return return { 'vertexCoords': numerix.concatenate((selfc.vertexCoords, other.vertexCoords[..., verticesToAdd]), axis=1), 'faceVertexIDs': numerix.concatenate((self_faceVertexIDs, other_faceVertexIDs), axis=1), 'cellFaceIDs': MA.concatenate((self_cellFaceIDs, other_cellFaceIDs), axis=1) }