Example #1
0
def make_source_and_target_points(side,
                                  inner_radius,
                                  outer_radius,
                                  ambient_dim,
                                  nsources=10,
                                  ntargets=20):
    if side == -1:
        test_src_geo_radius = outer_radius
        test_tgt_geo_radius = inner_radius
    elif side == +1:
        test_src_geo_radius = inner_radius
        test_tgt_geo_radius = outer_radius
    elif side == "scat":
        test_src_geo_radius = outer_radius
        test_tgt_geo_radius = outer_radius
    else:
        raise ValueError(f"unknown side: {side}")

    from pytential.source import PointPotentialSource
    point_sources = make_circular_point_group(ambient_dim,
                                              nsources,
                                              test_src_geo_radius,
                                              func=lambda x: x**1.5)
    point_source = PointPotentialSource(point_sources)

    from pytential.target import PointsTarget
    test_targets = make_circular_point_group(ambient_dim, ntargets,
                                             test_tgt_geo_radius)
    point_target = PointsTarget(test_targets)

    return point_source, point_target
Example #2
0
def test_off_surface_eval(actx_factory, use_fmm, visualize=False):
    logging.basicConfig(level=logging.INFO)

    actx = actx_factory()

    # prevent cache 'splosion
    from sympy.core.cache import clear_cache
    clear_cache()

    nelements = 30
    target_order = 8
    qbx_order = 3
    if use_fmm:
        fmm_order = qbx_order
    else:
        fmm_order = False

    mesh = mgen.make_curve_mesh(partial(mgen.ellipse, 3),
                                np.linspace(0, 1, nelements + 1), target_order)

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

    pre_density_discr = Discretization(
        actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order))
    qbx = QBXLayerPotentialSource(
        pre_density_discr,
        4 * target_order,
        qbx_order,
        fmm_order=fmm_order,
    )

    from pytential.target import PointsTarget
    fplot = FieldPlotter(np.zeros(2), extent=0.54, npoints=30)
    targets = PointsTarget(actx.freeze(actx.from_numpy(fplot.points)))

    places = GeometryCollection((qbx, targets))
    density_discr = places.get_discretization(places.auto_source.geometry)

    from sumpy.kernel import LaplaceKernel
    op = sym.D(LaplaceKernel(2), sym.var("sigma"), qbx_forced_limit=-2)

    sigma = density_discr.zeros(actx) + 1
    fld_in_vol = bind(places, op)(actx, sigma=sigma)
    fld_in_vol_exact = -1

    linf_err = actx.to_numpy(
        actx.np.linalg.norm(fld_in_vol - fld_in_vol_exact, ord=np.inf))
    logger.info("l_inf error: %.12e", linf_err)

    if visualize:
        fplot.show_scalar_in_matplotlib(actx.to_numpy(fld_in_vol))
        import matplotlib.pyplot as pt
        pt.colorbar()
        pt.show()

    assert linf_err < 1e-3
Example #3
0
def test_off_surface_eval(ctx_factory, use_fmm, do_plot=False):
    logging.basicConfig(level=logging.INFO)

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

    # prevent cache 'splosion
    from sympy.core.cache import clear_cache
    clear_cache()

    nelements = 30
    target_order = 8
    qbx_order = 3
    if use_fmm:
        fmm_order = qbx_order
    else:
        fmm_order = False

    mesh = make_curve_mesh(partial(ellipse, 3),
                           np.linspace(0, 1, nelements + 1), target_order)

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

    pre_density_discr = Discretization(
        cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order))
    qbx, _ = QBXLayerPotentialSource(
        pre_density_discr,
        4 * target_order,
        qbx_order,
        fmm_order=fmm_order,
    ).with_refinement()

    density_discr = qbx.density_discr

    from sumpy.kernel import LaplaceKernel
    op = sym.D(LaplaceKernel(2), sym.var("sigma"), qbx_forced_limit=-2)

    sigma = density_discr.zeros(queue) + 1

    fplot = FieldPlotter(np.zeros(2), extent=0.54, npoints=30)
    from pytential.target import PointsTarget
    fld_in_vol = bind((qbx, PointsTarget(fplot.points)), op)(queue,
                                                             sigma=sigma)

    err = cl.clmath.fabs(fld_in_vol - (-1))

    linf_err = cl.array.max(err).get()
    print("l_inf error:", linf_err)

    if do_plot:
        fplot.show_scalar_in_matplotlib(fld_in_vol.get())
        import matplotlib.pyplot as pt
        pt.colorbar()
        pt.show()

    assert linf_err < 1e-3
Example #4
0
def test_unregularized_off_surface_fmm_vs_direct(ctx_factory):
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

    nelements = 300
    target_order = 8
    fmm_order = 4

    # {{{ geometry

    mesh = make_curve_mesh(WobblyCircle.random(8, seed=30),
                np.linspace(0, 1, nelements+1),
                target_order)

    from pytential.unregularized import UnregularizedLayerPotentialSource
    from meshmode.discretization import Discretization
    from meshmode.discretization.poly_element import \
            InterpolatoryQuadratureSimplexGroupFactory

    density_discr = Discretization(
            actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order))
    direct = UnregularizedLayerPotentialSource(
            density_discr,
            fmm_order=False,
            )
    fmm = direct.copy(
            fmm_level_to_order=lambda kernel, kernel_args, tree, level: fmm_order)

    sigma = density_discr.zeros(actx) + 1

    fplot = FieldPlotter(np.zeros(2), extent=5, npoints=100)
    from pytential.target import PointsTarget
    ptarget = PointsTarget(fplot.points)

    from pytential import GeometryCollection
    places = GeometryCollection({
        "unregularized_direct": direct,
        "unregularized_fmm": fmm,
        "targets": ptarget})

    # }}}

    # {{{ check

    from sumpy.kernel import LaplaceKernel
    op = sym.D(LaplaceKernel(2), sym.var("sigma"), qbx_forced_limit=None)

    direct_fld_in_vol = bind(places, op,
            auto_where=("unregularized_direct", "targets"))(
                    actx, sigma=sigma)
    fmm_fld_in_vol = bind(places, op,
            auto_where=("unregularized_fmm", "targets"))(actx, sigma=sigma)

    err = actx.np.fabs(fmm_fld_in_vol - direct_fld_in_vol)
    linf_err = actx.to_numpy(err).max()
    print("l_inf error:", linf_err)

    assert linf_err < 5e-3
Example #5
0
def test_target_association_failure(ctx_factory):
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

    # {{{ generate circle

    order = 5
    nelements = 40

    # Make the curve mesh.
    curve_f = partial(ellipse, 1)
    mesh = make_curve_mesh(curve_f, np.linspace(0, 1, nelements + 1), order)

    from meshmode.discretization import Discretization
    from meshmode.discretization.poly_element import \
            InterpolatoryQuadratureSimplexGroupFactory
    factory = InterpolatoryQuadratureSimplexGroupFactory(order)
    discr = Discretization(actx, mesh, factory)
    lpot_source = QBXLayerPotentialSource(
        discr,
        qbx_order=order,  # not used in target association
        fine_order=order)
    places = GeometryCollection(lpot_source)

    # }}}

    # {{{ generate targets and check

    close_circle = 0.999 * np.exp(
        2j * np.pi * np.linspace(0, 1, 500, endpoint=False))
    from pytential.target import PointsTarget
    close_circle_target = (PointsTarget(
        actx.from_numpy(np.array([close_circle.real, close_circle.imag]))))

    targets = ((close_circle_target, 0), )

    from pytential.qbx.target_assoc import (TargetAssociationCodeContainer,
                                            associate_targets_to_qbx_centers,
                                            QBXTargetAssociationFailedException
                                            )

    from pytential.qbx.utils import TreeCodeContainer

    code_container = TargetAssociationCodeContainer(actx,
                                                    TreeCodeContainer(actx))

    with pytest.raises(QBXTargetAssociationFailedException):
        associate_targets_to_qbx_centers(places,
                                         places.auto_source,
                                         code_container.get_wrangler(actx),
                                         targets,
                                         target_association_tolerance=1e-10)
Example #6
0
    def set_bdy_as_target(self, bdy_id, method):
        """
            :arg bdy_id: An iterable of subdomain ids as could be
                              accepted as the :arg:`subdomain` in
                              a :class:`DirichletBC` from :mod:`firedrake`.
            :arg method: A method for determining bdy nodes as
                         in :class:`DirichletBC', either 'geometric'
                         or 'topological'
        """
        mesh = self._function_space.mesh()

        # if just passed an int, convert to an iterable of ints
        # so that just one case to deal with
        if isinstance(bdy_id, int):
            bdy_id = [bdy_id]
        target_markers = set(bdy_id)

        # Check that bdy ids are valid
        if not target_markers <= set(mesh.exterior_facets.unique_markers):
            warn("The following bdy ids are not exterior facet ids: %s" %
                 (target_markers - set(mesh.exterior_facets.unique_markers)))

        if not target_markers & set(mesh.exterior_facets.unique_markers):
            raise ValueError("No bdy ids are exterior facet ids")

        self._target_indices = set()
        for marker in target_markers:
            self._target_indices |= set(
                self._function_space.boundary_nodes(marker, method))
        self._target_indices = np.array(list(self._target_indices),
                                        dtype=np.int32)

        # Get coordinates of nodes
        coords = SpatialCoordinate(mesh)
        function_space_dim = VectorFunctionSpace(
            mesh,
            self._function_space.ufl_element().family(),
            degree=self._function_space.ufl_element().degree())

        coords = Function(function_space_dim).interpolate(coords)
        coords = np.real(coords.dat.data)

        target_pts = coords[self._target_indices]
        # change from [nnodes][ambient_dim] to [ambient_dim][nnodes]
        target_pts = np.transpose(target_pts).copy()
        self._target = PointsTarget(target_pts)
Example #7
0
def test_unregularized_with_ones_kernel(ctx_factory):
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

    nelements = 10
    order = 8

    mesh = make_curve_mesh(partial(ellipse, 1),
            np.linspace(0, 1, nelements+1),
            order)

    from meshmode.discretization import Discretization
    from meshmode.discretization.poly_element import \
            InterpolatoryQuadratureSimplexGroupFactory

    discr = Discretization(actx, mesh,
            InterpolatoryQuadratureSimplexGroupFactory(order))

    from pytential.unregularized import UnregularizedLayerPotentialSource
    lpot_source = UnregularizedLayerPotentialSource(discr)
    from pytential.target import PointsTarget
    targets = PointsTarget(np.zeros((2, 1), dtype=float))

    places = GeometryCollection({
        sym.DEFAULT_SOURCE: lpot_source,
        sym.DEFAULT_TARGET: lpot_source,
        "target_non_self": targets})

    from sumpy.kernel import one_kernel_2d
    sigma_sym = sym.var("sigma")
    op = sym.IntG(one_kernel_2d, sigma_sym, qbx_forced_limit=None)

    sigma = discr.zeros(actx) + 1

    result_self = bind(places, op,
            auto_where=places.auto_where)(
                    actx, sigma=sigma)
    result_nonself = bind(places, op,
            auto_where=(places.auto_source, "target_non_self"))(
                    actx, sigma=sigma)

    from meshmode.dof_array import flatten
    assert np.allclose(actx.to_numpy(flatten(result_self)), 2 * np.pi)
    assert np.allclose(actx.to_numpy(result_nonself), 2 * np.pi)
