Ejemplo n.º 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
Ejemplo n.º 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
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
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))
Ejemplo n.º 5
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
Ejemplo n.º 6
0
    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
Ejemplo n.º 7
0
    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
Ejemplo n.º 8
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
Ejemplo n.º 9
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
Ejemplo n.º 10
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()
Ejemplo n.º 11
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)
Ejemplo n.º 12
0
 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
Ejemplo n.º 13
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
Ejemplo n.º 14
0
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
Ejemplo n.º 15
0
 def _getPointToCellDistances(self, point):
     tmp = self.cellCenters - PhysicalField(point)
     return numerix.sqrtDot(tmp, tmp)
Ejemplo n.º 16
0
 def _calcValue(self):
     P = self.P.numericValue
     alpha = numerix.where(P > 0., 1., 0.)
     return PhysicalField(value=alpha)
Ejemplo n.º 17
0
 def physicalShape(self):
     """Return physical dimensions of Grid2D.
     """
     return PhysicalField(value=(self.nx * self.dx * self.scale,
                                 self.ny * self.dy * self.scale))