Пример #1
0
 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
Пример #2
0
    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
Пример #3
0
    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)
Пример #4
0
    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
Пример #5
0
 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)
Пример #6
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
Пример #7
0
    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
Пример #8
0
    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)
Пример #9
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
Пример #10
0
    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
Пример #11
0
    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
Пример #12
0
    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
Пример #13
0
 def __init__(self, P):
     FaceVariable.__init__(self, P.getMesh())
     self.P = self._requires(P)
Пример #14
0
    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)
Пример #15
0
 def __init__(self, P):
     FaceVariable.__init__(self, P.mesh, value=0.5)
Пример #16
0
 def faceCenters(self):
     from fipy.variables.faceVariable import FaceVariable
     return FaceVariable(mesh=self, value=self._faceCenters,
                         rank=1)
Пример #17
0
 def __init__(self, P):
     FaceVariable.__init__(self, P.mesh)
     self.P = self._requires(P)
Пример #18
0
 def __init__(self, var):
     FaceVariable.__init__(self, mesh=var.getMesh(), elementshape=var.shape[:-1])
     self.var = self._requires(var)
Пример #19
0
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')
Пример #20
0
 def __init__(self, P):
     FaceVariable.__init__(self, mesh=P.mesh, elementshape=P.shape[:-1])
     self.P = self._requires(P)
Пример #21
0
    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']
Пример #22
0
 def __init__(self, P):
     FaceVariable.__init__(self, P.mesh, value=0.5)
 def __init__(self, P):
     FaceVariable.__init__(self, P.getMesh())
     self.value = 0.5
Пример #24
0
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)
Пример #25
0
    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)
Пример #26
0
 def __init__(self, P):
     FaceVariable.__init__(self, mesh=P.mesh, elementshape=P.shape[:-1])
     self.P = self._requires(P)
Пример #27
0
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')
Пример #28
0
 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
Пример #29
0
 def __init__(self, var):
     FaceVariable.__init__(self, mesh=var.mesh, elementshape=(var.mesh.dim,) + var.shape[:-1])
     self.var = self._requires(var)
Пример #30
0
 def __init__(self, P):
     FaceVariable.__init__(self, P.mesh)
     self.P = self._requires(P)
Пример #31
0
 def __init__(self, var):
     FaceVariable.__init__(self,
                           mesh=var.mesh,
                           elementshape=(var.mesh.dim, ) + var.shape[:-1])
     self.var = self._requires(var)
Пример #32
0
 def __init__(self, var):
     FaceVariable.__init__(self, mesh=var.getMesh(), rank=var.getRank() + 1)
     self.var = self._requires(var)