Example #8
0
def get_target_points_and_indices(fspace, boundary_ids):
    """
    Get  the points from the function space which lie on the given boundary
    id as a pytential PointsTarget, and their indices into the
    firedrake function

    :return: (target_indices, target_points)
    """
    # if just passed an int, convert to an iterable of ints
    # so that just one case to deal with
    if isinstance(boundary_ids, int):
        boundary_ids = [boundary_ids]
    target_markers = set(boundary_ids)

    # Check that bdy ids are valid
    if not target_markers <= set(fspace.mesh().exterior_facets.unique_markers):
        raise ValueError(
            "The following bdy ids are not exterior facet ids: %s" %
            (target_markers -
             set(fspace.mesh().exterior_facets.unique_markers)))

    if not target_markers & set(fspace.mesh().exterior_facets.unique_markers):
        raise ValueError("No bdy ids are exterior facet ids")

    target_indices = set()
    for marker in target_markers:
        target_indices |= set(fspace.boundary_nodes(marker, 'topological'))
    target_indices = np.array(list(target_indices), dtype=np.int32)

    target_indices = np.array(target_indices, dtype=np.int32)
    # Get coordinates of nodes
    coords = SpatialCoordinate(fspace.mesh())
    function_space_dim = VectorFunctionSpace(
        fspace.mesh(),
        fspace.ufl_element().family(),
        degree=fspace.ufl_element().degree())

    coords = Function(function_space_dim).interpolate(coords)
    coords = np.real(coords.dat.data)

    target_pts = coords[target_indices]
    # change from [nnodes][ambient_dim] to [ambient_dim][nnodes]
    target_pts = np.transpose(target_pts).copy()
    return (target_indices, PointsTarget(target_pts))
Example #9
0
    def user_target_to_center(self):
        """Find which QBX center, if any, is to be used for each target.
        :attr:`target_state.NO_QBX_NEEDED` if none. :attr:`target_state.FAILED`
        if a center needs to be used, but none was found.
        See :meth:`center_to_tree_targets` for the reverse look-up table.

        Shape: ``[ntargets]`` of :attr:`boxtree.Tree.particle_id_dtype`, with extra
        values from :class:`target_state` allowed. Targets occur in user order.
        """
        from pytential.qbx.target_assoc import associate_targets_to_qbx_centers
        target_info = self.target_info()

        from pytential.target import PointsTarget

        queue = self.array_context.queue

        target_side_prefs = (
            self.target_side_preferences()[self.ncenters:].get(queue=queue))

        target_discrs_and_qbx_sides = [
            (PointsTarget(target_info.targets[:, self.ncenters:]),
             target_side_prefs.astype(np.int32))
        ]

        target_association_wrangler = (
            self.lpot_source.target_association_code_container.get_wrangler(
                self.array_context))

        tgt_assoc_result = associate_targets_to_qbx_centers(
            self.places,
            self.source_dd,
            target_association_wrangler,
            target_discrs_and_qbx_sides,
            target_association_tolerance=(self.target_association_tolerance),
            debug=self.debug)

        result = cl.array.empty(queue, target_info.ntargets,
                                tgt_assoc_result.target_to_center.dtype)
        result[:self.ncenters].fill(target_state.NO_QBX_NEEDED)
        result[self.ncenters:] = tgt_assoc_result.target_to_center

        return result.with_queue(None)
Example #10
0
def test_unregularized_off_surface_fmm_vs_direct(ctx_factory):
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)

    nelements = 300
    target_order = 8
    fmm_order = 4

    mesh = make_curve_mesh(WobblyCircle.random(8, seed=30),
                           np.linspace(0, 1, nelements + 1), target_order)

    from pytential.unregularized import UnregularizedLayerPotentialSource
    from meshmode.discretization import Discretization
    from meshmode.discretization.poly_element import \
            InterpolatoryQuadratureSimplexGroupFactory

    density_discr = Discretization(
        cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order))
    direct = UnregularizedLayerPotentialSource(
        density_discr,
        fmm_order=False,
    )
    fmm = direct.copy(
        fmm_level_to_order=lambda kernel, kernel_args, tree, level: fmm_order)

    sigma = density_discr.zeros(queue) + 1

    fplot = FieldPlotter(np.zeros(2), extent=5, npoints=100)
    from pytential.target import PointsTarget
    ptarget = PointsTarget(fplot.points)
    from sumpy.kernel import LaplaceKernel

    op = sym.D(LaplaceKernel(2), sym.var("sigma"), qbx_forced_limit=None)

    direct_fld_in_vol = bind((direct, ptarget), op)(queue, sigma=sigma)
    fmm_fld_in_vol = bind((fmm, ptarget), op)(queue, sigma=sigma)

    err = cl.clmath.fabs(fmm_fld_in_vol - direct_fld_in_vol)

    linf_err = cl.array.max(err).get()
    print("l_inf error:", linf_err)
    assert linf_err < 5e-3
Example #11
0
def test_unregularized_with_ones_kernel(ctx_factory):
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)

    nelements = 10
    order = 8

    mesh = make_curve_mesh(partial(ellipse, 1),
                           np.linspace(0, 1, nelements + 1), order)

    from meshmode.discretization import Discretization
    from meshmode.discretization.poly_element import \
            InterpolatoryQuadratureSimplexGroupFactory

    discr = Discretization(cl_ctx, mesh,
                           InterpolatoryQuadratureSimplexGroupFactory(order))

    from pytential.unregularized import UnregularizedLayerPotentialSource
    lpot_src = UnregularizedLayerPotentialSource(discr)

    from sumpy.kernel import one_kernel_2d

    expr = sym.IntG(one_kernel_2d, sym.var("sigma"), qbx_forced_limit=None)

    from pytential.target import PointsTarget
    op_self = bind(lpot_src, expr)
    op_nonself = bind((lpot_src, PointsTarget(np.zeros((2, 1), dtype=float))),
                      expr)

    with cl.CommandQueue(cl_ctx) as queue:
        sigma = cl.array.zeros(queue, discr.nnodes, dtype=float)
        sigma.fill(1)
        sigma.finish()

        result_self = op_self(queue, sigma=sigma)
        result_nonself = op_nonself(queue, sigma=sigma)

    assert np.allclose(result_self.get(), 2 * np.pi)
    assert np.allclose(result_nonself.get(), 2 * np.pi)
