コード例 #1
0
    def __init__(self, dx = 1., dy = 1., nx = 1, ny = 1,
                 _RepresentationClass=_Grid2DRepresentation, _TopologyClass=_Mesh2DTopology):
        """
        Creates a 2D triangular mesh with horizontal faces numbered first then
        vertical faces, then diagonal faces.  Vertices are numbered starting
        with the vertices at the corners of boxes and then the vertices at the
        centers of boxes.  Cells on the right of boxes are numbered first, then
        cells on the top of boxes, then cells on the left of boxes, then cells
        on the bottom of boxes.  Within each of the 'sub-categories' in the
        above, the vertices, cells and faces are numbered in the usual way.

        :Parameters:
          - `dx, dy`: The X and Y dimensions of each 'box'.
            If `dx` <> `dy`, the line segments connecting the cell
            centers will not be orthogonal to the faces.
          - `nx, ny`: The number of boxes in the X direction and the Y direction.
            The total number of boxes will be equal to `nx * ny`, and the total
            number of cells will be equal to `4 * nx * ny`.
        """

        self.args = {
            'dx': dx,
            'dy': dy,
            'nx': nx,
            'ny': ny
        }

        self.nx = nx
        self.ny = ny

        self.numberOfHorizontalFaces   = self.nx * (self.ny + 1)
        self.numberOfVerticalFaces     = self.ny * (self.nx + 1)
        self.numberOfEachDiagonalFaces = self.nx * self.ny

        self.dx  = PhysicalField(value = dx)
        scale    = PhysicalField(value = 1, unit = self.dx.unit)
        self.dx /= scale

        self.dy = PhysicalField(value = dy)
        if self.dy.unit.isDimensionless():
            self.dy = dy
        else:
            self.dy /= scale

        self.numberOfCornerVertices = (self.nx + 1) * (self. ny + 1)
        self.numberOfCenterVertices = self.nx * self.ny
        self.numberOfTotalVertices  = self.numberOfCornerVertices + self.numberOfCenterVertices

        self.offset = (0, 0)

        vertices = self._createVertices()
        faces    = self._createFaces()

        cells = self._createCells()
        cells = numerix.sort(cells, axis=0)

        Mesh2D.__init__(self, vertices, faces, cells,
                        _RepresentationClass=_RepresentationClass, _TopologyClass=_TopologyClass)

        self.scale = scale
コード例 #2
0
    def __init__(self, dx=1., nx=None, origin=(0,), overlap=2, communicator=parallelComm, *args, **kwargs):
        scale = PhysicalField(value=1, unit=PhysicalField(value=dx).unit)
        self.origin = PhysicalField(value=origin)
        self.origin /= scale

        super(CylindricalNonUniformGrid1D, self).__init__(dx=dx,
                                                          nx=nx,
                                                          overlap=overlap,
                                                          communicator=communicator,
                                                          *args,
                                                          **kwargs)

        self.vertexCoords += origin
        self.args['origin'] = origin
