Пример #1
0
def get_bound_op(lpot_source):
    from sumpy.kernel import LaplaceKernel
    sigma_sym = sym.var("sigma")
    k_sym = LaplaceKernel(lpot_source.ambient_dim)
    op = sym.S(k_sym, sigma_sym, qbx_forced_limit=+1)

    return bind(lpot_source, op)
Пример #2
0
def _sumpy_kernel_init(param):
    name, dim, order = param.name, param.dim, param.order
    # TODO: add other kernels
    assert name == "m2l"
    from sumpy.expansion.multipole import (
        LinearPDEConformingVolumeTaylorMultipoleExpansion,
    )
    from sumpy.expansion.local import LinearPDEConformingVolumeTaylorLocalExpansion
    from sumpy.kernel import LaplaceKernel
    from sumpy import E2EFromCSR

    ctx = cl.create_some_context()
    np.random.seed(17)

    knl = LaplaceKernel(dim)
    local_expn_class = LinearPDEConformingVolumeTaylorLocalExpansion
    mpole_expn_class = LinearPDEConformingVolumeTaylorMultipoleExpansion
    m_expn = mpole_expn_class(knl, order=order)
    l_expn = local_expn_class(knl, order=order)

    m2l = E2EFromCSR(ctx, m_expn, l_expn, name="loopy_kernel")
    m2l.get_translation_loopy_insns()
    m2l.ctx = None
    m2l.device = None
    return m2l
Пример #3
0
def test_timing_data_gathering(ctx_factory):
    """Test that timing data gathering can execute succesfully."""

    pytest.importorskip("pyfmmlib")

    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx,
            properties=cl.command_queue_properties.PROFILING_ENABLE)
    actx = PyOpenCLArrayContext(queue)

    lpot_source = get_lpot_source(actx, 2)
    places = GeometryCollection(lpot_source)

    dofdesc = places.auto_source.to_stage1()
    density_discr = places.get_discretization(dofdesc.geometry)
    sigma = get_density(actx, density_discr)

    sigma_sym = sym.var("sigma")
    k_sym = LaplaceKernel(lpot_source.ambient_dim)
    sym_op_S = sym.S(k_sym, sigma_sym, qbx_forced_limit=+1)

    op_S = bind(places, sym_op_S)

    timing_data = {}
    op_S.eval(dict(sigma=sigma), timing_data=timing_data, array_context=actx)
    assert timing_data
    print(timing_data)
Пример #4
0
def get_slp_wall_times(lpot_source, fmm_order, qbx_order):
    queue = cl.CommandQueue(lpot_source.cl_context)

    lpot_source = lpot_source.copy(
        qbx_order=qbx_order,
        fmm_level_to_order=(False if fmm_order is False else
                            lambda *args: fmm_order))

    d = lpot_source.ambient_dim

    u_sym = sym.var("u")

    from sumpy.kernel import LaplaceKernel
    S = sym.S(LaplaceKernel(d), u_sym, qbx_forced_limit=-1)
    density_discr = lpot_source.density_discr

    u = cl.array.empty(queue, density_discr.nnodes, np.float64)
    u.fill(1)

    op = bind(lpot_source, S)

    # Warmup
    op(queue, u=u)

    times = []
    from time import perf_counter as curr_time

    for _ in range(WALL_TIME_EXPERIMENT_TIMING_ROUNDS):
        t_start = curr_time()
        op(queue, u=u)
        t_end = curr_time()
        times.append(t_end - t_start)

    return times
Пример #5
0
def get_bound_op(places):
    from sumpy.kernel import LaplaceKernel
    op = sym.S(LaplaceKernel(places.ambient_dim),
               sym.var("sigma"),
               qbx_forced_limit=+1)

    return bind(places, op)