Example #12
0
    # {{{ come up with a solution to Maxwell's equations

    j_sym = sym.make_sym_vector("j", 3)
    jt_sym = sym.make_sym_vector("jt", 2)
    rho_sym = sym.var("rho")

    from pytential.symbolic.pde.maxwell import (PECChargeCurrentMFIEOperator,
                                                get_sym_maxwell_point_source,
                                                get_sym_maxwell_plane_wave)
    mfie = PECChargeCurrentMFIEOperator()

    test_source = case.get_source(actx)

    calc_patch = CalculusPatch(np.array([-3, 0, 0]), h=0.01)
    calc_patch_tgt = PointsTarget(actx.from_numpy(calc_patch.points))

    rng = cl.clrandom.PhiloxGenerator(cl_ctx, seed=12)
    from pytools.obj_array import make_obj_array
    src_j = make_obj_array([
        rng.normal(actx.queue, (test_source.ndofs), dtype=np.float64)
        for _ in range(3)
    ])

    def eval_inc_field_at(places, source=None, target=None):
        if source is None:
            source = "test_source"

        if use_plane_wave:
            # plane wave
            return bind(places,
Example #13
0
def main(mesh_name="ellipse", visualize=False):
    import logging
    logging.basicConfig(level=logging.INFO)  # INFO for more progress info

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

    from meshmode.mesh.generation import ellipse, make_curve_mesh
    from functools import partial

    if mesh_name == "ellipse":
        mesh = make_curve_mesh(partial(ellipse, 1),
                               np.linspace(0, 1, nelements + 1), mesh_order)
    elif mesh_name == "ellipse_array":
        base_mesh = make_curve_mesh(partial(ellipse, 1),
                                    np.linspace(0, 1, nelements + 1),
                                    mesh_order)

        from meshmode.mesh.processing import affine_map, merge_disjoint_meshes
        nx = 2
        ny = 2
        dx = 2 / nx
        meshes = [
            affine_map(base_mesh,
                       A=np.diag([dx * 0.25, dx * 0.25]),
                       b=np.array([dx * (ix - nx / 2), dx * (iy - ny / 2)]))
            for ix in range(nx) for iy in range(ny)
        ]

        mesh = merge_disjoint_meshes(meshes, single_group=True)

        if visualize:
            from meshmode.mesh.visualization import draw_curve
            draw_curve(mesh)
            import matplotlib.pyplot as plt
            plt.show()
    else:
        raise ValueError(f"unknown mesh name: {mesh_name}")

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

    from pytential.qbx import (QBXLayerPotentialSource,
                               QBXTargetAssociationFailedException)
    qbx = QBXLayerPotentialSource(pre_density_discr,
                                  fine_order=bdry_ovsmp_quad_order,
                                  qbx_order=qbx_order,
                                  fmm_order=fmm_order)

    from sumpy.visualization import FieldPlotter
    fplot = FieldPlotter(np.zeros(2), extent=5, npoints=500)
    targets = actx.from_numpy(fplot.points)

    from pytential import GeometryCollection
    places = GeometryCollection(
        {
            "qbx":
            qbx,
            "qbx_high_target_assoc_tol":
            qbx.copy(target_association_tolerance=0.05),
            "targets":
            PointsTarget(targets)
        },
        auto_where="qbx")
    density_discr = places.get_discretization("qbx")

    # {{{ describe bvp

    from sumpy.kernel import LaplaceKernel, HelmholtzKernel
    kernel = HelmholtzKernel(2)

    sigma_sym = sym.var("sigma")
    sqrt_w = sym.sqrt_jac_q_weight(2)
    inv_sqrt_w_sigma = sym.cse(sigma_sym / sqrt_w)

    # Brakhage-Werner parameter
    alpha = 1j

    # -1 for interior Dirichlet
    # +1 for exterior Dirichlet
    loc_sign = +1

    k_sym = sym.var("k")
    bdry_op_sym = (
        -loc_sign * 0.5 * sigma_sym + sqrt_w *
        (alpha * sym.S(kernel, inv_sqrt_w_sigma, k=k_sym, qbx_forced_limit=+1)
         - sym.D(kernel, inv_sqrt_w_sigma, k=k_sym, qbx_forced_limit="avg")))

    # }}}

    bound_op = bind(places, bdry_op_sym)

    # {{{ fix rhs and solve

    from meshmode.dof_array import thaw
    nodes = thaw(actx, density_discr.nodes())
    k_vec = np.array([2, 1])
    k_vec = k * k_vec / la.norm(k_vec, 2)

    def u_incoming_func(x):
        return actx.np.exp(1j * (x[0] * k_vec[0] + x[1] * k_vec[1]))

    bc = -u_incoming_func(nodes)

    bvp_rhs = bind(places, sqrt_w * sym.var("bc"))(actx, bc=bc)

    from pytential.solve import gmres
    gmres_result = gmres(bound_op.scipy_op(actx,
                                           sigma_sym.name,
                                           dtype=np.complex128,
                                           k=k),
                         bvp_rhs,
                         tol=1e-8,
                         progress=True,
                         stall_iterations=0,
                         hard_failure=True)

    # }}}

    # {{{ postprocess/visualize

    repr_kwargs = dict(source="qbx_high_target_assoc_tol",
                       target="targets",
                       qbx_forced_limit=None)
    representation_sym = (
        alpha * sym.S(kernel, inv_sqrt_w_sigma, k=k_sym, **repr_kwargs) -
        sym.D(kernel, inv_sqrt_w_sigma, k=k_sym, **repr_kwargs))

    u_incoming = u_incoming_func(targets)
    ones_density = density_discr.zeros(actx)
    for elem in ones_density:
        elem.fill(1)

    indicator = actx.to_numpy(
        bind(places, sym.D(LaplaceKernel(2), sigma_sym,
                           **repr_kwargs))(actx, sigma=ones_density))

    try:
        fld_in_vol = actx.to_numpy(
            bind(places, representation_sym)(actx,
                                             sigma=gmres_result.solution,
                                             k=k))
    except QBXTargetAssociationFailedException as e:
        fplot.write_vtk_file("helmholtz-dirichlet-failed-targets.vts",
                             [("failed", e.failed_target_flags.get(queue))])
        raise

    #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5)
    fplot.write_vtk_file("helmholtz-dirichlet-potential.vts", [
        ("potential", fld_in_vol),
        ("indicator", indicator),
        ("u_incoming", actx.to_numpy(u_incoming)),
    ])
Example #14
0
    # {{{ establish BCs

    from pytential.source import PointPotentialSource
    from pytential.target import PointsTarget

    point_source = PointPotentialSource(cl_ctx, point_sources)

    pot_src = sym.IntG(
        # FIXME: qbx_forced_limit--really?
        knl,
        sym.var("charges"),
        qbx_forced_limit=None,
        **knl_kwargs)

    test_direct = bind((point_source, PointsTarget(test_targets)),
                       pot_src)(queue,
                                charges=source_charges_dev,
                                **concrete_knl_kwargs)

    if case.bc_type == "dirichlet":
        bc = bind((point_source, density_discr),
                  pot_src)(queue,
                           charges=source_charges_dev,
                           **concrete_knl_kwargs)

    elif case.bc_type == "neumann":
        bc = bind((point_source, density_discr),
                  sym.normal_derivative(qbx.ambient_dim,
                                        pot_src,
                                        dofdesc=sym.DEFAULT_TARGET))(
 def general_mask(test_points):
     const_density = bind((qbx, PointsTarget(test_points)),
                          constant_laplace_rep)(queue,
                                                gamma=sqrt_w_vec).get()
     return (abs(const_density) > 0.1)
def main(nelements):
    import logging
    logging.basicConfig(level=logging.INFO)

    def get_obj_array(obj_array):
        from pytools.obj_array import make_obj_array
        return make_obj_array([ary.get() for ary in obj_array])

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

    from meshmode.mesh.generation import (  # noqa
        make_curve_mesh, starfish, ellipse, drop)
    mesh = make_curve_mesh(lambda t: starfish(t),
                           np.linspace(0, 1, nelements + 1), target_order)
    coarse_density_discr = Discretization(
        cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order))

    from pytential.qbx import QBXLayerPotentialSource
    target_association_tolerance = 0.05
    qbx, _ = QBXLayerPotentialSource(
        coarse_density_discr,
        fine_order=ovsmp_target_order,
        qbx_order=qbx_order,
        fmm_order=fmm_order,
        target_association_tolerance=target_association_tolerance,
    ).with_refinement()

    density_discr = qbx.density_discr
    nodes = density_discr.nodes().with_queue(queue)

    # Get normal vectors for the density discretization -- used in integration with stresslet
    mv_normal = bind(density_discr, sym.normal(2))(queue)
    normal = mv_normal.as_vector(np.object)

    # {{{ describe bvp

    from sumpy.kernel import LaplaceKernel
    from pytential.symbolic.stokes import StressletWrapper
    from pytools.obj_array import make_obj_array
    dim = 2
    cse = sym.cse

    nvec_sym = sym.make_sym_vector("normal", dim)
    sigma_sym = sym.make_sym_vector("sigma", dim)
    mu_sym = sym.var("mu")
    sqrt_w = sym.sqrt_jac_q_weight(2)
    inv_sqrt_w_sigma = cse(sigma_sym / sqrt_w)

    # -1 for interior Dirichlet
    # +1 for exterior Dirichlet
    loc_sign = -1

    # Create stresslet object
    stresslet_obj = StressletWrapper(dim=2)

    # Describe boundary operator
    bdry_op_sym = loc_sign * 0.5 * sigma_sym + sqrt_w * stresslet_obj.apply(
        inv_sqrt_w_sigma, nvec_sym, mu_sym, qbx_forced_limit='avg')

    # Bind to the qbx discretization
    bound_op = bind(qbx, bdry_op_sym)

    # }}}

    # {{{ fix rhs and solve

    def fund_soln(x, y, loc):
        #with direction (1,0) for point source
        r = cl.clmath.sqrt((x - loc[0])**2 + (y - loc[1])**2)
        scaling = 1. / (4 * np.pi * mu)
        xcomp = (-cl.clmath.log(r) + (x - loc[0])**2 / r**2) * scaling
        ycomp = ((x - loc[0]) * (y - loc[1]) / r**2) * scaling
        return [xcomp, ycomp]

    def couette_soln(x, y, dp, h):
        scaling = 1. / (2 * mu)
        xcomp = scaling * dp * ((y + (h / 2.))**2 - h * (y + (h / 2.)))
        ycomp = scaling * 0 * y
        return [xcomp, ycomp]

    if soln_type == 'fundamental':
        pt_loc = np.array([2.0, 0.0])
        bc = fund_soln(nodes[0], nodes[1], pt_loc)
    else:
        dp = -10.
        h = 2.5
        bc = couette_soln(nodes[0], nodes[1], dp, h)

    # Get rhs vector
    bvp_rhs = bind(qbx, sqrt_w * sym.make_sym_vector("bc", dim))(queue, bc=bc)

    from pytential.solve import gmres
    gmres_result = gmres(bound_op.scipy_op(queue,
                                           "sigma",
                                           np.float64,
                                           mu=mu,
                                           normal=normal),
                         bvp_rhs,
                         tol=1e-9,
                         progress=True,
                         stall_iterations=0,
                         hard_failure=True)

    # }}}

    # {{{ postprocess/visualize
    sigma = gmres_result.solution

    # Describe representation of solution for evaluation in domain
    representation_sym = stresslet_obj.apply(inv_sqrt_w_sigma,
                                             nvec_sym,
                                             mu_sym,
                                             qbx_forced_limit=-2)

    from sumpy.visualization import FieldPlotter
    nsamp = 10
    eval_points_1d = np.linspace(-1., 1., nsamp)
    eval_points = np.zeros((2, len(eval_points_1d)**2))
    eval_points[0, :] = np.tile(eval_points_1d, len(eval_points_1d))
    eval_points[1, :] = np.repeat(eval_points_1d, len(eval_points_1d))

    gamma_sym = sym.var("gamma")
    inv_sqrt_w_gamma = cse(gamma_sym / sqrt_w)
    constant_laplace_rep = sym.D(LaplaceKernel(dim=2),
                                 inv_sqrt_w_gamma,
                                 qbx_forced_limit=None)
    sqrt_w_vec = bind(qbx, sqrt_w)(queue)

    def general_mask(test_points):
        const_density = bind((qbx, PointsTarget(test_points)),
                             constant_laplace_rep)(queue,
                                                   gamma=sqrt_w_vec).get()
        return (abs(const_density) > 0.1)

    def inside_domain(test_points):
        mask = general_mask(test_points)
        return np.array([row[mask] for row in test_points])

    def stride_hack(arr):
        from numpy.lib.stride_tricks import as_strided
        return np.array(as_strided(arr, strides=(8 * len(arr[0]), 8)))

    eval_points = inside_domain(eval_points)
    eval_points_dev = cl.array.to_device(queue, eval_points)

    # Evaluate the solution at the evaluation points
    vel = bind((qbx, PointsTarget(eval_points_dev)),
               representation_sym)(queue, sigma=sigma, mu=mu, normal=normal)
    print("@@@@@@@@")
    vel = get_obj_array(vel)

    if soln_type == 'fundamental':
        exact_soln = fund_soln(eval_points_dev[0], eval_points_dev[1], pt_loc)
    else:
        exact_soln = couette_soln(eval_points_dev[0], eval_points_dev[1], dp,
                                  h)
    err = vel - get_obj_array(exact_soln)

    print("@@@@@@@@")

    print(
        "L2 error estimate: ",
        np.sqrt((2. / (nsamp - 1))**2 * np.sum(err[0] * err[0]) +
                (2. / (nsamp - 1))**2 * np.sum(err[1] * err[1])))
    max_error_loc = [abs(err[0]).argmax(), abs(err[1]).argmax()]
    print("max error at sampled points: ", max(abs(err[0])), max(abs(err[1])))
    print("exact velocity at max error points: x -> ",
          err[0][max_error_loc[0]], ", y -> ", err[1][max_error_loc[1]])

    from pytential.symbolic.mappers import DerivativeTaker
    rep_pressure = stresslet_obj.apply_pressure(inv_sqrt_w_sigma,
                                                nvec_sym,
                                                mu_sym,
                                                qbx_forced_limit=-2)
    pressure = bind((qbx, PointsTarget(eval_points_dev)),
                    rep_pressure)(queue, sigma=sigma, mu=mu, normal=normal)
    pressure = pressure.get()
    print "pressure = ", pressure

    x_dir_vecs = np.zeros((2, len(eval_points[0])))
    x_dir_vecs[0, :] = 1.0
    y_dir_vecs = np.zeros((2, len(eval_points[0])))
    y_dir_vecs[1, :] = 1.0
    x_dir_vecs = cl.array.to_device(queue, x_dir_vecs)
    y_dir_vecs = cl.array.to_device(queue, y_dir_vecs)
    dir_vec_sym = sym.make_sym_vector("force_direction", dim)
    rep_stress = stresslet_obj.apply_stress(inv_sqrt_w_sigma,
                                            nvec_sym,
                                            dir_vec_sym,
                                            mu_sym,
                                            qbx_forced_limit=-2)

    applied_stress_x = bind((qbx, PointsTarget(eval_points_dev)),
                            rep_stress)(queue,
                                        sigma=sigma,
                                        normal=normal,
                                        force_direction=x_dir_vecs,
                                        mu=mu)
    applied_stress_x = get_obj_array(applied_stress_x)
    applied_stress_y = bind((qbx, PointsTarget(eval_points_dev)),
                            rep_stress)(queue,
                                        sigma=sigma,
                                        normal=normal,
                                        force_direction=y_dir_vecs,
                                        mu=mu)
    applied_stress_y = get_obj_array(applied_stress_y)

    print "stress applied to x direction: ", applied_stress_x
    print "stress applied to y direction: ", applied_stress_y

    import matplotlib.pyplot as plt
    plt.quiver(eval_points[0], eval_points[1], vel[0], vel[1], linewidth=0.1)
    file_name = "field-n%s.pdf" % (nelements)
    plt.savefig(file_name)

    return (max(abs(err[0])), max(abs(err[1])))
Example #17
0
def test_off_surface_eval_vs_direct(ctx_factory,  do_plot=False):
    logging.basicConfig(level=logging.INFO)

    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

    # prevent cache 'splosion
    from sympy.core.cache import clear_cache
    clear_cache()

    nelements = 300
    target_order = 8
    qbx_order = 3

    mesh = make_curve_mesh(WobblyCircle.random(8, seed=30),
                np.linspace(0, 1, nelements+1),
                target_order)

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

    pre_density_discr = Discretization(
            actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order))
    direct_qbx = QBXLayerPotentialSource(
            pre_density_discr, 4*target_order, qbx_order,
            fmm_order=False,
            target_association_tolerance=0.05,
            )
    fmm_qbx = QBXLayerPotentialSource(
            pre_density_discr, 4*target_order, qbx_order,
            fmm_order=qbx_order + 3,
            _expansions_in_tree_have_extent=True,
            target_association_tolerance=0.05,
            )

    fplot = FieldPlotter(np.zeros(2), extent=5, npoints=500)
    from pytential.target import PointsTarget
    ptarget = PointsTarget(fplot.points)
    from sumpy.kernel import LaplaceKernel

    places = GeometryCollection({
        "direct_qbx": direct_qbx,
        "fmm_qbx": fmm_qbx,
        "target": ptarget})

    direct_density_discr = places.get_discretization("direct_qbx")
    fmm_density_discr = places.get_discretization("fmm_qbx")

    from pytential.qbx import QBXTargetAssociationFailedException
    op = sym.D(LaplaceKernel(2), sym.var("sigma"), qbx_forced_limit=None)
    try:
        direct_sigma = direct_density_discr.zeros(actx) + 1
        direct_fld_in_vol = bind(places, op,
                auto_where=("direct_qbx", "target"))(
                        actx, sigma=direct_sigma)
    except QBXTargetAssociationFailedException as e:
        fplot.show_scalar_in_matplotlib(
            actx.to_numpy(actx.thaw(e.failed_target_flags)))
        import matplotlib.pyplot as pt
        pt.show()
        raise

    fmm_sigma = fmm_density_discr.zeros(actx) + 1
    fmm_fld_in_vol = bind(places, op,
            auto_where=("fmm_qbx", "target"))(
                    actx, sigma=fmm_sigma)

    err = actx.np.fabs(fmm_fld_in_vol - direct_fld_in_vol)
    linf_err = actx.to_numpy(err).max()
    print("l_inf error:", linf_err)

    if do_plot:
        #fplot.show_scalar_in_mayavi(0.1*.get(queue))
        fplot.write_vtk_file("potential.vts", [
            ("fmm_fld_in_vol", actx.to_numpy(fmm_fld_in_vol)),
            ("direct_fld_in_vol", actx.to_numpy(direct_fld_in_vol))
            ])

    assert linf_err < 1e-3
