Пример #1
0
    def _buildMatrixPy(self, L, oldArray, b, dt, coeffVectors):
        N = len(oldArray)

        b += numerix.array(oldArray) * numerix.array(coeffVectors['old value']) / dt
        b += numerix.ones([N]) * numerix.array(coeffVectors['b vector'])
        L.addAtDiagonal(numerix.ones([N]) * numerix.array(coeffVectors['new value']) / dt)
        L.addAtDiagonal(numerix.ones([N]) * numerix.array(coeffVectors['diagonal']))
Пример #2
0
 def _cellAreas(self):
     areas = numerix.ones((4, self.numberOfCells), 'd')
     areas[0] = self.dx
     areas[1] = self.dy
     areas[2] = self.dx
     areas[3] = self.dy
     return areas
Пример #3
0
Файл: mesh.py Проект: regmi/fipy
 def _getNumberOfFacesPerCell(self):
     cellFaceIDs = self._getCellFaceIDs()
     if type(cellFaceIDs) is type(MA.array(0)):
         ## bug in count returns float values when there is no mask
         return numerix.array(cellFaceIDs.count(axis=0), 'l')
     else:
         return self._getMaxFacesPerCell() * numerix.ones(cellFaceIDs.shape[-1], 'l')
Пример #4
0
 def _getFaceNormals(self):
     faceNormals = numerix.ones((1, self.numberOfFaces), "d")
     # The left-most face has neighboring cells None and the left-most cell.
     # We must reverse the normal to make fluxes work correctly.
     if self.numberOfFaces > 0:
         faceNormals[..., 0] *= -1
     return faceNormals
Пример #5
0
 def _getCellDistances(self):
     distances = numerix.ones(self.numberOfFaces, "d")
     distances *= self.dx
     if len(distances) > 0:
         distances[0] = self.dx / 2.0
         distances[-1] = self.dx / 2.0
     return distances
 def _cellAreas(self):
     areas = numerix.ones((4, self.numberOfCells), 'd')
     areas[0] = self.dx * self._cellCenters[0]
     areas[1] = self.dy * (self._cellCenters[0] + self.dx / 2)
     areas[2] = self.dx * self._cellCenters[0]
     areas[3] = self.dy * (self._cellCenters[0] - self.dx / 2)
     return areas
Пример #7
0
 def __rmul__(self, other):
     if type(numerix.ones(1)) == type(other):
         y = other.copy()
         self.matrix.matvec_transp(other, y)
         return y
     else:
         return self * other
Пример #8
0
 def _cellAreas(self):
     areas = numerix.ones((4, self.numberOfCells), 'd')
     areas[0] = self.dx * self._cellCenters[0]
     areas[1] = self.dy * (self._cellCenters[0] + self.dx / 2)
     areas[2] = self.dx * self._cellCenters[0]
     areas[3] = self.dy * (self._cellCenters[0] - self.dx / 2)
     return areas
Пример #9
0
 def __rmul__(self, other):
     if isinstance(numerix.ones(1, 'l'), type(other)):
         y = other.copy()
         self.matrix.matvec_transp(other, y)
         return y
     else:
         return self * other
Пример #10
0
 def _cellAreas(self):
     areas = numerix.ones((4, self.numberOfCells), 'd')
     areas[0] = self.dx
     areas[1] = self.dy
     areas[2] = self.dx
     areas[3] = self.dy
     return areas
Пример #11
0
 def _calcFaceNormals(self):
     faceNormals = numerix.array((numerix.ones(self.numberOfFaces, 'd'), ))
     # The left-most face has neighboring cells None and the left-most cell.
     # We must reverse the normal to make fluxes work correctly.
     if self.numberOfFaces > 0:
         faceNormals[..., 0] = -faceNormals[..., 0]
     return faceNormals
Пример #12
0
 def _numberOfFacesPerCell(self):
     cellFaceIDs = self.cellFaceIDs
     if isinstance(cellFaceIDs, type(MA.array(0))):
         ## bug in count returns float values when there is no mask
         return numerix.array(cellFaceIDs.count(axis=0), 'l')
     else:
         return self._maxFacesPerCell * numerix.ones(cellFaceIDs.shape[-1], 'l')
Пример #13
0
    def quiver(self, sparsity=None, scale=None):
        var = self.vars[0]
        mesh = var.mesh

        if isinstance(var, FaceVariable):
            N = mesh.numberOfFaces 
            X, Y = mesh.faceCenters

        elif isinstance(var, CellVariable):
            N = mesh.numberOfCells 
            X, Y = mesh.cellCenters
            
        if sparsity is not None and N > sparsity:
            XYrand = numerix.random.random((2, sparsity))
            XYrand = numerix.array([[min(X)], 
                                    [min(Y)]]) + XYrand * numerix.array([[max(X) - min(X)],
                                                                         [max(Y) - min(Y)]])
            self.indices = numerix.nearest(numerix.array([X, Y]), XYrand)
        else:
            self.indices = numerix.arange(N)

        X = numerix.take(X, self.indices)
        Y = numerix.take(Y, self.indices)
        
        U = V = numerix.ones(X.shape, 'l')
        
        if hasattr(self, "_quiver"):
            self._quiver.remove()
        
        self._quiver = self.axes.quiver(X, Y, U, V, scale=scale, pivot='middle')
Пример #14
0
    def quiver(self, sparsity=None, scale=None):
        var = self.vars[0]
        mesh = var.mesh

        if isinstance(var, FaceVariable):
            N = mesh.numberOfFaces
            X, Y = mesh.faceCenters

        elif isinstance(var, CellVariable):
            N = mesh.numberOfCells
            X, Y = mesh.cellCenters

        if sparsity is not None and N > sparsity:
            XYrand = numerix.random.random((2, sparsity))
            XYrand = numerix.array([
                [min(X)], [min(Y)]
            ]) + XYrand * numerix.array([[max(X) - min(X)], [max(Y) - min(Y)]])
            self.indices = numerix.nearest(numerix.array([X, Y]), XYrand)
        else:
            self.indices = numerix.arange(N)

        X = numerix.take(X, self.indices)
        Y = numerix.take(Y, self.indices)

        U = V = numerix.ones(X.shape, 'l')

        if hasattr(self, "_quiver"):
            self._quiver.remove()

        self._quiver = self.axes.quiver(X,
                                        Y,
                                        U,
                                        V,
                                        scale=scale,
                                        pivot='middle')
