def get_zero_op(self, kernel, **knl_kwargs):

        u_sym = sym.var("u")
        dn_u_sym = sym.var("dn_u")

        return (
            sym.S(kernel, dn_u_sym, qbx_forced_limit=-1, **knl_kwargs)
            - sym.D(kernel, u_sym, qbx_forced_limit="avg", **knl_kwargs)
            - 0.5*u_sym)
    def get_zero_op(self, kernel, **knl_kwargs):
        d = kernel.dim
        u_sym = sym.var("u")
        grad_u_sym = sym.make_sym_mv("grad_u",  d)
        dn_u_sym = sym.var("dn_u")

        return (
                d1.resolve(d1.dnabla(d) * d1(sym.S(kernel, dn_u_sym,
                    qbx_forced_limit="avg", **knl_kwargs)))
                - d2.resolve(d2.dnabla(d) * d2(sym.D(kernel, u_sym,
                    qbx_forced_limit="avg", **knl_kwargs)))
                - 0.5*grad_u_sym
                )
Exemple #3
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)
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()
    def get_zero_op(self, kernel, **knl_kwargs):
        assert isinstance(kernel, LaplaceKernel)
        assert not knl_kwargs

        u_sym = sym.var("u")

        return (
                    -sym.Dp(kernel, sym.S(kernel, u_sym))
                    - 0.25*u_sym + sym.Sp(kernel, sym.Sp(kernel, u_sym))
                    )
Exemple #6
0
def test_unregularized_off_surface_fmm_vs_direct(ctx_getter):
    cl_ctx = ctx_getter()
    queue = cl.CommandQueue(cl_ctx)

    nelements = 300
    target_order = 8
    fmm_order = 4

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

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

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

    sigma = density_discr.zeros(queue) + 1

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

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

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

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

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

    nelements = 10
    order = 8

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

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

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

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

    from sumpy.kernel import one_kernel_2d

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

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

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

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

    assert np.allclose(result_self.get(), 2 * np.pi)
    assert np.allclose(result_nonself.get(), 2 * np.pi)
Exemple #8
0
def test_identities(ctx_getter, zero_op_name, curve_name, curve_f, qbx_order, k):
    cl_ctx = ctx_getter()
    queue = cl.CommandQueue(cl_ctx)

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

    target_order = 7

    u_sym = sym.var("u")
    grad_u_sym = sym.VectorVariable("grad_u")
    dn_u_sym = sym.var("dn_u")

    if k == 0:
        k_sym = 0
    else:
        k_sym = "k"

    zero_op_table = {
            "green":
            sym.S(k_sym, dn_u_sym) - sym.D(k_sym, u_sym) - 0.5*u_sym,

            "green_grad":
            d1.nabla * d1(sym.S(k_sym, dn_u_sym))
            - d2.nabla * d2(sym.D(k_sym, u_sym))
            - 0.5*grad_u_sym,

            # only for k==0:
            "zero_calderon":
            -sym.Dp(0, sym.S(0, u_sym))
            - 0.25*u_sym + sym.Sp(0, sym.Sp(0, u_sym))
            }
    order_table = {
            "green": qbx_order,
            "green_grad": qbx_order-1,
            "zero_calderon": qbx_order-1,
            }

    zero_op = zero_op_table[zero_op_name]

    from pytools.convergence import EOCRecorder
    eoc_rec = EOCRecorder()

    for nelements in [30, 50, 70]:
        mesh = make_curve_mesh(curve_f,
                np.linspace(0, 1, nelements+1),
                target_order)

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

        qbx = QBXLayerPotentialSource(density_discr, 4*target_order,
                qbx_order,
                # Don't use FMM for now
                fmm_order=False)

        # {{{ compute values of a solution to the PDE

        nodes_host = density_discr.nodes().get(queue)
        normal = bind(density_discr, sym.normal())(queue).as_vector(np.object)
        normal_host = [normal[0].get(), normal[1].get()]

        if k != 0:
            angle = 0.3
            wave_vec = np.array([np.cos(angle), np.sin(angle)])
            u = np.exp(1j*k*np.tensordot(wave_vec, nodes_host, axes=1))
            grad_u = 1j*k*wave_vec[:, np.newaxis]*u
        else:
            center = np.array([3, 1])
            diff = nodes_host - center[:, np.newaxis]
            dist_squared = np.sum(diff**2, axis=0)
            dist = np.sqrt(dist_squared)
            u = np.log(dist)
            grad_u = diff/dist_squared

        dn_u = normal_host[0]*grad_u[0] + normal_host[1]*grad_u[1]

        # }}}

        u_dev = cl.array.to_device(queue, u)
        dn_u_dev = cl.array.to_device(queue, dn_u)
        grad_u_dev = cl.array.to_device(queue, grad_u)

        key = (qbx_order, curve_name, nelements, zero_op_name)

        bound_op = bind(qbx, zero_op)
        error = bound_op(
                queue, u=u_dev, dn_u=dn_u_dev, grad_u=grad_u_dev, k=k)
        if 0:
            pt.plot(error)
            pt.show()

        l2_error_norm = norm(density_discr, queue, error)
        print(key, l2_error_norm)

        eoc_rec.add_data_point(1/nelements, l2_error_norm)

    print(eoc_rec)
    tgt_order = order_table[zero_op_name]
    assert eoc_rec.order_estimate() > tgt_order - 1.3
Exemple #9
0
def test_ellipse_eigenvalues(ctx_getter, ellipse_aspect, mode_nr, qbx_order):
    logging.basicConfig(level=logging.INFO)

    print("ellipse_aspect: %s, mode_nr: %d, qbx_order: %d" % (
            ellipse_aspect, mode_nr, qbx_order))

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

    target_order = 7

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

    s_eoc_rec = EOCRecorder()
    d_eoc_rec = EOCRecorder()
    sp_eoc_rec = EOCRecorder()

    if ellipse_aspect != 1:
        nelements_values = [60, 100, 150, 200]
    else:
        nelements_values = [30, 70]

    # See
    #
    # [1] G. J. Rodin and O. Steinbach, "Boundary Element Preconditioners
    # for Problems Defined on Slender Domains", SIAM Journal on Scientific
    # Computing, Vol. 24, No. 4, pg. 1450, 2003.
    # http://dx.doi.org/10.1137/S1064827500372067

    for nelements in nelements_values:
        mesh = make_curve_mesh(partial(ellipse, ellipse_aspect),
                np.linspace(0, 1, nelements+1),
                target_order)

        fmm_order = qbx_order
        if fmm_order > 3:
            # FIXME: for now
            fmm_order = False

        density_discr = Discretization(
                cl_ctx, mesh,
                InterpolatoryQuadratureSimplexGroupFactory(target_order))
        qbx = QBXLayerPotentialSource(density_discr, 4*target_order,
                qbx_order, fmm_order=fmm_order)

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

        if 0:
            # plot geometry, centers, normals
            centers = qbx.centers(density_discr, 1)
            nodes_h = nodes.get()
            centers_h = [centers[0].get(), centers[1].get()]
            pt.plot(nodes_h[0], nodes_h[1], "x-")
            pt.plot(centers_h[0], centers_h[1], "o")
            normal = bind(qbx, sym.normal())(queue).as_vector(np.object)
            pt.quiver(nodes_h[0], nodes_h[1],
                    normal[0].get(), normal[1].get())
            pt.gca().set_aspect("equal")
            pt.show()

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

        ellipse_fraction = ((1-ellipse_aspect)/(1+ellipse_aspect))**mode_nr

        # (2.6) in [1]
        J = cl.clmath.sqrt(  # noqa
                cl.clmath.sin(angle)**2
                + (1/ellipse_aspect)**2 * cl.clmath.cos(angle)**2)

        # {{{ single layer

        sigma = cl.clmath.cos(mode_nr*angle)/J

        s_sigma_op = bind(qbx, sym.S(0, sym.var("sigma")))
        s_sigma = s_sigma_op(queue=queue, sigma=sigma)

        # SIGN BINGO! :)
        s_eigval = 1/(2*mode_nr) * (1 + (-1)**mode_nr * ellipse_fraction)

        # (2.12) in [1]
        s_sigma_ref = s_eigval*J*sigma

        if 0:
            #pt.plot(s_sigma.get(), label="result")
            #pt.plot(s_sigma_ref.get(), label="ref")
            pt.plot((s_sigma_ref-s_sigma).get(), label="err")
            pt.legend()
            pt.show()

        s_err = (
                norm(density_discr, queue, s_sigma - s_sigma_ref)
                /
                norm(density_discr, queue, s_sigma_ref))
        s_eoc_rec.add_data_point(1/nelements, s_err)

        # }}}

        # {{{ double layer

        sigma = cl.clmath.cos(mode_nr*angle)

        d_sigma_op = bind(qbx, sym.D(0, sym.var("sigma")))
        d_sigma = d_sigma_op(queue=queue, sigma=sigma)

        # SIGN BINGO! :)
        d_eigval = -(-1)**mode_nr * 1/2*ellipse_fraction

        d_sigma_ref = d_eigval*sigma

        if 0:
            pt.plot(d_sigma.get(), label="result")
            pt.plot(d_sigma_ref.get(), label="ref")
            pt.legend()
            pt.show()

        if ellipse_aspect == 1:
            d_ref_norm = norm(density_discr, queue, sigma)
        else:
            d_ref_norm = norm(density_discr, queue, d_sigma_ref)

        d_err = (
                norm(density_discr, queue, d_sigma - d_sigma_ref)
                /
                d_ref_norm)
        d_eoc_rec.add_data_point(1/nelements, d_err)

        # }}}

        if ellipse_aspect == 1:
            # {{{ S'

            sigma = cl.clmath.cos(mode_nr*angle)

            sp_sigma_op = bind(qbx, sym.Sp(0, sym.var("sigma")))
            sp_sigma = sp_sigma_op(queue=queue, sigma=sigma)
            sp_eigval = 0

            sp_sigma_ref = sp_eigval*sigma

            sp_err = (
                    norm(density_discr, queue, sp_sigma - sp_sigma_ref)
                    /
                    norm(density_discr, queue, sigma))
            sp_eoc_rec.add_data_point(1/nelements, sp_err)

            # }}}

    print("Errors for S:")
    print(s_eoc_rec)
    required_order = qbx_order + 1
    assert s_eoc_rec.order_estimate() > required_order - 1.5

    print("Errors for D:")
    print(d_eoc_rec)
    required_order = qbx_order
    assert d_eoc_rec.order_estimate() > required_order - 1.5

    if ellipse_aspect == 1:
        print("Errors for S':")
        print(sp_eoc_rec)
        required_order = qbx_order
        assert sp_eoc_rec.order_estimate() > required_order - 1.5
def find_mode():
    import warnings
    warnings.simplefilter("error", np.ComplexWarning)

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

    k0 = 1.4447
    k1 = k0*1.02
    beta_sym = sym.var("beta")

    from pytential.symbolic.pde.scalar import (  # noqa
            DielectricSRep2DBoundaryOperator as SRep,
            DielectricSDRep2DBoundaryOperator as SDRep)
    pde_op = SDRep(
            mode="te",
            k_vacuum=1,
            interfaces=((0, 1, sym.DEFAULT_SOURCE),),
            domain_k_exprs=(k0, k1),
            beta=beta_sym,
            use_l2_weighting=False)

    u_sym = pde_op.make_unknown("u")
    op = pde_op.operator(u_sym)

    # {{{ discretization setup

    from meshmode.mesh.generation import ellipse, make_curve_mesh
    curve_f = partial(ellipse, 1)

    target_order = 7
    qbx_order = 4
    nelements = 30

    from meshmode.mesh.processing import affine_map
    mesh = make_curve_mesh(curve_f,
            np.linspace(0, 1, nelements+1),
            target_order)
    lambda_ = 1.55
    circle_radius = 3.4*2*np.pi/lambda_
    mesh = affine_map(mesh, A=circle_radius*np.eye(2))

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

    qbx = QBXLayerPotentialSource(density_discr, 4*target_order,
            qbx_order,
            # Don't use FMM for now
            fmm_order=False)

    # }}}

    x_vec = np.random.randn(len(u_sym)*density_discr.nnodes)
    y_vec = np.random.randn(len(u_sym)*density_discr.nnodes)

    def muller_solve_func(beta):
        from pytential.symbolic.execution import build_matrix
        mat = build_matrix(
                queue, qbx, op, u_sym,
                context={"beta": beta}).get()

        return 1/x_vec.dot(la.solve(mat, y_vec))

    starting_guesses = (1+0j)*(
            k0
            + (k1-k0) * np.random.rand(3))

    from pytential.muller import muller
    beta, niter = muller(muller_solve_func, z_start=starting_guesses)
    print("beta")