Пример #6
0
def test_line_taylor_coeff_growth():
    # Regression test for LineTaylorLocalExpansion.
    # See https://gitlab.tiker.net/inducer/pytential/merge_requests/12
    from sumpy.kernel import LaplaceKernel
    from sumpy.expansion.local import LineTaylorLocalExpansion
    from sumpy.symbolic import make_sym_vector, SympyToPymbolicMapper

    import numpy as np

    order = 10
    expn = LineTaylorLocalExpansion(LaplaceKernel(2), order)
    avec = make_sym_vector("a", 2)
    bvec = make_sym_vector("b", 2)
    coeffs = expn.coefficients_from_source(avec, bvec, rscale=1)

    sym2pymbolic = SympyToPymbolicMapper()
    coeffs_pymbolic = [sym2pymbolic(c) for c in coeffs]

    from pymbolic.mapper.flop_counter import FlopCounter
    flop_counter = FlopCounter()
    counts = [flop_counter(c) for c in coeffs_pymbolic]

    indices = np.arange(1, order + 2)
    max_order = 2
    assert np.polyfit(np.log(indices), np.log(counts), deg=1)[0] < max_order
Пример #7
0
def get_lpot_cost(queue, geometry_getter, kind):
    lpot_source = geometry_getter(queue)

    from pytential import sym, bind
    sigma_sym = sym.var("sigma")
    from sumpy.kernel import LaplaceKernel
    k_sym = LaplaceKernel(lpot_source.ambient_dim)
    op = sym.S(k_sym, sigma_sym, qbx_forced_limit=+1)

    bound_op = bind(lpot_source, op)

    density_discr = lpot_source.density_discr
    nodes = density_discr.nodes().with_queue(queue)
    sigma = cl.clmath.sin(10 * nodes[0])

    from pytools import one
    if kind == "actual":
        timing_data = {}
        result = bound_op.eval(queue, {"sigma": sigma},
                               timing_data=timing_data)
        assert not np.isnan(result.get(queue)).any()
        result = one(timing_data.values())

    elif kind == "model":
        perf_results = bound_op.get_modeled_performance(queue, sigma=sigma)
        result = one(perf_results.values())

    return result
Пример #8
0
 def __init__(self,
              ambient_dim,
              *,
              dim: Optional[int] = None,
              precond: str = "left") -> None:
     from sumpy.kernel import LaplaceKernel
     super().__init__(LaplaceKernel(ambient_dim), dim=dim, precond=precond)
Пример #9
0
    def __init__(self, kernel, loc_sign, alpha=None,
            use_improved_operator=True,
            laplace_kernel=0, use_l2_weighting=False,
            kernel_arguments=None):
        """
        :arg loc_sign: +1 for exterior, -1 for interior
        :arg alpha: the coefficient for the combined-field representation
            Set to 0 for Laplace.
        :arg use_improved_operator: Whether to use the least singular
            operator available
        """

        assert loc_sign in [-1, 1]

        from sumpy.kernel import Kernel, LaplaceKernel
        assert isinstance(kernel, Kernel)

        if kernel_arguments is None:
            kernel_arguments = {}
        self.kernel_arguments = kernel_arguments

        self.loc_sign = loc_sign
        self.laplace_kernel = LaplaceKernel(kernel.dim)

        L2WeightedPDEOperator.__init__(self, kernel, use_l2_weighting)

        if alpha is None:
            if isinstance(self.kernel, LaplaceKernel):
                alpha = 0
            else:
                alpha = 1j

        self.alpha = alpha
        self.use_improved_operator = use_improved_operator
Пример #10
0
def test_cost_model(ctx_factory, dim, use_target_specific_qbx):
    """Test that cost model gathering can execute successfully."""
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

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

    density_discr = places.get_discretization(places.auto_source.geometry)
    sigma = get_density(actx, density_discr)

    sigma_sym = sym.var("sigma")
    k_sym = LaplaceKernel(lpot_source.ambient_dim)

    sym_op_S = sym.S(k_sym, sigma_sym, qbx_forced_limit=+1)
    op_S = bind(places, sym_op_S)
    cost_S = op_S.get_modeled_cost(actx, sigma=sigma)
    assert len(cost_S) == 1

    sym_op_S_plus_D = (
            sym.S(k_sym, sigma_sym, qbx_forced_limit=+1)
            + sym.D(k_sym, sigma_sym, qbx_forced_limit="avg"))
    op_S_plus_D = bind(places, sym_op_S_plus_D)
    cost_S_plus_D = op_S_plus_D.get_modeled_cost(actx, sigma=sigma)
    assert len(cost_S_plus_D) == 2