Пример #15
0
 def _cellDistances(self):
     distances = numerix.ones(self.numberOfFaces, 'd')
     distances *= self.dx
     if len(distances) > 0:
         distances[0] = self.dx / 2.
         distances[-1] = self.dx / 2.
     return distances
Пример #16
0
    def _calcValue(self):
        ids = self.mesh.cellFaceIDs
        contributions = numerix.take(self.faceVariable, ids, axis=-1)
        s = (numerix.newaxis, ) * (len(contributions.shape) - 2) + (slice(
            0, None, None), ) + (slice(0, None, None), )

        faceContributions = contributions * self.mesh._cellToFaceOrientations[
            s]  #just changes sign

        temp = faceContributions.copy()
        maskedValues = np.vstack(
            ([not isinstance(xi, float) for xi in temp[0]
              ], [not isinstance(xi, float) for xi in temp[1]
                  ], [not isinstance(xi, float) for xi in temp[2]],
             [not isinstance(xi, float) for xi in temp[3]]))
        faceAreas = np.take(self.mesh._faceAreas, ids)
        faceAreas = MA.masked_where(maskedValues, faceAreas)
        if (len(temp) > 1):

            temp = temp * faceAreas
            temp[2] = numerix.MA.filled(temp[2], temp[0])
            temp[3] = numerix.MA.filled(temp[3], temp[1])

            faceAreas[2] = numerix.MA.filled(faceAreas[2], faceAreas[0])
            faceAreas[3] = numerix.MA.filled(faceAreas[3], faceAreas[1])
            faceAreas[0] = (faceAreas[0] + faceAreas[2])
            faceAreas[1] = (faceAreas[1] + faceAreas[3])

            temp[0] = (temp[0] + temp[2]) / faceAreas[0]
            temp[1] = (temp[1] + temp[3]) / faceAreas[1]
            temp = numerix.vstack(
                (numerix.array(temp[0]), numerix.array(temp[1])))

        return numerix.tensordot(numerix.ones(temp.shape[-2], 'd'), temp,
                                 (0, -2)) / self.mesh.cellVolumes
Пример #17
0
 def _getFaceToCellDistanceRatio(self):
     distances = numerix.ones(self.numberOfFaces, "d")
     distances *= 0.5
     if len(distances) > 0:
         distances[0] = 1
         distances[-1] = 1
     return distances
Пример #18
0
 def _cellToFaceOrientations(self):
     cellFaceOrientations = numerix.ones((4, self.numberOfCells), 'l')
     if self.numberOfCells > 0:
         cellFaceOrientations[0, self.nx:] = -1
         cellFaceOrientations[3, :] = -1
         cellFaceOrientations[3, ::self.nx] = 1
     return cellFaceOrientations
Пример #19
0
 def _cellToFaceOrientations(self):
     cellFaceOrientations = numerix.ones((4, self.numberOfCells), 'l')
     if self.numberOfCells > 0:
         cellFaceOrientations[0, self.nx:] = -1
         cellFaceOrientations[3,:] = -1
         cellFaceOrientations[3, ::self.nx] = 1
     return cellFaceOrientations
Пример #20
0
 def __rmul__(self, other):
     if isinstance(numerix.ones(1, 'l'), type(other)):
         y = other.copy()
         self.matrix.matvec_transp(other, y)
         return y
     else:
         return self * other
Пример #21
0
    def quiver(self, sparsity=None, scale=None):
        var = self.vars[0]
        mesh = var.getMesh()

        if isinstance(var, FaceVariable):
            N = mesh._getNumberOfFaces() 
            V = mesh._getFaceAreas()
            X, Y = mesh.getFaceCenters()
        elif isinstance(var, CellVariable):
            N = mesh.getNumberOfCells() 
            V = mesh.getCellVolumes()
            X, Y = mesh.getCellCenters()

        if sparsity is not None and N > sparsity:
            self.indices = numerix.random.rand(N) * V
            self.indices = self.indices.argsort()[-sparsity:]
        else:
            self.indices = numerix.arange(N)

        X = numerix.take(X, self.indices)
        Y = numerix.take(Y, self.indices)
        
        U = V = numerix.ones(X.shape)
        
        import pylab
        
        pylab.ion()
        pylab.cla()
        self._quiver = pylab.quiver(X, Y, U, V, scale=scale)
        pylab.ioff()
Пример #22
0
 def _calcFaceNormals(self):
     faceNormals = numerix.array((numerix.ones(self.numberOfFaces, 'd'),))
     # The left-most face has neighboring cells None and the left-most cell.
     # We must reverse the normal to make fluxes work correctly.
     if self.numberOfFaces > 0:
         faceNormals[...,0] = -faceNormals[...,0]
     return faceNormals
Пример #23
0
 def _numberOfFacesPerCell(self):
     cellFaceIDs = self.cellFaceIDs
     if isinstance(cellFaceIDs, type(MA.array(0))):
         ## bug in count returns float values when there is no mask
         return numerix.array(cellFaceIDs.count(axis=0), 'l')
     else:
         return self._maxFacesPerCell * numerix.ones(cellFaceIDs.shape[-1], 'l')
Пример #24
0
 def _cellDistances(self):
     distances = numerix.ones(self.numberOfFaces, 'd')
     distances *= self.dx
     if len(distances) > 0:
         distances[0] = self.dx / 2.
         distances[-1] = self.dx / 2.
     return distances
