コード例 #1
0
ファイル: cahn_hilliard.py プロジェクト: mattwala/pytential
    def S_G(self, i, density, qbx_forced_limit, op_map=None):  # noqa: N802
        if op_map is None:
            op_map = lambda x: x  # noqa: E731

        from sumpy.kernel import HelmholtzKernel
        hhk = HelmholtzKernel(2, allow_evanescent=True)
        hhk_scaling = 1j / 4

        if i == 0:
            lam1, lam2 = self.lambdas
            return (
                # FIXME: Verify scaling
                -1 / (2 * np.pi * (lam1**2 - lam2**2)) / hhk_scaling * (op_map(
                    sym.S(hhk,
                          density,
                          k=1j * lam1,
                          qbx_forced_limit=qbx_forced_limit)) - op_map(
                              sym.S(hhk,
                                    density,
                                    k=1j * lam2,
                                    qbx_forced_limit=qbx_forced_limit))))
        else:
            return (
                # FIXME: Verify scaling
                -1 / (2 * np.pi) / hhk_scaling * op_map(
                    sym.S(hhk,
                          density,
                          k=1j * self.lambdas[i - 1],
                          qbx_forced_limit=qbx_forced_limit)))
コード例 #2
0
ファイル: fmmlib.py プロジェクト: alexfikl/pytential
 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)
コード例 #3
0
 def __init__(self, omega, mus, epss):
     from sumpy.kernel import HelmholtzKernel
     self.kernel = HelmholtzKernel(3)
     self.omega = omega
     self.mus = mus
     self.epss = epss
     self.ks = [
             sym.cse(omega*(eps*mu)**0.5, "k%d" % i)
             for i, (eps, mu) in enumerate(zip(epss, mus))]
コード例 #4
0
 def __init__(self,
              ambient_dim: int,
              *,
              dim: Optional[int] = None,
              precond: str = "left",
              helmholtz_k_name: str = "k") -> None:
     from sumpy.kernel import HelmholtzKernel
     super().__init__(
         HelmholtzKernel(ambient_dim, helmholtz_k_name=helmholtz_k_name),
         dim=dim,
         precond=precond,
         kernel_arguments={helmholtz_k_name: sym.var(helmholtz_k_name)})
コード例 #5
0
    def __init__(self, domain_n_exprs, ne,
            interfaces, use_l2_weighting=None):
        """
        :attr interfaces: a tuple of tuples
            ``(outer_domain, inner_domain, interface_id)``,
            where *outer_domain* and *inner_domain* are indices into
            *domain_k_names*,
            and *interface_id* is a symbolic name for the discretization of the
            interface. 'outer' designates the side of the interface to which
            the normal points.
        :attr domain_n_exprs: a tuple of variable names of the Helmholtz
            parameter *k*, to be used inside each part of the source geometry.
            May also be a tuple of strings, which will be transformed into
            variable references of the corresponding names.
        :attr beta: A symbolic expression for the wave number in the :math:`z`
            direction. May be a string, which will be interpreted as a variable
            name.
        """

        self.interfaces = interfaces

        ne = sym.var(ne)
        self.ne = sym.cse(ne, "ne")

        self.domain_n_exprs = [
                sym.var(n_expr)
                for idom, n_expr in enumerate(domain_n_exprs)]
        del domain_n_exprs

        import pymbolic.primitives as p

        def upper_half_square_root(x):
            return p.If(
                    p.Comparison(
                        (x**0.5).a.imag,
                        "<", 0),
                    1j*(-x)**0.5,
                    x**0.5)

        self.domain_K_exprs = [
                sym.cse(
                    upper_half_square_root(n_expr**2-ne**2),
                    "K%d" % i)
                for i, n_expr in enumerate(self.domain_n_exprs)]

        from sumpy.kernel import HelmholtzKernel
        self.kernel = HelmholtzKernel(2, allow_evanescent=True)
コード例 #6
0
def test_cost_model_metadata_gathering(ctx_factory):
    """Test that the cost model correctly gathers metadata."""
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

    from sumpy.expansion.level_to_order import SimpleExpansionOrderFinder

    fmm_level_to_order = SimpleExpansionOrderFinder(tol=1e-5)

    lpot_source = get_lpot_source(actx, 2).copy(
            fmm_level_to_order=fmm_level_to_order)
    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 = HelmholtzKernel(2, "k")
    k = 2

    sym_op_S = sym.S(k_sym, sigma_sym, qbx_forced_limit=+1, k=sym.var("k"))
    op_S = bind(places, sym_op_S)

    _, metadata = op_S.cost_per_stage(
        "constant_one", sigma=sigma, k=k, return_metadata=True
    )
    metadata = one(metadata.values())

    geo_data = lpot_source.qbx_fmm_geometry_data(
            places,
            places.auto_source,
            target_discrs_and_qbx_sides=((density_discr, 1),))

    tree = geo_data.tree()

    assert metadata["p_qbx"] == QBX_ORDER
    assert metadata["nlevels"] == tree.nlevels
    assert metadata["nsources"] == tree.nsources
    assert metadata["ntargets"] == tree.ntargets
    assert metadata["ncenters"] == geo_data.ncenters

    for level in range(tree.nlevels):
        assert (
                metadata["p_fmm_lev%d" % level]
                == fmm_level_to_order(k_sym, {"k": 2}, tree, level))
コード例 #7
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
コード例 #8
0
ファイル: test_matrix.py プロジェクト: mattwala/pytential
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
コード例 #9
0
def get_true_sol(fspace, kappa, cl_ctx, queue):
    """
    Get the ufl expression for the true solution (3D)
    or a function with the evaluated solution (2D)
    """
    mesh_dim = fspace.mesh().geometric_dimension()
    if mesh_dim == 3:
        spatial_coord = SpatialCoordinate(fspace.mesh())
        x, y, z = spatial_coord  # pylint: disable=C0103
        norm = sqrt(x**2 + y**2 + z**2)
        return Constant(1j / (4 * pi)) / norm * exp(1j * kappa * norm)

    if mesh_dim == 2:
        # Evaluate true-sol using sumpy
        from sumpy.p2p import P2P
        from sumpy.kernel import HelmholtzKernel
        # https://github.com/inducer/sumpy/blob/900745184d2618bc27a64c847f247e01c2b90b02/examples/curve-pot.py#L87-L88
        p2p = P2P(cl_ctx, [HelmholtzKernel(dim=2)],
                  exclude_self=False,
                  value_dtypes=np.complex128)
        # source is just (0, 0)
        sources = np.array([[0.0], [0.0]])
        strengths = np.array([[1.0], [1.0]])
        # targets are everywhere
        targets = np.array([
            Function(fspace).interpolate(x_i).dat.data
            for x_i in SpatialCoordinate(fspace.mesh())
        ])
        evt, (true_sol_arr, ) = p2p(queue,
                                    targets,
                                    sources,
                                    strengths,
                                    k=kappa)
        true_sol = Function(fspace)
        true_sol.dat.data[:] = true_sol_arr[:]
        return true_sol
    raise ValueError("Only meshes of dimension 2, 3 supported")
コード例 #10
0
ファイル: test_cost_model.py プロジェクト: mattwala/pytential
def test_cost_model_metadata_gathering(ctx_getter):
    """Test that the cost model correctly gathers metadata."""
    cl_ctx = ctx_getter()
    queue = cl.CommandQueue(cl_ctx)

    from sumpy.expansion.level_to_order import SimpleExpansionOrderFinder

    fmm_level_to_order = SimpleExpansionOrderFinder(tol=1e-5)

    lpot_source = get_lpot_source(
        queue, 2).copy(fmm_level_to_order=fmm_level_to_order)

    sigma = get_density(queue, lpot_source)

    sigma_sym = sym.var("sigma")
    k_sym = HelmholtzKernel(2, "k")
    k = 2

    sym_op_S = sym.S(k_sym, sigma_sym, qbx_forced_limit=+1, k=sym.var("k"))
    op_S = bind(lpot_source, sym_op_S)

    cost_S = one(op_S.get_modeled_cost(queue, sigma=sigma, k=k).values())

    geo_data = lpot_source.qbx_fmm_geometry_data(
        target_discrs_and_qbx_sides=((lpot_source.density_discr, 1), ))

    tree = geo_data.tree()

    assert cost_S.params["p_qbx"] == QBX_ORDER
    assert cost_S.params["nlevels"] == tree.nlevels
    assert cost_S.params["nsources"] == tree.nsources
    assert cost_S.params["ntargets"] == tree.ntargets
    assert cost_S.params["ncenters"] == geo_data.ncenters

    for level in range(tree.nlevels):
        assert (cost_S.params["p_fmm_lev%d" % level] == fmm_level_to_order(
            k_sym, {"k": 2}, tree, level))