def test_toy_p2e2p(src, ctr, tgt, expn_func, expected):
    src = src.reshape(3, -1)
    tgt = tgt.reshape(3, -1)

    rtol = 1e-2
    if not 0 <= expected < 1 / (1 + rtol):
        raise ValueError()

    from sumpy.kernel import LaplaceKernel
    ctx = l3d.InterpretedToyContext(LaplaceKernel(3),
                                    l3d.L3DMultipoleExpansion,
                                    l3d.L3DLocalExpansion)

    src_pot = t.PointSources(ctx, src, weights=[1])
    pot_actual = src_pot.eval(tgt)

    errors = []

    for order in ORDERS:
        expn = expn_func(src_pot, ctr, order=order)
        pot_p2e2p = expn.eval(tgt)
        errors.append(np.abs(pot_actual - pot_p2e2p))

    conv_factor = compute_approx_convergence_factor(ORDERS, errors)

    assert conv_factor < expected * (1 + rtol)
Пример #12
0
    def apply_pressure(self, density_vec_sym, dir_vec_sym, mu_sym, qbx_forced_limit):
        """ Symbolic expression for pressure field associated with the stresslet"""

        import itertools
        from pytential.symbolic.mappers import DerivativeTaker
        kernel = LaplaceKernel(dim=self.dim)

        factor = (2. * mu_sym)

        for i, j in itertools.product(range(self.dim), range(self.dim)):

            if i + j < 1:
                sym_expr = factor * DerivativeTaker(i).map_int_g(
                             DerivativeTaker(j).map_int_g(
                                 sym.S(kernel, density_vec_sym[i] * dir_vec_sym[j],
                                 qbx_forced_limit=qbx_forced_limit)))
            else:
                sym_expr = sym_expr + (
                               factor * DerivativeTaker(i).map_int_g(
                                   DerivativeTaker(j).map_int_g(
                                       sym.S(kernel,
                                             density_vec_sym[i] * dir_vec_sym[j],
                                             qbx_forced_limit=qbx_forced_limit))))

        return sym_expr
Пример #13
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
Пример #14
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
Пример #15
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
Пример #16
0
def test_expr_pickling():
    import pickle
    from sumpy.kernel import LaplaceKernel, AxisTargetDerivative

    ops_for_testing = [
        sym.d_dx(
            2, sym.D(LaplaceKernel(2), sym.var("sigma"), qbx_forced_limit=-2)),
        sym.D(AxisTargetDerivative(0, LaplaceKernel(2)),
              sym.var("sigma"),
              qbx_forced_limit=-2)
    ]

    for op in ops_for_testing:
        pickled_op = pickle.dumps(op)
        after_pickle_op = pickle.loads(pickled_op)

        assert op == after_pickle_op
Пример #17
0
def test_layer_potential_construction(lpot_class, ambient_dim=2):
    from sumpy.kernel import LaplaceKernel

    kernel_sym = LaplaceKernel(ambient_dim)
    density_sym = sym.var("sigma")
    lpot_sym = lpot_class(kernel_sym, density_sym, qbx_forced_limit=None)

    assert lpot_sym is not None
Пример #18
0
 def inner_fmm_level_to_nterms(tree, level):
     if helmholtz_k == 0:
         return fmm_level_to_order(LaplaceKernel(tree.dimensions),
                                   frozenset(), tree, level)
     else:
         return fmm_level_to_order(HelmholtzKernel(tree.dimensions),
                                   frozenset([("k", helmholtz_k)]),
                                   tree, level)
