def test_interpolation(actx_factory, name, source_discr_stage, target_granularity):
    actx = actx_factory()

    nelements = 32
    target_order = 7
    qbx_order = 4

    where = sym.as_dofdesc("test_interpolation")
    from_dd = sym.DOFDescriptor(
            geometry=where.geometry,
            discr_stage=source_discr_stage,
            granularity=sym.GRANULARITY_NODE)
    to_dd = sym.DOFDescriptor(
            geometry=where.geometry,
            discr_stage=sym.QBX_SOURCE_QUAD_STAGE2,
            granularity=target_granularity)

    mesh = mgen.make_curve_mesh(mgen.starfish,
            np.linspace(0.0, 1.0, nelements + 1),
            target_order)
    discr = Discretization(actx, mesh,
            InterpolatoryQuadratureSimplexGroupFactory(target_order))

    from pytential.qbx import QBXLayerPotentialSource
    qbx = QBXLayerPotentialSource(discr,
            fine_order=4 * target_order,
            qbx_order=qbx_order,
            fmm_order=False)

    from pytential import GeometryCollection
    places = GeometryCollection(qbx, auto_where=where)

    sigma_sym = sym.var("sigma")
    op_sym = sym.sin(sym.interp(from_dd, to_dd, sigma_sym))
    bound_op = bind(places, op_sym, auto_where=where)

    def discr_and_nodes(stage):
        density_discr = places.get_discretization(where.geometry, stage)
        return density_discr, actx.to_numpy(
                flatten(density_discr.nodes(), actx)
                ).reshape(density_discr.ambient_dim, -1)

    _, target_nodes = discr_and_nodes(sym.QBX_SOURCE_QUAD_STAGE2)
    source_discr, source_nodes = discr_and_nodes(source_discr_stage)

    sigma_target = np.sin(la.norm(target_nodes, axis=0))
    sigma_dev = unflatten(
            thaw(source_discr.nodes()[0], actx),
            actx.from_numpy(la.norm(source_nodes, axis=0)), actx)
    sigma_target_interp = actx.to_numpy(
            flatten(bound_op(actx, sigma=sigma_dev), actx)
            )

    if name in ("default", "default_explicit", "stage2", "quad"):
        error = la.norm(sigma_target_interp - sigma_target) / la.norm(sigma_target)
        assert error < 1.0e-10
    elif name in ("stage2_center",):
        assert len(sigma_target_interp) == 2 * len(sigma_target)
    else:
        raise ValueError(f"unknown test case name: {name}")
Exemple #2
0
def test_interpolation(ctx_factory, name, source_discr_stage,
                       target_granularity):
    ctx = ctx_factory()
    queue = cl.CommandQueue(ctx)

    nelements = 32
    target_order = 7
    qbx_order = 4

    mesh = make_curve_mesh(starfish, np.linspace(0.0, 1.0, nelements + 1),
                           target_order)
    discr = Discretization(
        ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order))

    from pytential.qbx import QBXLayerPotentialSource
    qbx, _ = QBXLayerPotentialSource(discr,
                                     fine_order=4 * target_order,
                                     qbx_order=qbx_order,
                                     fmm_order=False).with_refinement()

    where = 'test-interpolation'
    from_dd = sym.DOFDescriptor(geometry=where,
                                discr_stage=source_discr_stage,
                                granularity=sym.GRANULARITY_NODE)
    to_dd = sym.DOFDescriptor(geometry=where,
                              discr_stage=sym.QBX_SOURCE_QUAD_STAGE2,
                              granularity=target_granularity)

    sigma_sym = sym.var("sigma")
    op_sym = sym.sin(sym.interp(from_dd, to_dd, sigma_sym))
    bound_op = bind(qbx, op_sym, auto_where=where)

    target_nodes = qbx.quad_stage2_density_discr.nodes().get(queue)
    if source_discr_stage == sym.QBX_SOURCE_STAGE2:
        source_nodes = qbx.stage2_density_discr.nodes().get(queue)
    elif source_discr_stage == sym.QBX_SOURCE_QUAD_STAGE2:
        source_nodes = target_nodes
    else:
        source_nodes = qbx.density_discr.nodes().get(queue)

    sigma_dev = cl.array.to_device(queue, la.norm(source_nodes, axis=0))
    sigma_target = np.sin(la.norm(target_nodes, axis=0))
    sigma_target_interp = bound_op(queue, sigma=sigma_dev).get(queue)

    if name in ('default', 'default-explicit', 'stage2', 'quad'):
        error = la.norm(sigma_target_interp -
                        sigma_target) / la.norm(sigma_target)
        assert error < 1.0e-10
    elif name in ('stage2-center', ):
        assert len(sigma_target_interp) == 2 * len(sigma_target)
    else:
        raise ValueError('unknown test case name: {}'.format(name))
