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 _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 _buildMatrixPy(self, L, oldArray, b, dt, coeffVectors): N = len(oldArray) b += numerix.array(oldArray) * numerix.array(coeffVectors['old value']) / dt b += numerix.ones([N]) * numerix.array(coeffVectors['b vector']) L.addAtDiagonal(numerix.ones([N]) * numerix.array(coeffVectors['new value']) / dt) L.addAtDiagonal(numerix.ones([N]) * numerix.array(coeffVectors['diagonal']))
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 _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 _plot(self): self.g('set cbrange [' + self._getLimit(('datamin', 'zmin')) + ':' + self._getLimit(('datamax', 'zmax')) + ']') self.g('set view map') self.g('set style data pm3d') self.g('set pm3d at st solid') mesh = self.vars[0].mesh if self.vars[0]._variableClass is FaceVariable: x, y = mesh.faceCenters if isinstance(mesh, Grid2D.__class__): nx, ny = mesh.shape else: N = int(numerix.sqrt(mesh.numberOfCells)) nx, ny = N, N else: x, y = mesh.cellCenters N = int(numerix.sqrt(mesh.numberOfFaces)) nx, ny = N, N self.g('set dgrid3d %i, %i, 2' % (ny, nx)) import Gnuplot data = Gnuplot.Data(numerix.array(x), numerix.array(y), self.vars[0].value) self.g.splot(data)
def _explicitBuildMatrixIn(self, oldArray, id1, id2, b, weightedStencilCoeff, mesh, interiorFaces, dt, weight): oldArrayId1, oldArrayId2 = self._getOldAdjacentValues(oldArray, id1, id2, dt) coeff = numerix.array(self._getGeomCoeff(mesh)) Nfac = mesh._getNumberOfFaces() cell1Diag = numerix.zeros((Nfac,),'d') cell1Diag[:] = weight['cell 1 diag'] cell1OffDiag = numerix.zeros((Nfac,),'d') cell1OffDiag[:] = weight['cell 1 offdiag'] cell2Diag = numerix.zeros((Nfac,),'d') cell2Diag[:] = weight['cell 2 diag'] cell2OffDiag = numerix.zeros((Nfac,),'d') cell2OffDiag[:] = weight['cell 2 offdiag'] inline._runInline(""" long int faceID = faceIDs[i]; long int cellID1 = id1[i]; long int cellID2 = id2[i]; b[cellID1] += -coeff[faceID] * (cell1Diag[faceID] * oldArrayId1[i] + cell1OffDiag[faceID] * oldArrayId2[i]); b[cellID2] += -coeff[faceID] * (cell2Diag[faceID] * oldArrayId2[i] + cell2OffDiag[faceID] * oldArrayId1[i]); """,oldArrayId1 = numerix.array(oldArrayId1), oldArrayId2 = numerix.array(oldArrayId2), id1 = id1, id2 = id2, b = b, cell1Diag = cell1Diag, cell1OffDiag = cell1OffDiag, cell2Diag = cell2Diag, cell2OffDiag = cell2OffDiag, coeff = coeff, faceIDs = interiorFaces, ni = len(interiorFaces))
def _explicitBuildMatrixInline_(self, oldArray, id1, id2, b, coeffMatrix, mesh, interiorFaces, dt, weight): oldArrayId1, oldArrayId2 = self._getOldAdjacentValues(oldArray, id1, id2, dt) coeff = numerix.array(self._getGeomCoeff(oldArray)) Nfac = mesh.numberOfFaces cell1Diag = numerix.zeros((Nfac,), 'd') cell1Diag[:] = weight['cell 1 diag'] cell1OffDiag = numerix.zeros((Nfac,), 'd') cell1OffDiag[:] = weight['cell 1 offdiag'] cell2Diag = numerix.zeros((Nfac,), 'd') cell2Diag[:] = weight['cell 2 diag'] cell2OffDiag = numerix.zeros((Nfac,), 'd') cell2OffDiag[:] = weight['cell 2 offdiag'] inline._runInline(""" long int faceID = faceIDs[i]; long int cellID1 = id1[i]; long int cellID2 = id2[i]; b[cellID1] += -coeff[faceID] * (cell1Diag[faceID] * oldArrayId1[i] + cell1OffDiag[faceID] * oldArrayId2[i]); b[cellID2] += -coeff[faceID] * (cell2Diag[faceID] * oldArrayId2[i] + cell2OffDiag[faceID] * oldArrayId1[i]); """, oldArrayId1 = numerix.array(oldArrayId1), oldArrayId2 = numerix.array(oldArrayId2), id1 = id1, id2 = id2, b = b, cell1Diag = cell1Diag, cell1OffDiag = cell1OffDiag, cell2Diag = cell2Diag, cell2OffDiag = cell2OffDiag, coeff = coeff, faceIDs = interiorFaces, ni = len(interiorFaces))
def VTKCellDataSet(self): """Returns a TVTK `DataSet` representing the cells of this mesh """ cvi = self._orderedCellVertexIDs.swapaxes(0, 1) from fipy.tools import numerix if isinstance(cvi, numerix.ma.masked_array): counts = cvi.count(axis=1)[:, None] cells = numerix.ma.concatenate((counts, cvi), axis=1).compressed() else: counts = numerix.array([cvi.shape[1]]*cvi.shape[0])[:, None] cells = numerix.concatenate((counts, cvi), axis=1).flatten() try: from tvtk.api import tvtk except ImportError as e: from enthought.tvtk.api import tvtk num = counts.shape[0] cps_type = self._VTKCellType cell_types = numerix.array([cps_type]*num) cell_array = tvtk.CellArray() cell_array.set_cells(num, cells) points = self.vertexCoords points = self._toVTK3D(points) ug = tvtk.UnstructuredGrid(points=points) offset = numerix.cumsum(counts[:, 0]+1) if len(offset) > 0: offset -= offset[0] ug.set_cells(cell_types, offset, cell_array) return ug
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 _plot(self): self.g('set yrange [' + self._getLimit(('datamin', 'ymin', 'zmin')) + ':' + self._getLimit(('datamax', 'ymin', 'zmax')) + ']') tupleOfGnuplotData = () import Gnuplot import re m = re.match(r"\d+.\d+", Gnuplot.__version__) if m is None or float(m.group(0)) < 1.8: raise ImportError("Gnuplot.py version 1.8 or newer is required.") for var in self.vars: # Python 2.6 made 'with' a keyward (deprecation warnings have been issued since 2.5) # this was addressed in Gnuplot.py in r299, in 2007 if var._variableClass is not FaceVariable: X = var.mesh.cellCenters[0] else: X = var.mesh.faceCenters[0] tupleOfGnuplotData += (Gnuplot.Data(numerix.array(X), numerix.array(var), title=var.name, with_='lines'), ) apply(self.g.plot, tupleOfGnuplotData)
def _calcValueInline(self): NCells = self.mesh.numberOfCells ids = self.mesh.cellFaceIDs val = self._array.copy() inline._runInline(""" int i; for(i = 0; i < numberOfCells; i++) { int j; value[i] = 0.; for(j = 0; j < numberOfCellFaces; j++) { // cellFaceIDs can be masked, which caused subtle and // unreproduceable problems on OS X (who knows why not elsewhere) long id = ids[i + j * numberOfCells]; if (id >= 0) { value[i] += orientations[i + j * numberOfCells] * faceVariable[id]; } } value[i] = value[i] / cellVolume[i]; } """, numberOfCellFaces = self.mesh._maxFacesPerCell, numberOfCells = NCells, faceVariable = self.faceVariable.numericValue, ids = numerix.array(ids), value = val, orientations = numerix.array(self.mesh._cellToFaceOrientations), cellVolume = numerix.array(self.mesh.cellVolumes)) return self._makeValue(value = val)
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 _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 getVTKCellDataSet(self): """Returns a TVTK `DataSet` representing the cells of this mesh """ cvi = self._getOrderedCellVertexIDs().swapaxes(0,1) from fipy.tools import numerix if type(cvi) is numerix.ma.masked_array: counts = cvi.count(axis=1)[:,None] cells = numerix.ma.concatenate((counts,cvi),axis=1).compressed() else: counts = numerix.array([cvi.shape[1]]*cvi.shape[0])[:,None] cells = numerix.concatenate((counts,cvi),axis=1).flatten() from enthought.tvtk.api import tvtk num = counts.shape[0] cps_type = self._getVTKCellType() cell_types = numerix.array([cps_type]*num) cell_array = tvtk.CellArray() cell_array.set_cells(num, cells) points = self.getVertexCoords() points = self._toVTK3D(points) ug = tvtk.UnstructuredGrid(points=points) offset = numerix.cumsum(counts[:,0]+1) if len(offset) > 0: offset -= offset[0] ug.set_cells(cell_types, offset, cell_array) return ug
def _plot(self): self.g('set yrange [' + self._getLimit(('datamin', 'ymin', 'zmin')) + ':' + self._getLimit(('datamax', 'ymin', 'zmax')) + ']') tupleOfGnuplotData = () import Gnuplot import re m = re.match(r"\d+.\d+", Gnuplot.__version__) if m is None or float(m.group(0)) < 1.8: raise ImportError("Gnuplot.py version 1.8 or newer is required.") for var in self.vars: # Python 2.6 made 'with' a keyward (deprecation warnings have been issued since 2.5) # this was addressed in Gnuplot.py in r299, in 2007 if var._variableClass is not FaceVariable: X = var.mesh.cellCenters[0] else: X = var.mesh.faceCenters[0] tupleOfGnuplotData += (Gnuplot.Data(numerix.array(X), numerix.array(var), title=var.name, with_='lines'),) apply(self.g.plot, tupleOfGnuplotData)
def _levelSetNormals(self): """ Return the face level set normals. >>> from fipy.meshes import Grid2D >>> from fipy.variables.faceVariable import FaceVariable >>> 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 = FaceVariable(mesh=mesh, ... value=((0, 0, v, v, 0, 0, 0, v, 0, 0, v, 0), ... (0, 0, v, v, 0, 0, 0, v, 0, 0, v, 0))) >>> print numerix.allclose(distanceVariable._levelSetNormals, answer) True """ faceGrad = self.grad.arithmeticFaceValue faceGradMag = numerix.array(faceGrad.mag) faceGradMag = numerix.where(faceGradMag > 1e-10, faceGradMag, 1e-10) faceGrad = numerix.array(faceGrad) ## set faceGrad zero on exteriorFaces exteriorFaces = self.mesh.exteriorFaces if len(exteriorFaces.value) > 0: faceGrad[..., exteriorFaces.value] = 0. return faceGrad / faceGradMag
def _getArrays(self): arrays = [] for var in self.vars: arrays.append((numerix.array(var), numerix.array(var.mesh.cellCenters[0]))) return arrays
def _getArrays(self): arrays = [] for var in self.vars: arrays.append((numerix.array(var), numerix.array(var.getMesh().getCellCenters()[0]))) return arrays
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 _calcValueInline(self): id1, id2 = self.mesh._adjacentCellIDs tangents1 = self.mesh._faceTangents1 tangents2 = self.mesh._faceTangents2 val = self._array.copy() faceNormals = self.mesh._orientedFaceNormals if numerix.MA.isMaskedArray(faceNormals): faceNormals = faceNormals.filled() inline._runIterateElementInline( """ int j; double t1grad1, t1grad2, t2grad1, t2grad2, N, N2; int ID1 = ITEM(id1, i, NULL); int ID2 = ITEM(id2, i, NULL); if ITEM(exteriorFaces, i, NULL) { N2 = ITEM(facevar, i, NULL); } else { N2 = ITEM(var, ID2, NULL); } N = (N2 - ITEM(var, ID1, NULL)) / ITEM(dAP, i, NULL); t1grad1 = t1grad2 = t2grad1 = t2grad2 = 0.; t1grad1 += ITEM(tangents1, i, vec) * ITEM(cellGrad, ID1, vec); t1grad2 += ITEM(tangents1, i, vec) * ITEM(cellGrad, ID2, vec); t2grad1 += ITEM(tangents2, i, vec) * ITEM(cellGrad, ID1, vec); t2grad2 += ITEM(tangents2, i, vec) * ITEM(cellGrad, ID2, vec); ITEM(val, i, vec) = ITEM(normals, i, vec) * N; ITEM(val, i, vec) += ITEM(tangents1, i, vec) * (t1grad1 + t1grad2) / 2.; ITEM(val, i, vec) += ITEM(tangents2, i, vec) * (t2grad1 + t2grad2) / 2.; """, tangents1=tangents1, tangents2=tangents2, cellGrad=self.var.grad.numericValue, normals=faceNormals, id1=id1, id2=id2, dAP=numerix.array(self.mesh._cellDistances), var=self.var.numericValue, facevar=self.var.faceValue.numericValue, exteriorFaces=self.mesh.exteriorFaces.numericValue, val=val, ni=tangents1.shape[1], shape=numerix.array(numerix.shape(tangents1))) return self._makeValue(value=val)
def snapshot_var(V, base=False, to_unit=None): """ Utility to express a variable array as its numeric value and corresponding units Args: V (PhysicalField, Variable, CellVariable, binOp, np.ndarray, int, float): The variable base (bool): Whether to express in base units to_unit (str): Return array in these units. Ignored if `base = True` Returns: Tuple of (array, dict(unit=unit)) """ if isinstance(V, (PhysicalField, Variable, _BinaryTerm)): # This should also cover fipy.CellVariable and fipy.variables.binaryOperatorVariable.binOp Vunit = V.unit.name() try: if base: var = V.inBaseUnits() else: if to_unit: var = V.inUnitsOf(to_unit) else: var = V.inUnitsOf(V.unit) except: import logging logger = logging.getLogger(__name__) logger.error('V={!r} could not be expressed in units: {}'.format( V, V.unit), exc_info=True) raise if Vunit != '1': unit = var.unit.name() arr = np.array(var.value) else: arr = var unit = Vunit elif isinstance(V, np.ndarray): arr = V unit = '1' elif isinstance(V, (int, float)): arr = np.array(V) unit = '1' else: raise ValueError('Cannot snapshot variable of type {}'.format(type(V))) return arr, dict(unit=unit)
def _calcValueInline(self): id1, id2 = self.mesh._adjacentCellIDs tangents1 = self.mesh._faceTangents1 tangents2 = self.mesh._faceTangents2 val = self._array.copy() faceNormals = self.mesh._orientedFaceNormals if numerix.MA.isMaskedArray(faceNormals): faceNormals = faceNormals.filled() inline._runIterateElementInline(""" int j; double t1grad1, t1grad2, t2grad1, t2grad2, N, N2; int ID1 = ITEM(id1, i, NULL); int ID2 = ITEM(id2, i, NULL); if ITEM(exteriorFaces, i, NULL) { N2 = ITEM(facevar, i, NULL); } else { N2 = ITEM(var, ID2, NULL); } N = (N2 - ITEM(var, ID1, NULL)) / ITEM(dAP, i, NULL); t1grad1 = t1grad2 = t2grad1 = t2grad2 = 0.; t1grad1 += ITEM(tangents1, i, vec) * ITEM(cellGrad, ID1, vec); t1grad2 += ITEM(tangents1, i, vec) * ITEM(cellGrad, ID2, vec); t2grad1 += ITEM(tangents2, i, vec) * ITEM(cellGrad, ID1, vec); t2grad2 += ITEM(tangents2, i, vec) * ITEM(cellGrad, ID2, vec); ITEM(val, i, vec) = ITEM(normals, i, vec) * N; ITEM(val, i, vec) += ITEM(tangents1, i, vec) * (t1grad1 + t1grad2) / 2.; ITEM(val, i, vec) += ITEM(tangents2, i, vec) * (t2grad1 + t2grad2) / 2.; """, tangents1 = tangents1, tangents2 = tangents2, cellGrad = self.var.grad.numericValue, normals = faceNormals, id1 = id1, id2 = id2, dAP = numerix.array(self.mesh._cellDistances), var = self.var.numericValue, facevar = self.var.faceValue.numericValue, exteriorFaces = self.mesh.exteriorFaces.numericValue, val = val, ni = tangents1.shape[1], shape=numerix.array(numerix.shape(tangents1))) return self._makeValue(value = val)
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 _getDiagonalSign(self, transientGeomCoeff=None, diffusionGeomCoeff=None): if transientGeomCoeff is not None and diffusionGeomCoeff is not None: diagonalSign = numerix.where(numerix.array(numerix.all(transientGeomCoeff == 0, axis=-1)), numerix.array(2 * numerix.all(diffusionGeomCoeff[0] <= 0, axis=-1) - 1), numerix.array(2 * numerix.all(transientGeomCoeff >= 0, axis=-1) - 1)) elif transientGeomCoeff is not None: diagonalSign = 2 * numerix.all(transientGeomCoeff >= 0, axis=-1) - 1 elif diffusionGeomCoeff is not None: diagonalSign = 2 * numerix.all(diffusionGeomCoeff[0] <= 0, axis=-1) - 1 else: diagonalSign = 1 return diagonalSign
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 _getCstring(self, argDict={}, id="", freshen=None): """ Generate the string and dictionary to be used in inline >>> (Variable((1)))._getCstring(argDict={}) 'var' >>> (Variable((1,2,3,4)))._getCstring(argDict={}) 'var[i]' >>> (Variable(((1,2),(3,4))))._getCstring(argDict={}) 'var[i + j * ni]' >>> Variable((((1,2),(3,4)),((5,6),(7,8))))._getCstring(argDict={}) 'var[i + j * ni + k * ni * nj]' >>> (Variable(1) * Variable((1,2,3)))._getCstring(argDict={}) '(var0 * var1[i])' freshen is ignored """ identifier = 'var%s' % (id) v = self.getValue() if type(v) not in (type(numerix.array(1)),): varray = numerix.array(v) else: varray = v if len(varray.shape) == 0: if varray.dtype in (numerix.array(1).dtype,): argDict[identifier] = int(varray) elif varray.dtype in (numerix.array(1.).dtype,): argDict[identifier] = float(varray) else: argDict[identifier] = varray else: argDict[identifier] = varray try: shape = self.opShape except AttributeError: shape = self.shape if len(shape) == 0: ## return identifier + '(0)' return identifier else: return identifier + self._getCIndexString(shape)
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 extrude(self, extrudeFunc=lambda x: x + numerix.array((0, 0, 1))[:, numerix.newaxis] , layers=1): """ This function returns a new 3D mesh. The 2D mesh is extruded using the `extrudeFunc` and the number of layers. >>> from fipy.meshes.nonUniformGrid2D import NonUniformGrid2D >>> print(NonUniformGrid2D(nx=2, ny=2).extrude(layers=2).cellCenters) [[ 0.5 1.5 0.5 1.5 0.5 1.5 0.5 1.5] [ 0.5 0.5 1.5 1.5 0.5 0.5 1.5 1.5] [ 0.5 0.5 0.5 0.5 1.5 1.5 1.5 1.5]] >>> from fipy.meshes.tri2D import Tri2D >>> print(Tri2D().extrude(layers=2).cellCenters.allclose([[ 0.83333333, 0.5, 0.16666667, 0.5, 0.83333333, 0.5, ... 0.16666667, 0.5 ], ... [ 0.5, 0.83333333, 0.5, 0.16666667, 0.5, 0.83333333, ... 0.5, 0.16666667], ... [ 0.5, 0.5, 0.5, 0.5, 1.5, 1.5, 1.5, ... 1.5 ]])) True Parameters ---------- extrudeFunc : function Takes the vertex coordinates and returns the displaced values layers : int Number of layers in the extruded mesh (number of times `extrudeFunc` will be called) """ return self._extrude(self, extrudeFunc, layers)
def _putAdd(vector, ids, additionVector, mask=False): """This is a temporary replacement for Numeric.put as it was not doing what we thought it was doing. """ additionVector = numerix.array(additionVector) if numerix.sometrue(mask): if len(vector.shape) < len(additionVector.shape): for j in range(vector.shape[0]): for id, value, masked in zip(ids.flat, additionVector[j].flat, mask.flat): if not masked: vector[j].flat[id] += value else: for id, value, masked in zip(ids.flat, additionVector.flat, mask.flat): if not masked: vector.flat[id] += value else: if len(vector.shape) < len(additionVector.shape): for j in range(vector.shape[0]): for id, value in zip(ids.flat, additionVector[j].flat): vector[j].flat[id] += value else: for id, value in zip(ids.flat, additionVector.flat): vector.flat[id] += value
def _explicitBuildMatrix_(self, SparseMatrix, oldArray, id1, id2, b, weight, var, boundaryConditions, interiorFaces, dt): mesh = var.mesh coeffMatrix = self._getCoeffMatrix_(var, weight) self._explicitBuildMatrixInline_(oldArray=oldArray, id1=id1, id2=id2, b=b, coeffMatrix=coeffMatrix, mesh=var.mesh, interiorFaces=interiorFaces, dt=dt, weight=weight) N = mesh.numberOfCells M = mesh._maxFacesPerCell for boundaryCondition in boundaryConditions: LL, bb = boundaryCondition._buildMatrix(SparseMatrix, N, M, coeffMatrix) if LL != 0: ## b -= LL.takeDiagonal() * numerix.array(oldArray) b -= LL * numerix.array(oldArray) b += bb
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 _calcResidualVector(self, residualFn=None): if residualFn is not None: return residualFn(self.var, self.matrix, self.RHSvector) else: Lx = self.matrix * numerix.array(self.var).flatten() return Lx - self.RHSvector
def _getOrderedLines(IDs, coordinates, thresholdDistance = 0.0): """ This function takes a set of IDs and corresponding coordinates and makes a set of closed curves. :Parameters: - `IDs`: An array of integers. - `coordinates`: An array of coordinates of the same length as IDs. The following are a general set of test cases. >>> _getOrderedLines((0, 1, 2, 3), ((0, 0), (2, 0), (0, 1), (2, 1))) [[0, 2, 3, 1]] >>> _getOrderedLines((0, 1, 2, 3, 4), ((-10, -10), (0, 0), (2, 0), (0, 1), (2, 1))) [[0], [1, 3, 4, 2]] >>> _getOrderedLines((0, 1, 2, 3), ((0, 0), (0.9, 0), (0, 1), (1, 1))) [[0, 1, 3, 2]] >>> _getOrderedLines((0, 1, 2, 3, 4, 5), ((0, 0), (1, 0), (2, 0), (0, 1.1), (1, 1.1), (2, 1.1))) [[0, 1, 2, 5, 4, 3]] >>> _getOrderedLines((4, 5, 0, 1, 3, 2, 6), ((0, 0), (1, 0), (3, 0), (0, 1.1), (1, 1.1), (3, 1), (4, 1))) [[4, 5, 3, 1], [0, 2, 6]] >>> _getOrderedLines((4, 5, 3, 2, 1, 0, 9, 8, 7, 6), ((0, 0), (1, 0), (0, 1.1), (1, 1.1), (0, 3), (1, 3), (-1, 4), (2, 4), (-2, 4), (3, 4))) [[4, 5, 2, 3], [7, 9, 1, 0, 8, 6]] >>> from builtins import range >>> _getOrderedLines(list(range(7)), ((-7, 0), (-6, 0), (-5, 0), (0, 0), (5, 0), (6, 0), (7, 0))) [[0, 1, 2], [3], [4, 5, 6]] >>> from builtins import range >>> _getOrderedLines(list(range(7)), ((-7, 0), (-6, 0), (-5, 0), (0, 0), (5, 0), (6, 0), (7, 0)), thresholdDistance = 5.5) [[0, 1, 2, 3, 4, 5, 6]] """ from fipy.tools import numerix coordinates = numerix.array(coordinates) closeIDs = numerix.zeros((len(IDs), len(IDs)), 'l') vertices = [] for ID in IDs: distances = numerix.zeros(len(IDs), 'd') for i in range(len(coordinates[0,:])): distances += (coordinates[:, i] - coordinates[ID, i])**2 vertices.append(_Vertex(ID, coordinates[ID, 0], coordinates[ID, 1])) closeIDs[ID,:] = numerix.argsort(distances) for ID in IDs: i = 1 closeVertices = [] while i < 3 or vertices[ID].distance(vertices[closeIDs[ID, i]]) < thresholdDistance: closeVertices.append(vertices[closeIDs[ID, i]]) i += 1 vertices[ID].setCloseVertices(closeVertices) listOfVertexLists = [] for vertex in vertices: if not vertex.getInLine(): listOfVertexLists.append(_Line(vertex).getVertexListIDs()) return listOfVertexLists
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 put(self, vector, id1, id2, overlapping=False): """Put elements of `vector` at positions of the matrix corresponding to (`id1`, `id2`) Parameters ---------- vector : array_like The values to insert. id1 : array_like The row indices. id2 : array_like The column indices. overlapping : bool Whether to insert ghosted values or not (Ignored. Default False). Examples -------- >>> L = _ScipyMatrixFromShape(rows=3, cols=3) >>> L.put([3., 10., numerix.pi, 2.5], [0, 0, 1, 2], [2, 1, 1, 0]) >>> print(L) --- 10.000000 3.000000 --- 3.141593 --- 2.500000 --- --- """ assert len(id1) == len(id2) == len(vector) # done in such a way to vectorize everything tempVec = numerix.array(vector) - self.matrix[id1, id2].flat tempMat = sp.csr_matrix((tempVec, (id1, id2)), self.matrix.shape) self.matrix = self.matrix + tempMat
def _calcValue_(self, alpha, id1, id2): val = self._array.copy() inline._runIterateElementInline(""" int ID1 = ITEM(id1, i, NULL); int ID2 = ITEM(id2, i, NULL); double cell1 = ITEM(var, ID1, vec); double cell2 = ITEM(var, ID2, vec); double cell1Xcell2 = cell1 * cell2; double tmp = ((cell2 - cell1) * ITEM(alpha, i, NULL) + cell1); if (tmp != 0 && cell1Xcell2 > 0.) { ITEM(val, i, vec) = cell1Xcell2 / tmp; } else { ITEM(val, i, vec) = 0.; } """, var=self.var.numericValue, val=val, alpha=alpha, id1=id1, id2=id2, shape=numerix.array( numerix.shape(val)), ni=self.mesh.numberOfFaces) return self._makeValue(value=val)
def _globalMatrixAndVectors(self): if not hasattr(self, 'globalVectors'): globalMatrix = self.matrix.asTrilinosMeshMatrix() mesh = self.var.mesh localNonOverlappingCellIDs = mesh._localNonOverlappingCellIDs ## The following conditional is required because empty indexing is not altogether functional. ## This numpy.empty((0,))[[]] and this numpy.empty((0,))[...,[]] both work, but this ## numpy.empty((3, 0))[...,[]] is broken. if self.var.shape[-1] != 0: s = (Ellipsis, localNonOverlappingCellIDs) else: s = (localNonOverlappingCellIDs,) nonOverlappingVector = Epetra.Vector(globalMatrix.domainMap, self.var[s].ravel()) from fipy.variables.coupledCellVariable import _CoupledCellVariable if isinstance(self.RHSvector, _CoupledCellVariable): RHSvector = self.RHSvector[localNonOverlappingCellIDs] else: RHSvector = numerix.reshape(numerix.array(self.RHSvector), self.var.shape)[s].ravel() nonOverlappingRHSvector = Epetra.Vector(globalMatrix.rangeMap, RHSvector) del RHSvector overlappingVector = Epetra.Vector(globalMatrix.colMap, self.var) self.globalVectors = (globalMatrix, nonOverlappingVector, nonOverlappingRHSvector, overlappingVector) return self.globalVectors
def _trilinosToNumpyVector(v): """ Takes a distributed Trilinos vector and gives all processors a copy of it in a numpy vector. """ if(v.Comm().NumProc() == 1): return numerix.array(v) else: PersonalMap = Epetra.Map(-1, range(0, v.GlobalLength()), 0, v.Comm()) DistToPers = Epetra.Import(PersonalMap, v.Map()) PersonalV = Epetra.Vector(PersonalMap) PersonalV.Import(v, DistToPers, Epetra.Insert) return numerix.array(PersonalV)
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 __init__(self, dx=1., dy=1., dz=1., nx=None, ny=None, nz=None, overlap=2, communicator=parallelComm, *args, **kwargs): super(_BasePeriodicGrid3D, self).__init__(dx=dx, dy=dy, dz=dz, nx=nx, ny=ny, nz=nz, overlap=overlap, communicator=communicator, *args, **kwargs) self._nonPeriodicCellVertexIDs = super(_BasePeriodicGrid3D, self)._cellVertexIDs self._orderedCellVertexIDs_data = super(_BasePeriodicGrid3D, self)._orderedCellVertexIDs self._nonPeriodicCellFaceIDs = numerix.array( super(_BasePeriodicGrid3D, self).cellFaceIDs) self._makePeriodic()
def _calcValue_(self, alpha, id1, id2): distance = numerix.array(self.var) cell1 = numerix.take(distance, id1) cell2 = numerix.take(distance, id2) return numerix.where(numerix.logical_or(cell1 < 0, cell2 < 0), 0, self.diffusionCoeff)
def _getWeight(self, var, transientGeomCoeff=None, diffusionGeomCoeff=None): """ Test for a bug due to the sign operator not being updating correctly. >>> from fipy import * >>> m = Grid1D(nx=1) >>> v = CellVariable(mesh=m, value=1.) >>> eq = TransientTerm() == ImplicitSourceTerm(v) >>> eq.solve(v, dt=1.) >>> print v [ 2.] >>> v.setValue(-1.) >>> eq.solve(v, dt=1.) >>> print v [-0.5] """ coeff = self._getGeomCoeff(var) diagonalSign = self._getDiagonalSign(transientGeomCoeff, diffusionGeomCoeff) combinedSign = numerix.array(diagonalSign)[ ..., numerix.newaxis] * numerix.sign(coeff) return { 'diagonal': (combinedSign >= 0), 'old value': numerix.zeros(var.shape, 'd'), 'b vector': -var * (combinedSign < 0), 'new value': numerix.zeros(var.shape, 'd') }
def _calcFaceNormals(self): faceNormals = numerix.array((numerix.ones(self.numberOfFaces, 'd'), )) # The left-most face has neighboring cells None and the left-most cell. # We must reverse the normal to make fluxes work correctly. if self.numberOfFaces > 0: faceNormals[..., 0] = -faceNormals[..., 0] return faceNormals
def _getWeight(self, var, transientGeomCoeff=None, diffusionGeomCoeff=None): """ Test for a bug due to the sign operator not being updating correctly. >>> from fipy import * >>> m = Grid1D(nx=1) >>> v = CellVariable(mesh=m, value=1.) >>> eq = TransientTerm() == ImplicitSourceTerm(v) >>> eq.solve(v, dt=1.) >>> print(v) [ 2.] >>> v.setValue(-1.) >>> eq.solve(v, dt=1.) >>> print(v) [-0.5] """ coeff = self._getGeomCoeff(var) diagonalSign = self._getDiagonalSign(transientGeomCoeff, diffusionGeomCoeff) combinedSign = numerix.array(diagonalSign)[..., numerix.newaxis] * numerix.sign(coeff) return {'diagonal' : (combinedSign >= 0), 'old value' : numerix.zeros(var.shape, 'd'), 'b vector' : -var * (combinedSign < 0), 'new value' : numerix.zeros(var.shape, 'd')}
def _cellValueOverFaces(self): """ Returns the cells values at the faces. >>> 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)) >>> answer = CellVariable(mesh=mesh, ... value=((-.5, .5, .5, 1.5), ... (-.5, .5, .5, 1.5), ... (-.5, .5, .5, 1.5), ... (-.5, .5, .5, 1.5))) >>> print numerix.allclose(distanceVariable._cellValueOverFaces, answer) True """ M = self.mesh._maxFacesPerCell N = self.mesh.numberOfCells return numerix.reshape( numerix.repeat(numerix.array(self._value)[numerix.newaxis, ...], M, axis=0), (M, N))
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 extrude(self, extrudeFunc=lambda x: x + numerix.array((0, 0, 1))[:,numerix.newaxis] , layers=1): """ This function returns a new 3D mesh. The 2D mesh is extruded using the extrudeFunc and the number of layers. :Parameters: - `extrudeFunc`: function that takes the vertex coordinates and returns the displaced values - `layers`: the number of layers in the extruded mesh (number of times extrudeFunc will be called) >>> from fipy.meshes.nonUniformGrid2D import NonUniformGrid2D >>> print NonUniformGrid2D(nx=2,ny=2).extrude(layers=2).cellCenters [[ 0.5 1.5 0.5 1.5 0.5 1.5 0.5 1.5] [ 0.5 0.5 1.5 1.5 0.5 0.5 1.5 1.5] [ 0.5 0.5 0.5 0.5 1.5 1.5 1.5 1.5]] >>> from fipy.meshes.tri2D import Tri2D >>> print Tri2D().extrude(layers=2).cellCenters [[ 0.83333333 0.5 0.16666667 0.5 0.83333333 0.5 0.16666667 0.5 ] [ 0.5 0.83333333 0.5 0.16666667 0.5 0.83333333 0.5 0.16666667] [ 0.5 0.5 0.5 0.5 1.5 1.5 1.5 1.5 ]] """ return self._extrude(self, extrudeFunc, layers)
def _calcResidualVector(self, residualFn=None): if residualFn is not None: return residualFn(self.var, self.matrix, self.RHSvector) else: Lx = self.matrix * numerix.array(self.var) return Lx - self.RHSvector