Beispiel #1
0
    def map_call(self, expr):
        arg, = expr.parameters
        rec_arg = self.rec(arg)

        if isinstance(rec_arg, np.ndarray) and self.is_kind_matrix(rec_arg):
            raise RuntimeError("expression is nonlinear in variable")

        from numbers import Number
        if isinstance(rec_arg, Number):
            return getattr(np, expr.function.name)(rec_arg)
        else:
            rec_arg = unflatten_from_numpy(self.array_context, None, rec_arg)
            result = getattr(self.array_context.np,
                             expr.function.name)(rec_arg)
            return flatten_to_numpy(self.array_context, result)
Beispiel #2
0
def plot_partition_indices(actx, discr, indices, **kwargs):
    try:
        import matplotlib.pyplot as pt
    except ImportError:
        return

    indices = indices.get(actx.queue)
    args = [
        kwargs.get("tree_kind", "linear").replace("-", "_"),
        kwargs.get("discr_stage", "stage1"), discr.ambient_dim
    ]

    pt.figure(figsize=(10, 8), dpi=300)
    pt.plot(np.diff(indices.ranges))
    pt.savefig("test_partition_{1}_{3}d_ranges_{2}.png".format(*args))
    pt.clf()

    from pytential.utils import flatten_to_numpy
    if discr.ambient_dim == 2:
        sources = flatten_to_numpy(actx, discr.nodes())

        pt.figure(figsize=(10, 8), dpi=300)
        if indices.indices.shape[0] != discr.ndofs:
            pt.plot(sources[0], sources[1], 'ko', alpha=0.5)

        for i in range(indices.nblocks):
            isrc = indices.block_indices(i)
            pt.plot(sources[0][isrc], sources[1][isrc], 'o')

        pt.xlim([-1.5, 1.5])
        pt.ylim([-1.5, 1.5])
        pt.savefig("test_partition_{1}_{3}d_{2}.png".format(*args))
        pt.clf()
    elif discr.ambient_dim == 3:
        from meshmode.discretization.visualization import make_visualizer
        marker = -42.0 * np.ones(discr.ndofs)

        for i in range(indices.nblocks):
            isrc = indices.block_indices(i)
            marker[isrc] = 10.0 * (i + 1.0)

        from meshmode.dof_array import unflatten
        marker = unflatten(actx, discr, actx.from_numpy(marker))

        vis = make_visualizer(actx, discr, 10)

        filename = "test_partition_{0}_{1}_{3}d_{2}.vtu".format(*args)
        vis.write_vtk_file(filename, [("marker", marker)])
Beispiel #3
0
    def map_interpolation(self, expr):
        from pytential import sym

        if expr.to_dd.discr_stage != sym.QBX_SOURCE_QUAD_STAGE2:
            raise RuntimeError(
                "can only interpolate to QBX_SOURCE_QUAD_STAGE2")
        operand = self.rec(expr.operand)
        actx = self.array_context

        if isinstance(operand, (int, float, complex, np.number)):
            return operand
        elif isinstance(operand, np.ndarray) and operand.ndim == 1:
            conn = self.places.get_connection(expr.from_dd, expr.to_dd)
            discr = self.places.get_discretization(expr.from_dd.geometry,
                                                   expr.from_dd.discr_stage)

            operand = unflatten_from_numpy(actx, discr, operand)
            return flatten_to_numpy(actx, conn(operand))
        elif isinstance(operand, np.ndarray) and operand.ndim == 2:
            cache = self.places._get_cache("direct_resampler")
            key = (expr.from_dd.geometry, expr.from_dd.discr_stage,
                   expr.to_dd.discr_stage)

            try:
                mat = cache[key]
            except KeyError:
                from meshmode.discretization.connection import \
                    flatten_chained_connection

                conn = self.places.get_connection(expr.from_dd, expr.to_dd)
                conn = flatten_chained_connection(actx, conn)
                mat = actx.to_numpy(conn.full_resample_matrix(actx))

                # FIXME: the resample matrix is slow to compute and very big
                # to store, so caching it may not be the best idea
                cache[key] = mat

            return mat.dot(operand)
        else:
            raise RuntimeError("unknown operand type: {}".format(
                type(operand)))
Beispiel #4
0
    def map_num_reference_derivative(self, expr):
        from pytential import bind, sym
        rec_operand = self.rec(expr.operand)

        assert isinstance(rec_operand, np.ndarray)
        if self.is_kind_matrix(rec_operand):
            raise NotImplementedError("derivatives")

        dofdesc = expr.dofdesc
        op = sym.NumReferenceDerivative(ref_axes=expr.ref_axes,
                                        operand=sym.var("u"),
                                        dofdesc=dofdesc)

        discr = self.places.get_discretization(dofdesc.geometry,
                                               dofdesc.discr_stage)
        rec_operand = unflatten_from_numpy(self.array_context, discr,
                                           rec_operand)

        return flatten_to_numpy(
            self.array_context,
            bind(self.places, op)(self.array_context, u=rec_operand))