Пример #25
0
 def faceNormals(self):
     faceNormals = numerix.ones((1, self.numberOfFaces), 'd')
     # The left-most face has neighboring cells None and the left-most cell.
     # We must reverse the normal to make fluxes work correctly.
     if self.numberOfFaces > 0:
         faceNormals[..., 0] *= -1
     return faceNormals
Пример #26
0
 def __rmul__(self, other):
     if type(numerix.ones(1)) == type(other):
         y = Epetra.Vector(other)
         result = Epetra.Vector(self.nonOverlappingMap)
         self._getMatrix().Multiply(True, y, result)
         return _trilinosToNumpyVector(result)
     else:
         return self * other
Пример #27
0
 def __rmul__(self, other):
     if type(numerix.ones(1)) == type(other):
         y = Epetra.Vector(other)
         result = Epetra.Vector(self.nonOverlappingMap)
         self._getMatrix().Multiply(True, y, result)
         return _trilinosToNumpyVector(result)
     else:
         return self * other
Пример #28
0
 def _cellAreas(self):
     areas = numerix.ones((6, self.numberOfCells), 'd')
     areas[0] = self.dy * self.dz
     areas[1] = self.dy * self.dz
     areas[2] = self.dx * self.dz
     areas[3] = self.dx * self.dz
     areas[4] = self.dx * self.dy
     areas[5] = self.dx * self.dy
     return areas
Пример #29
0
 def _cellAreas(self):
     areas = numerix.ones((6, self.numberOfCells), 'd')
     areas[0] = self.dy * self.dz
     areas[1] = self.dy * self.dz
     areas[2] = self.dx * self.dz
     areas[3] = self.dx * self.dz
     areas[4] = self.dx * self.dy
     areas[5] = self.dx * self.dy
     return areas
Пример #30
0
    def __rmul__(self, other):
        if isinstance(numerix.ones(1, 'l'), type(other)):
            self.fillComplete()

            y = Epetra.Vector(self.rangeMap, other)
            result = Epetra.Vector(self.domainMap)
            self.matrix.Multiply(True, y, result)
            return numerix.array(result)
        else:
            return self * other
Пример #31
0
 def __rmul__(self, other):
     if type(numerix.ones(1, 'l')) == type(other):
         N = self._shape[1]
         x = PETSc.Vec().createMPI(N, comm=self.matrix.comm)
         y = x.duplicate()
         x[:] = other
         self.matrix.multTranspose(x, y)
         return numerix.asarray(y)
     else:
         return self * other
Пример #32
0
    def __init__(self, size):
        """Create a sparse matrix with '1' in the diagonal

            >>> print(_PysparseIdentityMatrix(size=3))
             1.000000      ---        ---    
                ---     1.000000      ---    
                ---        ---     1.000000  
        """
        _PysparseMatrixFromShape.__init__(self, rows=size, cols=size, bandwidth = 1)
        ids = numerix.arange(size)
        self.put(numerix.ones(size, 'd'), ids, ids)
Пример #33
0
    def __init__(self, size):
        """Create a sparse matrix with `1` in the diagonal

            >>> print(_PysparseIdentityMatrix(size=3))
             1.000000      ---        ---    
                ---     1.000000      ---    
                ---        ---     1.000000  
        """
        _PysparseMatrixFromShape.__init__(self, rows=size, cols=size, bandwidth=1)
        ids = numerix.arange(size)
        self.put(numerix.ones(size, 'd'), ids, ids)
Пример #34
0
 def __init__(self, size):
     """
     Create a sparse matrix with '1' in the diagonal
     
         >>> print _TrilinosIdentityMatrix(size=3)
          1.000000      ---        ---    
             ---     1.000000      ---    
             ---        ---     1.000000  
     """
     _TrilinosMatrix.__init__(self, size=size, bandwidth=1)
     ids = numerix.arange(size)
     self.addAt(numerix.ones(size), ids, ids)
Пример #35
0
 def __init__(self, size):
     """
     Create a sparse matrix with '1' in the diagonal
     
         >>> print _ScipyIdentityMatrix(size=3)
          1.000000      ---        ---    
             ---     1.000000      ---    
             ---        ---     1.000000  
     """
     _ScipyMatrixFromShape.__init__(self, size=size, bandwidth=1)
     ids = numerix.arange(size)
     self.put(numerix.ones(size, 'd'), ids, ids)
Пример #36
0
 def __init__(self, size):
     """
     Create a sparse matrix with '1' in the diagonal
     
         >>> print _PysparseIdentityMatrix(size=3)
          1.000000      ---        ---    
             ---     1.000000      ---    
             ---        ---     1.000000  
     """
     _PysparseMatrix.__init__(self, size=size, bandwidth=1)
     ids = numerix.arange(size)
     self.put(numerix.ones(size, "d"), ids, ids)
Пример #37
0
 def _faceToCellDistanceRatio(self):
     """how far face is from first to second cell
     
     distance from center of face to center of first cell divided by distance
     between cell centers
     """
     distances = numerix.ones(self.numberOfFaces, 'd')
     distances *= 0.5
     if len(distances) > 0:
         distances[0] = 1
         distances[-1] = 1
     return distances
Пример #38
0
    def _calcValueNoInline(self):
        ids = self.mesh.cellFaceIDs

        contributions = numerix.take(self.faceVariable, ids, axis=-1)

        # FIXME: numerix.MA.filled casts away dimensions
        s = (numerix.newaxis,) * (len(contributions.shape) - 2) + (slice(0,None,None),) + (slice(0,None,None),)

        faceContributions = contributions * self.mesh._cellToFaceOrientations[s]
        
        return numerix.tensordot(numerix.ones(faceContributions.shape[-2], 'd'),
                                 numerix.MA.filled(faceContributions, 0.), (0, -2)) / self.mesh.cellVolumes