コード例 #11
0
ファイル: sym-exp-complexity.py プロジェクト: xywei/sumpy
def find_flops():
    ctx = cl.create_some_context()

    if 0:
        knl = LaplaceKernel(2)
        m_expn_cls = LaplaceConformingVolumeTaylorMultipoleExpansion
        l_expn_cls = LaplaceConformingVolumeTaylorLocalExpansion
        flop_type = np.float64
    else:
        knl = HelmholtzKernel(2)
        m_expn_cls = HelmholtzConformingVolumeTaylorMultipoleExpansion
        l_expn_cls = HelmholtzConformingVolumeTaylorLocalExpansion
        flop_type = np.complex128

    orders = list(range(1, 11, 1))
    flop_counts = []
    for order in orders:
        print(order)
        m_expn = m_expn_cls(knl, order)
        l_expn = l_expn_cls(knl, order)
        m2l = E2EFromCSR(ctx, m_expn, l_expn)

        loopy_knl = m2l.get_kernel()
        loopy_knl = lp.add_and_infer_dtypes(
            loopy_knl, {
                "target_boxes,src_box_lists,src_box_starts": np.int32,
                "centers,src_expansions": np.float64,
            })

        flops = lp.get_op_map(loopy_knl).filter_by(dtype=[flop_type]).sum()
        flop_counts.append(
            flops.eval_with_dict(dict(isrc_start=0, isrc_stop=1,
                                      ntgt_boxes=1)))

    print(orders)
    print(flop_counts)
コード例 #12
0
                ("bdry_normals", bdry_normals),
            ])

        else:
            raise ValueError("invalid mesh dim")

    # }}}

    # {{{ set up operator

    from pytential.symbolic.pde.scalar import (DirichletOperator,
                                               NeumannOperator)

    from sumpy.kernel import LaplaceKernel, HelmholtzKernel
    if case.k:
        knl = HelmholtzKernel(mesh.ambient_dim)
        knl_kwargs = {"k": sym.var("k")}
        concrete_knl_kwargs = {"k": case.k}
    else:
        knl = LaplaceKernel(mesh.ambient_dim)
        knl_kwargs = {}
        concrete_knl_kwargs = {}

    if knl.is_complex_valued:
        dtype = np.complex128
    else:
        dtype = np.float64

    loc_sign = +1 if case.prob_side in [+1, "scat"] else -1

    if case.bc_type == "dirichlet":
コード例 #13
0
def test_target_specific_qbx(actx_factory, op, helmholtz_k, qbx_order):
    logging.basicConfig(level=logging.INFO)

    actx = actx_factory()

    target_order = 4
    fmm_tol = 1e-3

    from meshmode.mesh.generation import generate_sphere
    mesh = generate_sphere(1, target_order)

    from meshmode.discretization import Discretization
    from meshmode.discretization.poly_element import \
        InterpolatoryQuadratureSimplexGroupFactory
    from pytential.qbx import QBXLayerPotentialSource
    pre_density_discr = Discretization(
        actx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order))

    from sumpy.expansion.level_to_order import SimpleExpansionOrderFinder
    qbx = QBXLayerPotentialSource(
        pre_density_discr,
        4 * target_order,
        qbx_order=qbx_order,
        fmm_level_to_order=SimpleExpansionOrderFinder(fmm_tol),
        fmm_backend="fmmlib",
        _expansions_in_tree_have_extent=True,
        _expansion_stick_out_factor=0.9,
        _use_target_specific_qbx=False,
    )

    kernel_length_scale = 5 / abs(helmholtz_k) if helmholtz_k else None
    places = {
        "qbx": qbx,
        "qbx_target_specific": qbx.copy(_use_target_specific_qbx=True)
    }

    from pytential.qbx.refinement import refine_geometry_collection
    places = GeometryCollection(places, auto_where="qbx")
    places = refine_geometry_collection(
        places, kernel_length_scale=kernel_length_scale)

    density_discr = places.get_discretization("qbx")
    nodes = thaw(density_discr.nodes(), actx)
    u_dev = actx.np.sin(nodes[0])

    if helmholtz_k == 0:
        kernel = LaplaceKernel(3)
        kernel_kwargs = {}
    else:
        kernel = HelmholtzKernel(3, allow_evanescent=True)
        kernel_kwargs = {"k": sym.var("k")}

    u_sym = sym.var("u")

    if op == "S":
        op = sym.S
    elif op == "D":
        op = sym.D
    elif op == "Sp":
        op = sym.Sp
    else:
        raise ValueError("unknown operator: '%s'" % op)

    expr = op(kernel, u_sym, qbx_forced_limit=-1, **kernel_kwargs)

    bound_op = bind(places, expr)
    pot_ref = actx.to_numpy(
        flatten(bound_op(actx, u=u_dev, k=helmholtz_k), actx))

    bound_op = bind(places, expr, auto_where="qbx_target_specific")
    pot_tsqbx = actx.to_numpy(
        flatten(bound_op(actx, u=u_dev, k=helmholtz_k), actx))

    assert np.allclose(pot_tsqbx, pot_ref, atol=1e-13, rtol=1e-13)