Exemple #3
0
    def _get_qbx_discretization(self, geometry, discr_stage):
        lpot_source = self.get_geometry(geometry)

        try:
            discr = self._get_discr_from_cache(geometry, discr_stage)
        except KeyError:
            from pytential.qbx.refinement import _refine_for_global_qbx

            # NOTE: this adds the required discretizations to the cache
            dofdesc = sym.DOFDescriptor(geometry, discr_stage)
            _refine_for_global_qbx(
                self,
                dofdesc,
                lpot_source.refiner_code_container.get_wrangler(),
                _copy_collection=False)

            discr = self._get_discr_from_cache(geometry, discr_stage)

        return discr
Exemple #4
0
    def _operator(self, sigma, normal, mu, qbx_forced_limit):
        slp_qbx_forced_limit = qbx_forced_limit
        if slp_qbx_forced_limit == "avg":
            slp_qbx_forced_limit = +1

        # NOTE: we set a dofdesc here to force the evaluation of this integral
        # on the source instead of the target when using automatic tagging
        # see :meth:`pytential.symbolic.mappers.LocationTagger._default_dofdesc`
        dd = sym.DOFDescriptor(None, discr_stage=sym.QBX_SOURCE_STAGE1)

        int_sigma = sym.integral(self.ambient_dim, self.dim, sigma, dofdesc=dd)
        meanless_sigma = sym.cse(sigma - sym.mean(self.ambient_dim, self.dim, sigma))

        op_k = self.stresslet.apply(sigma, normal, mu,
                qbx_forced_limit=qbx_forced_limit)
        op_s = (
                self.alpha / (2.0 * np.pi) * int_sigma
                - self.stokeslet.apply(meanless_sigma, mu,
                    qbx_forced_limit=slp_qbx_forced_limit)
                )

        return op_k + self.eta * op_s