Пример #39
0
    def __init__(self, size):
        """
        Create a sparse matrix with '1' in the diagonal

            >>> print _TrilinosIdentityMatrix(size=3)
             1.000000      ---        ---
                ---     1.000000      ---
                ---        ---     1.000000
        """
        _TrilinosMatrix.__init__(self, size=size, bandwidth=1)
        ids = numerix.arange(size)
        self.addAt(numerix.ones(size), ids, ids)
Пример #40
0
Файл: mesh.py Проект: regmi/fipy
 def _calcInteriorAndExteriorCellIDs(self):
     try:
         import sets
         self.exteriorCellIDs = sets.Set(self.faceCellIDs[0, self.getExteriorFaces().getValue()])
         self.interiorCellIDs = list(sets.Set(range(self.numberOfCells)) - self.exteriorCellIDs)
         self.exteriorCellIDs = list(self.exteriorCellIDs)
     except:
         self.exteriorCellIDs = self.faceCellIDs[0, self.getExteriorFaces().getValue()]
         tmp = numerix.zeros(self.numberOfCells)
         numerix.put(tmp, self.exteriorCellIDs, numerix.ones(len(self.exteriorCellIDs)))
         self.exteriorCellIDs = numerix.nonzero(tmp)            
         self.interiorCellIDs = numerix.nonzero(numerix.logical_not(tmp))
Пример #41
0
 def _faceToCellDistanceRatio(self):
     """how far face is from first to second cell
     
     distance from center of face to center of first cell divided by distance
     between cell centers
     """
     distances = numerix.ones(self.numberOfFaces, 'd')
     distances *= 0.5
     if len(distances) > 0:
         distances[0] = 1
         distances[-1] = 1
     return distances
Пример #42
0
    def __init__(self, mesh):
        """
        Create a sparse matrix associated with a `Mesh` with `1` in the diagonal

            >>> from fipy import Grid1D
            >>> mesh = Grid1D(nx=3)
            >>> print(_TrilinosIdentityMeshMatrix(mesh=mesh))
             1.000000      ---        ---    
                ---     1.000000      ---    
                ---        ---     1.000000  
        """
        _TrilinosMeshMatrix.__init__(self, mesh=mesh, bandwidth=1)
        size = mesh.numberOfCells
        ids = numerix.arange(size)
        self.addAt(numerix.ones(size, 'l'), ids, ids)
    def _calcValueNoInline(self):
        ids = self.mesh.cellFaceIDs

        contributions = numerix.take(self.faceVariable, ids, axis=-1)

        # FIXME: numerix.MA.filled casts away dimensions
        s = (numerix.newaxis, ) * (len(contributions.shape) - 2) + (slice(
            0, None, None), ) + (slice(0, None, None), )

        faceContributions = contributions * self.mesh._cellToFaceOrientations[s]

        return numerix.tensordot(
            numerix.ones(faceContributions.shape[-2], 'd'),
            numerix.MA.filled(faceContributions, 0.),
            (0, -2)) / self.mesh.cellVolumes
Пример #44
0
 def _calcInteriorAndExteriorCellIDs(self):
     try:
         import sys
         if sys.version_info < (2, 6):
             from sets import Set as set
         exteriorCellIDs = set(self.faceCellIDs[0, self._exteriorFaces.value])
         interiorCellIDs = list(set(range(self.numberOfCells)) - self._exteriorCellIDs)
         exteriorCellIDs = list(self._exteriorCellIDs)
     except:
         exteriorCellIDs = self.faceCellIDs[0, self._exteriorFaces.value]
         tmp = numerix.zeros(self.numberOfCells, 'l')
         numerix.put(tmp, exteriorCellIDs, numerix.ones(len(exteriorCellIDs), 'l'))
         exteriorCellIDs = numerix.nonzero(tmp)            
         interiorCellIDs = numerix.nonzero(numerix.logical_not(tmp))
     return interiorCellIDs, exteriorCellIDs
Пример #45
0
 def __init__(self, mesh):
     """
     Create a sparse matrix associated with a `Mesh` with '1' in the diagonal
     
         >>> from fipy import Grid1D
         >>> mesh = Grid1D(nx=3)
         >>> print _TrilinosIdentityMeshMatrix(mesh=mesh)
          1.000000      ---        ---    
             ---     1.000000      ---    
             ---        ---     1.000000  
     """
     _TrilinosMeshMatrix.__init__(self, mesh=mesh, bandwidth=1)
     size = mesh.getNumberOfCells()
     ids = numerix.arange(size)
     self.addAt(numerix.ones(size), ids, ids)
Пример #46
0
    def __mul__(self, other):
        """
        Multiply a sparse matrix by another sparse matrix

            >>> L1 = _PysparseMatrixFromShape(rows=3, cols=3)
            >>> L1.put([3.,10.,numerix.pi,2.5], [0,0,1,2], [2,1,1,0])
            >>> L2 = _PysparseIdentityMatrix(size=3)
            >>> L2.put([4.38,12357.2,1.1], [2,1,0], [1,0,2])

            >>> tmp = numerix.array(((1.23572000e+05, 2.31400000e+01, 3.00000000e+00),
            ...                      (3.88212887e+04, 3.14159265e+00, 0.00000000e+00),
            ...                      (2.50000000e+00, 0.00000000e+00, 2.75000000e+00)))

            >>> numerix.allclose((L1 * L2).numpyArray, tmp)
            1

        or a sparse matrix by a vector

            >>> tmp = numerix.array((29., 6.28318531, 2.5))
            >>> numerix.allclose(L1 * numerix.array((1,2,3),'d'), tmp)
            1

        or a vector by a sparse matrix

            >>> tmp = numerix.array((7.5, 16.28318531,  3.))
            >>> numerix.allclose(numerix.array((1,2,3),'d') * L1, tmp) ## The multiplication is broken. Numpy is calling __rmul__ for every element instead of with  the whole array.
            1


        """
        N = self.matrix.shape[1]

        if isinstance(other, _PysparseMatrix):
            return _PysparseMatrix(
                matrix=spmatrix.matrixmultiply(self.matrix, other.matrix))
        else:
            shape = numerix.shape(other)
            if shape == ():
                L = spmatrix.ll_mat(N, N, N)
                L.put(other * numerix.ones(N, 'l'))
                return _PysparseMatrix(
                    matrix=spmatrix.matrixmultiply(self.matrix, L))
            elif shape == (N, ):
                y = numerix.empty((self.matrix.shape[0], ))
                self.matrix.matvec(other, y)
                return y
            else:
                raise TypeError