コード例 #14
0
def run_dielectric_test(cl_ctx,
                        queue,
                        nelements,
                        qbx_order,
                        op_class,
                        mode,
                        k0=3,
                        k1=2.9,
                        mesh_order=10,
                        bdry_quad_order=None,
                        bdry_ovsmp_quad_order=None,
                        use_l2_weighting=False,
                        fmm_order=None,
                        visualize=False):

    if fmm_order is None:
        fmm_order = qbx_order * 2
    if bdry_quad_order is None:
        bdry_quad_order = mesh_order
    if bdry_ovsmp_quad_order is None:
        bdry_ovsmp_quad_order = 4 * bdry_quad_order

    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, AxisTargetDerivative
    kernel = HelmholtzKernel(2)

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

    pde_op = op_class(mode,
                      k_vacuum=1,
                      interfaces=((0, 1, sym.DEFAULT_SOURCE), ),
                      domain_k_exprs=(k0, k1),
                      beta=beta,
                      use_l2_weighting=use_l2_weighting)

    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).with_refinement()

    #print(sym.pretty(pde_op.operator(op_unknown_sym)))
    #1/0
    bound_pde_op = bind(qbx, pde_op.operator(op_unknown_sym))

    e_factor = float(pde_op.ez_enabled)
    h_factor = float(pde_op.hz_enabled)

    e_sources_0 = make_obj_array(list(np.array([[0.1, 0.2]]).T.copy()))
    e_strengths_0 = np.array([1 * e_factor])
    e_sources_1 = make_obj_array(list(np.array([[4, 4]]).T.copy()))
    e_strengths_1 = np.array([1 * e_factor])

    h_sources_0 = make_obj_array(list(np.array([[0.2, 0.1]]).T.copy()))
    h_strengths_0 = np.array([1 * h_factor])
    h_sources_1 = make_obj_array(list(np.array([[4, 5]]).T.copy()))
    h_strengths_1 = np.array([1 * h_factor])

    kernel_grad = [
        AxisTargetDerivative(i, kernel)
        for i in range(density_discr.ambient_dim)
    ]

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

    normal = bind(density_discr, sym.normal())(queue).as_vector(np.object)
    tangent = bind(density_discr,
                   sym.pseudoscalar() / sym.area_element())(queue).as_vector(
                       np.object)

    _, (E0, ) = pot_p2p(queue,
                        density_discr.nodes(),
                        e_sources_0, [e_strengths_0],
                        out_host=False,
                        k=K0)
    _, (E1, ) = pot_p2p(queue,
                        density_discr.nodes(),
                        e_sources_1, [e_strengths_1],
                        out_host=False,
                        k=K1)
    _, (grad0_E0, grad1_E0) = pot_p2p_grad(queue,
                                           density_discr.nodes(),
                                           e_sources_0, [e_strengths_0],
                                           out_host=False,
                                           k=K0)
    _, (grad0_E1, grad1_E1) = pot_p2p_grad(queue,
                                           density_discr.nodes(),
                                           e_sources_1, [e_strengths_1],
                                           out_host=False,
                                           k=K1)

    _, (H0, ) = pot_p2p(queue,
                        density_discr.nodes(),
                        h_sources_0, [h_strengths_0],
                        out_host=False,
                        k=K0)
    _, (H1, ) = pot_p2p(queue,
                        density_discr.nodes(),
                        h_sources_1, [h_strengths_1],
                        out_host=False,
                        k=K1)
    _, (grad0_H0, grad1_H0) = pot_p2p_grad(queue,
                                           density_discr.nodes(),
                                           h_sources_0, [h_strengths_0],
                                           out_host=False,
                                           k=K0)
    _, (grad0_H1, grad1_H1) = pot_p2p_grad(queue,
                                           density_discr.nodes(),
                                           h_sources_1, [h_strengths_1],
                                           out_host=False,
                                           k=K1)

    E0_dntarget = (grad0_E0 * normal[0] + grad1_E0 * normal[1])  # noqa
    E1_dntarget = (grad0_E1 * normal[0] + grad1_E1 * normal[1])  # noqa

    H0_dntarget = (grad0_H0 * normal[0] + grad1_H0 * normal[1])  # noqa
    H1_dntarget = (grad0_H1 * normal[0] + grad1_H1 * normal[1])  # noqa

    E0_dttarget = (grad0_E0 * tangent[0] + grad1_E0 * tangent[1])  # noqa
    E1_dttarget = (grad0_E1 * tangent[0] + grad1_E1 * tangent[1])  # noqa

    H0_dttarget = (grad0_H0 * tangent[0] + grad1_H0 * tangent[1])  # noqa
    H1_dttarget = (grad0_H1 * tangent[0] + grad1_H1 * tangent[1])  # noqa

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

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

                if term.direction == pde_op.dir_none:
                    bvp_rhs[i_bc] += (term.coeff_outer * E0 +
                                      term.coeff_inner * E1)
                elif term.direction == pde_op.dir_normal:
                    bvp_rhs[i_bc] += (term.coeff_outer * E0_dntarget +
                                      term.coeff_inner * E1_dntarget)
                elif term.direction == pde_op.dir_tangential:
                    bvp_rhs[i_bc] += (term.coeff_outer * E0_dttarget +
                                      term.coeff_inner * E1_dttarget)
                else:
                    raise NotImplementedError("direction spec in RHS")

            elif term.field_kind == pde_op.field_kind_h:
                if term.direction == pde_op.dir_none:
                    bvp_rhs[i_bc] += (term.coeff_outer * H0 +
                                      term.coeff_inner * H1)
                elif term.direction == pde_op.dir_normal:
                    bvp_rhs[i_bc] += (term.coeff_outer * H0_dntarget +
                                      term.coeff_inner * H1_dntarget)
                elif term.direction == pde_op.dir_tangential:
                    bvp_rhs[i_bc] += (term.coeff_outer * H0_dttarget +
                                      term.coeff_inner * H1_dttarget)
                else:
                    raise NotImplementedError("direction spec in RHS")

            if use_l2_weighting:
                bvp_rhs[i_bc] *= sqrt_w

    scipy_op = bound_pde_op.scipy_op(queue,
                                     "unknown",
                                     domains=[sym.DEFAULT_TARGET] *
                                     len(pde_op.bcs),
                                     K0=K0,
                                     K1=K1,
                                     dtype=np.complex128)

    if mode == "tem" or op_class is SRep:
        from sumpy.tools import vector_from_device, vector_to_device
        from pytential.solve import lu
        unknown = lu(scipy_op, vector_from_device(queue, bvp_rhs))
        unknown = vector_to_device(queue, unknown)

    else:
        from pytential.solve import gmres
        gmres_result = gmres(scipy_op,
                             bvp_rhs,
                             tol=1e-14,
                             progress=True,
                             hard_failure=True,
                             stall_iterations=0)

        unknown = gmres_result.solution

    # }}}

    targets_0 = make_obj_array(
        list(np.array([[3.2 + t, -4] for t in [0, 0.5, 1]]).T.copy()))
    targets_1 = make_obj_array(
        list(np.array([[t * -0.3, t * -0.2] for t in [0, 0.5, 1]]).T.copy()))

    from pytential.target import PointsTarget
    from sumpy.tools import vector_from_device
    F0_tgt = vector_from_device(
        queue,
        bind(  # noqa
            (qbx, PointsTarget(targets_0)),
            representation0_sym)(queue, unknown=unknown, K0=K0, K1=K1))
    F1_tgt = vector_from_device(
        queue,
        bind(  # noqa
            (qbx, PointsTarget(targets_1)),
            representation1_sym)(queue, unknown=unknown, K0=K0, K1=K1))

    _, (E0_tgt_true, ) = pot_p2p(queue,
                                 targets_0,
                                 e_sources_0, [e_strengths_0],
                                 out_host=True,
                                 k=K0)
    _, (E1_tgt_true, ) = pot_p2p(queue,
                                 targets_1,
                                 e_sources_1, [e_strengths_1],
                                 out_host=True,
                                 k=K1)

    _, (H0_tgt_true, ) = pot_p2p(queue,
                                 targets_0,
                                 h_sources_0, [h_strengths_0],
                                 out_host=True,
                                 k=K0)
    _, (H1_tgt_true, ) = pot_p2p(queue,
                                 targets_1,
                                 h_sources_1, [h_strengths_1],
                                 out_host=True,
                                 k=K1)

    err_F0_total = 0  # noqa
    err_F1_total = 0  # noqa

    i_field = 0

    def vec_norm(ary):
        return la.norm(ary.reshape(-1))

    def field_kind_to_string(field_kind):
        return {pde_op.field_kind_e: "E", pde_op.field_kind_h: "H"}[field_kind]

    for field_kind in pde_op.field_kinds:
        if not pde_op.is_field_present(field_kind):
            continue

        if field_kind == pde_op.field_kind_e:
            F0_tgt_true = E0_tgt_true  # noqa
            F1_tgt_true = E1_tgt_true  # noqa
        elif field_kind == pde_op.field_kind_h:
            F0_tgt_true = H0_tgt_true  # noqa
            F1_tgt_true = H1_tgt_true  # noqa
        else:
            assert False

        abs_err_F0 = vec_norm(F0_tgt[i_field] - F0_tgt_true)  # noqa
        abs_err_F1 = vec_norm(F1_tgt[i_field] - F1_tgt_true)  # noqa

        rel_err_F0 = abs_err_F0 / vec_norm(F0_tgt_true)  # noqa
        rel_err_F1 = abs_err_F1 / vec_norm(F1_tgt_true)  # noqa

        err_F0_total = max(rel_err_F0, err_F0_total)  # noqa
        err_F1_total = max(rel_err_F1, err_F1_total)  # noqa

        print("Abs Err %s0" % field_kind_to_string(field_kind), abs_err_F0)
        print("Abs Err %s1" % field_kind_to_string(field_kind), abs_err_F1)

        print("Rel Err %s0" % field_kind_to_string(field_kind), rel_err_F0)
        print("Rel Err %s1" % field_kind_to_string(field_kind), rel_err_F1)

        i_field += 1

    if visualize:
        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)
        fld1 = bind((qbx, PointsTarget(fplot.points)),
                    representation1_sym)(queue, unknown=unknown, K1=K1)

        comp_fields = []
        i_field = 0
        for field_kind in pde_op.field_kinds:
            if not pde_op.is_field_present(field_kind):
                continue

            fld_str = field_kind_to_string(field_kind)
            comp_fields.extend([
                ("%s_fld0" % fld_str, fld0[i_field].get()),
                ("%s_fld1" % fld_str, fld1[i_field].get()),
            ])

            i_field += 0

        low_order_qbx = QBXLayerPotentialSource(
            density_discr,
            fine_order=bdry_ovsmp_quad_order,
            qbx_order=2,
            fmm_order=3).with_refinement()
        from sumpy.kernel import LaplaceKernel
        from pytential.target import PointsTarget
        ones = (cl.array.empty(queue, (density_discr.nnodes, ),
                               dtype=np.float64).fill(1))
        ind_func = -bind(
            (low_order_qbx, PointsTarget(fplot.points)),
            sym.D(LaplaceKernel(2), sym.var("u")))(queue, u=ones).get()

        _, (e_fld0_true, ) = pot_p2p(queue,
                                     fplot.points,
                                     e_sources_0, [e_strengths_0],
                                     out_host=True,
                                     k=K0)
        _, (e_fld1_true, ) = pot_p2p(queue,
                                     fplot.points,
                                     e_sources_1, [e_strengths_1],
                                     out_host=True,
                                     k=K1)
        _, (h_fld0_true, ) = pot_p2p(queue,
                                     fplot.points,
                                     h_sources_0, [h_strengths_0],
                                     out_host=True,
                                     k=K0)
        _, (h_fld1_true, ) = pot_p2p(queue,
                                     fplot.points,
                                     h_sources_1, [h_strengths_1],
                                     out_host=True,
                                     k=K1)

        #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5)
        fplot.write_vtk_file("potential-n%d.vts" % nelements, [
            ("e_fld0_true", e_fld0_true),
            ("e_fld1_true", e_fld1_true),
            ("h_fld0_true", h_fld0_true),
            ("h_fld1_true", h_fld1_true),
            ("ind", ind_func),
        ] + comp_fields)

    return err_F0_total, err_F1_total