def main():
    cl_ctx = cl.create_some_context()
    queue = cl.CommandQueue(cl_ctx)

    target_order = 10

    from functools import partial
    nelements = 30
    qbx_order = 4

    from sumpy.kernel import LaplaceKernel
    from meshmode.mesh.generation import (  # noqa
            ellipse, cloverleaf, starfish, drop, n_gon, qbx_peanut,
            make_curve_mesh)
    mesh = make_curve_mesh(partial(ellipse, 1),
            np.linspace(0, 1, nelements+1),
            target_order)

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

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

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

    from pytools.obj_array import join_fields
    sig_sym = sym.var("sig")
    knl = LaplaceKernel(2)
    op = join_fields(
            sym.tangential_derivative(mesh.ambient_dim,
                sym.D(knl, sig_sym, qbx_forced_limit=+1)).as_scalar(),
            sym.tangential_derivative(mesh.ambient_dim,
                sym.D(knl, sig_sym, qbx_forced_limit=-1)).as_scalar(),
            )

    nodes = density_discr.nodes().with_queue(queue)
    angle = cl.clmath.atan2(nodes[1], nodes[0])
    n = 10
    sig = cl.clmath.sin(n*angle)
    dt_sig = n*cl.clmath.cos(n*angle)

    res = bind(qbx, op)(queue, sig=sig)

    extval = res[0].get()
    intval = res[1].get()
    pv = 0.5*(extval + intval)

    dt_sig_h = dt_sig.get()

    import matplotlib.pyplot as pt
    pt.plot(extval, label="+num")
    pt.plot(pv + dt_sig_h*0.5, label="+ex")
    pt.legend(loc="best")
    pt.show()
Пример #20
0
def test_direct(ctx_factory):
    # This evaluates a single layer potential on a circle.
    logging.basicConfig(level=logging.INFO)

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

    from sumpy.kernel import LaplaceKernel
    lknl = LaplaceKernel(2)

    order = 12

    from sumpy.qbx import LayerPotential
    from sumpy.expansion.local import LineTaylorLocalExpansion

    lpot = LayerPotential(ctx, [LineTaylorLocalExpansion(lknl, order)])

    mode_nr = 25

    from pytools.convergence import EOCRecorder

    eocrec = EOCRecorder()

    for n in [200, 300, 400]:
        t = np.linspace(0, 2 * np.pi, n, endpoint=False)
        unit_circle = np.exp(1j * t)
        unit_circle = np.array([unit_circle.real, unit_circle.imag])

        sigma = np.cos(mode_nr * t)
        eigval = 1 / (2 * mode_nr)

        result_ref = eigval * sigma

        h = 2 * np.pi / n

        targets = unit_circle
        sources = unit_circle

        radius = 7 * h
        centers = unit_circle * (1 - radius)

        expansion_radii = np.ones(n) * radius

        strengths = (sigma * h, )
        evt, (result_qbx, ) = lpot(queue,
                                   targets,
                                   sources,
                                   centers,
                                   strengths,
                                   expansion_radii=expansion_radii)

        eocrec.add_data_point(h, np.max(np.abs(result_ref - result_qbx)))

    print(eocrec)

    slack = 1.5
    assert eocrec.order_estimate() > order - slack