Пример #47
0
    def _getStencil_(self,
                     id1,
                     id2,
                     globalOverlappihgIDs,
                     globalNonOverlappihgIDs,
                     overlapping=False):
        id1 = globalOverlappihgIDs[id1]

        if overlapping:
            mask = numerix.ones(id1.shape, dtype=bool)
        else:
            mask = numerix.in1d(id1, globalNonOverlappihgIDs)

        id1 = self.matrix()._mesh2matrix(id1[mask])
        id2 = numerix.asarray(id2)[mask]

        return id1, id2, mask
Пример #48
0
    def __mul__(self, other):
        """
        Multiply a sparse matrix by another sparse matrix
        
            >>> L1 = _PysparseMatrix(size = 3)
            >>> L1.put([3.,10.,numerix.pi,2.5], [0,0,1,2], [2,1,1,0])
            >>> L2 = _PysparseIdentityMatrix(size = 3)
            >>> L2.put([4.38,12357.2,1.1], [2,1,0], [1,0,2])
            
            >>> tmp = numerix.array(((1.23572000e+05, 2.31400000e+01, 3.00000000e+00),
            ...                      (3.88212887e+04, 3.14159265e+00, 0.00000000e+00),
            ...                      (2.50000000e+00, 0.00000000e+00, 2.75000000e+00)))

            >>> numerix.allclose((L1 * L2).getNumpyArray(), tmp)
            1

        or a sparse matrix by a vector

            >>> tmp = numerix.array((29., 6.28318531, 2.5))       
            >>> numerix.allclose(L1 * numerix.array((1,2,3),'d'), tmp)
            1
            
        or a vector by a sparse matrix

            >>> tmp = numerix.array((7.5, 16.28318531,  3.))  
            >>> numerix.allclose(numerix.array((1,2,3),'d') * L1, tmp) ## The multiplication is broken. Numpy is calling __rmul__ for every element instead of with  the whole array.
            1

            
        """
        N = self.matrix.shape[0]

        if isinstance(other, _PysparseMatrix):
            return _PysparseMatrix(matrix = spmatrix.matrixmultiply(self.matrix, other._getMatrix()))
        else:
            shape = numerix.shape(other)
            if shape == ():
                L = spmatrix.ll_mat(N, N, N)
                L.put(other * numerix.ones(N))
                return _PysparseMatrix(matrix = spmatrix.matrixmultiply(self.matrix, L))
            elif shape == (N,):
                y = other.copy()
                self.matrix.matvec(other, y)
                return y
            else:
                raise TypeError
Пример #49
0
    def _calcBaseFaceVertexIDs(self):
        
        cellVertexIDs = self.cellVertexIDs
    ## compute the face vertex IDs.
        ### this assumes triangular grid
        #cellFaceVertexIDs = numerix.ones((self.dimensions, self.dimensions + 1, self.numCells))
        cellFaceVertexIDs = numerix.ones((self.dimensions,len(cellVertexIDs), self.numCells))
        cellFaceVertexIDs = -1 * cellFaceVertexIDs

        if (self.dimensions == 3):
            cellFaceVertexIDs[:, 0, :] = cellVertexIDs[:3]
            cellFaceVertexIDs[:, 1, :] = numerix.concatenate((cellVertexIDs[:2], cellVertexIDs[3:]), axis = 0)
            cellFaceVertexIDs[:, 2, :] = numerix.concatenate((cellVertexIDs[:1], cellVertexIDs[2:]), axis = 0)
            cellFaceVertexIDs[:, 3, :] = cellVertexIDs[1:]
        elif (self.dimensions == 2):#define face with vertex pairs
            ###This isn't very general.
            ###Would be nice to allow cells with different number of faces. 
            if len(cellVertexIDs)==3:
                cellFaceVertexIDs[:, 0, :] = cellVertexIDs[:2]
                cellFaceVertexIDs[:, 1, :] = numerix.concatenate((cellVertexIDs[2:], cellVertexIDs[:1]), axis = 0)
                cellFaceVertexIDs[:, 2, :] = cellVertexIDs[1:]
            elif len(cellVertexIDs)==4:
                cellFaceVertexIDs[:, 0, :] = cellVertexIDs[0:2]
                cellFaceVertexIDs[:, 1, :] = cellVertexIDs[1:3]
                cellFaceVertexIDs[:, 2, :] = cellVertexIDs[2:4]
                cellFaceVertexIDs[:, 3, :] = numerix.concatenate((cellVertexIDs[3:], cellVertexIDs[:1]), axis = 0)

        cellFaceVertexIDs = cellFaceVertexIDs[::-1]#reverses order of vertex pair

        #self.unsortedBaseIDs = numerix.reshape(cellFaceVertexIDs.swapaxes(1,2), 
        #                                       (self.dimensions, 
        #                                        self.numCells * (self.dimensions + 1)))
        
        self.unsortedBaseIDs = numerix.reshape(cellFaceVertexIDs.swapaxes(1,2), 
                                               (self.dimensions, 
                                                self.numCells * (len(cellVertexIDs))))
        cellFaceVertexIDs = numerix.sort(cellFaceVertexIDs, axis=0)
        baseFaceVertexIDs = numerix.reshape(cellFaceVertexIDs.swapaxes(1,2), 
                                            (self.dimensions, 
                                             self.numCells * (len(cellVertexIDs))))

        self.baseFaceVertexIDs = baseFaceVertexIDs       
        self.cellFaceVertexIDs = cellFaceVertexIDs
