Пример #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 __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
Пример #4
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
Пример #5
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)
Пример #6
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
Пример #7
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
Пример #8
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
Пример #9
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)
Пример #10
0
 def faceCenters(self):
     from fipy.variables.faceVariable import FaceVariable
     return FaceVariable(mesh=self, value=self._faceCenters,
                         rank=1)
Пример #11
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']
Пример #12
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')
Пример #13
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