Пример #21
0
    def operator(self,
                 sigma: sym.var,
                 mean_curvature: Optional[sym.var] = None,
                 **kwargs) -> sym.var:
        """
        :arg mean_curvature: an expression for the mean curvature that can be
            used in the construction of the operator.
        :returns: a Fredholm integral equation of the second kind for the
            Beltrami PDE with the unknown density *sigma*.
        """
        from sumpy.kernel import LaplaceKernel
        if isinstance(self.kernel, LaplaceKernel):
            raise TypeError(
                f"{type(self).__name__} does not support the Laplace "
                "kernel, use LaplaceBeltramiOperator instead")

        if mean_curvature is None:
            mean_curvature = sym.mean_curvature(self.ambient_dim, dim=self.dim)

        kappa = self.dim * mean_curvature
        context = self.kernel_arguments.copy()
        context.update(kwargs)

        knl = self.kernel
        lknl = LaplaceKernel(knl.dim)

        # {{{ layer potentials

        # laplace
        S0 = partial(sym.S, lknl, qbx_forced_limit=+1, **kwargs)  # noqa: N806
        D0 = partial(sym.D, lknl, qbx_forced_limit="avg",
                     **kwargs)  # noqa: N806
        Sp0 = partial(sym.Sp, lknl, qbx_forced_limit="avg",
                      **kwargs)  # noqa: N806
        Dp0 = partial(sym.Dp, lknl, qbx_forced_limit="avg",
                      **kwargs)  # noqa: N806

        # base
        S = partial(sym.S, knl, qbx_forced_limit=+1, **context)  # noqa: N806
        Sp = partial(sym.Sp, knl, qbx_forced_limit="avg",
                     **context)  # noqa: N806
        Spp = partial(sym.Spp, knl, qbx_forced_limit="avg",
                      **context)  # noqa: N806

        # }}}

        if self.precond == "left":
            # similar to 6.2 in [ONeil2017]
            op = (sigma / 4 - D0(D0(sigma)) + S(kappa * Sp(sigma)) +
                  S(Spp(sigma) + Dp0(sigma)) - S(Dp0(sigma)) + S0(Dp0(sigma)))
        else:
            # similar to 6.2 in [ONeil2017]
            op = (sigma / 4 - Sp0(Sp0(sigma)) +
                  (Spp(S(sigma)) + Dp0(S(sigma))) - Dp0(S(sigma) - S0(sigma)) +
                  kappa * Sp(S(sigma)))

        return op
Пример #22
0
def test_cost_model_order_varying_by_level(ctx_factory):
    """For FMM order varying by level, this checks to ensure that the costs are
    different. The varying-level case should have larger cost.
    """

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

    # {{{ constant level to order

    def level_to_order_constant(kernel, kernel_args, tree, level):
        return 1

    lpot_source = get_lpot_source(actx, 2).copy(
            cost_model=QBXCostModel(),
            fmm_level_to_order=level_to_order_constant)
    places = GeometryCollection(lpot_source)

    density_discr = places.get_discretization(places.auto_source.geometry)
    sigma_sym = sym.var("sigma")

    k_sym = LaplaceKernel(2)
    sym_op = sym.S(k_sym, sigma_sym, qbx_forced_limit=+1)

    sigma = get_density(actx, density_discr)

    cost_constant, metadata = bind(places, sym_op).cost_per_stage(
            "constant_one", sigma=sigma)

    cost_constant = one(cost_constant.values())
    metadata = one(metadata.values())

    # }}}

    # {{{ varying level to order

    def level_to_order_varying(kernel, kernel_args, tree, level):
        return metadata["nlevels"] - level

    lpot_source = get_lpot_source(actx, 2).copy(
            cost_model=QBXCostModel(),
            fmm_level_to_order=level_to_order_varying)
    places = GeometryCollection(lpot_source)

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

    sigma = get_density(actx, density_discr)

    cost_varying, _ = bind(lpot_source, sym_op).cost_per_stage(
        "constant_one", sigma=sigma)

    cost_varying = one(cost_varying.values())

    # }}}

    assert sum(cost_varying.values()) > sum(cost_constant.values())