Example #18
0
def test_cost_model_correctness(ctx_factory, dim, off_surface,
        use_target_specific_qbx):
    """Check that computed cost matches that of a constant-one FMM."""
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

    cost_model = QBXCostModel(
        translation_cost_model_factory=OpCountingTranslationCostModel)

    lpot_source = get_lpot_source(actx, dim).copy(
            cost_model=cost_model,
            _use_target_specific_qbx=use_target_specific_qbx)

    # Construct targets.
    if off_surface:
        from pytential.target import PointsTarget
        from boxtree.tools import make_uniform_particle_array
        ntargets = 10 ** 3
        targets = PointsTarget(
                make_uniform_particle_array(queue, ntargets, dim, np.float))
        target_discrs_and_qbx_sides = ((targets, 0),)
        qbx_forced_limit = None
    else:
        targets = lpot_source.density_discr
        target_discrs_and_qbx_sides = ((targets, 1),)
        qbx_forced_limit = 1
    places = GeometryCollection((lpot_source, targets))

    source_dd = places.auto_source
    density_discr = places.get_discretization(source_dd.geometry)

    # Construct bound op, run cost model.
    sigma_sym = sym.var("sigma")
    k_sym = LaplaceKernel(lpot_source.ambient_dim)
    sym_op_S = sym.S(k_sym, sigma_sym, qbx_forced_limit=qbx_forced_limit)

    op_S = bind(places, sym_op_S)
    sigma = get_density(actx, density_discr)

    from pytools import one
    modeled_time, _ = op_S.cost_per_stage("constant_one", sigma=sigma)
    modeled_time = one(modeled_time.values())

    # Run FMM with ConstantOneWrangler. This can't be done with pytential's
    # high-level interface, so call the FMM driver directly.
    from pytential.qbx.fmm import drive_fmm
    geo_data = lpot_source.qbx_fmm_geometry_data(
            places, source_dd.geometry,
            target_discrs_and_qbx_sides=target_discrs_and_qbx_sides)

    wrangler = ConstantOneQBXExpansionWrangler(
            queue, geo_data, use_target_specific_qbx)

    quad_stage2_density_discr = places.get_discretization(
            source_dd.geometry, sym.QBX_SOURCE_QUAD_STAGE2)
    ndofs = quad_stage2_density_discr.ndofs
    src_weights = np.ones(ndofs)

    timing_data = {}
    potential = drive_fmm(wrangler, (src_weights,), timing_data,
            traversal=wrangler.trav)[0][geo_data.ncenters:]

    # Check constant one wrangler for correctness.
    assert (potential == ndofs).all()

    # Check that the cost model matches the timing data returned by the
    # constant one wrangler.
    mismatches = []
    for stage in timing_data:
        if stage not in modeled_time:
            assert timing_data[stage]["ops_elapsed"] == 0
        else:
            if timing_data[stage]["ops_elapsed"] != modeled_time[stage]:
                mismatches.append(
                    (stage, timing_data[stage]["ops_elapsed"], modeled_time[stage]))

    assert not mismatches, "\n".join(str(s) for s in mismatches)

    # {{{ Test per-box cost

    total_cost = 0.0
    for stage in timing_data:
        total_cost += timing_data[stage]["ops_elapsed"]

    per_box_cost, _ = op_S.cost_per_box("constant_one", sigma=sigma)
    print(per_box_cost)
    per_box_cost = one(per_box_cost.values())

    total_aggregate_cost = cost_model.aggregate_over_boxes(per_box_cost)
    assert total_cost == (
            total_aggregate_cost
            + modeled_time["coarsen_multipoles"]
            + modeled_time["refine_locals"]
    )
Example #19
0
def test_target_association(ctx_factory,
                            curve_name,
                            curve_f,
                            nelements,
                            visualize=False):
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

    # {{{ generate lpot source

    order = 16

    # Make the curve mesh.
    mesh = make_curve_mesh(curve_f, np.linspace(0, 1, nelements + 1), order)

    from meshmode.discretization import Discretization
    from meshmode.discretization.poly_element import \
            InterpolatoryQuadratureSimplexGroupFactory
    factory = InterpolatoryQuadratureSimplexGroupFactory(order)
    discr = Discretization(actx, mesh, factory)

    lpot_source = QBXLayerPotentialSource(
        discr,
        qbx_order=order,  # not used in target association
        fine_order=order)
    places = GeometryCollection(lpot_source)

    # }}}

    # {{{ generate targets

    from pyopencl.clrandom import PhiloxGenerator
    rng = PhiloxGenerator(cl_ctx, seed=RNG_SEED)

    dd = places.auto_source.to_stage1()
    centers = dof_array_to_numpy(
        actx,
        bind(
            places,
            sym.interleaved_expansion_centers(lpot_source.ambient_dim,
                                              dofdesc=dd))(actx))

    density_discr = places.get_discretization(dd.geometry)

    noise = actx.to_numpy(
        rng.uniform(queue, density_discr.ndofs, dtype=np.float, a=0.01, b=1.0))

    tunnel_radius = dof_array_to_numpy(
        actx,
        bind(
            places,
            sym._close_target_tunnel_radii(lpot_source.ambient_dim,
                                           dofdesc=dd))(actx))

    def targets_from_sources(sign, dist, dim=2):
        nodes = dof_array_to_numpy(
            actx,
            bind(places, sym.nodes(dim,
                                   dofdesc=dd))(actx).as_vector(np.object))
        normals = dof_array_to_numpy(
            actx,
            bind(places, sym.normal(dim,
                                    dofdesc=dd))(actx).as_vector(np.object))
        return actx.from_numpy(nodes + normals * sign * dist)

    from pytential.target import PointsTarget
    int_targets = PointsTarget(targets_from_sources(-1, noise * tunnel_radius))
    ext_targets = PointsTarget(targets_from_sources(+1, noise * tunnel_radius))
    far_targets = PointsTarget(
        targets_from_sources(+1, FAR_TARGET_DIST_FROM_SOURCE))

    # Create target discretizations.
    target_discrs = (
        # On-surface targets, interior
        (density_discr, -1),
        # On-surface targets, exterior
        (density_discr, +1),
        # Interior close targets
        (int_targets, -2),
        # Exterior close targets
        (ext_targets, +2),
        # Far targets, should not need centers
        (far_targets, 0),
    )

    sizes = np.cumsum([discr.ndofs for discr, _ in target_discrs])

    (
        surf_int_slice,
        surf_ext_slice,
        vol_int_slice,
        vol_ext_slice,
        far_slice,
    ) = [slice(start, end) for start, end in zip(np.r_[0, sizes], sizes)]

    # }}}

    # {{{ run target associator and check

    from pytential.qbx.target_assoc import (TargetAssociationCodeContainer,
                                            associate_targets_to_qbx_centers)

    from pytential.qbx.utils import TreeCodeContainer
    code_container = TargetAssociationCodeContainer(actx,
                                                    TreeCodeContainer(actx))

    target_assoc = (associate_targets_to_qbx_centers(
        places,
        places.auto_source,
        code_container.get_wrangler(actx),
        target_discrs,
        target_association_tolerance=1e-10).get(queue=queue))

    expansion_radii = dof_array_to_numpy(
        actx,
        bind(
            places,
            sym.expansion_radii(lpot_source.ambient_dim,
                                granularity=sym.GRANULARITY_CENTER))(actx))
    from meshmode.dof_array import thaw
    surf_targets = dof_array_to_numpy(actx, thaw(actx, density_discr.nodes()))
    int_targets = actx.to_numpy(int_targets.nodes())
    ext_targets = actx.to_numpy(ext_targets.nodes())

    def visualize_curve_and_assoc():
        import matplotlib.pyplot as plt
        from meshmode.mesh.visualization import draw_curve

        draw_curve(density_discr.mesh)

        targets = int_targets
        tgt_slice = surf_int_slice

        plt.plot(centers[0], centers[1], "+", color="orange")
        ax = plt.gca()

        for tx, ty, tcenter in zip(targets[0, tgt_slice], targets[1,
                                                                  tgt_slice],
                                   target_assoc.target_to_center[tgt_slice]):
            if tcenter >= 0:
                ax.add_artist(
                    plt.Line2D(
                        (tx, centers[0, tcenter]),
                        (ty, centers[1, tcenter]),
                    ))

        ax.set_aspect("equal")
        plt.show()

    if visualize:
        visualize_curve_and_assoc()

    # Checks that the targets match with centers on the appropriate side and
    # within the allowable distance.
    def check_close_targets(centers, targets, true_side, target_to_center,
                            target_to_side_result, tgt_slice):
        targets_have_centers = (target_to_center >= 0).all()
        assert targets_have_centers

        assert (target_to_side_result == true_side).all()

        TOL = 1e-3
        dists = la.norm((targets.T - centers.T[target_to_center]), axis=1)
        assert (dists <= (1 + TOL) * expansion_radii[target_to_center]).all()

    # Center side order = -1, 1, -1, 1, ...
    target_to_center_side = 2 * (target_assoc.target_to_center % 2) - 1

    # interior surface
    check_close_targets(centers, surf_targets, -1,
                        target_assoc.target_to_center[surf_int_slice],
                        target_to_center_side[surf_int_slice], surf_int_slice)

    # exterior surface
    check_close_targets(centers, surf_targets, +1,
                        target_assoc.target_to_center[surf_ext_slice],
                        target_to_center_side[surf_ext_slice], surf_ext_slice)

    # interior volume
    check_close_targets(centers, int_targets, -1,
                        target_assoc.target_to_center[vol_int_slice],
                        target_to_center_side[vol_int_slice], vol_int_slice)

    # exterior volume
    check_close_targets(centers, ext_targets, +1,
                        target_assoc.target_to_center[vol_ext_slice],
                        target_to_center_side[vol_ext_slice], vol_ext_slice)

    # Checks that far targets are not assigned a center.
    assert (target_assoc.target_to_center[far_slice] == -1).all()
Example #20
0
def test_single_plus_double_with_single_fmm(actx_factory, do_plot=False):
    logging.basicConfig(level=logging.INFO)

    actx = actx_factory()

    # prevent cache 'splosion
    from sympy.core.cache import clear_cache
    clear_cache()

    nelements = 300
    target_order = 8
    qbx_order = 3

    mesh = mgen.make_curve_mesh(mgen.WobblyCircle.random(8, seed=30),
                                np.linspace(0, 1, nelements + 1), target_order)

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

    pre_density_discr = Discretization(
        actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order))
    direct_qbx = QBXLayerPotentialSource(
        pre_density_discr,
        4 * target_order,
        qbx_order,
        fmm_order=False,
        target_association_tolerance=0.05,
    )
    fmm_qbx = QBXLayerPotentialSource(
        pre_density_discr,
        4 * target_order,
        qbx_order,
        fmm_order=qbx_order + 3,
        _expansions_in_tree_have_extent=True,
        target_association_tolerance=0.05,
    )

    fplot = FieldPlotter(np.zeros(2), extent=5, npoints=500)
    from pytential.target import PointsTarget
    ptarget = PointsTarget(actx.freeze(actx.from_numpy(fplot.points)))
    from sumpy.kernel import LaplaceKernel

    places = GeometryCollection(
        {
            "direct_qbx": direct_qbx,
            "fmm_qbx": fmm_qbx,
            "target": ptarget,
        },
        auto_where=("fmm_qbx", "target"))

    direct_density_discr = places.get_discretization("direct_qbx")
    fmm_density_discr = places.get_discretization("fmm_qbx")

    knl = LaplaceKernel(2)
    from pytential.qbx import QBXTargetAssociationFailedException
    op_d = sym.D(knl, sym.var("sigma"), qbx_forced_limit=None)
    op_s = sym.S(knl, sym.var("sigma"), qbx_forced_limit=None)
    op = op_d + op_s * 0.5
    try:
        direct_sigma = direct_density_discr.zeros(actx) + 1
        direct_fld_in_vol = bind(places,
                                 op,
                                 auto_where=("direct_qbx",
                                             "target"))(actx,
                                                        sigma=direct_sigma)
    except QBXTargetAssociationFailedException as e:
        fplot.show_scalar_in_matplotlib(
            actx.to_numpy(actx.thaw(e.failed_target_flags)))
        import matplotlib.pyplot as pt
        pt.show()
        raise

    fmm_sigma = fmm_density_discr.zeros(actx) + 1
    fmm_bound_op = bind(places, op, auto_where=("fmm_qbx", "target"))
    print(fmm_bound_op.code)
    fmm_fld_in_vol = fmm_bound_op(actx, sigma=fmm_sigma)

    err = actx.np.fabs(fmm_fld_in_vol - direct_fld_in_vol)
    linf_err = actx.to_numpy(err).max()
    print("l_inf error:", linf_err)

    if do_plot:
        fplot.write_vtk_file(
            "potential.vts",
            [("fmm_fld_in_vol", actx.to_numpy(fmm_fld_in_vol)),
             ("direct_fld_in_vol", actx.to_numpy(direct_fld_in_vol))])

    assert linf_err < 1e-3

    # check that using one FMM works
    op = op_d.copy(source_kernels=op_d.source_kernels + (knl, ),
                   densities=op_d.densities + (sym.var("sigma") * 0.5, ))
    single_fmm_bound_op = bind(places, op, auto_where=("fmm_qbx", "target"))
    print(single_fmm_bound_op.code)
    single_fmm_fld_in_vol = fmm_bound_op(actx, sigma=fmm_sigma)

    err = actx.np.fabs(fmm_fld_in_vol - single_fmm_fld_in_vol)
    linf_err = actx.to_numpy(err).max()
    print("l_inf error:", linf_err)

    assert linf_err < 1e-15