Пример #50
0
Файл: mesh.py Проект: regmi/fipy
    def _getAddedMeshValues(self, other, smallNumber):
        """
        Returns a `dictionary` with 3 elements: the new mesh vertexCoords, faceVertexIDs, and cellFaceIDs.
        """

        other = other._getConcatenableMesh()

        selfNumFaces = self.faceVertexIDs.shape[-1]
        selfNumVertices = self.vertexCoords.shape[-1]
        otherNumFaces = other.faceVertexIDs.shape[-1]
        otherNumVertices = other.vertexCoords.shape[-1]
        ## check dimensions
        if(self.vertexCoords.shape[0] != other.vertexCoords.shape[0]):
            raise MeshAdditionError, "Dimensions do not match"
        ## compute vertex correlates
        vertexCorrelates = {}
        for i in range(selfNumVertices):
            for j in range(otherNumVertices):
                diff = self.vertexCoords[...,i] - other.vertexCoords[...,j]
                diff = numerix.array(diff)
                if (sum(diff ** 2) < smallNumber):
                    vertexCorrelates[j] = i
        if (self._getNumberOfVertices() > 0 and other._getNumberOfVertices() > 0 and vertexCorrelates == {}):
            raise MeshAdditionError, "Vertices are not aligned"

        
         
        ## compute face correlates
        faceCorrelates = {}
        for i in range(otherNumFaces):
##          Seems to be overwriting other.faceVertexIDs with new numpy
##            currFace = other.faceVertexIDs[i]
##            currFace = other.faceVertexIDs[...,i].copy()
##          Changed this again as numpy 1.0.4 seems to have no copy method for
##          masked arrays.
            try:
                currFace = other.faceVertexIDs[...,i].copy()
            except:
                currFace = MA.array(other.faceVertexIDs[...,i], mask=MA.getmask(other.faceVertexIDs[...,i]))

            keepGoing = 1
            currIndex = 0 
            for item in currFace:
                if(vertexCorrelates.has_key(item)):
                    currFace[currIndex] = vertexCorrelates[item]
                    currIndex = currIndex + 1
                else:
                    keepGoing = 0
            if(keepGoing == 1):
                for j in range(selfNumFaces):
                    if (self._equalExceptOrder(currFace, self.faceVertexIDs[...,j])):
                        faceCorrelates[i] = j
        if (self._getNumberOfFaces() > 0 and other._getNumberOfFaces() > 0 and faceCorrelates == {}):
            raise MeshAdditionError, "Faces are not aligned"
        
        faceIndicesToAdd = ()
        for i in range(otherNumFaces):
            if(not faceCorrelates.has_key(i)):
                faceIndicesToAdd = faceIndicesToAdd + (i,)
        vertexIndicesToAdd = ()
        for i in range(otherNumVertices):
            if(not vertexCorrelates.has_key(i)):
                vertexIndicesToAdd = vertexIndicesToAdd + (i,)

        ##compute the full face and vertex correlation list
        a = selfNumFaces
        for i in faceIndicesToAdd:
            faceCorrelates[i] = a
            a = a + 1
        b = selfNumVertices
        for i in vertexIndicesToAdd:
            vertexCorrelates[i] = b
            b = b + 1

        ## compute what the cells are that we need to add
        cellsToAdd = numerix.ones((self.cellFaceIDs.shape[0], other.cellFaceIDs.shape[-1]))
        cellsToAdd = -1 * cellsToAdd

        for j in range(other.cellFaceIDs.shape[-1]):
            for i in range(other.cellFaceIDs.shape[0]):
                cellsToAdd[i, j] = faceCorrelates[other.cellFaceIDs[i, j]]

        cellsToAdd = MA.masked_values(cellsToAdd, -1)


        ## compute what the faces are that we need to add
        facesToAdd = numerix.take(other.faceVertexIDs, faceIndicesToAdd, axis=1)

        for j in range(facesToAdd.shape[-1]):
            for i in range(facesToAdd.shape[0]):
                facesToAdd[i, j] = vertexCorrelates[facesToAdd[i, j]]

        ## compute what the vertices are that we need to add
        verticesToAdd = numerix.take(other.vertexCoords, vertexIndicesToAdd, axis=1)

        return {
            'vertexCoords': numerix.concatenate((self.vertexCoords, verticesToAdd), axis=1), 
            'faceVertexIDs': numerix.concatenate((self.faceVertexIDs, facesToAdd), axis=1), 
            'cellFaceIDs': MA.concatenate((self.cellFaceIDs, cellsToAdd), axis=1)
            }
Пример #51
0
 def _calcFaceAreas(self):
     return numerix.ones(self.numberOfFaces, 'd')
Пример #52
0
 def _cellToFaceOrientations(self):
     orientations = numerix.ones((2, self.numberOfCells), 'l')
     if self.numberOfCells > 0:
         orientations[0] *= -1
         orientations[0, 0] = 1
     return orientations
 def _cellVolumes(self):
     return numerix.ones(self.numberOfCells, 'd') * self.dx * self.dy
