예제 #1
0
def test_p2p(ctx_factory, exclude_self):
    ctx = ctx_factory()
    queue = cl.CommandQueue(ctx)

    dimensions = 3
    n = 5000

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

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

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

    extra_kwargs = {}

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

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

    potential_ref = np.empty_like(potential)

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

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

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

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

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

    rel_err = la.norm(potential - potential_ref) / la.norm(potential_ref)
    print(rel_err)
    assert rel_err < 1e-3
예제 #2
0
def test_expr_pickling():
    import pickle
    from sumpy.kernel import LaplaceKernel, AxisTargetDerivative

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

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

        assert op == after_pickle_op
예제 #3
0
def drive_test_cheb_tables_grad_laplace3d(requires_pypvfmm, ctx_factory,
                                          q_order, axis):
    from sumpy.kernel import LaplaceKernel, AxisTargetDerivative
    from volumential.list1_symmetry import Flip, Swap

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

    kernel = AxisTargetDerivative(axis, LaplaceKernel(3))
    source_box_r = 1.69

    from itertools import product
    symmetry_tags = [Flip(iaxis) for iaxis in range(3) if iaxis != axis] + \
            [Swap(iaxis, jaxis) for iaxis, jaxis in product(range(3), repeat=2)
                    if (iaxis < jaxis and iaxis != axis and jaxis != axis)]
    print(symmetry_tags)

    drive_test_cheb_table(queue,
                          kernel,
                          q_order,
                          source_box_r,
                          n_brick_q_points=120,
                          kernel_symmetry_tags=symmetry_tags)