def run_test(cl_ctx, queue):

    q_order = 5
    qbx_order = q_order
    fmm_backend = "sumpy"
    mesh = get_ellipse_mesh(20, 40, mesh_order=5)
    a = 1
    b = 1 / 40

    if 0:
        from meshmode.mesh.visualization import draw_curve
        import matplotlib.pyplot as plt
        draw_curve(mesh)
        plt.axes().set_aspect('equal')
        plt.show()

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

    pre_density_discr = Discretization(
        cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(q_order))

    refiner_extra_kwargs = {
        # "_expansion_disturbance_tolerance": 0.05,
        "_scaled_max_curvature_threshold": 1,
        "maxiter": 10,
    }

    qbx, _ = QBXLayerPotentialSource(
        pre_density_discr,
        fine_order=4 * q_order,
        qbx_order=qbx_order,
        fmm_backend=fmm_backend,
        fmm_order=qbx_order + 5,
    ).with_refinement(**refiner_extra_kwargs)

    if 1:
        print("%d stage-1 elements after refinement" %
              qbx.density_discr.mesh.nelements)
        print("%d stage-2 elements after refinement" %
              qbx.stage2_density_discr.mesh.nelements)
        print("quad stage-2 elements have %d nodes" %
              qbx.quad_stage2_density_discr.groups[0].nunit_nodes)

    def reference_solu(rvec):
        # a harmonic function
        x, y = rvec
        return 2.1 * x * y + (x**2 - y**2) * 0.5 + x

    bvals = reference_solu(qbx.density_discr.nodes().with_queue(queue))

    from pytential.symbolic.pde.scalar import DirichletOperator
    from sumpy.kernel import LaplaceKernel
    from pytential import sym, bind
    op = DirichletOperator(LaplaceKernel(2), -1)

    bound_op = bind(qbx.copy(target_association_tolerance=0.5),
                    op.operator(sym.var('sigma')))
    rhs = bind(qbx.density_discr, op.prepare_rhs(sym.var("bc")))(queue,
                                                                 bc=bvals)

    from pytential.solve import gmres
    gmres_result = gmres(bound_op.scipy_op(queue, "sigma", dtype=np.float64),
                         rhs,
                         tol=1e-12,
                         progress=True,
                         hard_failure=True,
                         stall_iterations=50,
                         no_progress_factor=1.05)

    from sumpy.visualization import FieldPlotter
    from pytential.target import PointsTarget
    pltsize = b * 1.5
    fplot = FieldPlotter(np.array([-1 + pltsize * 0.5, 0]),
                         extent=pltsize * 1.05,
                         npoints=500)
    plt_targets = cl.array.to_device(queue, fplot.points)

    interior_pts = (fplot.points[0]**2 / a**2 +
                    fplot.points[1]**2 / b**2) < 0.99

    exact_vals = reference_solu(fplot.points)
    out_errs = []

    for assotol in [0.05]:

        qbx_stick_out = qbx.copy(target_association_tolerance=0.05)

        vol_solution = bind((qbx_stick_out, PointsTarget(plt_targets)),
                            op.representation(sym.var('sigma')))(
                                queue, sigma=gmres_result.solution).get()

        interior_error_linf = (
            np.linalg.norm(np.abs(vol_solution - exact_vals)[interior_pts],
                           ord=np.inf) /
            np.linalg.norm(exact_vals[interior_pts], ord=np.inf))

        interior_error_l2 = (np.linalg.norm(
            np.abs(vol_solution - exact_vals)[interior_pts], ord=2) /
                             np.linalg.norm(exact_vals[interior_pts], ord=2))

        print("\nassotol = %f" % assotol)
        print("L_inf Error = %e " % interior_error_linf)
        print("L_2 Error = %e " % interior_error_l2)

        out_errs.append(
            ("error-%f" % assotol, np.abs(vol_solution - exact_vals)))

    if 1:
        fplot.write_vtk_file("results.vts", out_errs)
Example #22
0
def main(mesh_name="ellipsoid"):
    import logging
    logger = logging.getLogger(__name__)
    logging.basicConfig(level=logging.WARNING)  # INFO for more progress info

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

    if mesh_name == "ellipsoid":
        cad_file_name = "geometries/ellipsoid.step"
        h = 0.6
    elif mesh_name == "two-cylinders":
        cad_file_name = "geometries/two-cylinders-smooth.step"
        h = 0.4
    else:
        raise ValueError("unknown mesh name: %s" % mesh_name)

    from meshmode.mesh.io import generate_gmsh, FileSource
    mesh = generate_gmsh(
        FileSource(cad_file_name),
        2,
        order=2,
        other_options=["-string",
                       "Mesh.CharacteristicLengthMax = %g;" % h],
        target_unit="MM")

    from meshmode.mesh.processing import perform_flips
    # Flip elements--gmsh generates inside-out geometry.
    mesh = perform_flips(mesh, np.ones(mesh.nelements))

    from meshmode.mesh.processing import find_bounding_box
    bbox_min, bbox_max = find_bounding_box(mesh)
    bbox_center = 0.5 * (bbox_min + bbox_max)
    bbox_size = max(bbox_max - bbox_min) / 2

    logger.info("%d elements" % mesh.nelements)

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

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

    qbx = QBXLayerPotentialSource(density_discr,
                                  4 * target_order,
                                  qbx_order,
                                  fmm_order=qbx_order + 3,
                                  target_association_tolerance=0.15)

    from pytential.target import PointsTarget
    fplot = FieldPlotter(bbox_center, extent=3.5 * bbox_size, npoints=150)

    from pytential import GeometryCollection
    places = GeometryCollection(
        {
            "qbx": qbx,
            "targets": PointsTarget(fplot.points)
        }, auto_where="qbx")
    density_discr = places.get_discretization("qbx")

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

    if k:
        kernel = HelmholtzKernel(3)
    else:
        kernel = LaplaceKernel(3)

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

    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)

    fld_in_vol = actx.to_numpy(
        bind(places, op, auto_where=("qbx", "targets"))(actx, sigma=sigma,
                                                        k=k))

    #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5)
    fplot.write_vtk_file("layerpot-3d-potential.vts",
                         [("potential", fld_in_vol)])

    bdry_normals = bind(places, sym.normal(
        density_discr.ambient_dim))(actx).as_vector(dtype=object)

    from meshmode.discretization.visualization import make_visualizer
    bdry_vis = make_visualizer(actx, density_discr, target_order)
    bdry_vis.write_vtk_file("layerpot-3d-density.vtu", [
        ("sigma", sigma),
        ("bdry_normals", bdry_normals),
    ])