Пример #54
0
    def _extrude(self, mesh, extrudeFunc, layers):
        ## should extrude self rather than creating a new mesh?

        ## the following allows the 2D mesh to be in 3D space, this can be the case for a
        ## Gmsh2DIn3DSpace which would then be extruded.
        oldVertices = mesh.vertexCoords
        if oldVertices.shape[0] == 2:
            oldVertices = numerix.resize(oldVertices, (3, len(oldVertices[0])))
            oldVertices[2] = 0

        NCells = mesh.numberOfCells
        NFac = mesh.numberOfFaces
        NFacPerCell =  mesh._maxFacesPerCell

        ## set up the initial data arrays
        new_shape = (max(NFacPerCell, 4), (1 + layers)*NCells + layers*NFac)
        faces = numerix.MA.masked_values(-numerix.ones(new_shape, 'l'), value = -1)
        orderedVertices = mesh._orderedCellVertexIDs
        faces[:NFacPerCell, :NCells] = orderedVertices
        vertices = oldVertices
        vert0 = mesh.faceVertexIDs
        faceCount = NCells

        for layer in range(layers):

            ## need this later
            initialFaceCount = faceCount

            ## build the vertices
            newVertices = extrudeFunc(oldVertices)
            vertices = numerix.concatenate((vertices, newVertices), axis=1)

            ## build the faces along the layers
            faces[:NFacPerCell, faceCount: faceCount + NCells] = orderedVertices + len(oldVertices[0]) * (layer + 1)
            try:
                # numpy 1.1 doesn't copy right side before assigning slice
                # See: http://www.mail-archive.com/[email protected]/msg09843.html
                faces[:NFacPerCell, faceCount: faceCount + NCells] = faces[:NFacPerCell, faceCount: faceCount + NCells][::-1,:].copy()
            except:
                faces[:NFacPerCell, faceCount: faceCount + NCells] = faces[:NFacPerCell, faceCount: faceCount + NCells][::-1,:]

            faceCount = faceCount + NCells

            vert1 = (vert0 + len(oldVertices[0]))[::-1,:]

            ## build the faces between the layers
            faces[:4, faceCount: faceCount + NFac] = numerix.concatenate((vert0, vert1), axis = 0)[::-1,:]

            vert0 = vert0 + len(oldVertices[0])

            NCells = mesh.numberOfCells


            ## build the cells, the first layer has slightly different ordering
            if layer == 0:
                c0 =  numerix.reshape(numerix.arange(NCells), (1, NCells))
                cells = numerix.concatenate((c0, c0 + NCells, mesh.cellFaceIDs + 2 * NCells), axis = 0)
            else:
                newCells = numerix.concatenate((c0, c0 + initialFaceCount, mesh.cellFaceIDs + faceCount), axis=0)
                newCells[0] = cells[1, -NCells:]
                cells = numerix.concatenate((cells, newCells), axis=1)

            ## keep a count of things for the next layer
            faceCount = faceCount + NFac
            oldVertices = newVertices

        ## return a new mesh, extrude could just as easily act on self
        return Mesh(vertices, faces, cells, communicator=mesh.communicator)
Пример #55
0
    def _getAddedMeshValues(self, other, resolution=1e-2):
        """Calculate the parameters to define a concatenation of `other` with `self`

        Parameters
        ----------
        other : ~fipy.meshes.mesh.Mesh
             The `Mesh` to concatenate with `self`
        resolution : float
            How close vertices have to be (relative to the smallest
            cell-to-cell distance in either mesh) to be considered the same

        Returns
        -------
        dict
            (`vertexCoords`, `faceVertexIDs`, `cellFaceIDs`) for the new mesh.
        """

        selfc = self._concatenableMesh
        otherc = other._concatenableMesh

        selfNumFaces = selfc.faceVertexIDs.shape[-1]
        selfNumVertices = selfc.vertexCoords.shape[-1]
        otherNumFaces = otherc.faceVertexIDs.shape[-1]
        otherNumVertices = otherc.vertexCoords.shape[-1]
        ## check dimensions
        if(selfc.vertexCoords.shape[0] != otherc.vertexCoords.shape[0]):
            raise MeshAdditionError("Dimensions do not match")

        ## compute vertex correlates

#         from fipy.tools.debug import PRINT
#         PRINT("selfNumFaces", selfNumFaces)
#         PRINT("otherNumFaces", otherNumVertices)
#         PRINT("selfNumVertices", selfNumVertices)
#         PRINT("otherNumVertices", otherNumVertices)
# 
#         from fipy.tools.debug import PRINT
#         from fipy.tools.debug import PRINT
#         PRINT("otherExt", otherc.exteriorFaces.value)
#         raw_input()
#         PRINT("selfExt", selfc.exteriorFaces.value)
# 
#         PRINT("self filled", selfc.faceVertexIDs.filled())
#         PRINT("othe filled", otherc.faceVertexIDs.filled())
#         raw_input()
# 
#         PRINT("selfc.faceVertexIDs.filled()\n",selfc.faceVertexIDs.filled())
#         PRINT("flat\n",selfc.faceVertexIDs.filled()[...,
#             selfc.exteriorFaces.value].flatten())
#         PRINT("selfc.exteriorFaces.value\n",selfc.exteriorFaces.value)
#         PRINT("extfaces type", type(selfc.exteriorFaces))
#         PRINT("extfaces mesh", selfc.exteriorFaces.mesh)

        ## only try to match along the operation manifold
        if hasattr(self, "opManifold"):
            self_faces = self.opManifold(selfc)
        else:
            self_faces = selfc.exteriorFaces.value
        if hasattr(other, "opManifold"):
            other_faces = other.opManifold(otherc)
        else:
            other_faces = otherc.exteriorFaces.value

        ## only try to match exterior (X) vertices
        self_Xvertices = numerix.unique(selfc.faceVertexIDs.filled()[...,
            self_faces].flatten())
        other_Xvertices = numerix.unique(otherc.faceVertexIDs.filled()[...,
            other_faces].flatten())

        self_XvertexCoords = selfc.vertexCoords[..., self_Xvertices]
        other_XvertexCoords = otherc.vertexCoords[..., other_Xvertices]

        closest = numerix.nearest(self_XvertexCoords, other_XvertexCoords)

        # 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._cellToCellDistances.min(),
                                            otherc._cellToCellDistances.min())
        vertexCorrelates = numerix.array((self_Xvertices[closest[close]],
                                          other_Xvertices[close]))

        # warn if meshes don't touch, but allow it
        if (selfc._numberOfVertices > 0
            and otherc._numberOfVertices > 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 = otherc.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:], 'l'),
                                                 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:], 'l'),
                                                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=numerix.INT_DTYPE)
        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.numberOfFaces > 0
            and otherc.numberOfFaces > 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=numerix.INT_DTYPE)
        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[otherc.faceVertexIDs[..., facesToAdd]]

        # ensure that both sets of cellFaceIDs have the same maximum number of (masked) elements
        self_cellFaceIDs = selfc.cellFaceIDs
        other_cellFaceIDs = face_map[otherc.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:], 'l'),
                                               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:], 'l'),
                                              axis=0)
            self_cellFaceIDs = MA.masked_values(self_cellFaceIDs, -1)

        # concatenate everything and return
        return {
            'vertexCoords': numerix.concatenate((selfc.vertexCoords,
                                                 otherc.vertexCoords[..., verticesToAdd]), axis=1),
            'faceVertexIDs': numerix.concatenate((self_faceVertexIDs,
                                                  other_faceVertexIDs), axis=1),
            'cellFaceIDs': MA.concatenate((self_cellFaceIDs,
                                           other_cellFaceIDs), axis=1)
            }