Beispiel #5
0
def main(curve_fn=starfish, visualize=True):
    import logging
    logging.basicConfig(level=logging.WARNING)  # INFO for more progress info

    cl_ctx = cl.create_some_context()
    queue = cl.CommandQueue(cl_ctx)

    from meshmode.mesh.generation import make_curve_mesh
    mesh = make_curve_mesh(
            curve_fn,
            np.linspace(0, 1, nelements+1),
            target_order)

    from pytential.qbx import QBXLayerPotentialSource
    from meshmode.array_context import PyOpenCLArrayContext
    from meshmode.discretization import Discretization
    from meshmode.discretization.poly_element import \
            InterpolatoryQuadratureSimplexGroupFactory

    actx = PyOpenCLArrayContext(queue)

    pre_density_discr = Discretization(
            actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order))

    qbx = QBXLayerPotentialSource(pre_density_discr, 4*target_order, qbx_order,
            fmm_order=qbx_order+3,
            target_association_tolerance=0.005)

    from pytential.target import PointsTarget
    fplot = FieldPlotter(np.zeros(2), extent=5, npoints=1000)
    targets_dev = cl.array.to_device(queue, fplot.points)

    from pytential import GeometryCollection
    places = GeometryCollection({
        "qbx": qbx,
        "targets": PointsTarget(targets_dev),
        }, auto_where="qbx")

    density_discr = places.get_discretization("qbx")

    from meshmode.dof_array import thaw
    nodes = thaw(actx, density_discr.nodes())
    angle = actx.np.arctan2(nodes[1], nodes[0])

    if k:
        kernel = HelmholtzKernel(2)
        kernel_kwargs = {"k": sym.var("k")}
    else:
        kernel = LaplaceKernel(2)
        kernel_kwargs = {}

    def op(**kwargs):
        kwargs.update(kernel_kwargs)

        #op = sym.d_dx(sym.S(kernel, sym.var("sigma"), **kwargs))
        return sym.D(kernel, sym.var("sigma"), **kwargs)
        #op = sym.S(kernel, sym.var("sigma"), qbx_forced_limit=None, **kwargs)

    sigma = actx.np.cos(mode_nr*angle)
    if 0:
        from meshmode.dof_array import flatten, unflatten
        sigma = flatten(0 * angle)
        from random import randrange
        for i in range(5):
            sigma[randrange(len(sigma))] = 1
        sigma = unflatten(actx, density_discr, sigma)

    if isinstance(kernel, HelmholtzKernel):
        for i, elem in np.ndenumerate(sigma):
            sigma[i] = elem.astype(np.complex128)

    bound_bdry_op = bind(places, op())
    if visualize:
        fld_in_vol = actx.to_numpy(
                bind(places, op(
                    source="qbx",
                    target="targets",
                    qbx_forced_limit=None))(actx, sigma=sigma, k=k))

        if enable_mayavi:
            fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5)
        else:
            fplot.write_vtk_file("layerpot-potential.vts", [
                ("potential", fld_in_vol)
                ])

    if 0:
        apply_op = bound_bdry_op.scipy_op(actx, "sigma", np.float64, k=k)
        from sumpy.tools import build_matrix
        mat = build_matrix(apply_op)

        import matplotlib.pyplot as pt
        pt.imshow(mat)
        pt.colorbar()
        pt.show()

    if enable_mayavi:
        # {{{ plot boundary field

        from pytential.utils import flatten_to_numpy

        fld_on_bdry = flatten_to_numpy(
                actx, bound_bdry_op(actx, sigma=sigma, k=k))
        nodes_host = flatten_to_numpy(actx, density_discr.nodes())

        mlab.points3d(nodes_host[0], nodes_host[1],
                fld_on_bdry.real, scale_factor=0.03)

        mlab.colorbar()
        mlab.show()
