def putDiagonal(self, vector): """ Put elements of `vector` along diagonal of matrix >>> L = _TrilinosMatrixFromShape(rows=3, cols=3) >>> L.putDiagonal((3., 10., numerix.pi)) >>> print(L) 3.000000 --- --- --- 10.000000 --- --- --- 3.141593 >>> L.putDiagonal((10., 3.)) >>> print(L) 10.000000 --- --- --- 3.000000 --- --- --- 3.141593 """ if type(vector) in [type(1), type(1.)]: ids = numerix.arange(self.matrix.NumGlobalRows()) tmp = numerix.zeros((self.matrix.NumGlobalRows), 'd') tmp[:] = vector if ids.dtype.name == 'int64': ids = ids.astype('int32') self.put(tmp, ids, ids) else: ids = numerix.arange(len(vector)) if ids.dtype.name == 'int64': ids = ids.astype('int32') self.put(vector, ids, ids)
def createCells(nx, ny, nz, numXYFaces, numXZFaces, numYZFaces): """ cells = (front face, back face, left face, right face, bottom face, top face) front and back faces are YZ faces left and right faces are XZ faces top and bottom faces are XY faces """ ## front and back faces frontFaces = numerix.arange(numYZFaces) frontFaces = vector.prune(frontFaces, nx + 1, nx) frontFaces = frontFaces + numXYFaces + numXZFaces backFaces = frontFaces + 1 ## left and right faces leftFaces = numerix.arange(nx * ny) leftFaces = _Grid3DBuilder._repeatWithOffset(leftFaces, nx * (ny + 1), nz) leftFaces = numerix.ravel(leftFaces) leftFaces = leftFaces + numXYFaces rightFaces = leftFaces + nx ## bottom and top faces bottomFaces = numerix.arange(nx * ny * nz) topFaces = bottomFaces + (nx * ny) return numerix.array((frontFaces, backFaces, leftFaces, rightFaces, bottomFaces, topFaces))
def _createCells(self): ## cells = (f1, f2, f3, f4) going anticlockwise. ## f1 etc. refer to the faces bottomFaces = numerix.arange(0, self.numberOfHorizontalFaces - self.nx) topFaces = numerix.arange(self.nx, self.numberOfHorizontalFaces) leftFaces = vector.prune( numerix.arange( self.numberOfHorizontalFaces, self.numberOfHorizontalFaces + self.numberOfVerticalFaces), self.nx + 1, self.nx) rightFaces = vector.prune( numerix.arange( self.numberOfHorizontalFaces, self.numberOfHorizontalFaces + self.numberOfVerticalFaces), self.nx + 1, 0) lowerLeftDiagonalFaces = numerix.arange( self.numberOfHorizontalFaces + self.numberOfVerticalFaces, self.numberOfHorizontalFaces + self.numberOfVerticalFaces + self.numberOfEachDiagonalFaces) lowerRightDiagonalFaces = lowerLeftDiagonalFaces + self.numberOfEachDiagonalFaces upperLeftDiagonalFaces = lowerRightDiagonalFaces + self.numberOfEachDiagonalFaces upperRightDiagonalFaces = upperLeftDiagonalFaces + self.numberOfEachDiagonalFaces ##faces in arrays, now get the cells bottomOfBoxCells = numerix.array( [bottomFaces, lowerRightDiagonalFaces, lowerLeftDiagonalFaces]) rightOfBoxCells = numerix.array( [rightFaces, upperRightDiagonalFaces, lowerRightDiagonalFaces]) topOfBoxCells = numerix.array( [topFaces, upperLeftDiagonalFaces, upperRightDiagonalFaces]) leftOfBoxCells = numerix.array( [leftFaces, lowerLeftDiagonalFaces, upperLeftDiagonalFaces]) return numerix.concatenate( (rightOfBoxCells, topOfBoxCells, leftOfBoxCells, bottomOfBoxCells), axis=1)
def _createFaces(self): """ v1, v2 refer to the vertices. Horizontal faces are first """ v1 = numerix.arange(self.numberOfVertices) v2 = v1 + 1 horizontalFaces = vector.prune(numerix.array((v1, v2)), self.numberOfVerticalColumns, self.nx, axis=1) v1 = numerix.arange(self.numberOfVertices - self.numberOfVerticalColumns) v2 = v1 + self.numberOfVerticalColumns verticalFaces = numerix.array((v1, v2)) ## The cell normals must point out of the cell. ## The left and bottom faces have only one neighboring cell, ## in the 2nd neighbor position (there is nothing in the 1st). ## ## reverse some of the face orientations to obtain the correct normals tmp = horizontalFaces.copy() horizontalFaces[0,:self.nx] = tmp[1,:self.nx] horizontalFaces[1,:self.nx] = tmp[0,:self.nx] self.numberOfHorizontalFaces = horizontalFaces.shape[-1] tmp = verticalFaces.copy() verticalFaces[0, :] = tmp[1, :] verticalFaces[1, :] = tmp[0, :] if self.numberOfVerticalColumns > 0: verticalFaces[0, ::self.numberOfVerticalColumns] = tmp[0, ::self.numberOfVerticalColumns] verticalFaces[1, ::self.numberOfVerticalColumns] = tmp[1,::self.numberOfVerticalColumns] return numerix.concatenate((horizontalFaces, verticalFaces), axis=1)
def _createCells(self): """ cells = (front face, back face, left face, right face, bottom face, top face) front and back faces are YZ faces left and right faces are XZ faces top and bottom faces are XY faces """ self.numberOfCells = self.nx * self.ny * self.nz ## front and back faces frontFaces = numerix.arange(self.numberOfYZFaces) frontFaces = vector.prune(frontFaces, self.nx + 1, self.nx) frontFaces = frontFaces + self.numberOfXYFaces + self.numberOfXZFaces backFaces = frontFaces + 1 ## left and right faces leftFaces = numerix.arange(self.nx * self.ny) leftFaces = self._repeatWithOffset(leftFaces, self.nx * (self.ny + 1), self.nz) leftFaces = numerix.ravel(leftFaces) leftFaces = leftFaces + self.numberOfXYFaces rightFaces = leftFaces + self.nx ## bottom and top faces bottomFaces = numerix.arange(self.nx * self.ny * self.nz) topFaces = bottomFaces + (self.nx * self.ny) return numerix.array((frontFaces, backFaces, leftFaces, rightFaces, bottomFaces, topFaces))
def putDiagonal(self, vector): """ Put elements of `vector` along diagonal of matrix >>> L = _TrilinosMatrix(size=3) >>> L.putDiagonal((3.,10.,numerix.pi)) >>> print L 3.000000 --- --- --- 10.000000 --- --- --- 3.141593 >>> L.putDiagonal((10.,3.)) >>> print L 10.000000 --- --- --- 3.000000 --- --- --- 3.141593 """ if type(vector) in [type(1), type(1.)]: ids = numerix.arange(self._getMatrix().NumGlobalRows()) tmp = numerix.zeros((self._getMatrix().NumGlobalRows), 'd') tmp[:] = vector if ids.dtype.name == 'int64': ids = ids.astype('int32') self.put(tmp, ids, ids) else: ids = numerix.arange(len(vector)) if ids.dtype.name == 'int64': ids = ids.astype('int32') self.put(vector, ids, ids)
def addAtDiagonal(self, vector): if type(vector) in [type(1), type(1.)]: ids = numerix.arange(self._getMatrix().GetMyRows()) tmp = numerix.zeros((self._getMatrix().GetMyRows(),), 'd') tmp[:] = vector self.addAt(tmp, ids, ids) else: ids = numerix.arange(len(vector)) self.addAt(vector, ids, ids)
def addAtDiagonal(self, vector): if type(vector) in [type(1), type(1.)]: ids = numerix.arange(self._getShape()[0]) tmp = numerix.zeros((self._getShape()[0],), 'd') tmp[:] = vector self.addAt(tmp, ids, ids) else: ids = numerix.arange(len(vector)) self.addAt(vector, ids, ids)
def addAtDiagonal(self, vector): if isinstance(vector, (int, float)): ids = numerix.arange(self._shape[0]) tmp = numerix.zeros((self._shape[0],), 'd') tmp[:] = vector self.addAt(tmp, ids, ids) else: ids = numerix.arange(len(vector)) self.addAt(vector, ids, ids)
def addAtDiagonal(self, vector): if type(vector) in [type(1), type(1.)]: ids = numerix.arange(self._shape[0]) tmp = numerix.zeros((self._shape[0],), 'd') tmp[:] = vector self.addAt(tmp, ids, ids) else: ids = numerix.arange(len(vector)) self.addAt(vector, ids, ids)
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 _exteriorFaces(self): """ Return only the faces that have one neighboring cell. """ exteriorIDs = numerix.concatenate((numerix.arange(0, self.nx), numerix.arange(0, self.nx) + self.nx * self.ny, numerix.arange(0, self.ny) * self.numberOfVerticalColumns + self.numberOfHorizontalFaces, numerix.arange(0, self.ny) * self.numberOfVerticalColumns + self.numberOfHorizontalFaces + self.nx)) from fipy.variables.faceVariable import FaceVariable exteriorFaces = FaceVariable(mesh=self, value=False) exteriorFaces[exteriorIDs] = True return exteriorFaces
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 addAtDiagonal(self, vector): if isinstance(vector, (int, float)): if hasattr(self.matrix, 'GetMyRows'): Nrows = self.matrix.GetMyRows() else: Nrows = self.matrix.NumMyRows() ids = numerix.arange(Nrows) tmp = numerix.zeros((Nrows, ), 'd') tmp[:] = vector self.addAt(tmp, ids, ids) else: ids = numerix.arange(len(vector)) self.addAt(vector, ids, ids)
def quiver(self, sparsity=None, scale=None): var = self.vars[0] mesh = var.mesh if isinstance(var, FaceVariable): N = mesh.numberOfFaces X, Y = mesh.faceCenters elif isinstance(var, CellVariable): N = mesh.numberOfCells X, Y = mesh.cellCenters if sparsity is not None and N > sparsity: XYrand = numerix.random.random((2, sparsity)) XYrand = numerix.array([[min(X)], [min(Y)]]) + XYrand * numerix.array([[max(X) - min(X)], [max(Y) - min(Y)]]) self.indices = numerix.nearest(numerix.array([X, Y]), XYrand) else: self.indices = numerix.arange(N) X = numerix.take(X, self.indices) Y = numerix.take(Y, self.indices) U = V = numerix.ones(X.shape, 'l') if hasattr(self, "_quiver"): self._quiver.remove() self._quiver = self.axes.quiver(X, Y, U, V, scale=scale, pivot='middle')
def VTKFaceDataSet(self): """Returns a TVTK `DataSet` representing the face centers of this mesh """ try: from tvtk.api import tvtk except ImportError as e: from enthought.tvtk.api import tvtk points = self.faceCenters points = self._toVTK3D(numerix.array(points)) ug = tvtk.UnstructuredGrid(points=points) num = len(points) counts = numerix.array([1] * num)[..., numerix.newaxis] cells = numerix.arange(self.numberOfFaces)[..., numerix.newaxis] cells = numerix.concatenate((counts, cells), axis=1) cell_types = numerix.array([tvtk.Vertex().cell_type]*num) cell_array = tvtk.CellArray() cell_array.set_cells(num, cells) counts = numerix.array([1] * num) offset = numerix.cumsum(counts+1) if len(offset) > 0: offset -= offset[0] ug.set_cells(cell_types, offset, cell_array) return ug
def _buildMatrix(self, var, SparseMatrix, boundaryConditions=(), dt=None, transientGeomCoeff=None, diffusionGeomCoeff=None): var, L, b = FaceTerm._buildMatrix(self, var, SparseMatrix, boundaryConditions=boundaryConditions, dt=dt, transientGeomCoeff=transientGeomCoeff, diffusionGeomCoeff=diffusionGeomCoeff) ## if var.rank != 1: mesh = var.mesh if (not hasattr(self, 'constraintL')) or (not hasattr(self, 'constraintB')): constraintMask = var.faceGrad.constraintMask | var.arithmeticFaceValue.constraintMask weight = self._getWeight(var, transientGeomCoeff, diffusionGeomCoeff) if 'implicit' in weight: alpha = weight['implicit']['cell 1 diag'] else: alpha = 0.0 exteriorCoeff = self.coeff * mesh.exteriorFaces self.constraintL = (alpha * constraintMask * exteriorCoeff).divergence * mesh.cellVolumes self.constraintB = -((1 - alpha) * var.arithmeticFaceValue * constraintMask * exteriorCoeff).divergence * mesh.cellVolumes ids = self._reshapeIDs(var, numerix.arange(mesh.numberOfCells)) L.addAt(numerix.array(self.constraintL).ravel(), ids.ravel(), ids.swapaxes(0, 1).ravel()) b += numerix.reshape(self.constraintB.value, ids.shape).sum(0).ravel() return (var, L, b)
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 _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 quiver(self, sparsity=None, scale=None): var = self.vars[0] mesh = var.getMesh() if isinstance(var, FaceVariable): N = mesh._getNumberOfFaces() V = mesh._getFaceAreas() X, Y = mesh.getFaceCenters() elif isinstance(var, CellVariable): N = mesh.getNumberOfCells() V = mesh.getCellVolumes() X, Y = mesh.getCellCenters() if sparsity is not None and N > sparsity: self.indices = numerix.random.rand(N) * V self.indices = self.indices.argsort()[-sparsity:] else: self.indices = numerix.arange(N) X = numerix.take(X, self.indices) Y = numerix.take(Y, self.indices) U = V = numerix.ones(X.shape) import pylab pylab.ion() pylab.cla() self._quiver = pylab.quiver(X, Y, U, V, scale=scale) pylab.ioff()
def _getNearestCellID(self, points): """ Test cases >>> from fipy import * >>> m = Grid1D(nx=3) >>> print(m._getNearestCellID(([0., .9, 3.],))) [0 0 2] >>> print(m._getNearestCellID(([1.1],))) [1] >>> m0 = Grid1D(nx=2, dx=1.) >>> m1 = Grid1D(nx=4, dx=.5) >>> print(m0._getNearestCellID(m1.cellCenters.globalValue)) [0 0 1 1] """ nx = self.globalNumberOfCells if nx == 0: return numerix.arange(0) x0, = self.cellCenters.globalValue[..., 0] xi, = points dx = self.dx i = numerix.array(numerix.rint(((xi - x0) / dx)), 'l') i[i < 0] = 0 i[i > nx - 1] = nx - 1 return i
def _adjacentCellIDs(self): c1 = numerix.arange(self.numberOfFaces) ids = numerix.array((c1 - 1, c1)) if self.numberOfFaces > 0: ids[0, 0] = ids[1, 0] ids[1, -1] = ids[0, -1] return ids[0], ids[1]
def quiver(self, sparsity=None, scale=None): var = self.vars[0] mesh = var.mesh if isinstance(var, FaceVariable): N = mesh.numberOfFaces X, Y = mesh.faceCenters elif isinstance(var, CellVariable): N = mesh.numberOfCells X, Y = mesh.cellCenters if sparsity is not None and N > sparsity: XYrand = numerix.random.random((2, sparsity)) XYrand = numerix.array([ [min(X)], [min(Y)] ]) + XYrand * numerix.array([[max(X) - min(X)], [max(Y) - min(Y)]]) self.indices = numerix.nearest(numerix.array([X, Y]), XYrand) else: self.indices = numerix.arange(N) X = numerix.take(X, self.indices) Y = numerix.take(Y, self.indices) U = V = numerix.ones(X.shape, 'l') if hasattr(self, "_quiver"): self._quiver.remove() self._quiver = self.axes.quiver(X, Y, U, V, scale=scale, pivot='middle')
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 _getNearestCellID(self, points): """ Test cases >>> from fipy import * >>> m = Grid1D(nx=3) >>> print m._getNearestCellID(([0., .9, 3.],)) [0 0 2] >>> print m._getNearestCellID(([1.1],)) [1] >>> m0 = Grid1D(nx=2, dx=1.) >>> m1 = Grid1D(nx=4, dx=.5) >>> print m0._getNearestCellID(m1.getCellCenters().getGlobalValue()) [0 0 1 1] """ nx = self.globalNumberOfCells if nx == 0: return numerix.arange(0) x0, = self.getCellCenters().getGlobalValue()[..., 0] xi, = points dx = self.dx i = numerix.array(numerix.rint(((xi - x0) / dx)), "l") i[i < 0] = 0 i[i > nx - 1] = nx - 1 return i
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 _getAdjacentCellIDs(self): c1 = numerix.arange(self.numberOfFaces) ids = numerix.array((c1 - 1, c1)) if self.numberOfFaces > 0: ids[0, 0] = ids[1, 0] ids[1, -1] = ids[0, -1] return ids[0], ids[1]
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 _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 test_finalize(self, model): eqn = ModelEquation(model, 'domain.abc', coeff=3) assert not eqn.finalized model.get_object.return_value = rv = mock.MagicMock(CellVariable) eqn.var.unit.name.return_value = 'mol/l' varpath = 'domain.var1' coeff = 1.1 # model.get_object.return_value = rv = mock.MagicMock(CellVariable) rv.as_term = mock.Mock(return_value=mock.MagicMock(CellVariable)) eqn.add_diffusion_term_from(varpath, coeff) print(eqn.var) with mock.patch('fipy.tools.numerix.zeros_like') as npMock: npMock.return_value = np.arange(10) eqn.finalize() assert eqn.finalized eqn.finalize()
def _getLocalOverlappingCellIDs(self): """ Return the IDs of the local mesh in isolation. Includes the IDs of boundary cells. .. note:: Trivial except for parallel meshes """ return numerix.arange(0, self.ny * self.nx * self.nz)
def solve_light(self, save = False): self.light = AM1_5(orientation=[[1]], faces=self.illuminatedFaces) # sample the light source from 300 nm to 1 um at 10 nm intervals self.diode.illuminate(self.light(wavelength=numerix.arange(300e-9, 1000e-9, 10e-9))) # m self.diode.solve(solver=None, sweeps=10, outer_tol=1e4) if save == True: self.diode.save('light{Na}.band'.format(Na=self.Na))
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 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 _createFaces(self): """ XY faces are first, then XZ faces, then YZ faces """ ## do the XY faces v1 = numerix.arange((self.nx + 1) * (self.ny)) v1 = vector.prune(v1, self.nx + 1, self.nx) v1 = self._repeatWithOffset(v1, (self.nx + 1) * (self.ny + 1), self.nz + 1) v2 = v1 + 1 v3 = v1 + (self.nx + 2) v4 = v1 + (self.nx + 1) XYFaces = numerix.array((v1, v2, v3, v4)) ## do the XZ faces v1 = numerix.arange((self.nx + 1) * (self.ny + 1)) v1 = vector.prune(v1, self.nx + 1, self.nx) v1 = self._repeatWithOffset(v1, (self.nx + 1) * (self.ny + 1), self.nz) v2 = v1 + 1 v3 = v1 + ((self.nx + 1)*(self.ny + 1)) + 1 v4 = v1 + ((self.nx + 1)*(self.ny + 1)) XZFaces = numerix.array((v1, v2, v3, v4)) ## do the YZ faces v1 = numerix.arange((self.nx + 1) * self.ny) v1 = self._repeatWithOffset(v1, (self.nx + 1) * (self.ny + 1), self.nz) v2 = v1 + (self.nx + 1) v3 = v1 + ((self.nx + 1)*(self.ny + 1)) + (self.nx + 1) v4 = v1 + ((self.nx + 1)*(self.ny + 1)) YZFaces = numerix.array((v1, v2, v3, v4)) ## reverse some of the face orientations to obtain the correct normals ##tmp = horizontalFaces.copy() ##horizontalFaces[:self.nx, 0] = tmp[:self.nx, 1] ##horizontalFaces[:self.nx, 1] = tmp[:self.nx, 0] ##tmp = verticalFaces.copy() ##verticalFaces[:, 0] = tmp[:, 1] ##verticalFaces[:, 1] = tmp[:, 0] ##verticalFaces[::(self.nx + 1), 0] = tmp[::(self.nx + 1), 0] ##verticalFaces[::(self.nx + 1), 1] = tmp[::(self.nx + 1), 1] self.numberOfXYFaces = (self.nx * self.ny * (self.nz + 1)) self.numberOfXZFaces = (self.nx * (self.ny + 1) * self.nz) self.numberOfYZFaces = ((self.nx + 1) * self.ny * self.nz) self.numberOfFaces = self.numberOfXYFaces + self.numberOfXZFaces + self.numberOfYZFaces return numerix.concatenate((XYFaces, XZFaces, YZFaces), axis=1)
def createCells(nx): """ cells = (f1, f2) going left to right. f1 etc. refer to the faces """ f1 = numerix.arange(nx) f2 = f1 + 1 return numerix.array((f1, f2))
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 createCells(nx): """ `cells = (f1, f2)` going left to right. `f1` etc. refer to the faces """ f1 = numerix.arange(nx) f2 = f1 + 1 return numerix.array((f1, f2))
def __call__(self): 'Return the locations of the ticks' b = self._base vmin, vmax = self.axis.get_view_interval() if vmax < vmin: vmin, vmax = vmax, vmin if vmax * vmin > 0: raise ValueError( "The interval must range from negative to positive values") ticklocs = [] for limit, sgn in zip([vmax, -vmin], [1, -1]): numdec = numerix.floor(limit + self.threshold) - numerix.ceil( self.threshold) if self._subs is None: # autosub if numdec > 10: subs = numerix.array([1.0]) elif numdec > 6: subs = numerix.arange(2.0, b, 2.0) else: subs = numerix.arange(2.0, b) subs = numerix.log(subs) / numerix.log(b) else: subs = self._subs if numdec == 0 and len(subs) == 1: subs = numerix.array( list(subs) + list( numerix.log(numerix.arange(2.0, b)) / numerix.log(b))) stride = 1 while numdec // stride + 1 > self.numticks: stride += 1 for decadeStart in numerix.arange( numerix.floor(self.threshold), numerix.ceil(limit + self.threshold) + stride, stride): ticks = subs + decadeStart - self.threshold ticklocs.extend(sgn * ticks.compress(ticks > 0)) return numerix.array(ticklocs)
def _localOverlappingCellIDs(self): """ Return the IDs of the local mesh in isolation. Includes the IDs of boundary cells. .. note:: Trivial except for parallel meshes """ return numerix.arange(0, self.mesh.ny * self.mesh.nx * self.mesh.nz)
def _createFaces(self): """ v1, v2 refer to the cells. Horizontel faces are first """ v1 = numerix.arange(self.numberOfCornerVertices) v2 = v1 + 1 horizontalFaces = vector.prune(numerix.array((v1, v2)), self.nx + 1, self.nx, axis=1) v1 = numerix.arange(self.numberOfCornerVertices - (self.nx + 1)) v2 = v1 + self.nx + 1 verticalFaces = numerix.array((v1, v2)) ## reverse some of the face orientations to obtain the correct normals tmp = horizontalFaces.copy() horizontalFaces[0, :self.nx] = tmp[1, :self.nx] horizontalFaces[1, :self.nx] = tmp[0, :self.nx] tmp = verticalFaces.copy() verticalFaces[0] = tmp[1] verticalFaces[1] = tmp[0] verticalFaces[0, ::(self.nx + 1)] = tmp[0, ::(self.nx + 1)] verticalFaces[1, ::(self.nx + 1)] = tmp[1, ::(self.nx + 1)] ## do the center ones now cellCenters = numerix.arange(self.numberOfCornerVertices, self.numberOfTotalVertices) lowerLefts = vector.prune( numerix.arange(self.numberOfCornerVertices - (self.nx + 1)), self.nx + 1, self.nx) lowerRights = lowerLefts + 1 upperLefts = lowerLefts + self.nx + 1 upperRights = lowerLefts + self.nx + 2 lowerLeftFaces = numerix.array((cellCenters, lowerLefts)) lowerRightFaces = numerix.array((lowerRights, cellCenters)) upperLeftFaces = numerix.array((cellCenters, upperLefts)) upperRightFaces = numerix.array((cellCenters, upperRights)) return numerix.concatenate( (horizontalFaces, verticalFaces, lowerLeftFaces, lowerRightFaces, upperLeftFaces, upperRightFaces), axis=1)
def solve_eqe(self, view=False, save = False): self.eqe_spectrum = self.diode.EQE(self.light, numerix.arange(320e-9,700e-9, 1e-9), path=None, adapt=True) if view ==True: import pylab pylab.figure() wavelength, eqe = zip(*self.eqe_spectrum) pylab.plot(wavelength,eqe) if save == True: self.save_eqe('eqe{Na}.eqe'.format(Na = self.Na))
def _buildMatrixNoInline_(self, L, oldArray, b, dt, coeffVectors): ids = self._reshapeIDs(oldArray, numerix.arange(oldArray.shape[-1])) b += (oldArray.value[numerix.newaxis] * coeffVectors['old value']).sum(-2).ravel() / dt b += coeffVectors['b vector'][numerix.newaxis].sum(-2).ravel() L.addAt(coeffVectors['new value'].ravel() / dt, ids.ravel(), ids.swapaxes(0, 1).ravel()) L.addAt(coeffVectors['diagonal'].ravel(), ids.ravel(), ids.swapaxes(0, 1).ravel())
def _getGlobalNonOverlappingCellIDs(self): """ Return the IDs of the local mesh in the context of the global parallel mesh. Does not include the IDs of boundary cells. .. note:: Trivial except for parallel meshes """ return numerix.arange((self.offset[2] + self.overlap['front']) * self.nx * self.ny, (self.offset[2] + self.nz - self.overlap['back']) * self.nx * self.ny)
def _getGlobalOverlappingCellIDs(self): """ Return the IDs of the local mesh in the context of the global parallel mesh. Includes the IDs of boundary cells. .. note:: Trivial except for parallel meshes """ return numerix.arange(self.offset[2] * self.nx * self.ny, (self.offset[2] + self.nz) * self.nx * self.ny)
def _createCellsPy(self): cellFaceIDs = numerix.zeros((4, self.nx * self.ny)) faceIDs = numerix.arange(self.numberOfFaces) if self.numberOfFaces > 0: cellFaceIDs[0,:] = faceIDs[:self.numberOfHorizontalFaces - self.nx] cellFaceIDs[2,:] = cellFaceIDs[0,:] + self.nx cellFaceIDs[1,:] = vector.prune(faceIDs[self.numberOfHorizontalFaces:], self.numberOfVerticalColumns) cellFaceIDs[3,:] = cellFaceIDs[1,:] - 1 return cellFaceIDs
def _getLocalNonOverlappingCellIDs(self): """ Return the IDs of the local mesh in isolation. Does not include the IDs of boundary cells. .. note:: Trivial except for parallel meshes """ return numerix.arange(self.overlap['front'] * self.nx * self.ny, (self.nz - self.overlap['back']) * self.nx * self.ny)
def _plot(self): ## pylab.clf() ## ## Added garbage collection since matplotlib objects seem to hang ## ## around and accumulate. ## import gc ## gc.collect() mesh = self.vars[0].mesh shape = mesh.shape X, Y = mesh.cellCenters Z = self.vars[0].value X, Y, Z = [v.reshape(shape, order="FORTRAN") for v in (X, Y, Z)] zmin, zmax = self._autoscale(vars=self.vars, datamin=self._getLimit( ('datamin', 'zmin')), datamax=self._getLimit( ('datamax', 'zmax'))) self.norm.vmin = zmin self.norm.vmax = zmax numberOfContours = 10 smallNumber = 1e-7 diff = zmax - zmin if diff < smallNumber: V = numerix.arange(numberOfContours + 1) * smallNumber / numberOfContours + zmin else: V = numerix.arange(numberOfContours + 1) * diff / numberOfContours + zmin self.axes.contourf(X, Y, Z, V, cmap=self.cmap) self.axes.set_xlim(xmin=self._getLimit('xmin'), xmax=self._getLimit('xmax')) self.axes.set_ylim(ymin=self._getLimit('ymin'), ymax=self._getLimit('ymax')) if self.colorbar is not None: self.colorbar.plot()
def _buildMatrix(self, var, SparseMatrix, boundaryConditions=(), dt=None, transientGeomCoeff=None, diffusionGeomCoeff=None): var, L, b = FaceTerm._buildMatrix( self, var, SparseMatrix, boundaryConditions=boundaryConditions, dt=dt, transientGeomCoeff=transientGeomCoeff, diffusionGeomCoeff=diffusionGeomCoeff) ## if var.rank != 1: mesh = var.mesh if (not hasattr(self, 'constraintL')) or (not hasattr( self, 'constraintB')): weight = self._getWeight(var, transientGeomCoeff, diffusionGeomCoeff) if 'implicit' in weight: alpha = weight['implicit']['cell 1 diag'] else: alpha = 0.0 alpha_constraint = numerix.where(var.faceGrad.constraintMask, 1.0, alpha) def divergence(face_value): return ( face_value * \ (var.faceGrad.constraintMask | var.arithmeticFaceValue.constraintMask) * \ self.coeff * mesh.exteriorFaces ).divergence * mesh.cellVolumes self.constraintL = divergence(alpha_constraint) dvar = (var.faceGrad * mesh._cellDistances * mesh.faceNormals).sum(axis=0) self.constraintB = divergence( (alpha_constraint - 1) * var.arithmeticFaceValue + (alpha - 1) * dvar * var.faceGrad.constraintMask) ids = self._reshapeIDs(var, numerix.arange(mesh.numberOfCells)) L.addAt( numerix.array(self.constraintL).ravel(), ids.ravel(), ids.swapaxes(0, 1).ravel()) b += numerix.reshape(self.constraintB.value, ids.shape).sum(0).ravel() return (var, L, b)
def _createCells(self): """ cells = (f1, f2, f3, f4) going anticlockwise. f1 etc. refer to the faces """ bottomFaces = numerix.arange(0, self.numberOfHorizontalFaces - self.nx) topFaces = numerix.arange(self.nx, self.numberOfHorizontalFaces) leftFaces = vector.prune(numerix.arange(self.numberOfHorizontalFaces, self.numberOfHorizontalFaces + self.numberOfVerticalFaces), self.nx + 1, self.nx) rightFaces = vector.prune(numerix.arange(self.numberOfHorizontalFaces, self.numberOfHorizontalFaces + self.numberOfVerticalFaces), self.nx + 1, 0) lowerLeftDiagonalFaces = numerix.arange(self.numberOfHorizontalFaces + self.numberOfVerticalFaces, self.numberOfHorizontalFaces + self.numberOfVerticalFaces + self.numberOfEachDiagonalFaces) lowerRightDiagonalFaces = lowerLeftDiagonalFaces + self.numberOfEachDiagonalFaces upperLeftDiagonalFaces = lowerRightDiagonalFaces + self.numberOfEachDiagonalFaces upperRightDiagonalFaces = upperLeftDiagonalFaces + self.numberOfEachDiagonalFaces ##faces in arrays, now get the cells bottomOfBoxCells = numerix.array([bottomFaces, lowerRightDiagonalFaces, lowerLeftDiagonalFaces]) rightOfBoxCells = numerix.array([rightFaces, upperRightDiagonalFaces, lowerRightDiagonalFaces]) topOfBoxCells = numerix.array([topFaces, upperLeftDiagonalFaces, upperRightDiagonalFaces]) leftOfBoxCells = numerix.array([leftFaces, lowerLeftDiagonalFaces, upperLeftDiagonalFaces]) return numerix.concatenate((rightOfBoxCells, topOfBoxCells, leftOfBoxCells, bottomOfBoxCells), axis=1)
def _interiorFaces(self): """ Return only the faces that have two neighboring cells. """ Hids = numerix.arange(0, self.numberOfHorizontalFaces) Hids = numerix.reshape(Hids, (self.numberOfHorizontalRows, self.nx)) Hids = Hids[1:-1, ...] Vids = numerix.arange(self.numberOfHorizontalFaces, self.numberOfFaces) Vids = numerix.reshape(Vids, (self.ny, self.numberOfVerticalColumns)) Vids = Vids[..., 1:-1] interiorIDs = numerix.concatenate((numerix.reshape(Hids, (self.nx * (self.ny - 1),)), numerix.reshape(Vids, ((self.nx - 1) * self.ny,)))) from fipy.variables.faceVariable import FaceVariable interiorFaces = FaceVariable(mesh=self, value=False) interiorFaces[interiorIDs] = True return interiorFaces
def _plot(self): ## plt.clf() ## ## Added garbage collection since matplotlib objects seem to hang ## ## around and accumulate. ## import gc ## gc.collect() mesh = self.vars[0].mesh x, y = mesh.cellCenters z = self.vars[0].value xmin, ymin = mesh.extents['min'] xmax, ymax = mesh.extents['max'] from matplotlib.mlab import griddata xi = numerix.linspace(xmin, xmax, 1000) yi = numerix.linspace(ymin, ymax, 1000) # grid the data. zi = griddata(x, y, z, xi, yi, interp='linear') if hasattr(self, "_contourSet"): for collection in self._contourSet.collections: try: ix = self.axes.collections.index(collection) except ValueError as e: ix = None if ix is not None: del self.axes.collections[ix] zmin, zmax = self._autoscale(vars=self.vars, datamin=self._getLimit(('datamin', 'zmin')), datamax=self._getLimit(('datamax', 'zmax'))) self.norm.vmin = zmin self.norm.vmax = zmax if self.levels is not None: levels = self.levels else: levels = numerix.arange(self.number + 1) * (zmax - zmin) / self.number + zmin self._contourSet = self.axes.contour(xi, yi, zi, levels=levels, cmap=self.cmap) self.axes.set_xlim(xmin=self._getLimit('xmin'), xmax=self._getLimit('xmax')) self.axes.set_ylim(ymin=self._getLimit('ymin'), ymax=self._getLimit('ymax')) if self.colorbar is not None: self.colorbar.plot()
def _localNonOverlappingCellIDs(self): """ Return the IDs of the local mesh in isolation. Does not include the IDs of boundary cells. .. note:: Trivial except for parallel meshes """ return numerix.arange( self.mesh.overlap['front'] * self.mesh.nx * self.mesh.ny, (self.mesh.nz - self.mesh.overlap['back']) * self.mesh.nx * self.mesh.ny)