Exemple #11
0
        InterpolatoryQuadratureSimplexGroupFactory

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

qbx = QBXLayerPotentialSource(density_discr, 4*target_order, qbx_order,
        fmm_order=qbx_order)

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

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

from pytential import bind, sym
d = sym.Derivative()
#op = d.nabla[0] * d(sym.S(kernel, sym.var("sigma")))
op = sym.D(kernel, sym.var("sigma"))
#op = sym.S(kernel, sym.var("sigma"))

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

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

bound_bdry_op = bind(qbx, op)
#mlab.figure(bgcolor=(1, 1, 1))
if 1:
Exemple #12
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))
def get_qbx_center_neighborhood_sizes(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)

        from boxtree.area_query import PeerListFinder
        plf = PeerListFinder(queue.context)
        pl, evt = plf(queue, tree)

        # Perform an area query around each QBX center, counting the
        # neighborhood sizes.
        knl = NeighborhoodCounter.generate(
                queue.context,
                tree.dimensions,
                tree.coord_dtype,
                tree.box_id_dtype,
                tree.box_id_dtype,
                tree.nlevels,
                extra_type_aliases=(('particle_id_t', tree.particle_id_dtype),))

        centers = geo_data.centers()
        search_radii = radius * geo_data.expansion_radii().with_queue(queue)

        ncenters = len(search_radii)
        nsources = tree.nsources
        sizes = cl.array.zeros(queue, ncenters, np.int32)

        assert nsources == lpot_source.quad_stage2_density_discr.nnodes

        coords = []
        coords.extend(tree.sources)
        coords.extend(centers)

        evt = knl(
                *NeighborhoodCounter.unwrap_args(
                    tree,
                    pl,
                    tree.box_source_starts,
                    tree.box_source_counts_cumul,
                    search_radii,
                    sizes,
                    *coords),
                range=slice(ncenters),
                queue=queue,
                wait_for=[evt])

        cl.wait_for_events([evt])

        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.get(queue), nsources, ncenters)
            raise ValueError("invalid mesh dim")

    # }}}

    # {{{ set up operator

    knl = case.knl_class(ambient_dim)
    op = case.get_operator(ambient_dim)
    if knl.is_complex_valued:
        dtype = np.complex128
    else:
        dtype = np.float64

    sym_u = op.get_density_var("u")
    sym_bc = op.get_density_var("bc")
    sym_charges = sym.var("charges")

    sym_op_u = op.operator(sym_u)

    # }}}

    # {{{ set up test data

    np.random.seed(22)
    source_charges = np.random.randn(point_source.ndofs)
    source_charges[-1] = -np.sum(source_charges[:-1])
    source_charges = source_charges.astype(dtype)
    assert np.sum(source_charges) < 1.0e-15

    source_charges_dev = actx.from_numpy(source_charges)
Exemple #15
0
from pytential import bind, sym

import faulthandler
from six.moves import range
faulthandler.enable()

target_order = 16
qbx_order = 3
nelements = 60
mode_nr = 3

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


def main():
    import logging
    logging.basicConfig(level=logging.WARNING)  # INFO for more progress info

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

    from meshmode.mesh.generation import (  # noqa
        make_curve_mesh, starfish, ellipse, drop)
Exemple #16
0
def main(mesh_name="torus", visualize=False):
    import logging
    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 == "torus":
        rout = 10
        rin = 1

        from meshmode.mesh.generation import generate_torus
        base_mesh = generate_torus(rout, rin, 40, 4, mesh_order)

        from meshmode.mesh.processing import affine_map, merge_disjoint_meshes
        # nx = 1
        # ny = 1
        nz = 1
        dz = 0
        meshes = [
            affine_map(base_mesh,
                       A=np.diag([1, 1, 1]),
                       b=np.array([0, 0, iz * dz])) for iz in range(nz)
        ]

        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("unknown mesh name: {}".format(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(3), extent=20, npoints=50)
    targets = actx.from_numpy(fplot.points)

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

    # {{{ describe bvp

    from sumpy.kernel import LaplaceKernel
    kernel = LaplaceKernel(3)

    sigma_sym = sym.var("sigma")
    #sqrt_w = sym.sqrt_jac_q_weight(3)
    sqrt_w = 1
    inv_sqrt_w_sigma = sym.cse(sigma_sym / sqrt_w)

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

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

    # }}}

    bound_op = bind(places, bdry_op_sym)

    # {{{ fix rhs and solve

    from meshmode.dof_array import thaw, flatten, unflatten
    nodes = thaw(actx, density_discr.nodes())
    source = np.array([rout, 0, 0])

    def u_incoming_func(x):
        from pytools.obj_array import obj_array_vectorize
        x = obj_array_vectorize(actx.to_numpy, flatten(x))
        x = np.array(list(x))
        #        return 1/cl.clmath.sqrt( (x[0] - source[0])**2
        #                                +(x[1] - source[1])**2
        #                                +(x[2] - source[2])**2 )
        return 1.0 / la.norm(x - source[:, None], axis=0)

    bc = unflatten(actx, density_discr,
                   actx.from_numpy(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", dtype=np.float64),
                         bvp_rhs,
                         tol=1e-14,
                         progress=True,
                         stall_iterations=0,
                         hard_failure=True)

    sigma = bind(places,
                 sym.var("sigma") / sqrt_w)(actx, sigma=gmres_result.solution)

    # }}}

    from meshmode.discretization.visualization import make_visualizer
    bdry_vis = make_visualizer(actx, density_discr, 20)
    bdry_vis.write_vtk_file("laplace.vtu", [
        ("sigma", sigma),
    ])

    # {{{ postprocess/visualize

    repr_kwargs = dict(source="qbx_target_assoc",
                       target="targets",
                       qbx_forced_limit=None)
    representation_sym = (sym.S(kernel, inv_sqrt_w_sigma, **repr_kwargs) +
                          sym.D(kernel, inv_sqrt_w_sigma, **repr_kwargs))

    try:
        fld_in_vol = actx.to_numpy(
            bind(places, representation_sym)(actx, sigma=sigma))
    except QBXTargetAssociationFailedException as e:
        fplot.write_vtk_file("laplace-dirichlet-3d-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("laplace-dirichlet-3d-potential.vts", [
        ("potential", fld_in_vol),
    ])
def main():
    # cl.array.to_device(queue, numpy_array)
    from meshmode.mesh.io import generate_gmsh, FileSource
    from meshmode.mesh.generation import generate_icosphere
    from meshmode.mesh.refinement import Refiner
    mesh = generate_icosphere(1, target_order)

    refinement_increment = 1
    refiner = Refiner(mesh)
    for i in range(refinement_increment):
        flags = np.ones(mesh.nelements, dtype=bool)
        refiner.refine(flags)
        mesh = refiner.get_current_mesh()

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

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

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

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

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

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

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

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

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

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

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

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

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

    if 1:

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

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

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

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

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

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

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

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

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

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

            hvec = np.cross(strength, fvec)

            return hvec

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

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

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

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

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

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

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

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

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

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

        bound_op = bind(qbx, sym_operator)

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

            sigma = gmres_result.solution

        fld_at_tgt = bind((qbx, PointsTarget(tgt_points)),
                          sym_repr)(queue, sigma=sigma, k=k)
        fld_at_tgt = np.array([fi.get() for fi in fld_at_tgt])
        print(fld_at_tgt)
        fld_exact_e, fld_exact_h = dipole3e(tgt_points[0, 0], tgt_points[1, 0],
                                            tgt_points[2,
                                                       0], source, strength, k)
        print(fld_exact_e)
        print(fld_exact_h)
        1 / 0

    # }}}

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

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

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

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

        qbx_stick_out = qbx.copy(target_stick_out_factor=0.1)
        from pytential.target import PointsTarget
        from pytential.qbx import QBXTargetAssociationFailedException

        rho_sym = sym.var("rho")

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

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

        #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5)
        fplot.write_vtk_file("potential.vts", [
            ("potential", fld_in_vol[0]),
            ("grad", fld_in_vol[1:]),
        ])
def test_cost_model_correctness(actx_factory, dim, off_surface,
                                use_target_specific_qbx):
    """Check that computed cost matches that of a constant-one FMM."""
    actx = actx_factory()
    queue = actx.queue

    cost_model = QBXCostModel(
        translation_cost_model_factory=OpCountingTranslationCostModel)

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

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

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

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

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

    modeled_time, _ = op_S.cost_per_stage("constant_one", sigma=sigma)
    modeled_time, = modeled_time.values()

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

    wrangler = ConstantOneQBXExpansionWrangler(
        TreeIndependentDataForWrangler(), queue, geo_data,
        use_target_specific_qbx)

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

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

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

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

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

    # {{{ Test per-box cost

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

    per_box_cost, _ = op_S.cost_per_box("constant_one", sigma=sigma)
    logging.info(per_box_cost)
    per_box_cost, = per_box_cost.values()

    total_aggregate_cost = cost_model.aggregate_over_boxes(per_box_cost)
    assert total_cost == (total_aggregate_cost +
                          modeled_time["coarsen_multipoles"] +
                          modeled_time["refine_locals"])
Exemple #19
0
def test_target_specific_qbx(ctx_factory, op, helmholtz_k, qbx_order):
    logging.basicConfig(level=logging.INFO)

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

    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(
        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")
    from meshmode.dof_array import thaw
    nodes = thaw(actx, density_discr.nodes())
    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)

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

    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)))

    assert np.allclose(pot_tsqbx, pot_ref, atol=1e-13, rtol=1e-13)
