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 _buildMatrix(self, var, SparseMatrix, boundaryConditions=(), dt=1., equation=None): """Implicit portion considers """ mesh = var.getMesh() id1, id2 = mesh._getAdjacentCellIDs() interiorFaces = numerix.nonzero(mesh.getInteriorFaces())[0] id1 = numerix.take(id1, interiorFaces) id2 = numerix.take(id2, interiorFaces) N = len(var) b = numerix.zeros((N),'d') L = SparseMatrix(size = N) if equation is not None: from fipy.tools.numerix import sign, add self._diagonalSign.setValue(sign(add.reduce(equation.matrix.takeDiagonal()))) else: self._diagonalSign.setValue(1) weight = self._getWeight(mesh, equation=equation) if weight.has_key('implicit'): self._implicitBuildMatrix(SparseMatrix, L, id1, id2, b, weight['implicit'], mesh, boundaryConditions, interiorFaces, dt) if weight.has_key('explicit'): self._explicitBuildMatrix(SparseMatrix, var.getOld(), id1, id2, b, weight['explicit'], mesh, boundaryConditions, interiorFaces, dt) return (L, b)
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 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 _calcValuePy(self): dAP = self.mesh._getCellDistances() id1, id2 = self.mesh._getAdjacentCellIDs() v1 = take(self.var, id1) v2 = take(self.var, id2) for bc in self.bcs: if isinstance(bc, FixedValue): v2[bc.faces.getValue()] = bc._getValue() N = (v2 - v1) / dAP normals = self.mesh._getOrientedFaceNormals() tangents1 = self.mesh._getFaceTangents1() tangents2 = self.mesh._getFaceTangents2() cellGrad = self.var.getGrad().getValue() grad1 = take(cellGrad, id1, axis=1) grad2 = take(cellGrad, id2, axis=1) t1grad1 = sum(tangents1 * grad1, 0) t1grad2 = sum(tangents1 * grad2, 0) t2grad1 = sum(tangents2 * grad1, 0) t2grad2 = sum(tangents2 * grad2, 0) T1 = (t1grad1 + t1grad2) / 2.0 T2 = (t2grad1 + t2grad2) / 2.0 T1 = (id1 == id2) * T1 T2 = (id1 == id2) * T2 return normals * N + tangents1 * T1 + tangents2 * T2
def plotMesh(self, filename = None): self._plot() faceVertexIDs = self.mesh.faceVertexIDs vertexCoords = self.mesh.vertexCoords x0 = numerix.take(vertexCoords[0], faceVertexIDs[0]) y0 = numerix.take(vertexCoords[1], faceVertexIDs[0]) x1 = numerix.take(vertexCoords[0], faceVertexIDs[1]) y1 = numerix.take(vertexCoords[1], faceVertexIDs[1]) import gist gist.pldj(x0, y0, x1, y1) if filename is not None: import os.path root, ext = os.path.splitext(filename) if ext.lower() in (".eps", ".epsi"): gist.eps(root) else: gist.hcp_file(filename, dump = 1) gist.hcp() gist.hcp_finish(-1) gist.fma()
def _implicitBuildMatrix_(self, SparseMatrix, L, id1, id2, b, weight, var, boundaryConditions, interiorFaces, dt): mesh = var.mesh coeffMatrix = self._getCoeffMatrix_(var, weight) id1 = self._reshapeIDs(var, id1) id2 = self._reshapeIDs(var, id2) L.addAt(numerix.take(coeffMatrix['cell 1 diag'], interiorFaces, axis=-1).ravel(), id1.ravel(), id1.swapaxes(0, 1).ravel()) L.addAt(numerix.take(coeffMatrix['cell 1 offdiag'], interiorFaces, axis=-1).ravel(), id1.ravel(), id2.swapaxes(0, 1).ravel()) L.addAt(numerix.take(coeffMatrix['cell 2 offdiag'], interiorFaces, axis=-1).ravel(), id2.ravel(), id1.swapaxes(0, 1).ravel()) L.addAt(numerix.take(coeffMatrix['cell 2 diag'], interiorFaces, axis=-1).ravel(), id2.ravel(), id2.swapaxes(0, 1).ravel()) N = mesh.numberOfCells M = mesh._maxFacesPerCell for boundaryCondition in boundaryConditions: LL, bb = boundaryCondition._buildMatrix(SparseMatrix, N, M, coeffMatrix) if 'FIPY_DISPLAY_MATRIX' in os.environ: self._viewer.title = r"%s %s" % (boundaryCondition.__class__.__name__, self.__class__.__name__) self._viewer.plot(matrix=LL, RHSvector=bb) from fipy import raw_input input() L += LL b += bb
def _plot(self): var = self.vars[0] mesh = var.mesh U, V = var.numericValue U = numerix.take(U, self.indices) V = numerix.take(V, self.indices) ang = numerix.arctan2(V, U) mag = numerix.sqrt(U**2 + V**2) datamin, datamax = self._autoscale(vars=(mag,), datamin=self._getLimit('datamin'), datamax=self._getLimit('datamax')) mag = numerix.where(mag > datamax, datamax, mag) mag = numerix.ma.masked_array(mag, mag < datamin) if self.log: mag = numerix.log10(mag) mag = numerix.ma.masked_array(mag, numerix.isnan(mag)) U = mag * numerix.cos(ang) V = mag * numerix.sin(ang) self._quiver.set_UVC(U, V) self.axes.set_xlim(xmin=self._getLimit('xmin'), xmax=self._getLimit('xmax')) self.axes.set_ylim(ymin=self._getLimit('ymin'), ymax=self._getLimit('ymax'))
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 _orderVertices(vertexCoords, vertices): coordinates = numerix.take(vertexCoords, vertices, axis=1) centroid = numerix.add.reduce(coordinates, axis=1) / coordinates.shape[1] coordinates = coordinates - centroid[..., numerix.newaxis] coordinates = numerix.where(coordinates == 0, 1.e-10, coordinates) ## to prevent division by zero angles = numerix.arctan(coordinates[1] / coordinates[0]) + numerix.where(coordinates[0] < 0, numerix.pi, 0) ## angles go from -pi / 2 to 3*pi / 2 sortorder = numerix.argsort(angles) return numerix.take(vertices, sortorder)
def _calcValue_(self, alpha, id1, id2): cell1 = numerix.take(self.var,id1, axis=-1) cell2 = numerix.take(self.var,id2, axis=-1) return numerix.where((cell1 > 0) & (cell2 > 0), numerix.minimum(cell1, cell2), numerix.where((cell1 < 0) & (cell2 < 0), numerix.maximum(cell1, cell2), 0))
def __getCoefficientMatrix(self, SparseMatrix, var, coeff): mesh = var.mesh id1, id2 = mesh._adjacentCellIDs interiorFaces = numerix.nonzero(mesh.interiorFaces)[0] id1 = numerix.take(id1, interiorFaces) id2 = numerix.take(id2, interiorFaces) id1 = self._reshapeIDs(var, id1) id2 = self._reshapeIDs(var, id2) ## print 'id1',id1 ## print 'id2',id2 coefficientMatrix = SparseMatrix(mesh=mesh, bandwidth = mesh._maxFacesPerCell + 1) interiorCoeff = numerix.take(coeff, interiorFaces, axis=-1).ravel() coefficientMatrix.addAt(interiorCoeff, id1.ravel(), id1.swapaxes(0,1).ravel()) coefficientMatrix.addAt(-interiorCoeff, id1.ravel(), id2.swapaxes(0,1).ravel()) coefficientMatrix.addAt(-interiorCoeff, id2.ravel(), id1.swapaxes(0,1).ravel()) coefficientMatrix.addAt(interiorCoeff, id2.ravel(), id2.swapaxes(0,1).ravel()) ## print 'coefficientMatrix',coefficientMatrix ## raw_input('stopped') ## interiorCoeff = numerix.array(coeff) ## interiorCoeff[...,mesh.exteriorFaces.value] = 0 ## print 'interiorCoeff',interiorCoeff ## interiorCoeff = numerix.take(interiorCoeff, mesh.cellFaceIDs, axis=-1) ## ## print interiorCoeff.shape ## ## print interiorCoeff[:,:,0] ## ## print interiorCoeff[:,:,1] ## coefficientMatrix = SparseMatrix(mesh=mesh, bandwidth = mesh._maxFacesPerCell + 1) ## ## print 'numerix.sum(interiorCoeff, -2)',numerix.sum(interiorCoeff, -2) ## ## print numerix.sum(interiorCoeff, -2).ravel() ## ## raw_input('stopped') ## ## coefficientMatrix.addAtDiagonal(numerix.sum(interiorCoeff, -2).ravel()) ## ## print 'coefficientMatrix',coefficientMatrix ## del interiorCoeff ## interiorFaces = mesh.interiorFaceIDs ## interiorFaceCellIDs = mesh.interiorFaceCellIDs ## interiorCoeff = -numerix.take(coeff, interiorFaces, axis=-1) ## print 'interiorCoeff',interiorCoeff ## raw_input('stopped') ## coefficientMatrix.addAt(interiorCoeff, interiorFaceCellIDs[0], interiorFaceCellIDs[1]) ## interiorCoeff = -numerix.take(coeff, interiorFaces, axis=-1) ## coefficientMatrix.addAt(interiorCoeff, interiorFaceCellIDs[1], interiorFaceCellIDs[0]) return coefficientMatrix
def _explicitBuildMatrixPy(self, oldArray, id1, id2, b, coeffMatrix, mesh, interiorFaces, dt, weight): oldArrayId1, oldArrayId2 = self._getOldAdjacentValues(oldArray, id1, id2, dt=dt) cell1diag = numerix.take(coeffMatrix['cell 1 diag'], interiorFaces) cell1offdiag = numerix.take(coeffMatrix['cell 1 offdiag'], interiorFaces) cell2diag = numerix.take(coeffMatrix['cell 2 diag'], interiorFaces) cell2offdiag = numerix.take(coeffMatrix['cell 2 offdiag'], interiorFaces) vector.putAdd(b, id1, -(cell1diag * oldArrayId1 + cell1offdiag * oldArrayId2)) vector.putAdd(b, id2, -(cell2diag * oldArrayId2 + cell2offdiag * oldArrayId1))
def _calcCellNormals(self): cellNormals = numerix.take(self.faceNormals, self.cellFaceIDs, axis=1) cellFaceCellIDs = numerix.take(self.faceCellIDs[0], self.cellFaceIDs) cellIDs = numerix.repeat(numerix.arange(self.numberOfCells)[numerix.newaxis,...], self._maxFacesPerCell, axis=0) direction = (cellFaceCellIDs == cellIDs) * 2 - 1 if self._maxFacesPerCell > 0: return direction[numerix.newaxis, ...] * cellNormals else: return cellNormals
def _orderVertices(vertexCoords, vertices): coordinates = numerix.take(vertexCoords, vertices) centroid = numerix.add.reduce(coordinates) / coordinates.shape[0] coordinates = coordinates - centroid # to prevent division by zero coordinates = numerix.where(coordinates == 0, 1.e-100, coordinates) # angles go from -pi / 2 to 3*pi / 2 angles = numerix.arctan(coordinates[:, 1] / coordinates[:, 0]) \ + numerix.where(coordinates[:, 0] < 0, numerix.pi, 0) sortorder = numerix.argsort(angles) return numerix.take(vertices, sortorder)
def _calcCellNormals(self): cellNormals = numerix.take(self._getFaceNormals(), self._getCellFaceIDs(), axis=1) cellFaceCellIDs = numerix.take(self.faceCellIDs[0], self.cellFaceIDs) cellIDs = numerix.repeat(numerix.arange(self.getNumberOfCells())[numerix.newaxis,...], self._getMaxFacesPerCell(), axis=0) direction = (cellFaceCellIDs == cellIDs) * 2 - 1 if self._getMaxFacesPerCell() > 0: self.cellNormals = direction[numerix.newaxis, ...] * cellNormals else: self.cellNormals = cellNormals
def _calcValue_(self, alpha, id1, id2): cell1 = numerix.take(self.var,id1, axis=-1) cell2 = numerix.take(self.var,id2, axis=-1) value = ((cell2 - cell1) * alpha + cell1) eps = 1e-20 value = (value == 0.) * eps + (value != 0.) * value cell1Xcell2 = cell1 * cell2 value = ((value > eps) | (value < -eps)) * cell1Xcell2 / value value = (cell1Xcell2 >= 0.) * value return value
def aspect2D(self): """The physical y:x aspect ratio of a 2D mesh """ if self.dim != 2: raise NotImplementedError else: vertexIDs = self._orderedCellVertexIDs xCoords = numerix.take(self.vertexCoords[0], vertexIDs) yCoords = numerix.take(self.vertexCoords[1], vertexIDs) return float((yCoords.max() - yCoords.min()) / (xCoords.max() - xCoords.min()))
def _calcOrderedCellVertexIDs(self): from fipy.tools.numerix import take NFac = self._maxFacesPerCell # numpy 1.1's MA.take doesn't like FlatIter. Call ravel() instead. cellVertexIDs0 = take(self.faceVertexIDs[0], self.cellFaceIDs.ravel()) cellVertexIDs1 = take(self.faceVertexIDs[1], self.cellFaceIDs.ravel()) cellVertexIDs = MA.where(self._cellToFaceOrientations.ravel() > 0, cellVertexIDs0, cellVertexIDs1) cellVertexIDs = numerix.reshape(cellVertexIDs, (NFac, -1)) return cellVertexIDs
def _explicitBuildMatrixInline_(self, oldArray, id1, id2, b, coeffMatrix, mesh, interiorFaces, dt, weight): oldArrayId1, oldArrayId2 = self._getOldAdjacentValues(oldArray, id1, id2, dt=dt) cell1diag = numerix.take(coeffMatrix['cell 1 diag'], interiorFaces) cell1offdiag = numerix.take(coeffMatrix['cell 1 offdiag'], interiorFaces) cell2diag = numerix.take(coeffMatrix['cell 2 diag'], interiorFaces) cell2offdiag = numerix.take(coeffMatrix['cell 2 offdiag'], interiorFaces) vector.putAdd(b, id1, -(cell1diag * oldArrayId1 + cell1offdiag * oldArrayId2)) vector.putAdd(b, id2, -(cell2diag * oldArrayId2 + cell2offdiag * oldArrayId1))
def plot_mesh(self): vertexIDs = self.mesh._orderedCellVertexIDs vertexCoords = self.mesh.vertexCoords xCoords = numerix.take(vertexCoords[0], vertexIDs) yCoords = numerix.take(vertexCoords[1], vertexIDs) polys = [] for x, y in zip(xCoords.swapaxes(0, 1), yCoords.swapaxes(0, 1)): polys.append(zip(x, y)) self.collection = PolyCollection(polys) self.collection.set_linewidth(0.5) self.axes.add_collection(self.collection) self.update(self.var)
def _calcCellNormals(self): cellNormals = numerix.take(self.faceNormals, self.cellFaceIDs, axis=1) cellFaceCellIDs = numerix.take(self.faceCellIDs[0], self.cellFaceIDs) cellIDs = numerix.repeat(numerix.arange( self.numberOfCells)[numerix.newaxis, ...], self._maxFacesPerCell, axis=0) direction = (cellFaceCellIDs == cellIDs) * 2 - 1 if self._maxFacesPerCell > 0: return direction[numerix.newaxis, ...] * cellNormals else: return cellNormals
def _calcFaceAreas(self): faceVertexIDs = MA.filled(self.faceVertexIDs, -1) substitute = numerix.repeat(faceVertexIDs[numerix.newaxis, 0], faceVertexIDs.shape[0], axis=0) faceVertexIDs = numerix.where(MA.getmaskarray(self.faceVertexIDs), substitute, faceVertexIDs) faceVertexCoords = numerix.take(self.vertexCoords, faceVertexIDs, axis=1) faceOrigins = numerix.repeat(faceVertexCoords[:,0], faceVertexIDs.shape[0], axis=0) faceOrigins = numerix.reshape(faceOrigins, MA.shape(faceVertexCoords)) faceVertexCoords = faceVertexCoords - faceOrigins left = range(faceVertexIDs.shape[0]) right = left[1:] + [left[0]] cross = numerix.sum(numerix.cross(faceVertexCoords, numerix.take(faceVertexCoords, right, 1), axis=0), 1) self.faceAreas = numerix.sqrtDot(cross, cross) / 2.
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 _getOldAdjacentValues(self, oldArray, id1, id2, dt): oldArray1, oldArray2 = ExplicitUpwindConvectionTerm._getOldAdjacentValues(self, oldArray, id1, id2, dt) mesh = oldArray.getMesh() interiorIDs = numerix.nonzero(mesh.getInteriorFaces())[0] interiorFaceAreas = numerix.take(mesh._getFaceAreas(), interiorIDs) interiorFaceNormals = numerix.take(mesh._getOrientedFaceNormals(), interiorIDs, axis=-1) # Courant-Friedrichs-Levy number interiorCFL = abs(numerix.take(self._getGeomCoeff(mesh), interiorIDs)) * dt gradUpwind = (oldArray2 - oldArray1) / numerix.take(mesh._getCellDistances(), interiorIDs) vol1 = numerix.take(mesh.getCellVolumes(), id1) self.CFL = interiorCFL / vol1 oldArray1 += 0.5 * self._getGradient(numerix.dot(numerix.take(oldArray.getGrad(), id1, axis=-1), interiorFaceNormals), gradUpwind) \ * (vol1 - interiorCFL) / interiorFaceAreas vol2 = numerix.take(mesh.getCellVolumes(), id2) self.CFL = numerix.maximum(interiorCFL / vol2, self.CFL) oldArray2 += 0.5 * self._getGradient(numerix.dot(numerix.take(oldArray.getGrad(), id2, axis=-1), -interiorFaceNormals), -gradUpwind) \ * (vol2 - interiorCFL) / interiorFaceAreas return oldArray1, oldArray2
def _getOldAdjacentValues(self, oldArray, id1, id2, dt): oldArray1, oldArray2 = ExplicitUpwindConvectionTerm._getOldAdjacentValues(self, oldArray, id1, id2, dt) mesh = oldArray.mesh interiorIDs = numerix.nonzero(mesh.interiorFaces)[0] interiorFaceAreas = numerix.take(mesh._faceAreas, interiorIDs) interiorFaceNormals = numerix.take(mesh._orientedFaceNormals, interiorIDs, axis=-1) # Courant-Friedrichs-Levy number interiorCFL = abs(numerix.take(self._getGeomCoeff(oldArray), interiorIDs)) * dt gradUpwind = (oldArray2 - oldArray1) / numerix.take(mesh._cellDistances, interiorIDs) vol1 = numerix.take(mesh.cellVolumes, id1) oldArray1 += 0.5 * self._getGradient(numerix.dot(numerix.take(oldArray.grad, id1, axis=-1), interiorFaceNormals), gradUpwind) \ * (vol1 - interiorCFL) / interiorFaceAreas vol2 = numerix.take(mesh.cellVolumes, id2) oldArray2 += 0.5 * self._getGradient(numerix.dot(numerix.take(oldArray.grad, id2, axis=-1), -interiorFaceNormals), -gradUpwind) \ * (vol2 - interiorCFL) / interiorFaceAreas return oldArray1, oldArray2
def _implicitBuildMatrix(self, SparseMatrix, L, id1, id2, b, weight, mesh, boundaryConditions, interiorFaces, dt): coeffMatrix = self._getCoeffMatrix(mesh, weight) L.addAt(numerix.take(coeffMatrix['cell 1 diag'], interiorFaces), id1, id1) L.addAt(numerix.take(coeffMatrix['cell 1 offdiag'], interiorFaces), id1, id2) L.addAt(numerix.take(coeffMatrix['cell 2 offdiag'], interiorFaces), id2, id1) L.addAt(numerix.take(coeffMatrix['cell 2 diag'], interiorFaces), id2, id2) N = mesh.getNumberOfCells() M = mesh._getMaxFacesPerCell() for boundaryCondition in boundaryConditions: LL, bb = boundaryCondition._buildMatrix(SparseMatrix, N, M, coeffMatrix) L += LL b += bb
def _calcCellToCellIDs(self): cellToCellIDs = numerix.take(self.faceCellIDs, self.cellFaceIDs, axis=1) cellToCellIDs = MA.where(self._cellToFaceOrientations == 1, cellToCellIDs[1], cellToCellIDs[0]) return cellToCellIDs
def _calcCellDistAndVec(self): tmp = numerix.take(self._cellCenters, self.faceCellIDs, axis=1) tmp = tmp[...,1,:] - tmp[...,0,:] tmp = MA.filled(MA.where(MA.getmaskarray(tmp), self._cellToFaceDistanceVectors[:,0], tmp)) cellDistanceVectors = tmp cellDistances = MA.filled(MA.sqrt(MA.sum(tmp * tmp, 0))) return cellDistances, cellDistanceVectors
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 _calcValue(self): flag = MA.filled( numerix.take(self.distanceVar._interfaceFlag, self.mesh.cellFaceIDs), 0) flag = numerix.sum(flag, axis=0) return numerix.where( numerix.logical_and(self.distanceVar.value > 0, flag > 0), 1, 0)
def interiorFaceCellIDs(self): if not hasattr(self, '_interiorFaceCellIDs'): ## Commented line is better, but doesn't work for zero length arrays ## self.interiorFaceCellIDs = self.getFaceCellIDs()[..., self.getInteriorFaceIDs()] self._interiorFaceCellIDs = numerix.take(self.faceCellIDs, self.interiorFaceIDs, axis=1) return self._interiorFaceCellIDs
def _calcFaceToCellDistances(self): tmp = MA.repeat(self.faceCenters[...,numerix.NewAxis,:], 2, 1) # array -= masked_array screws up masking for on numpy 1.1 tmp = tmp - numerix.take(self.cellCenters, self.faceCellIDs, axis=1) self.cellToFaceDistanceVectors = tmp self.faceToCellDistances = MA.sqrt(MA.sum(tmp * tmp,0))
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 _calcValue(self): Nfaces = self.mesh.numberOfFaces M = self.mesh._maxFacesPerCell dim = self.mesh.dim cellFaceIDs = self.mesh.cellFaceIDs faceNormalAreas = self.distanceVar._levelSetNormals * self.mesh._faceAreas cellFaceNormalAreas = numerix.array(MA.filled(numerix.take(faceNormalAreas, cellFaceIDs, axis=-1), 0)) norms = numerix.array(MA.filled(MA.array(self.mesh._cellNormals), 0)) alpha = numerix.dot(cellFaceNormalAreas, norms) alpha = numerix.where(alpha > 0, alpha, 0) alphasum = numerix.sum(alpha, axis=0) alphasum += (alphasum < 1e-100) * 1.0 alpha = alpha / alphasum phi = numerix.repeat(self.distanceVar[numerix.newaxis, ...], M, axis=0) alpha = numerix.where(phi > 0., 0, alpha) volumes = numerix.array(self.mesh.cellVolumes) alpha = alpha * volumes * norms value = numerix.zeros((dim, Nfaces), 'd') vector._putAdd(value, cellFaceIDs, alpha, mask=MA.getmask(MA.array(cellFaceIDs))) ## value = numerix.reshape(value, (dim, Nfaces, dim)) return -value / self.mesh._faceAreas
def _buildMatrix(self, var, SparseMatrix, 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 plot(self, filename=None): """ Plot the `CellVariable` as a contour plot. """ self._plot() datamin = self._getLimit(('datamin', 'zmin')) datamax = self._getLimit(('datamax', 'zmax')) if datamin == 'e': datamin = None if datamax == 'e': datamax = None datamin, datamax = self._autoscale(vars=self.vars, datamin=datamin, datamax=datamax) if datamax == datamin: datamax = datamin + 1e-10 vertexIDs = self.mesh._orderedCellVertexIDs vertexCoords = self.mesh.vertexCoords xCoords = numerix.take(vertexCoords[0], vertexIDs).flatten("FORTRAN") yCoords = numerix.take(vertexCoords[1], vertexIDs).flatten("FORTRAN") import gist import Numeric gist.plfp(Numeric.array(numerix.array(self.vars[0])), yCoords, xCoords, self.mesh._numberOfFacesPerCell, cmin=datamin, cmax=datamax) import fipy.viewers.gistViewer.colorbar colorbar._color_bar(minz=datamin, maxz=datamax, ncol=240, zlabel=self.vars[0].name) _GistViewer.plot(self, filename=filename)
def _calcFaceTangents(self): faceVertexCoord = numerix.array( numerix.take(self.vertexCoords, self.faceVertexIDs[0], axis=1)) tmp = self._faceCenters - faceVertexCoord faceTangents1 = tmp / numerix.sqrtDot(tmp, tmp) tmp = numerix.cross(faceTangents1, self.faceNormals, axis=0) faceTangents2 = tmp / numerix.sqrtDot(tmp, tmp) return faceTangents1, faceTangents2
def _calcFaceAreas(self): faceVertexIDs = MA.filled(self.faceVertexIDs, -1) substitute = numerix.repeat(faceVertexIDs[numerix.newaxis, 0], faceVertexIDs.shape[0], axis=0) faceVertexIDs = numerix.where(MA.getmaskarray(self.faceVertexIDs), substitute, faceVertexIDs) faceVertexCoords = numerix.take(self.vertexCoords, faceVertexIDs, axis=1) faceOrigins = numerix.repeat(faceVertexCoords[:,0], faceVertexIDs.shape[0], axis=0) faceOrigins = numerix.reshape(faceOrigins, MA.shape(faceVertexCoords)) faceVertexCoords = faceVertexCoords - faceOrigins left = range(faceVertexIDs.shape[0]) right = left[1:] + [left[0]] cross = numerix.sum(numerix.cross(faceVertexCoords, numerix.take(faceVertexCoords, right, 1), axis=0), 1) return numerix.sqrtDot(cross, cross) / 2.
def _calcFaceToCellDistAndVec(self): tmp = MA.repeat(self._faceCenters[..., numerix.NewAxis, :], 2, 1) # array -= masked_array screws up masking for on numpy 1.1 tmp = tmp - numerix.take(self._cellCenters, self.faceCellIDs, axis=1) cellToFaceDistanceVectors = tmp faceToCellDistances = MA.sqrt(MA.sum(tmp * tmp, 0)) return faceToCellDistances, cellToFaceDistanceVectors
def _calcValueNoInline(self): dAP = self.mesh._cellDistances id1, id2 = self.mesh._adjacentCellIDs N2 = numerix.take(self.var.value, id2, axis=-1) faceMask = numerix.array(self.mesh.exteriorFaces) ## 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.faceValue.shape[-1] != 0: s = (Ellipsis, faceMask) else: s = (faceMask, ) N2[s] = self.var.faceValue[s] N = (N2 - numerix.take(self.var, id1, axis=-1)) / dAP normals = self.mesh._orientedFaceNormals tangents1 = self.mesh._faceTangents1 tangents2 = self.mesh._faceTangents2 cellGrad = self.var.grad.numericValue grad1 = numerix.take(cellGrad, id1, axis=-1) grad2 = numerix.take(cellGrad, id2, axis=-1) s = (slice(0, None, None), ) + (numerix.newaxis, ) * (len(grad1.shape) - 2) + ( slice(0, None, None), ) t1grad1 = numerix.sum(tangents1[s] * grad1, 0) t1grad2 = numerix.sum(tangents1[s] * grad2, 0) t2grad1 = numerix.sum(tangents2[s] * grad1, 0) t2grad2 = numerix.sum(tangents2[s] * grad2, 0) T1 = (t1grad1 + t1grad2) / 2. T2 = (t2grad1 + t2grad2) / 2. return normals[s] * N[numerix.newaxis] + tangents1[s] * T1[ numerix.newaxis] + tangents2[s] * T2[numerix.newaxis]
def extents(self): ext = dict(min=[], max=[]) for d in range(self.dim): X = numerix.take(self.vertexCoords[d], self._orderedCellVertexIDs) ext['min'].append(X.min()) ext['max'].append(X.max()) return ext
def _calcValue_(self, alpha, id1, id2): cell1 = take(self.var,id1) cell2 = take(self.var,id2) delta = cell1 - cell2 eps = 1e-14 value = where(abs(delta) < eps, 1. / exp(delta), 0.) delta = where(abs(delta) < eps, eps, delta) value = where((abs(delta) > eps) & (delta < 100), delta / (exp(delta) - 1), value) value *= exp(cell1) for bc in self.bcs: if isinstance(bc, FixedValue): value[bc.faces.value] = bc._value return value
def _calcFaceNormals(self): faceVertexCoords = numerix.take(self.vertexCoords, self.faceVertexIDs, axis=1) t1 = faceVertexCoords[:, 1,:] - faceVertexCoords[:, 0,:] faceNormals = t1.copy() mag = numerix.sqrt(t1[1]**2 + t1[0]**2) faceNormals[0] = -t1[1] / mag faceNormals[1] = t1[0] / mag orientation = 1 - 2 * (numerix.dot(faceNormals, self.cellDistanceVectors) < 0) return faceNormals * orientation
def _implicitBuildMatrix_(self, SparseMatrix, L, id1, id2, b, weight, var, boundaryConditions, interiorFaces, dt): mesh = var.mesh coeffMatrix = self._getCoeffMatrix_(var, weight) id1 = self._reshapeIDs(var, id1) id2 = self._reshapeIDs(var, id2) L.addAt( numerix.take(coeffMatrix['cell 1 diag'], interiorFaces, axis=-1).ravel(), id1.ravel(), id1.swapaxes(0, 1).ravel()) L.addAt( numerix.take(coeffMatrix['cell 1 offdiag'], interiorFaces, axis=-1).ravel(), id1.ravel(), id2.swapaxes(0, 1).ravel()) L.addAt( numerix.take(coeffMatrix['cell 2 offdiag'], interiorFaces, axis=-1).ravel(), id2.ravel(), id1.swapaxes(0, 1).ravel()) L.addAt( numerix.take(coeffMatrix['cell 2 diag'], interiorFaces, axis=-1).ravel(), id2.ravel(), id2.swapaxes(0, 1).ravel()) N = mesh.numberOfCells M = mesh._maxFacesPerCell for boundaryCondition in boundaryConditions: LL, bb = boundaryCondition._buildMatrix(SparseMatrix, N, M, coeffMatrix) if 'FIPY_DISPLAY_MATRIX' in os.environ: self._viewer.title = r"%s %s" % ( boundaryCondition.__class__.__name__, self.__class__.__name__) self._viewer.plot(matrix=LL, RHSvector=bb) from fipy import raw_input input() L += LL b += bb
def _nonOrthogonality(self): exteriorFaceArray = numerix.zeros((self.faceCellIDs.shape[1], ), 'l') numerix.put(exteriorFaceArray, numerix.nonzero(self.exteriorFaces), 1) unmaskedFaceCellIDs = MA.filled(self.faceCellIDs, 0) # what we put in for the "fill" doesn't matter because only exterior # faces have anything masked, and exterior faces have their displacement # vectors set to zero. # # if it's an exterior face, make the "displacement vector" equal to zero # so the cross product will be zero. faceDisplacementVectors = \ numerix.where(numerix.array(zip(exteriorFaceArray, exteriorFaceArray)), 0.0, numerix.take(self._scaledCellCenters.swapaxes(0,1), unmaskedFaceCellIDs[1, :]) \ - numerix.take(self._scaledCellCenters.swapaxes(0,1), unmaskedFaceCellIDs[0, :])) faceDisplacementVectors = faceDisplacementVectors.swapaxes(0, 1) faceCrossProducts = (faceDisplacementVectors[0, :] * self.faceNormals[1,:]) \ - (faceDisplacementVectors[1, :] * self.faceNormals[0, :]) faceDisplacementVectorLengths = numerix.maximum(((faceDisplacementVectors[0, :] ** 2) \ + (faceDisplacementVectors[1, :] ** 2)) ** 0.5, 1.e-100) faceWeightedNonOrthogonalities = abs( faceCrossProducts / faceDisplacementVectorLengths) * self._faceAreas cellFaceWeightedNonOrthogonalities = numerix.take( faceWeightedNonOrthogonalities, self.cellFaceIDs) cellFaceAreas = numerix.take(self._faceAreas, self.cellFaceIDs) cellTotalWeightedValues = numerix.add.reduce( cellFaceWeightedNonOrthogonalities, axis=0) cellTotalFaceAreas = numerix.add.reduce(cellFaceAreas, axis=0) return (cellTotalWeightedValues / cellTotalFaceAreas)
def _interfaceFlag(self): """ Returns 1 for faces on boundary and 0 otherwise. >>> 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)) >>> answer = FaceVariable(mesh=mesh, ... value=(0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0)) >>> print numerix.allclose(distanceVariable._interfaceFlag, answer) True """ adjacentCellIDs = self.mesh._adjacentCellIDs val0 = numerix.take(numerix.array(self._value), adjacentCellIDs[0]) val1 = numerix.take(numerix.array(self._value), adjacentCellIDs[1]) return numerix.where(val1 * val0 < 0, 1, 0)
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 _calcValue(self): dAP = self.mesh._cellDistances id1, id2 = self.mesh._adjacentCellIDs N = (numerix.take(self.var, id2) - numerix.take(self.var, id1)) / dAP normals = self.mesh._orientedFaceNormals tangents1 = self.mesh._faceTangents1 tangents2 = self.mesh._faceTangents2 cellGrad = self.var.grad.numericValue grad1 = numerix.take(cellGrad, id1, axis=1) grad2 = numerix.take(cellGrad, id2, axis=1) t1grad1 = numerix.sum(tangents1 * grad1, 0) t1grad2 = numerix.sum(tangents1 * grad2, 0) t2grad1 = numerix.sum(tangents2 * grad1, 0) t2grad2 = numerix.sum(tangents2 * grad2, 0) T1 = (t1grad1 + t1grad2) / 2. T2 = (t2grad1 + t2grad2) / 2. return normals * N + tangents1 * T1 + tangents2 * T2
def _rightHandOrientation(self): faceVertexIDs = MA.filled(self.faceVertexIDs, 0) faceVertexCoords = numerix.take(self.vertexCoords, faceVertexIDs, axis=1) t1 = faceVertexCoords[:,1,:] - faceVertexCoords[:,0,:] t2 = faceVertexCoords[:,2,:] - faceVertexCoords[:,1,:] norm = numerix.cross(t1, t2, axis=0) ## reordering norm's internal memory for inlining norm = norm.copy() norm = norm / numerix.sqrtDot(norm, norm) faceNormals = -norm return 1 - 2 * (numerix.dot(faceNormals, self.cellDistanceVectors) < 0)
def _buildMatrix(self, var, SparseMatrix, boundaryConditions=(), dt=None, transientGeomCoeff=None, diffusionGeomCoeff=None): """Implicit portion considers """ mesh = var.mesh id1, id2 = mesh._adjacentCellIDs interiorFaces = numerix.nonzero(mesh.interiorFaces)[0] id1 = numerix.take(id1, interiorFaces) id2 = numerix.take(id2, interiorFaces) b = numerix.zeros(var.shape, 'd').ravel() L = SparseMatrix(mesh=mesh) weight = self._getWeight(var, transientGeomCoeff, diffusionGeomCoeff) if 'implicit' in weight: self._implicitBuildMatrix_(SparseMatrix, L, id1, id2, b, weight['implicit'], var, boundaryConditions, interiorFaces, dt) if 'explicit' in weight: self._explicitBuildMatrix_(SparseMatrix, var.old, id1, id2, b, weight['explicit'], var, boundaryConditions, interiorFaces, dt) return (var, L, b)
def _calcFaceCenters(self): maskedFaceVertexIDs = MA.filled(self.faceVertexIDs, 0) faceVertexCoords = numerix.take(self.vertexCoords, maskedFaceVertexIDs, axis=1) if MA.getmask(self.faceVertexIDs) is False: faceVertexCoordsMask = numerix.zeros(numerix.shape(faceVertexCoords), 'l') else: faceVertexCoordsMask = \ numerix.repeat(MA.getmaskarray(self.faceVertexIDs)[numerix.newaxis,...], self.dim, axis=0) faceVertexCoords = MA.array(data=faceVertexCoords, mask=faceVertexCoordsMask) return MA.filled(MA.average(faceVertexCoords, axis=1))
def _calcValueNoInline(self): ids = self.mesh.cellFaceIDs contributions = numerix.take(self.faceVariable, ids, axis=-1) # FIXME: numerix.MA.filled casts away dimensions s = (numerix.newaxis, ) * (len(contributions.shape) - 2) + (slice( 0, None, None), ) + (slice(0, None, None), ) faceContributions = contributions * self.mesh._cellToFaceOrientations[s] return numerix.tensordot( numerix.ones(faceContributions.shape[-2], 'd'), numerix.MA.filled(faceContributions, 0.), (0, -2)) / self.mesh.cellVolumes