Example #23
0
def main():
    # cl.array.to_device(queue, numpy_array)
    from meshmode.mesh.io import generate_gmsh, FileSource
    mesh = generate_gmsh(
        FileSource("ellipsoid.step"),
        2,
        order=2,
        other_options=["-string",
                       "Mesh.CharacteristicLengthMax = %g;" % h])

    from meshmode.mesh.processing import perform_flips
    # Flip elements--gmsh generates inside-out geometry.
    mesh = perform_flips(mesh, np.ones(mesh.nelements))

    print("%d elements" % mesh.nelements)

    from meshmode.mesh.processing import find_bounding_box
    bbox_min, bbox_max = find_bounding_box(mesh)
    bbox_center = 0.5 * (bbox_min + bbox_max)
    bbox_size = max(bbox_max - bbox_min) / 2

    logger.info("%d elements" % mesh.nelements)

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

    density_discr = Discretization(
        cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order))

    qbx = QBXLayerPotentialSource(density_discr,
                                  4 * target_order,
                                  qbx_order,
                                  fmm_order=qbx_order + 10,
                                  fmm_backend="fmmlib")

    from pytential.symbolic.pde.maxwell import MuellerAugmentedMFIEOperator
    pde_op = MuellerAugmentedMFIEOperator(
        omega=0.4,
        epss=[1.4, 1.0],
        mus=[1.2, 1.0],
    )
    from pytential import bind, sym

    unk = pde_op.make_unknown("sigma")
    sym_operator = pde_op.operator(unk)
    sym_rhs = pde_op.rhs(sym.make_sym_vector("Einc", 3),
                         sym.make_sym_vector("Hinc", 3))
    sym_repr = pde_op.representation(0, unk)

    if 1:
        expr = sym_repr
        print(sym.pretty(expr))

        print("#" * 80)
        from pytential.target import PointsTarget

        tgt_points = np.zeros((3, 1))
        tgt_points[0, 0] = 100
        tgt_points[1, 0] = -200
        tgt_points[2, 0] = 300

        bound_op = bind((qbx, PointsTarget(tgt_points)), expr)
        print(bound_op.code)

    if 1:

        def green3e(x, y, z, source, strength, k):
            # electric field corresponding to dyadic green's function
            # due to monochromatic electric dipole located at "source".
            # "strength" is the the intensity of the dipole.
            #  E = (I + Hess)(exp(ikr)/r) dot (strength)
            #
            dx = x - source[0]
            dy = y - source[1]
            dz = z - source[2]
            rr = np.sqrt(dx**2 + dy**2 + dz**2)

            fout = np.exp(1j * k * rr) / rr
            evec = fout * strength
            qmat = np.zeros((3, 3), dtype=np.complex128)

            qmat[0, 0] = (2 * dx**2 - dy**2 - dz**2) * (1 - 1j * k * rr)
            qmat[1, 1] = (2 * dy**2 - dz**2 - dx**2) * (1 - 1j * k * rr)
            qmat[2, 2] = (2 * dz**2 - dx**2 - dy**2) * (1 - 1j * k * rr)

            qmat[0, 0] = qmat[0, 0] + (-k**2 * dx**2 * rr**2)
            qmat[1, 1] = qmat[1, 1] + (-k**2 * dy**2 * rr**2)
            qmat[2, 2] = qmat[2, 2] + (-k**2 * dz**2 * rr**2)

            qmat[0, 1] = (3 - k**2 * rr**2 - 3 * 1j * k * rr) * (dx * dy)
            qmat[1, 2] = (3 - k**2 * rr**2 - 3 * 1j * k * rr) * (dy * dz)
            qmat[2, 0] = (3 - k**2 * rr**2 - 3 * 1j * k * rr) * (dz * dx)

            qmat[1, 0] = qmat[0, 1]
            qmat[2, 1] = qmat[1, 2]
            qmat[0, 2] = qmat[2, 0]

            fout = np.exp(1j * k * rr) / rr**5 / k**2

            fvec = fout * np.dot(qmat, strength)
            evec = evec + fvec
            return evec

        def green3m(x, y, z, source, strength, k):
            # magnetic field corresponding to dyadic green's function
            # due to monochromatic electric dipole located at "source".
            # "strength" is the the intensity of the dipole.
            #  H = curl((I + Hess)(exp(ikr)/r) dot (strength)) =
            #  strength \cross \grad (exp(ikr)/r)
            #
            dx = x - source[0]
            dy = y - source[1]
            dz = z - source[2]
            rr = np.sqrt(dx**2 + dy**2 + dz**2)

            fout = (1 - 1j * k * rr) * np.exp(1j * k * rr) / rr**3
            fvec = np.zeros(3, dtype=np.complex128)
            fvec[0] = fout * dx
            fvec[1] = fout * dy
            fvec[2] = fout * dz

            hvec = np.cross(strength, fvec)

            return hvec

        def dipole3e(x, y, z, source, strength, k):
            #
            #  evalaute electric and magnetic field due
            #  to monochromatic electric dipole located at "source"
            #  with intensity "strength"

            evec = green3e(x, y, z, source, strength, k)
            evec = evec * 1j * k
            hvec = green3m(x, y, z, source, strength, k)
            return evec, hvec

        def dipole3m(x, y, z, source, strength, k):
            #
            #  evalaute electric and magnetic field due
            #  to monochromatic magnetic dipole located at "source"
            #  with intensity "strength"
            evec = green3m(x, y, z, source, strength, k)
            hvec = green3e(x, y, z, source, strength, k)
            hvec = -hvec * 1j * k
            return evec, hvec

        def dipole3eall(x, y, z, sources, strengths, k):
            ns = len(strengths)
            evec = np.zeros(3, dtype=np.complex128)
            hvec = np.zeros(3, dtype=np.complex128)

            for i in range(ns):
                evect, hvect = dipole3e(x, y, z, sources[i], strengths[i], k)
                evec = evec + evect
                hvec = hvec + hvect

        nodes = density_discr.nodes().with_queue(queue).get()
        source = [0.01, -0.03, 0.02]
        #        source = cl.array.to_device(queue,np.zeros(3))
        #        source[0] = 0.01
        #        source[1] =-0.03
        #        source[2] = 0.02
        strength = np.ones(3)

        #        evec = cl.array.to_device(queue,np.zeros((3,len(nodes[0])),dtype=np.complex128))
        #        hvec = cl.array.to_device(queue,np.zeros((3,len(nodes[0])),dtype=np.complex128))

        evec = np.zeros((3, len(nodes[0])), dtype=np.complex128)
        hvec = np.zeros((3, len(nodes[0])), dtype=np.complex128)
        for i in range(len(nodes[0])):
            evec[:, i], hvec[:, i] = dipole3e(nodes[0][i], nodes[1][i],
                                              nodes[2][i], source, strength, k)
        print(np.shape(hvec))
        print(type(evec))
        print(type(hvec))

        evec = cl.array.to_device(queue, evec)
        hvec = cl.array.to_device(queue, hvec)

        bvp_rhs = bind(qbx, sym_rhs)(queue, Einc=evec, Hinc=hvec)
        print(np.shape(bvp_rhs))
        print(type(bvp_rhs))
        #        print(bvp_rhs)
        1 / -1

        bound_op = bind(qbx, sym_operator)

        from pytential.solve import gmres
        if 0:
            gmres_result = gmres(bound_op.scipy_op(queue,
                                                   "sigma",
                                                   dtype=np.complex128,
                                                   k=k),
                                 bvp_rhs,
                                 tol=1e-8,
                                 progress=True,
                                 stall_iterations=0,
                                 hard_failure=True)

            sigma = gmres_result.solution

        fld_at_tgt = bind((qbx, PointsTarget(tgt_points)),
                          sym_repr)(queue, sigma=bvp_rhs, k=k)
        fld_at_tgt = np.array([fi.get() for fi in fld_at_tgt])
        print(fld_at_tgt)
        1 / 0

    # }}}

    #mlab.figure(bgcolor=(1, 1, 1))
    if 1:
        from meshmode.discretization.visualization import make_visualizer
        bdry_vis = make_visualizer(queue, density_discr, target_order)

        bdry_normals = bind(density_discr, sym.normal(3))(queue)\
                .as_vector(dtype=object)

        bdry_vis.write_vtk_file("source.vtu", [
            ("sigma", sigma),
            ("bdry_normals", bdry_normals),
        ])

        fplot = FieldPlotter(bbox_center,
                             extent=2 * bbox_size,
                             npoints=(150, 150, 1))

        qbx_tgt_tol = qbx.copy(target_association_tolerance=0.1)
        from pytential.target import PointsTarget
        from pytential.qbx import QBXTargetAssociationFailedException

        rho_sym = sym.var("rho")

        try:
            fld_in_vol = bind((qbx_tgt_tol, PointsTarget(fplot.points)),
                              sym.make_obj_array([
                                  sym.S(pde_op.kernel,
                                        rho_sym,
                                        k=sym.var("k"),
                                        qbx_forced_limit=None),
                                  sym.d_dx(
                                      3,
                                      sym.S(pde_op.kernel,
                                            rho_sym,
                                            k=sym.var("k"),
                                            qbx_forced_limit=None)),
                                  sym.d_dy(
                                      3,
                                      sym.S(pde_op.kernel,
                                            rho_sym,
                                            k=sym.var("k"),
                                            qbx_forced_limit=None)),
                                  sym.d_dz(
                                      3,
                                      sym.S(pde_op.kernel,
                                            rho_sym,
                                            k=sym.var("k"),
                                            qbx_forced_limit=None)),
                              ]))(queue, jt=jt, rho=rho, k=k)
        except QBXTargetAssociationFailedException as e:
            fplot.write_vtk_file(
                "failed-targets.vts",
                [("failed_targets", e.failed_target_flags.get(queue))])
            raise

        fld_in_vol = sym.make_obj_array([fiv.get() for fiv in fld_in_vol])

        #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5)
        fplot.write_vtk_file("potential.vts", [
            ("potential", fld_in_vol[0]),
            ("grad", fld_in_vol[1:]),
        ])
    # plotting grid points
    ambient_dim = qbx.ambient_dim
    if visualize:
        vis_grid_spacing = getattr(case, "vis_grid_spacing",
                                   (0.1, 0.1, 0.1)[:ambient_dim])
        vis_extend_factor = getattr(case, "vis_extend_factor", 0.2)

        from sumpy.visualization import make_field_plotter_from_bbox
        from meshmode.mesh.processing import find_bounding_box
        fplot = make_field_plotter_from_bbox(find_bounding_box(
            qbx.density_discr.mesh),
                                             h=vis_grid_spacing,
                                             extend_factor=vis_extend_factor)

        from pytential.target import PointsTarget
        plot_targets = PointsTarget(fplot.points)

        places.update({
            "qbx_target_tol":
            qbx.copy(target_association_tolerance=0.15),
            "plot_targets":
            plot_targets
        })

    places = GeometryCollection(places, auto_where=case.name)
    if case.use_refinement:
        from pytential.qbx.refinement import refine_geometry_collection
        places = refine_geometry_collection(places, **refiner_extra_kwargs)

    dd = sym.as_dofdesc(case.name).to_stage1()
    density_discr = places.get_discretization(dd.geometry)