Exemple #20
0
def test_3d_jump_relations(ctx_factory, relation, visualize=False):
    # logging.basicConfig(level=logging.INFO)

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

    if relation == "div_s":
        target_order = 3
    else:
        target_order = 4

    qbx_order = target_order

    from pytools.convergence import EOCRecorder
    eoc_rec = EOCRecorder()

    for nel_factor in [6, 10, 14]:
        from meshmode.mesh.generation import generate_torus
        mesh = generate_torus(5,
                              2,
                              order=target_order,
                              n_major=2 * nel_factor,
                              n_minor=nel_factor)

        from meshmode.discretization import Discretization
        from meshmode.discretization.poly_element import \
            InterpolatoryQuadratureSimplexGroupFactory
        pre_discr = Discretization(
            cl_ctx, mesh, InterpolatoryQuadratureSimplexGroupFactory(3))

        from pytential.qbx import QBXLayerPotentialSource
        qbx, _ = QBXLayerPotentialSource(
            pre_discr,
            fine_order=4 * target_order,
            qbx_order=qbx_order,
            fmm_order=qbx_order + 5,
            fmm_backend="fmmlib").with_refinement()

        from sumpy.kernel import LaplaceKernel
        knl = LaplaceKernel(3)

        def nxcurlS(qbx_forced_limit):

            return sym.n_cross(
                sym.curl(
                    sym.S(knl,
                          sym.cse(sym.tangential_to_xyz(density_sym), "jxyz"),
                          qbx_forced_limit=qbx_forced_limit)))

        x, y, z = qbx.density_discr.nodes().with_queue(queue)
        m = cl.clmath

        if relation == "nxcurls":
            density_sym = sym.make_sym_vector("density", 2)

            jump_identity_sym = (
                nxcurlS(+1) -
                (nxcurlS("avg") + 0.5 * sym.tangential_to_xyz(density_sym)))

            # The tangential coordinate system is element-local, so we can't just
            # conjure up some globally smooth functions, interpret their values
            # in the tangential coordinate system, and be done. Instead, generate
            # an XYZ function and project it.
            density = bind(
                qbx, sym.xyz_to_tangential(sym.make_sym_vector("jxyz", 3)))(
                    queue,
                    jxyz=sym.make_obj_array([
                        m.cos(0.5 * x) * m.cos(0.5 * y) * m.cos(0.5 * z),
                        m.sin(0.5 * x) * m.cos(0.5 * y) * m.sin(0.5 * z),
                        m.sin(0.5 * x) * m.cos(0.5 * y) * m.cos(0.5 * z),
                    ]))

        elif relation == "sp":

            density = m.cos(2 * x) * m.cos(2 * y) * m.cos(z)
            density_sym = sym.var("density")

            jump_identity_sym = (
                sym.Sp(knl, density_sym, qbx_forced_limit=+1) -
                (sym.Sp(knl, density_sym, qbx_forced_limit="avg") -
                 0.5 * density_sym))

        elif relation == "div_s":

            density = m.cos(2 * x) * m.cos(2 * y) * m.cos(z)
            density_sym = sym.var("density")

            jump_identity_sym = (
                sym.div(
                    sym.S(knl,
                          sym.normal(3).as_vector() * density_sym,
                          qbx_forced_limit="avg")) +
                sym.D(knl, density_sym, qbx_forced_limit="avg"))

        else:
            raise ValueError("unexpected value of 'relation': %s" % relation)

        bound_jump_identity = bind(qbx, jump_identity_sym)
        jump_identity = bound_jump_identity(queue, density=density)

        h_max = bind(qbx, sym.h_max(qbx.ambient_dim))(queue)
        err = (norm(qbx, queue, jump_identity, np.inf) /
               norm(qbx, queue, density, np.inf))
        print("ERROR", h_max, err)

        eoc_rec.add_data_point(h_max, err)

        # {{{ visualization

        if visualize and relation == "nxcurls":
            nxcurlS_ext = bind(qbx, nxcurlS(+1))(queue, density=density)
            nxcurlS_avg = bind(qbx, nxcurlS("avg"))(queue, density=density)
            jtxyz = bind(qbx,
                         sym.tangential_to_xyz(density_sym))(queue,
                                                             density=density)

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

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

            bdry_vis.write_vtk_file("source-%s.vtu" % nel_factor, [
                ("jt", jtxyz),
                ("nxcurlS_ext", nxcurlS_ext),
                ("nxcurlS_avg", nxcurlS_avg),
                ("bdry_normals", bdry_normals),
            ])

        if visualize and relation == "sp":
            sp_ext = bind(qbx, sym.Sp(knl, density_sym,
                                      qbx_forced_limit=+1))(queue,
                                                            density=density)
            sp_avg = bind(qbx, sym.Sp(knl, density_sym,
                                      qbx_forced_limit="avg"))(queue,
                                                               density=density)

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

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

            bdry_vis.write_vtk_file("source-%s.vtu" % nel_factor, [
                ("density", density),
                ("sp_ext", sp_ext),
                ("sp_avg", sp_avg),
                ("bdry_normals", bdry_normals),
            ])

        # }}}

    print(eoc_rec)

    assert eoc_rec.order_estimate() >= qbx_order - 1.5
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
Exemple #22
0
    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)
Exemple #23
0
mesh = make_curve_mesh(starfish,
        np.linspace(0, 1, nelements+1),
        target_order)

from pytential.discretization.qbx import make_upsampling_qbx_discr

discr = make_upsampling_qbx_discr(
        cl_ctx, mesh, target_order, qbx_order)

nodes = discr.nodes().with_queue(queue)

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

from pytential import bind, sym
representation = sym.D(0, sym.var("sigma"))
op = representation - 0.5*sym.var("sigma")

bc = cl.clmath.cos(mode_nr*angle)

bound_op = bind(discr, op)
from pytential.gmres import gmres
gmres_result = gmres(
        bound_op.scipy_op(queue, "sigma"),
        bc, tol=1e-14, progress=True,
        hard_failure=True)

import sys
sys.exit()

sigma = gmres_result.solution
Exemple #24
0
def test_cost_model_correctness(ctx_factory, dim, off_surface,
        use_target_specific_qbx):
    """Check that computed cost matches that of a constant-one FMM."""
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

    cost_model = (
            CostModel(
                translation_cost_model_factory=OpCountingTranslationCostModel))

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

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

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

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

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

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

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

    wrangler = ConstantOneQBXExpansionWrangler(
            queue, geo_data, use_target_specific_qbx)

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

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

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

    modeled_time = cost_S.get_predicted_times(merge_close_lists=True)

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

    assert not mismatches, "\n".join(str(s) for s in mismatches)
Exemple #25
0
def test_off_surface_eval_vs_direct(ctx_factory, do_plot=False):
    logging.basicConfig(level=logging.INFO)

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

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

    nelements = 300
    target_order = 8
    qbx_order = 3

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

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

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

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

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

    from pytential.qbx import QBXTargetAssociationFailedException
    try:
        direct_density_discr = direct_qbx.density_discr
        direct_sigma = direct_density_discr.zeros(queue) + 1
        direct_fld_in_vol = bind((direct_qbx, ptarget), op)(queue,
                                                            sigma=direct_sigma)

    except QBXTargetAssociationFailedException as e:
        fplot.show_scalar_in_matplotlib(e.failed_target_flags.get(queue))
        import matplotlib.pyplot as pt
        pt.show()
        raise

    fmm_density_discr = fmm_qbx.density_discr
    fmm_sigma = fmm_density_discr.zeros(queue) + 1
    fmm_fld_in_vol = bind((fmm_qbx, ptarget), op)(queue, sigma=fmm_sigma)

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

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

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

    assert linf_err < 1e-3
Exemple #26
0
def main(mesh_name="ellipse", visualize=False):
    import logging
    logging.basicConfig(level=logging.WARNING)  # 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("unknown mesh name: {}".format(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)),
        ])
Exemple #27
0
def main():
    import logging
    logging.basicConfig(level=logging.WARNING)  # INFO for more progress info

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

    target_order = 16
    qbx_order = 3
    nelements = 60
    mode_nr = 0

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

    mesh = make_curve_mesh(
            #lambda t: ellipse(1, t),
            starfish,
            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))

    slow_qbx, _ = QBXLayerPotentialSource(
            pre_density_discr, fine_order=2*target_order,
            qbx_order=qbx_order, fmm_order=False,
            target_association_tolerance=.05
            ).with_refinement()
    qbx = slow_qbx.copy(fmm_order=10)
    density_discr = slow_qbx.density_discr

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

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

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

    sigma = cl.clmath.cos(mode_nr*angle)

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

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

    fld_in_vol = bind(
            (slow_qbx, PointsTarget(fplot.points)),
            op)(queue, sigma=sigma, k=k).get()

    fmm_fld_in_vol = bind(
            (qbx, PointsTarget(fplot.points)),
            op)(queue, sigma=sigma, k=k).get()

    err = fmm_fld_in_vol-fld_in_vol

    import matplotlib
    matplotlib.use('Agg')
    im = fplot.show_scalar_in_matplotlib(np.log10(np.abs(err) + 1e-17))

    from matplotlib.colors import Normalize
    im.set_norm(Normalize(vmin=-12, vmax=0))

    import matplotlib.pyplot as pt
    from matplotlib.ticker import NullFormatter
    pt.gca().xaxis.set_major_formatter(NullFormatter())
    pt.gca().yaxis.set_major_formatter(NullFormatter())

    cb = pt.colorbar(shrink=0.9)
    cb.set_label(r"$\log_{10}(\mathdefault{Error})$")

    pt.savefig("fmm-error-order-%d.pdf" % qbx_order)
Exemple #28
0
def run_exterior_stokes_2d(
        ctx_factory,
        nelements,
        mesh_order=4,
        target_order=4,
        qbx_order=4,
        fmm_order=False,  # FIXME: FMM is slower than direct eval
        mu=1,
        circle_rad=1.5,
        visualize=False):

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

    logging.basicConfig(level=logging.INFO)

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

    ovsmp_target_order = 4 * target_order

    # {{{ geometries

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

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

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

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

    from pytential.target import PointsTarget
    nsamp = 30
    eval_points_1d = np.linspace(-3., 3., nsamp)
    eval_points = np.zeros((2, len(eval_points_1d)**2))
    eval_points[0, :] = np.tile(eval_points_1d, len(eval_points_1d))
    eval_points[1, :] = np.repeat(eval_points_1d, len(eval_points_1d))
    eval_points = outside_circle(eval_points, radius=circle_rad)
    point_targets = PointsTarget(eval_points)

    fplot = FieldPlotter(np.zeros(2), extent=6, npoints=100)
    plot_targets = PointsTarget(outside_circle(fplot.points,
                                               radius=circle_rad))

    places = GeometryCollection({
        sym.DEFAULT_SOURCE: qbx,
        sym.DEFAULT_TARGET: qbx.density_discr,
        "point_target": point_targets,
        "plot_target": plot_targets,
    })

    density_discr = places.get_discretization(sym.DEFAULT_SOURCE)

    normal = bind(places, sym.normal(2).as_vector())(actx)
    path_length = bind(places, sym.integral(2, 1, 1))(actx)

    # }}}

    # {{{ describe bvp

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

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

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

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

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

    # }}}

    bound_op = bind(places, bdry_op_sym)

    # {{{ fix rhs and solve

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

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

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

    from meshmode.dof_array import unflatten, flatten, thaw
    nodes = flatten(thaw(actx, density_discr.nodes()))
    fund_soln_loc = np.array([0.5, -0.2])
    strength = 100.
    bc = unflatten(
        actx, density_discr,
        fund_and_rot_soln(nodes[0], nodes[1], fund_soln_loc, strength))

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

    from pytential.utils import unflatten_from_numpy
    omega = unflatten_from_numpy(
        actx, density_discr,
        make_obj_array([(strength / path_length) * np.ones(len(nodes[0])),
                        np.zeros(len(nodes[0]))]))

    bvp_rhs = bind(places,
                   sym.make_sym_vector("bc", dim) + u_A_sym_bdry)(actx,
                                                                  bc=bc,
                                                                  mu=mu,
                                                                  omega=omega)
    gmres_result = gmres(bound_op.scipy_op(actx,
                                           "sigma",
                                           np.float64,
                                           mu=mu,
                                           normal=normal),
                         bvp_rhs,
                         x0=bvp_rhs,
                         tol=1e-9,
                         progress=True,
                         stall_iterations=0,
                         hard_failure=True)

    # }}}

    # {{{ postprocess/visualize

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

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

    where = (sym.DEFAULT_SOURCE, "point_target")
    vel = bind(places, representation_sym,
               auto_where=where)(actx,
                                 sigma=sigma,
                                 mu=mu,
                                 normal=normal,
                                 sigma_int_val=int_val,
                                 omega=omega)
    print("@@@@@@@@")

    plot_vel = bind(places,
                    representation_sym,
                    auto_where=(sym.DEFAULT_SOURCE,
                                "plot_target"))(actx,
                                                sigma=sigma,
                                                mu=mu,
                                                normal=normal,
                                                sigma_int_val=int_val,
                                                omega=omega)

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

    exact_soln = fund_and_rot_soln(actx.from_numpy(eval_points[0]),
                                   actx.from_numpy(eval_points[1]),
                                   fund_soln_loc, strength)

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

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

    if 0:
        print("@@@@@@@@")
        print("vel[0], err[0], rel_err[0] ***** vel[1], err[1], rel_err[1]: ")
        for i in range(len(vel[0])):
            print(
                "{:15.8e}, {:15.8e}, {:15.8e} ***** {:15.8e}, {:15.8e}, {:15.8e}"
                .format(vel[0][i], err[0][i], rel_err[0][i], vel[1][i],
                        err[1][i], rel_err[1][i]))

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

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

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

    if visualize:
        import matplotlib.pyplot as plt

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

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

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

    # }}}

    h_max = bind(places, sym.h_max(qbx.ambient_dim))(actx)
    return h_max, l2_err