コード例 #15
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)),
    ])
コード例 #16
0
 def __init__(self, k=sym.var("k")):
     from sumpy.kernel import HelmholtzKernel
     self.kernel = HelmholtzKernel(3)
     self.k = k
コード例 #17
0
ファイル: test_kernels.py プロジェクト: benSepanski/sumpy
            #flags="print_hl_cl",
            out_host=True,
            **extra_source_kwargs)
        expected_result += mpoles

    norm = la.norm(actual_result - expected_result) / la.norm(expected_result)
    assert norm < 1e-12


@pytest.mark.parametrize("order", [4])
@pytest.mark.parametrize(("base_knl", "expn_class"), [
    (LaplaceKernel(2), VolumeTaylorLocalExpansion),
    (LaplaceKernel(2), VolumeTaylorMultipoleExpansion),
    (LaplaceKernel(2), LaplaceConformingVolumeTaylorLocalExpansion),
    (LaplaceKernel(2), LaplaceConformingVolumeTaylorMultipoleExpansion),
    (HelmholtzKernel(2), VolumeTaylorMultipoleExpansion),
    (HelmholtzKernel(2), VolumeTaylorLocalExpansion),
    (HelmholtzKernel(2), HelmholtzConformingVolumeTaylorLocalExpansion),
    (HelmholtzKernel(2), HelmholtzConformingVolumeTaylorMultipoleExpansion),
    (HelmholtzKernel(2), H2DLocalExpansion),
    (HelmholtzKernel(2), H2DMultipoleExpansion),
    (DirectionalSourceDerivative(BiharmonicKernel(2),
                                 "dir_vec"), VolumeTaylorMultipoleExpansion),
    (DirectionalSourceDerivative(BiharmonicKernel(2),
                                 "dir_vec"), VolumeTaylorLocalExpansion),
    (HelmholtzKernel(2,
                     allow_evanescent=True), VolumeTaylorMultipoleExpansion),
    (HelmholtzKernel(2, allow_evanescent=True), VolumeTaylorLocalExpansion),
    (HelmholtzKernel(2, allow_evanescent=True),
     HelmholtzConformingVolumeTaylorLocalExpansion),
    (HelmholtzKernel(2, allow_evanescent=True),
コード例 #18
0
def test_pyfmmlib_fmm(ctx_getter, dims, use_dipoles, helmholtz_k):
    logging.basicConfig(level=logging.INFO)

    from pytest import importorskip
    importorskip("pyfmmlib")

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

    nsources = 3000
    ntargets = 1000
    dtype = np.float64

    sources = p_normal(queue, nsources, dims, dtype, seed=15)
    targets = (p_normal(queue, ntargets, dims, dtype, seed=18) +
               np.array([2, 0, 0])[:dims])

    sources_host = particle_array_to_host(sources)
    targets_host = particle_array_to_host(targets)

    from boxtree import TreeBuilder
    tb = TreeBuilder(ctx)

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

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

    trav = trav.get(queue=queue)

    from pyopencl.clrandom import PhiloxGenerator
    rng = PhiloxGenerator(queue.context, seed=20)

    weights = rng.uniform(queue, nsources, dtype=np.float64).get()
    #weights = np.ones(nsources)

    if use_dipoles:
        np.random.seed(13)
        dipole_vec = np.random.randn(dims, nsources)
    else:
        dipole_vec = None

    if dims == 2 and helmholtz_k == 0:
        base_nterms = 20
    else:
        base_nterms = 10

    def fmm_level_to_nterms(tree, lev):
        result = base_nterms

        if lev < 3 and helmholtz_k:
            # exercise order-varies-by-level capability
            result += 5

        if use_dipoles:
            result += 1

        return result

    from boxtree.pyfmmlib_integration import FMMLibExpansionWrangler
    wrangler = FMMLibExpansionWrangler(trav.tree,
                                       helmholtz_k,
                                       fmm_level_to_nterms=fmm_level_to_nterms,
                                       dipole_vec=dipole_vec)

    from boxtree.fmm import drive_fmm

    timing_data = {}
    pot = drive_fmm(trav, wrangler, weights, timing_data=timing_data)
    print(timing_data)
    assert timing_data

    # {{{ ref fmmlib computation

    logger.info("computing direct (reference) result")

    import pyfmmlib
    fmmlib_routine = getattr(
        pyfmmlib, "%spot%s%ddall%s_vec" %
        (wrangler.eqn_letter, "fld" if dims == 3 else "grad", dims,
         "_dp" if use_dipoles else ""))

    kwargs = {}
    if dims == 3:
        kwargs["iffld"] = False
    else:
        kwargs["ifgrad"] = False
        kwargs["ifhess"] = False

    if use_dipoles:
        if helmholtz_k == 0 and dims == 2:
            kwargs["dipstr"] = -weights * (dipole_vec[0] + 1j * dipole_vec[1])
        else:
            kwargs["dipstr"] = weights
            kwargs["dipvec"] = dipole_vec
    else:
        kwargs["charge"] = weights
    if helmholtz_k:
        kwargs["zk"] = helmholtz_k

    ref_pot = wrangler.finalize_potentials(
        fmmlib_routine(sources=sources_host.T,
                       targets=targets_host.T,
                       **kwargs)[0])

    rel_err = la.norm(pot - ref_pot, np.inf) / la.norm(ref_pot, np.inf)
    logger.info("relative l2 error vs fmmlib direct: %g" % rel_err)
    assert rel_err < 1e-5, rel_err

    # }}}

    # {{{ check against sumpy

    try:
        import sumpy  # noqa
    except ImportError:
        have_sumpy = False
        from warnings import warn
        warn("sumpy unavailable: cannot compute independent reference "
             "values for pyfmmlib")
    else:
        have_sumpy = True

    if have_sumpy:
        from sumpy.kernel import (LaplaceKernel, HelmholtzKernel,
                                  DirectionalSourceDerivative)
        from sumpy.p2p import P2P

        sumpy_extra_kwargs = {}
        if helmholtz_k:
            knl = HelmholtzKernel(dims)
            sumpy_extra_kwargs["k"] = helmholtz_k
        else:
            knl = LaplaceKernel(dims)

        if use_dipoles:
            knl = DirectionalSourceDerivative(knl)
            sumpy_extra_kwargs["src_derivative_dir"] = dipole_vec

        p2p = P2P(ctx, [knl], exclude_self=False)

        evt, (sumpy_ref_pot, ) = p2p(queue,
                                     targets,
                                     sources, [weights],
                                     out_host=True,
                                     **sumpy_extra_kwargs)

        sumpy_rel_err = (la.norm(pot - sumpy_ref_pot, np.inf) /
                         la.norm(sumpy_ref_pot, np.inf))

        logger.info("relative l2 error vs sumpy direct: %g" % sumpy_rel_err)
        assert sumpy_rel_err < 1e-5, sumpy_rel_err
コード例 #19
0
def nonlocal_integral_eq(
    mesh,
    scatterer_bdy_id,
    outer_bdy_id,
    wave_number,
    options_prefix=None,
    solver_parameters=None,
    fspace=None,
    vfspace=None,
    true_sol_grad_expr=None,
    actx=None,
    dgfspace=None,
    dgvfspace=None,
    meshmode_src_connection=None,
    qbx_kwargs=None,
):
    r"""
        see run_method for descriptions of unlisted args

        args:

        gamma and beta are used to precondition
        with the following equation:

        \Delta u - \kappa^2 \gamma u = 0
        (\partial_n - i\kappa\beta) u |_\Sigma = 0
    """
    # make sure we get outer bdy id as tuple in case it consists of multiple ids
    if isinstance(outer_bdy_id, int):
        outer_bdy_id = [outer_bdy_id]
    outer_bdy_id = tuple(outer_bdy_id)
    # away from the excluded region, but firedrake and meshmode point
    # into
    pyt_inner_normal_sign = -1

    ambient_dim = mesh.geometric_dimension()

    # {{{ Build src and tgt

    # build connection meshmode near src boundary -> src boundary inside meshmode
    from meshmode.discretization.poly_element import \
        InterpolatoryQuadratureSimplexGroupFactory
    from meshmode.discretization.connection import make_face_restriction
    factory = InterpolatoryQuadratureSimplexGroupFactory(
        dgfspace.finat_element.degree)
    src_bdy_connection = make_face_restriction(actx,
                                               meshmode_src_connection.discr,
                                               factory, scatterer_bdy_id)
    # source is a qbx layer potential
    from pytential.qbx import QBXLayerPotentialSource
    disable_refinement = (fspace.mesh().geometric_dimension() == 3)
    qbx = QBXLayerPotentialSource(src_bdy_connection.to_discr,
                                  **qbx_kwargs,
                                  _disable_refinement=disable_refinement)

    # get target indices and point-set
    target_indices, target = get_target_points_and_indices(
        fspace, outer_bdy_id)

    # }}}

    # build the operations
    from pytential import bind, sym
    r"""
    ..math:

    x \in \Sigma

    grad_op(x) =
        \nabla(
            \int_\Gamma(
                u(y) \partial_n H_0^{(1)}(\kappa |x - y|)
            )d\gamma(y)
        )
    """
    grad_op = pyt_inner_normal_sign * sym.grad(
        ambient_dim,
        sym.D(HelmholtzKernel(ambient_dim),
              sym.var("u"),
              k=sym.var("k"),
              qbx_forced_limit=None))
    r"""
    ..math:

    x \in \Sigma

    op(x) =
        i \kappa \cdot
        \int_\Gamma(
            u(y) \partial_n H_0^{(1)}(\kappa |x - y|)
        )d\gamma(y)
    """
    op = pyt_inner_normal_sign * 1j * sym.var("k") * (sym.D(
        HelmholtzKernel(ambient_dim),
        sym.var("u"),
        k=sym.var("k"),
        qbx_forced_limit=None))

    # bind the operations
    pyt_grad_op = bind((qbx, target), grad_op)
    pyt_op = bind((qbx, target), op)

    # }}}

    class MatrixFreeB(object):
        def __init__(self, A, pyt_grad_op, pyt_op, actx, kappa):
            """
            :arg kappa: The wave number
            """

            self.actx = actx
            self.k = kappa
            self.pyt_op = pyt_op
            self.pyt_grad_op = pyt_grad_op
            self.A = A
            self.meshmode_src_connection = meshmode_src_connection

            # {{{ Create some functions needed for multing
            self.x_fntn = Function(fspace)

            # CG
            self.potential_int = Function(fspace)
            self.potential_int.dat.data[:] = 0.0
            self.grad_potential_int = Function(vfspace)
            self.grad_potential_int.dat.data[:] = 0.0
            self.pyt_result = Function(fspace)

            self.n = FacetNormal(mesh)
            self.v = TestFunction(fspace)

            # some meshmode ones
            self.x_mm_fntn = self.meshmode_src_connection.discr.empty(
                self.actx, dtype='c')

            # }}}

        def mult(self, mat, x, y):
            # Copy function data into the fivredrake function
            self.x_fntn.dat.data[:] = x[:]
            # Transfer the function to meshmode
            self.meshmode_src_connection.from_firedrake(project(
                self.x_fntn, dgfspace),
                                                        out=self.x_mm_fntn)
            # Restrict to boundary
            x_mm_fntn_on_bdy = src_bdy_connection(self.x_mm_fntn)

            # Apply the operation
            potential_int_mm = self.pyt_op(self.actx,
                                           u=x_mm_fntn_on_bdy,
                                           k=self.k)
            grad_potential_int_mm = self.pyt_grad_op(self.actx,
                                                     u=x_mm_fntn_on_bdy,
                                                     k=self.k)
            # Store in firedrake
            self.potential_int.dat.data[target_indices] = potential_int_mm.get(
            )
            for dim in range(grad_potential_int_mm.shape[0]):
                self.grad_potential_int.dat.data[
                    target_indices, dim] = grad_potential_int_mm[dim].get()

            # Integrate the potential
            r"""
            Compute the inner products using firedrake. Note this
            will be subtracted later, hence appears off by a sign.

            .. math::

                \langle
                    n(x) \cdot \nabla(
                        \int_\Gamma(
                            u(y) \partial_n H_0^{(1)}(\kappa |x - y|)
                        )d\gamma(y)
                    ), v
                \rangle_\Sigma
                - \langle
                    i \kappa \cdot
                    \int_\Gamma(
                        u(y) \partial_n H_0^{(1)}(\kappa |x - y|)
                    )d\gamma(y), v
                \rangle_\Sigma
            """
            self.pyt_result = assemble(
                inner(inner(self.grad_potential_int, self.n), self.v) *
                ds(outer_bdy_id) -
                inner(self.potential_int, self.v) * ds(outer_bdy_id))

            # y <- Ax - evaluated potential
            self.A.mult(x, y)
            with self.pyt_result.dat.vec_ro as ep:
                y.axpy(-1, ep)

    # {{{ Compute normal helmholtz operator
    u = TrialFunction(fspace)
    v = TestFunction(fspace)
    r"""
    .. math::

        \langle
            \nabla u, \nabla v
        \rangle
        - \kappa^2 \cdot \langle
            u, v
        \rangle
        - i \kappa \langle
            u, v
        \rangle_\Sigma
    """
    a = inner(grad(u), grad(v)) * dx \
        - Constant(wave_number**2) * inner(u, v) * dx \
        - Constant(1j * wave_number) * inner(u, v) * ds(outer_bdy_id)

    # get the concrete matrix from a general bilinear form
    A = assemble(a).M.handle
    # }}}

    # {{{ Setup Python matrix
    B = PETSc.Mat().create()

    # build matrix context
    Bctx = MatrixFreeB(A, pyt_grad_op, pyt_op, actx, wave_number)

    # set up B as same size as A
    B.setSizes(*A.getSizes())

    B.setType(B.Type.PYTHON)
    B.setPythonContext(Bctx)
    B.setUp()
    # }}}

    # {{{ Create rhs

    # Remember f is \partial_n(true_sol)|_\Gamma
    # so we just need to compute \int_\Gamma\partial_n(true_sol) H(x-y)

    sigma = sym.make_sym_vector("sigma", ambient_dim)
    r"""
    ..math:

    x \in \Sigma

    grad_op(x) =
        \nabla(
            \int_\Gamma(
                f(y) H_0^{(1)}(\kappa |x - y|)
            )d\gamma(y)
        )
    """
    grad_op = pyt_inner_normal_sign * \
        sym.grad(ambient_dim, sym.S(HelmholtzKernel(ambient_dim),
                                    sym.n_dot(sigma),
                                    k=sym.var("k"), qbx_forced_limit=None))
    r"""
    ..math:

    x \in \Sigma

    op(x) =
        i \kappa \cdot
        \int_\Gamma(
            f(y) H_0^{(1)}(\kappa |x - y|)
        )d\gamma(y)
        )
    """
    op = 1j * sym.var("k") * pyt_inner_normal_sign * \
        sym.S(HelmholtzKernel(ambient_dim),
              sym.n_dot(sigma),
              k=sym.var("k"),
              qbx_forced_limit=None)

    rhs_grad_op = bind((qbx, target), grad_op)
    rhs_op = bind((qbx, target), op)

    # Transfer to meshmode
    metadata = {'quadrature_degree': 2 * fspace.ufl_element().degree()}
    dg_true_sol_grad = project(true_sol_grad_expr,
                               dgvfspace,
                               form_compiler_parameters=metadata)
    true_sol_grad_mm = meshmode_src_connection.from_firedrake(dg_true_sol_grad,
                                                              actx=actx)
    true_sol_grad_mm = src_bdy_connection(true_sol_grad_mm)
    # Apply the operations
    f_grad_convoluted_mm = rhs_grad_op(actx,
                                       sigma=true_sol_grad_mm,
                                       k=wave_number)
    f_convoluted_mm = rhs_op(actx, sigma=true_sol_grad_mm, k=wave_number)
    # Transfer function back to firedrake
    f_grad_convoluted = Function(vfspace)
    f_convoluted = Function(fspace)
    f_grad_convoluted.dat.data[:] = 0.0
    f_convoluted.dat.data[:] = 0.0

    for dim in range(f_grad_convoluted_mm.shape[0]):
        f_grad_convoluted.dat.data[target_indices,
                                   dim] = f_grad_convoluted_mm[dim].get()
    f_convoluted.dat.data[target_indices] = f_convoluted_mm.get()
    r"""
        \langle
            f, v
        \rangle_\Gamma
        + \langle
            i \kappa \cdot \int_\Gamma(
                f(y) H_0^{(1)}(\kappa |x - y|)
            )d\gamma(y), v
        \rangle_\Sigma
        - \langle
            n(x) \cdot \nabla(
                \int_\Gamma(
                    f(y) H_0^{(1)}(\kappa |x - y|)
                )d\gamma(y)
            ), v
        \rangle_\Sigma
    """
    rhs_form = inner(inner(true_sol_grad_expr, FacetNormal(mesh)),
                     v) * ds(scatterer_bdy_id, metadata=metadata) \
        + inner(f_convoluted, v) * ds(outer_bdy_id) \
        - inner(inner(f_grad_convoluted, FacetNormal(mesh)),
                v) * ds(outer_bdy_id)

    rhs = assemble(rhs_form)

    # {{{ set up a solver:
    solution = Function(fspace, name="Computed Solution")

    #       {{{ Used for preconditioning
    if 'gamma' in solver_parameters or 'beta' in solver_parameters:
        gamma = complex(solver_parameters.pop('gamma', 1.0))

        import cmath
        beta = complex(solver_parameters.pop('beta', cmath.sqrt(gamma)))

        p = inner(grad(u), grad(v)) * dx \
            - Constant(wave_number**2 * gamma) * inner(u, v) * dx \
            - Constant(1j * wave_number * beta) * inner(u, v) * ds(outer_bdy_id)
        P = assemble(p).M.handle

    else:
        P = A
    #       }}}

    # Set up options to contain solver parameters:
    ksp = PETSc.KSP().create()
    if solver_parameters['pc_type'] == 'pyamg':
        del solver_parameters['pc_type']  # We are using the AMG preconditioner

        pyamg_tol = solver_parameters.get('pyamg_tol', None)
        if pyamg_tol is not None:
            pyamg_tol = float(pyamg_tol)
        pyamg_maxiter = solver_parameters.get('pyamg_maxiter', None)
        if pyamg_maxiter is not None:
            pyamg_maxiter = int(pyamg_maxiter)
        ksp.setOperators(B)
        ksp.setUp()
        pc = ksp.pc
        pc.setType(pc.Type.PYTHON)
        pc.setPythonContext(
            AMGTransmissionPreconditioner(wave_number,
                                          fspace,
                                          A,
                                          tol=pyamg_tol,
                                          maxiter=pyamg_maxiter,
                                          use_plane_waves=True))
    # Otherwise use regular preconditioner
    else:
        ksp.setOperators(B, P)

    options_manager = OptionsManager(solver_parameters, options_prefix)
    options_manager.set_from_options(ksp)

    import petsc4py.PETSc
    petsc4py.PETSc.Sys.popErrorHandler()
    with rhs.dat.vec_ro as b:
        with solution.dat.vec as x:
            ksp.solve(b, x)
    # }}}

    return ksp, solution
コード例 #20
0
def draw_pot_figure(aspect_ratio,
                    nsrc=100,
                    novsmp=None,
                    helmholtz_k=0,
                    what_operator="S",
                    what_operator_lpot=None,
                    order=4,
                    ovsmp_center_exp=0.66,
                    force_center_side=None):

    import logging
    logging.basicConfig(level=logging.INFO)

    if novsmp is None:
        novsmp = 4 * nsrc

    if what_operator_lpot is None:
        what_operator_lpot = what_operator

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

    # {{{ make plot targets

    center = np.asarray([0, 0], dtype=np.float64)
    from sumpy.visualization import FieldPlotter
    fp = FieldPlotter(center, npoints=1000, extent=6)

    # }}}

    # {{{ make p2p kernel calculator

    from sumpy.p2p import P2P
    from sumpy.kernel import LaplaceKernel, HelmholtzKernel
    from sumpy.expansion.local import H2DLocalExpansion, LineTaylorLocalExpansion
    if helmholtz_k:
        if isinstance(helmholtz_k, complex):
            knl = HelmholtzKernel(2, allow_evanescent=True)
            expn_class = H2DLocalExpansion
            knl_kwargs = {"k": helmholtz_k}
        else:
            knl = HelmholtzKernel(2)
            expn_class = H2DLocalExpansion
            knl_kwargs = {"k": helmholtz_k}

    else:
        knl = LaplaceKernel(2)
        expn_class = LineTaylorLocalExpansion
        knl_kwargs = {}

    vol_knl = process_kernel(knl, what_operator)
    p2p = P2P(ctx, [vol_knl], exclude_self=False, value_dtypes=np.complex128)

    lpot_knl = process_kernel(knl, what_operator_lpot)

    from sumpy.qbx import LayerPotential
    lpot = LayerPotential(ctx, [expn_class(lpot_knl, order=order)],
                          value_dtypes=np.complex128)

    # }}}

    # {{{ set up geometry

    # r,a,b match the corresponding letters from G. J. Rodin and O. Steinbach,
    # Boundary Element Preconditioners for problems defined on slender domains.
    # http://dx.doi.org/10.1137/S1064827500372067

    a = 1
    b = 1 / aspect_ratio

    def map_to_curve(t):
        t = t * (2 * np.pi)

        x = a * np.cos(t)
        y = b * np.sin(t)

        w = (np.zeros_like(t) + 1) / len(t)

        return x, y, w

    from curve import CurveGrid

    native_t = np.linspace(0, 1, nsrc, endpoint=False)
    native_x, native_y, native_weights = map_to_curve(native_t)
    native_curve = CurveGrid(native_x, native_y)

    ovsmp_t = np.linspace(0, 1, novsmp, endpoint=False)
    ovsmp_x, ovsmp_y, ovsmp_weights = map_to_curve(ovsmp_t)
    ovsmp_curve = CurveGrid(ovsmp_x, ovsmp_y)

    curve_len = np.sum(ovsmp_weights * ovsmp_curve.speed)
    hovsmp = curve_len / novsmp
    center_dist = 5 * hovsmp

    if force_center_side is not None:
        center_side = force_center_side * np.ones(len(native_curve))
    else:
        center_side = -np.sign(native_curve.mean_curvature)

    centers = (native_curve.pos +
               center_side[:, np.newaxis] * center_dist * native_curve.normal)

    #native_curve.plot()
    #pt.show()

    volpot_kwargs = knl_kwargs.copy()
    lpot_kwargs = knl_kwargs.copy()

    if what_operator == "D":
        volpot_kwargs["src_derivative_dir"] = native_curve.normal

    if what_operator_lpot == "D":
        lpot_kwargs["src_derivative_dir"] = ovsmp_curve.normal

    if what_operator_lpot == "S'":
        lpot_kwargs["tgt_derivative_dir"] = native_curve.normal

    # }}}

    if 0:
        # {{{ build matrix

        from fourier import make_fourier_interp_matrix
        fim = make_fourier_interp_matrix(novsmp, nsrc)
        from sumpy.tools import build_matrix
        from scipy.sparse.linalg import LinearOperator

        def apply_lpot(x):
            xovsmp = np.dot(fim, x)
            evt, (y, ) = lpot(queue,
                              native_curve.pos,
                              ovsmp_curve.pos,
                              centers,
                              [xovsmp * ovsmp_curve.speed * ovsmp_weights],
                              expansion_radii=np.ones(centers.shape[1]),
                              **lpot_kwargs)

            return y

        op = LinearOperator((nsrc, nsrc), apply_lpot)
        mat = build_matrix(op, dtype=np.complex128)
        w, v = la.eig(mat)
        pt.plot(w.real, "o-")
        #import sys; sys.exit(0)
        return

        # }}}

    # {{{ compute potentials

    mode_nr = 0
    density = np.cos(mode_nr * 2 * np.pi * native_t).astype(np.complex128)
    ovsmp_density = np.cos(mode_nr * 2 * np.pi * ovsmp_t).astype(np.complex128)
    evt, (vol_pot, ) = p2p(queue, fp.points, native_curve.pos,
                           [native_curve.speed * native_weights * density],
                           **volpot_kwargs)

    evt, (curve_pot, ) = lpot(
        queue,
        native_curve.pos,
        ovsmp_curve.pos,
        centers, [ovsmp_density * ovsmp_curve.speed * ovsmp_weights],
        expansion_radii=np.ones(centers.shape[1]),
        **lpot_kwargs)

    # }}}

    if 0:
        # {{{ plot on-surface potential in 2D

        pt.plot(curve_pot, label="pot")
        pt.plot(density, label="dens")
        pt.legend()
        pt.show()

        # }}}

    fp.write_vtk_file("potential.vts", [("potential", vol_pot.real)])

    if 0:
        # {{{ 2D false-color plot

        pt.clf()
        plotval = np.log10(1e-20 + np.abs(vol_pot))
        im = fp.show_scalar_in_matplotlib(plotval.real)
        from matplotlib.colors import Normalize
        im.set_norm(Normalize(vmin=-2, vmax=1))

        src = native_curve.pos
        pt.plot(src[:, 0], src[:, 1], "o-k")
        # close the curve
        pt.plot(src[-1::-len(src) + 1, 0], src[-1::-len(src) + 1, 1], "o-k")

        #pt.gca().set_aspect("equal", "datalim")
        cb = pt.colorbar(shrink=0.9)
        cb.set_label(r"$\log_{10}(\mathdefault{Error})$")
        #from matplotlib.ticker import NullFormatter
        #pt.gca().xaxis.set_major_formatter(NullFormatter())
        #pt.gca().yaxis.set_major_formatter(NullFormatter())
        fp.set_matplotlib_limits()

        # }}}
    else:
        # {{{ 3D plots

        plotval_vol = vol_pot.real
        plotval_c = curve_pot.real

        scale = 1

        if 0:
            # crop singularities--doesn't work very well
            neighbors = [
                np.roll(plotval_vol, 3, 0),
                np.roll(plotval_vol, -3, 0),
                np.roll(plotval_vol, 6, 0),
                np.roll(plotval_vol, -6, 0),
            ]
            avg = np.average(np.abs(plotval_vol))
            outlier_flag = sum(np.abs(plotval_vol - nb)
                               for nb in neighbors) > avg
            plotval_vol[outlier_flag] = sum(
                nb[outlier_flag] for nb in neighbors) / len(neighbors)

        fp.show_scalar_in_mayavi(scale * plotval_vol, max_val=1)
        from mayavi import mlab
        mlab.colorbar()
        if 1:
            mlab.points3d(native_curve.pos[0],
                          native_curve.pos[1],
                          scale * plotval_c,
                          scale_factor=0.02)
        mlab.show()
コード例 #21
0
    def __init__(self,
                 mode,
                 k_vacuum,
                 domain_k_exprs,
                 beta,
                 interfaces,
                 use_l2_weighting=None):
        """
        :attr mode: one of 'te', 'tm', 'tem'
        :attr k_vacuum: A symbolic expression for the wave number in vacuum.
            May be a string, which will be interpreted as a variable name.
        :attr interfaces: a tuple of tuples
            ``(outer_domain, inner_domain, interface_id)``,
            where *outer_domain* and *inner_domain* are indices into
            *domain_k_names*,
            and *interface_id* is a symbolic name for the discretization of the
            interface. 'outer' designates the side of the interface to which
            the normal points.
        :attr domain_k_exprs: a tuple of variable names of the Helmholtz
            parameter *k*, to be used inside each part of the source geometry.
            May also be a tuple of strings, which will be transformed into
            variable references of the corresponding names.
        :attr beta: A symbolic expression for the wave number in the :math:`z`
            direction. May be a string, which will be interpreted as a variable
            name.
        """

        if use_l2_weighting is None:
            use_l2_weighting = False

        super(Dielectric2DBoundaryOperatorBase,
              self).__init__(use_l2_weighting=use_l2_weighting)

        if mode == "te":
            self.ez_enabled = False
            self.hz_enabled = True
        elif mode == "tm":
            self.ez_enabled = True
            self.hz_enabled = False
        elif mode == "tem":
            self.ez_enabled = True
            self.hz_enabled = True
        else:
            raise ValueError("invalid mode '%s'" % mode)

        self.interfaces = interfaces

        fk_e = self.field_kind_e
        fk_h = self.field_kind_h

        dir_none = self.dir_none
        dir_normal = self.dir_normal
        dir_tangential = self.dir_tangential

        if isinstance(beta, str):
            beta = sym.var(beta)
        beta = sym.cse(beta, "beta")

        if isinstance(k_vacuum, str):
            k_vacuum = sym.var(k_vacuum)
        k_vacuum = sym.cse(k_vacuum, "k_vac")

        self.domain_k_exprs = [
            sym.var(k_expr) if isinstance(k_expr, str) else sym.cse(
                k_expr, "k%d" % idom)
            for idom, k_expr in enumerate(domain_k_exprs)
        ]
        del domain_k_exprs

        # Note the case of k/K!
        # "K" is the 2D Helmholtz parameter.
        # "k" is the 3D Helmholtz parameter.

        self.domain_K_exprs = [
            sym.cse((k_expr**2 - beta**2)**0.5, "K%d" % i)
            for i, k_expr in enumerate(self.domain_k_exprs)
        ]

        from sumpy.kernel import HelmholtzKernel
        self.kernel = HelmholtzKernel(2, allow_evanescent=True)

        # {{{ build bc list

        # list of tuples, where each tuple consists of BCTermDescriptor instances

        all_bcs = []
        for i_interface, (outer_domain, inner_domain,
                          _) in (enumerate(self.interfaces)):
            k_outer = self.domain_k_exprs[outer_domain]
            k_inner = self.domain_k_exprs[inner_domain]

            all_bcs += [
                (  # [E] = 0
                    self.BCTermDescriptor(i_interface=i_interface,
                                          direction=dir_none,
                                          field_kind=fk_e,
                                          coeff_outer=1,
                                          coeff_inner=-1), ),
                (  # [H] = 0
                    self.BCTermDescriptor(i_interface=i_interface,
                                          direction=dir_none,
                                          field_kind=fk_h,
                                          coeff_outer=1,
                                          coeff_inner=-1), ),
                (
                    self.BCTermDescriptor(
                        i_interface=i_interface,
                        direction=dir_tangential,
                        field_kind=fk_e,
                        coeff_outer=beta / (k_outer**2 - beta**2),
                        coeff_inner=-beta / (k_inner**2 - beta**2)),
                    self.BCTermDescriptor(
                        i_interface=i_interface,
                        direction=dir_normal,
                        field_kind=fk_h,
                        coeff_outer=sym.cse(-k_vacuum /
                                            (k_outer**2 - beta**2)),
                        coeff_inner=sym.cse(k_vacuum /
                                            (k_inner**2 - beta**2))),
                ),
                (self.BCTermDescriptor(
                    i_interface=i_interface,
                    direction=dir_tangential,
                    field_kind=fk_h,
                    coeff_outer=beta / (k_outer**2 - beta**2),
                    coeff_inner=-beta / (k_inner**2 - beta**2)),
                 self.BCTermDescriptor(
                     i_interface=i_interface,
                     direction=dir_normal,
                     field_kind=fk_e,
                     coeff_outer=sym.cse(
                         (k_outer**2 / k_vacuum) / (k_outer**2 - beta**2)),
                     coeff_inner=sym.cse(-(k_inner**2 / k_vacuum) /
                                         (k_inner**2 - beta**2)))),
            ]

            del k_outer
            del k_inner

        self.bcs = []
        for bc in all_bcs:
            any_significant_e = any(
                term.field_kind == fk_e
                and term.direction in [dir_normal, dir_none] for term in bc)
            any_significant_h = any(
                term.field_kind == fk_h
                and term.direction in [dir_normal, dir_none] for term in bc)
            is_necessary = ((self.ez_enabled and any_significant_e)
                            or (self.hz_enabled and any_significant_h))

            # Only keep tangential modes for TEM. Otherwise,
            # no jump in H already implies jump condition on
            # tangential derivative.
            is_tem = self.ez_enabled and self.hz_enabled
            terms = tuple(term for term in bc
                          if term.direction != dir_tangential or is_tem)

            if is_necessary:
                self.bcs.append(terms)

        assert (len(all_bcs) * (int(self.ez_enabled) + int(self.hz_enabled)) //
                2 == len(self.bcs))
コード例 #22
0
ファイル: __init__.py プロジェクト: choward1491/pytential
 def __init__(self, k=None):
     if k is None:
         k = sym.var("k")
     from sumpy.kernel import HelmholtzKernel
     self.kernel = HelmholtzKernel(3)
     self.k = k
コード例 #23
0
ファイル: test_misc.py プロジェクト: xywei/sumpy
            eoc_rec.add_data_point(h, err)

        print(eoc_rec)
        assert eoc_rec.order_estimate() > order - 2 - 0.1


class FakeTree:
    def __init__(self, dimensions, root_extent, stick_out_factor):
        self.dimensions = dimensions
        self.root_extent = root_extent
        self.stick_out_factor = stick_out_factor


@pytest.mark.parametrize("knl", [
    LaplaceKernel(2),
    HelmholtzKernel(2),
    LaplaceKernel(3),
    HelmholtzKernel(3)
])
def test_order_finder(knl):
    from sumpy.expansion.level_to_order import SimpleExpansionOrderFinder

    ofind = SimpleExpansionOrderFinder(1e-5)

    tree = FakeTree(knl.dim, 200, 0.5)
    orders = [
        ofind(knl, frozenset([("k", 5)]), tree, level) for level in range(30)
    ]
    print(orders)

    # Order should not increase with level
コード例 #24
0
    for resolution in (getattr(case, "resolutions", None)
                       or case.geometry.resolutions):
        mesh = case.geometry.get_mesh(resolution, target_order)
        if mesh is None:
            break

        d = mesh.ambient_dim
        k = case.k

        lap_k_sym = LaplaceKernel(d)
        if k == 0:
            k_sym = lap_k_sym
            knl_kwargs = {}
        else:
            k_sym = HelmholtzKernel(d)
            knl_kwargs = {"k": sym.var("k")}

        from meshmode.discretization import Discretization
        from meshmode.discretization.poly_element import \
                InterpolatoryQuadratureSimplexGroupFactory
        from pytential.qbx import QBXLayerPotentialSource
        pre_density_discr = Discretization(
            cl_ctx, mesh,
            InterpolatoryQuadratureSimplexGroupFactory(target_order))

        refiner_extra_kwargs = {}

        if case.k != 0:
            refiner_extra_kwargs["kernel_length_scale"] = 5 / case.k
コード例 #25
0
ファイル: layerpot.py プロジェクト: choward1491/pytential
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()
コード例 #26
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),
    ])
