Esempio n. 1
0
    def _shapeClassAndOther(self, opShape, operatorClass, other):
        """
        Determine the shape of the result, the base class of the result, and (if
        necessary) a modified form of `other` that is suitable for the
        operation.
        
        By default, returns the result of the generic
        `Variable._shapeClassAndOther()`, but if that fails, and if each
        dimension of `other` is exactly the `Mesh` dimension, do what the user
        probably "meant" and project `other` onto the `Mesh`.
        
        >>> from fipy import *
        >>> mesh = Grid1D(nx=5)
        >>> A = numerix.arange(5)
        >>> B = Variable(1.)
        >>> import warnings
        >>> savedFilters = list(warnings.filters)
        >>> warnings.resetwarnings()
        >>> warnings.simplefilter("error", UserWarning, append=True)
        >>> C = CellVariable(mesh=mesh) * (A * B)
        Traceback (most recent call last):
          ...
        UserWarning: The expression `(multiply([0 1 2 3 4], Variable(value=array(1.0))))` has been cast to a constant `CellVariable`
        >>> warnings.filters = savedFilters
        """
        otherShape = numerix.getShape(other)
        if (not isinstance(other, _MeshVariable) and otherShape is not ()
                and otherShape[-1] == self._globalNumberOfElements):
            if (isinstance(other, Variable)
                    and len(other.requiredVariables) > 0):
                import warnings
                warnings.warn(
                    "The expression `%s` has been cast to a constant `%s`" %
                    (repr(other), self._variableClass.__name__),
                    UserWarning,
                    stacklevel=4)
            other = self._variableClass(value=other, mesh=self.mesh)

        newOpShape, baseClass, newOther = Variable._shapeClassAndOther(
            self, opShape, operatorClass, other)

        if ((newOpShape is None or baseClass is None) and numerix.alltrue(
                numerix.array(numerix.getShape(other)) == self.mesh.dim)):
            newOpShape, baseClass, newOther = Variable._shapeClassAndOther(
                self, opShape, operatorClass, other[..., numerix.newaxis])

        return (newOpShape, baseClass, newOther)
Esempio n. 2
0
    def _shapeClassAndOther(self, opShape, operatorClass, other):
        """
        Determine the shape of the result, the base class of the result, and (if
        necessary) a modified form of `other` that is suitable for the
        operation.
        
        By default, returns the result of the generic
        `Variable._shapeClassAndOther()`, but if that fails, and if each
        dimension of `other` is exactly the `Mesh` dimension, do what the user
        probably "meant" and project `other` onto the `Mesh`.
        
        >>> from fipy import *
        >>> mesh = Grid1D(nx=5)
        >>> A = numerix.arange(5)
        >>> B = Variable(1.)
        >>> import warnings
        >>> savedFilters = list(warnings.filters)
        >>> warnings.resetwarnings()
        >>> warnings.simplefilter("error", UserWarning, append=True)
        >>> C = CellVariable(mesh=mesh) * (A * B)
        Traceback (most recent call last):
          ...
        UserWarning: The expression `(multiply([0 1 2 3 4], Variable(value=array(1.0))))` has been cast to a constant `CellVariable`
        >>> warnings.filters = savedFilters
        """
        otherShape = numerix.getShape(other)
        if (not isinstance(other, _MeshVariable) 
            and otherShape is not () 
            and otherShape[-1] == self._globalNumberOfElements):
            if (isinstance(other, Variable) and len(other.requiredVariables) > 0):
                import warnings
                warnings.warn("The expression `%s` has been cast to a constant `%s`" 
                              % (repr(other), self._variableClass.__name__), 
                              UserWarning, stacklevel=4)
            other = self._variableClass(value=other, mesh=self.mesh)

        newOpShape, baseClass, newOther = Variable._shapeClassAndOther(self, opShape, operatorClass, other)
        
        if ((newOpShape is None or baseClass is None)
            and numerix.alltrue(numerix.array(numerix.getShape(other)) == self.mesh.dim)):
                newOpShape, baseClass, newOther = Variable._shapeClassAndOther(self, opShape, operatorClass, other[..., numerix.newaxis])

        return (newOpShape, baseClass, newOther)
Esempio n. 3
0
    def _shapeClassAndOther(self, opShape, operatorClass, other):
        """
        Determine the shape of the result, the base class of the result, and (if
        necessary) a modified form of `other` that is suitable for the
        operation.
        
        By default, returns the result of the generic
        `Variable._shapeClassAndOther()`, but if that fails, and if each
        dimension of `other` is exactly the `Mesh` dimension, do what the user
        probably "meant" and project `other` onto the `Mesh`.
        """
        otherShape = numerix.getShape(other)
        if (not isinstance(other, _MeshVariable) 
            and otherShape is not () 
            and otherShape[-1] == self._getGlobalNumberOfElements()):
            other = self._getVariableClass()(value=other, mesh=self.getMesh())

        newOpShape, baseClass, newOther = Variable._shapeClassAndOther(self, opShape, operatorClass, other)
        
        if ((newOpShape is None or baseClass is None)
            and numerix.alltrue(numerix.array(numerix.getShape(other)) == self.getMesh().getDim())):
                newOpShape, baseClass, newOther = Variable._shapeClassAndOther(self, opShape, operatorClass, other[..., numerix.newaxis])

        return (newOpShape, baseClass, newOther)
Esempio n. 4
0
File: mesh.py Progetto: regmi/fipy
    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.numMesh.grid2D import Grid2D
           >>> mesh = Grid2D(nx = 2, ny = 2, dx = 1., dy = 1.)

           >>> from fipy.tools import parallel
           >>> print parallel.procID != 0 or (mesh._getCellFaceIDs() == [[0, 1, 2, 3],
           ...                                                           [7, 8, 10, 11],
           ...                                                           [2, 3, 4, 5],
           ...                                                           [6, 7, 9, 10]]).flatten().all()
           True

           >>> mesh._connectFaces(numerix.nonzero(mesh.getFacesLeft()), numerix.nonzero(mesh.getFacesRight()))

           >>> print parallel.procID != 0 or (mesh._getCellFaceIDs() == [[0, 1, 2, 3],
           ...                                                           [7, 6, 10, 9],
           ...                                                           [2, 3, 4, 5],
           ...                                                           [6, 7, 9, 10]]).flatten().all()
           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.getExteriorFaces() == self.getExteriorFaces()).all()

        ## following assert checks number of faces are equal, normals are opposite and areas are the same
        assert numerix.alltrue(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.getDim()):
            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
            tmp = self.cellFaceIDs[i]
            numerix.put(tmp, faceCellIDs, cellFaceIDs[i])
            self.cellFaceIDs[i] = tmp

        ## calculate new topology
        _CommonMesh._calcTopology(self)

        ## calculate new geometry
        self._calcFaceToCellDistanceRatio()
        self._calcCellToCellDistances()
        self._calcScaledGeometry()
        self._calcFaceAspectRatios()