Пример #1
0
    def putdefault(self, grid):
        """
        Derive a key ``K`` from the :class:`Grid` ``grid``; if ``K`` in ``self``,
        return the existing :class:`YaskContext` ``self[K]``, otherwise create a
        new context ``C``, set ``self[K] = C`` and return ``C``.
        """
        assert grid is not None

        key = self._getkey(grid, grid.dtype)

        # Does a YaskContext exist already corresponding to this key?
        if key in self:
            return self[key]

        # Functions declared with explicit dimensions (i.e., with no Grid) must be
        # able to retrieve the right context
        partial_keys = [
            self._getkey(None, grid.dtype, i) for i in powerset(key[-1])
        ]
        if any(i in self._partial_map for i in partial_keys if i[2]):
            warning(
                "Non-unique Dimensions found in different contexts; dumping "
                "all known contexts. Perhaps you're attempting to use multiple "
                "Grids, and some of them share identical Dimensions? ")
            self.dump()

        # Create a new YaskContext
        context = YaskContext('ctx%d' % self._ncontexts, grid)
        self._ncontexts += 1

        self[key] = context
        self._partial_map.update({i: context for i in partial_keys})

        log("Context successfully created!")
def guard(clusters):
    """
    Return a new :class:`ClusterGroup` including new :class:`PartialCluster`s
    for each conditional expression encountered in ``clusters``.
    """
    processed = ClusterGroup()
    for c in clusters:
        # Find out what expressions in /c/ should be guarded
        mapper = {}
        for e in c.exprs:
            for k, v in e.ispace.sub_iterators.items():
                for i in v:
                    if i.dim.is_Conditional:
                        mapper.setdefault(i.dim, []).append(e)

        # Build conditional expressions to guard clusters
        conditions = {d: CondEq(d.parent % d.factor, 0) for d in mapper}
        negated = {d: CondNe(d.parent % d.factor, 0) for d in mapper}

        # Expand with guarded clusters
        combs = list(powerset(mapper))
        for dims, ndims in zip(combs, reversed(combs)):
            banned = flatten(v for k, v in mapper.items() if k not in dims)
            exprs = [
                e.xreplace({i: IntDiv(i.parent, i.factor)
                            for i in mapper}) for e in c.exprs
                if e not in banned
            ]
            guards = [(i.parent, conditions[i]) for i in dims]
            guards.extend([(i.parent, negated[i]) for i in ndims])
            cluster = PartialCluster(exprs, c.ispace, c.dspace, c.atomics,
                                     dict(guards))
            processed.append(cluster)

    return processed
Пример #3
0
    def putdefault(self, grid):
        """
        Derive a unique key ``K`` from a Grid`; if ``K`` is in ``self``,
        return the pre-existing YaskContext ``self[K]``, otherwise create a
        new context ``C``, set ``self[K] = C`` and return ``C``.
        """
        assert grid is not None

        key = self._getkey(grid, grid.dtype)

        # Does a YaskContext exist already corresponding to this key?
        if key in self:
            return self[key]

        # Functions declared with explicit dimensions (i.e., with no Grid) must be
        # able to retrieve the right context
        partial_keys = [self._getkey(None, grid.dtype, i) for i in powerset(key[-1])]
        if any(i in self._partial_map for i in partial_keys if i[2]):
            warning("Non-unique Dimensions found in different contexts; dumping "
                    "all known contexts. Perhaps you're attempting to use multiple "
                    "Grids, and some of them share identical Dimensions? ")
            self.dump()

        # Create a new YaskContext
        context = YaskContext('ctx%d' % self._ncontexts, grid)
        self._ncontexts += 1

        self[key] = context
        self._partial_map.update({i: context for i in partial_keys})

        log("Context successfully created!")
Пример #4
0
    def _interpolation_coeffs(self):
        """
        Symbolic expression for the coefficients for sparse point interpolation
        according to:

            https://en.wikipedia.org/wiki/Bilinear_interpolation.

        Returns
        -------
        Matrix of coefficient expressions.
        """
        # Grid indices corresponding to the corners of the cell ie x1, y1, z1
        indices1 = tuple(
            sympy.symbols('%s1' % d) for d in self.grid.dimensions)
        indices2 = tuple(
            sympy.symbols('%s2' % d) for d in self.grid.dimensions)
        # 1, x1, y1, z1, x1*y1, ...
        indices = list(powerset(indices1))
        indices[0] = (1, )
        point_sym = list(powerset(self._point_symbols))
        point_sym[0] = (1, )
        # 1, px. py, pz, px*py, ...
        A = []
        ref_A = [np.prod(ind) for ind in indices]
        # Create the matrix with the same increment order as the point increment
        for i in self._point_increments:
            # substitute x1 by x2 if increment in that dimension
            subs = dict(
                (indices1[d], indices2[d] if i[d] == 1 else indices1[d])
                for d in range(len(i)))
            A += [[1] + [a.subs(subs) for a in ref_A[1:]]]

        A = sympy.Matrix(A)
        # Coordinate values of the sparse point
        p = sympy.Matrix([[np.prod(ind)] for ind in point_sym])

        # reference cell x1:0, x2:h_x
        left = dict((a, 0) for a in indices1)
        right = dict(
            (b, dim.spacing) for b, dim in zip(indices2, self.grid.dimensions))
        reference_cell = {**left, **right}
        # Substitute in interpolation matrix
        A = A.subs(reference_cell)
        return A.inv().T * p