コード例 #27
0
queue = cl.CommandQueue(cl_ctx)

target_order = 5
qbx_order = 3
mode_nr = 4

if 1:
    cad_file_name = "geometries/ellipsoid.step"
    h = 0.6
else:
    cad_file_name = "geometries/two-cylinders-smooth.step"
    h = 0.4

k = 0
if k:
    kernel = HelmholtzKernel(3)
else:
    kernel = LaplaceKernel(3)
#kernel = OneKernel()


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])
コード例 #28
0
except ImportError:
    pass
else:
    faulthandler.enable()


@pytest.mark.parametrize("knl, local_expn_class, mpole_expn_class", [
    (LaplaceKernel(2), VolumeTaylorLocalExpansion,
     VolumeTaylorMultipoleExpansion),
    (LaplaceKernel(2), LaplaceConformingVolumeTaylorLocalExpansion,
     LaplaceConformingVolumeTaylorMultipoleExpansion),
    (LaplaceKernel(3), VolumeTaylorLocalExpansion,
     VolumeTaylorMultipoleExpansion),
    (LaplaceKernel(3), LaplaceConformingVolumeTaylorLocalExpansion,
     LaplaceConformingVolumeTaylorMultipoleExpansion),
    (HelmholtzKernel(2), VolumeTaylorLocalExpansion,
     VolumeTaylorMultipoleExpansion),
    (HelmholtzKernel(2), HelmholtzConformingVolumeTaylorLocalExpansion,
     HelmholtzConformingVolumeTaylorMultipoleExpansion),
    (HelmholtzKernel(2), H2DLocalExpansion, H2DMultipoleExpansion),
    (HelmholtzKernel(3), VolumeTaylorLocalExpansion,
     VolumeTaylorMultipoleExpansion),
    (HelmholtzKernel(3), HelmholtzConformingVolumeTaylorLocalExpansion,
     HelmholtzConformingVolumeTaylorMultipoleExpansion),
    (YukawaKernel(2), Y2DLocalExpansion, Y2DMultipoleExpansion),
])
def test_sumpy_fmm(ctx_getter, knl, local_expn_class, mpole_expn_class):
    logging.basicConfig(level=logging.INFO)

    ctx = ctx_getter()
    queue = cl.CommandQueue(ctx)