예제 #4
0
def test_p2e2p(ctx_factory, base_knl, expn_class, order,
               with_source_derivative):
    #logging.basicConfig(level=logging.INFO)

    from sympy.core.cache import clear_cache
    clear_cache()

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

    np.random.seed(17)

    res = 100
    nsources = 100

    extra_kwargs = {}
    if isinstance(base_knl, HelmholtzKernel):
        if base_knl.allow_evanescent:
            extra_kwargs["k"] = 0.2 * (0.707 + 0.707j)
        else:
            extra_kwargs["k"] = 0.2
    if isinstance(base_knl, StokesletKernel):
        extra_kwargs["mu"] = 0.2

    if with_source_derivative:
        knl = DirectionalSourceDerivative(base_knl, "dir_vec")
    else:
        knl = base_knl

    out_kernels = [
        knl,
        AxisTargetDerivative(0, knl),
    ]
    expn = expn_class(knl, order=order)

    from sumpy import P2EFromSingleBox, E2PFromSingleBox, P2P
    p2e = P2EFromSingleBox(ctx, expn, kernels=[knl])
    e2p = E2PFromSingleBox(ctx, expn, kernels=out_kernels)
    p2p = P2P(ctx, out_kernels, exclude_self=False)

    from pytools.convergence import EOCRecorder
    eoc_rec_pot = EOCRecorder()
    eoc_rec_grad_x = EOCRecorder()

    from sumpy.expansion.local import LocalExpansionBase
    if issubclass(expn_class, LocalExpansionBase):
        h_values = [1 / 5, 1 / 7, 1 / 20]
    else:
        h_values = [1 / 2, 1 / 3, 1 / 5]

    center = np.array([2, 1, 0][:knl.dim], np.float64)
    sources = (0.7 *
               (-0.5 + np.random.rand(knl.dim, nsources).astype(np.float64)) +
               center[:, np.newaxis])

    strengths = np.ones(nsources, dtype=np.float64) * (1 / nsources)

    source_boxes = np.array([0], dtype=np.int32)
    box_source_starts = np.array([0], dtype=np.int32)
    box_source_counts_nonchild = np.array([nsources], dtype=np.int32)

    extra_source_kwargs = extra_kwargs.copy()
    if isinstance(knl, DirectionalSourceDerivative):
        alpha = np.linspace(0, 2 * np.pi, nsources, np.float64)
        dir_vec = np.vstack([np.cos(alpha), np.sin(alpha)])
        extra_source_kwargs["dir_vec"] = dir_vec

    from sumpy.visualization import FieldPlotter

    for h in h_values:
        if issubclass(expn_class, LocalExpansionBase):
            loc_center = np.array([5.5, 0.0, 0.0][:knl.dim]) + center
            centers = np.array(loc_center,
                               dtype=np.float64).reshape(knl.dim, 1)
            fp = FieldPlotter(loc_center, extent=h, npoints=res)
        else:
            eval_center = np.array([1 / h, 0.0, 0.0][:knl.dim]) + center
            fp = FieldPlotter(eval_center, extent=0.1, npoints=res)
            centers = (np.array([0.0, 0.0, 0.0][:knl.dim],
                                dtype=np.float64).reshape(knl.dim, 1) +
                       center[:, np.newaxis])

        targets = fp.points

        rscale = 0.5  # pick something non-1

        # {{{ apply p2e

        evt, (mpoles, ) = p2e(
            queue,
            source_boxes=source_boxes,
            box_source_starts=box_source_starts,
            box_source_counts_nonchild=box_source_counts_nonchild,
            centers=centers,
            sources=sources,
            strengths=(strengths, ),
            nboxes=1,
            tgt_base_ibox=0,
            rscale=rscale,

            #flags="print_hl_cl",
            out_host=True,
            **extra_source_kwargs)

        # }}}

        # {{{ apply e2p

        ntargets = targets.shape[-1]

        box_target_starts = np.array([0], dtype=np.int32)
        box_target_counts_nonchild = np.array([ntargets], dtype=np.int32)

        evt, (
            pot,
            grad_x,
        ) = e2p(
            queue,
            src_expansions=mpoles,
            src_base_ibox=0,
            target_boxes=source_boxes,
            box_target_starts=box_target_starts,
            box_target_counts_nonchild=box_target_counts_nonchild,
            centers=centers,
            targets=targets,
            rscale=rscale,

            #flags="print_hl_cl",
            out_host=True,
            **extra_kwargs)

        # }}}

        # {{{ compute (direct) reference solution

        evt, (
            pot_direct,
            grad_x_direct,
        ) = p2p(queue,
                targets,
                sources, (strengths, ),
                out_host=True,
                **extra_source_kwargs)

        err_pot = la.norm((pot - pot_direct) / res**2)
        err_grad_x = la.norm((grad_x - grad_x_direct) / res**2)

        if 1:
            err_pot = err_pot / la.norm((pot_direct) / res**2)
            err_grad_x = err_grad_x / la.norm((grad_x_direct) / res**2)

        if 0:
            import matplotlib.pyplot as pt
            from matplotlib.colors import Normalize

            pt.subplot(131)
            im = fp.show_scalar_in_matplotlib(pot.real)
            im.set_norm(Normalize(vmin=-0.1, vmax=0.1))

            pt.subplot(132)
            im = fp.show_scalar_in_matplotlib(pot_direct.real)
            im.set_norm(Normalize(vmin=-0.1, vmax=0.1))
            pt.colorbar()

            pt.subplot(133)
            im = fp.show_scalar_in_matplotlib(
                np.log10(1e-15 + np.abs(pot - pot_direct)))
            im.set_norm(Normalize(vmin=-6, vmax=1))

            pt.colorbar()
            pt.show()

        # }}}

        eoc_rec_pot.add_data_point(h, err_pot)
        eoc_rec_grad_x.add_data_point(h, err_grad_x)

    print(expn_class, knl, order)
    print("POTENTIAL:")
    print(eoc_rec_pot)
    print("X TARGET DERIVATIVE:")
    print(eoc_rec_grad_x)

    tgt_order = order + 1
    if issubclass(expn_class, LocalExpansionBase):
        tgt_order_grad = tgt_order - 1
        slack = 0.7
        grad_slack = 0.5
    else:
        tgt_order_grad = tgt_order + 1

        slack = 0.5
        grad_slack = 1

        if order <= 2:
            slack += 1
            grad_slack += 1

    if isinstance(knl, DirectionalSourceDerivative):
        slack += 1
        grad_slack += 2

    if isinstance(base_knl, DirectionalSourceDerivative):
        slack += 1
        grad_slack += 2

    if isinstance(base_knl, HelmholtzKernel):
        if base_knl.allow_evanescent:
            slack += 0.5
            grad_slack += 0.5

        if issubclass(expn_class, VolumeTaylorMultipoleExpansionBase):
            slack += 0.3
            grad_slack += 0.3

    assert eoc_rec_pot.order_estimate() > tgt_order - slack
    assert eoc_rec_grad_x.order_estimate() > tgt_order_grad - grad_slack