Пример #56
0
 def __rmul__(self, other):
     if isinstance(numerix.ones(1, 'l'), type(other)):
         y = self.matrix.transpose() * other.copy()
         return y
     else:
         return self * other
        index_phi]  # pulling out the values of the rho corresponding to index_phi

    yvar = rho_at_index[
        0, :]  # storing the values of rho corresponding to index_phi into xvar

    rho_sorted_acc_to_theta = index_sorted(
        xvar, yvar)  # calling the index_sorted function
    rho_sorted_acc_to_theta = np.reshape(
        rho_sorted_acc_to_theta,
        (1, len(rho_sorted_acc_to_theta)))  # reshaping into a single array

    theta_sorted = np.sort(theta_at_index)  # theta value sorted
    theta_sorted = theta_sorted[
        0, :]  # converting from 1Xn matrix to row array of n elements

    phi_new = phi_value * numerix.ones(len(theta_sorted))

    m_cell_modified_sph_pol = numerix.append(
        numerix.asarray(r_at_index),
        [numerix.asarray(theta_sorted),
         numerix.asarray(phi_new)],
        axis=0)

    #print(numerix.shape(m_cell_modified_sph_pol))
    m_cell_sph = numerix.append(
        m_cell_sph, (m_cell_modified_sph_pol),
        axis=1)  #Appending the m values in spherical polar coordinate

    theta_sz = np.shape(theta_sorted)
    size = theta_sz[0]
    total_size = total_size + size  # calculate total number of cells being covered during calculation
Пример #58
0
 def _cellVolumes(self):
     return numerix.ones(self.numberOfCells, 'd') * self.dx * self.dy * self.dz
Пример #59
0
    def _extrude(self, mesh, extrudeFunc, layers):
        ## should extrude cnahe self rather than creating a new mesh?

        ## the following allows the 2D mesh to be in 3D space, this can be the case for a
        ## Gmsh2DIn3DSpace which would then be extruded.
        oldVertices = mesh.vertexCoords
        if oldVertices.shape[0] == 2:
            oldVertices = numerix.resize(oldVertices, (3, len(oldVertices[0])))
            oldVertices[2] = 0

        NCells = mesh.numberOfCells
        NFac = mesh.numberOfFaces
        NFacPerCell =  mesh._maxFacesPerCell

        ## set up the initial data arrays
        new_shape = (max(NFacPerCell, 4), (1 + layers)*NCells + layers*NFac)
        faces = numerix.MA.masked_values(-numerix.ones(new_shape, 'l'), value = -1)
        orderedVertices = mesh._orderedCellVertexIDs
        faces[:NFacPerCell, :NCells] = orderedVertices
        vertices = oldVertices
        vert0 = mesh.faceVertexIDs
        faceCount = NCells
        
        for layer in range(layers):

            ## need this later
            initialFaceCount = faceCount

            ## build the vertices
            newVertices = extrudeFunc(oldVertices)
            vertices = numerix.concatenate((vertices, newVertices), axis=1)

            ## build the faces along the layers
            faces[:NFacPerCell, faceCount: faceCount + NCells] = orderedVertices + len(oldVertices[0]) * (layer + 1)
            try:
                # numpy 1.1 doesn't copy right side before assigning slice
                # See: http://www.mail-archive.com/[email protected]/msg09843.html
                faces[:NFacPerCell, faceCount: faceCount + NCells] = faces[:NFacPerCell, faceCount: faceCount + NCells][::-1,:].copy()
            except:
                faces[:NFacPerCell, faceCount: faceCount + NCells] = faces[:NFacPerCell, faceCount: faceCount + NCells][::-1,:]

            faceCount = faceCount + NCells

            vert1 = (vert0 + len(oldVertices[0]))[::-1,:]

            ## build the faces between the layers
            faces[:4, faceCount: faceCount + NFac] = numerix.concatenate((vert0, vert1), axis = 0)[::-1,:]

            vert0 = vert0 + len(oldVertices[0])

            NCells = mesh.numberOfCells

            
            ## build the cells, the first layer has slightly different ordering
            if layer == 0:
                c0 =  numerix.reshape(numerix.arange(NCells), (1, NCells))
                cells = numerix.concatenate((c0, c0 + NCells, mesh.cellFaceIDs + 2 * NCells), axis = 0)
            else:
                newCells = numerix.concatenate((c0, c0 + initialFaceCount, mesh.cellFaceIDs + faceCount), axis=0)
                newCells[0] = cells[1,-NCells:]
                cells = numerix.concatenate((cells, newCells), axis=1)

            ## keep a count of things for the next layer
            faceCount = faceCount + NFac
            oldVertices = newVertices

        ## return a new mesh, extrude could just as easily act on self
        return Mesh(vertices, faces, cells, communicator=mesh.communicator)