Пример #23
0
def test_sumpy_fmm_timing_data_collection(ctx_factory):
    logging.basicConfig(level=logging.INFO)

    ctx = ctx_factory()
    queue = cl.CommandQueue(
            ctx,
            properties=cl.command_queue_properties.PROFILING_ENABLE)

    nsources = 500
    dtype = np.float64

    from boxtree.tools import (
            make_normal_particle_array as p_normal)

    knl = LaplaceKernel(2)
    local_expn_class = VolumeTaylorLocalExpansion
    mpole_expn_class = VolumeTaylorMultipoleExpansion
    order = 1

    sources = p_normal(queue, nsources, knl.dim, dtype, seed=15)

    from boxtree import TreeBuilder
    tb = TreeBuilder(ctx)

    tree, _ = tb(queue, sources,
            max_particles_in_box=30, debug=True)

    from boxtree.traversal import FMMTraversalBuilder
    tbuild = FMMTraversalBuilder(ctx)
    trav, _ = tbuild(queue, tree, debug=True)

    from pyopencl.clrandom import PhiloxGenerator
    rng = PhiloxGenerator(ctx)
    weights = rng.uniform(queue, nsources, dtype=np.float64)

    out_kernels = [knl]

    from functools import partial

    from sumpy.fmm import SumpyExpansionWranglerCodeContainer
    wcc = SumpyExpansionWranglerCodeContainer(
            ctx,
            partial(mpole_expn_class, knl),
            partial(local_expn_class, knl),
            out_kernels)

    wrangler = wcc.get_wrangler(queue, tree, dtype,
            fmm_level_to_order=lambda kernel, kernel_args, tree, lev: order)
    from boxtree.fmm import drive_fmm

    timing_data = {}
    pot, = drive_fmm(trav, wrangler, (weights,), timing_data=timing_data)
    print(timing_data)
    assert timing_data
def test_p2e2e2p(src, ctr, ctr2, tgt, from_expn_class, to_expn_class,
                 expected):
    errors = []

    rtol = 1e-2
    if not 0 <= expected < 1 / (1 + rtol):
        raise ValueError()

    pot_actual = SCALING / la.norm(tgt - src)

    for order in ORDERS:
        expn = from_expn_class(LaplaceKernel(3), order)
        coeffs = expn.coefficients_from_source(ctr - src)
        expn2 = to_expn_class(LaplaceKernel(3), order)
        coeffs2 = expn2.translate_from(expn, coeffs, ctr2 - ctr)
        pot_p2e2e2p = expn2.evaluate(coeffs2, tgt - ctr2)
        errors.append(np.abs(pot_actual - pot_p2e2e2p))

    conv_factor = compute_approx_convergence_factor(ORDERS, errors)

    assert conv_factor < expected * (1 + rtol)
Пример #25
0
def m2l_experiment(param):
    from sumpy.kernel import LaplaceKernel
    ctx = l3d.InterpretedToyContext(LaplaceKernel(3),
                                    l3d.L3DMultipoleExpansion,
                                    l3d.L3DLocalExpansion)

    assert param.r / param.rho < 1

    mpole_center_dist = param.R + param.rho

    sources = param.r * SPHERE_SAMPLE
    sources[:, 2] += mpole_center_dist

    origin = np.zeros(3)
    mpole_center = np.array([0., 0., mpole_center_dist])
    local_centers = BALL_SAMPLE * param.R

    error = 0

    fmm_order = param.p
    qbx_order = param.q

    for src in sources:
        src = src.reshape(3, -1)

        src_pot = t.PointSources(ctx, src, weights=[1])
        mpole_pot = t.multipole_expand(src_pot, mpole_center, order=fmm_order)
        local_pot = t.local_expand(mpole_pot, origin, order=fmm_order)

        for local_center in local_centers:
            targets = ((param.R - la.norm(local_center)) * SPHERE_SAMPLE +
                       local_center)
            assert (la.norm(targets, axis=1) <= param.R * (1 + 1e-5)).all()

            if qbx_order == np.inf:
                actual = src_pot.eval(targets.T) - local_pot.eval(targets.T)
            else:
                qbx_src_pot = t.local_expand(src_pot,
                                             local_center,
                                             order=qbx_order)
                qbx_local_pot = t.local_expand(local_pot,
                                               local_center,
                                               order=qbx_order)
                diff = qbx_src_pot.with_coeffs(qbx_src_pot.coeffs -
                                               qbx_local_pot.coeffs)
                actual = diff.eval(targets.T)

            error = max(error, np.max(np.abs(actual)))

    return Result(param.R, param.r, param.rho, param.ratio, param.p, param.q,
                  error)