Exemple #5
0
def test_geometry_collection_caching(ctx_factory):
    # NOTE: checks that the on-demand caching works properly in
    # the `GeometryCollection`. This is done by constructing a few separated
    # spheres, putting a few `QBXLayerPotentialSource`s on them and requesting
    # the `nodes` on each `discr_stage`.
    ctx = ctx_factory()
    queue = cl.CommandQueue(ctx)
    actx = PyOpenCLArrayContext(queue)

    ndim = 2
    nelements = 1024
    target_order = 7
    qbx_order = 4
    ngeometry = 3

    # construct discretizations
    from meshmode.mesh.generation import ellipse, make_curve_mesh
    from meshmode.mesh.processing import affine_map
    from meshmode.discretization import Discretization
    from meshmode.discretization.poly_element import \
            InterpolatoryQuadratureSimplexGroupFactory

    discrs = []
    radius = 1.0
    for k in range(ngeometry):
        if k == 0:
            mesh = make_curve_mesh(partial(ellipse, radius),
                                   np.linspace(0.0, 1.0, nelements + 1),
                                   target_order)
        else:
            mesh = affine_map(discrs[0].mesh, b=np.array([3 * k * radius, 0]))

        discr = Discretization(
            actx, mesh,
            InterpolatoryQuadratureSimplexGroupFactory(target_order))
        discrs.append(discr)

    # construct qbx source
    from pytential.qbx import QBXLayerPotentialSource

    lpots = []
    sources = [f"source_{k}" for k in range(ngeometry)]
    for k, density_discr in enumerate(discrs):
        qbx = QBXLayerPotentialSource(density_discr,
                                      fine_order=2 * target_order,
                                      qbx_order=qbx_order,
                                      fmm_order=False)
        lpots.append(qbx)

    # construct a geometry collection
    from pytential import GeometryCollection
    places = GeometryCollection(dict(zip(sources, lpots)))
    print(places.places)

    # check on-demand refinement
    from pytential import bind, sym
    discr_stages = [
        sym.QBX_SOURCE_STAGE1, sym.QBX_SOURCE_STAGE2,
        sym.QBX_SOURCE_QUAD_STAGE2
    ]

    for k in range(ngeometry):
        for discr_stage in discr_stages:
            with pytest.raises(KeyError):
                discr = places._get_discr_from_cache(sources[k], discr_stage)

            dofdesc = sym.DOFDescriptor(sources[k], discr_stage=discr_stage)
            bind(places, sym.nodes(ndim, dofdesc=dofdesc))(actx)

            discr = places._get_discr_from_cache(sources[k], discr_stage)
            assert discr is not None
Exemple #6
0
def test_build_matrix_places(ctx_factory,
        source_discr_stage, target_discr_stage, visualize=False):
    ctx = ctx_factory()
    queue = cl.CommandQueue(ctx)

    # prevent cache explosion
    from sympy.core.cache import clear_cache
    clear_cache()

    qbx_forced_limit = -1
    place_ids = (
            sym.DOFDescriptor(
                geometry=sym.DEFAULT_SOURCE,
                discr_stage=source_discr_stage),
            sym.DOFDescriptor(
                geometry=sym.DEFAULT_TARGET,
                discr_stage=target_discr_stage),
            )

    # build test operators
    qbx = _build_qbx_discr(queue, nelements=8, target_order=2, ndim=2,
                           curve_f=partial(ellipse, 1.0))

    op, u_sym, _ = _build_op(lpot_id=1, ndim=2,
            source=place_ids[0],
            target=place_ids[1],
            qbx_forced_limit=qbx_forced_limit)

    from pytential.symbolic.execution import GeometryCollection
    places = GeometryCollection(qbx, auto_where=place_ids)
    source_discr = places.get_discretization(place_ids[0])
    target_discr = places.get_discretization(place_ids[1])

    index_set = _build_block_index(source_discr, factor=0.6)

    from pytential.symbolic.execution import _prepare_expr
    op = _prepare_expr(places, op)

    # build full QBX matrix
    from pytential.symbolic.matrix import MatrixBuilder
    mbuilder = MatrixBuilder(queue,
            dep_expr=u_sym,
            other_dep_exprs=[],
            dep_source=places.get_geometry(place_ids[0]),
            dep_discr=places.get_discretization(place_ids[0]),
            places=places,
            context={})
    qbx_mat = mbuilder(op)

    # build full p2p matrix
    from pytential.symbolic.matrix import P2PMatrixBuilder
    mbuilder = P2PMatrixBuilder(queue,
            dep_expr=u_sym,
            other_dep_exprs=[],
            dep_source=places.get_geometry(place_ids[0]),
            dep_discr=places.get_discretization(place_ids[0]),
            places=places,
            context={})
    p2p_mat = mbuilder(op)

    assert p2p_mat.shape == (target_discr.nnodes, source_discr.nnodes)

    # build block qbx and p2p matrices
    from pytential.symbolic.matrix import NearFieldBlockBuilder
    mbuilder = NearFieldBlockBuilder(queue,
            dep_expr=u_sym,
            other_dep_exprs=[],
            dep_source=places.get_geometry(place_ids[0]),
            dep_discr=places.get_discretization(place_ids[0]),
            places=places,
            index_set=index_set,
            context={})
    mat = mbuilder(op)
    if place_ids[0].discr_stage is not None:
        assert _max_block_error(qbx_mat, mat, index_set.get(queue)) < 1.0e-14

    from pytential.symbolic.matrix import FarFieldBlockBuilder
    mbuilder = FarFieldBlockBuilder(queue,
            dep_expr=u_sym,
            other_dep_exprs=[],
            dep_source=places.get_geometry(place_ids[0]),
            dep_discr=places.get_discretization(place_ids[0]),
            places=places,
            index_set=index_set,
            context={},
            exclude_self=True)
    mat = mbuilder(op)
    assert _max_block_error(p2p_mat, mat, index_set.get(queue)) < 1.0e-14