コード例 #3
0
ファイル: skewedGrid2D.py プロジェクト: ztrautt/fipy
    def __init__(self, dx=1., dy=1., nx=None, ny=1, rand=0, *args, **kwargs):
        self.args = {'dx': dx, 'dy': dy, 'nx': nx, 'ny': ny, 'rand': rand}

        self.nx = nx
        self.ny = ny

        self.dx = PhysicalField(value=dx)
        scale = PhysicalField(value=1, unit=self.dx.unit)
        self.dx /= scale

        self.dy = PhysicalField(value=dy)
        if self.dy.unit.isDimensionless():
            self.dy = dy
        else:
            self.dy /= scale

        self.grid = Grid2D(nx=nx, ny=ny, dx=dx, dy=dy, communicator=serialComm)

        self.numberOfVertices = self.grid._numberOfVertices

        vertices = self.grid.vertexCoords

        changedVertices = numerix.zeros(vertices.shape, 'd')

        for i in range(len(vertices[0])):
            if ((i % (nx + 1)) != 0 and (i % (nx + 1)) != nx
                    and (i // nx + 1) != 0 and (i // nx + 1) != ny):
                changedVertices[0, i] = vertices[0, i] + (rand * (
                    (random.random() * 2) - 1))
                changedVertices[1, i] = vertices[1, i] + (rand * (
                    (random.random() * 2) - 1))
            else:
                changedVertices[0, i] = vertices[0, i]
                changedVertices[1, i] = vertices[1, i]

        faces = self.grid.faceVertexIDs

        cells = self.grid.cellFaceIDs

        Mesh2D.__init__(self,
                        changedVertices,
                        faces,
                        cells,
                        communicator=serialComm,
                        *args,
                        **kwargs)

        self.scale = scale
コード例 #4
0
    def __init__(self, faces, value):
        """
        Parameters
        ----------
        faces : :obj:`~fipy.variables.faceVariable.FaceVariable` of :obj:`bool`
            Mask of faces where this condition applies.
        value : float
            Value to impose.
        """
        if self.__class__ is BoundaryCondition:
            raise NotImplementedError("can't instantiate abstract base class")

        self.faces = faces
        if not (isinstance(value, PhysicalField)
                or isinstance(value, Variable)):
            value = PhysicalField(value)
        self.value = value

        if not (self.faces | self.faces.mesh.exteriorFaces
                == self.faces.mesh.exteriorFaces).value.all():
            raise IndexError('Face list has interior faces')

        self.adjacentCellIDs = self.faces.mesh._adjacentCellIDs[0][
            self.faces.value]
        self.boundaryConditionApplied = False
コード例 #5
0
 def _calcPhysicalShape(self):
     """Return physical dimensions of `Grid3D`
     """
     from fipy.tools.dimensions.physicalField import PhysicalField
     return PhysicalField(value=(self.ns[0] * self.ds[0] * self.scale,
                                 self.ns[1] * self.ds[1] * self.scale,
                                 self.ns[2] * self.ds[2] * self.scale))
コード例 #6
0
ファイル: uniformGrid1D.py プロジェクト: huahbo/FiPy-2.1.3
    def __init__(self, dx=1.0, nx=1, origin=(0,), overlap=2, communicator=parallel):
        origin = numerix.array(origin)

        self.args = {"dx": dx, "nx": nx, "origin": origin, "overlap": overlap}

        self.dim = 1

        self.dx = PhysicalField(value=dx)
        scale = PhysicalField(value=1, unit=self.dx.getUnit())
        self.dx /= scale

        nx = int(nx)

        (self.nx, self.overlap, self.offset) = self._calcParallelGridInfo(nx, overlap, communicator)

        self.origin = PhysicalField(value=origin)
        self.origin /= scale
        self.origin += self.offset * self.dx

        self.numberOfVertices = self.nx + 1
        if self.nx == 0:
            self.numberOfFaces = 0
        else:
            self.numberOfFaces = self.nx + 1
        self.numberOfCells = self.nx

        self.exteriorFaces = self.getFacesLeft() | self.getFacesRight()

        self.scale = {"length": 1.0, "area": 1.0, "volume": 1.0}

        self.setScale(value=scale)
        self.communicator = communicator
コード例 #7
0
ファイル: grid1D.py プロジェクト: calbaker/FiPy-2.1.3
    def __init__(self, dx=1., nx=None, overlap=2, communicator=parallel):
        self.args = {
            'dx': dx, 
            'nx': nx, 
            'overlap': overlap
        }

        from fipy.tools.dimensions.physicalField import PhysicalField
        self.dx = PhysicalField(value=dx)
        scale = PhysicalField(value=1, unit=self.dx.getUnit())
        self.dx /= scale
        
        nx = self._calcNumPts(d=self.dx, n=nx)

        (self.nx,
         self.overlap,
         self.offset) = self._calcParallelGridInfo(nx, overlap, communicator)

        if numerix.getShape(self.dx) is not ():
            Xoffset = numerix.sum(self.dx[0:self.offset])
            self.dx = self.dx[self.offset:self.offset + self.nx]
        else:
            Xoffset = self.dx * self.offset
            
        vertices = self._createVertices() + ((Xoffset,),)
        self.numberOfVertices = len(vertices[0])
        faces = self._createFaces()
        self.numberOfFaces = len(faces[0])
        cells = self._createCells()
        Mesh1D.__init__(self, vertices, faces, cells, communicator=communicator)
        
        self.setScale(value = scale)
コード例 #8
0
ファイル: grid2DBuilder.py プロジェクト: yswang0927/fipy
    def _calcPhysicalShape(self):
        """Return physical dimensions of Grid2D."""
        from fipy.tools.dimensions.physicalField import PhysicalField

        if self._dsUniformLen():
            return PhysicalField(value=(self.ns[0] * self.ds[0] * self.scale,
                                        self.ns[1] * self.ds[1] * self.scale))
        else:
            return None
コード例 #9
0
ファイル: utilityClasses.py プロジェクト: yswang0927/fipy
    def calcOrigin(origin, offset, ds, scale):
        newOrigin  = PhysicalField(value=origin)
        newOrigin /= scale

        if type(offset) in [int, float]:
            newOrigin += offset * ds[0]
        else:
            newOrigin += [[o*float(d)] for o, d in zip(offset, ds)]

        return newOrigin
コード例 #10
0
ファイル: tri2D.py プロジェクト: calbaker/FiPy-2.1.3
 def __init__(self, dx = 1., dy = 1., nx = 1, ny = 1):
     """
     Creates a 2D triangular mesh with horizontal faces numbered first then
     vertical faces, then diagonal faces.  Vertices are numbered starting
     with the vertices at the corners of boxes and then the vertices at the
     centers of boxes.  Cells on the right of boxes are numbered first, then
     cells on the top of boxes, then cells on the left of boxes, then cells
     on the bottom of boxes.  Within each of the 'sub-categories' in the
     above, the vertices, cells and faces are numbered in the usual way.
     
     :Parameters:
       - `dx, dy`: The X and Y dimensions of each 'box'. 
         If `dx` <> `dy`, the line segments connecting the cell 
         centers will not be orthogonal to the faces.
       - `nx, ny`: The number of boxes in the X direction and the Y direction. 
         The total number of boxes will be equal to `nx * ny`, and the total 
         number of cells will be equal to `4 * nx * ny`.
     """
     self.nx = nx
     self.ny = ny
     
     self.dx = PhysicalField(value = dx)
     scale = PhysicalField(value = 1, unit = self.dx.getUnit())
     self.dx /= scale
     
     self.dy = PhysicalField(value = dy)
     if self.dy.getUnit().isDimensionless():
         self.dy = dy
     else:
         self.dy /= scale
     
     self.numberOfCornerVertices = (self.nx + 1) * (self. ny + 1)
     self.numberOfCenterVertices = self.nx * self.ny
     self.numberOfTotalVertices = self.numberOfCornerVertices + self.numberOfCenterVertices
     
     vertices = self._createVertices()
     faces = self._createFaces()
     cells = self._createCells()
     cells = numerix.sort(cells, axis=0)
     Mesh2D.__init__(self, vertices, faces, cells)
     self.setScale(value = scale)
コード例 #11
0
    def __init__(self, dx=1., dy=1., nx=None, ny=None, 
                 origin=((0.,), (0.,)), overlap=2, communicator=parallelComm, *args, **kwargs):
        scale = PhysicalField(value=1, unit=PhysicalField(value=dx).unit)
        self.origin = PhysicalField(value=origin)
        self.origin /= scale

        super(CylindricalNonUniformGrid2D, self).__init__(dx=dx, dy=dy, nx=nx, ny=ny, overlap=overlap, 
                        communicator=communicator, *args, **kwargs)
        
        self._faceAreas *= self.faceCenters[0]

        self._scaledFaceAreas = self._scale['area'] * self._faceAreas
        self._areaProjections = self.faceNormals * self._faceAreas
        self._orientedAreaProjections = self._calcOrientedAreaProjections()
        self._faceAspectRatios = self._calcFaceAspectRatios()
                                       
        self._cellAreas = self._calcCellAreas()
        self._cellNormals = self._calcCellNormals() 
          
        self.vertexCoords += self.origin
        self.args['origin'] = self.origin
コード例 #12
0
ファイル: skewedGrid2D.py プロジェクト: calbaker/FiPy-2.1.3
    def __init__(self, dx = 1., dy = 1., nx = None, ny = 1, rand = 0):
        self.nx = nx
        self.ny = ny
        
        self.dx = PhysicalField(value = dx)
        scale = PhysicalField(value = 1, unit = self.dx.getUnit())
        self.dx /= scale
        
        self.dy = PhysicalField(value = dy)
        if self.dy.getUnit().isDimensionless():
            self.dy = dy
        else:
            self.dy /= scale

        from fipy import Grid2D
        self.grid = Grid2D(nx=nx, ny=ny, dx=dx, dy=dy)

        self.numberOfVertices = self.grid._getNumberOfVertices()
        
        vertices = self.grid.getVertexCoords()

        changedVertices = numerix.zeros(vertices.shape, 'd')

        for i in range(len(vertices[0])):
            if((i % (nx+1)) != 0 and (i % (nx+1)) != nx and (i / nx+1) != 0 and (i / nx+1) != ny):
                changedVertices[0, i] = vertices[0, i] + (rand * ((random.random() * 2) - 1))
                changedVertices[1, i] = vertices[1, i] + (rand * ((random.random() * 2) - 1))
            else:
                changedVertices[0, i] = vertices[0, i]
                changedVertices[1, i] = vertices[1, i]


        faces = self.grid._getFaceVertexIDs()
        
        cells = self.grid._getCellFaceIDs()

        Mesh2D.__init__(self, changedVertices, faces, cells)
        
        self.setScale(value = scale)
コード例 #13
0
    def sqrtDot(a1, a2):
        """Return array of square roots of vector dot-products
        for arrays a1 and a2 of vectors v1 and v2

        Usually used with v1==v2 to return magnitude of v1.
        """
        from fipy.tools.dimensions import physicalField
        unit1 = unit2 = physicalField._unity

        def dimensionlessUnmasked(a):
            unit = physicalField._unity
            mask = False
            if _isPhysical(a):
                unit = a.inBaseUnits().unit
                a = a.numericValue
            if MA.isMaskedArray(a):
                mask = a.mask
                a = a.filled(fill_value=1)
            if not a.flags['C_CONTIGUOUS']:
                a = a.copy('C')
            return (a, unit, mask)

        a1, unit1, mask1 = dimensionlessUnmasked(a1)
        a2, unit2, mask2 = dimensionlessUnmasked(a2)

        NJ, ni = NUMERIX.shape(a1)
        result1 = NUMERIX.zeros((ni, ), 'd')

        inline._runInline("""
            int j;
            result1[i] = 0.;
            for (j = 0; j < NJ; j++)
            {
                result1[i] += a1[i + j * ni] * a2[i + j * ni];
            }
            result1[i] = sqrt(result1[i]);
        """,
                          result1=result1,
                          a1=a1,
                          a2=a2,
                          ni=ni,
                          NJ=NJ)

        if NUMERIX.any(mask1) or NUMERIX.any(mask2):
            result1 = MA.array(result1, mask=NUMERIX.logical_or(mask1, mask2))

        if unit1 != physicalField._unity or unit2 != physicalField._unity:
            from fipy.tools.dimensions.physicalField import PhysicalField
            result1 = PhysicalField(value=result, unit=(unit1 * unit2)**0.5)

        return result1
コード例 #14
0
    def _setScaledGeometry(self, val):
        """
        Set the scale by length.

        :Parameters:
          - `val`: The new scale length.
        """

        self._scale['length'] = PhysicalField(value=val)

        if self._scale['length'].unit.isDimensionless():
            self._scale['length'] = 1

        self._scale['area'] = self._calcAreaScale()
        self._scale['volume'] = self._calcVolumeScale()
        self._setScaledValues()
コード例 #15
0
        def _calcValue(self):
            eps = self.eps 
            P = self.P.numericValue
            P = numerix.where(abs(P) < eps, eps, P)

            alpha = numerix.where(                  P > 10.,                     (P - 1.) / P,   0.5)

            tmp = (1. - P / 10.)
            tmpSqr = tmp * tmp
            alpha = numerix.where(  (10. >= P) & (P > eps), ((P-1.) + tmpSqr*tmpSqr*tmp) / P, alpha)

            tmp = (1. + P / 10.)
            tmpSqr = tmp * tmp
            alpha = numerix.where((-eps >  P) & (P >= -10.),     (tmpSqr*tmpSqr*tmp - 1.) / P, alpha)

            alpha = numerix.where(                 P < -10.,                          -1. / P, alpha)

            return PhysicalField(value = alpha)
コード例 #16
0
ファイル: uniformGrid1D.py プロジェクト: regmi/fipy
 def __init__(self, dx=1., nx=1, origin=(0,), overlap=2, parallelModule=parallel):
     origin = numerix.array(origin)
     
     self.args = {
         'dx': dx, 
         'nx': nx, 
         'origin': origin, 
         'overlap': overlap
     }
     
     self.dim = 1
     
     self.dx = PhysicalField(value=dx)
     scale = PhysicalField(value=1, unit=self.dx.getUnit())
     self.dx /= scale
     
     nx = int(nx)
     
     (self.nx,
      self.overlap,
      self.offset) = self._calcParallelGridInfo(nx, overlap, parallelModule)
     
     self.origin = PhysicalField(value=origin)
     self.origin /= scale
     self.origin += self.offset * self.dx
     
     self.numberOfVertices = self.nx + 1
     if self.nx == 0:
         self.numberOfFaces = 0
     else:
         self.numberOfFaces = self.nx + 1
     self.numberOfCells = self.nx
     
     self.exteriorFaces = self.getFacesLeft() | self.getFacesRight()
     
     self.scale = {
         'length': 1.,
         'area': 1.,
         'volume': 1.
     }
     
     self.setScale(value=scale)
コード例 #17
0
ファイル: boundaryCondition.py プロジェクト: xinxinboss/fipy
 def __init__(self,faces,value):
     """
     :Parameters:
         - `faces`: A `list` or `tuple` of exterior `Face` objects to which this condition applies.
         - `value`: The value to impose.
     """
     if self.__class__ is BoundaryCondition:
         raise NotImplementedError, "can't instantiate abstract base class"
     
     self.faces = faces
     if not (isinstance(value, PhysicalField) or isinstance(value, Variable)):
         value = PhysicalField(value)
     self.value = value
     
     if not (self.faces | self.faces.mesh.exteriorFaces 
             == self.faces.mesh.exteriorFaces).value.all():
         raise IndexError, 'Face list has interior faces'
     
     self.adjacentCellIDs = self.faces.mesh._adjacentCellIDs[0][self.faces.value]
     self.boundaryConditionApplied = False
コード例 #18
0
ファイル: grid2D.py プロジェクト: calbaker/FiPy-2.1.3
    def __init__(self, dx, dy, nx, ny):
	"""Grid2D is initialized by caller
	
	:Parameters:
	    
	  - `dx`: dimension of each cell in **x** direction
	  - `dy`: dimension of each cell in **y** direction
	  - `nx`: number of cells in **x** direction
	  - `ny`: number of cells in **y** direction
	"""
        self.nx=nx
        self.ny=ny
        self.dx=PhysicalField(value = dx)
        self.dy=PhysicalField(value = dy)
	self.scale = PhysicalField(value = 1, unit = self.dx.getUnit())
	self.dx /= self.scale
	self.dy /= self.scale
	
	vertices = self._createVertices()
	rowFaces,colFaces = self._createFaces(vertices)
	cells = self._createCells(rowFaces,colFaces)
	faces,interiorFaces = self._reorderFaces(rowFaces,colFaces)
	Mesh.__init__(self, cells, faces, interiorFaces, vertices)
コード例 #19
0
ファイル: grid2D.py プロジェクト: regmi/fipy
    def __init__(self, dx=1., dy=1., nx=None, ny=None, overlap=2, parallelModule=parallel):
        
        self.args = {
            'dx': dx, 
            'dy': dy, 
            'nx': nx, 
            'ny': ny, 
            'overlap': overlap,
            'parallelModule': parallelModule
        }

        self.dx = PhysicalField(value = dx)
        scale = PhysicalField(value=1, unit=self.dx.getUnit())
        self.dx /= scale
        
        nx = self._calcNumPts(d=self.dx, n=nx, axis="x")
        
        self.dy = PhysicalField(value = dy)
        if self.dy.getUnit().isDimensionless():
            self.dy = dy
        else:
            self.dy /= scale
            
        ny = self._calcNumPts(d=self.dy, n=ny, axis="y")
        
        (self.nx,
         self.ny,
         self.overlap,
         self.offset) = self._calcParallelGridInfo(nx, ny, overlap, parallelModule)

        if numerix.getShape(self.dx) is not ():
            Xoffset = numerix.sum(self.dx[0:self.offset[0]])
            self.dx = self.dx[self.offset[0]:self.offset[0] + self.nx]
        else:
            Xoffset = 0

        if numerix.getShape(self.dy) is not ():
            Yoffset =  numerix.sum(self.dy[0:self.offset[1]])
            self.dy = self.dy[self.offset[1]:self.offset[1] + self.ny]
        else:
            Yoffset = 0
            
        if self.nx == 0:
            self.ny = 0
        if self.ny == 0:
            self.nx = 0
        if self.nx == 0 or self.ny == 0:
            self.numberOfHorizontalRows = 0
            self.numberOfVerticalColumns = 0
        else:
            self.numberOfHorizontalRows = (self.ny + 1)
            self.numberOfVerticalColumns = (self.nx + 1)

        self.numberOfVertices = self.numberOfHorizontalRows * self.numberOfVerticalColumns

        vertices = self._createVertices() + ((Xoffset,), (Yoffset,))
        faces = self._createFaces()
        self.numberOfFaces = len(faces[0])
        cells = self._createCells()
        Mesh2D.__init__(self, vertices, faces, cells)
        
        self.setScale(value = scale)
コード例 #20
0
ファイル: grid2D.py プロジェクト: regmi/fipy
class Grid2D(Mesh2D):
    """
    Creates a 2D grid mesh with horizontal faces numbered
    first and then vertical faces.
    """
    def __init__(self, dx=1., dy=1., nx=None, ny=None, overlap=2, parallelModule=parallel):
        
        self.args = {
            'dx': dx, 
            'dy': dy, 
            'nx': nx, 
            'ny': ny, 
            'overlap': overlap,
            'parallelModule': parallelModule
        }

        self.dx = PhysicalField(value = dx)
        scale = PhysicalField(value=1, unit=self.dx.getUnit())
        self.dx /= scale
        
        nx = self._calcNumPts(d=self.dx, n=nx, axis="x")
        
        self.dy = PhysicalField(value = dy)
        if self.dy.getUnit().isDimensionless():
            self.dy = dy
        else:
            self.dy /= scale
            
        ny = self._calcNumPts(d=self.dy, n=ny, axis="y")
        
        (self.nx,
         self.ny,
         self.overlap,
         self.offset) = self._calcParallelGridInfo(nx, ny, overlap, parallelModule)

        if numerix.getShape(self.dx) is not ():
            Xoffset = numerix.sum(self.dx[0:self.offset[0]])
            self.dx = self.dx[self.offset[0]:self.offset[0] + self.nx]
        else:
            Xoffset = 0

        if numerix.getShape(self.dy) is not ():
            Yoffset =  numerix.sum(self.dy[0:self.offset[1]])
            self.dy = self.dy[self.offset[1]:self.offset[1] + self.ny]
        else:
            Yoffset = 0
            
        if self.nx == 0:
            self.ny = 0
        if self.ny == 0:
            self.nx = 0
        if self.nx == 0 or self.ny == 0:
            self.numberOfHorizontalRows = 0
            self.numberOfVerticalColumns = 0
        else:
            self.numberOfHorizontalRows = (self.ny + 1)
            self.numberOfVerticalColumns = (self.nx + 1)

        self.numberOfVertices = self.numberOfHorizontalRows * self.numberOfVerticalColumns

        vertices = self._createVertices() + ((Xoffset,), (Yoffset,))
        faces = self._createFaces()
        self.numberOfFaces = len(faces[0])
        cells = self._createCells()
        Mesh2D.__init__(self, vertices, faces, cells)
        
        self.setScale(value = scale)

    def _calcParallelGridInfo(self, nx, ny, overlap, parallelModule):
        
        procID = parallelModule.procID
        Nproc = parallelModule.Nproc

        overlap = min(overlap, ny)
        cellsPerNode = max(int(ny / Nproc), overlap)
        occupiedNodes = min(int(ny / (cellsPerNode or 1)), Nproc)
            
        overlap = {
            'left': 0,
            'right': 0,
            'bottom': overlap * (procID > 0) * (procID < occupiedNodes),
            'top': overlap * (procID < occupiedNodes - 1)
        }
        
        offset = (0,
                  min(procID, occupiedNodes-1) * cellsPerNode - overlap['bottom'])
                
        local_nx = nx
        local_ny = cellsPerNode * (procID < occupiedNodes)
        if procID == occupiedNodes - 1:
            local_ny += (ny - cellsPerNode * occupiedNodes)
        local_ny = local_ny + overlap['bottom'] + overlap['top']
        
        self.globalNumberOfCells = nx * ny
        self.globalNumberOfFaces = nx * (ny + 1) + ny * (nx + 1)
        
        return local_nx, local_ny, overlap, offset

    def __repr__(self):
        return "%s(dx=%s, dy=%s, nx=%d, ny=%d)" \
            % (self.__class__.__name__, str(self.args["dx"]), str(self.args["dy"]), 
               self.args["nx"], self.args["ny"])
            
    def _createVertices(self):
        x = self._calcVertexCoordinates(self.dx, self.nx)
        x = numerix.resize(x, (self.numberOfVertices,))
            
        y = self._calcVertexCoordinates(self.dy, self.ny)
        y = numerix.repeat(y, self.numberOfVerticalColumns)
        
        return numerix.array((x, y))
    
    def _createFaces(self):
        """
        v1, v2 refer to the vertices.
        Horizontal faces are first
        """
        v1 = numerix.arange(self.numberOfVertices)
        v2 = v1 + 1

        horizontalFaces = vector.prune(numerix.array((v1, v2)), self.numberOfVerticalColumns, self.nx, axis=1)

        v1 = numerix.arange(self.numberOfVertices - self.numberOfVerticalColumns)
        v2 = v1 + self.numberOfVerticalColumns
        verticalFaces =  numerix.array((v1, v2))

        ## The cell normals must point out of the cell.
        ## The left and bottom faces have only one neighboring cell,
        ## in the 2nd neighbor position (there is nothing in the 1st).
        ## 
        ## reverse some of the face orientations to obtain the correct normals

        tmp = horizontalFaces.copy()
        horizontalFaces[0,:self.nx] = tmp[1,:self.nx]
        horizontalFaces[1,:self.nx] = tmp[0,:self.nx]

        self.numberOfHorizontalFaces = horizontalFaces.shape[-1]

        tmp = verticalFaces.copy()
        verticalFaces[0, :] = tmp[1, :]
        verticalFaces[1, :] = tmp[0, :]
        if self.numberOfVerticalColumns > 0:
            verticalFaces[0, ::self.numberOfVerticalColumns] = tmp[0, ::self.numberOfVerticalColumns]
            verticalFaces[1, ::self.numberOfVerticalColumns] = tmp[1,::self.numberOfVerticalColumns]

        return numerix.concatenate((horizontalFaces, verticalFaces), axis=1)

    def _createCells(self):
        """
        cells = (f1, f2, f3, f4) going anticlock wise.
        f1 etc. refer to the faces
        """
        return inline._optionalInline(self._createCellsIn, self._createCellsPy)

    def _createCellsPy(self):
        cellFaceIDs = numerix.zeros((4, self.nx * self.ny))
        faceIDs = numerix.arange(self.numberOfFaces)
        if self.numberOfFaces > 0:
            cellFaceIDs[0,:] = faceIDs[:self.numberOfHorizontalFaces - self.nx]
            cellFaceIDs[2,:] = cellFaceIDs[0,:] + self.nx
            cellFaceIDs[1,:] = vector.prune(faceIDs[self.numberOfHorizontalFaces:], self.numberOfVerticalColumns)
            cellFaceIDs[3,:] = cellFaceIDs[1,:] - 1
        return cellFaceIDs

    def _createCellsIn(self):
        cellFaceIDs = numerix.zeros((4, self.nx * self.ny))
        
        inline._runInline("""
            int ID = j * ni + i;
            int NCELLS = ni * nj;
            cellFaceIDs[ID + 0 * NCELLS] = ID;
            cellFaceIDs[ID + 2 * NCELLS] = cellFaceIDs[ID + 0 * NCELLS] + ni;
            cellFaceIDs[ID + 3 * NCELLS] = horizontalFaces + ID + j;
            cellFaceIDs[ID + 1 * NCELLS] = cellFaceIDs[ID + 3 * NCELLS] + 1;
        """,
        horizontalFaces=self.numberOfHorizontalFaces,
        cellFaceIDs=cellFaceIDs,
        ni=self.nx,
        nj=self.ny)

        return cellFaceIDs
    
    def getScale(self):
        return self.scale['length']
        
    def getPhysicalShape(self):
        """Return physical dimensions of Grid2D.
        """
        return PhysicalField(value = (self.nx * self.dx * self.getScale(), self.ny * self.dy * self.getScale()))

    def _getMeshSpacing(self):
        return numerix.array((self.dx,self.dy))[...,numerix.newaxis]
    
    def getShape(self):
        return (self.nx, self.ny)

    def _isOrthogonal(self):
        return True
        
    def _getGlobalNonOverlappingCellIDs(self):
        """
        Return the IDs of the local mesh in the context of the
        global parallel mesh. Does not include the IDs of boundary cells.

        E.g., would return [0, 1] for mesh A

        ---------
        | 4 | 5 |     
        ---------  B
        | 2 | 3 |     
        =========
        | 0 | 1 |  A
        ---------
        
        .. note:: Trivial except for parallel meshes
        """
        return numerix.arange((self.offset[1] + self.overlap['bottom']) * self.nx, 
                              (self.offset[1] + self.ny - self.overlap['top']) * self.nx)

    def _getGlobalOverlappingCellIDs(self):
        """
        Return the IDs of the local mesh in the context of the
        global parallel mesh. Includes the IDs of boundary cells.
        
        E.g., would return [0, 1, 2, 3] for mesh A

        ---------
        | 4 | 5 |     
        ---------  B
        | 2 | 3 |     
        =========
        | 0 | 1 |  A
        ---------
        
        .. note:: Trivial except for parallel meshes
        """
        return numerix.arange(self.offset[1] * self.nx, (self.offset[1] + self.ny) * self.nx)

    def _getLocalNonOverlappingCellIDs(self):
        """
        Return the IDs of the local mesh in isolation. 
        Does not include the IDs of boundary cells.
        
        E.g., would return [0, 1] for mesh A

        ---------
        | 4 | 5 |     
        ---------  B
        | 2 | 3 |     
        =========
        | 0 | 1 |  A
        ---------
        
        .. note:: Trivial except for parallel meshes
        """
        return numerix.arange(self.overlap['bottom'] * self.nx, 
                              (self.ny - self.overlap['top']) * self.nx)

    def _getLocalOverlappingCellIDs(self):
        """
        Return the IDs of the local mesh in isolation. 
        Includes the IDs of boundary cells.
        
        E.g., would return [0, 1, 2, 3] for mesh A

        ---------
        |   |   |     
        ---------  B
        | 2 | 3 |     
        =========
        | 0 | 1 |  A
        ---------
        
        .. note:: Trivial except for parallel meshes
        """
        return numerix.arange(0, self.ny * self.nx)
    
## pickling

    def __getstate__(self):
        """
        Used internally to collect the necessary information to ``pickle`` the 
        `Grid2D` to persistent storage.
        """
        return self.args

    def __setstate__(self, dict):
        """
        Used internally to create a new `Grid2D` from ``pickled`` 
        persistent storage.
        """
        self.__init__(**dict)

    def _test(self):
        """
コード例 #21
0
ファイル: uniformGrid2D.py プロジェクト: calbaker/FiPy-2.1.3
    def __init__(self, dx=1., dy=1., nx=1, ny=1, origin=((0,),(0,)), overlap=2, communicator=parallel):        
        self.args = {
            'dx': dx, 
            'dy': dy, 
            'nx': nx, 
            'ny': ny, 
            'origin': origin,
            'overlap': overlap,
            'communicator': communicator
        }

        self.dim = 2
        
        self.dx = PhysicalField(value = dx)
        scale = PhysicalField(value = 1, unit = self.dx.getUnit())
        self.dx /= scale
        
        nx = int(nx)
        
        self.dy = PhysicalField(value = dy)
        if self.dy.getUnit().isDimensionless():
            self.dy = dy
        else:
            self.dy /= scale
            
        ny = int(ny)
        
        (self.nx,
         self.ny,
         self.overlap,
         self.offset) = self._calcParallelGridInfo(nx, ny, overlap, communicator)
        
        self.origin = PhysicalField(value = origin)
        self.origin /= scale

        self.origin += ((self.offset[0] * float(self.dx),),
                        (self.offset[1] * float(self.dy),))

        if self.nx == 0:
            self.ny = 0
        if self.ny == 0:
            self.nx = 0
        if self.nx == 0 or self.ny == 0:
            self.numberOfHorizontalRows = 0
            self.numberOfVerticalColumns = 0
        else:
            self.numberOfHorizontalRows = (self.ny + 1)
            self.numberOfVerticalColumns = (self.nx + 1)
            
        self.numberOfVertices = self.numberOfHorizontalRows * self.numberOfVerticalColumns

        self.numberOfHorizontalFaces = self.nx * self.numberOfHorizontalRows
        self.numberOfVerticalFaces = self.numberOfVerticalColumns * self.ny
        self.numberOfFaces = self.numberOfHorizontalFaces + self.numberOfVerticalFaces
        self.numberOfCells = self.nx * self.ny
        
        
        self.scale = {
            'length': 1.,
            'area': 1.,
            'volume': 1.
        }

        self.setScale(value = scale)
        self.communicator = communicator
コード例 #22
0
ファイル: grid2D.py プロジェクト: calbaker/FiPy-2.1.3
class Grid2D(Mesh):
    """2D rectangular Mesh
    
    Numbering system

	nx=5
	
	ny=3

	Cells::
	
	    *************************************
	    *      *      *       *      *      *
	    * 10   * 11   * 12    * 13   * 14   *
	    *************************************
	    *      *      *       *      *      *
	    * 5    * 6    * 7     * 8    * 9    *
	    *************************************
	    *      *      *       *      *      *
	    * 0    * 1    * 2     * 3    * 4    *
	    *************************************

	Faces (before reordering)::
	    
	    ***15******16*****17******18****19***
	    *      *      *       *      *      *
	    32    33      34      35     36     37
	    ***10******11*****12******13*****14**
	    *      *      *       *      *      *
	    26     27     28      29     30     31
	    ***5*******6******7*******8******9***
	    *      *      *       *      *      *
	    20     21     22      23     24     25
	    ***0*******1******2*******3******4***

    
	Faces (after reordering)::
	    
	    ***27******28*****29******30****31***
	    *      *      *       *      *      *
	    34     18     19      20     21     37
	    ***5*******6******7*******8******9***
	    *      *      *       *      *      *
	    33     14     15      16     17     36
	    ***0*******1******2*******3******4***
	    *      *      *       *      *      *
	    32     10     11      12     13     35
	    ***22******23*****24******25*****26**
		
	Vertices::

	    18*****19*****20******21*****22****23
	    *      *      *       *      *      *
	    *      *      *       *      *      *
	    12*****13*****14******15*****16****17
	    *      *      *       *      *      *
	    *      *      *       *      *      *
	    6******7******8*******9******10****11
	    *      *      *       *      *      *
	    *      *      *       *      *      *
	    0******1******2*******3******4******5
    """
    
    def __init__(self, dx, dy, nx, ny):
	"""Grid2D is initialized by caller
	
	:Parameters:
	    
	  - `dx`: dimension of each cell in **x** direction
	  - `dy`: dimension of each cell in **y** direction
	  - `nx`: number of cells in **x** direction
	  - `ny`: number of cells in **y** direction
	"""
        self.nx=nx
        self.ny=ny
        self.dx=PhysicalField(value = dx)
        self.dy=PhysicalField(value = dy)
	self.scale = PhysicalField(value = 1, unit = self.dx.getUnit())
	self.dx /= self.scale
	self.dy /= self.scale
	
	vertices = self._createVertices()
	rowFaces,colFaces = self._createFaces(vertices)
	cells = self._createCells(rowFaces,colFaces)
	faces,interiorFaces = self._reorderFaces(rowFaces,colFaces)
	Mesh.__init__(self, cells, faces, interiorFaces, vertices)
		
    def _createVertices(self):
	"""Return list of `Vertex` objects
	"""
	vertices = ()
        ny=self.ny
        nx=self.nx
        dx=self.dx
        dy=self.dy
	for j in range(ny+1):
	    for	i in range(nx+1):
		vertices += (Vertex(numerix.array([i * dx, j * dy],'d')),)
## 		vertices += (Vertex(PhysicalField(value = [i * dx, j * dy])),)
        return vertices	
		    
    def _createFaces(self, vertices):
	"""Return 2-`tuple` of `Face` objects bounded by `vertices`. 
	
	First `tuple` are the `Face` objects that separate rows of `Cell` objects.  
	Second `tuple` are the `Face` objects that separate columns of `Cell 
	objects.  These initial lists are layed out for efficiency of composing 
	and indexing into the lists to compose `Cell` objects.  They will 
	subsequently be reordered for efficiency of computations.
	"""
        nx=self.nx
        ny=self.ny

	id = 0
	rowFaces = ()
	for j in range(ny+1):
	    oneRow = ()
	    for i in range(nx):
		oneRow += (Face2D((vertices[i + j * (nx + 1)],vertices[i + 1 + j * (nx + 1)]),id),)
		id += 1
	    rowFaces += (oneRow,)
	colFaces = []
	for j in range(ny):
	    oneCol = ()
	    for i in range(nx+1):
		oneCol += (Face2D((vertices[i + j * (nx + 1)],vertices[i + (j + 1) * (nx + 1)]),id),)
		id += 1
	    colFaces += (oneCol,)
	return (rowFaces,colFaces)
	
    def _reorderFaces(self,rowFaces,colFaces):
	"""Return a `tuple` of `Face` objects ordered for best efficiency.
	
	Composed from `rowFaces` and `colFaces` such that all interior faces
	are listed contiguously, rows then columns, followed by all boundary
	faces, rows then columns.
	"""
	interiorFaces = ()

	for rowFace in rowFaces[1:-1]:
	    interiorFaces += rowFace
	for colFace in colFaces:
	    interiorFaces += colFace[1:-1]
	    
	faces = interiorFaces
	faces += rowFaces[0] + rowFaces[-1]
	for colFace in colFaces:
	    faces += (colFace[0],)
	for colFace in colFaces:
	    faces += (colFace[-1],)
	
	id = 0
	for face in faces:
	    face._setID(id)
	    id += 1

	return (faces, interiorFaces)
	
    def _createCells(self,rowFaces,colFaces):
	"""Return list of `Cell` objects.
	"""
	nx=self.nx
	ny=self.ny
	cells = ()
	for j in range(ny):
	    for i in range(nx):
                id = j * nx + i
		cells += (
		    Cell(
			faces = (rowFaces[j][i],
				rowFaces[j+1][i],
				colFaces[j][i],
				colFaces[j][i+1]),
			faceOrientations = (-1,1,1,-1),
			id = id
			),
		    ) 
		    
	return cells

    def _createInteriorFaces(self,faces):
	"""Return list of faces that are not on boundary of Grid2D.
	"""
        interiorFaces = ()
        for face in faces:
            if len(face.getCells()) == 2:
                interiorFaces += (face,)
        return interiorFaces

    def getFacesLeft(self):
        """
        Return list of faces on left boundary of Grid2D with the
        x-axis running from left to right.
        """
	nx=self.nx
	ny=self.ny
	start = len(self.interiorFaces) + 2 * nx
	return self.faces[start:start + ny]
	
    def getFacesRight(self):
        """
        Return list of faces on right boundary of Grid2D with the
        x-axis running from left to right.
        """
	nx=self.nx
	ny=self.ny
	start = len(self.interiorFaces) + 2 * nx + ny
	return self.faces[start:start + ny]
	
    def getFacesTop(self):
        """
        Return list of faces on top boundary of Grid2D with the
        y-axis running from bottom to top.
        """
	nx=self.nx
	start = len(self.interiorFaces) + nx
	return self.faces[start:start + nx]
	
    def getFacesBottom(self):
        """
        Return list of faces on bottom boundary of Grid2D with the
        y-axis running from bottom to top.
        """
	nx=self.nx
	start = len(self.interiorFaces)
	return self.faces[start:start + nx]
	    
    def getShape(self):
	"""Return cell dimensions `Grid2D`.
	"""
        return (self.nx,self.ny)
        
    def getPhysicalShape(self):
	"""Return physical dimensions of Grid2D.
	"""
	return PhysicalField(value = (self.nx * self.dx * self.getScale(), self.ny * self.dy * self.getScale()))

    def _getMaxFacesPerCell(self):
        return 4

    def _getFaceAreas(self):
	return Mesh._getFaceAreas(self) * self.getScale()

    def getCellVolumes(self):
        if self.getScale() is 1:
            return Mesh.getCellVolumes(self)
        else:
            return Mesh.getCellVolumes(self) * self.getScale() * self.getScale()

    def getCellCenters(self):
        if self.getScale() is 1:
            return Mesh.getCellCenters(self)
        else:
            return Mesh.getCellCenters(self) * self.getScale()

    def _getCellDistances(self):
        if self.getScale() is 1:
            return Mesh._getCellDistances(self)
        else:
            return Mesh._getCellDistances(self) * self.getScale()
        
    def _getFaceToCellDistances(self):
        if self.getScale() is 1:
            return Mesh._getFaceToCellDistances(self)
        else:
            return Mesh._getFaceToCellDistances(self) * self.getScale()

    def _getMeshSpacing(self):
	return PhysicalField(value = ((self.dx * self.getScale(),),(self.dy * self.getScale(),)))
コード例 #23
0
ファイル: abstractMesh.py プロジェクト: yannikbehr/fipy
 def _getPointToCellDistances(self, point):
     tmp = self.cellCenters - PhysicalField(point)
     return numerix.sqrtDot(tmp, tmp)
コード例 #24
0
ファイル: uniformGrid2D.py プロジェクト: calbaker/FiPy-2.1.3
class UniformGrid2D(Grid2D):
    """
    Creates a 2D grid mesh with horizontal faces numbered
    first and then vertical faces.
    """
    def __init__(self, dx=1., dy=1., nx=1, ny=1, origin=((0,),(0,)), overlap=2, communicator=parallel):        
        self.args = {
            'dx': dx, 
            'dy': dy, 
            'nx': nx, 
            'ny': ny, 
            'origin': origin,
            'overlap': overlap,
            'communicator': communicator
        }

        self.dim = 2
        
        self.dx = PhysicalField(value = dx)
        scale = PhysicalField(value = 1, unit = self.dx.getUnit())
        self.dx /= scale
        
        nx = int(nx)
        
        self.dy = PhysicalField(value = dy)
        if self.dy.getUnit().isDimensionless():
            self.dy = dy
        else:
            self.dy /= scale
            
        ny = int(ny)
        
        (self.nx,
         self.ny,
         self.overlap,
         self.offset) = self._calcParallelGridInfo(nx, ny, overlap, communicator)
        
        self.origin = PhysicalField(value = origin)
        self.origin /= scale

        self.origin += ((self.offset[0] * float(self.dx),),
                        (self.offset[1] * float(self.dy),))

        if self.nx == 0:
            self.ny = 0
        if self.ny == 0:
            self.nx = 0
        if self.nx == 0 or self.ny == 0:
            self.numberOfHorizontalRows = 0
            self.numberOfVerticalColumns = 0
        else:
            self.numberOfHorizontalRows = (self.ny + 1)
            self.numberOfVerticalColumns = (self.nx + 1)
            
        self.numberOfVertices = self.numberOfHorizontalRows * self.numberOfVerticalColumns

        self.numberOfHorizontalFaces = self.nx * self.numberOfHorizontalRows
        self.numberOfVerticalFaces = self.numberOfVerticalColumns * self.ny
        self.numberOfFaces = self.numberOfHorizontalFaces + self.numberOfVerticalFaces
        self.numberOfCells = self.nx * self.ny
        
        
        self.scale = {
            'length': 1.,
            'area': 1.,
            'volume': 1.
        }

        self.setScale(value = scale)
        self.communicator = communicator
        
    def _translate(self, vector):
        return self.__class__(dx = self.args['dx'], nx = self.args['nx'], 
                              dy = self.args['dy'], ny = self.args['ny'], 
                             origin = numerix.array(self.args['origin']) + vector, overlap=self.args['overlap'])

    def __mul__(self, factor):
        if numerix.shape(factor) is ():
            factor = numerix.resize(factor, (2,1))
        
        return UniformGrid2D(dx=self.args['dx'] * numerix.array(factor[0]), nx=self.args['nx'], 
                             dy=self.args['dy'] * numerix.array(factor[1]), ny=self.args['ny'], 
                             origin=numerix.array(self.args['origin']) * factor, overlap=self.args['overlap'])

    def _getConcatenableMesh(self):
        from fipy.meshes.numMesh.grid2D import Grid2D
        args = self.args.copy()
        origin = args['origin']
        from fipy.tools import serial
        args['communicator'] = serial
        del args['origin']
        return Grid2D(**args) + origin

##     get topology methods

##         from common/mesh
        
    def _getCellFaceIDs(self):
        return self._createCells()
        
    def getExteriorFaces(self):
        """
        Return only the faces that have one neighboring cell.
        """
        exteriorIDs = numerix.concatenate((numerix.arange(0, self.nx),
                                           numerix.arange(0, self.nx) + self.nx * self.ny,
                                           numerix.arange(0, self.ny) * self.numberOfVerticalColumns + self.numberOfHorizontalFaces,
                                           numerix.arange(0, self.ny) * self.numberOfVerticalColumns + self.numberOfHorizontalFaces + self.nx))
                       
        from fipy.variables.faceVariable import FaceVariable
        exteriorFaces = FaceVariable(mesh=self, value=False)
        exteriorFaces[exteriorIDs] = True
        return exteriorFaces
        
    def getInteriorFaces(self):
        """
        Return only the faces that have two neighboring cells.
        """
        Hids = numerix.arange(0, self.numberOfHorizontalFaces)
        Hids = numerix.reshape(Hids, (self.numberOfHorizontalRows, self.nx))
        Hids = Hids[1:-1,...]
        
        Vids = numerix.arange(self.numberOfHorizontalFaces, self.numberOfFaces)
        Vids = numerix.reshape(Vids, (self.ny, self.numberOfVerticalColumns))
        Vids = Vids[...,1:-1]
        
        interiorIDs = numerix.concatenate((numerix.reshape(Hids, (self.nx * (self.ny - 1),)), 
                                           numerix.reshape(Vids, ((self.nx - 1) * self.ny,))))
                                           
        from fipy.variables.faceVariable import FaceVariable
        interiorFaces = FaceVariable(mesh=self, value=False)
        interiorFaces[interiorIDs] = True
        return interiorFaces

    def _getCellFaceOrientations(self):
        cellFaceOrientations = numerix.ones((4, self.numberOfCells))
        if self.numberOfCells > 0:
            cellFaceOrientations[0, self.nx:] = -1
            cellFaceOrientations[3, :] = -1
            cellFaceOrientations[3, ::self.nx] = 1
        return cellFaceOrientations

    def _getAdjacentCellIDs(self):
        return inline._optionalInline(self._getAdjacentCellIDsIn, self._getAdjacentCellIDsPy)
    
    def _getAdjacentCellIDsIn(self):
        faceCellIDs0 =  numerix.zeros(self.numberOfFaces)
        faceCellIDs1 =  numerix.zeros(self.numberOfFaces)

        inline._runInline("""
            int ID = j * ni + i;

            faceCellIDs0[ID] = ID - ni;
            faceCellIDs1[ID] = ID;

            faceCellIDs0[ID + Nhor + j] = ID - 1;
            faceCellIDs1[ID + Nhor + j] = ID;

            if (j == 0) {
                faceCellIDs0[ID] = ID;
            }

            if (j == nj - 1) {
                faceCellIDs0[ID + ni] = ID;
                faceCellIDs1[ID + ni] = ID;
            }

            if (i == 0) {
                faceCellIDs0[ID + Nhor + j] = ID;
            }

            if ( i == ni - 1 ) {
                faceCellIDs0[ID + Nhor + j + 1] = ID;
                faceCellIDs1[ID + Nhor + j + 1] = ID;
            }
            
        """,
        Nhor=self.numberOfHorizontalFaces,
        faceCellIDs0=faceCellIDs0,
        faceCellIDs1=faceCellIDs1,
        ni=self.nx,
        nj=self.ny)

        return (faceCellIDs0, faceCellIDs1)

    def _getAdjacentCellIDsPy(self):
        Hids = numerix.zeros((self.numberOfHorizontalRows, self.nx, 2))
        indices = numerix.indices((self.numberOfHorizontalRows, self.nx))
        
        Hids[...,1] = indices[1] + indices[0] * self.nx
        Hids[...,0] = Hids[...,1] - self.nx
        
        if self.numberOfHorizontalRows > 0:
            Hids[0,...,0] = Hids[0,...,1]
            Hids[0,...,1] = Hids[0,...,0]
            Hids[-1,...,1] = Hids[-1,...,0]
      
        Vids = numerix.zeros((self.ny, self.numberOfVerticalColumns, 2))
        indices = numerix.indices((self.ny, self.numberOfVerticalColumns))
        Vids[...,1] = indices[1] + indices[0] * self.nx
        Vids[...,0] = Vids[...,1] - 1
        
        if self.numberOfVerticalColumns > 0:
            Vids[...,0,0] = Vids[...,0,1]
            Vids[...,0,1] = Vids[...,0,0]
            Vids[...,-1,1] = Vids[...,-1,0]

        faceCellIDs =  numerix.concatenate((numerix.reshape(Hids, (self.numberOfHorizontalFaces, 2)), 
                                            numerix.reshape(Vids, (self.numberOfFaces - self.numberOfHorizontalFaces, 2))))

        return (faceCellIDs[:,0], faceCellIDs[:,1])


    def _getCellToCellIDs(self):
        ids = MA.zeros((4, self.nx, self.ny), 'l')
        indices = numerix.indices((self.nx, self.ny))
        ids[0] = indices[0] + (indices[1] - 1) * self.nx
        ids[1] = (indices[0] + 1) + indices[1] * self.nx
        ids[2] = indices[0] + (indices[1] + 1) * self.nx
        ids[3] = (indices[0] - 1) + indices[1] * self.nx
        
        if self.ny > 0:
            ids[0,..., 0] = MA.masked
            ids[2,...,-1] = MA.masked
        if self.nx > 0:
            ids[1,-1,...] = MA.masked
            ids[3, 0,...] = MA.masked
        
        return MA.reshape(ids.swapaxes(1,2), (4, self.numberOfCells))
        
    def _getCellToCellIDsFilled(self):
        N = self.getNumberOfCells()
        M = self._getMaxFacesPerCell()
        cellIDs = numerix.repeat(numerix.arange(N)[numerix.newaxis, ...], M, axis=0)
        cellToCellIDs = self._getCellToCellIDs()
        return MA.where(MA.getmaskarray(cellToCellIDs), cellIDs, cellToCellIDs)
        
    def _getMaxFacesPerCell(self):
        return 4
        
##         from numMesh/mesh

    def getVertexCoords(self):
        return self._createVertices() + self.origin

    def getFaceCellIDs(self):
        return inline._optionalInline(self._getFaceCellIDsIn, self._getFaceCellIDsPy)

    def _getFaceCellIDsIn(self):
        faceCellIDs = numerix.zeros((2, self.numberOfFaces))
        mask = numerix.zeros((2, self.numberOfFaces))
        
        inline._runInline("""
            int ID = j * ni + i; 
            int rowlength = ni * nj + Nhor + nj;

            faceCellIDs[ID + 0 * rowlength] = ID - ni;
            faceCellIDs[ID + 1 * rowlength] = ID;

            faceCellIDs[ID + Nhor + j + 0 * rowlength] = ID - 1;
            faceCellIDs[ID + Nhor + j + 1 * rowlength] = ID;

            if (j == 0) {
                faceCellIDs[ID + 0 * rowlength] = ID;
                mask[ID + 1 * rowlength] = 1;
            }

            if (j == nj - 1) {
                faceCellIDs[ID + ni + 0 * rowlength] = ID;
                mask[ID + ni + 1 * rowlength] = 1;
            }

            if (i == 0) {
                faceCellIDs[ID + Nhor + j + 0 * rowlength] = ID;
                mask[ID + Nhor + j + 1 * rowlength] = 1;
            }

            if ( i == ni - 1 ) {
                faceCellIDs[ID + Nhor + j + 1 + 0 * rowlength] = ID;
                mask[ID + Nhor + j + 1 + 1 * rowlength] = 1;
            }
        """,
        Nhor=self.numberOfHorizontalFaces,
        mask=mask,
        faceCellIDs=faceCellIDs,
        ni=self.nx,
        nj=self.ny)

        return MA.masked_where(mask, faceCellIDs)

    def _getFaceCellIDsPy(self):

        Hids = numerix.zeros((2, self.nx, self.numberOfHorizontalRows))
        indices = numerix.indices((self.nx, self.numberOfHorizontalRows))
        Hids[1] = indices[0] + indices[1] * self.nx
        Hids[0] = Hids[1] - self.nx
        if self.numberOfHorizontalRows > 0:
            Hids[0,...,0] = Hids[1,...,0]
            Hids[1,...,0] = -1
            Hids[1,...,-1] = -1

        Vids = numerix.zeros((2, self.numberOfVerticalColumns, self.ny))
        indices = numerix.indices((self.numberOfVerticalColumns, self.ny))
        Vids[1] = indices[0] + indices[1] * self.nx
        Vids[0] = Vids[1] - 1
        if self.numberOfVerticalColumns > 0:
            Vids[0,0] = Vids[1,0]
            Vids[1,0] = -1
            Vids[1,-1] = -1
        
        return MA.masked_values(numerix.concatenate((Hids.reshape((2, self.numberOfHorizontalFaces), order="FORTRAN"), 
                                                     Vids.reshape((2, self.numberOfFaces - self.numberOfHorizontalFaces), order="FORTRAN")), axis=1), value = -1)
    
    def _getFaceAreas(self):
        faceAreas = numerix.zeros(self.numberOfFaces, 'd')
        faceAreas[:self.numberOfHorizontalFaces] = self.dx
        faceAreas[self.numberOfHorizontalFaces:] = self.dy
        return faceAreas

    def _getFaceNormals(self):
        normals = numerix.zeros((2, self.numberOfFaces), 'd')

        normals[1, :self.numberOfHorizontalFaces] = 1
        normals[1, :self.nx] = -1

        normals[0, self.numberOfHorizontalFaces:] = 1
        if self.numberOfVerticalColumns > 0:
            normals[0, self.numberOfHorizontalFaces::self.numberOfVerticalColumns] = -1

        return normals

    def _getFaceCellToCellNormals(self):
        return self._getFaceNormals()
        
    def getCellVolumes(self):
        return numerix.ones(self.numberOfCells, 'd') * self.dx * self.dy

    def _getCellCenters(self):
        centers = numerix.zeros((2, self.nx, self.ny), 'd')
        indices = numerix.indices((self.nx, self.ny))
        centers[0] = (indices[0] + 0.5) * self.dx
        centers[1] = (indices[1] + 0.5) * self.dy
        return centers.reshape((2, self.numberOfCells), order="FORTRAN") + self.origin

    def _getCellDistances(self):
        Hdis = numerix.repeat((self.dy,), self.numberOfHorizontalFaces)
        Hdis = numerix.reshape(Hdis, (self.nx, self.numberOfHorizontalRows))
        if self.numberOfHorizontalRows > 0:
            Hdis[...,0] = self.dy / 2.
            Hdis[...,-1] = self.dy / 2.
        
        Vdis = numerix.repeat((self.dx,), self.numberOfFaces - self.numberOfHorizontalFaces)
        Vdis = numerix.reshape(Vdis, (self.numberOfVerticalColumns, self.ny))
        if self.numberOfVerticalColumns > 0:
            Vdis[0,...] = self.dx / 2.
            Vdis[-1,...] = self.dx / 2.

        return numerix.concatenate((numerix.reshape(numerix.swapaxes(Hdis,0,1), (self.numberOfHorizontalFaces,)), 
                                    numerix.reshape(numerix.swapaxes(Vdis,0,1), (self.numberOfFaces - self.numberOfHorizontalFaces,))))

    def _getFaceToCellDistanceRatio(self):
        faceToCellDistanceRatios = numerix.zeros(self.numberOfFaces, 'd')
        faceToCellDistanceRatios[:] = 0.5
        faceToCellDistanceRatios[:self.nx] = 1.
        faceToCellDistanceRatios[self.numberOfHorizontalFaces - self.nx:self.numberOfHorizontalFaces] = 1.
        if self.numberOfVerticalColumns > 0:
            faceToCellDistanceRatios[self.numberOfHorizontalFaces::self.numberOfVerticalColumns] = 1.
            faceToCellDistanceRatios[(self.numberOfHorizontalFaces + self.nx)::self.numberOfVerticalColumns] = 1.
        return faceToCellDistanceRatios

    def _getFaceToCellDistances(self):
        faceToCellDistances = numerix.zeros((2, self.numberOfFaces), 'd')
        distances = self._getCellDistances()
        ratios = self._getFaceToCellDistanceRatio()
        faceToCellDistances[0] = distances * ratios
        faceToCellDistances[1] = distances * (1 - ratios)
        return faceToCellDistances

    def _getOrientedAreaProjections(self):
        return self._getAreaProjections()

    def _getAreaProjections(self):
        return inline._optionalInline(self._getAreaProjectionsIn, self._getAreaProjectionsPy)

    def _getAreaProjectionsPy(self):
        return self._getFaceNormals() * self._getFaceAreas()

    def _getAreaProjectionsIn(self):
        areaProjections = numerix.zeros((2, self.numberOfFaces), 'd')

        inline._runInline("""
            if (i < nx) {
                areaProjections[i + 1 * ni] = -dx;
            } else if (i < Nhor) {
                areaProjections[i + 1 * ni] = dx;
            } else if ( (i - Nhor) % (nx + 1) == 0 ) {
                areaProjections[i + 0 * ni] = -dy;
            } else {
                areaProjections[i + 0 * ni] = dy;
           }
        """,
        dx = float(self.dx), # horrible hack to get around
        dy = float(self.dy), # http://www.scipy.org/scipy/scipy/ticket/496
        nx = self.nx,
        Nhor = self.numberOfHorizontalFaces,
        areaProjections = areaProjections,
        ni = self.numberOfFaces)

        return areaProjections

    def _getOrientedFaceNormals(self):
        return self._getFaceNormals()

    def _getFaceTangents1(self):
        tangents = numerix.zeros((2,self.numberOfFaces), 'd')

        if self.numberOfFaces > 0:
            tangents[0, :self.numberOfHorizontalFaces] = -1
            tangents[0, :self.nx] = 1        
            tangents[1, self.numberOfHorizontalFaces:] = 1
            tangents[1, self.numberOfHorizontalFaces::self.numberOfVerticalColumns] = -1

        return tangents
        
    def _getFaceTangents2(self):
        return numerix.zeros((2, self.numberOfFaces), 'd')
        
    def _getFaceAspectRatios(self):
        return self._getFaceAreas() / self._getCellDistances()
    
    def _getCellToCellDistances(self):
        distances = numerix.zeros((4, self.nx, self.ny), 'd')
        distances[0] = self.dy
        distances[1] = self.dx
        distances[2] = self.dy
        distances[3] = self.dx
        
        if self.ny > 0:
            distances[0,..., 0] = self.dy / 2.
            distances[2,...,-1] = self.dy / 2.
        if self.nx > 0:
            distances[3, 0,...] = self.dx / 2.
            distances[1,-1,...] = self.dx / 2.
        
        return distances.reshape((4, self.numberOfCells), order="FORTRAN")


    def _getCellNormals(self):
        normals = numerix.zeros((2, 4, self.numberOfCells), 'd')
        normals[:, 0] = [[ 0], [-1]]
        normals[:, 1] = [[ 1], [ 0]]
        normals[:, 2] = [[ 0], [ 1]]
        normals[:, 3] = [[-1], [ 0]]

        return normals
        
    def _getCellAreas(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

    def _getCellAreaProjections(self):
        return self._getCellAreas() * self._getCellNormals()

##         from numMesh/mesh

    def getFaceCenters(self):
        Hcen = numerix.zeros((2, self.nx, self.numberOfHorizontalRows), 'd')
        indices = numerix.indices((self.nx, self.numberOfHorizontalRows))
        Hcen[0,...] = (indices[0] + 0.5) * self.dx
        Hcen[1,...] = indices[1] * self.dy
        
        Vcen = numerix.zeros((2, self.numberOfVerticalColumns, self.ny), 'd')
        indices = numerix.indices((self.numberOfVerticalColumns, self.ny))
        Vcen[0,...] = indices[0] * self.dx
        Vcen[1,...] = (indices[1] + 0.5) * self.dy
        
        return numerix.concatenate((Hcen.reshape((2, self.numberOfHorizontalFaces), order="FORTRAN"),
                                    Vcen.reshape((2, self.numberOfVerticalFaces), order="FORTRAN")), axis=1) + self.origin
                                    
    def _getCellVertexIDs(self):
        ids = numerix.zeros((4, self.nx, self.ny))
        indices = numerix.indices((self.nx, self.ny))
        ids[1] = indices[0] + (indices[1] + 1) * self.numberOfVerticalColumns
        ids[0] = ids[1] + 1
        ids[3] = indices[0] + indices[1] * self.numberOfVerticalColumns
        ids[2] = ids[3] + 1
        
        return numerix.reshape(ids, (4, self.numberOfCells))
        
    def _getFaceVertexIDs(self):
        Hids = numerix.zeros((2, self.nx, self.numberOfHorizontalRows))
        indices = numerix.indices((self.nx, self.numberOfHorizontalRows))
        Hids[0] = indices[0] + indices[1] * self.numberOfVerticalColumns
        Hids[1] = Hids[0] + 1

        Vids = numerix.zeros((2, self.numberOfVerticalColumns, self.ny))
        indices = numerix.indices((self.numberOfVerticalColumns, self.ny))
        Vids[0] = indices[0] + indices[1] * self.numberOfVerticalColumns
        Vids[1] = Vids[0] + self.numberOfVerticalColumns
        
        return numerix.concatenate((Hids.reshape((2, self.numberOfHorizontalFaces), order="FORTRAN"), 
                                    Vids.reshape((2, self.numberOfFaces - self.numberOfHorizontalFaces), order="FORTRAN")),
                                   axis=1)
                                    
    def _getOrderedCellVertexIDs(self):
        ids = numerix.zeros((4, self.nx, self.ny))
        indices = numerix.indices((self.nx, self.ny))
        ids[2] = indices[0] + (indices[1] + 1) * self.numberOfVerticalColumns
        ids[1] = ids[2] + 1
        ids[3] = indices[0] + indices[1] * self.numberOfVerticalColumns
        ids[0] = ids[3] + 1
        
        return ids.reshape((4, self.numberOfCells), order="FORTRAN")
        
##     scaling
    
    def _calcScaledGeometry(self):
        pass

    def _getNearestCellID(self, points):
        """
        Test cases

           >>> from fipy import *
           >>> m = Grid2D(nx=3, ny=2)
           >>> eps = numerix.array([[1e-5, 1e-5]])
           >>> print m._getNearestCellID(((0., .9, 3.), (0., 2., 2.)))
           [0 3 5]
           >>> print m._getNearestCellID(([1.1], [1.5]))
           [4]
           >>> m0 = Grid2D(nx=2, ny=2, dx=1., dy=1.)
           >>> m1 = Grid2D(nx=4, ny=4, dx=.5, dy=.5)
           >>> print m0._getNearestCellID(m1.getCellCenters().getGlobalValue())
           [0 0 1 1 0 0 1 1 2 2 3 3 2 2 3 3]
           
        """
        nx = self.args['nx']
        ny = self.args['ny']
        
        if nx == 0 or ny == 0:
            return numerix.arange(0)
            
        x0, y0 = self.getCellCenters().getGlobalValue()[...,0]        
        xi, yi = points
        dx, dy = self.dx, self.dy
        
        i = numerix.array(numerix.rint(((xi - x0) / dx)), 'l')
        i[i < 0] = 0
        i[i > nx - 1] = nx - 1

        j = numerix.array(numerix.rint(((yi - y0) / dy)), 'l')
        j[j < 0] = 0
        j[j > ny - 1]  = ny - 1

        return j * nx + i

    def _test(self):
        """
コード例 #25
0
 def physicalShape(self):
     """Return physical dimensions of Grid2D.
     """
     return PhysicalField(value=(self.nx * self.dx * self.scale,
                                 self.ny * self.dy * self.scale))
コード例 #26
0
ファイル: uniformGrid1D.py プロジェクト: regmi/fipy
class UniformGrid1D(Grid1D):
    """
    Creates a 1D grid mesh.
    
        >>> mesh = UniformGrid1D(nx = 3)
        >>> print mesh.getCellCenters()
        [[ 0.5  1.5  2.5]]
         
    """
    def __init__(self, dx=1., nx=1, origin=(0,), overlap=2, parallelModule=parallel):
        origin = numerix.array(origin)
        
        self.args = {
            'dx': dx, 
            'nx': nx, 
            'origin': origin, 
            'overlap': overlap
        }
        
        self.dim = 1
        
        self.dx = PhysicalField(value=dx)
        scale = PhysicalField(value=1, unit=self.dx.getUnit())
        self.dx /= scale
        
        nx = int(nx)
        
        (self.nx,
         self.overlap,
         self.offset) = self._calcParallelGridInfo(nx, overlap, parallelModule)
        
        self.origin = PhysicalField(value=origin)
        self.origin /= scale
        self.origin += self.offset * self.dx
        
        self.numberOfVertices = self.nx + 1
        if self.nx == 0:
            self.numberOfFaces = 0
        else:
            self.numberOfFaces = self.nx + 1
        self.numberOfCells = self.nx
        
        self.exteriorFaces = self.getFacesLeft() | self.getFacesRight()
        
        self.scale = {
            'length': 1.,
            'area': 1.,
            'volume': 1.
        }
        
        self.setScale(value=scale)
        
    def _translate(self, vector):
        return UniformGrid1D(dx=self.dx, 
                             nx=self.args['nx'], 
                             origin=self.args['origin'] + numerix.array(vector),
                             overlap=self.args['overlap'])

    def __mul__(self, factor):
        return UniformGrid1D(dx=self.dx * factor,
                             nx=self.args['nx'],
                             origin=self.args['origin'] * factor,
                             overlap=self.args['overlap'])

    def _getConcatenableMesh(self):
        from fipy.meshes.numMesh.mesh1D import Mesh1D
        return Mesh1D(vertexCoords = self.getVertexCoords(), 
                      faceVertexIDs = self._createFaces(), 
                      cellFaceIDs = self._createCells())
                      
    def _concatenate(self, other, smallNumber):
        """
        Following test was added due to a bug in adding Meshes.

            >>> a = UniformGrid1D(nx=10) + (10,)
            >>> print a.getCellCenters()
            [[ 10.5  11.5  12.5  13.5  14.5  15.5  16.5  17.5  18.5  19.5]]
            >>> b = 10 + UniformGrid1D(nx=10)
            >>> print b.getCellCenters()
            [[ 10.5  11.5  12.5  13.5  14.5  15.5  16.5  17.5  18.5  19.5]]
            
            >>> from fipy.tools import parallel
            >>> if parallel.Nproc == 1:
            ...     c =  UniformGrid1D(nx=10) + (UniformGrid1D(nx=10) + 10)
            >>> print (parallel.Nproc > 1 
            ...        or numerix.allclose(c.getCellCenters()[0],
            ...                            [0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 10.5, 11.5,
            ...                            12.5, 13.5, 14.5, 15.5, 16.5, 17.5, 18.5, 19.5]))
            True
            
        """
        return self._getConcatenableMesh()._concatenate(other = other, smallNumber = smallNumber)
        
##     get topology methods

##         from common/mesh
        
    def _getCellFaceIDs(self):
        return MA.array(self._createCells())
        
    def getInteriorFaces(self):
        from fipy.variables.faceVariable import FaceVariable
        interiorFaces = FaceVariable(mesh=self, value=False)
        interiorFaces[numerix.arange(self.numberOfFaces-2) + 1] = True
        return interiorFaces
            
    def _getCellFaceOrientations(self):
        orientations = numerix.ones((2, self.numberOfCells))
        if self.numberOfCells > 0:
            orientations[0] *= -1
            orientations[0,0] = 1
        return orientations

    def _getAdjacentCellIDs(self):
        c1 = numerix.arange(self.numberOfFaces)
        ids = numerix.array((c1 - 1, c1))
        if self.numberOfFaces > 0:
            ids[0,0] = ids[1,0]
            ids[1,-1] = ids[0,-1]
        return ids[0], ids[1]

    def _getCellToCellIDs(self):
        c1 = numerix.arange(self.numberOfCells)
        ids = MA.array((c1 - 1, c1 + 1))
        if self.numberOfCells > 0:
            ids[0,0] = MA.masked
            ids[1,-1] = MA.masked
        return ids
        
    def _getCellToCellIDsFilled(self):
        ids = self._getCellToCellIDs().filled()
        if self.numberOfCells > 0:
            ids[0,0] = 0
            ids[1,-1] = self.numberOfCells - 1
        return ids
        
    def _getMaxFacesPerCell(self):
        return 2
        
##         from numMesh/mesh

    def getVertexCoords(self):
        return self.getFaceCenters()

    def getFaceCellIDs(self):
        c1 = numerix.arange(self.numberOfFaces)
        ids = MA.array((c1 - 1, c1))
        if self.numberOfFaces > 0:
            ids[0,0] = ids[1,0]
            ids[1,0] = MA.masked
            ids[1,-1] = MA.masked
        return ids

##     get geometry methods
        
##         from common/mesh
        
    def _getFaceAreas(self):
        return numerix.ones(self.numberOfFaces,'d')

    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

    def _getFaceCellToCellNormals(self):
        return self._getFaceNormals()
        
    def getCellVolumes(self):
        return numerix.ones(self.numberOfCells, 'd') * self.dx

    def _getCellCenters(self):
        return ((numerix.arange(self.numberOfCells)[numerix.NewAxis, ...] + 0.5) * self.dx + self.origin) * self.scale['length']

    def _getCellDistances(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

    def _getFaceToCellDistanceRatio(self):
        distances = numerix.ones(self.numberOfFaces, 'd')
        distances *= 0.5
        if len(distances) > 0:
            distances[0] = 1
            distances[-1] = 1
        return distances
        
    def _getOrientedAreaProjections(self):
        return self._getAreaProjections()

    def _getAreaProjections(self):
        return self._getFaceNormals()

    def _getOrientedFaceNormals(self):
        return self._getFaceNormals()

    def _getFaceTangents1(self):
        return numerix.zeros(self.numberOfFaces, 'd')[numerix.NewAxis, ...]

    def _getFaceTangents2(self):
        return numerix.zeros(self.numberOfFaces, 'd')[numerix.NewAxis, ...]
        
    def _getFaceAspectRatios(self):
        return 1. / self._getCellDistances()
    
    def _getCellToCellDistances(self):
        distances = MA.zeros((2, self.numberOfCells), 'd')
        distances[:] = self.dx
        if self.numberOfCells > 0:
            distances[0,0] = self.dx / 2.
            distances[1,-1] = self.dx / 2.
        return distances

    def _getCellNormals(self):
        normals = numerix.ones((1, 2, self.numberOfCells), 'd')
        if self.numberOfCells > 0:
            normals[:,0] = -1
        return normals
        
    def _getCellAreas(self):
        return numerix.ones((2, self.numberOfCells), 'd')

    def _getCellAreaProjections(self):
        return MA.array(self._getCellNormals())

##         from numMesh/mesh

    def getFaceCenters(self):
        return numerix.arange(self.numberOfFaces)[numerix.NewAxis, ...] * self.dx + self.origin

    def _getCellVertexIDs(self):
        c1 = numerix.arange(self.numberOfCells)
        return numerix.array((c1 + 1, c1))


##     scaling
    
    def _calcScaledGeometry(self):
        pass

    def _getNearestCellID(self, points):
        """
        Test cases

           >>> from fipy import *
           >>> m = Grid1D(nx=3)
           >>> print m._getNearestCellID(([0., .9, 3.],))
           [0 0 2]
           >>> print m._getNearestCellID(([1.1],))
           [1]
           >>> m0 = Grid1D(nx=2, dx=1.)
           >>> m1 = Grid1D(nx=4, dx=.5)
           >>> print m0._getNearestCellID(m1.getCellCenters().getGlobalValue())
           [0 0 1 1]
           
        """
        nx = self.globalNumberOfCells
        
        if nx == 0:
            return numerix.arange(0)
            
        x0, = self.getCellCenters().getGlobalValue()[...,0]        
        xi, = points
        dx = self.dx
        
        i = numerix.array(numerix.rint(((xi - x0) / dx)), 'l')
        i[i < 0] = 0
        i[i > nx - 1] = nx - 1

        return i

    def _test(self):
        """
コード例 #27
0
ファイル: numerix.py プロジェクト: xinxinboss/fipy
def nearest(data, points, max_mem=1e8):
    """find the indices of `data` that are closest to `points`
    
    >>> from fipy import *
    >>> m0 = Grid2D(dx=(.1, 1., 10.), dy=(.1, 1., 10.))
    >>> m1 = Grid2D(nx=2, ny=2, dx=5., dy=5.)
    >>> print nearest(m0.cellCenters.globalValue, m1.cellCenters.globalValue)
    [4 5 7 8]
    >>> print nearest(m0.cellCenters.globalValue, m1.cellCenters.globalValue, max_mem=100)
    [4 5 7 8]
    >>> print nearest(m0.cellCenters.globalValue, m1.cellCenters.globalValue, max_mem=10000)
    [4 5 7 8]
    """
    data = asanyarray(data)
    points = asanyarray(points)

    D = data.shape[0]
    N = data.shape[-1]
    M = points.shape[-1]

    if N == 0:
        return arange(0)

    # given (D, N) data and (D, M) points,
    # break points into (D, C) chunks of points
    # calculatate the full factorial (D, N, C) distances between them
    # and then reduce to the indices of the C closest values of data
    # then assemble chunks C into total M closest indices

    # (D, N) -> (D, N, 1)
    data = data[..., newaxis]

    # there appears to be no benefit to taking chunks that use more
    # than about 100 MiB for D x N x C, and there is a substantial penalty
    # for going much above that (presumably due to swapping, even
    # though this is vastly less than the 4 GiB I had available)
    # see ticket:348

    numChunks = int(round(D * N * data.itemsize * M / max_mem + 0.5))

    nearestIndices = empty((M, ), dtype=INT_DTYPE)
    for chunk in array_split(arange(points.shape[-1]), numChunks):
        # last chunk can be empty, but numpy (1.5.0.dev8716, anyway)
        # returns array([], dtype=float64), which can't be used for indexing
        chunk = chunk.astype(int)

        # (D, M) -> (D, C)
        chunkOfPoints = points[..., chunk]
        # (D, C) -> (D, 1, C)
        chunkOfPoints = chunkOfPoints[..., newaxis, :]
        # (D, 1, C) -> (D, N, C)
        chunkOfPoints = NUMERIX.repeat(chunkOfPoints, N, axis=1)

        #         print "chunkOfPoints size: ", chunkOfPoints.shape, chunkOfPoints.size, chunkOfPoints.itemsize, chunkOfPoints.size * chunkOfPoints.itemsize

        try:
            tmp = data - chunkOfPoints
        except TypeError:
            tmp = data - PhysicalField(chunkOfPoints)

        # (D, N, C) -> (N, C)
        tmp = dot(tmp, tmp, axis=0)

        # (N, C) -> C
        nearestIndices[chunk] = argmin(tmp, axis=0)

    return nearestIndices
コード例 #28
0
ファイル: tri2D.py プロジェクト: calbaker/FiPy-2.1.3
class Tri2D(Mesh2D):
    """
    This class creates a mesh made out of triangles.  It does this by
    starting with a standard Cartesian mesh (`Grid2D`) and dividing each cell
    in that mesh (hereafter referred to as a 'box') into four equal
    parts with the dividing lines being the diagonals.
    """
    
    def __init__(self, dx = 1., dy = 1., nx = 1, ny = 1):
        """
        Creates a 2D triangular mesh with horizontal faces numbered first then
        vertical faces, then diagonal faces.  Vertices are numbered starting
        with the vertices at the corners of boxes and then the vertices at the
        centers of boxes.  Cells on the right of boxes are numbered first, then
        cells on the top of boxes, then cells on the left of boxes, then cells
        on the bottom of boxes.  Within each of the 'sub-categories' in the
        above, the vertices, cells and faces are numbered in the usual way.
        
        :Parameters:
          - `dx, dy`: The X and Y dimensions of each 'box'. 
            If `dx` <> `dy`, the line segments connecting the cell 
            centers will not be orthogonal to the faces.
          - `nx, ny`: The number of boxes in the X direction and the Y direction. 
            The total number of boxes will be equal to `nx * ny`, and the total 
            number of cells will be equal to `4 * nx * ny`.
        """
        self.nx = nx
        self.ny = ny
        
        self.dx = PhysicalField(value = dx)
        scale = PhysicalField(value = 1, unit = self.dx.getUnit())
        self.dx /= scale
        
        self.dy = PhysicalField(value = dy)
        if self.dy.getUnit().isDimensionless():
            self.dy = dy
        else:
            self.dy /= scale
        
        self.numberOfCornerVertices = (self.nx + 1) * (self. ny + 1)
        self.numberOfCenterVertices = self.nx * self.ny
        self.numberOfTotalVertices = self.numberOfCornerVertices + self.numberOfCenterVertices
        
        vertices = self._createVertices()
        faces = self._createFaces()
        cells = self._createCells()
        cells = numerix.sort(cells, axis=0)
        Mesh2D.__init__(self, vertices, faces, cells)
        self.setScale(value = scale)
        
    def _createVertices(self):
        
        x = numerix.arange(self.nx + 1) * self.dx
        y = numerix.arange(self.ny + 1) * self.dy
        x = numerix.resize(x, (self.numberOfCornerVertices,))
        y = numerix.repeat(y, self.nx + 1)
        boxCorners = numerix.array((x, y))
        x = numerix.arange(0.5, self.nx + 0.5) * self.dx
        y = numerix.arange(0.5, self.ny + 0.5) * self.dy
        x = numerix.resize(x, (self.numberOfCenterVertices,))
        y = numerix.repeat(y, self.nx)
        boxCenters = numerix.array((x, y))
        return numerix.concatenate((boxCorners, boxCenters), axis=1)
    
    def _createFaces(self):
        """
        v1, v2 refer to the cells.
        Horizontel faces are first
        """
        v1 = numerix.arange(self.numberOfCornerVertices)
        v2 = v1 + 1
        horizontalFaces = vector.prune(numerix.array((v1, v2)), self.nx + 1, self.nx, axis=1)
        v1 = numerix.arange(self.numberOfCornerVertices - (self.nx + 1))
        v2 = v1 + self.nx + 1
        verticalFaces =  numerix.array((v1, v2))

        ## reverse some of the face orientations to obtain the correct normals

        tmp = horizontalFaces.copy()
        horizontalFaces[0, :self.nx] = tmp[1, :self.nx]
        horizontalFaces[1, :self.nx] = tmp[0, :self.nx]

        tmp = verticalFaces.copy()
        verticalFaces[0] = tmp[1]
        verticalFaces[1] = tmp[0]
        verticalFaces[0, ::(self.nx + 1)] = tmp[0, ::(self.nx + 1)]
        verticalFaces[1, ::(self.nx + 1)] = tmp[1, ::(self.nx + 1)]

        ## do the center ones now
        
        cellCenters = numerix.arange(self.numberOfCornerVertices, self.numberOfTotalVertices)
        lowerLefts = vector.prune(numerix.arange(self.numberOfCornerVertices - (self.nx + 1)), self.nx + 1, self.nx)
        lowerRights = lowerLefts + 1
        upperLefts = lowerLefts + self.nx + 1
        upperRights = lowerLefts + self.nx + 2
        lowerLeftFaces = numerix.array((cellCenters, lowerLefts))
        lowerRightFaces = numerix.array((lowerRights, cellCenters))
        upperLeftFaces = numerix.array((cellCenters, upperLefts))
        upperRightFaces = numerix.array((cellCenters, upperRights))
        return numerix.concatenate((horizontalFaces, verticalFaces, lowerLeftFaces, lowerRightFaces, upperLeftFaces, upperRightFaces), axis=1)

    def _createCells(self):
        """
        cells = (f1, f2, f3, f4) going anticlockwise.
        f1 etc. refer to the faces
        """
        self.numberOfHorizontalFaces = self.nx * (self.ny + 1)
        self.numberOfVerticalFaces =  self.ny * (self.nx + 1)
        self.numberOfEachDiagonalFaces = self.nx * self.ny
        bottomFaces = numerix.arange(0, self.numberOfHorizontalFaces - self.nx)
        topFaces = numerix.arange(self.nx, self.numberOfHorizontalFaces)
        leftFaces = vector.prune(numerix.arange(self.numberOfHorizontalFaces, self.numberOfHorizontalFaces + self.numberOfVerticalFaces), self.nx + 1, self.nx)
        rightFaces = vector.prune(numerix.arange(self.numberOfHorizontalFaces, self.numberOfHorizontalFaces + self.numberOfVerticalFaces), self.nx + 1, 0)
        lowerLeftDiagonalFaces = numerix.arange(self.numberOfHorizontalFaces + self.numberOfVerticalFaces, self.numberOfHorizontalFaces + self.numberOfVerticalFaces + self.numberOfEachDiagonalFaces)
        lowerRightDiagonalFaces = lowerLeftDiagonalFaces + self.numberOfEachDiagonalFaces
        upperLeftDiagonalFaces = lowerRightDiagonalFaces + self.numberOfEachDiagonalFaces
        upperRightDiagonalFaces = upperLeftDiagonalFaces + self.numberOfEachDiagonalFaces
        ##faces in arrays, now get the cells
        bottomOfBoxCells = numerix.array([bottomFaces, lowerRightDiagonalFaces, lowerLeftDiagonalFaces])
        rightOfBoxCells = numerix.array([rightFaces, upperRightDiagonalFaces, lowerRightDiagonalFaces])
        topOfBoxCells = numerix.array([topFaces, upperLeftDiagonalFaces, upperRightDiagonalFaces])
        leftOfBoxCells = numerix.array([leftFaces, lowerLeftDiagonalFaces, upperLeftDiagonalFaces])
        return numerix.concatenate((rightOfBoxCells, topOfBoxCells, leftOfBoxCells, bottomOfBoxCells), axis=1)
        
    def getScale(self):
        return self.scale['length']
        
    def getPhysicalShape(self):
        """Return physical dimensions of Grid2D.
        """
        return PhysicalField(value = (self.nx * self.dx * self.getScale(), self.ny * self.dy * self.getScale()))



    def _getMeshSpacing(self):
        return numerix.array((self.dx,self.dy))[...,numerix.newaxis]
    
    def getShape(self):
        return (self.nx, self.ny)

    def _isOrthogonal(self):
        return True
    
## pickling

    def __getstate__(self):
        return {
            'dx' : self.dx * self.scale['length'],
            'dy' : self.dy * self.scale['length'],
            'nx' : self.nx,
            'ny' : self.ny
        }

    def __setstate__(self, dict):
        self.__init__(**dict)

        
    def _test(self):
        """
コード例 #29
0
ファイル: grid3D.py プロジェクト: calbaker/FiPy-2.1.3
class Grid3D(Mesh):
    """
    3D rectangular-prism Mesh

    X axis runs from left to right.
    Y axis runs from bottom to top.
    Z axis runs from front to back.

    Numbering System:

    Vertices: Numbered in the usual way. X coordinate changes most quickly, then Y, then Z.

    Cells: Same numbering system as vertices.

    Faces: XY faces numbered first, then XZ faces, then YZ faces. Within each subcategory, it is numbered in the usual way.
    """
    def __init__(self, dx = 1., dy = 1., dz = 1., nx = None, ny = None, nz = None, overlap=2, communicator=parallel):
        
        self.args = {
            'dx': dx, 
            'dy': dy,
            'dz' :dz,
            'nx': nx, 
            'ny': ny,
            'nz': nz,
            'overlap': overlap,
            'communicator': communicator
        }
        
        self.dx = PhysicalField(value = dx)
        scale = PhysicalField(value = 1, unit = self.dx.getUnit())
        self.dx /= scale
        
        nx = self._calcNumPts(d = self.dx, n = nx, axis = "x")
        
        self.dy = PhysicalField(value = dy)
        if self.dy.getUnit().isDimensionless():
            self.dy = dy
        else:
            self.dy /= scale

        ny = self._calcNumPts(d = self.dy, n = ny, axis = "y")
        
        self.dz = PhysicalField(value = dz)
        if self.dz.getUnit().isDimensionless():
            self.dz = dz
        else:
            self.dz /= scale
        
        nz = self._calcNumPts(d = self.dz, n = nz, axis = "z")

        (self.nx,
         self.ny,
         self.nz,
         self.overlap,
         self.offset) = self._calcParallelGridInfo(nx, ny, nz, overlap, communicator)

        if numerix.getShape(self.dx) is not ():
            Xoffset = numerix.sum(self.dx[0:self.offset[0]])
            self.dx = self.dx[self.offset[0]:self.offset[0] + self.nx]
        else:
            Xoffset = 0

        if numerix.getShape(self.dy) is not ():
            Yoffset =  numerix.sum(self.dy[0:self.offset[1]])
            self.dy = self.dy[self.offset[1]:self.offset[1] + self.ny]
        else:
            Yoffset = 0

        if numerix.getShape(self.dy) is not ():
            Zoffset =  numerix.sum(self.dz[0:self.offset[2]])
            self.dz = self.dz[self.offset[2]:self.offset[2] + self.nz]
        else:
            Zoffset = 0

        if self.nx == 0 or self.ny == 0 or self.nz == 0:
            self.nx = 0
            self.ny = 0
            self.nz = 0

        if self.nx == 0 or self.ny == 0 or self.nz == 0:
            self.numberOfHorizontalRows = 0
            self.numberOfVerticalColumns = 0
            self.numberOfLayersDeep = 0
        else:
            self.numberOfHorizontalRows = (self.ny + 1)
            self.numberOfVerticalColumns = (self.nx + 1)
            self.numberOfLayersDeep = (self.nz + 1)
            
        self.numberOfVertices = self.numberOfHorizontalRows * self.numberOfVerticalColumns * self.numberOfLayersDeep
        
        vertices = self._createVertices() + ((Xoffset,), (Yoffset,), (Zoffset,))
        faces = self._createFaces()
        cells = self._createCells()
        Mesh.__init__(self, vertices, faces, cells)
        
        self.setScale(value = scale)

    def _calcParallelGridInfo(self, nx, ny, nz, overlap, communicator):
        
        procID = communicator.procID
        Nproc = communicator.Nproc

        overlap = min(overlap, nz)
        cellsPerNode = max(int(nz / Nproc), overlap)
        occupiedNodes = min(int(nz / (cellsPerNode or 1)), Nproc)
            
        overlap = {
            'left': 0,
            'right': 0,
            'bottom' : 0,
            'top' : 0,
            'front': overlap * (procID > 0) * (procID < occupiedNodes),
            'back': overlap * (procID < occupiedNodes - 1)
        }
        
        offset = (0,
                  0,
                  min(procID, occupiedNodes-1) * cellsPerNode - overlap['front'])
                
        local_nx = nx
        local_ny = ny
        local_nz = cellsPerNode * (procID < occupiedNodes)
        
        if procID == occupiedNodes - 1:
            local_nz += (nz - cellsPerNode * occupiedNodes)
        local_nz = local_nz + overlap['front'] + overlap['back']
        
        self.globalNumberOfCells = nx * ny * nz
        self.globalNumberOfFaces = nx * nz * (ny + 1) + ny * nz * (nx + 1) + nx * ny * (nz + 1)
        
        return local_nx, local_ny, local_nz, overlap, offset

    def __repr__(self):
        dnstr = []
        for d, n in [("dx", "nx"), ("dy", "ny"), ("dz", "nz")]:
            dnstr.append(d + "=" + str(self.args[d]))
            if self.args[n] is not None:
                dnstr.append(n + "=" + str(self.args[n]))

        return "%s(%s)" % (self.__class__.__name__, ", ".join(dnstr))

    def _createVertices(self):
        x = self._calcVertexCoordinates(self.dx, self.nx)
        x = numerix.resize(x, (self.numberOfVertices,))
        
        y = self._calcVertexCoordinates(self.dy, self.ny)
        y = numerix.repeat(y, self.numberOfVerticalColumns)
        y = numerix.resize(y, (self.numberOfVertices,))
        
        z = self._calcVertexCoordinates(self.dz, self.nz)
        z = numerix.repeat(z, self.numberOfHorizontalRows * self.numberOfVerticalColumns)
        z = numerix.resize(z, (self.numberOfVertices,))
        
        return numerix.array((x, y, z))
    
    def _createFaces(self):
        """
        XY faces are first, then XZ faces, then YZ faces
        """
        ## do the XY faces
        v1 = numerix.arange((self.nx + 1) * (self.ny))
        v1 = vector.prune(v1, self.nx + 1, self.nx)
        v1 = self._repeatWithOffset(v1, (self.nx + 1) * (self.ny + 1), self.nz + 1) 
        v2 = v1 + 1
        v3 = v1 + (self.nx + 2)
        v4 = v1 + (self.nx + 1)
        XYFaces = numerix.array((v1, v2, v3, v4))

        ## do the XZ faces
        v1 = numerix.arange((self.nx + 1) * (self.ny + 1))
        v1 = vector.prune(v1, self.nx + 1, self.nx)
        v1 = self._repeatWithOffset(v1, (self.nx + 1) * (self.ny + 1), self.nz)
        v2 = v1 + 1
        v3 = v1 + ((self.nx + 1)*(self.ny + 1)) + 1
        v4 = v1 + ((self.nx + 1)*(self.ny + 1))
        XZFaces = numerix.array((v1, v2, v3, v4))
        
        ## do the YZ faces
        v1 = numerix.arange((self.nx + 1) * self.ny)
        v1 = self._repeatWithOffset(v1, (self.nx + 1) * (self.ny + 1), self.nz)
        v2 = v1 + (self.nx + 1)
        v3 = v1 + ((self.nx + 1)*(self.ny + 1)) + (self.nx + 1)                                  
        v4 = v1 + ((self.nx + 1)*(self.ny + 1))
        YZFaces = numerix.array((v1, v2, v3, v4))

        ## reverse some of the face orientations to obtain the correct normals
        ##tmp = horizontalFaces.copy()
        ##horizontalFaces[:self.nx, 0] = tmp[:self.nx, 1]
        ##horizontalFaces[:self.nx, 1] = tmp[:self.nx, 0]
        ##tmp = verticalFaces.copy()
        ##verticalFaces[:, 0] = tmp[:, 1]
        ##verticalFaces[:, 1] = tmp[:, 0]
        ##verticalFaces[::(self.nx + 1), 0] = tmp[::(self.nx + 1), 0]
        ##verticalFaces[::(self.nx + 1), 1] = tmp[::(self.nx + 1), 1]

        self.numberOfXYFaces = (self.nx * self.ny * (self.nz + 1))
        self.numberOfXZFaces = (self.nx * (self.ny + 1) * self.nz)
        self.numberOfYZFaces = ((self.nx + 1) * self.ny * self.nz)
        self.numberOfFaces = self.numberOfXYFaces + self.numberOfXZFaces + self.numberOfYZFaces
        
        return numerix.concatenate((XYFaces, XZFaces, YZFaces), axis=1)
    
    def _createCells(self):
        """
        cells = (front face, back face, left face, right face, bottom face, top face)
        front and back faces are YZ faces
        left and right faces are XZ faces
        top and bottom faces are XY faces
        """
        self.numberOfCells = self.nx * self.ny * self.nz
        
        ## front and back faces
        frontFaces = numerix.arange(self.numberOfYZFaces)
        frontFaces = vector.prune(frontFaces, self.nx + 1, self.nx)
        frontFaces = frontFaces + self.numberOfXYFaces + self.numberOfXZFaces
        backFaces = frontFaces + 1

        ## left and right faces
        leftFaces = numerix.arange(self.nx * self.ny)
        leftFaces = self._repeatWithOffset(leftFaces, self.nx * (self.ny + 1), self.nz)
        leftFaces = numerix.ravel(leftFaces)
        leftFaces = leftFaces + self.numberOfXYFaces
        rightFaces = leftFaces + self.nx

        ## bottom and top faces
        bottomFaces = numerix.arange(self.nx * self.ny * self.nz)
        topFaces = bottomFaces + (self.nx * self.ny)

        return numerix.array((frontFaces, backFaces, leftFaces, rightFaces, bottomFaces, topFaces))
         
    def getScale(self):
        return self.scale['length']
        
    def getPhysicalShape(self):
        """Return physical dimensions of Grid3D.
        """
        return PhysicalField(value = (self.nx * self.dx * self.getScale(), self.ny * self.dy * self.getScale(), self.nz * self.dz * self.getScale()))

    def _getMeshSpacing(self):
        return numerix.array((self.dx, self.dy, self.dz))[...,numerix.newaxis]
    
    def getShape(self):
        return (self.nx, self.ny, self.nz)

    def _repeatWithOffset(self, array, offset, reps):
        a = numerix.fromfunction(lambda rnum, x: array + (offset * rnum), (reps, numerix.size(array))).astype('l')
        return numerix.ravel(a)

## The following method is broken when dx, dy or dz are not scalar. Simpler to use the generic
## _calcFaceAreas rather than do the required type checking, resizing and outer product.
##
##     def _calcFaceAreas(self):
##         XYFaceAreas = numerix.ones(self.numberOfXYFaces)
##         XYFaceAreas = XYFaceAreas * self.dx * self.dy
##         XZFaceAreas = numerix.ones(self.numberOfXZFaces)
##         XZFaceAreas = XZFaceAreas * self.dx * self.dz        
##         YZFaceAreas = numerix.ones(self.numberOfYZFaces)
##         YZFaceAreas = YZFaceAreas * self.dy * self.dz
##         self.faceAreas =  numerix.concatenate((XYFaceAreas, XZFaceAreas, YZFaceAreas))

    def _calcFaceNormals(self):
        XYFaceNormals = numerix.zeros((3, self.numberOfXYFaces))
        XYFaceNormals[2, (self.nx * self.ny):] = 1
        XYFaceNormals[2, :(self.nx * self.ny)] = -1
        XZFaceNormals = numerix.zeros((3, self.numberOfXZFaces))
        xzd = numerix.arange(self.numberOfXZFaces)
        xzd = xzd % (self.nx * (self.ny + 1))
        xzd = (xzd < self.nx)
        xzd = 1 - (2 * xzd)
        XZFaceNormals[1, :] = xzd
        YZFaceNormals = numerix.zeros((3, self.numberOfYZFaces))
        YZFaceNormals[0, :] = 1
        YZFaceNormals[0, ::self.nx + 1] = -1
        self.faceNormals = numerix.concatenate((XYFaceNormals, 
                                                XZFaceNormals, 
                                                YZFaceNormals), 
                                               axis=-1)
        
    def _calcFaceTangents(self):
        ## need to see whether order matters.
        faceTangents1 = numerix.zeros((3, self.numberOfFaces), 'd')
        faceTangents2 = numerix.zeros((3, self.numberOfFaces), 'd')
        ## XY faces
        faceTangents1[0, :self.numberOfXYFaces] = 1.
        faceTangents2[1, :self.numberOfXYFaces] = 1.
        ## XZ faces
        faceTangents1[0, self.numberOfXYFaces:self.numberOfXYFaces + self.numberOfXZFaces] = 1.
        faceTangents2[2, self.numberOfXYFaces:self.numberOfXYFaces + self.numberOfXZFaces] = 1.
        ## YZ faces
        faceTangents1[1, self.numberOfXYFaces + self.numberOfXZFaces:] = 1.
        faceTangents2[2, self.numberOfXYFaces + self.numberOfXZFaces:] = 1.
        self.faceTangents1 = faceTangents1
        self.faceTangents2 = faceTangents2

    def _calcHigherOrderScalings(self):
        self.scale['area'] = self.scale['length']**2
        self.scale['volume'] = self.scale['length']**3

    def _isOrthogonal(self):
        return True

    def _getGlobalNonOverlappingCellIDs(self):
        """
        Return the IDs of the local mesh in the context of the
        global parallel mesh. Does not include the IDs of boundary cells.
        
        .. note:: Trivial except for parallel meshes
        """
        return numerix.arange((self.offset[2] + self.overlap['front']) * self.nx * self.ny, 
                              (self.offset[2] + self.nz - self.overlap['back']) * self.nx * self.ny)

    def _getGlobalOverlappingCellIDs(self):
        """
        Return the IDs of the local mesh in the context of the
        global parallel mesh. Includes the IDs of boundary cells.
        
        .. note:: Trivial except for parallel meshes
        """
        
        return numerix.arange(self.offset[2] * self.nx * self.ny, (self.offset[2] + self.nz) * self.nx * self.ny)

    def _getLocalNonOverlappingCellIDs(self):
        """
        Return the IDs of the local mesh in isolation. 
        Does not include the IDs of boundary cells.
        
        .. note:: Trivial except for parallel meshes
        """
        return numerix.arange(self.overlap['front'] * self.nx * self.ny, 
                              (self.nz - self.overlap['back']) * self.nx * self.ny)

    def _getLocalOverlappingCellIDs(self):
        """
        Return the IDs of the local mesh in isolation. 
        Includes the IDs of boundary cells.
        
        .. note:: Trivial except for parallel meshes
        """
        return numerix.arange(0, self.ny * self.nx * self.nz)
       
## pickling

    def __getstate__(self):
        return self.args

    def __setstate__(self, dict):
        self.__init__(**dict)

    def _test(self):
        """
コード例 #30
0
 def _calcValue(self):
     P = self.P.numericValue
     alpha = numerix.where(P > 0., 1., 0.)
     return PhysicalField(value=alpha)
コード例 #31
0
ファイル: grid3D.py プロジェクト: calbaker/FiPy-2.1.3
    def __init__(self, dx = 1., dy = 1., dz = 1., nx = None, ny = None, nz = None, overlap=2, communicator=parallel):
        
        self.args = {
            'dx': dx, 
            'dy': dy,
            'dz' :dz,
            'nx': nx, 
            'ny': ny,
            'nz': nz,
            'overlap': overlap,
            'communicator': communicator
        }
        
        self.dx = PhysicalField(value = dx)
        scale = PhysicalField(value = 1, unit = self.dx.getUnit())
        self.dx /= scale
        
        nx = self._calcNumPts(d = self.dx, n = nx, axis = "x")
        
        self.dy = PhysicalField(value = dy)
        if self.dy.getUnit().isDimensionless():
            self.dy = dy
        else:
            self.dy /= scale

        ny = self._calcNumPts(d = self.dy, n = ny, axis = "y")
        
        self.dz = PhysicalField(value = dz)
        if self.dz.getUnit().isDimensionless():
            self.dz = dz
        else:
            self.dz /= scale
        
        nz = self._calcNumPts(d = self.dz, n = nz, axis = "z")

        (self.nx,
         self.ny,
         self.nz,
         self.overlap,
         self.offset) = self._calcParallelGridInfo(nx, ny, nz, overlap, communicator)

        if numerix.getShape(self.dx) is not ():
            Xoffset = numerix.sum(self.dx[0:self.offset[0]])
            self.dx = self.dx[self.offset[0]:self.offset[0] + self.nx]
        else:
            Xoffset = 0

        if numerix.getShape(self.dy) is not ():
            Yoffset =  numerix.sum(self.dy[0:self.offset[1]])
            self.dy = self.dy[self.offset[1]:self.offset[1] + self.ny]
        else:
            Yoffset = 0

        if numerix.getShape(self.dy) is not ():
            Zoffset =  numerix.sum(self.dz[0:self.offset[2]])
            self.dz = self.dz[self.offset[2]:self.offset[2] + self.nz]
        else:
            Zoffset = 0

        if self.nx == 0 or self.ny == 0 or self.nz == 0:
            self.nx = 0
            self.ny = 0
            self.nz = 0

        if self.nx == 0 or self.ny == 0 or self.nz == 0:
            self.numberOfHorizontalRows = 0
            self.numberOfVerticalColumns = 0
            self.numberOfLayersDeep = 0
        else:
            self.numberOfHorizontalRows = (self.ny + 1)
            self.numberOfVerticalColumns = (self.nx + 1)
            self.numberOfLayersDeep = (self.nz + 1)
            
        self.numberOfVertices = self.numberOfHorizontalRows * self.numberOfVerticalColumns * self.numberOfLayersDeep
        
        vertices = self._createVertices() + ((Xoffset,), (Yoffset,), (Zoffset,))
        faces = self._createFaces()
        cells = self._createCells()
        Mesh.__init__(self, vertices, faces, cells)
        
        self.setScale(value = scale)
コード例 #32
0
ファイル: grid1D.py プロジェクト: calbaker/FiPy-2.1.3
class Grid1D(Mesh1D):
    """
    Creates a 1D grid mesh.
    
        >>> mesh = Grid1D(nx = 3)
        >>> print mesh.getCellCenters()
        [[ 0.5  1.5  2.5]]
         
        >>> mesh = Grid1D(dx = (1, 2, 3))
        >>> print mesh.getCellCenters()
        [[ 0.5  2.   4.5]]
         
        >>> mesh = Grid1D(nx = 2, dx = (1, 2, 3))
        Traceback (most recent call last):
        ...
        IndexError: nx != len(dx)

    """
    def __init__(self, dx=1., nx=None, overlap=2, communicator=parallel):
        self.args = {
            'dx': dx, 
            'nx': nx, 
            'overlap': overlap
        }

        from fipy.tools.dimensions.physicalField import PhysicalField
        self.dx = PhysicalField(value=dx)
        scale = PhysicalField(value=1, unit=self.dx.getUnit())
        self.dx /= scale
        
        nx = self._calcNumPts(d=self.dx, n=nx)

        (self.nx,
         self.overlap,
         self.offset) = self._calcParallelGridInfo(nx, overlap, communicator)

        if numerix.getShape(self.dx) is not ():
            Xoffset = numerix.sum(self.dx[0:self.offset])
            self.dx = self.dx[self.offset:self.offset + self.nx]
        else:
            Xoffset = self.dx * self.offset
            
        vertices = self._createVertices() + ((Xoffset,),)
        self.numberOfVertices = len(vertices[0])
        faces = self._createFaces()
        self.numberOfFaces = len(faces[0])
        cells = self._createCells()
        Mesh1D.__init__(self, vertices, faces, cells, communicator=communicator)
        
        self.setScale(value = scale)

    def _getOverlap(self, overlap, procID, occupiedNodes):
        return {'left': overlap * (procID > 0) * (procID < occupiedNodes),
                'right': overlap * (procID < occupiedNodes - 1)}
        
    def _calcParallelGridInfo(self, nx, overlap, communicator):

        procID = communicator.procID
        Nproc = communicator.Nproc
        
        overlap = min(overlap, nx)
        cellsPerNode = max(int(nx / Nproc), overlap)
        occupiedNodes = min(int(nx / (cellsPerNode or 1)), Nproc)
            
        overlap = self._getOverlap(overlap, procID, occupiedNodes)

        offset = min(procID, occupiedNodes-1) * cellsPerNode - overlap['left']
        local_nx = cellsPerNode * (procID < occupiedNodes)
        if procID == occupiedNodes - 1:
            local_nx += (nx - cellsPerNode * occupiedNodes)
            
        local_nx = local_nx + overlap['left'] + overlap['right']

        self.globalNumberOfCells = nx
        self.globalNumberOfFaces = nx + 1
        
        return local_nx, overlap, offset

    def __repr__(self):
        dnstr = []
        for d, n in [("dx", "nx")]:
            dnstr.append(d + "=" + str(self.args[d]))
            if self.args[n] is not None:
                dnstr.append(n + "=" + str(self.args[n]))

        return "%s(%s)" % (self.__class__.__name__, ", ".join(dnstr))

    def _createVertices(self):
        x = self._calcVertexCoordinates(self.dx, self.nx)
        return x[numerix.newaxis,...]
    
    def _createFaces(self):
        if self.numberOfVertices == 1:
            return numerix.arange(0)[numerix.newaxis, ...]
        else:
            return numerix.arange(self.numberOfVertices)[numerix.newaxis, ...]

    def _createCells(self):
        """
        cells = (f1, f2) going left to right.
        f1 etc. refer to the faces
        """
        f1 = numerix.arange(self.nx)
        f2 = f1 + 1
        return numerix.array((f1, f2))

    def getDim(self):
        return 1
        
    def getScale(self):
        return self.scale['length']
        
    def getPhysicalShape(self):
        """Return physical dimensions of Grid1D.
        """
        from fipy.tools.dimensions.physicalField import PhysicalField
        return PhysicalField(value = (self.nx * self.dx * self.getScale(),))

    def _getMeshSpacing(self):
        return numerix.array((self.dx,))[...,numerix.newaxis]
    
    def getShape(self):
        return (self.nx,)
        
    def _getGlobalNonOverlappingCellIDs(self):
        """
        Return the IDs of the local mesh in the context of the
        global parallel mesh. Does not include the IDs of boundary cells.

        E.g., would return [0, 1] for mesh A

            A        B
        ------------------
        | 0 | 1 || 2 | 3 |
        ------------------
        
        .. note:: Trivial except for parallel meshes
        """

        return numerix.arange(self.offset + self.overlap['left'], 
                              self.offset + self.nx - self.overlap['right'])

    def _getGlobalOverlappingCellIDs(self):
        """
        Return the IDs of the local mesh in the context of the
        global parallel mesh. Includes the IDs of boundary cells.
        
        E.g., would return [0, 1, 2] for mesh A

            A        B
        ------------------
        | 0 | 1 || 2 | 3 |
        ------------------
        
        .. note:: Trivial except for parallel meshes
        """
        return numerix.arange(self.offset, self.offset + self.nx)

    def _getLocalNonOverlappingCellIDs(self):
        """
        Return the IDs of the local mesh in isolation. 
        Does not include the IDs of boundary cells.
        
        E.g., would return [0, 1] for mesh A

            A        B
        ------------------
        | 0 | 1 || 1 | 2 |
        ------------------
        
        .. note:: Trivial except for parallel meshes
        """
        return numerix.arange(self.overlap['left'], 
                              self.nx - self.overlap['right'])

    def _getLocalOverlappingCellIDs(self):
        """
        Return the IDs of the local mesh in isolation. 
        Includes the IDs of boundary cells.
        
        E.g., would return [0, 1, 2] for mesh A

            A        B
        ------------------
        | 0 | 1 || 2 |   |
        ------------------
        
        .. note:: Trivial except for parallel meshes
        """
        return numerix.arange(0, self.nx)

    def _getGlobalNonOverlappingFaceIDs(self):
        """
        Return the IDs of the local mesh in the context of the
        global parallel mesh. Does not include the IDs of boundary cells.

        E.g., would return [0, 1, 2] for mesh A

            A    ||   B
        ------------------
        0   1    2   3   4
        ------------------
        
        .. note:: Trivial except for parallel meshes
        """
        return numerix.arange(self.offset + self.overlap['left'], 
                              self.offset + self.numberOfFaces - self.overlap['right'])

    def _getGlobalOverlappingFaceIDs(self):
        """
        Return the IDs of the local mesh in the context of the
        global parallel mesh. Includes the IDs of boundary cells.
        
        E.g., would return [0, 1, 2, 3] for mesh A

            A    ||   B
        ------------------
        0   1    2   3   4
        ------------------
        
        .. note:: Trivial except for parallel meshes
        """
        return numerix.arange(self.offset, self.offset + self.numberOfFaces)

    def _getLocalNonOverlappingFaceIDs(self):
        """
        Return the IDs of the local mesh in isolation. 
        Does not include the IDs of boundary cells.
        
        E.g., would return [0, 1, 2] for mesh A

            A    ||   B
        ------------------
        0   1   2/1  2   3
        ------------------
        
        .. note:: Trivial except for parallel meshes
        """
        return numerix.arange(self.overlap['left'], 
                              self.numberOfFaces - self.overlap['right'])

    def _getLocalOverlappingFaceIDs(self):
        """
        Return the IDs of the local mesh in isolation. 
        Includes the IDs of boundary cells.
        
        E.g., would return [0, 1, 2, 3] for mesh A

            A   ||   B
        ------------------
        0   1   2   3    |
        ------------------
        
        .. note:: Trivial except for parallel meshes
        """
        return numerix.arange(0, self.numberOfFaces)

    
## pickling

    def __getstate__(self):
        return self.args
        
    def __setstate__(self, dict):
        self.__init__(**dict)

    def _test(self):
        """
コード例 #33
0
ファイル: uniformGrid1D.py プロジェクト: huahbo/FiPy-2.1.3
class UniformGrid1D(Grid1D):
    """
    Creates a 1D grid mesh.
    
        >>> mesh = UniformGrid1D(nx = 3)
        >>> print mesh.getCellCenters()
        [[ 0.5  1.5  2.5]]
         
    """

    def __init__(self, dx=1.0, nx=1, origin=(0,), overlap=2, communicator=parallel):
        origin = numerix.array(origin)

        self.args = {"dx": dx, "nx": nx, "origin": origin, "overlap": overlap}

        self.dim = 1

        self.dx = PhysicalField(value=dx)
        scale = PhysicalField(value=1, unit=self.dx.getUnit())
        self.dx /= scale

        nx = int(nx)

        (self.nx, self.overlap, self.offset) = self._calcParallelGridInfo(nx, overlap, communicator)

        self.origin = PhysicalField(value=origin)
        self.origin /= scale
        self.origin += self.offset * self.dx

        self.numberOfVertices = self.nx + 1
        if self.nx == 0:
            self.numberOfFaces = 0
        else:
            self.numberOfFaces = self.nx + 1
        self.numberOfCells = self.nx

        self.exteriorFaces = self.getFacesLeft() | self.getFacesRight()

        self.scale = {"length": 1.0, "area": 1.0, "volume": 1.0}

        self.setScale(value=scale)
        self.communicator = communicator

    def _translate(self, vector):
        return UniformGrid1D(
            dx=self.dx,
            nx=self.args["nx"],
            origin=self.args["origin"] + numerix.array(vector),
            overlap=self.args["overlap"],
        )

    def __mul__(self, factor):
        return UniformGrid1D(
            dx=self.dx * factor, nx=self.args["nx"], origin=self.args["origin"] * factor, overlap=self.args["overlap"]
        )

    def _getConcatenableMesh(self):
        from fipy.meshes.numMesh.mesh1D import Mesh1D

        return Mesh1D(
            vertexCoords=self.getVertexCoords(), faceVertexIDs=self._createFaces(), cellFaceIDs=self._createCells()
        )

    ##     get topology methods

    ##         from common/mesh

    def _getCellFaceIDs(self):
        return MA.array(self._createCells())

    def getInteriorFaces(self):
        from fipy.variables.faceVariable import FaceVariable

        interiorFaces = FaceVariable(mesh=self, value=False)
        interiorFaces[numerix.arange(self.numberOfFaces - 2) + 1] = True
        return interiorFaces

    def _getCellFaceOrientations(self):
        orientations = numerix.ones((2, self.numberOfCells))
        if self.numberOfCells > 0:
            orientations[0] *= -1
            orientations[0, 0] = 1
        return orientations

    def _getAdjacentCellIDs(self):
        c1 = numerix.arange(self.numberOfFaces)
        ids = numerix.array((c1 - 1, c1))
        if self.numberOfFaces > 0:
            ids[0, 0] = ids[1, 0]
            ids[1, -1] = ids[0, -1]
        return ids[0], ids[1]

    def _getCellToCellIDs(self):
        c1 = numerix.arange(self.numberOfCells)
        ids = MA.array((c1 - 1, c1 + 1))
        if self.numberOfCells > 0:
            ids[0, 0] = MA.masked
            ids[1, -1] = MA.masked
        return ids

    def _getCellToCellIDsFilled(self):
        ids = self._getCellToCellIDs().filled()
        if self.numberOfCells > 0:
            ids[0, 0] = 0
            ids[1, -1] = self.numberOfCells - 1
        return ids

    def _getMaxFacesPerCell(self):
        return 2

    ##         from numMesh/mesh

    def getVertexCoords(self):
        return self.getFaceCenters()

    def getFaceCellIDs(self):
        c1 = numerix.arange(self.numberOfFaces)
        ids = MA.array((c1 - 1, c1))
        if self.numberOfFaces > 0:
            ids[0, 0] = ids[1, 0]
            ids[1, 0] = MA.masked
            ids[1, -1] = MA.masked
        return ids

    ##     get geometry methods

    ##         from common/mesh

    def _getFaceAreas(self):
        return numerix.ones(self.numberOfFaces, "d")

    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

    def _getFaceCellToCellNormals(self):
        return self._getFaceNormals()

    def getCellVolumes(self):
        return numerix.ones(self.numberOfCells, "d") * self.dx

    def _getCellCenters(self):
        return ((numerix.arange(self.numberOfCells)[numerix.NewAxis, ...] + 0.5) * self.dx + self.origin) * self.scale[
            "length"
        ]

    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 _getFaceToCellDistanceRatio(self):
        distances = numerix.ones(self.numberOfFaces, "d")
        distances *= 0.5
        if len(distances) > 0:
            distances[0] = 1
            distances[-1] = 1
        return distances

    def _getOrientedAreaProjections(self):
        return self._getAreaProjections()

    def _getAreaProjections(self):
        return self._getFaceNormals()

    def _getOrientedFaceNormals(self):
        return self._getFaceNormals()

    def _getFaceTangents1(self):
        return numerix.zeros(self.numberOfFaces, "d")[numerix.NewAxis, ...]

    def _getFaceTangents2(self):
        return numerix.zeros(self.numberOfFaces, "d")[numerix.NewAxis, ...]

    def _getFaceAspectRatios(self):
        return 1.0 / self._getCellDistances()

    def _getCellToCellDistances(self):
        distances = MA.zeros((2, self.numberOfCells), "d")
        distances[:] = self.dx
        if self.numberOfCells > 0:
            distances[0, 0] = self.dx / 2.0
            distances[1, -1] = self.dx / 2.0
        return distances

    def _getCellNormals(self):
        normals = numerix.ones((1, 2, self.numberOfCells), "d")
        if self.numberOfCells > 0:
            normals[:, 0] = -1
        return normals

    def _getCellAreas(self):
        return numerix.ones((2, self.numberOfCells), "d")

    def _getCellAreaProjections(self):
        return MA.array(self._getCellNormals())

    ##         from numMesh/mesh

    def getFaceCenters(self):
        return numerix.arange(self.numberOfFaces)[numerix.NewAxis, ...] * self.dx + self.origin

    def _getCellVertexIDs(self):
        c1 = numerix.arange(self.numberOfCells)
        return numerix.array((c1 + 1, c1))

    ##     scaling

    def _calcScaledGeometry(self):
        pass

    def _getNearestCellID(self, points):
        """
        Test cases

           >>> from fipy import *
           >>> m = Grid1D(nx=3)
           >>> print m._getNearestCellID(([0., .9, 3.],))
           [0 0 2]
           >>> print m._getNearestCellID(([1.1],))
           [1]
           >>> m0 = Grid1D(nx=2, dx=1.)
           >>> m1 = Grid1D(nx=4, dx=.5)
           >>> print m0._getNearestCellID(m1.getCellCenters().getGlobalValue())
           [0 0 1 1]
           
        """
        nx = self.globalNumberOfCells

        if nx == 0:
            return numerix.arange(0)

        x0, = self.getCellCenters().getGlobalValue()[..., 0]
        xi, = points
        dx = self.dx

        i = numerix.array(numerix.rint(((xi - x0) / dx)), "l")
        i[i < 0] = 0
        i[i > nx - 1] = nx - 1

        return i

    def _test(self):
        """
コード例 #34
0
    def buildGridData(self,
                      ds,
                      ns,
                      overlap,
                      communicator,
                      cacheOccupiedNodes=False):
        """
        Build and save any information relevant to the construction of a grid.
        Generalized to handle any dimension. Has side-effects.
             
        Dimension specific functionality is built into `_buildOverlap` and
        `_packOffset`, which are overridden by children of this class. Often,
        this method is overridden (but always called) by children classes who
        must distinguish between uniform and non-uniform behavior.
             
        :Note: 
            - `spatialNums` is a list whose elements are analogous to
                * numberOfHorizontalRows
                * numberOfVerticalColumns
                * numberOfLayersDeep
              though `spatialNums` may be of length 1, 2, or 3 depending on
              dimensionality.
         
        :Parameters:
            - `ds` - A list containing grid spacing information, e.g. [dx, dy]
            - `ns` - A list containing number of grid points, e.g. [nx, ny, nz]
            - `overlap` 
        """

        dim = len(ns)

        newDs = []

        newdx = PhysicalField(value=ds[0])
        scale = PhysicalField(value=1, unit=newdx.unit)
        newdx /= scale

        newDs.append(newdx)

        for d in ds[1:]:  # for remaining ds
            newD = PhysicalField(value=d)

            if newD.unit.isDimensionless():
                if type(d) in [list, tuple]:
                    newD = numerix.array(d)
                else:
                    newD = d
            else:
                newD /= scale

            newDs.append(newD)

        newNs = self._calcNs(ns, newDs)

        globalNumCells = reduce(self._mult, newNs)
        globalNumFaces = self._calcGlobalNumFaces(newNs)
        """
        parallel stuff
        """

        newNs = list(newNs)

        procID = communicator.procID
        Nproc = communicator.Nproc

        overlap = min(overlap, newNs[-1])
        cellsPerNode = max(newNs[-1] // Nproc, overlap)
        occupiedNodes = min(newNs[-1] // (cellsPerNode or 1), Nproc)

        (firstOverlap, secOverlap,
         overlap) = self._buildOverlap(overlap, procID, occupiedNodes)

        offsetArg = min(procID,
                        occupiedNodes - 1) * cellsPerNode - firstOverlap
        offset = self._packOffset(offsetArg)
        """
        local nx, [ny, [nz]] calculation
        """
        local_n = cellsPerNode * (procID < occupiedNodes)

        if procID == occupiedNodes - 1:
            local_n += (newNs[-1] - cellsPerNode * occupiedNodes)

        local_n += firstOverlap + secOverlap

        newNs = tuple(newNs[:-1] + [local_n])
        """
        post-parallel
        """

        # "what is spatialNums?" -> see docstring
        if 0 in newNs:
            newNs = [0 for n in newNs]
            spatialNums = [0 for n in newNs]
        else:
            spatialNums = [n + 1 for n in newNs]

        spatialDict = dict(
            zip(["numVerticalCols", "numHorizontalRows",
                 "numLayersDeep"][:len(spatialNums)], spatialNums))

        numVertices = reduce(self._mult, spatialNums)
        numCells = reduce(self._mult, newNs)
        """
        Side-effects
        """
        self.dim = dim
        self.ds = newDs
        self.ns = newNs
        self.scale = scale

        self.globalNumberOfCells = globalNumCells
        self.globalNumberOfFaces = globalNumFaces

        self.offset = offset
        self.overlap = overlap

        self.spatialDict = spatialDict
        self.numberOfVertices = numVertices
        self.numberOfCells = numCells

        if cacheOccupiedNodes:
            self.occupiedNodes = occupiedNodes
コード例 #35
0
ファイル: skewedGrid2D.py プロジェクト: calbaker/FiPy-2.1.3
class SkewedGrid2D(Mesh2D):
    """
    Creates a 2D grid mesh with horizontal faces numbered first and then
    vertical faces.  The points are skewed by a random amount (between `rand`
    and `-rand`) in the X and Y directions.
    """
    def __init__(self, dx = 1., dy = 1., nx = None, ny = 1, rand = 0):
        self.nx = nx
        self.ny = ny
        
        self.dx = PhysicalField(value = dx)
        scale = PhysicalField(value = 1, unit = self.dx.getUnit())
        self.dx /= scale
        
        self.dy = PhysicalField(value = dy)
        if self.dy.getUnit().isDimensionless():
            self.dy = dy
        else:
            self.dy /= scale

        from fipy import Grid2D
        self.grid = Grid2D(nx=nx, ny=ny, dx=dx, dy=dy)

        self.numberOfVertices = self.grid._getNumberOfVertices()
        
        vertices = self.grid.getVertexCoords()

        changedVertices = numerix.zeros(vertices.shape, 'd')

        for i in range(len(vertices[0])):
            if((i % (nx+1)) != 0 and (i % (nx+1)) != nx and (i / nx+1) != 0 and (i / nx+1) != ny):
                changedVertices[0, i] = vertices[0, i] + (rand * ((random.random() * 2) - 1))
                changedVertices[1, i] = vertices[1, i] + (rand * ((random.random() * 2) - 1))
            else:
                changedVertices[0, i] = vertices[0, i]
                changedVertices[1, i] = vertices[1, i]


        faces = self.grid._getFaceVertexIDs()
        
        cells = self.grid._getCellFaceIDs()

        Mesh2D.__init__(self, changedVertices, faces, cells)
        
        self.setScale(value = scale)
            
    def getScale(self):
        return self.scale['length']
        
    def getPhysicalShape(self):
        """Return physical dimensions of Grid2D.
        """
        return PhysicalField(value = (self.nx * self.dx * self.getScale(), self.ny * self.dy * self.getScale()))

    def _getMeshSpacing(self):
        return numerix.array((self.dx,self.dy))[...,numerix.newaxis]
    
    def getShape(self):
        return (self.nx, self.ny)
    
## pickling

    def __getstate__(self):
        return {
            'dx' : self.dx * self.scale['length'],
            'dy' : self.dy * self.scale['length'],
            'nx' : self.nx,
            'ny' : self.ny
        }

    def __setstate__(self, dict):
        self.__init__(**dict)