def _calcInteriorAndExteriorFaceIDs(self): from fipy.variables.faceVariable import FaceVariable mask = MA.getmask(self.faceCellIDs[1]) exteriorFaces = FaceVariable(mesh=self, value=mask) interiorFaces = FaceVariable(mesh=self, value=numerix.logical_not(mask)) return interiorFaces, exteriorFaces
def _calcGeomCoeff(self, var): mesh = var.mesh if self.nthCoeff is not None: coeff = self.nthCoeff shape = numerix.getShape(coeff) if isinstance(coeff, FaceVariable): rank = coeff.rank else: rank = len(shape) if var.rank == 0: anisotropicRank = rank elif var.rank == 1: anisotropicRank = rank - 2 else: raise IndexError('the solution variable has the wrong rank') if anisotropicRank == 0 and self._treatMeshAsOrthogonal(mesh): if coeff.shape != () and not isinstance(coeff, FaceVariable): coeff = coeff[..., numerix.newaxis] tmpBop = (coeff * FaceVariable(mesh=mesh, value=mesh._faceAreas) / mesh._cellDistances)[numerix.newaxis, :] else: if anisotropicRank == 1 or anisotropicRank == 0: coeff = coeff * numerix.identity(mesh.dim) if anisotropicRank > 0: shape = numerix.getShape(coeff) if mesh.dim != shape[0] or mesh.dim != shape[1]: raise IndexError( 'diffusion coefficient tensor is not an appropriate shape for this mesh' ) faceNormals = FaceVariable(mesh=mesh, rank=1, value=mesh.faceNormals) rotationTensor = self.__getRotationTensor(mesh) rotationTensor[:, 0] = rotationTensor[:, 0] / mesh._cellDistances tmpBop = faceNormals.dot(coeff).dot( rotationTensor) * mesh._faceAreas return tmpBop else: return None
def __init__(self, distanceVar): """ Simple one dimensional test: >>> from fipy.variables.cellVariable import CellVariable >>> from fipy.meshes import Grid2D >>> mesh = Grid2D(nx = 3, ny = 1, dx = 1., dy = 1.) >>> from fipy.variables.distanceVariable import DistanceVariable >>> distanceVar = DistanceVariable(mesh, value = (-.5, .5, 1.5)) >>> ## answer = numerix.zeros((2, mesh.numberOfFaces),'d') >>> answer = FaceVariable(mesh=mesh, rank=1, value=0.).globalValue >>> answer[0, 7] = -1 >>> print(numerix.allclose(SurfactantConvectionVariable(distanceVar).globalValue, answer)) True Change the dimensions: >>> mesh = Grid2D(nx = 3, ny = 1, dx = .5, dy = .25) >>> distanceVar = DistanceVariable(mesh, value = (-.25, .25, .75)) >>> answer[0, 7] = -.5 >>> print(numerix.allclose(SurfactantConvectionVariable(distanceVar).globalValue, answer)) True Two dimensional example: >>> mesh = Grid2D(nx = 2, ny = 2, dx = 1., dy = 1.) >>> distanceVar = DistanceVariable(mesh, value = (-1.5, -.5, -.5, .5)) >>> answer = FaceVariable(mesh=mesh, rank=1, value=0.).globalValue >>> answer[1, 2] = -.5 >>> answer[1, 3] = -1 >>> answer[0, 7] = -.5 >>> answer[0, 10] = -1 >>> print(numerix.allclose(SurfactantConvectionVariable(distanceVar).globalValue, answer)) True Larger grid: >>> mesh = Grid2D(nx = 3, ny = 3, dx = 1., dy = 1.) >>> distanceVar = DistanceVariable(mesh, value = (1.5, .5, 1.5, ... .5, -.5, .5, ... 1.5, .5, 1.5)) >>> answer = FaceVariable(mesh=mesh, rank=1, value=0.).globalValue >>> answer[1, 4] = .25 >>> answer[1, 7] = -.25 >>> answer[0, 17] = .25 >>> answer[0, 18] = -.25 >>> print(numerix.allclose(SurfactantConvectionVariable(distanceVar).globalValue, answer)) True """ FaceVariable.__init__(self, mesh=distanceVar.mesh, name='surfactant convection', rank=1) self.distanceVar = self._requires(distanceVar)
def _calcGeomCoeff(self, var): mesh = var.mesh if self.nthCoeff is not None: coeff = self.nthCoeff shape = numerix.getShape(coeff) if isinstance(coeff, FaceVariable): rank = coeff.rank else: rank = len(shape) if var.rank == 0: anisotropicRank = rank elif var.rank == 1: anisotropicRank = rank - 2 else: raise IndexError, 'the solution variable has the wrong rank' if anisotropicRank == 0 and self._treatMeshAsOrthogonal(mesh): if coeff.shape != () and not isinstance(coeff, FaceVariable): coeff = coeff[...,numerix.newaxis] tmpBop = (coeff * FaceVariable(mesh=mesh, value=mesh._faceAreas) / mesh._cellDistances)[numerix.newaxis, :] else: if anisotropicRank == 1 or anisotropicRank == 0: coeff = coeff * numerix.identity(mesh.dim) if anisotropicRank > 0: shape = numerix.getShape(coeff) if mesh.dim != shape[0] or mesh.dim != shape[1]: raise IndexError, 'diffusion coefficent tensor is not an appropriate shape for this mesh' faceNormals = FaceVariable(mesh=mesh, rank=1, value=mesh.faceNormals) rotationTensor = self.__getRotationTensor(mesh) rotationTensor[:,0] = rotationTensor[:,0] / mesh._cellDistances tmpBop = faceNormals.dot(coeff).dot(rotationTensor) * mesh._faceAreas return tmpBop else: return None
def _calcGeomCoeff(self, mesh): if not isinstance(self.coeff, FaceVariable): self.coeff = FaceVariable(mesh=mesh, value=self.coeff, rank=1) projectedCoefficients = self.coeff * mesh._getOrientedAreaProjections() return projectedCoefficients.sum(0)
def __getRotationTensor(self, mesh): if not hasattr(self, 'rotationTensor'): rotationTensor = FaceVariable(mesh=mesh, rank=2) rotationTensor[:, 0] = self._getNormals(mesh) if mesh.dim == 2: rotationTensor[:, 1] = rotationTensor[:, 0].dot( (((0, 1), (-1, 0)))) elif mesh.dim == 3: epsilon = 1e-20 div = numerix.sqrt(1 - rotationTensor[2, 0]**2) flag = numerix.resize(div > epsilon, (mesh.dim, mesh.numberOfFaces)) rotationTensor[0, 1] = 1 rotationTensor[:, 1] = numerix.where( flag, rotationTensor[:, 0].dot( (((0, 1, 0), (-1, 0, 0), (0, 0, 0)))) / div, rotationTensor[:, 1]) rotationTensor[1, 2] = 1 rotationTensor[:, 2] = numerix.where( flag, rotationTensor[:, 0] * rotationTensor[2, 0] / div, rotationTensor[:, 2]) rotationTensor[2, 2] = -div self.rotationTensor = rotationTensor return self.rotationTensor
def _exteriorFaces(self): """ Return only the faces that have one neighboring cell. """ exteriorIDs = numerix.concatenate((numerix.arange(0, self.nx), numerix.arange(0, self.nx) + self.nx * self.ny, numerix.arange(0, self.ny) * self.numberOfVerticalColumns + self.numberOfHorizontalFaces, numerix.arange(0, self.ny) * self.numberOfVerticalColumns + self.numberOfHorizontalFaces + self.nx)) from fipy.variables.faceVariable import FaceVariable exteriorFaces = FaceVariable(mesh=self, value=False) exteriorFaces[exteriorIDs] = True return exteriorFaces
def _calcGeomCoeff(self, var): mesh = var.mesh if not isinstance(self.coeff, FaceVariable): shape = numerix.array(self.coeff).shape if shape != () and shape != (1,) and shape[-1] == 1: shape = shape[:-1] self.coeff = FaceVariable(mesh=mesh, elementshape=shape, value=self.coeff) projectedCoefficients = self.coeff * mesh._orientedAreaProjections return projectedCoefficients.sum(0)
def _calcGeomCoeff(self, mesh): if self.nthCoeff is not None: coeff = self.nthCoeff shape = numerix.getShape(coeff) from fipy.variables.faceVariable import FaceVariable if isinstance(coeff, FaceVariable): rank = coeff.getRank() else: rank = len(shape) if rank == 0 and self._treatMeshAsOrthogonal(mesh): tmpBop = (coeff * mesh._getFaceAreas() / mesh._getCellDistances())[numerix.newaxis, :] else: if rank == 1 or rank == 0: coeff = coeff * numerix.identity(mesh.getDim()) if rank > 0: shape = numerix.getShape(coeff) if mesh.getDim() != shape[0] or mesh.getDim() != shape[1]: raise IndexError, 'diffusion coefficent tensor is not an appropriate shape for this mesh' faceNormals = FaceVariable(mesh=mesh, rank=1, value=mesh._getFaceNormals()) rotationTensor = self._getRotationTensor(mesh) rotationTensor[:,0] = rotationTensor[:,0] / mesh._getCellDistances() tmpBop = faceNormals.dot(coeff).dot(rotationTensor) * mesh._getFaceAreas() return tmpBop else: return None
def _interiorFaces(self): """ Return only the faces that have two neighboring cells """ XYids = self._XYFaceIDs XZids = self._XZFaceIDs YZids = self._YZFaceIDs interiorIDs = numerix.concatenate((numerix.ravel(XYids[ ... ,1:-1]), numerix.ravel(XZids[ :, 1:-1, :]), numerix.ravel(YZids[1:-1, ...].swapaxes(0,1)))) from fipy.variables.faceVariable import FaceVariable interiorFaces = FaceVariable(mesh=self, value=False) interiorFaces[interiorIDs] = True return interiorFaces
def _exteriorFaces(self): """ Return only the faces that have one neighboring cell. """ XYids = self._XYFaceIDs XZids = self._XZFaceIDs YZids = self._YZFaceIDs exteriorIDs = numerix.concatenate( (numerix.ravel(XYids[..., 0].swapaxes(0, 1)), numerix.ravel(XYids[..., -1].swapaxes(0, 1)), numerix.ravel(XZids[:, 0, :]), numerix.ravel(XZids[:, -1, :]), numerix.ravel(YZids[0, ...]), numerix.ravel(YZids[-1, ...]))) from fipy.variables.faceVariable import FaceVariable exteriorFaces = FaceVariable(mesh=self, value=False) exteriorFaces[exteriorIDs] = True return exteriorFaces
def _interiorFaces(self): """ Return only the faces that have two neighboring cells. """ Hids = numerix.arange(0, self.numberOfHorizontalFaces) Hids = numerix.reshape(Hids, (self.numberOfHorizontalRows, self.nx)) Hids = Hids[1:-1, ...] Vids = numerix.arange(self.numberOfHorizontalFaces, self.numberOfFaces) Vids = numerix.reshape(Vids, (self.ny, self.numberOfVerticalColumns)) Vids = Vids[..., 1:-1] interiorIDs = numerix.concatenate((numerix.reshape(Hids, (self.nx * (self.ny - 1),)), numerix.reshape(Vids, ((self.nx - 1) * self.ny,)))) from fipy.variables.faceVariable import FaceVariable interiorFaces = FaceVariable(mesh=self, value=False) interiorFaces[interiorIDs] = True return interiorFaces
def __init__(self, P): FaceVariable.__init__(self, P.getMesh()) self.P = self._requires(P)
def _buildMatrix(self, var, SparseMatrix, boundaryConditions=(), dt=None, transientGeomCoeff=None, diffusionGeomCoeff=None): """ Test to ensure that a changing coefficient influences the boundary conditions. >>> from fipy import * >>> m = Grid2D(nx=2, ny=2) >>> v = CellVariable(mesh=m) >>> c0 = Variable(1.) >>> v.constrain(c0, where=m.facesLeft) Diffusion will only be in the y-direction >>> coeff = Variable([[0. , 0.], [0. , 1.]]) >>> eq = DiffusionTerm(coeff) >>> eq.solve(v, solver=DummySolver()) >>> print v [ 0. 0. 0. 0.] Change the coefficient. >>> coeff[0, 0] = 1. >>> eq.solve(v) >>> print v [ 1. 1. 1. 1.] Change the constraints. >>> c0.setValue(2.) >>> v.constrain(3., where=m.facesRight) >>> print v.faceValue.constraintMask [False False False False False False True False True True False True] >>> eq.solve(v) >>> print v [ 2.25 2.75 2.25 2.75] """ var, L, b = self.__higherOrderbuildMatrix(var, SparseMatrix, boundaryConditions=boundaryConditions, dt=dt, transientGeomCoeff=transientGeomCoeff, diffusionGeomCoeff=diffusionGeomCoeff) mesh = var.mesh if self.order == 2: if (not hasattr(self, 'constraintL')) or (not hasattr(self, 'constraintB')): normals = FaceVariable(mesh=mesh, rank=1, value=mesh._orientedFaceNormals) if len(var.shape) == 1 and len(self.nthCoeff.shape) > 1: nthCoeffFaceGrad = var.faceGrad.dot(self.nthCoeff) normalsNthCoeff = normals.dot(self.nthCoeff) else: if self.nthCoeff.shape != () and not isinstance(self.nthCoeff, FaceVariable): coeff = self.nthCoeff[...,numerix.newaxis] else: coeff = self.nthCoeff nthCoeffFaceGrad = coeff[numerix.newaxis] * var.faceGrad[:,numerix.newaxis] s = (slice(0,None,None),) + (numerix.newaxis,) * (len(coeff.shape) - 1) + (slice(0,None,None),) normalsNthCoeff = coeff[numerix.newaxis] * normals[s] self.constraintB = -(var.faceGrad.constraintMask * nthCoeffFaceGrad).divergence * mesh.cellVolumes constrainedNormalsDotCoeffOverdAP = var.arithmeticFaceValue.constraintMask * \ normalsNthCoeff / mesh._cellDistances self.constraintB -= (constrainedNormalsDotCoeffOverdAP * var.arithmeticFaceValue).divergence * mesh.cellVolumes ids = self._reshapeIDs(var, numerix.arange(mesh.numberOfCells)) self.constraintL = -constrainedNormalsDotCoeffOverdAP.divergence * mesh.cellVolumes ids = self._reshapeIDs(var, numerix.arange(mesh.numberOfCells)) L.addAt(self.constraintL.ravel(), ids.ravel(), ids.swapaxes(0,1).ravel()) b += numerix.reshape(self.constraintB.ravel(), ids.shape).sum(-2).ravel() return (var, L, b)
def __init__(self, P): FaceVariable.__init__(self, P.mesh, value=0.5)
def faceCenters(self): from fipy.variables.faceVariable import FaceVariable return FaceVariable(mesh=self, value=self._faceCenters, rank=1)
def __init__(self, P): FaceVariable.__init__(self, P.mesh) self.P = self._requires(P)
def __init__(self, var): FaceVariable.__init__(self, mesh=var.getMesh(), elementshape=var.shape[:-1]) self.var = self._requires(var)
ny = 1 valueLeft = 0. fluxRight = 1. timeStepDuration = 1. L = 10. dx = L / nx dy = 1. mesh = Tri2D(dx, dy, nx, ny) var = CellVariable(name="solution variable", mesh=mesh, value=valueLeft) from fipy.variables.faceVariable import FaceVariable diffCoeff = FaceVariable(mesh=mesh, value=1.0) x = mesh.getFaceCenters()[..., 0] diffCoeff.setValue(0.1, where=(L / 4. <= x) & (x < 3. * L / 4.)) boundaryConditions = (FixedValue(mesh.getFacesLeft(), valueLeft), FixedFlux(mesh.getFacesRight(), fluxRight)) if __name__ == '__main__': ImplicitDiffusionTerm(coeff=diffCoeff).solve( var, boundaryConditions=boundaryConditions) viewer = fipy.viewers.make(vars=var) viewer.plot() raw_input('finished')
def __init__(self, P): FaceVariable.__init__(self, mesh=P.mesh, elementshape=P.shape[:-1]) self.P = self._requires(P)
def _connectFaces(self, faces0, faces1): """ Merge faces on the same mesh. This is used to create periodic meshes. The first list of faces, `faces1`, will be the faces that are used to add to the matrix diagonals. The faces in `faces2` will not be used. They aren't deleted but their adjacent cells are made to point at `faces1`. The list `faces2` are not altered, they still remain as members of exterior faces. >>> from fipy.meshes.nonUniformGrid2D import NonUniformGrid2D >>> mesh = NonUniformGrid2D(nx = 2, ny = 2, dx = 1., dy = 1.) >>> print((mesh.cellFaceIDs == [[0, 1, 2, 3], ... [7, 8, 10, 11], ... [2, 3, 4, 5], ... [6, 7, 9, 10]]).flatten().all()) # doctest: +PROCESSOR_0 True >>> mesh._connectFaces(numerix.nonzero(mesh.facesLeft), numerix.nonzero(mesh.facesRight)) >>> print((mesh.cellFaceIDs == [[0, 1, 2, 3], ... [7, 6, 10, 9], ... [2, 3, 4, 5], ... [6, 7, 9, 10]]).flatten().all()) # doctest: +PROCESSOR_0 True """ ## check for errors ## check that faces are members of exterior faces from fipy.variables.faceVariable import FaceVariable faces = FaceVariable(mesh=self, value=False) faces[faces0] = True faces[faces1] = True assert (faces | self.exteriorFaces == self.exteriorFaces).all() ## following assert checks number of faces are equal, normals are opposite and areas are the same assert numerix.allclose(numerix.take(self._areaProjections, faces0, axis=1), numerix.take(-self._areaProjections, faces1, axis=1)) ## extract the adjacent cells for both sets of faces faceCellIDs0 = self.faceCellIDs[0] faceCellIDs1 = self.faceCellIDs[1] ## set the new adjacent cells for `faces0` MA.put(faceCellIDs1, faces0, MA.take(faceCellIDs0, faces0)) MA.put(faceCellIDs0, faces0, MA.take(faceCellIDs0, faces1)) self.faceCellIDs[0] = faceCellIDs0 self.faceCellIDs[1] = faceCellIDs1 ## extract the face to cell distances for both sets of faces faceToCellDistances0 = self._faceToCellDistances[0] faceToCellDistances1 = self._faceToCellDistances[1] ## set the new faceToCellDistances for `faces0` MA.put(faceToCellDistances1, faces0, MA.take(faceToCellDistances0, faces0)) MA.put(faceToCellDistances0, faces0, MA.take(faceToCellDistances0, faces1)) self._faceToCellDistances[0] = faceToCellDistances0 self._faceToCellDistances[1] = faceToCellDistances1 ## calculate new cell distances and add them to faces0 numerix.put(self._cellDistances, faces0, MA.take(faceToCellDistances0 + faceToCellDistances1, faces0)) ## change the direction of the face normals for faces0 for dim in range(self.dim): faceNormals = self.faceNormals[dim].copy() numerix.put(faceNormals, faces0, MA.take(faceNormals, faces1)) self.faceNormals[dim] = faceNormals ## Cells that are adjacent to faces1 are changed to point at faces0 ## get the cells adjacent to faces1 faceCellIDs = MA.take(self.faceCellIDs[0], faces1) ## get all the adjacent faces for those particular cells cellFaceIDs = numerix.take(self.cellFaceIDs, faceCellIDs, axis=1) for i in range(cellFaceIDs.shape[0]): ## if the faces is a member of faces1 then change the face to point at ## faces0 cellFaceIDs[i] = MA.where(cellFaceIDs[i] == faces1, faces0, cellFaceIDs[i]) ## add those faces back to the main self.cellFaceIDs numerix.put(self.cellFaceIDs[i], faceCellIDs, cellFaceIDs[i]) ## calculate new topology self._setTopology() ## calculate new geometry self._handleFaceConnection() self.scale = self.scale['length']
def __init__(self, P): FaceVariable.__init__(self, P.getMesh()) self.value = 0.5
class ConvectionTerm(FaceTerm): """ .. attention:: This class is abstract. Always create one of its subclasses. """ def __init__(self, coeff=1.0, diffusionTerm=None): """ Create a `ConvectionTerm` object. >>> from fipy.meshes.grid1D import Grid1D >>> from fipy.variables.cellVariable import CellVariable >>> from fipy.variables.faceVariable import FaceVariable >>> m = Grid1D(nx = 2) >>> cv = CellVariable(mesh = m) >>> fv = FaceVariable(mesh = m) >>> vcv = CellVariable(mesh=m, rank=1) >>> vfv = FaceVariable(mesh=m, rank=1) >>> __ConvectionTerm(coeff = cv) Traceback (most recent call last): ... TypeError: The coefficient must be a vector value. >>> __ConvectionTerm(coeff = fv) Traceback (most recent call last): ... TypeError: The coefficient must be a vector value. >>> __ConvectionTerm(coeff = vcv) __ConvectionTerm(coeff=_ArithmeticCellToFaceVariable(value=array([[ 0., 0., 0.]]), mesh=UniformGrid1D(dx=1.0, nx=2))) >>> __ConvectionTerm(coeff = vfv) __ConvectionTerm(coeff=FaceVariable(value=array([[ 0., 0., 0.]]), mesh=UniformGrid1D(dx=1.0, nx=2))) >>> __ConvectionTerm(coeff = (1,)) __ConvectionTerm(coeff=(1,)) >>> from fipy.terms.explicitUpwindConvectionTerm import ExplicitUpwindConvectionTerm >>> ExplicitUpwindConvectionTerm(coeff = (0,)).solve(var = cv) >>> ExplicitUpwindConvectionTerm(coeff = 1).solve(var = cv) Traceback (most recent call last): ... TypeError: The coefficient must be a vector value. >>> from fipy.meshes.grid2D import Grid2D >>> m2 = Grid2D(nx=2, ny=1) >>> cv2 = CellVariable(mesh=m2) >>> vcv2 = CellVariable(mesh=m2, rank=1) >>> vfv2 = FaceVariable(mesh=m2, rank=1) >>> __ConvectionTerm(coeff=vcv2) __ConvectionTerm(coeff=_ArithmeticCellToFaceVariable(value=array([[ 0., 0., 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0., 0., 0.]]), mesh=UniformGrid2D(dx=1.0, nx=2, dy=1.0, ny=1))) >>> __ConvectionTerm(coeff=vfv2) __ConvectionTerm(coeff=FaceVariable(value=array([[ 0., 0., 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0., 0., 0.]]), mesh=UniformGrid2D(dx=1.0, nx=2, dy=1.0, ny=1))) >>> ExplicitUpwindConvectionTerm(coeff = ((0,),(0,))).solve(var=cv2) >>> ExplicitUpwindConvectionTerm(coeff = (0,0)).solve(var=cv2) :Parameters: - `coeff` : The `Term`'s coefficient value. - `diffusionTerm` : **deprecated**. The Peclet number is calculated automatically. """ if self.__class__ is ConvectionTerm: raise NotImplementedError, "can't instantiate abstract base class" if diffusionTerm is not None: import warnings warnings.warn("The Peclet number is calculated automatically. diffusionTerm will be ignored.", DeprecationWarning, stacklevel=2) self.stencil = None if isinstance(coeff, _MeshVariable) and coeff.getRank() != 1: raise TypeError, "The coefficient must be a vector value." if isinstance(coeff, CellVariable): coeff = coeff.getArithmeticFaceValue() FaceTerm.__init__(self, coeff = coeff) def _calcGeomCoeff(self, mesh): if not isinstance(self.coeff, FaceVariable): self.coeff = FaceVariable(mesh=mesh, value=self.coeff, rank=1) projectedCoefficients = self.coeff * mesh._getOrientedAreaProjections() return projectedCoefficients.sum(0) def _getWeight(self, mesh, equation=None): if self.stencil is None: small = -1e-20 if equation is None: diffCoeff = small else: diffCoeff = equation._getDiffusiveGeomCoeff(mesh) if diffCoeff is None: diffCoeff = small else: diffCoeff = diffCoeff.getNumericValue() diffCoeff = (diffCoeff == 0) * small + diffCoeff alpha = self._Alpha(-self._getGeomCoeff(mesh) / diffCoeff) self.stencil = {'implicit' : {'cell 1 diag' : alpha, 'cell 1 offdiag' : (1-alpha), 'cell 2 diag' : -(1-alpha), 'cell 2 offdiag' : -alpha}} return self.stencil def _getDefaultSolver(self, solver, *args, **kwargs): if solver and not solver._canSolveAsymmetric(): import warnings warnings.warn("%s cannot solve assymetric matrices" % solver) return solver or DefaultAsymmetricSolver(*args, **kwargs) def _verifyCoeffType(self, var): if not (isinstance(self.coeff, FaceVariable) and self.coeff.getRank() == 1) \ and numerix.getShape(self.coeff) != (var.getMesh().getDim(),): raise TypeError, "The coefficient must be a vector value." def __add__(self, other): if isinstance(other, ConvectionTerm): if other.__class__ != self.__class__: raise TypeError, "ConvectionTerms must use the same scheme: %s != %s" % (self.__class__.__name__, other.__class__.__name__) return self.__class__(coeff=self.coeff + other.coeff) else: return FaceTerm.__add__(self, other)
def _buildMatrix(self, var, SparseMatrix, boundaryConditions=(), dt=None, transientGeomCoeff=None, diffusionGeomCoeff=None): """ Test to ensure that a changing coefficient influences the boundary conditions. >>> from fipy import * >>> m = Grid2D(nx=2, ny=2) >>> v = CellVariable(mesh=m) >>> c0 = Variable(1.) >>> v.constrain(c0, where=m.facesLeft) Diffusion will only be in the y-direction >>> coeff = Variable([[0. , 0.], [0. , 1.]]) >>> eq = DiffusionTerm(coeff) >>> eq.solve(v, solver=DummySolver()) >>> print v [ 0. 0. 0. 0.] Change the coefficient. >>> coeff[0, 0] = 1. >>> eq.solve(v) >>> print v [ 1. 1. 1. 1.] Change the constraints. >>> c0.setValue(2.) >>> v.constrain(3., where=m.facesRight) >>> print v.faceValue.constraintMask [False False False False False False True False True True False True] >>> eq.solve(v) >>> print v [ 2.25 2.75 2.25 2.75] """ var, L, b = self.__higherOrderbuildMatrix( var, SparseMatrix, boundaryConditions=boundaryConditions, dt=dt, transientGeomCoeff=transientGeomCoeff, diffusionGeomCoeff=diffusionGeomCoeff) mesh = var.mesh if self.order == 2: if (not hasattr(self, 'constraintL')) or (not hasattr( self, 'constraintB')): normals = FaceVariable(mesh=mesh, rank=1, value=mesh._orientedFaceNormals) if len(var.shape) == 1 and len(self.nthCoeff.shape) > 1: nthCoeffFaceGrad = var.faceGrad.dot(self.nthCoeff) normalsNthCoeff = normals.dot(self.nthCoeff) else: if self.nthCoeff.shape != () and not isinstance( self.nthCoeff, FaceVariable): coeff = self.nthCoeff[..., numerix.newaxis] else: coeff = self.nthCoeff nthCoeffFaceGrad = coeff[ numerix.newaxis] * var.faceGrad[:, numerix.newaxis] s = (slice(0, None, None), ) + (numerix.newaxis, ) * ( len(coeff.shape) - 1) + (slice(0, None, None), ) normalsNthCoeff = coeff[numerix.newaxis] * normals[s] self.constraintB = -( var.faceGrad.constraintMask * nthCoeffFaceGrad).divergence * mesh.cellVolumes constrainedNormalsDotCoeffOverdAP = var.arithmeticFaceValue.constraintMask * \ normalsNthCoeff / mesh._cellDistances self.constraintB -= ( constrainedNormalsDotCoeffOverdAP * var.arithmeticFaceValue).divergence * mesh.cellVolumes ids = self._reshapeIDs(var, numerix.arange(mesh.numberOfCells)) self.constraintL = -constrainedNormalsDotCoeffOverdAP.divergence * mesh.cellVolumes ids = self._reshapeIDs(var, numerix.arange(mesh.numberOfCells)) L.addAt(self.constraintL.ravel(), ids.ravel(), ids.swapaxes(0, 1).ravel()) b += numerix.reshape(self.constraintB.ravel(), ids.shape).sum(-2).ravel() return (var, L, b)
valueLeft = 0. fluxRight = 1. timeStepDuration = 1. L = 10. dx = L / nx dy = 1. mesh = Tri2D(dx, dy, nx, ny) var = CellVariable( name = "solution variable", mesh = mesh, value = valueLeft) from fipy.variables.faceVariable import FaceVariable diffCoeff = FaceVariable(mesh = mesh, value = 1.0) x = mesh.getFaceCenters()[...,0] diffCoeff.setValue(0.1, where=(L/4. <= x) & (x < 3. * L / 4.)) boundaryConditions=(FixedValue(mesh.getFacesLeft(),valueLeft), FixedFlux(mesh.getFacesRight(),fluxRight)) if __name__ == '__main__': ImplicitDiffusionTerm(coeff = diffCoeff).solve(var, boundaryConditions = boundaryConditions) viewer = fipy.viewers.make(vars = var) viewer.plot() raw_input('finished')
def _interiorFaces(self): from fipy.variables.faceVariable import FaceVariable interiorFaces = FaceVariable(mesh=self, value=False) interiorFaces[numerix.arange(self.numberOfFaces - 2) + 1] = True return interiorFaces
def __init__(self, var): FaceVariable.__init__(self, mesh=var.mesh, elementshape=(var.mesh.dim,) + var.shape[:-1]) self.var = self._requires(var)
def __init__(self, var): FaceVariable.__init__(self, mesh=var.mesh, elementshape=(var.mesh.dim, ) + var.shape[:-1]) self.var = self._requires(var)
def __init__(self, var): FaceVariable.__init__(self, mesh=var.getMesh(), rank=var.getRank() + 1) self.var = self._requires(var)