Exemple #7
0
def test_qbx_block_builder(ctx_factory, factor, ndim, lpot_id,
                           visualize=False):
    ctx = ctx_factory()
    queue = cl.CommandQueue(ctx)

    # prevent cache explosion
    from sympy.core.cache import clear_cache
    clear_cache()

    place_ids = (
            sym.DOFDescriptor(
                geometry=sym.DEFAULT_SOURCE,
                discr_stage=sym.QBX_SOURCE_STAGE2),
            sym.DOFDescriptor(
                geometry=sym.DEFAULT_TARGET,
                discr_stage=sym.QBX_SOURCE_STAGE2),
            )
    target_order = 2 if ndim == 3 else 7

    qbx = _build_qbx_discr(queue, target_order=target_order, ndim=ndim)
    op, u_sym, _ = _build_op(lpot_id, ndim=ndim,
            source=place_ids[0],
            target=place_ids[1],
            qbx_forced_limit="avg")

    from pytential.symbolic.execution import GeometryCollection, _prepare_expr
    places = GeometryCollection(qbx, auto_where=place_ids)
    expr = _prepare_expr(places, op)
    density_discr = places.get_discretization(place_ids[0])
    index_set = _build_block_index(density_discr, factor=factor)

    from pytential.symbolic.matrix import NearFieldBlockBuilder
    mbuilder = NearFieldBlockBuilder(queue,
            dep_expr=u_sym,
            other_dep_exprs=[],
            dep_source=places.get_geometry(place_ids[0]),
            dep_discr=places.get_discretization(place_ids[0]),
            places=places,
            index_set=index_set,
            context={})
    blk = mbuilder(expr)

    from pytential.symbolic.matrix import MatrixBuilder
    mbuilder = MatrixBuilder(queue,
            dep_expr=u_sym,
            other_dep_exprs=[],
            dep_source=places.get_geometry(place_ids[0]),
            dep_discr=places.get_discretization(place_ids[0]),
            places=places,
            context={})
    mat = mbuilder(expr)

    index_set = index_set.get(queue)
    if visualize:
        blk_full = np.zeros_like(mat)
        mat_full = np.zeros_like(mat)

        for i in range(index_set.nblocks):
            itgt, isrc = index_set.block_indices(i)

            blk_full[np.ix_(itgt, isrc)] = index_set.block_take(blk, i)
            mat_full[np.ix_(itgt, isrc)] = index_set.take(mat, i)

        import matplotlib.pyplot as mp
        _, (ax1, ax2) = mp.subplots(1, 2,
                figsize=(10, 8), constrained_layout=True)
        ax1.imshow(mat_full)
        ax1.set_title('MatrixBuilder')
        ax2.imshow(blk_full)
        ax2.set_title('NearFieldBlockBuilder')
        mp.savefig("test_qbx_block_builder.png", dpi=300)

    assert _max_block_error(mat, blk, index_set) < 1.0e-14