Exemple #29
0
 def __init__(self, k=sym.var("k")):
     from sumpy.kernel import HelmholtzKernel
     self.kernel = HelmholtzKernel(3)
     self.k = k
Exemple #30
0
def main():
    import logging
    logging.basicConfig(level=logging.WARNING)  # INFO for more progress info

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

    target_order = 16
    qbx_order = 3
    nelements = 60
    mode_nr = 0

    k = 0
    if k:
        kernel = HelmholtzKernel(2)
    else:
        kernel = LaplaceKernel(2)

    mesh = make_curve_mesh(
        #lambda t: ellipse(1, t),
        starfish,
        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))

    unaccel_qbx = QBXLayerPotentialSource(
        pre_density_discr,
        fine_order=2 * target_order,
        qbx_order=qbx_order,
        fmm_order=False,
        target_association_tolerance=.05,
    )

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

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

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

    from pytential import bind, sym
    if k:
        kernel_kwargs = {"k": sym.var("k")}
    else:
        kernel_kwargs = {}

    def get_op():
        kwargs = dict(qbx_forced_limit=None)
        kwargs.update(kernel_kwargs)
        # return sym.d_dx(2, sym.S(kernel, sym.var("sigma"), **kwargs))
        # return sym.D(kernel, sym.var("sigma"), **kwargs)
        return sym.S(kernel, sym.var("sigma"), **kwargs)

    op = get_op()

    sigma = actx.np.cos(mode_nr * angle)

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

    fld_in_vol = bind(places, op,
                      auto_where=("unaccel_qbx", "targets"))(actx,
                                                             sigma=sigma,
                                                             k=k).get()

    fmm_fld_in_vol = bind(places, op,
                          auto_where=("qbx", "targets"))(actx,
                                                         sigma=sigma,
                                                         k=k).get()

    err = fmm_fld_in_vol - fld_in_vol

    try:
        import matplotlib
    except ImportError:
        return

    matplotlib.use("Agg")
    im = fplot.show_scalar_in_matplotlib(np.log10(np.abs(err) + 1e-17))

    from matplotlib.colors import Normalize
    im.set_norm(Normalize(vmin=-12, vmax=0))

    import matplotlib.pyplot as pt
    from matplotlib.ticker import NullFormatter
    pt.gca().xaxis.set_major_formatter(NullFormatter())
    pt.gca().yaxis.set_major_formatter(NullFormatter())

    cb = pt.colorbar(shrink=0.9)
    cb.set_label(r"$\log_{10}(\mathrm{Error})$")

    pt.savefig("fmm-error-order-%d.pdf" % qbx_order)
Exemple #31
0
def timing_run(nx, ny):
    import logging
    logging.basicConfig(level=logging.WARNING)  # INFO for more progress info

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

    mesh = make_mesh(nx=nx, ny=ny)

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

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

    # {{{ describe bvp

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

    cse = sym.cse

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

    # Brakhage-Werner parameter
    alpha = 1j

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

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

    # }}}

    bound_op = bind(qbx, bdry_op_sym)

    # {{{ fix rhs and solve

    mode_nr = 3
    nodes = density_discr.nodes().with_queue(queue)
    angle = cl.clmath.atan2(nodes[1], nodes[0])

    sigma = cl.clmath.cos(mode_nr*angle)

    # }}}

    # {{{ postprocess/visualize

    repr_kwargs = dict(k=sym.var("k"), qbx_forced_limit=+1)

    sym_op = sym.S(kernel, sym.var("sigma"), **repr_kwargs)
    bound_op = bind(qbx, sym_op)

    print("FMM WARM-UP RUN 1: %d elements" % mesh.nelements)
    bound_op(queue, sigma=sigma, k=k)
    print("FMM WARM-UP RUN 2: %d elements" % mesh.nelements)
    bound_op(queue, sigma=sigma, k=k)
    queue.finish()
    print("FMM TIMING RUN: %d elements" % mesh.nelements)

    from time import time
    t_start = time()

    bound_op(queue, sigma=sigma, k=k)
    queue.finish()
    elapsed = time()-t_start

    print("FMM TIMING RUN DONE: %d elements -> %g s"
            % (mesh.nelements, elapsed))

    return (mesh.nelements, elapsed)

    if 0:
        from sumpy.visualization import FieldPlotter
        fplot = FieldPlotter(np.zeros(2), extent=5, npoints=1500)

        targets = cl.array.to_device(queue, fplot.points)

        qbx_tgt_tol = qbx.copy(target_association_tolerance=0.05)

        indicator_qbx = qbx_tgt_tol.copy(
                fmm_level_to_order=lambda lev: 7, qbx_order=2)

        ones_density = density_discr.zeros(queue)
        ones_density.fill(1)
        indicator = bind(
                (indicator_qbx, PointsTarget(targets)),
                sym_op)(
                queue, sigma=ones_density).get()

        qbx_stick_out = qbx.copy(target_stick_out_factor=0.1)
        try:
            fld_in_vol = bind(
                    (qbx_stick_out, PointsTarget(targets)),
                    sym_op)(queue, sigma=sigma, k=k).get()
        except QBXTargetAssociationFailedException as e:
            fplot.write_vtk_file(
                    "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(
                "potential-scaling.vts",
                [
                    ("potential", fld_in_vol),
                    ("indicator", indicator)
                    ]
                )
Exemple #32
0
 def get_op():
     kwargs = dict(qbx_forced_limit=None)
     kwargs.update(kernel_kwargs)
     # return sym.d_dx(2, sym.S(kernel, sym.var("sigma"), **kwargs))
     # return sym.D(kernel, sym.var("sigma"), **kwargs)
     return sym.S(kernel, sym.var("sigma"), **kwargs)