Пример #26
0
def test_cost_model_order_varying_by_level(ctx_factory):
    """For FMM order varying by level, this checks to ensure that the costs are
    different. The varying-level case should have larger cost.
    """

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

    # {{{ constant level to order

    def level_to_order_constant(kernel, kernel_args, tree, level):
        return 1

    lpot_source = get_lpot_source(actx, 2).copy(
            cost_model=CostModel(
                calibration_params=CONSTANT_ONE_PARAMS),
            fmm_level_to_order=level_to_order_constant)
    places = GeometryCollection(lpot_source)

    density_discr = places.get_discretization(places.auto_source.geometry)
    sigma_sym = sym.var("sigma")

    k_sym = LaplaceKernel(2)
    sym_op = sym.S(k_sym, sigma_sym, qbx_forced_limit=+1)

    sigma = get_density(actx, density_discr)

    cost_constant = one(
            bind(places, sym_op)
            .get_modeled_cost(actx, sigma=sigma).values())

    # }}}

    # {{{ varying level to order

    varying_order_params = cost_constant.params.copy()

    nlevels = cost_constant.params["nlevels"]
    for level in range(nlevels):
        varying_order_params["p_fmm_lev%d" % level] = nlevels - level

    cost_varying = cost_constant.with_params(varying_order_params)

    # }}}

    assert (
            sum(cost_varying.get_predicted_times().values())
            > sum(cost_constant.get_predicted_times().values()))
Пример #27
0
def test_p2p(ctx_factory, exclude_self):
    ctx = ctx_factory()
    queue = cl.CommandQueue(ctx)

    dimensions = 3
    n = 5000

    from sumpy.p2p import P2P
    lknl = LaplaceKernel(dimensions)
    knl = P2P(ctx, [lknl, AxisTargetDerivative(0, lknl)],
              exclude_self=exclude_self)

    targets = np.random.rand(dimensions, n)
    sources = targets if exclude_self else np.random.rand(dimensions, n)

    strengths = np.ones(n, dtype=np.float64)

    extra_kwargs = {}

    if exclude_self:
        extra_kwargs["target_to_source"] = np.arange(n, dtype=np.int32)

    evt, (potential, x_derivative) = knl(queue,
                                         targets,
                                         sources, [strengths],
                                         out_host=True,
                                         **extra_kwargs)

    potential_ref = np.empty_like(potential)

    targets = targets.T
    sources = sources.T
    for itarg in range(n):

        with np.errstate(divide="ignore"):
            invdists = np.sum((targets[itarg] - sources)**2, axis=-1)**-0.5

        if exclude_self:
            assert np.isinf(invdists[itarg])
            invdists[itarg] = 0

        potential_ref[itarg] = np.sum(strengths * invdists)

    potential_ref *= 1 / (4 * np.pi)

    rel_err = la.norm(potential - potential_ref) / la.norm(potential_ref)
    print(rel_err)
    assert rel_err < 1e-3
Пример #28
0
def get_qbx_center_neighborhood_sizes_direct(lpot_source, radius):
    queue = cl.CommandQueue(lpot_source.cl_context)

    def inspect_geo_data(insn, bound_expr, geo_data):
        nonlocal sizes, nsources, ncenters
        tree = geo_data.tree().with_queue(queue)

        centers = np.array([axis.get(queue) for axis in geo_data.centers()])
        search_radii = radius * geo_data.expansion_radii().get(queue)
        sources = np.array([axis.get(queue) for axis in tree.sources])

        ncenters = len(search_radii)
        nsources = tree.nsources

        assert nsources == lpot_source.quad_stage2_density_discr.nnodes

        center_to_source_dists = (
                la.norm(
                    (centers[:, np.newaxis, :] - sources[:, :, np.newaxis]).T,
                    ord=np.inf,
                    axis=-1))

        sizes = np.count_nonzero(
                center_to_source_dists <= search_radii[:, np.newaxis],
                axis=1)

        return False  # no need to do the actual FMM

    sizes = None
    nsources = None
    ncenters = None

    lpot_source = lpot_source.copy(geometry_data_inspector=inspect_geo_data)
    density_discr = lpot_source.density_discr
    nodes = density_discr.nodes().with_queue(queue)
    sigma = cl.clmath.sin(10 * nodes[0])

    # The kernel doesn't really matter here
    from sumpy.kernel import LaplaceKernel
    sigma_sym = sym.var('sigma')
    k_sym = LaplaceKernel(lpot_source.ambient_dim)
    sym_op = sym.S(k_sym, sigma_sym, qbx_forced_limit=+1)

    bound_op = bind(lpot_source, sym_op)
    bound_op(queue, sigma=sigma)

    return (sizes, nsources, ncenters)