예제 #5
0
    def get_sumpy_kernel(self, dim, kernel_type):
        """Sumpy (symbolic) version of the kernel.
        """

        if kernel_type == "Laplace":
            from sumpy.kernel import LaplaceKernel

            return LaplaceKernel(dim)

        if kernel_type == "Laplace-Dx":
            from sumpy.kernel import LaplaceKernel, AxisTargetDerivative

            return AxisTargetDerivative(0, LaplaceKernel(dim))

        if kernel_type == "Laplace-Dy":
            from sumpy.kernel import LaplaceKernel, AxisTargetDerivative

            return AxisTargetDerivative(1, LaplaceKernel(dim))

        if kernel_type == "Laplace-Dz":
            from sumpy.kernel import LaplaceKernel, AxisTargetDerivative

            assert dim >= 3
            return AxisTargetDerivative(2, LaplaceKernel(dim))

        elif kernel_type == "Constant":
            return ConstantKernel(dim)

        elif kernel_type == "Yukawa":
            from sumpy.kernel import YukawaKernel

            return YukawaKernel(dim)

        elif kernel_type == "Yukawa-Dx":
            from sumpy.kernel import YukawaKernel, AxisTargetDerivative

            return AxisTargetDerivative(0, YukawaKernel(dim))

        elif kernel_type == "Yukawa-Dy":
            from sumpy.kernel import YukawaKernel, AxisTargetDerivative

            return AxisTargetDerivative(1, YukawaKernel(dim))

        elif kernel_type == "Cahn-Hilliard":
            from sumpy.kernel import FactorizedBiharmonicKernel

            return FactorizedBiharmonicKernel(dim)

        elif kernel_type == "Cahn-Hilliard-Laplacian":
            from sumpy.kernel import (
                FactorizedBiharmonicKernel,
                LaplacianTargetDerivative,
            )

            return LaplacianTargetDerivative(FactorizedBiharmonicKernel(dim))

        elif kernel_type == "Cahn-Hilliard-Dx":
            from sumpy.kernel import FactorizedBiharmonicKernel, AxisTargetDerivative

            return AxisTargetDerivative(0, FactorizedBiharmonicKernel(dim))

        elif kernel_type == "Cahn-Hilliard-Laplacian-Dx":
            from sumpy.kernel import (
                FactorizedBiharmonicKernel,
                LaplacianTargetDerivative,
            )
            from sumpy.kernel import AxisTargetDerivative

            return AxisTargetDerivative(
                0, LaplacianTargetDerivative(FactorizedBiharmonicKernel(dim)))

        elif kernel_type == "Cahn-Hilliard-Laplacian-Dy":
            from sumpy.kernel import (
                FactorizedBiharmonicKernel,
                LaplacianTargetDerivative,
            )
            from sumpy.kernel import AxisTargetDerivative

            return AxisTargetDerivative(
                1, LaplacianTargetDerivative(FactorizedBiharmonicKernel(dim)))

        elif kernel_type == "Cahn-Hilliard-Dy":
            from sumpy.kernel import FactorizedBiharmonicKernel, AxisTargetDerivative

            return AxisTargetDerivative(1, FactorizedBiharmonicKernel(dim))

        elif kernel_type in self.supported_kernels:
            return None

        else:
            raise NotImplementedError("Kernel type not supported.")
예제 #6
0
 def map_int_g(self, expr):
     from sumpy.kernel import AxisTargetDerivative
     return expr.copy(
         kernel=AxisTargetDerivative(self.ambient_axis, expr.kernel))