Example #25
0
def run_exterior_stokes_2d(ctx_factory,
                           nelements,
                           mesh_order=4,
                           target_order=4,
                           qbx_order=4,
                           fmm_order=10,
                           mu=1,
                           circle_rad=1.5,
                           do_plot=False):

    # This program tests an exterior Stokes flow in 2D using the
    # compound representation given in Hsiao & Kress,
    # ``On an integral equation for the two-dimensional exterior Stokes problem,''
    # Applied Numerical Mathematics 1 (1985).

    logging.basicConfig(level=logging.INFO)

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

    ovsmp_target_order = 4 * target_order

    from meshmode.mesh.generation import (  # noqa
        make_curve_mesh, starfish, ellipse, drop)
    mesh = make_curve_mesh(lambda t: circle_rad * ellipse(1, t),
                           np.linspace(0, 1, nelements + 1), target_order)
    coarse_density_discr = Discretization(
        cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order))

    from pytential.qbx import QBXLayerPotentialSource
    target_association_tolerance = 0.05
    qbx, _ = QBXLayerPotentialSource(
        coarse_density_discr,
        fine_order=ovsmp_target_order,
        qbx_order=qbx_order,
        fmm_order=fmm_order,
        target_association_tolerance=target_association_tolerance,
        _expansions_in_tree_have_extent=True,
    ).with_refinement()

    density_discr = qbx.density_discr
    normal = bind(density_discr, sym.normal(2).as_vector())(queue)
    path_length = bind(density_discr, sym.integral(2, 1, 1))(queue)

    # {{{ describe bvp

    from pytential.symbolic.stokes import StressletWrapper, StokesletWrapper
    dim = 2
    cse = sym.cse

    sigma_sym = sym.make_sym_vector("sigma", dim)
    meanless_sigma_sym = cse(sigma_sym - sym.mean(2, 1, sigma_sym))
    int_sigma = sym.Ones() * sym.integral(2, 1, sigma_sym)

    nvec_sym = sym.make_sym_vector("normal", dim)
    mu_sym = sym.var("mu")

    # -1 for interior Dirichlet
    # +1 for exterior Dirichlet
    loc_sign = 1

    stresslet_obj = StressletWrapper(dim=2)
    stokeslet_obj = StokesletWrapper(dim=2)
    bdry_op_sym = (-loc_sign * 0.5 * sigma_sym - stresslet_obj.apply(
        sigma_sym, nvec_sym, mu_sym, qbx_forced_limit='avg') +
                   stokeslet_obj.apply(
                       meanless_sigma_sym, mu_sym, qbx_forced_limit='avg') -
                   (0.5 / np.pi) * int_sigma)

    # }}}

    bound_op = bind(qbx, bdry_op_sym)

    # {{{ fix rhs and solve

    def fund_soln(x, y, loc, strength):
        #with direction (1,0) for point source
        r = cl.clmath.sqrt((x - loc[0])**2 + (y - loc[1])**2)
        scaling = strength / (4 * np.pi * mu)
        xcomp = (-cl.clmath.log(r) + (x - loc[0])**2 / r**2) * scaling
        ycomp = ((x - loc[0]) * (y - loc[1]) / r**2) * scaling
        return [xcomp, ycomp]

    def rotlet_soln(x, y, loc):
        r = cl.clmath.sqrt((x - loc[0])**2 + (y - loc[1])**2)
        xcomp = -(y - loc[1]) / r**2
        ycomp = (x - loc[0]) / r**2
        return [xcomp, ycomp]

    def fund_and_rot_soln(x, y, loc, strength):
        #with direction (1,0) for point source
        r = cl.clmath.sqrt((x - loc[0])**2 + (y - loc[1])**2)
        scaling = strength / (4 * np.pi * mu)
        xcomp = ((-cl.clmath.log(r) + (x - loc[0])**2 / r**2) * scaling -
                 (y - loc[1]) * strength * 0.125 / r**2 + 3.3)
        ycomp = (((x - loc[0]) * (y - loc[1]) / r**2) * scaling +
                 (x - loc[0]) * strength * 0.125 / r**2 + 1.5)
        return [xcomp, ycomp]

    nodes = density_discr.nodes().with_queue(queue)
    fund_soln_loc = np.array([0.5, -0.2])
    strength = 100.
    bc = fund_and_rot_soln(nodes[0], nodes[1], fund_soln_loc, strength)

    omega_sym = sym.make_sym_vector("omega", dim)
    u_A_sym_bdry = stokeslet_obj.apply(  # noqa: N806
        omega_sym, mu_sym, qbx_forced_limit=1)

    omega = [
        cl.array.to_device(queue,
                           (strength / path_length) * np.ones(len(nodes[0]))),
        cl.array.to_device(queue, np.zeros(len(nodes[0])))
    ]
    bvp_rhs = bind(qbx,
                   sym.make_sym_vector("bc", dim) + u_A_sym_bdry)(queue,
                                                                  bc=bc,
                                                                  mu=mu,
                                                                  omega=omega)
    gmres_result = gmres(bound_op.scipy_op(queue,
                                           "sigma",
                                           np.float64,
                                           mu=mu,
                                           normal=normal),
                         bvp_rhs,
                         x0=bvp_rhs,
                         tol=1e-9,
                         progress=True,
                         stall_iterations=0,
                         hard_failure=True)

    # }}}

    # {{{ postprocess/visualize

    sigma = gmres_result.solution
    sigma_int_val_sym = sym.make_sym_vector("sigma_int_val", 2)
    int_val = bind(qbx, sym.integral(2, 1, sigma_sym))(queue, sigma=sigma)
    int_val = -int_val / (2 * np.pi)
    print("int_val = ", int_val)

    u_A_sym_vol = stokeslet_obj.apply(  # noqa: N806
        omega_sym, mu_sym, qbx_forced_limit=2)
    representation_sym = (
        -stresslet_obj.apply(sigma_sym, nvec_sym, mu_sym, qbx_forced_limit=2) +
        stokeslet_obj.apply(meanless_sigma_sym, mu_sym, qbx_forced_limit=2) -
        u_A_sym_vol + sigma_int_val_sym)

    nsamp = 30
    eval_points_1d = np.linspace(-3., 3., nsamp)
    eval_points = np.zeros((2, len(eval_points_1d)**2))
    eval_points[0, :] = np.tile(eval_points_1d, len(eval_points_1d))
    eval_points[1, :] = np.repeat(eval_points_1d, len(eval_points_1d))

    def circle_mask(test_points, radius):
        return (test_points[0, :]**2 + test_points[1, :]**2 > radius**2)

    def outside_circle(test_points, radius):
        mask = circle_mask(test_points, radius)
        return np.array([row[mask] for row in test_points])

    eval_points = outside_circle(eval_points, radius=circle_rad)
    from pytential.target import PointsTarget
    vel = bind((qbx, PointsTarget(eval_points)),
               representation_sym)(queue,
                                   sigma=sigma,
                                   mu=mu,
                                   normal=normal,
                                   sigma_int_val=int_val,
                                   omega=omega)
    print("@@@@@@@@")

    fplot = FieldPlotter(np.zeros(2), extent=6, npoints=100)
    plot_pts = outside_circle(fplot.points, radius=circle_rad)
    plot_vel = bind((qbx, PointsTarget(plot_pts)),
                    representation_sym)(queue,
                                        sigma=sigma,
                                        mu=mu,
                                        normal=normal,
                                        sigma_int_val=int_val,
                                        omega=omega)

    def get_obj_array(obj_array):
        return make_obj_array([ary.get() for ary in obj_array])

    exact_soln = fund_and_rot_soln(cl.array.to_device(queue, eval_points[0]),
                                   cl.array.to_device(queue, eval_points[1]),
                                   fund_soln_loc, strength)

    vel = get_obj_array(vel)
    err = vel - get_obj_array(exact_soln)

    # FIXME: Pointwise relative errors don't make sense!
    rel_err = err / (get_obj_array(exact_soln))

    if 0:
        print("@@@@@@@@")
        print("vel[0], err[0], rel_err[0] ***** vel[1], err[1], rel_err[1]: ")
        for i in range(len(vel[0])):
            print("%15.8e, %15.8e, %15.8e ***** %15.8e, %15.8e, %15.8e\n" %
                  (vel[0][i], err[0][i], rel_err[0][i], vel[1][i], err[1][i],
                   rel_err[1][i]))

        print("@@@@@@@@")

    l2_err = np.sqrt((6. / (nsamp - 1))**2 * np.sum(err[0] * err[0]) +
                     (6. / (nsamp - 1))**2 * np.sum(err[1] * err[1]))
    l2_rel_err = np.sqrt((6. /
                          (nsamp - 1))**2 * np.sum(rel_err[0] * rel_err[0]) +
                         (6. /
                          (nsamp - 1))**2 * np.sum(rel_err[1] * rel_err[1]))

    print("L2 error estimate: ", l2_err)
    print("L2 rel error estimate: ", l2_rel_err)
    print("max error at sampled points: ", max(abs(err[0])), max(abs(err[1])))
    print("max rel error at sampled points: ", max(abs(rel_err[0])),
          max(abs(rel_err[1])))

    if do_plot:
        import matplotlib
        matplotlib.use("Agg")
        import matplotlib.pyplot as plt

        full_pot = np.zeros_like(fplot.points) * float("nan")
        mask = circle_mask(fplot.points, radius=circle_rad)

        for i, vel in enumerate(plot_vel):
            full_pot[i, mask] = vel.get()

        plt.quiver(fplot.points[0],
                   fplot.points[1],
                   full_pot[0],
                   full_pot[1],
                   linewidth=0.1)
        plt.savefig("exterior-2d-field.pdf")

    # }}}

    h_max = bind(qbx, sym.h_max(qbx.ambient_dim))(queue)
    return h_max, l2_err
Example #26
0
def main(curve_fn=starfish, visualize=True):
    import logging
    logging.basicConfig(level=logging.WARNING)  # INFO for more progress info

    import pyopencl as cl
    cl_ctx = cl.create_some_context()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue, force_device_scalars=True)

    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.discretization import Discretization
    from meshmode.discretization.poly_element import \
            InterpolatoryQuadratureSimplexGroupFactory

    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,
            #fmm_backend="fmmlib",
            )

    from pytential.target import PointsTarget
    fplot = FieldPlotter(np.zeros(2), extent=5, npoints=1000)
    targets_dev = actx.from_numpy(fplot.points)

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

    density_discr = places.get_discretization("qbx")

    nodes = thaw(density_discr.nodes(), actx)
    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)

    if 0:
        from random import randrange
        sigma = actx.zeros(density_discr.ndofs, angle.entry_dtype)
        for _ in range(5):
            sigma[randrange(len(sigma))] = 1

        from arraycontext import unflatten
        sigma = unflatten(angle, sigma, actx)
    else:
        sigma = actx.np.cos(mode_nr*angle)

    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 arraycontext import flatten
        fld_on_bdry = actx.to_numpy(
                flatten(bound_bdry_op(actx, sigma=sigma, k=k), actx))
        nodes_host = actx.to_numpy(
                flatten(density_discr.nodes(), actx)
                ).reshape(density_discr.ambient_dim, -1)

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

        mlab.colorbar()
        mlab.show()
Example #27
0
def test_target_association(ctx_getter, curve_name, curve_f, nelements,
        visualize=False):
    cl_ctx = ctx_getter()
    queue = cl.CommandQueue(cl_ctx)

    # {{{ generate lpot source

    order = 16

    # Make the curve mesh.
    mesh = make_curve_mesh(curve_f, np.linspace(0, 1, nelements+1), order)

    from meshmode.discretization import Discretization
    from meshmode.discretization.poly_element import \
            InterpolatoryQuadratureSimplexGroupFactory
    factory = InterpolatoryQuadratureSimplexGroupFactory(order)

    discr = Discretization(cl_ctx, mesh, factory)

    lpot_source, conn = QBXLayerPotentialSource(discr,
            qbx_order=order,  # not used in target association
            fine_order=order).with_refinement()
    del discr

    from pytential.qbx.utils import get_interleaved_centers
    centers = np.array([ax.get(queue)
            for ax in get_interleaved_centers(queue, lpot_source)])

    # }}}

    # {{{ generate targets

    from pyopencl.clrandom import PhiloxGenerator
    rng = PhiloxGenerator(cl_ctx, seed=RNG_SEED)
    nsources = lpot_source.density_discr.nnodes
    noise = rng.uniform(queue, nsources, dtype=np.float, a=0.01, b=1.0)
    tunnel_radius = \
            lpot_source._close_target_tunnel_radius("nsources").with_queue(queue)

    def targets_from_sources(sign, dist):
        from pytential import sym, bind
        dim = 2
        nodes = bind(lpot_source.density_discr, sym.nodes(dim))(queue)
        normals = bind(lpot_source.density_discr, sym.normal(dim))(queue)
        return (nodes + normals * sign * dist).as_vector(np.object)

    from pytential.target import PointsTarget

    int_targets = PointsTarget(targets_from_sources(-1, noise * tunnel_radius))
    ext_targets = PointsTarget(targets_from_sources(+1, noise * tunnel_radius))
    far_targets = PointsTarget(targets_from_sources(+1, FAR_TARGET_DIST_FROM_SOURCE))

    # Create target discretizations.
    target_discrs = (
        # On-surface targets, interior
        (lpot_source.density_discr, -1),
        # On-surface targets, exterior
        (lpot_source.density_discr, +1),
        # Interior close targets
        (int_targets, -2),
        # Exterior close targets
        (ext_targets, +2),
        # Far targets, should not need centers
        (far_targets, 0),
    )

    sizes = np.cumsum([discr.nnodes for discr, _ in target_discrs])

    (surf_int_slice,
     surf_ext_slice,
     vol_int_slice,
     vol_ext_slice,
     far_slice,
     ) = [slice(start, end) for start, end in zip(np.r_[0, sizes], sizes)]

    # }}}

    # {{{ run target associator and check

    from pytential.qbx.target_assoc import (
            TargetAssociationCodeContainer, associate_targets_to_qbx_centers)

    from pytential.qbx.utils import TreeCodeContainer

    code_container = TargetAssociationCodeContainer(
            cl_ctx, TreeCodeContainer(cl_ctx))

    target_assoc = (associate_targets_to_qbx_centers(
            lpot_source,
            code_container.get_wrangler(queue),
            target_discrs,
            target_association_tolerance=1e-10)
        .get(queue=queue))

    expansion_radii = lpot_source._expansion_radii("ncenters").get(queue)

    surf_targets = np.array(
            [axis.get(queue) for axis in lpot_source.density_discr.nodes()])
    int_targets = np.array([axis.get(queue) for axis in int_targets.nodes()])
    ext_targets = np.array([axis.get(queue) for axis in ext_targets.nodes()])

    def visualize_curve_and_assoc():
        import matplotlib.pyplot as plt
        from meshmode.mesh.visualization import draw_curve

        draw_curve(lpot_source.density_discr.mesh)

        targets = int_targets
        tgt_slice = surf_int_slice

        plt.plot(centers[0], centers[1], "+", color="orange")
        ax = plt.gca()

        for tx, ty, tcenter in zip(
                targets[0, tgt_slice],
                targets[1, tgt_slice],
                target_assoc.target_to_center[tgt_slice]):
            if tcenter >= 0:
                ax.add_artist(
                        plt.Line2D(
                            (tx, centers[0, tcenter]),
                            (ty, centers[1, tcenter]),
                            ))

        ax.set_aspect("equal")
        plt.show()

    if visualize:
        visualize_curve_and_assoc()

    # Checks that the targets match with centers on the appropriate side and
    # within the allowable distance.
    def check_close_targets(centers, targets, true_side,
                            target_to_center, target_to_side_result,
                            tgt_slice):
        targets_have_centers = (target_to_center >= 0).all()
        assert targets_have_centers

        assert (target_to_side_result == true_side).all()

        TOL = 1e-3
        dists = la.norm((targets.T - centers.T[target_to_center]), axis=1)
        assert (dists <= (1 + TOL) * expansion_radii[target_to_center]).all()

    # Center side order = -1, 1, -1, 1, ...
    target_to_center_side = 2 * (target_assoc.target_to_center % 2) - 1

    # interior surface
    check_close_targets(
        centers, surf_targets, -1,
        target_assoc.target_to_center[surf_int_slice],
        target_to_center_side[surf_int_slice],
        surf_int_slice)

    # exterior surface
    check_close_targets(
        centers, surf_targets, +1,
        target_assoc.target_to_center[surf_ext_slice],
        target_to_center_side[surf_ext_slice],
        surf_ext_slice)

    # interior volume
    check_close_targets(
        centers, int_targets, -1,
        target_assoc.target_to_center[vol_int_slice],
        target_to_center_side[vol_int_slice],
        vol_int_slice)

    # exterior volume
    check_close_targets(
        centers, ext_targets, +1,
        target_assoc.target_to_center[vol_ext_slice],
        target_to_center_side[vol_ext_slice],
        vol_ext_slice)

    # Checks that far targets are not assigned a center.
    assert (target_assoc.target_to_center[far_slice] == -1).all()
