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 _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 _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): 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 H_UniaxialAnisotropy(mUnit, uAxis, Ku2, Msat): global mu0 ############ calculate normalized direction ##### uAxisNorm = numerix.linalg.norm(uAxis) uAxisUnit = uAxis / uAxisNorm ################################################# mArray = mUnit ################################################# ################################################# # repeat uniaxial direction vector for n times # where n= number of cells. uAxisUnit=3X1 # uAxisArr=nX3, represents uniaxial direction for # each cells in the unit sphere ################################################# uAxisArr = numerix.tile(uAxisUnit, (len(mUnit[0]), 1)) uAxisArr = numerix.transpose(uAxisArr) # converted to 3Xn mdotu = numerix.dot(mArray, uAxisArr) # projection of m along uniaxial direction scaleFac = numerix.multiply( mdotu, (2.0 * Ku2 / (mu0 * Msat))) # calculate the magnitude in A/m Heff = numerix.zeros((3, len(scaleFac)), 'd') # Uniaxial vector for each cell Heff[0] = numerix.multiply(scaleFac, uAxisArr[0]) Heff[1] = numerix.multiply(scaleFac, uAxisArr[1]) Heff[2] = numerix.multiply(scaleFac, uAxisArr[2]) # unit is in A/m return Heff
def __call__(self, points=None, order=0, nearestCellIDs=None): r""" Interpolates the `CellVariable` to a set of points using a method that has a memory requirement on the order of `Ncells` by `Npoints` in general, but uses only `Ncells` when the `CellVariable`'s mesh is a `UniformGrid` object. Tests >>> from fipy import * >>> m = Grid2D(nx=3, ny=2) >>> v = CellVariable(mesh=m, value=m.cellCenters[0]) >>> print(v(((0., 1.1, 1.2), (0., 1., 1.)))) [ 0.5 1.5 1.5] >>> print(v(((0., 1.1, 1.2), (0., 1., 1.)), order=1)) [ 0.25 1.1 1.2 ] >>> m0 = Grid2D(nx=2, ny=2, dx=1., dy=1.) >>> m1 = Grid2D(nx=4, ny=4, dx=.5, dy=.5) >>> x, y = m0.cellCenters >>> v0 = CellVariable(mesh=m0, value=x * y) >>> print(v0(m1.cellCenters.globalValue)) [ 0.25 0.25 0.75 0.75 0.25 0.25 0.75 0.75 0.75 0.75 2.25 2.25 0.75 0.75 2.25 2.25] >>> print(v0(m1.cellCenters.globalValue, order=1)) [ 0.125 0.25 0.5 0.625 0.25 0.375 0.875 1. 0.5 0.875 1.875 2.25 0.625 1. 2.25 2.625] Parameters ---------- points : tuple or :obj:`list` of :obj:`tuple` A point or set of points in the format (X, Y, Z) order : {`0`, `1`} The order of interpolation, default is 0 nearestCellIDs : array_like Optional argument if user can calculate own nearest cell IDs array, shape should be same as points """ if points is not None: if nearestCellIDs is None: nearestCellIDs = self.mesh._getNearestCellID(points) if order == 0: return self.globalValue[..., nearestCellIDs] elif order == 1: ##cellID = self.mesh._getNearestCellID(points) ## return self[...,self.mesh._getNearestCellID(points)] + numerix.dot(points - self.mesh.cellCenters[...,cellID], self.grad[...,cellID]) return (self.globalValue[..., nearestCellIDs] + numerix.dot( points - self.mesh.cellCenters.globalValue[..., nearestCellIDs], self.grad.globalValue[..., nearestCellIDs])) else: raise ValueError('order should be either 0 or 1') else: return _MeshVariable.__call__(self)
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 __call__(self, points=None, order=0, nearestCellIDs=None): r""" Interpolates the CellVariable to a set of points using a method that has a memory requirement on the order of Ncells by Npoints in general, but uses only Ncells when the CellVariable's mesh is a UniformGrid object. :Parameters: - `points`: A point or set of points in the format (X, Y, Z) - `order`: The order of interpolation, 0 or 1, default is 0 - `nearestCellIDs` : Optional argument if user can calculate own nearest cell IDs array, shape should be same as points Tests >>> from fipy import * >>> m = Grid2D(nx=3, ny=2) >>> v = CellVariable(mesh=m, value=m.cellCenters[0]) >>> print v(((0., 1.1, 1.2), (0., 1., 1.))) [ 0.5 1.5 1.5] >>> print v(((0., 1.1, 1.2), (0., 1., 1.)), order=1) [ 0.25 1.1 1.2 ] >>> m0 = Grid2D(nx=2, ny=2, dx=1., dy=1.) >>> m1 = Grid2D(nx=4, ny=4, dx=.5, dy=.5) >>> x, y = m0.cellCenters >>> v0 = CellVariable(mesh=m0, value=x * y) >>> print v0(m1.cellCenters.globalValue) [ 0.25 0.25 0.75 0.75 0.25 0.25 0.75 0.75 0.75 0.75 2.25 2.25 0.75 0.75 2.25 2.25] >>> print v0(m1.cellCenters.globalValue, order=1) [ 0.125 0.25 0.5 0.625 0.25 0.375 0.875 1. 0.5 0.875 1.875 2.25 0.625 1. 2.25 2.625] """ if points is not None: if nearestCellIDs is None: nearestCellIDs = self.mesh._getNearestCellID(points) if order == 0: return self.globalValue[..., nearestCellIDs] elif order == 1: ##cellID = self.mesh._getNearestCellID(points) ## return self[...,self.mesh._getNearestCellID(points)] + numerix.dot(points - self.mesh.cellCenters[...,cellID], self.grad[...,cellID]) return (self.globalValue[..., nearestCellIDs] + numerix.dot( points - self.mesh.cellCenters.globalValue[..., nearestCellIDs], self.grad.globalValue[..., nearestCellIDs])) else: raise ValueError, 'order should be either 0 or 1' else: return _MeshVariable.__call__(self)
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 _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 __call__(self, points=None, order=0, nearestCellIDs=None): r""" Interpolates the CellVariable to a set of points using a method that has a memory requirement on the order of Ncells by Npoints in general, but uses only Ncells when the CellVariable's mesh is a UniformGrid object. :Parameters: - `points`: A point or set of points in the format (X, Y, Z) - `order`: The order of interpolation, 0 or 1, default is 0 - `nearestCellIDs` : Optional argument if user can calculate own nearest cell IDs array, shape should be same as points Tests >>> from fipy import * >>> m = Grid2D(nx=3, ny=2) >>> v = CellVariable(mesh=m, value=m.getCellCenters()[0]) >>> print v(((0., 1.1, 1.2), (0., 1., 1.))) [ 0.5 1.5 1.5] >>> print v(((0., 1.1, 1.2), (0., 1., 1.)), order=1) [ 0.25 1.1 1.2 ] >>> m0 = Grid2D(nx=2, ny=2, dx=1., dy=1.) >>> m1 = Grid2D(nx=4, ny=4, dx=.5, dy=.5) >>> x, y = m0.getCellCenters() >>> v0 = CellVariable(mesh=m0, value=x * y) >>> print v0(m1.getCellCenters().getGlobalValue()) [ 0.25 0.25 0.75 0.75 0.25 0.25 0.75 0.75 0.75 0.75 2.25 2.25 0.75 0.75 2.25 2.25] >>> print v0(m1.getCellCenters().getGlobalValue(), order=1) [ 0.125 0.25 0.5 0.625 0.25 0.375 0.875 1. 0.5 0.875 1.875 2.25 0.625 1. 2.25 2.625] """ if points is not None: if nearestCellIDs is None: nearestCellIDs = self.getMesh()._getNearestCellID(points) if order == 0: return self.getGlobalValue()[..., nearestCellIDs] elif order == 1: ##cellID = self.getMesh()._getNearestCellID(points) ## return self[...,self.getMesh()._getNearestCellID(points)] + numerix.dot(points - self.getMesh().getCellCenters()[...,cellID], self.getGrad()[...,cellID]) return (self.getGlobalValue()[..., nearestCellIDs] + numerix.dot(points - self.getMesh().getCellCenters().getGlobalValue()[...,nearestCellIDs], self.getGrad().getGlobalValue()[...,nearestCellIDs])) else: raise ValueError, 'order should be either 0 or 1' else: return _MeshVariable.__call__(self)
def dot(self, other, opShape=None, operatorClass=None, axis=0): if not isinstance(other, Variable): from fipy.variables.constant import _Constant other = _Constant(value=other) if opShape is None: opShape = self._broadcastShape(other) return self._BinaryOperatorVariable(lambda a,b: numerix.dot(a,b, axis=axis), other, opShape=opShape[:axis]+opShape[axis+1:], operatorClass=operatorClass, canInline=False)
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 _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 _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 HeffUniaxialAnisotropyFac(mUnit, uAxis, Hfac): uAxisNorm = numerix.linalg.norm(uAxis) uAxisUnit = uAxis / uAxisNorm mNorm = numerix.linalg.norm(mUnit,axis=0) mArray = mUnit / mNorm uAxisArr = numerix.tile(uAxisUnit, (len(mUnit[0]), 1)) uAxisArr = numerix.transpose(uAxisArr) mdotu = numerix.dot(mArray, uAxisArr) scaleFac = numerix.multiply(mdotu, Hfac) Heff = numerix.zeros((3, len(scaleFac)), 'd') Heff[0] = numerix.multiply(scaleFac, uAxisArr[0]) Heff[1] = numerix.multiply(scaleFac, uAxisArr[1]) Heff[2] = numerix.multiply(scaleFac, uAxisArr[2]) return Heff
def _getNearestCellID(self, points): """ Test cases >>> from fipy import * >>> m0 = Grid2D(dx=(.1, 1., 10.), dy=(.1, 1., 10.)) >>> m1 = Grid2D(nx=2, ny=2, dx=5., dy=5.) >>> print m0._getNearestCellID(m1.getCellCenters().getGlobalValue()) [4 5 7 8] """ if self.globalNumberOfCells == 0: return numerix.arange(0) points = numerix.resize(points, (self.globalNumberOfCells, len(points), len(points[0]))).swapaxes(0,1) centers = self.getCellCenters().getGlobalValue()[...,numerix.newaxis] try: tmp = centers - points except TypeError: tmp = centers - PhysicalField(points) return numerix.argmin(numerix.dot(tmp, tmp, axis = 0), axis=0)
def _calcValue(self): normals = numerix.array(MA.filled(self.distanceVar._cellInterfaceNormals, 0)) areas = numerix.array(MA.filled(self.mesh._cellAreaProjections, 0)) return numerix.sum(abs(numerix.dot(normals, areas)), axis=0)
def _getAddedMeshValues(self, other, resolution=1e-2): """Calculate the parameters to define a concatenation of `other` with `self` :Parameters: - `other`: The :class:`~fipy.meshes.numMesh.Mesh` to concatenate with `self` - `resolution`: How close vertices have to be (relative to the smallest cell-to-cell distance in either mesh) to be considered the same :Returns: A `dict` with 3 elements: the new mesh vertexCoords, faceVertexIDs, and cellFaceIDs. """ selfc = self._getConcatenableMesh() other = other._getConcatenableMesh() selfNumFaces = selfc.faceVertexIDs.shape[-1] selfNumVertices = selfc.vertexCoords.shape[-1] otherNumFaces = other.faceVertexIDs.shape[-1] otherNumVertices = other.vertexCoords.shape[-1] ## check dimensions if(selfc.vertexCoords.shape[0] != other.vertexCoords.shape[0]): raise MeshAdditionError, "Dimensions do not match" ## compute vertex correlates ## only try to match exterior (X) vertices self_Xvertices = numerix.unique(selfc._getFaceVertexIDs().filled()[..., selfc.getExteriorFaces().getValue()].flatten()) other_Xvertices = numerix.unique(other._getFaceVertexIDs().filled()[..., other.getExteriorFaces().getValue()].flatten()) self_XvertexCoords = selfc.vertexCoords[..., self_Xvertices] other_XvertexCoords = other.vertexCoords[..., other_Xvertices] # lifted from Mesh._getNearestCellID() other_vertexCoordMap = numerix.resize(other_XvertexCoords, (self_XvertexCoords.shape[-1], other_XvertexCoords.shape[0], other_XvertexCoords.shape[-1])).swapaxes(0,1) tmp = self_XvertexCoords[..., numerix.newaxis] - other_vertexCoordMap closest = numerix.argmin(numerix.dot(tmp, tmp), axis=0) # just because they're closest, doesn't mean they're close tmp = self_XvertexCoords[..., closest] - other_XvertexCoords distance = numerix.sqrtDot(tmp, tmp) # only want vertex pairs that are 100x closer than the smallest # cell-to-cell distance close = distance < resolution * min(selfc._getCellToCellDistances().min(), other._getCellToCellDistances().min()) vertexCorrelates = numerix.array((self_Xvertices[closest[close]], other_Xvertices[close])) # warn if meshes don't touch, but allow it if (selfc._getNumberOfVertices() > 0 and other._getNumberOfVertices() > 0 and vertexCorrelates.shape[-1] == 0): import warnings warnings.warn("Vertices are not aligned", UserWarning, stacklevel=4) ## compute face correlates # ensure that both sets of faceVertexIDs have the same maximum number of (masked) elements self_faceVertexIDs = selfc.faceVertexIDs other_faceVertexIDs = other.faceVertexIDs diff = self_faceVertexIDs.shape[0] - other_faceVertexIDs.shape[0] if diff > 0: other_faceVertexIDs = numerix.append(other_faceVertexIDs, -1 * numerix.ones((diff,) + other_faceVertexIDs.shape[1:]), axis=0) other_faceVertexIDs = MA.masked_values(other_faceVertexIDs, -1) elif diff < 0: self_faceVertexIDs = numerix.append(self_faceVertexIDs, -1 * numerix.ones((-diff,) + self_faceVertexIDs.shape[1:]), axis=0) self_faceVertexIDs = MA.masked_values(self_faceVertexIDs, -1) # want self's Faces for which all faceVertexIDs are in vertexCorrelates self_matchingFaces = numerix.in1d(self_faceVertexIDs, vertexCorrelates[0]).reshape(self_faceVertexIDs.shape).all(axis=0).nonzero()[0] # want other's Faces for which all faceVertexIDs are in vertexCorrelates other_matchingFaces = numerix.in1d(other_faceVertexIDs, vertexCorrelates[1]).reshape(other_faceVertexIDs.shape).all(axis=0).nonzero()[0] # map other's Vertex IDs to new Vertex IDs, # accounting for overlaps with self's Vertex IDs vertex_map = numerix.empty(otherNumVertices, dtype=int) verticesToAdd = numerix.delete(numerix.arange(otherNumVertices), vertexCorrelates[1]) vertex_map[verticesToAdd] = numerix.arange(otherNumVertices - len(vertexCorrelates[1])) + selfNumVertices vertex_map[vertexCorrelates[1]] = vertexCorrelates[0] # calculate hashes of faceVertexIDs for comparing Faces if self_matchingFaces.shape[-1] == 0: self_faceHash = numerix.empty(self_matchingFaces.shape[:-1] + (0,), dtype="str") else: # sort each of self's Face's vertexIDs for canonical comparison self_faceHash = numerix.sort(self_faceVertexIDs[..., self_matchingFaces], axis=0) # then hash the Faces for comparison (NumPy set operations are only for 1D arrays) self_faceHash = numerix.apply_along_axis(str, axis=0, arr=self_faceHash) face_sort = numerix.argsort(self_faceHash) self_faceHash = self_faceHash[face_sort] self_matchingFaces = self_matchingFaces[face_sort] if other_matchingFaces.shape[-1] == 0: other_faceHash = numerix.empty(other_matchingFaces.shape[:-1] + (0,), dtype="str") else: # convert each of other's Face's vertexIDs to new IDs other_faceHash = vertex_map[other_faceVertexIDs[..., other_matchingFaces]] # sort each of other's Face's vertexIDs for canonical comparison other_faceHash = numerix.sort(other_faceHash, axis=0) # then hash the Faces for comparison (NumPy set operations are only for 1D arrays) other_faceHash = numerix.apply_along_axis(str, axis=0, arr=other_faceHash) face_sort = numerix.argsort(other_faceHash) other_faceHash = other_faceHash[face_sort] other_matchingFaces = other_matchingFaces[face_sort] self_matchingFaces = self_matchingFaces[numerix.in1d(self_faceHash, other_faceHash)] other_matchingFaces = other_matchingFaces[numerix.in1d(other_faceHash, self_faceHash)] faceCorrelates = numerix.array((self_matchingFaces, other_matchingFaces)) # warn if meshes don't touch, but allow it if (selfc._getNumberOfFaces() > 0 and other._getNumberOfFaces() > 0 and faceCorrelates.shape[-1] == 0): import warnings warnings.warn("Faces are not aligned", UserWarning, stacklevel=4) # map other's Face IDs to new Face IDs, # accounting for overlaps with self's Face IDs face_map = numerix.empty(otherNumFaces, dtype=int) facesToAdd = numerix.delete(numerix.arange(otherNumFaces), faceCorrelates[1]) face_map[facesToAdd] = numerix.arange(otherNumFaces - len(faceCorrelates[1])) + selfNumFaces face_map[faceCorrelates[1]] = faceCorrelates[0] other_faceVertexIDs = vertex_map[other.faceVertexIDs[..., facesToAdd]] # ensure that both sets of cellFaceIDs have the same maximum number of (masked) elements self_cellFaceIDs = selfc.cellFaceIDs other_cellFaceIDs = face_map[other.cellFaceIDs] diff = self_cellFaceIDs.shape[0] - other_cellFaceIDs.shape[0] if diff > 0: other_cellFaceIDs = numerix.append(other_cellFaceIDs, -1 * numerix.ones((diff,) + other_cellFaceIDs.shape[1:]), axis=0) other_cellFaceIDs = MA.masked_values(other_cellFaceIDs, -1) elif diff < 0: self_cellFaceIDs = numerix.append(self_cellFaceIDs, -1 * numerix.ones((-diff,) + self_cellFaceIDs.shape[1:]), axis=0) self_cellFaceIDs = MA.masked_values(self_cellFaceIDs, -1) # concatenate everything and return return { 'vertexCoords': numerix.concatenate((selfc.vertexCoords, other.vertexCoords[..., verticesToAdd]), axis=1), 'faceVertexIDs': numerix.concatenate((self_faceVertexIDs, other_faceVertexIDs), axis=1), 'cellFaceIDs': MA.concatenate((self_cellFaceIDs, other_cellFaceIDs), axis=1) }
def _calcDistanceFunction(self, extensionVariable = None, narrowBandWidth = None, deleteIslands = False): if narrowBandWidth == None: narrowBandWidth = self.narrowBandWidth ## calculate interface values cellToCellIDs = self.mesh._getCellToCellIDs() if deleteIslands: adjVals = numerix.take(self.value, cellToCellIDs) adjInterfaceValues = MA.masked_array(adjVals, mask = (adjVals * self.value) > 0) masksum = numerix.sum(numerix.logical_not(MA.getmask(adjInterfaceValues)), 0) tmp = MA.logical_and(masksum == 4, self.value > 0) self.value = MA.where(tmp, -1, self.value) adjVals = numerix.take(self.value, cellToCellIDs) adjInterfaceValues = MA.masked_array(adjVals, mask = (adjVals * self.value) > 0) dAP = self.mesh._getCellToCellDistances() distances = abs(self.value * dAP / (self.value - adjInterfaceValues)) indices = MA.argsort(distances, 0) sign = (self.value > 0) * 2 - 1 s = distances[indices[0], numerix.arange(indices.shape[1])] if self.mesh.getDim() == 2: t = distances[indices[1], numerix.arange(indices.shape[1])] u = distances[indices[2], numerix.arange(indices.shape[1])] if indices.shape[1] > 0: ns = self.cellNormals[..., indices[0], numerix.arange(indices.shape[1])] nt = self.cellNormals[..., indices[1], numerix.arange(indices.shape[1])] else: ns = MA.zeros(self.cellNormals.shape[:-1] + (0,)) nt = MA.zeros(self.cellNormals.shape[:-1] + (0,)) signedDistance = MA.where(MA.getmask(s), self.value, MA.where(MA.getmask(t), sign * s, MA.where(abs(numerix.dot(ns,nt)) < 0.9, sign * s * t / MA.sqrt(s**2 + t**2), MA.where(MA.getmask(u), sign * s, sign * s * u / MA.sqrt(s**2 + u**2) ) ) ) ) else: signedDistance = MA.where(MA.getmask(s), self.value, sign * s) self.value = signedDistance ## calculate interface flag masksum = numerix.sum(numerix.logical_not(MA.getmask(distances)), 0) interfaceFlag = (masksum > 0).astype('l') ## spread the extensionVariable to the whole interface flag = True if extensionVariable is None: extensionVariable = numerix.zeros(self.mesh.getNumberOfCells(), 'd') flag = False ext = numerix.zeros(self.mesh.getNumberOfCells(), 'd') positiveInterfaceFlag = numerix.where(self.value > 0, interfaceFlag, 0) negativeInterfaceIDs = numerix.nonzero(numerix.where(self.value < 0, interfaceFlag, 0))[0] for id in negativeInterfaceIDs: tmp, extensionVariable[...,id] = self._calcTrialValue(id, positiveInterfaceFlag, extensionVariable) if flag: self.value = self.tmpValue.copy() ## evaluate the trialIDs adjInterfaceFlag = numerix.take(interfaceFlag, cellToCellIDs) hasAdjInterface = (numerix.sum(MA.filled(adjInterfaceFlag, 0), 0) > 0).astype('l') trialFlag = numerix.logical_and(numerix.logical_not(interfaceFlag), hasAdjInterface).astype('l') trialIDs = list(numerix.nonzero(trialFlag)[0]) evaluatedFlag = interfaceFlag for id in trialIDs: self.value[...,id], extensionVariable[id] = self._calcTrialValue(id, evaluatedFlag, extensionVariable) while len(trialIDs): id = trialIDs[numerix.argmin(abs(numerix.take(self.value, trialIDs)))] if abs(self.value[...,id]) > narrowBandWidth / 2: break trialIDs.remove(id) evaluatedFlag[...,id] = 1 for adjID in MA.filled(cellToCellIDs[...,id], -1): if adjID != -1: if not evaluatedFlag[...,adjID]: self.value[...,adjID], extensionVariable[...,adjID] = self._calcTrialValue(adjID, evaluatedFlag, extensionVariable) if adjID not in trialIDs: trialIDs.append(adjID) self.value = numerix.array(self.value)
def _calcTrialValue(self, id, evaluatedFlag, extensionVariable): adjIDs = self.cellToCellIDs[...,id] adjEvaluatedFlag = numerix.take(evaluatedFlag, adjIDs) adjValues = numerix.take(self.value, adjIDs) adjValues = numerix.where(adjEvaluatedFlag, adjValues, 1e+10) try: indices = numerix.argsort(abs(adjValues)) except TypeError: # numpy 1.1 raises a TypeError when using argsort function indices = abs(adjValues).argsort() sign = (self.value[id] > 0) * 2 - 1 d0 = self.cellToCellDistances[indices[0], id] v0 = self.value[..., adjIDs[indices[0]]] e0 = extensionVariable[..., adjIDs[indices[0]]] N = numerix.sum(adjEvaluatedFlag) index0 = indices[0] index1 = indices[1] index2 = indices[self.mesh.getDim()] if N > 1: n0 = self.cellNormals[..., index0, id] n1 = self.cellNormals[..., index1, id] if self.mesh.getDim() == 2: cross = (n0[0] * n1[1] - n0[1] * n1[0]) else: cross = 0.0 if abs(cross) < 0.1: if N == 2: N = 1 elif N == 3: index1 = index2 if N == 0: raise Exception elif N == 1: return v0 + sign * d0, e0 else: d1 = self.cellToCellDistances[index1, id] n0 = self.cellNormals[..., index0, id] n1 = self.cellNormals[..., index1, id] v1 = self.value[..., adjIDs[index1]] crossProd = d0 * d1 * (n0[0] * n1[1] - n0[1] * n1[0]) dotProd = d0 * d1 * numerix.dot(n0, n1) dsq = d0**2 + d1**2 - 2 * dotProd top = -v0 * (dotProd - d1**2) - v1 * (dotProd - d0**2) sqrt = crossProd**2 *(dsq - (v0 - v1)**2) sqrt = numerix.sqrt(max(sqrt, 0)) dis = (top + sign * sqrt) / dsq ## extension variable e1 = extensionVariable[..., adjIDs[index1]] a0 = self.cellAreas[index0, id] a1 = self.cellAreas[index1, id] if self.value[id] > 0: phi = max(dis, 0) else: phi = min(dis, 0) n0grad = a0 * abs(v0 - phi) / d0 n1grad = a1 * abs(v1 - phi) / d1 return dis, (e0 * n0grad + e1 * n1grad) / (n0grad + n1grad)
Z = CellVariable(name=r"$Z$", mesh=mesh, hasOld=True) Diffusivity = CellVariable(name=r"$D$", mesh=mesh, hasOld=True) # ----------- Initial Conditions of Z --------------------- Z0L = 1.0 # L--mode Z0H = Z_S * (1.0 - numerix.tanh((L * x - L) / 2.0)) # H--mode Z.setValue(Z0H) # ----------------- Diffusivities ------------------------- # Itohs'/Zohm's model D_Zohm = (D_max + D_min) / 2.0 + ((D_max - D_min) * numerix.tanh(Z)) / 2.0 # Stap's Model alpha_sup = 0.5 D_Staps = D_min + (D_max - D_min) / (1.0 + alpha_sup * numerix.dot(Z.grad, Z.grad)) # Flow-Shear Model a1, a3 = 1.0, 0.5 # ASSUMES a2 = 0 D_Shear = D_min + (D_max - D_min) / (1.0 + a1 * (Z)**2 + a3 * numerix.dot(Z.grad, Z.grad)) # CHOOSE DIFFUSIVITY HERE! D_choice = D_Staps # If Diffusivity is a Cell/Face variable Diffusivity.setValue(D_choice) Diffusivity.equation = (ImplicitSourceTerm(1.0)) # ----------------- Boundary Conditions ------------------- """ Density Boundary Conditions:
def _calcValue(self): normals = numerix.array( MA.filled(self.distanceVar._cellInterfaceNormals, 0)) areas = numerix.array(MA.filled(self.mesh._cellAreaProjections, 0)) return numerix.sum(abs(numerix.dot(normals, areas)), axis=0)