예제 #7
0
def run_dielectric_test(cl_ctx,
                        queue,
                        nelements,
                        qbx_order,
                        op_class,
                        mode,
                        k0=3,
                        k1=2.9,
                        mesh_order=10,
                        bdry_quad_order=None,
                        bdry_ovsmp_quad_order=None,
                        use_l2_weighting=False,
                        fmm_order=None,
                        visualize=False):

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

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

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

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

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

    # {{{ solve bvp

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

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

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

    op_unknown_sym = pde_op.make_unknown("unknown")

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            if use_l2_weighting:
                bvp_rhs[i_bc] *= sqrt_w

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

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

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

        unknown = gmres_result.solution

    # }}}

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

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

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

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

    err_F0_total = 0  # noqa
    err_F1_total = 0  # noqa

    i_field = 0

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

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

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

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

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

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

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

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

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

        i_field += 1

    if visualize:
        from sumpy.visualization import FieldPlotter
        fplot = FieldPlotter(np.zeros(2), extent=5, npoints=300)
        from pytential.target import PointsTarget
        fld0 = bind((qbx, PointsTarget(fplot.points)),
                    representation0_sym)(queue, unknown=unknown, K0=K0)
        fld1 = bind((qbx, PointsTarget(fplot.points)),
                    representation1_sym)(queue, unknown=unknown, K1=K1)

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

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

            i_field += 0

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

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

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

    return err_F0_total, err_F1_total
예제 #8
0
    nftable = {
        tb.integral_knl.__repr__(): tb,
        tb_dx.integral_knl.__repr__(): tb_dx,
        tb_dy.integral_knl.__repr__(): tb_dy,
    }

# }}} End build near field potential table

# {{{ sumpy expansion for laplace kernel

from sumpy.expansion import DefaultExpansionFactory
from sumpy.kernel import LaplaceKernel, AxisTargetDerivative

knl = LaplaceKernel(dim)
knl_dx = AxisTargetDerivative(0, knl)
knl_dy = AxisTargetDerivative(1, knl)

expn_factory = DefaultExpansionFactory()
local_expn_class = expn_factory.get_local_expansion_class(knl)
mpole_expn_class = expn_factory.get_multipole_expansion_class(knl)
out_kernels = [knl, knl_dx, knl_dy]

exclude_self = True
from volumential.expansion_wrangler_fpnd import (
    FPNDExpansionWranglerCodeContainer, FPNDExpansionWrangler)