Example #28
0
def main():
    import logging
    logger = logging.getLogger(__name__)
    logging.basicConfig(level=logging.WARNING)  # INFO for more progress info

    from meshmode.mesh.io import generate_gmsh, FileSource
    mesh = generate_gmsh(
            FileSource(cad_file_name), 2, order=2,
            other_options=["-string", "Mesh.CharacteristicLengthMax = %g;" % h])

    from meshmode.mesh.processing import perform_flips
    # Flip elements--gmsh generates inside-out geometry.
    mesh = perform_flips(mesh, np.ones(mesh.nelements))

    from meshmode.mesh.processing import find_bounding_box
    bbox_min, bbox_max = find_bounding_box(mesh)
    bbox_center = 0.5*(bbox_min+bbox_max)
    bbox_size = max(bbox_max-bbox_min) / 2

    logger.info("%d elements" % mesh.nelements)

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

    density_discr = Discretization(
            cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order))

    qbx, _ = QBXLayerPotentialSource(density_discr, 4*target_order, qbx_order,
            fmm_order=qbx_order + 3,
            target_association_tolerance=0.15).with_refinement()

    nodes = density_discr.nodes().with_queue(queue)

    angle = cl.clmath.atan2(nodes[1], nodes[0])

    from pytential import bind, sym
    #op = sym.d_dx(sym.S(kernel, sym.var("sigma"), qbx_forced_limit=None))
    op = sym.D(kernel, sym.var("sigma"), qbx_forced_limit=None)
    #op = sym.S(kernel, sym.var("sigma"), qbx_forced_limit=None)

    sigma = cl.clmath.cos(mode_nr*angle)
    if 0:
        sigma = 0*angle
        from random import randrange
        for i in range(5):
            sigma[randrange(len(sigma))] = 1

    if isinstance(kernel, HelmholtzKernel):
        sigma = sigma.astype(np.complex128)

    fplot = FieldPlotter(bbox_center, extent=3.5*bbox_size, npoints=150)

    from pytential.target import PointsTarget
    fld_in_vol = bind(
            (qbx, PointsTarget(fplot.points)),
            op)(queue, sigma=sigma, k=k).get()

    #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5)
    fplot.write_vtk_file(
            "potential-3d.vts",
            [
                ("potential", fld_in_vol)
                ]
            )

    bdry_normals = bind(
            density_discr,
            sym.normal(density_discr.ambient_dim))(queue).as_vector(dtype=object)

    from meshmode.discretization.visualization import make_visualizer
    bdry_vis = make_visualizer(queue, density_discr, target_order)

    bdry_vis.write_vtk_file("source-3d.vtu", [
        ("sigma", sigma),
        ("bdry_normals", bdry_normals),
        ])
def main():
    logging.basicConfig(level=logging.INFO)

    nelements = 60
    qbx_order = 3
    k_fac = 4
    k0 = 3 * k_fac
    k1 = 2.9 * k_fac
    mesh_order = 10
    bdry_quad_order = mesh_order
    bdry_ovsmp_quad_order = bdry_quad_order * 4
    fmm_order = qbx_order * 2

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

    from meshmode.mesh.generation import ellipse, make_curve_mesh
    from functools import partial
    mesh = make_curve_mesh(partial(ellipse, 3),
                           np.linspace(0, 1, nelements + 1), mesh_order)

    density_discr = Discretization(
        cl_ctx, mesh,
        InterpolatoryQuadratureSimplexGroupFactory(bdry_quad_order))

    logger.info("%d elements" % mesh.nelements)

    # from meshmode.discretization.visualization import make_visualizer
    # bdry_vis = make_visualizer(queue, density_discr, 20)

    # {{{ solve bvp

    from sumpy.kernel import HelmholtzKernel
    kernel = HelmholtzKernel(2)

    beta = 2.5 * k_fac
    K0 = np.sqrt(k0**2 - beta**2)
    K1 = np.sqrt(k1**2 - beta**2)

    from pytential.symbolic.pde.scalar import DielectricSDRep2DBoundaryOperator
    pde_op = DielectricSDRep2DBoundaryOperator(
        mode='tm',
        k_vacuum=1,
        interfaces=((0, 1, sym.DEFAULT_SOURCE), ),
        domain_k_exprs=(k0, k1),
        beta=beta)

    op_unknown_sym = pde_op.make_unknown("unknown")

    representation0_sym = pde_op.representation(op_unknown_sym, 0)
    representation1_sym = pde_op.representation(op_unknown_sym, 1)

    from pytential.qbx import QBXLayerPotentialSource
    qbx = QBXLayerPotentialSource(density_discr,
                                  fine_order=bdry_ovsmp_quad_order,
                                  qbx_order=qbx_order,
                                  fmm_order=fmm_order)

    bound_pde_op = bind(qbx, pde_op.operator(op_unknown_sym))

    # in inner domain
    sources_1 = make_obj_array(list(np.array([[-1.5, 0.5]]).T.copy()))
    strengths_1 = np.array([1])

    from sumpy.p2p import P2P
    pot_p2p = P2P(cl_ctx, [kernel], exclude_self=False)

    _, (Einc, ) = pot_p2p(queue,
                          density_discr.nodes(),
                          sources_1, [strengths_1],
                          out_host=False,
                          k=K0)

    sqrt_w = bind(density_discr, sym.sqrt_jac_q_weight())(queue)

    bvp_rhs = np.zeros(len(pde_op.bcs), dtype=object)
    for i_bc, terms in enumerate(pde_op.bcs):
        for term in terms:
            assert term.i_interface == 0
            assert term.field_kind == pde_op.field_kind_e

            if term.direction == pde_op.dir_none:
                bvp_rhs[i_bc] += (term.coeff_outer * (-Einc))
            elif term.direction == pde_op.dir_normal:
                # no jump in normal derivative
                bvp_rhs[i_bc] += 0 * Einc
            else:
                raise NotImplementedError("direction spec in RHS")

        bvp_rhs[i_bc] *= sqrt_w

    from pytential.solve import gmres
    gmres_result = gmres(bound_pde_op.scipy_op(queue,
                                               "unknown",
                                               dtype=np.complex128,
                                               domains=[sym.DEFAULT_TARGET] *
                                               2,
                                               K0=K0,
                                               K1=K1),
                         bvp_rhs,
                         tol=1e-6,
                         progress=True,
                         hard_failure=True,
                         stall_iterations=0)

    # }}}

    unknown = gmres_result.solution

    # {{{ visualize

    from pytential.qbx import QBXLayerPotentialSource
    lap_qbx = QBXLayerPotentialSource(density_discr,
                                      fine_order=bdry_ovsmp_quad_order,
                                      qbx_order=qbx_order,
                                      fmm_order=qbx_order)

    from sumpy.visualization import FieldPlotter
    fplot = FieldPlotter(np.zeros(2), extent=5, npoints=300)
    from pytential.target import PointsTarget
    fld0 = bind((qbx, PointsTarget(fplot.points)),
                representation0_sym)(queue, unknown=unknown, K0=K0).get()
    fld1 = bind((qbx, PointsTarget(fplot.points)),
                representation1_sym)(queue, unknown=unknown, K1=K1).get()
    ones = cl.array.empty(queue, density_discr.nnodes, np.float64)
    dom1_indicator = -bind(
        (lap_qbx, PointsTarget(fplot.points)), sym.D(0, sym.var("sigma")))(
            queue, sigma=ones.fill(1)).get()
    _, (fld_inc_vol, ) = pot_p2p(queue,
                                 fplot.points,
                                 sources_1, [strengths_1],
                                 out_host=True,
                                 k=K0)

    #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5)
    fplot.write_vtk_file("potential.vts", [
        ("fld0", fld0),
        ("fld1", fld1),
        ("fld_inc_vol", fld_inc_vol),
        ("fld_total", ((fld_inc_vol + fld0) *
                       (1 - dom1_indicator) + fld1 * dom1_indicator)),
        ("dom1_indicator", dom1_indicator),
    ])
Example #30
0
    # {{{ come up with a solution to Maxwell's equations

    j_sym = sym.make_sym_vector("j", 3)
    jt_sym = sym.make_sym_vector("jt", 2)
    rho_sym = sym.var("rho")

    from pytential.symbolic.pde.maxwell import (PECChargeCurrentMFIEOperator,
                                                get_sym_maxwell_point_source,
                                                get_sym_maxwell_plane_wave)
    mfie = PECChargeCurrentMFIEOperator()

    test_source = case.get_source(queue)

    calc_patch = CalculusPatch(np.array([-3, 0, 0]), h=0.01)
    calc_patch_tgt = PointsTarget(cl.array.to_device(queue, calc_patch.points))

    rng = cl.clrandom.PhiloxGenerator(cl_ctx, seed=12)
    src_j = rng.normal(queue, (3, test_source.nnodes), dtype=np.float64)

    def eval_inc_field_at(tgt):
        if 0:
            # plane wave
            return bind(
                tgt,
                get_sym_maxwell_plane_wave(amplitude_vec=np.array([1, 1, 1]),
                                           v=np.array([1, 0, 0]),
                                           omega=case.k))(queue)
        else:
            # point source
            return bind((test_source, tgt),
Example #31
0
def test_cost_model_correctness(ctx_getter, dim, off_surface,
                                use_target_specific_qbx):
    """Check that computed cost matches that of a constant-one FMM."""
    cl_ctx = ctx_getter()
    queue = cl.CommandQueue(cl_ctx)

    cost_model = (CostModel(
        translation_cost_model_factory=OpCountingTranslationCostModel))

    lpot_source = get_lpot_source(queue, dim).copy(
        cost_model=cost_model,
        _use_target_specific_qbx=use_target_specific_qbx)

    # Construct targets.
    if off_surface:
        from pytential.target import PointsTarget
        from boxtree.tools import make_uniform_particle_array
        ntargets = 10**3
        targets = PointsTarget(
            make_uniform_particle_array(queue, ntargets, dim, np.float))
        target_discrs_and_qbx_sides = ((targets, 0), )
        qbx_forced_limit = None
    else:
        targets = lpot_source.density_discr
        target_discrs_and_qbx_sides = ((targets, 1), )
        qbx_forced_limit = 1

    # Construct bound op, run cost model.
    sigma_sym = sym.var("sigma")
    k_sym = LaplaceKernel(lpot_source.ambient_dim)
    sym_op_S = sym.S(k_sym, sigma_sym, qbx_forced_limit=qbx_forced_limit)

    op_S = bind((lpot_source, targets), sym_op_S)
    sigma = get_density(queue, lpot_source)

    from pytools import one
    cost_S = one(op_S.get_modeled_cost(queue, sigma=sigma).values())

    # Run FMM with ConstantOneWrangler. This can't be done with pytential's
    # high-level interface, so call the FMM driver directly.
    from pytential.qbx.fmm import drive_fmm
    geo_data = lpot_source.qbx_fmm_geometry_data(
        target_discrs_and_qbx_sides=target_discrs_and_qbx_sides)

    wrangler = ConstantOneQBXExpansionWrangler(queue, geo_data,
                                               use_target_specific_qbx)
    nnodes = lpot_source.quad_stage2_density_discr.nnodes
    src_weights = np.ones(nnodes)

    timing_data = {}
    potential = drive_fmm(wrangler,
                          src_weights,
                          timing_data,
                          traversal=wrangler.trav)[0][geo_data.ncenters:]

    # Check constant one wrangler for correctness.
    assert (potential == nnodes).all()

    modeled_time = cost_S.get_predicted_times(merge_close_lists=True)

    # Check that the cost model matches the timing data returned by the
    # constant one wrangler.
    mismatches = []
    for stage in timing_data:
        if timing_data[stage]["ops_elapsed"] != modeled_time[stage]:
            mismatches.append((stage, timing_data[stage]["ops_elapsed"],
                               modeled_time[stage]))

    assert not mismatches, "\n".join(str(s) for s in mismatches)