Пример #5
0
def test_indices(ndim):
    """
    Test that inidces are shifted by half a grid point for staggered Function
    """
    grid = Grid(tuple([10] * ndim))
    dims = grid.dimensions
    for d in list(powerset(dims))[1:]:
        f = Function(name="f", grid=grid, staggered=d)
        for dd in d:
            assert f.indices_ref[dd] == dd + dd.spacing / 2
Пример #6
0
    def _interpolation_coeffs(self):
        """
        Symbolic expression for the coefficients for sparse point interpolation
        according to:

            https://en.wikipedia.org/wiki/Bilinear_interpolation.

        Returns
        -------
        Matrix of coefficient expressions.
        """
        # Grid indices corresponding to the corners of the cell ie x1, y1, z1
        indices1 = tuple(sympy.symbols('%s1' % d) for d in self.grid.dimensions)
        indices2 = tuple(sympy.symbols('%s2' % d) for d in self.grid.dimensions)
        # 1, x1, y1, z1, x1*y1, ...
        indices = list(powerset(indices1))
        indices[0] = (1,)
        point_sym = list(powerset(self._point_symbols))
        point_sym[0] = (1,)
        # 1, px. py, pz, px*py, ...
        A = []
        ref_A = [np.prod(ind) for ind in indices]
        # Create the matrix with the same increment order as the point increment
        for i in self._point_increments:
            # substitute x1 by x2 if increment in that dimension
            subs = dict((indices1[d], indices2[d] if i[d] == 1 else indices1[d])
                        for d in range(len(i)))
            A += [[1] + [a.subs(subs) for a in ref_A[1:]]]

        A = sympy.Matrix(A)
        # Coordinate values of the sparse point
        p = sympy.Matrix([[np.prod(ind)] for ind in point_sym])

        # reference cell x1:0, x2:h_x
        left = dict((a, 0) for a in indices1)
        right = dict((b, dim.spacing) for b, dim in zip(indices2, self.grid.dimensions))
        reference_cell = {**left, **right}
        # Substitute in interpolation matrix
        A = A.subs(reference_cell)
        return A.inv().T * p
Пример #7
0
def test_is_param(ndim):
    """
    Test that only parameter are evaluated at the variable anf Function and FD indices
    stay unchanged
    """
    grid = Grid(tuple([10] * ndim))
    dims = list(powerset(grid.dimensions))[1:]
    var = Function(name="f", grid=grid, staggered=NODE)
    for d in dims:
        f = Function(name="f", grid=grid, staggered=d)
        f2 = Function(name="f2", grid=grid, staggered=d, parameter=True)

        # Not a parameter stay untouched (or FD would be destroyed by _eval_at)
        assert f._eval_at(var).evaluate == f
        # Parameter, automatic averaging
        avg = f2
        for dd in d:
            avg = .5 * (avg + avg.subs({dd: dd - dd.spacing}))
        assert f2._eval_at(var).evaluate == avg
Пример #8
0
def test_avg(ndim):
    """
    Test automatic averaging of Function at undefined grid points
    """
    grid = Grid(tuple([10] * ndim))
    dims = list(powerset(grid.dimensions))[1:]
    for d in dims:
        f = Function(name="f", grid=grid, staggered=d)
        # f at nod (x, y, z)
        shifted = f
        for dd in d:
            shifted = shifted.subs({dd: dd - dd.spacing / 2})
        assert all(i == dd for i, dd in zip(shifted.indices, grid.dimensions))
        # Average automatically i.e.:
        # f not defined at x so f(x, y) = 0.5*f(x - h_x/2, y) + 0.5*f(x + h_x/2, y)
        avg = f
        for dd in d:
            avg = .5 * (avg + avg.subs({dd: dd - dd.spacing}))
        assert shifted.evaluate == avg