wcc = FPNDExpansionWranglerCodeContainer(
    ctx,
    partial(mpole_expn_class, knl),
    partial(local_expn_class, knl),
예제 #9
0
def compute_biharmonic_extension(queue,
                                 target_discr,
                                 qbx,
                                 density_discr,
                                 f,
                                 fx,
                                 fy,
                                 target_association_tolerance=0.05):
    """Biharmoc extension. Currently only support
    interior domains in 2D (i.e., extension is on the exterior).
    """
    # pylint: disable=invalid-unary-operand-type
    dim = 2
    queue = setup_command_queue(queue=queue)
    qbx_forced_limit = 1

    normal = get_normal_vectors(queue, density_discr, loc_sign=1)

    bdry_op_sym = get_extension_bie_symbolic_operator(loc_sign=1)
    bound_op = bind(qbx, bdry_op_sym)

    bc = [fy, -fx]
    bvp_rhs = bind(qbx, sym.make_sym_vector("bc", dim))(queue, bc=bc)
    gmres_result = gmres(bound_op.scipy_op(queue,
                                           "sigma",
                                           np.float64,
                                           mu=1.,
                                           normal=normal),
                         bvp_rhs,
                         tol=1e-9,
                         progress=True,
                         stall_iterations=0,
                         hard_failure=True)
    mu = gmres_result.solution

    arclength_parametrization_derivatives_sym = sym.make_sym_vector(
        "arclength_parametrization_derivatives", dim)
    density_mu_sym = sym.make_sym_vector("mu", dim)
    dxids_sym = arclength_parametrization_derivatives_sym[0] + \
            1j * arclength_parametrization_derivatives_sym[1]
    dxids_conj_sym = arclength_parametrization_derivatives_sym[0] - \
            1j * arclength_parametrization_derivatives_sym[1]
    density_rho_sym = density_mu_sym[1] - 1j * density_mu_sym[0]
    density_conj_rho_sym = density_mu_sym[1] + 1j * density_mu_sym[0]

    # convolutions
    GS1 = sym.IntG(  # noqa: N806
        ComplexLinearLogKernel(dim),
        density_rho_sym,
        qbx_forced_limit=None)
    GS2 = sym.IntG(  # noqa: N806
        ComplexLinearKernel(dim),
        density_conj_rho_sym,
        qbx_forced_limit=None)
    GD1 = sym.IntG(  # noqa: N806
        ComplexFractionalKernel(dim),
        density_rho_sym * dxids_sym,
        qbx_forced_limit=None)
    GD2 = [
        sym.IntG(  # noqa: N806
            AxisTargetDerivative(iaxis, ComplexLogKernel(dim)),
            density_conj_rho_sym * dxids_sym +
            density_rho_sym * dxids_conj_sym,
            qbx_forced_limit=qbx_forced_limit) for iaxis in range(dim)
    ]

    GS1_bdry = sym.IntG(  # noqa: N806
        ComplexLinearLogKernel(dim),
        density_rho_sym,
        qbx_forced_limit=qbx_forced_limit)
    GS2_bdry = sym.IntG(  # noqa: N806
        ComplexLinearKernel(dim),
        density_conj_rho_sym,
        qbx_forced_limit=qbx_forced_limit)
    GD1_bdry = sym.IntG(  # noqa: N806
        ComplexFractionalKernel(dim),
        density_rho_sym * dxids_sym,
        qbx_forced_limit=qbx_forced_limit)

    xp, yp = get_arclength_parametrization_derivative(queue, density_discr)
    xp = -xp
    yp = -yp
    tangent = get_tangent_vectors(queue,
                                  density_discr,
                                  loc_sign=qbx_forced_limit)

    # check and fix the direction of parametrization
    # logger.info("Fix all negative signs in:" +
    #        str(xp * tangent[0] + yp * tangent[1]))

    grad_v2 = [
        bind(qbx,
             GD2[iaxis])(queue,
                         mu=mu,
                         arclength_parametrization_derivatives=make_obj_array(
                             [xp, yp])).real for iaxis in range(dim)
    ]
    v2_tangent_der = sum(tangent[iaxis] * grad_v2[iaxis]
                         for iaxis in range(dim))

    from pytential.symbolic.pde.scalar import NeumannOperator
    from sumpy.kernel import LaplaceKernel
    operator_v1 = NeumannOperator(LaplaceKernel(dim),
                                  loc_sign=qbx_forced_limit)
    bound_op_v1 = bind(qbx, operator_v1.operator(var("sigma")))
    # FIXME: the positive sign works here
    rhs_v1 = operator_v1.prepare_rhs(1 * v2_tangent_der)
    gmres_result = gmres(bound_op_v1.scipy_op(queue, "sigma",
                                              dtype=np.float64),
                         rhs_v1,
                         tol=1e-9,
                         progress=True,
                         stall_iterations=0,
                         hard_failure=True)
    sigma = gmres_result.solution
    qbx_stick_out = qbx.copy(
        target_association_tolerance=target_association_tolerance)
    v1 = bind((qbx_stick_out, target_discr),
              operator_v1.representation(var("sigma"),
                                         qbx_forced_limit=None))(queue,
                                                                 sigma=sigma)
    grad_v1 = bind(
        (qbx_stick_out, target_discr),
        operator_v1.representation(
            var("sigma"),
            qbx_forced_limit=None,
            map_potentials=lambda pot: sym.grad(dim, pot)))(queue, sigma=sigma)
    v1_bdry = bind(
        qbx,
        operator_v1.representation(var("sigma"),
                                   qbx_forced_limit=qbx_forced_limit))(
                                       queue, sigma=sigma)

    z_conj = target_discr.nodes()[0] - 1j * target_discr.nodes()[1]
    z_conj_bdry = density_discr.nodes().with_queue(queue)[0] \
            - 1j * density_discr.nodes().with_queue(queue)[1]
    int_rho = 1 / (8 * np.pi) * bind(
        qbx, sym.integral(dim, dim - 1, density_rho_sym))(queue, mu=mu)

    omega_S1 = bind(  # noqa: N806
        (qbx_stick_out, target_discr), GS1)(queue, mu=mu).real
    omega_S2 = -1 * bind(  # noqa: N806
        (qbx_stick_out, target_discr), GS2)(queue, mu=mu).real
    omega_S3 = (z_conj * int_rho).real  # noqa: N806
    omega_S = -(omega_S1 + omega_S2 + omega_S3)  # noqa: N806

    grad_omega_S1 = bind(  # noqa: N806
        (qbx_stick_out, target_discr), sym.grad(dim, GS1))(queue, mu=mu).real
    grad_omega_S2 = -1 * bind(  # noqa: N806
        (qbx_stick_out, target_discr), sym.grad(dim, GS2))(queue, mu=mu).real
    grad_omega_S3 = (int_rho * make_obj_array([1., -1.])).real  # noqa: N806
    grad_omega_S = -(grad_omega_S1 + grad_omega_S2 + grad_omega_S3
                     )  # noqa: N806

    omega_S1_bdry = bind(qbx, GS1_bdry)(queue, mu=mu).real  # noqa: N806
    omega_S2_bdry = -1 * bind(qbx, GS2_bdry)(queue, mu=mu).real  # noqa: N806
    omega_S3_bdry = (z_conj_bdry * int_rho).real  # noqa: N806
    omega_S_bdry = -(omega_S1_bdry + omega_S2_bdry + omega_S3_bdry
                     )  # noqa: N806

    omega_D1 = bind(  # noqa: N806
        (qbx_stick_out, target_discr),
        GD1)(queue,
             mu=mu,
             arclength_parametrization_derivatives=make_obj_array([xp,
                                                                   yp])).real
    omega_D = (omega_D1 + v1)  # noqa: N806

    grad_omega_D1 = bind(  # noqa: N806
        (qbx_stick_out, target_discr), sym.grad(dim, GD1))(
            queue,
            mu=mu,
            arclength_parametrization_derivatives=make_obj_array([xp,
                                                                  yp])).real
    grad_omega_D = grad_omega_D1 + grad_v1  # noqa: N806

    omega_D1_bdry = bind(  # noqa: N806
        qbx, GD1_bdry)(queue,
                       mu=mu,
                       arclength_parametrization_derivatives=make_obj_array(
                           [xp, yp])).real
    omega_D_bdry = (omega_D1_bdry + v1_bdry)  # noqa: N806

    int_bdry_mu = bind(
        qbx, sym.integral(dim, dim - 1, sym.make_sym_vector("mu", dim)))(queue,
                                                                         mu=mu)
    omega_W = (  # noqa: N806
        int_bdry_mu[0] * target_discr.nodes()[1] -
        int_bdry_mu[1] * target_discr.nodes()[0])
    grad_omega_W = make_obj_array(  # noqa: N806
        [-int_bdry_mu[1], int_bdry_mu[0]])
    omega_W_bdry = (  # noqa: N806
        int_bdry_mu[0] * density_discr.nodes().with_queue(queue)[1] -
        int_bdry_mu[1] * density_discr.nodes().with_queue(queue)[0])

    int_bdry = bind(qbx, sym.integral(dim, dim - 1, var("integrand")))(
        queue, integrand=omega_S_bdry + omega_D_bdry + omega_W_bdry)

    debugging_info = {}
    debugging_info['omega_S'] = omega_S
    debugging_info['omega_D'] = omega_D
    debugging_info['omega_W'] = omega_W
    debugging_info['omega_v1'] = v1
    debugging_info['omega_D1'] = omega_D1

    int_interior_func_bdry = bind(qbx,
                                  sym.integral(2, 1,
                                               var("integrand")))(queue,
                                                                  integrand=f)

    path_length = get_path_length(queue, density_discr)
    ext_f = omega_S + omega_D + omega_W + (int_interior_func_bdry -
                                           int_bdry) / path_length
    grad_f = grad_omega_S + grad_omega_D + grad_omega_W

    return ext_f, grad_f[0], grad_f[1], debugging_info