Beispiel #6
0
        r = la.norm(proxies[:, ipxy] - pxycenters[:, i].reshape(-1, 1), axis=0)
        assert np.allclose(r - pxyradii[i], 0.0, atol=1.0e-14)

    # }}}

    # {{{ visualization

    srcindices = srcindices.get(queue)
    if visualize:
        ambient_dim = places.ambient_dim
        if ambient_dim == 2:
            import matplotlib.pyplot as pt

            from pytential.utils import flatten_to_numpy
            density_nodes = np.vstack(
                flatten_to_numpy(actx, density_discr.nodes()))
            ci = bind(places, sym.expansion_centers(ambient_dim, -1))(actx)
            ci = np.vstack(flatten_to_numpy(actx, ci))
            ce = bind(places, sym.expansion_centers(ambient_dim, +1))(actx)
            ce = np.vstack(flatten_to_numpy(actx, ce))
            r = bind(places, sym.expansion_radii(ambient_dim))(actx)
            r = flatten_to_numpy(actx, r)

            for i in range(srcindices.nblocks):
                isrc = srcindices.block_indices(i)
                ipxy = np.s_[pxyranges[i]:pxyranges[i + 1]]

                pt.figure(figsize=(10, 8))
                axis = pt.gca()
                for j in isrc:
                    c = pt.Circle(ci[:, j], r[j], color='k', alpha=0.1)
Beispiel #7
0
def gather_block_neighbor_points(actx, discr, indices, pxycenters, pxyradii,
        max_nodes_in_box=None):
    """Generate a set of neighboring points for each range of points in
    *discr*. Neighboring points of a range :math:`i` are defined
    as all the points inside the proxy ball :math:`i` that do not also
    belong to the range itself.

    :arg discr: a :class:`meshmode.discretization.Discretization`.
    :arg indices: a :class:`sumpy.tools.BlockIndexRanges`.
    :arg pxycenters: an array containing the center of each proxy ball.
    :arg pxyradii: an array containing the radius of each proxy ball.

    :return: a :class:`sumpy.tools.BlockIndexRanges`.
    """

    if max_nodes_in_box is None:
        # FIXME: this is a fairly arbitrary value
        max_nodes_in_box = 32

    indices = indices.get(actx.queue)

    # NOTE: this is constructed for multiple reasons:
    #   * TreeBuilder takes object arrays
    #   * `srcindices` can be a small subset of nodes, so this will save
    #   some work
    #   * `srcindices` may reorder the array returned by nodes(), so this
    #   makes sure that we have the same order in tree.user_source_ids
    #   and friends
    from pytential.utils import flatten_to_numpy
    sources = flatten_to_numpy(actx, discr.nodes())
    sources = make_obj_array([
        actx.from_numpy(sources[idim][indices.indices])
        for idim in range(discr.ambient_dim)])

    # construct tree
    from boxtree import TreeBuilder
    builder = TreeBuilder(actx.context)
    tree, _ = builder(actx.queue, sources,
            max_particles_in_box=max_nodes_in_box)

    from boxtree.area_query import AreaQueryBuilder
    builder = AreaQueryBuilder(actx.context)
    query, _ = builder(actx.queue, tree, pxycenters, pxyradii)

    # find nodes inside each proxy ball
    tree = tree.get(actx.queue)
    query = query.get(actx.queue)

    pxycenters = np.vstack([
        actx.to_numpy(pxycenters[idim])
        for idim in range(discr.ambient_dim)
        ])
    pxyradii = actx.to_numpy(pxyradii)

    nbrindices = np.empty(indices.nblocks, dtype=np.object)
    for iproxy in range(indices.nblocks):
        # get list of boxes intersecting the current ball
        istart = query.leaves_near_ball_starts[iproxy]
        iend = query.leaves_near_ball_starts[iproxy + 1]
        iboxes = query.leaves_near_ball_lists[istart:iend]

        # get nodes inside the boxes
        istart = tree.box_source_starts[iboxes]
        iend = istart + tree.box_source_counts_cumul[iboxes]
        isources = np.hstack([np.arange(s, e)
                              for s, e in zip(istart, iend)])
        nodes = np.vstack([tree.sources[idim][isources]
                           for idim in range(discr.ambient_dim)])
        isources = tree.user_source_ids[isources]

        # get nodes inside the ball but outside the current range
        center = pxycenters[:, iproxy].reshape(-1, 1)
        radius = pxyradii[iproxy]
        mask = ((la.norm(nodes - center, axis=0) < radius)
                & ((isources < indices.ranges[iproxy])
                    | (indices.ranges[iproxy + 1] <= isources)))

        nbrindices[iproxy] = indices.indices[isources[mask]]

    nbrranges = actx.from_numpy(np.cumsum([0] + [n.shape[0] for n in nbrindices]))
    nbrindices = actx.from_numpy(np.hstack(nbrindices))

    return BlockIndexRanges(actx.context,
            actx.freeze(nbrindices), actx.freeze(nbrranges))