コード例 #29
0
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),
    ])
コード例 #30
0
def test_target_specific_qbx(ctx_getter, op, helmholtz_k, qbx_order):
    logging.basicConfig(level=logging.INFO)

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

    target_order = 4
    fmm_tol = 1e-3

    from meshmode.mesh.generation import generate_icosphere
    mesh = generate_icosphere(1, target_order)

    from meshmode.discretization import Discretization
    from meshmode.discretization.poly_element import \
        InterpolatoryQuadratureSimplexGroupFactory
    from pytential.qbx import QBXLayerPotentialSource
    pre_density_discr = Discretization(
        cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(target_order))

    from sumpy.expansion.level_to_order import SimpleExpansionOrderFinder

    refiner_extra_kwargs = {}

    if helmholtz_k != 0:
        refiner_extra_kwargs["kernel_length_scale"] = 5 / abs(helmholtz_k)

    qbx, _ = QBXLayerPotentialSource(
        pre_density_discr,
        4 * target_order,
        qbx_order=qbx_order,
        fmm_level_to_order=SimpleExpansionOrderFinder(fmm_tol),
        fmm_backend="fmmlib",
        _expansions_in_tree_have_extent=True,
        _expansion_stick_out_factor=0.9,
        _use_target_specific_qbx=False,
    ).with_refinement(**refiner_extra_kwargs)

    density_discr = qbx.density_discr

    nodes = density_discr.nodes().with_queue(queue)
    u_dev = clmath.sin(nodes[0])

    if helmholtz_k == 0:
        kernel = LaplaceKernel(3)
        kernel_kwargs = {}
    else:
        kernel = HelmholtzKernel(3, allow_evanescent=True)
        kernel_kwargs = {"k": sym.var("k")}

    u_sym = sym.var("u")

    if op == "S":
        op = sym.S
    elif op == "D":
        op = sym.D
    elif op == "Sp":
        op = sym.Sp
    else:
        raise ValueError("unknown operator: '%s'" % op)

    expr = op(kernel, u_sym, qbx_forced_limit=-1, **kernel_kwargs)

    bound_op = bind(qbx, expr)
    pot_ref = bound_op(queue, u=u_dev, k=helmholtz_k).get()

    qbx = qbx.copy(_use_target_specific_qbx=True)
    bound_op = bind(qbx, expr)
    pot_tsqbx = bound_op(queue, u=u_dev, k=helmholtz_k).get()

    assert np.allclose(pot_tsqbx, pot_ref, atol=1e-13, rtol=1e-13)