Exemple #33
0
    extinction of the combined (incoming + scattered) field on the interior
    of the scatterer.
    """
    logging.basicConfig(level=logging.INFO)

    actx = actx_factory()

    np.random.seed(12)

    knl_kwargs = {"k": case.k}

    # {{{ come up with a solution to Maxwell's equations

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

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

    test_source = case.get_source(actx)

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

    import pyopencl.clrandom as clrandom
    rng = clrandom.PhiloxGenerator(actx.context, seed=12)
Exemple #34
0
def main():
    import logging
    logging.basicConfig(level=logging.INFO)

    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, 2),
                np.linspace(0, 1, nelements+1),
                mesh_order)

    pre_density_discr = Discretization(
            cl_ctx, 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,
            expansion_disks_in_tree_have_extent=True,
            ).with_refinement()
    density_discr = qbx.density_discr

    from pytential.symbolic.pde.cahn_hilliard import CahnHilliardOperator
    chop = CahnHilliardOperator(
            # FIXME: Constants?
            lambda1=1.5,
            lambda2=1.25,
            c=1)

    unk = chop.make_unknown("sigma")
    bound_op = bind(qbx, chop.operator(unk))

    # {{{ fix rhs and solve

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

    def g(xvec):
        x, y = xvec
        return cl.clmath.atan2(y, x)

    bc = sym.make_obj_array([
        # FIXME: Realistic BC
        g(nodes),
        -g(nodes),
        ])

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

    # }}}

    # {{{ postprocess/visualize

    sigma = gmres_result.solution

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

    targets = cl.array.to_device(queue, fplot.points)

    qbx_stick_out = qbx.copy(target_association_tolerance=0.05)

    indicator_qbx = qbx_stick_out.copy(qbx_order=2)

    from sumpy.kernel import LaplaceKernel
    ones_density = density_discr.zeros(queue)
    ones_density.fill(1)
    indicator = bind(
            (indicator_qbx, PointsTarget(targets)),
            sym.D(LaplaceKernel(2), sym.var("sigma")))(
            queue, sigma=ones_density).get()

    try:
        fld_in_vol = bind(
                (qbx_stick_out, PointsTarget(targets)),
                chop.representation(unk))(queue, sigma=sigma).get()
    except QBXTargetAssociationFailedException as e:
        fplot.write_vtk_file(
                "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(
            "potential.vts",
            [
                ("potential", fld_in_vol),
                ("indicator", indicator),
                ]
            )
Exemple #35
0
def run_int_eq_test(
        cl_ctx, queue, curve_f, nelements, qbx_order, bc_type, loc_sign, k,
        target_order, source_order):

    mesh = make_curve_mesh(curve_f,
            np.linspace(0, 1, nelements+1),
            target_order)

    if 0:
        from pytential.visualization import show_mesh
        show_mesh(mesh)

        pt.gca().set_aspect("equal")
        pt.show()

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

    if source_order is None:
        source_order = 4*target_order

    qbx = QBXLayerPotentialSource(
            density_discr, fine_order=source_order, qbx_order=qbx_order,
            # Don't use FMM for now
            fmm_order=False)

    # {{{ set up operator

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

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

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

    if bc_type == "dirichlet":
        op = DirichletOperator((knl, knl_kwargs), loc_sign, use_l2_weighting=True)
    elif bc_type == "neumann":
        op = NeumannOperator((knl, knl_kwargs), loc_sign, use_l2_weighting=True,
                 use_improved_operator=False)
    else:
        assert False

    op_u = op.operator(sym.var("u"))

    # }}}

    # {{{ set up test data

    inner_radius = 0.1
    outer_radius = 2

    if loc_sign < 0:
        test_src_geo_radius = outer_radius
        test_tgt_geo_radius = inner_radius
    else:
        test_src_geo_radius = inner_radius
        test_tgt_geo_radius = outer_radius

    point_sources = make_circular_point_group(10, test_src_geo_radius,
            func=lambda x: x**1.5)
    test_targets = make_circular_point_group(20, test_tgt_geo_radius)

    np.random.seed(22)
    source_charges = np.random.randn(point_sources.shape[1])
    source_charges[-1] = -np.sum(source_charges[:-1])
    source_charges = source_charges.astype(dtype)
    assert np.sum(source_charges) < 1e-15

    # }}}

    if 0:
        # show geometry, centers, normals
        nodes_h = density_discr.nodes().get(queue=queue)
        pt.plot(nodes_h[0], nodes_h[1], "x-")
        normal = bind(density_discr, sym.normal())(queue).as_vector(np.object)
        pt.quiver(nodes_h[0], nodes_h[1], normal[0].get(queue), normal[1].get(queue))
        pt.gca().set_aspect("equal")
        pt.show()

    # {{{ establish BCs

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

    evt, (test_direct,) = pot_p2p(
            queue, test_targets, point_sources, [source_charges],
            out_host=False, **knl_kwargs)

    nodes = density_discr.nodes()

    evt, (src_pot,) = pot_p2p(
            queue, nodes, point_sources, [source_charges],
            **knl_kwargs)

    grad_p2p = P2P(cl_ctx,
            [AxisTargetDerivative(0, knl), AxisTargetDerivative(1, knl)],
            exclude_self=False, value_dtypes=dtype)
    evt, (src_grad0, src_grad1) = grad_p2p(
            queue, nodes, point_sources, [source_charges],
            **knl_kwargs)

    if bc_type == "dirichlet":
        bc = src_pot
    elif bc_type == "neumann":
        normal = bind(density_discr, sym.normal())(queue).as_vector(np.object)
        bc = (src_grad0*normal[0] + src_grad1*normal[1])

    # }}}

    # {{{ solve

    bound_op = bind(qbx, op_u)

    rhs = bind(density_discr, op.prepare_rhs(sym.var("bc")))(queue, bc=bc)

    from pytential.solve import gmres
    gmres_result = gmres(
            bound_op.scipy_op(queue, "u", k=k),
            rhs, tol=1e-14, progress=True,
            hard_failure=False)

    u = gmres_result.solution
    print("gmres state:", gmres_result.state)

    if 0:
        # {{{ build matrix for spectrum check

        from sumpy.tools import build_matrix
        mat = build_matrix(bound_op.scipy_op("u"))
        w, v = la.eig(mat)
        if 0:
            pt.imshow(np.log10(1e-20+np.abs(mat)))
            pt.colorbar()
            pt.show()

        #assert abs(s[-1]) < 1e-13, "h
        #assert abs(s[-2]) > 1e-7
        #from pudb import set_trace; set_trace()

        # }}}

    # }}}

    # {{{ error check

    from pytential.target import PointsTarget

    bound_tgt_op = bind((qbx, PointsTarget(test_targets)),
            op.representation(sym.var("u")))

    test_via_bdry = bound_tgt_op(queue, u=u, k=k)

    err = test_direct-test_via_bdry

    err = err.get()
    test_direct = test_direct.get()
    test_via_bdry = test_via_bdry.get()

    # {{{ remove effect of net source charge

    if k == 0 and bc_type == "neumann" and loc_sign == -1:
        # remove constant offset in interior Laplace Neumann error
        tgt_ones = np.ones_like(test_direct)
        tgt_ones = tgt_ones/la.norm(tgt_ones)
        err = err - np.vdot(tgt_ones, err)*tgt_ones

    # }}}

    rel_err_2 = la.norm(err)/la.norm(test_direct)
    rel_err_inf = la.norm(err, np.inf)/la.norm(test_direct, np.inf)

    # }}}

    print("rel_err_2: %g rel_err_inf: %g" % (rel_err_2, rel_err_inf))

    # {{{ test tangential derivative

    bound_t_deriv_op = bind(qbx,
            op.representation(
                sym.var("u"), map_potentials=sym.tangential_derivative,
                qbx_forced_limit=loc_sign))

    #print(bound_t_deriv_op.code)

    tang_deriv_from_src = bound_t_deriv_op(queue, u=u).as_scalar().get()

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

    tang_deriv_ref = (src_grad0 * tangent[0] + src_grad1 * tangent[1]).get()

    if 0:
        pt.plot(tang_deriv_ref.real)
        pt.plot(tang_deriv_from_src.real)
        pt.show()

    td_err = tang_deriv_from_src - tang_deriv_ref

    rel_td_err_inf = la.norm(td_err, np.inf)/la.norm(tang_deriv_ref, np.inf)

    print("rel_td_err_inf: %g" % rel_td_err_inf)

    # }}}

    # {{{ plotting

    if 0:
        fplot = FieldPlotter(np.zeros(2),
                extent=1.25*2*max(test_src_geo_radius, test_tgt_geo_radius),
                npoints=200)

        #pt.plot(u)
        #pt.show()

        evt, (fld_from_src,) = pot_p2p(
                queue, fplot.points, point_sources, [source_charges],
                **knl_kwargs)
        fld_from_bdry = bind(
                (qbx, PointsTarget(fplot.points)),
                op.representation(sym.var("u"))
                )(queue, u=u, k=k)
        fld_from_src = fld_from_src.get()
        fld_from_bdry = fld_from_bdry.get()

        nodes = density_discr.nodes().get(queue=queue)

        def prep():
            pt.plot(point_sources[0], point_sources[1], "o",
                    label="Monopole 'Point Charges'")
            pt.plot(test_targets[0], test_targets[1], "v",
                    label="Observation Points")
            pt.plot(nodes[0], nodes[1], "k-",
                    label=r"$\Gamma$")

        from matplotlib.cm import get_cmap
        cmap = get_cmap()
        cmap._init()
        if 0:
            cmap._lut[(cmap.N*99)//100:, -1] = 0  # make last percent transparent?

        prep()
        if 1:
            pt.subplot(131)
            pt.title("Field error (loc_sign=%s)" % loc_sign)
            log_err = np.log10(1e-20+np.abs(fld_from_src-fld_from_bdry))
            log_err = np.minimum(-3, log_err)
            fplot.show_scalar_in_matplotlib(log_err, cmap=cmap)

            #from matplotlib.colors import Normalize
            #im.set_norm(Normalize(vmin=-6, vmax=1))

            cb = pt.colorbar(shrink=0.9)
            cb.set_label(r"$\log_{10}(\mathdefault{Error})$")

        if 1:
            pt.subplot(132)
            prep()
            pt.title("Source Field")
            fplot.show_scalar_in_matplotlib(
                    fld_from_src.real, max_val=3)

            pt.colorbar(shrink=0.9)
        if 1:
            pt.subplot(133)
            prep()
            pt.title("Solved Field")
            fplot.show_scalar_in_matplotlib(
                    fld_from_bdry.real, max_val=3)

            pt.colorbar(shrink=0.9)

        # total field
        #fplot.show_scalar_in_matplotlib(
        #fld_from_src.real+fld_from_bdry.real, max_val=0.1)

        #pt.colorbar()

        pt.legend(loc="best", prop=dict(size=15))
        from matplotlib.ticker import NullFormatter
        pt.gca().xaxis.set_major_formatter(NullFormatter())
        pt.gca().yaxis.set_major_formatter(NullFormatter())

        pt.gca().set_aspect("equal")

        if 0:
            border_factor_top = 0.9
            border_factor = 0.3

            xl, xh = pt.xlim()
            xhsize = 0.5*(xh-xl)
            pt.xlim(xl-border_factor*xhsize, xh+border_factor*xhsize)

            yl, yh = pt.ylim()
            yhsize = 0.5*(yh-yl)
            pt.ylim(yl-border_factor_top*yhsize, yh+border_factor*yhsize)

        #pt.savefig("helmholtz.pdf", dpi=600)
        pt.show()

        # }}}

    class Result(Record):
        pass

    return Result(
            rel_err_2=rel_err_2,
            rel_err_inf=rel_err_inf,
            rel_td_err_inf=rel_td_err_inf,
            gmres_result=gmres_result)
Exemple #36
0
def test_perf_data_gathering(ctx_getter, n_arms=5):
    cl_ctx = ctx_getter()
    queue = cl.CommandQueue(cl_ctx)

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

    target_order = 8

    starfish_func = NArmedStarfish(n_arms, 0.8)
    mesh = make_curve_mesh(
            starfish_func,
            np.linspace(0, 1, n_arms * 30),
            target_order)

    sigma_sym = sym.var("sigma")

    # The kernel doesn't really matter here
    from sumpy.kernel import LaplaceKernel
    k_sym = LaplaceKernel(mesh.ambient_dim)

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

    from meshmode.discretization import Discretization
    from meshmode.discretization.poly_element import (
            InterpolatoryQuadratureSimplexGroupFactory)
    pre_density_discr = Discretization(
            queue.context, mesh,
            InterpolatoryQuadratureSimplexGroupFactory(target_order))

    results = []

    def inspect_geo_data(insn, bound_expr, geo_data):
        from pytential.qbx.fmm import assemble_performance_data
        perf_data = assemble_performance_data(geo_data, uses_pde_expansions=True)
        results.append(perf_data)

        return False  # no need to do the actual FMM

    from pytential.qbx import QBXLayerPotentialSource
    lpot_source = QBXLayerPotentialSource(
            pre_density_discr, 4*target_order,
            # qbx order and fmm order don't really matter
            10, fmm_order=10,
            _expansions_in_tree_have_extent=True,
            _expansion_stick_out_factor=0.5,
            geometry_data_inspector=inspect_geo_data,
            target_association_tolerance=1e-10,
            )

    lpot_source, _ = lpot_source.with_refinement()

    density_discr = lpot_source.density_discr

    if 0:
        from meshmode.discretization.visualization import draw_curve
        draw_curve(density_discr)
        import matplotlib.pyplot as plt
        plt.show()

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

    bind(lpot_source, sym_op)(queue, sigma=sigma)
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=np.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),
                ]
            )
Exemple #38
0
def test_off_surface_eval(ctx_getter, use_fmm, do_plot=False):
    logging.basicConfig(level=logging.INFO)

    cl_ctx = ctx_getter()
    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
def main():
    import logging
    logging.basicConfig(level=logging.WARNING)  # INFO for more progress info

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

    from meshmode.mesh.generation import generate_torus

    rout = 10
    rin = 1
    if 1:
        base_mesh = generate_torus(
                rout, rin, 40, 4,
                mesh_order)

        from meshmode.mesh.processing import affine_map, merge_disjoint_meshes
        # nx = 1
        # ny = 1
        nz = 1
        dz = 0
        meshes = [
                affine_map(
                    base_mesh,
                    A=np.diag([1, 1, 1]),
                    b=np.array([0, 0, iz*dz]))
                for iz in range(nz)]

        mesh = merge_disjoint_meshes(meshes, single_group=True)

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

    pre_density_discr = Discretization(
            cl_ctx, 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
            ).with_refinement()
    density_discr = qbx.density_discr

    # {{{ describe bvp

    from sumpy.kernel import LaplaceKernel
    kernel = LaplaceKernel(3)

    cse = sym.cse

    sigma_sym = sym.var("sigma")
    #sqrt_w = sym.sqrt_jac_q_weight(3)
    sqrt_w = 1
    inv_sqrt_w_sigma = cse(sigma_sym/sqrt_w)

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

    bdry_op_sym = (loc_sign*0.5*sigma_sym
            + sqrt_w*(
                sym.S(kernel, inv_sqrt_w_sigma)
                + sym.D(kernel, inv_sqrt_w_sigma)
                ))

    # }}}

    bound_op = bind(qbx, bdry_op_sym)

    # {{{ fix rhs and solve

    nodes = density_discr.nodes().with_queue(queue)
    source = np.array([rout, 0, 0])

    def u_incoming_func(x):
        #        return 1/cl.clmath.sqrt( (x[0] - source[0])**2
        #                                +(x[1] - source[1])**2
        #                                +(x[2] - source[2])**2 )
        return 1.0/la.norm(x.get()-source[:, None], axis=0)

    bc = cl.array.to_device(queue, u_incoming_func(nodes))

    bvp_rhs = bind(qbx, sqrt_w*sym.var("bc"))(queue, bc=bc)

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

    sigma = bind(qbx, sym.var("sigma")/sqrt_w)(queue, sigma=gmres_result.solution)

    # }}}

    from meshmode.discretization.visualization import make_visualizer
    bdry_vis = make_visualizer(queue, density_discr, 20)
    bdry_vis.write_vtk_file("laplace.vtu", [
        ("sigma", sigma),
        ])

    # {{{ postprocess/visualize

    repr_kwargs = dict(qbx_forced_limit=None)
    representation_sym = (
            sym.S(kernel, inv_sqrt_w_sigma, **repr_kwargs)
            + sym.D(kernel, inv_sqrt_w_sigma, **repr_kwargs))

    from sumpy.visualization import FieldPlotter
    fplot = FieldPlotter(np.zeros(3), extent=20, npoints=50)

    targets = cl.array.to_device(queue, fplot.points)

    qbx_stick_out = qbx.copy(target_stick_out_factor=0.2)

    try:
        fld_in_vol = bind(
                (qbx_stick_out, PointsTarget(targets)),
                representation_sym)(queue, sigma=sigma).get()
    except QBXTargetAssociationFailedException as e:
        fplot.write_vtk_file(
                "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(
            "potential-laplace-3d.vts",
            [
                ("potential", fld_in_vol),
                ]
            )
Exemple #40
0
def main():
    import logging
    logging.basicConfig(level=logging.INFO)

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

    mesh = generate_gmsh(
            FileSource("circle.step"), 2, order=mesh_order,
            force_ambient_dim=2,
            other_options=["-string", "Mesh.CharacteristicLengthMax = %g;" % h]
            )

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

    # {{{ discretizations and connections

    vol_discr = Discretization(ctx, mesh,
            InterpolatoryQuadratureSimplexGroupFactory(vol_quad_order))
    ovsmp_vol_discr = Discretization(ctx, mesh,
            InterpolatoryQuadratureSimplexGroupFactory(vol_ovsmp_quad_order))

    from meshmode.discretization.connection import (
            make_boundary_restriction, make_same_mesh_connection)
    bdry_mesh, bdry_discr, bdry_connection = make_boundary_restriction(
            queue, vol_discr,
            InterpolatoryQuadratureSimplexGroupFactory(bdry_quad_order))

    vol_to_ovsmp_vol = make_same_mesh_connection(
            queue, ovsmp_vol_discr, vol_discr)

    # }}}

    # {{{ visualizers

    vol_vis = make_visualizer(queue, vol_discr, 20)
    bdry_vis = make_visualizer(queue, bdry_discr, 20)

    # }}}

    vol_x = vol_discr.nodes().with_queue(queue)
    ovsmp_vol_x = ovsmp_vol_discr.nodes().with_queue(queue)

    rhs = rhs_func(vol_x[0], vol_x[1])
    poisson_true_sol = sol_func(vol_x[0], vol_x[1])

    vol_vis.write_vtk_file("volume.vtu", [("f", rhs)])

    bdry_normals = bind(bdry_discr, p.normal())(queue).as_vector(dtype=object)
    bdry_vis.write_vtk_file("boundary.vtu", [
        ("normals", bdry_normals)
        ])

    bdry_nodes = bdry_discr.nodes().with_queue(queue)
    bdry_f = rhs_func(bdry_nodes[0], bdry_nodes[1])
    bdry_f_2 = bdry_connection(queue, rhs)

    bdry_vis.write_vtk_file("y.vtu", [("f", bdry_f_2)])

    if 0:
        vol_vis.show_scalar_in_mayavi(rhs, do_show=False)
        bdry_vis.show_scalar_in_mayavi(bdry_f - bdry_f_2, line_width=10,
                do_show=False)

        import mayavi.mlab as mlab
        mlab.colorbar()
        mlab.show()

    # {{{ compute volume potential

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

    def get_kernel():
        from sumpy.symbolic import pymbolic_real_norm_2
        from pymbolic.primitives import (make_sym_vector, Variable as var)

        r = pymbolic_real_norm_2(make_sym_vector("d", 3))
        expr = var("log")(r)
        scaling = 1/(2*var("pi"))

        from sumpy.kernel import ExpressionKernel
        return ExpressionKernel(
                dim=3,
                expression=expr,
                scaling=scaling,
                is_complex_valued=False)

    laplace_2d_in_3d_kernel = get_kernel()

    layer_pot = LayerPotential(ctx, [
        LineTaylorLocalExpansion(laplace_2d_in_3d_kernel,
            order=vol_qbx_order)])

    targets = cl.array.zeros(queue, (3,) + vol_x.shape[1:], vol_x.dtype)
    targets[:2] = vol_x

    center_dist = np.min(
            cl.clmath.sqrt(
                bind(vol_discr, p.area_element())(queue)).get())

    centers = make_obj_array([ci.copy().reshape(vol_discr.nnodes) for ci in targets])
    centers[2][:] = center_dist

    sources = cl.array.zeros(queue, (3,) + ovsmp_vol_x.shape[1:], ovsmp_vol_x.dtype)
    sources[:2] = ovsmp_vol_x

    ovsmp_rhs = vol_to_ovsmp_vol(queue, rhs)
    ovsmp_vol_weights = bind(ovsmp_vol_discr, p.area_element() * p.QWeight())(queue)

    evt, (vol_pot,) = layer_pot(
            queue,
            targets=targets.reshape(3, vol_discr.nnodes),
            centers=centers,
            sources=sources.reshape(3, ovsmp_vol_discr.nnodes),
            strengths=(
                (ovsmp_vol_weights*ovsmp_rhs).reshape(ovsmp_vol_discr.nnodes),)
            )

    vol_pot_bdry = bdry_connection(queue, vol_pot)

    # }}}

    # {{{ solve bvp

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

    sym_sigma = sym.var("sigma")
    op_sigma = op.operator(sym_sigma)

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

    bound_op = bind(qbx, op_sigma)

    poisson_bc = poisson_bc_func(bdry_nodes[0], bdry_nodes[1])
    bvp_bc = poisson_bc - vol_pot_bdry
    bdry_f = rhs_func(bdry_nodes[0], bdry_nodes[1])

    bvp_rhs = bind(bdry_discr, op.prepare_rhs(sym.var("bc")))(queue, bc=bvp_bc)

    from pytential.solve import gmres
    gmres_result = gmres(
            bound_op.scipy_op(queue, "sigma"),
            bvp_rhs, tol=1e-14, progress=True,
            hard_failure=False)

    sigma = gmres_result.solution
    print("gmres state:", gmres_result.state)

    # }}}

    bvp_sol = bind(
            (qbx, vol_discr),
            op.representation(sym_sigma))(queue, sigma=sigma)

    poisson_sol = bvp_sol + vol_pot
    poisson_err = poisson_sol-poisson_true_sol

    rel_err = (
            norm(vol_discr, queue, poisson_err)
            /
            norm(vol_discr, queue, poisson_true_sol))
    bdry_vis.write_vtk_file("poisson-boundary.vtu", [
        ("vol_pot_bdry", vol_pot_bdry),
        ("sigma", sigma),
        ])

    vol_vis.write_vtk_file("poisson-volume.vtu", [
        ("bvp_sol", bvp_sol),
        ("poisson_sol", poisson_sol),
        ("poisson_true_sol", poisson_true_sol),
        ("poisson_err", poisson_err),
        ("vol_pot", vol_pot),
        ("rhs", rhs),
        ])

    print("h = %s" % h)
    print("mesh_order = %s" % mesh_order)
    print("vol_quad_order = %s" % vol_quad_order)
    print("vol_ovsmp_quad_order = %s" % vol_ovsmp_quad_order)
    print("bdry_quad_order = %s" % bdry_quad_order)
    print("bdry_ovsmp_quad_order = %s" % bdry_ovsmp_quad_order)
    print("qbx_order = %s" % qbx_order)
    print("vol_qbx_order = %s" % vol_qbx_order)
    print("fmm_order = %s" % fmm_order)
    print()
    print("rel err: %g" % rel_err)
Exemple #41
0
def test_off_surface_eval_vs_direct(ctx_getter,  do_plot=False):
    logging.basicConfig(level=logging.INFO)

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

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

    nelements = 300
    target_order = 8
    qbx_order = 3

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

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

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

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

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

    from pytential.qbx import QBXTargetAssociationFailedException
    try:
        direct_density_discr = direct_qbx.density_discr
        direct_sigma = direct_density_discr.zeros(queue) + 1
        direct_fld_in_vol = bind((direct_qbx, ptarget), op)(
                queue, sigma=direct_sigma)

    except QBXTargetAssociationFailedException as e:
        fplot.show_scalar_in_matplotlib(e.failed_target_flags.get(queue))
        import matplotlib.pyplot as pt
        pt.show()
        raise

    fmm_density_discr = fmm_qbx.density_discr
    fmm_sigma = fmm_density_discr.zeros(queue) + 1
    fmm_fld_in_vol = bind((fmm_qbx, ptarget), op)(queue, sigma=fmm_sigma)

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

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

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

    assert linf_err < 1e-3
def run_int_eq_test(cl_ctx, queue, case, resolution, visualize):
    mesh = case.get_mesh(resolution, case.target_order)
    print("%d elements" % mesh.nelements)

    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(case.target_order))

    source_order = 4*case.target_order

    refiner_extra_kwargs = {}

    qbx_lpot_kwargs = {}
    if case.fmm_backend is None:
        qbx_lpot_kwargs["fmm_order"] = False
    else:
        if hasattr(case, "fmm_tol"):
            from sumpy.expansion.level_to_order import SimpleExpansionOrderFinder
            qbx_lpot_kwargs["fmm_level_to_order"] = SimpleExpansionOrderFinder(
                    case.fmm_tol)

        elif hasattr(case, "fmm_order"):
            qbx_lpot_kwargs["fmm_order"] = case.fmm_order
        else:
            qbx_lpot_kwargs["fmm_order"] = case.qbx_order + 5

    qbx = QBXLayerPotentialSource(
            pre_density_discr,
            fine_order=source_order,
            qbx_order=case.qbx_order,

            _box_extent_norm=getattr(case, "box_extent_norm", None),
            _from_sep_smaller_crit=getattr(case, "from_sep_smaller_crit", None),
            _from_sep_smaller_min_nsources_cumul=30,
            fmm_backend=case.fmm_backend, **qbx_lpot_kwargs)

    if case.use_refinement:
        if case.k != 0 and getattr(case, "refine_on_helmholtz_k", True):
            refiner_extra_kwargs["kernel_length_scale"] = 5/case.k

        if hasattr(case, "scaled_max_curvature_threshold"):
            refiner_extra_kwargs["_scaled_max_curvature_threshold"] = \
                    case.scaled_max_curvature_threshold

        if hasattr(case, "expansion_disturbance_tolerance"):
            refiner_extra_kwargs["_expansion_disturbance_tolerance"] = \
                    case.expansion_disturbance_tolerance

        if hasattr(case, "refinement_maxiter"):
            refiner_extra_kwargs["maxiter"] = case.refinement_maxiter

        #refiner_extra_kwargs["visualize"] = True

        print("%d elements before refinement" % pre_density_discr.mesh.nelements)
        qbx, _ = qbx.with_refinement(**refiner_extra_kwargs)
        print("%d stage-1 elements after refinement"
                % qbx.density_discr.mesh.nelements)
        print("%d stage-2 elements after refinement"
                % qbx.stage2_density_discr.mesh.nelements)
        print("quad stage-2 elements have %d nodes"
                % qbx.quad_stage2_density_discr.groups[0].nunit_nodes)

    density_discr = qbx.density_discr

    if hasattr(case, "visualize_geometry") and case.visualize_geometry:
        bdry_normals = bind(
                density_discr, sym.normal(mesh.ambient_dim)
                )(queue).as_vector(dtype=object)

        bdry_vis = make_visualizer(queue, density_discr, case.target_order)
        bdry_vis.write_vtk_file("geometry.vtu", [
            ("normals", bdry_normals)
            ])

    # {{{ plot geometry

    if 0:
        if mesh.ambient_dim == 2:
            # show geometry, centers, normals
            nodes_h = density_discr.nodes().get(queue=queue)
            pt.plot(nodes_h[0], nodes_h[1], "x-")
            normal = bind(density_discr, sym.normal(2))(queue).as_vector(np.object)
            pt.quiver(nodes_h[0], nodes_h[1],
                    normal[0].get(queue), normal[1].get(queue))
            pt.gca().set_aspect("equal")
            pt.show()

        elif mesh.ambient_dim == 3:
            bdry_vis = make_visualizer(queue, density_discr, case.target_order+3)

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

            bdry_vis.write_vtk_file("pre-solve-source-%s.vtu" % resolution, [
                ("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":
        op = DirichletOperator(knl, loc_sign, use_l2_weighting=True,
                kernel_arguments=knl_kwargs)
    elif case.bc_type == "neumann":
        op = NeumannOperator(knl, loc_sign, use_l2_weighting=True,
                 use_improved_operator=False, kernel_arguments=knl_kwargs)
    else:
        assert False

    op_u = op.operator(sym.var("u"))

    # }}}

    # {{{ set up test data

    if case.prob_side == -1:
        test_src_geo_radius = case.outer_radius
        test_tgt_geo_radius = case.inner_radius
    elif case.prob_side == +1:
        test_src_geo_radius = case.inner_radius
        test_tgt_geo_radius = case.outer_radius
    elif case.prob_side == "scat":
        test_src_geo_radius = case.outer_radius
        test_tgt_geo_radius = case.outer_radius
    else:
        raise ValueError("unknown problem_side")

    point_sources = make_circular_point_group(
            mesh.ambient_dim, 10, test_src_geo_radius,
            func=lambda x: x**1.5)
    test_targets = make_circular_point_group(
            mesh.ambient_dim, 20, test_tgt_geo_radius)

    np.random.seed(22)
    source_charges = np.random.randn(point_sources.shape[1])
    source_charges[-1] = -np.sum(source_charges[:-1])
    source_charges = source_charges.astype(dtype)
    assert np.sum(source_charges) < 1e-15

    source_charges_dev = cl.array.to_device(queue, source_charges)

    # }}}

    # {{{ establish BCs

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

    point_source = PointPotentialSource(cl_ctx, point_sources)

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

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

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

    elif case.bc_type == "neumann":
        bc = bind(
                (point_source, density_discr),
                sym.normal_derivative(
                    qbx.ambient_dim, pot_src, where=sym.DEFAULT_TARGET)
                )(queue, charges=source_charges_dev, **concrete_knl_kwargs)

    # }}}

    # {{{ solve

    bound_op = bind(qbx, op_u)

    rhs = bind(density_discr, op.prepare_rhs(sym.var("bc")))(queue, bc=bc)

    try:
        from pytential.solve import gmres
        gmres_result = gmres(
                bound_op.scipy_op(queue, "u", dtype, **concrete_knl_kwargs),
                rhs,
                tol=case.gmres_tol,
                progress=True,
                hard_failure=True,
                stall_iterations=50, no_progress_factor=1.05)
    except QBXTargetAssociationFailedException as e:
        bdry_vis = make_visualizer(queue, density_discr, case.target_order+3)

        bdry_vis.write_vtk_file("failed-targets-%s.vtu" % resolution, [
            ("failed_targets", e.failed_target_flags),
            ])
        raise

    print("gmres state:", gmres_result.state)
    weighted_u = gmres_result.solution

    # }}}

    # {{{ build matrix for spectrum check

    if 0:
        from sumpy.tools import build_matrix
        mat = build_matrix(
                bound_op.scipy_op(
                    queue, arg_name="u", dtype=dtype, k=case.k))
        w, v = la.eig(mat)
        if 0:
            pt.imshow(np.log10(1e-20+np.abs(mat)))
            pt.colorbar()
            pt.show()

        #assert abs(s[-1]) < 1e-13, "h
        #assert abs(s[-2]) > 1e-7
        #from pudb import set_trace; set_trace()

    # }}}

    if case.prob_side != "scat":
        # {{{ error check

        points_target = PointsTarget(test_targets)
        bound_tgt_op = bind((qbx, points_target),
                op.representation(sym.var("u")))

        test_via_bdry = bound_tgt_op(queue, u=weighted_u, k=case.k)

        err = test_via_bdry - test_direct

        err = err.get()
        test_direct = test_direct.get()
        test_via_bdry = test_via_bdry.get()

        # {{{ remove effect of net source charge

        if case.k == 0 and case.bc_type == "neumann" and loc_sign == -1:

            # remove constant offset in interior Laplace Neumann error
            tgt_ones = np.ones_like(test_direct)
            tgt_ones = tgt_ones/la.norm(tgt_ones)
            err = err - np.vdot(tgt_ones, err)*tgt_ones

        # }}}

        rel_err_2 = la.norm(err)/la.norm(test_direct)
        rel_err_inf = la.norm(err, np.inf)/la.norm(test_direct, np.inf)

        # }}}

        print("rel_err_2: %g rel_err_inf: %g" % (rel_err_2, rel_err_inf))

    else:
        rel_err_2 = None
        rel_err_inf = None

    # {{{ test gradient

    if case.check_gradient and case.prob_side != "scat":
        bound_grad_op = bind((qbx, points_target),
                op.representation(
                    sym.var("u"),
                    map_potentials=lambda pot: sym.grad(mesh.ambient_dim, pot),
                    qbx_forced_limit=None))

        #print(bound_t_deriv_op.code)

        grad_from_src = bound_grad_op(
                queue, u=weighted_u, **concrete_knl_kwargs)

        grad_ref = (bind(
                (point_source, points_target),
                sym.grad(mesh.ambient_dim, pot_src)
                )(queue, charges=source_charges_dev, **concrete_knl_kwargs)
                )

        grad_err = (grad_from_src - grad_ref)

        rel_grad_err_inf = (
                la.norm(grad_err[0].get(), np.inf)
                / la.norm(grad_ref[0].get(), np.inf))

        print("rel_grad_err_inf: %g" % rel_grad_err_inf)

    # }}}

    # {{{ test tangential derivative

    if case.check_tangential_deriv and case.prob_side != "scat":
        bound_t_deriv_op = bind(qbx,
                op.representation(
                    sym.var("u"),
                    map_potentials=lambda pot: sym.tangential_derivative(2, pot),
                    qbx_forced_limit=loc_sign))

        #print(bound_t_deriv_op.code)

        tang_deriv_from_src = bound_t_deriv_op(
                queue, u=weighted_u, **concrete_knl_kwargs).as_scalar().get()

        tang_deriv_ref = (bind(
                (point_source, density_discr),
                sym.tangential_derivative(2, pot_src)
                )(queue, charges=source_charges_dev, **concrete_knl_kwargs)
                .as_scalar().get())

        if 0:
            pt.plot(tang_deriv_ref.real)
            pt.plot(tang_deriv_from_src.real)
            pt.show()

        td_err = (tang_deriv_from_src - tang_deriv_ref)

        rel_td_err_inf = la.norm(td_err, np.inf)/la.norm(tang_deriv_ref, np.inf)

        print("rel_td_err_inf: %g" % rel_td_err_inf)

    else:
        rel_td_err_inf = None

    # }}}

    # {{{ any-D file plotting

    if visualize:
        bdry_vis = make_visualizer(queue, density_discr, case.target_order+3)

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

        sym_sqrt_j = sym.sqrt_jac_q_weight(density_discr.ambient_dim)
        u = bind(density_discr, sym.var("u")/sym_sqrt_j)(queue, u=weighted_u)

        bdry_vis.write_vtk_file("source-%s.vtu" % resolution, [
            ("u", u),
            ("bc", bc),
            #("bdry_normals", bdry_normals),
            ])

        from sumpy.visualization import make_field_plotter_from_bbox  # noqa
        from meshmode.mesh.processing import find_bounding_box

        vis_grid_spacing = (0.1, 0.1, 0.1)[:qbx.ambient_dim]
        if hasattr(case, "vis_grid_spacing"):
            vis_grid_spacing = case.vis_grid_spacing
        vis_extend_factor = 0.2
        if hasattr(case, "vis_extend_factor"):
            vis_grid_spacing = case.vis_grid_spacing

        fplot = make_field_plotter_from_bbox(
                find_bounding_box(mesh),
                h=vis_grid_spacing,
                extend_factor=vis_extend_factor)

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

        try:
            solved_pot = bind(
                    (qbx_tgt_tol, PointsTarget(fplot.points)),
                    op.representation(sym.var("u"))
                    )(queue, u=weighted_u, k=case.k)
        except QBXTargetAssociationFailedException as e:
            fplot.write_vtk_file(
                    "failed-targets.vts",
                    [
                        ("failed_targets", e.failed_target_flags.get(queue))
                        ])
            raise

        from sumpy.kernel import LaplaceKernel
        ones_density = density_discr.zeros(queue)
        ones_density.fill(1)
        indicator = bind(
                (qbx_tgt_tol, PointsTarget(fplot.points)),
                -sym.D(LaplaceKernel(density_discr.ambient_dim),
                    sym.var("sigma"),
                    qbx_forced_limit=None))(
                queue, sigma=ones_density).get()

        solved_pot = solved_pot.get()

        true_pot = bind((point_source, PointsTarget(fplot.points)), pot_src)(
                queue, charges=source_charges_dev, **concrete_knl_kwargs).get()

        #fplot.show_scalar_in_mayavi(solved_pot.real, max_val=5)
        if case.prob_side == "scat":
            fplot.write_vtk_file(
                    "potential-%s.vts" % resolution,
                    [
                        ("pot_scattered", solved_pot),
                        ("pot_incoming", -true_pot),
                        ("indicator", indicator),
                        ]
                    )
        else:
            fplot.write_vtk_file(
                    "potential-%s.vts" % resolution,
                    [
                        ("solved_pot", solved_pot),
                        ("true_pot", true_pot),
                        ("indicator", indicator),
                        ]
                    )

    # }}}

    class Result(Record):
        pass

    return Result(
            h_max=qbx.h_max,
            rel_err_2=rel_err_2,
            rel_err_inf=rel_err_inf,
            rel_td_err_inf=rel_td_err_inf,
            gmres_result=gmres_result)
Exemple #43
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=np.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),
                ]
            )
def main():
    import logging
    logging.basicConfig(level=logging.WARNING)  # INFO for more progress info

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

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

    if 0:
        mesh = make_curve_mesh(partial(ellipse, 1),
                               np.linspace(0, 1, nelements + 1), mesh_order)
    else:
        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 0:
            from meshmode.mesh.visualization import draw_curve
            draw_curve(mesh)
            import matplotlib.pyplot as plt
            plt.show()

    pre_density_discr = Discretization(
        cl_ctx, 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).with_refinement()
    density_discr = qbx.density_discr

    # {{{ describe bvp

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

    cse = sym.cse

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

    # Brakhage-Werner parameter
    alpha = 1j

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

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

    # }}}

    bound_op = bind(qbx, bdry_op_sym)

    # {{{ fix rhs and solve

    nodes = density_discr.nodes().with_queue(queue)
    k_vec = np.array([2, 1])
    k_vec = k * k_vec / la.norm(k_vec, 2)

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

    bc = -u_incoming_func(nodes)

    bvp_rhs = bind(qbx, sqrt_w * sym.var("bc"))(queue, bc=bc)

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

    # }}}

    # {{{ postprocess/visualize

    sigma = gmres_result.solution

    repr_kwargs = dict(k=sym.var("k"), qbx_forced_limit=None)
    representation_sym = (
        alpha * sym.S(kernel, inv_sqrt_w_sigma, **repr_kwargs) -
        sym.D(kernel, inv_sqrt_w_sigma, **repr_kwargs))

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

    targets = cl.array.to_device(queue, fplot.points)

    u_incoming = u_incoming_func(targets)

    qbx_stick_out = qbx.copy(target_association_tolerance=0.05)

    ones_density = density_discr.zeros(queue)
    ones_density.fill(1)
    indicator = bind((qbx_stick_out, PointsTarget(targets)),
                     sym.D(LaplaceKernel(2),
                           sym.var("sigma"),
                           qbx_forced_limit=None))(queue,
                                                   sigma=ones_density).get()

    try:
        fld_in_vol = bind((qbx_stick_out, PointsTarget(targets)),
                          representation_sym)(queue, sigma=sigma, k=k).get()
    except QBXTargetAssociationFailedException as e:
        fplot.write_vtk_file("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("potential-helm.vts", [
        ("potential", fld_in_vol),
        ("indicator", indicator),
        ("u_incoming", u_incoming.get()),
    ])
Exemple #45
0
def test_3d_jump_relations(ctx_factory, relation, visualize=False):
    # logging.basicConfig(level=logging.INFO)

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

    if relation == "div_s":
        target_order = 3
    else:
        target_order = 4

    qbx_order = target_order

    from pytools.convergence import EOCRecorder
    eoc_rec = EOCRecorder()

    for nel_factor in [6, 10, 14]:
        from meshmode.mesh.generation import generate_torus
        mesh = generate_torus(
                5, 2, order=target_order,
                n_outer=2*nel_factor, n_inner=nel_factor)

        from meshmode.discretization import Discretization
        from meshmode.discretization.poly_element import \
            InterpolatoryQuadratureSimplexGroupFactory
        pre_discr = Discretization(
                cl_ctx, mesh,
                InterpolatoryQuadratureSimplexGroupFactory(3))

        from pytential.qbx import QBXLayerPotentialSource
        qbx, _ = QBXLayerPotentialSource(
                pre_discr, fine_order=4*target_order,
                qbx_order=qbx_order,
                fmm_order=qbx_order + 5,
                fmm_backend="fmmlib"
                ).with_refinement()

        from sumpy.kernel import LaplaceKernel
        knl = LaplaceKernel(3)

        def nxcurlS(qbx_forced_limit):

            return sym.n_cross(sym.curl(sym.S(
                knl,
                sym.cse(sym.tangential_to_xyz(density_sym), "jxyz"),
                qbx_forced_limit=qbx_forced_limit)))

        x, y, z = qbx.density_discr.nodes().with_queue(queue)
        m = cl.clmath

        if relation == "nxcurls":
            density_sym = sym.make_sym_vector("density", 2)

            jump_identity_sym = (
                    nxcurlS(+1)
                    - (nxcurlS("avg") + 0.5*sym.tangential_to_xyz(density_sym)))

            # The tangential coordinate system is element-local, so we can't just
            # conjure up some globally smooth functions, interpret their values
            # in the tangential coordinate system, and be done. Instead, generate
            # an XYZ function and project it.
            density = bind(
                    qbx,
                    sym.xyz_to_tangential(sym.make_sym_vector("jxyz", 3)))(
                            queue,
                            jxyz=sym.make_obj_array([
                                m.cos(0.5*x) * m.cos(0.5*y) * m.cos(0.5*z),
                                m.sin(0.5*x) * m.cos(0.5*y) * m.sin(0.5*z),
                                m.sin(0.5*x) * m.cos(0.5*y) * m.cos(0.5*z),
                                ]))

        elif relation == "sp":

            density = m.cos(2*x) * m.cos(2*y) * m.cos(z)
            density_sym = sym.var("density")

            jump_identity_sym = (
                    sym.Sp(knl, density_sym, qbx_forced_limit=+1)
                    - (sym.Sp(knl, density_sym, qbx_forced_limit="avg")
                        - 0.5*density_sym))

        elif relation == "div_s":

            density = m.cos(2*x) * m.cos(2*y) * m.cos(z)
            density_sym = sym.var("density")

            jump_identity_sym = (
                    sym.div(sym.S(knl, sym.normal(3).as_vector()*density_sym,
                        qbx_forced_limit="avg"))
                    + sym.D(knl, density_sym, qbx_forced_limit="avg"))

        else:
            raise ValueError("unexpected value of 'relation': %s" % relation)

        bound_jump_identity = bind(qbx, jump_identity_sym)
        jump_identity = bound_jump_identity(queue, density=density)

        err = (
                norm(qbx, queue, jump_identity, np.inf)
                / norm(qbx, queue, density, np.inf))
        print("ERROR", qbx.h_max, err)

        eoc_rec.add_data_point(qbx.h_max, err)

        # {{{ visualization

        if visualize and relation == "nxcurls":
            nxcurlS_ext = bind(qbx, nxcurlS(+1))(queue, density=density)
            nxcurlS_avg = bind(qbx, nxcurlS("avg"))(queue, density=density)
            jtxyz = bind(qbx, sym.tangential_to_xyz(density_sym))(
                    queue, density=density)

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

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

            bdry_vis.write_vtk_file("source-%s.vtu" % nel_factor, [
                ("jt", jtxyz),
                ("nxcurlS_ext", nxcurlS_ext),
                ("nxcurlS_avg", nxcurlS_avg),
                ("bdry_normals", bdry_normals),
                ])

        if visualize and relation == "sp":
            sp_ext = bind(qbx, sym.Sp(knl, density_sym, qbx_forced_limit=+1))(
                    queue, density=density)
            sp_avg = bind(qbx, sym.Sp(knl, density_sym, qbx_forced_limit="avg"))(
                    queue, density=density)

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

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

            bdry_vis.write_vtk_file("source-%s.vtu" % nel_factor, [
                ("density", density),
                ("sp_ext", sp_ext),
                ("sp_avg", sp_avg),
                ("bdry_normals", bdry_normals),
                ])

        # }}}

    print(eoc_rec)

    assert eoc_rec.order_estimate() >= qbx_order - 1.5
def find_mode():
    import warnings
    warnings.simplefilter("error", np.ComplexWarning)

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

    k0 = 1.4447
    k1 = k0 * 1.02
    beta_sym = sym.var("beta")

    from pytential.symbolic.pde.scalar import (  # noqa
        DielectricSRep2DBoundaryOperator as SRep,
        DielectricSDRep2DBoundaryOperator as SDRep)
    pde_op = SDRep(mode="te",
                   k_vacuum=1,
                   interfaces=((0, 1, sym.DEFAULT_SOURCE), ),
                   domain_k_exprs=(k0, k1),
                   beta=beta_sym,
                   use_l2_weighting=False)

    u_sym = pde_op.make_unknown("u")
    op = pde_op.operator(u_sym)

    # {{{ discretization setup

    from meshmode.mesh.generation import ellipse, make_curve_mesh
    curve_f = partial(ellipse, 1)

    target_order = 7
    qbx_order = 4
    nelements = 30

    from meshmode.mesh.processing import affine_map
    mesh = make_curve_mesh(curve_f, np.linspace(0, 1, nelements + 1),
                           target_order)
    lambda_ = 1.55
    circle_radius = 3.4 * 2 * np.pi / lambda_
    mesh = affine_map(mesh, A=circle_radius * np.eye(2))

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

    qbx = QBXLayerPotentialSource(
        density_discr,
        4 * target_order,
        qbx_order,
        # Don't use FMM for now
        fmm_order=False)

    # }}}

    x_vec = np.random.randn(len(u_sym) * density_discr.nnodes)
    y_vec = np.random.randn(len(u_sym) * density_discr.nnodes)

    def muller_solve_func(beta):
        from pytential.symbolic.execution import build_matrix
        mat = build_matrix(queue, qbx, op, u_sym, context={"beta": beta}).get()

        return 1 / x_vec.dot(la.solve(mat, y_vec))

    starting_guesses = (1 + 0j) * (k0 + (k1 - k0) * np.random.rand(3))

    from pytential.muller import muller
    beta, niter = muller(muller_solve_func, z_start=starting_guesses)
    print("beta")
Exemple #47
0
def main():
    # cl.array.to_device(queue, numpy_array)
    from meshmode.mesh.io import generate_gmsh, FileSource
    mesh = generate_gmsh(
            FileSource("ellipsoid.step"), 2, order=2,
            other_options=["-string", "Mesh.CharacteristicLengthMax = %g;" % h])

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

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

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

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

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

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

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

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

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

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

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

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

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

    if 1:

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

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

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

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

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

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

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

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

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

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

            hvec = np.cross(strength,fvec)

            return hvec

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

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

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

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

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

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

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

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

        bound_op = bind(qbx, sym_operator)

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

            sigma = gmres_result.solution

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

    # }}}

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

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

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

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

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

        rho_sym = sym.var("rho")

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

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

        #fplot.show_scalar_in_mayavi(fld_in_vol.real, max_val=5)
        fplot.write_vtk_file(
                "potential.vts",
                [
                    ("potential", fld_in_vol[0]),
                    ("grad", fld_in_vol[1:]),
                    ]
                )
Exemple #48
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),
    ])
mesh = make_curve_mesh(starfish,
        np.linspace(0, 1, nelements+1),
        target_order)

from pytential.discretization.qbx import make_upsampling_qbx_discr

discr = make_upsampling_qbx_discr(
        cl_ctx, mesh, target_order, qbx_order)

nodes = discr.nodes().with_queue(queue)

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

from pytential import bind, sym
representation = sym.S(0, sym.var("sigma"))
op = representation

bc = cl.clmath.cos(mode_nr*angle)

bound_op = bind(discr, op)

from sumpy.tools import build_matrix
mat = build_matrix(bound_op.scipy_op(queue, "sigma"))

w, v = la.eig(mat)

import matplotlib.pyplot as pt
pt.plot(w.real, w.imag, "x")
pt.rc("font", size=20)
pt.grid()
def main():
    import logging
    logging.basicConfig(level=logging.WARNING)  # INFO for more progress info

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

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

    if 0:
        mesh = make_curve_mesh(
                partial(ellipse, 1),
                np.linspace(0, 1, nelements+1),
                mesh_order)
    else:
        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 0:
            from meshmode.mesh.visualization import draw_curve
            draw_curve(mesh)
            import matplotlib.pyplot as plt
            plt.show()

    pre_density_discr = Discretization(
            cl_ctx, 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
            ).with_refinement()
    density_discr = qbx.density_discr

    # {{{ describe bvp

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

    cse = sym.cse

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

    # Brakhage-Werner parameter
    alpha = 1j

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

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

    # }}}

    bound_op = bind(qbx, bdry_op_sym)

    # {{{ fix rhs and solve

    nodes = density_discr.nodes().with_queue(queue)
    k_vec = np.array([2, 1])
    k_vec = k * k_vec / la.norm(k_vec, 2)

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

    bc = -u_incoming_func(nodes)

    bvp_rhs = bind(qbx, sqrt_w*sym.var("bc"))(queue, bc=bc)

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

    # }}}

    # {{{ postprocess/visualize

    sigma = gmres_result.solution

    repr_kwargs = dict(k=sym.var("k"), qbx_forced_limit=None)
    representation_sym = (
            alpha*sym.S(kernel, inv_sqrt_w_sigma, **repr_kwargs)
            - sym.D(kernel, inv_sqrt_w_sigma, **repr_kwargs))

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

    targets = cl.array.to_device(queue, fplot.points)

    u_incoming = u_incoming_func(targets)

    qbx_stick_out = qbx.copy(target_association_tolerance=0.05)

    ones_density = density_discr.zeros(queue)
    ones_density.fill(1)
    indicator = bind(
            (qbx_stick_out, PointsTarget(targets)),
            sym.D(LaplaceKernel(2), sym.var("sigma"), qbx_forced_limit=None))(
            queue, sigma=ones_density).get()

    try:
        fld_in_vol = bind(
                (qbx_stick_out, PointsTarget(targets)),
                representation_sym)(queue, sigma=sigma, k=k).get()
    except QBXTargetAssociationFailedException as e:
        fplot.write_vtk_file(
                "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(
            "potential-helm.vts",
            [
                ("potential", fld_in_vol),
                ("indicator", indicator),
                ("u_incoming", u_incoming.get()),
                ]
            )
Exemple #51
0
def main():
    import logging
    logger = logging.getLogger(__name__)
    logging.basicConfig(level=logging.WARNING)  # INFO for more progress info

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    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))

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

    # {{{ describe bvp

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

    cse = sym.cse

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

    # Brakhage-Werner parameter
    alpha = 1j

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

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

    # }}}

    bound_op = bind(qbx, bdry_op_sym)

    # {{{ fix rhs and solve

    mode_nr = 3
    nodes = density_discr.nodes().with_queue(queue)
    angle = cl.clmath.atan2(nodes[1], nodes[0])

    bc = cl.clmath.cos(mode_nr*angle)

    bvp_rhs = bind(qbx, sqrt_w*sym.var("bc"))(queue, bc=bc)

    from pytential.solve import gmres
    gmres_result = gmres(
            bound_op.scipy_op(queue, "sigma", k=k),
            bvp_rhs, tol=1e-14, progress=True,
            stall_iterations=0,
            hard_failure=True)

    # }}}

    # {{{ postprocess/visualize

    sigma = gmres_result.solution

    representation_sym = (
            alpha*sym.S(kernel, inv_sqrt_w_sigma, k=sym.var("k"))
            - sym.D(kernel, inv_sqrt_w_sigma, k=sym.var("k")))

    from sumpy.visualization import FieldPlotter
    fplot = FieldPlotter(np.zeros(2), extent=5, npoints=1500)
    from pytential.target import PointsTarget
    fld_in_vol = bind(
            (qbx, PointsTarget(fplot.points)),
            representation_sym)(queue, sigma=sigma, k=k).get()

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