Beispiel #8
0
    def __call__(self, actx, source_dd, indices, **kwargs):
        """Generate proxy points for each given range of source points in
        the discretization in *source_dd*.

        :arg actx: a :class:`~meshmode.array_context.ArrayContext`.
        :arg source_dd: a :class:`~pytential.symbolic.primitives.DOFDescriptor`
            for the discretization on which the proxy points are to be
            generated.
        :arg indices: a :class:`sumpy.tools.BlockIndexRanges`.

        :return: a tuple of ``(proxies, pxyranges, pxycenters, pxyranges)``,
            where each element is a :class:`pyopencl.array.Array`. The
            sizes of the arrays are as follows: ``pxycenters`` is of size
            ``(2, nranges)``, ``pxyradii`` is of size ``(nranges,)``,
            ``pxyranges`` is of size ``(nranges + 1,)`` and ``proxies`` is
            of size ``(2, nranges * nproxy)``. The proxy points in a range
            :math:`i` can be obtained by a slice
            ``proxies[pxyranges[i]:pxyranges[i + 1]]`` and are all at a
            distance ``pxyradii[i]`` from the range center ``pxycenters[i]``.
        """

        def _affine_map(v, A, b):
            return np.dot(A, v) + b

        from pytential import bind, sym
        source_dd = sym.as_dofdesc(source_dd)
        discr = self.places.get_discretization(
                source_dd.geometry, source_dd.discr_stage)

        radii = bind(self.places, sym.expansion_radii(
            self.ambient_dim, dofdesc=source_dd))(actx)
        center_int = bind(self.places, sym.expansion_centers(
            self.ambient_dim, -1, dofdesc=source_dd))(actx)
        center_ext = bind(self.places, sym.expansion_centers(
            self.ambient_dim, +1, dofdesc=source_dd))(actx)

        from meshmode.dof_array import flatten, thaw
        knl = self.get_kernel()
        _, (centers_dev, radii_dev,) = knl(actx.queue,
            sources=flatten(thaw(actx, discr.nodes())),
            center_int=flatten(center_int),
            center_ext=flatten(center_ext),
            expansion_radii=flatten(radii),
            srcindices=indices.indices,
            srcranges=indices.ranges, **kwargs)

        from pytential.utils import flatten_to_numpy
        centers = flatten_to_numpy(actx, centers_dev)
        radii = flatten_to_numpy(actx, radii_dev)
        proxies = np.empty(indices.nblocks, dtype=np.object)
        for i in range(indices.nblocks):
            proxies[i] = _affine_map(self.ref_points,
                    A=(radii[i] * np.eye(self.ambient_dim)),
                    b=centers[:, i].reshape(-1, 1))

        pxyranges = actx.from_numpy(np.arange(
            0,
            proxies.shape[0] * proxies[0].shape[1] + 1,
            proxies[0].shape[1],
            dtype=indices.ranges.dtype))
        proxies = make_obj_array([
            actx.freeze(actx.from_numpy(np.hstack([p[idim] for p in proxies])))
            for idim in range(self.ambient_dim)
            ])
        centers = make_obj_array([
            actx.freeze(centers_dev[idim])
            for idim in range(self.ambient_dim)
            ])

        assert pxyranges[-1] == proxies[0].shape[0]
        return proxies, actx.freeze(pxyranges), centers, actx.freeze(radii_dev)
Beispiel #9
0
 def map_node_coordinate_component(self, expr):
     from pytential import bind, sym
     op = sym.NodeCoordinateComponent(expr.ambient_axis,
                                      dofdesc=expr.dofdesc)
     return flatten_to_numpy(self.array_context,
                             bind(self.places, op)(self.array_context))
Beispiel #10
0
    # }}}

    # {{{ plot geometry

    if visualize and ambient_dim == 2:
        try:
            import matplotlib.pyplot as pt
        except ImportError:
            visualize = False

    if visualize:
        normals = bind(places, sym.normal(ambient_dim).as_vector())(actx)

        # show geometry, centers, normals
        if ambient_dim == 2:
            nodes = flatten_to_numpy(actx, density_discr.nodes())
            normals = flatten_to_numpy(actx, normals)

            pt.plot(nodes[0], nodes[1], "x-")
            pt.quiver(nodes[0], nodes[1], normals[0], normals[1])
            pt.gca().set_aspect("equal")
            pt.savefig(f"pre-solve-source-{resolution}", dpi=300)
        elif ambient_dim == 3:
            bdry_vis = make_visualizer(actx, density_discr, case.target_order + 3)
            bdry_vis.write_vtk_file(f"pre-solve-source-{resolution}.vtu", [
                ("normals", normals),
                ])
        else:
            raise ValueError("invalid mesh dim")

    # }}}