Пример #29
0
def _build_op(lpot_id,
              k=0,
              ndim=2,
              source=sym.DEFAULT_SOURCE,
              target=sym.DEFAULT_TARGET,
              qbx_forced_limit="avg"):

    from sumpy.kernel import LaplaceKernel, HelmholtzKernel
    if k:
        knl = HelmholtzKernel(ndim)
        knl_kwargs = {"k": k}
    else:
        knl = LaplaceKernel(ndim)
        knl_kwargs = {}

    lpot_kwargs = {
            "qbx_forced_limit": qbx_forced_limit,
            "source": source,
            "target": target}
    lpot_kwargs.update(knl_kwargs)
    if lpot_id == 1:
        # scalar single-layer potential
        u_sym = sym.var("u")
        op = sym.S(knl, u_sym, **lpot_kwargs)
    elif lpot_id == 2:
        # scalar combination of layer potentials
        u_sym = sym.var("u")
        op = sym.S(knl, 0.3 * u_sym, **lpot_kwargs) \
             + sym.D(knl, 0.5 * u_sym, **lpot_kwargs)
    elif lpot_id == 3:
        # vector potential
        u_sym = sym.make_sym_vector("u", 2)
        u0_sym, u1_sym = u_sym

        op = make_obj_array([
            sym.Sp(knl, u0_sym, **lpot_kwargs)
            + sym.D(knl, u1_sym, **lpot_kwargs),
            sym.S(knl, 0.4 * u0_sym, **lpot_kwargs)
            + 0.3 * sym.D(knl, u0_sym, **lpot_kwargs)
            ])
    else:
        raise ValueError("Unknown lpot_id: {}".format(lpot_id))

    op = 0.5 * u_sym + op

    return op, u_sym, knl_kwargs
Пример #30
0
def get_lpot_cost(which, helmholtz_k, geometry_getter, lpot_kwargs, kind):
    """
    Parameters:

        which: "D" or "S"
        kind: "actual" or "model"
    """
    context = cl.create_some_context(interactive=False)
    queue = cl.CommandQueue(context)

    lpot_source = geometry_getter(queue, lpot_kwargs)

    from sumpy.kernel import LaplaceKernel, HelmholtzKernel
    sigma_sym = sym.var("sigma")
    if helmholtz_k == 0:
        k_sym = LaplaceKernel(lpot_source.ambient_dim)
        kernel_kwargs = {}
    else:
        k_sym = HelmholtzKernel(lpot_source.ambient_dim, "k")
        kernel_kwargs = {"k": helmholtz_k}

    if which == "S":
        op = sym.S(k_sym, sigma_sym, qbx_forced_limit=+1, **kernel_kwargs)
    elif which == "D":
        op = sym.D(k_sym, sigma_sym, qbx_forced_limit="avg", **kernel_kwargs)
    else:
        raise ValueError("unknown lpot symbol: '%s'" % which)

    bound_op = bind(lpot_source, op)

    density_discr = lpot_source.density_discr
    nodes = density_discr.nodes().with_queue(queue)
    sigma = cl.clmath.sin(10 * nodes[0])

    if kind == "actual":
        timing_data = {}
        result = bound_op.eval(queue, {"sigma": sigma},
                               timing_data=timing_data)
        assert not np.isnan(result.get(queue)).any()
        result = one(timing_data.values())

    elif kind == "model":
        perf_results = bound_op.get_modeled_performance(queue, sigma=sigma)
        result = one(perf_results.values())

    return result