Exemple #1
0
def test_line_taylor_coeff_growth():
    # Regression test for LineTaylorLocalExpansion.
    # See https://gitlab.tiker.net/inducer/pytential/merge_requests/12
    from sumpy.kernel import LaplaceKernel
    from sumpy.expansion.local import LineTaylorLocalExpansion
    from sumpy.symbolic import make_sym_vector, SympyToPymbolicMapper

    import numpy as np

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

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

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

    indices = np.arange(1, order + 2)
    max_order = 2
    assert np.polyfit(np.log(indices), np.log(counts), deg=1)[0] < max_order
Exemple #2
0
def test_line_taylor_coeff_growth():
    # Regression test for LineTaylorLocalExpansion.
    # See https://gitlab.tiker.net/inducer/pytential/merge_requests/12
    from sumpy.kernel import LaplaceKernel
    from sumpy.expansion.local import LineTaylorLocalExpansion
    from sumpy.symbolic import make_sym_vector, SympyToPymbolicMapper

    import numpy as np

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

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

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

    indices = np.arange(1, order + 2)
    max_order = 2
    assert np.polyfit(np.log(indices), np.log(counts), deg=1)[0] < max_order
Exemple #3
0
    def map_int_g(self, expr):
        lpot_source = self.places.get_geometry(expr.source.geometry)
        source_discr = self.places.get_discretization(expr.source.geometry,
                                                      expr.source.discr_stage)
        target_discr = self.places.get_discretization(expr.target.geometry,
                                                      expr.target.discr_stage)

        if source_discr is not target_discr:
            raise NotImplementedError

        rec_density = self._blk_mapper.rec(expr.density)
        if is_zero(rec_density):
            return 0

        if not np.isscalar(rec_density):
            raise NotImplementedError

        actx = self.array_context
        kernel = expr.kernel
        kernel_args = _get_layer_potential_args(self._mat_mapper, expr)

        from sumpy.expansion.local import LineTaylorLocalExpansion
        local_expn = LineTaylorLocalExpansion(kernel, lpot_source.qbx_order)

        from sumpy.qbx import LayerPotentialMatrixBlockGenerator
        mat_gen = LayerPotentialMatrixBlockGenerator(actx.context,
                                                     (local_expn, ))

        assert abs(expr.qbx_forced_limit) > 0
        from pytential import bind, sym
        radii = bind(
            self.places,
            sym.expansion_radii(source_discr.ambient_dim,
                                dofdesc=expr.target))(actx)
        centers = bind(
            self.places,
            sym.expansion_centers(source_discr.ambient_dim,
                                  expr.qbx_forced_limit,
                                  dofdesc=expr.target))(actx)

        from meshmode.dof_array import flatten, thaw
        _, (mat, ) = mat_gen(actx.queue,
                             targets=flatten(thaw(actx, target_discr.nodes())),
                             sources=flatten(thaw(actx, source_discr.nodes())),
                             centers=flatten(centers),
                             expansion_radii=flatten(radii),
                             index_set=self.index_set,
                             **kernel_args)

        waa = bind(
            self.places,
            sym.weights_and_area_elements(source_discr.ambient_dim,
                                          dofdesc=expr.source))(actx)
        waa = flatten(waa)

        mat *= waa[self.index_set.linear_col_indices]
        return rec_density * actx.to_numpy(mat)
Exemple #4
0
def test_direct(ctx_factory):
    # This evaluates a single layer potential on a circle.
    logging.basicConfig(level=logging.INFO)

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

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

    order = 12

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

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

    mode_nr = 25

    from pytools.convergence import EOCRecorder

    eocrec = EOCRecorder()

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

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

        result_ref = eigval * sigma

        h = 2 * np.pi / n

        targets = unit_circle
        sources = unit_circle

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

        expansion_radii = np.ones(n) * radius

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

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

    print(eocrec)

    slack = 1.5
    assert eocrec.order_estimate() > order - slack
Exemple #5
0
    def get_expansion_for_qbx_direct_eval(self, base_kernel, target_kernels):
        from sumpy.expansion.local import LineTaylorLocalExpansion
        from sumpy.kernel import TargetDerivativeRemover

        # line Taylor cannot support target derivatives
        txr = TargetDerivativeRemover()
        if any(knl != txr(knl) for knl in target_kernels):
            return self.expansion_factory.get_local_expansion_class(
                    base_kernel)(base_kernel, self.qbx_order)
        else:
            return LineTaylorLocalExpansion(base_kernel, self.qbx_order)
Exemple #6
0
    def map_int_g(self, expr):
        lpot_source = self.places.get_geometry(expr.source.geometry)
        source_discr = self.places.get_discretization(expr.source.geometry,
                                                      expr.source.discr_stage)
        target_discr = self.places.get_discretization(expr.target.geometry,
                                                      expr.target.discr_stage)

        rec_density = self.rec(expr.density)
        if is_zero(rec_density):
            return 0

        assert isinstance(rec_density, np.ndarray)
        if not self.is_kind_matrix(rec_density):
            raise NotImplementedError("layer potentials on non-variables")

        actx = self.array_context
        kernel = expr.kernel
        kernel_args = _get_layer_potential_args(self, expr)

        from sumpy.expansion.local import LineTaylorLocalExpansion
        local_expn = LineTaylorLocalExpansion(kernel, lpot_source.qbx_order)

        from sumpy.qbx import LayerPotentialMatrixGenerator
        mat_gen = LayerPotentialMatrixGenerator(actx.context, (local_expn, ))

        assert abs(expr.qbx_forced_limit) > 0
        from pytential import bind, sym
        radii = bind(
            self.places,
            sym.expansion_radii(source_discr.ambient_dim,
                                dofdesc=expr.target))(actx)
        centers = bind(
            self.places,
            sym.expansion_centers(source_discr.ambient_dim,
                                  expr.qbx_forced_limit,
                                  dofdesc=expr.target))(actx)

        from meshmode.dof_array import flatten, thaw
        _, (mat, ) = mat_gen(actx.queue,
                             targets=flatten(thaw(actx, target_discr.nodes())),
                             sources=flatten(thaw(actx, source_discr.nodes())),
                             centers=flatten(centers),
                             expansion_radii=flatten(radii),
                             **kernel_args)
        mat = actx.to_numpy(mat)

        waa = bind(
            self.places,
            sym.weights_and_area_elements(source_discr.ambient_dim,
                                          dofdesc=expr.source))(actx)
        mat[:, :] *= actx.to_numpy(flatten(waa))
        mat = mat.dot(rec_density)

        return mat
Exemple #7
0
    def get_lpot_applier(self, kernels):
        # needs to be separate method for caching

        if any(knl.is_complex_valued for knl in kernels):
            value_dtype = self.density_discr.complex_dtype
        else:
            value_dtype = self.density_discr.real_dtype

        from sumpy.qbx import LayerPotential
        from sumpy.expansion.local import LineTaylorLocalExpansion
        return LayerPotential(
            self.cl_context,
            [LineTaylorLocalExpansion(knl, self.qbx_order) for knl in kernels],
            value_dtypes=value_dtype)
Exemple #8
0
    def get_lpot_applier(self, target_kernels, source_kernels):
        # needs to be separate method for caching

        if any(knl.is_complex_valued for knl in target_kernels):
            value_dtype = self.density_discr.complex_dtype
        else:
            value_dtype = self.density_discr.real_dtype

        base_kernel = single_valued(knl.get_base_kernel()
                                    for knl in source_kernels)

        from sumpy.qbx import LayerPotential
        from sumpy.expansion.local import LineTaylorLocalExpansion
        return LayerPotential(self.cl_context,
                              expansion=LineTaylorLocalExpansion(
                                  base_kernel, self.qbx_order),
                              target_kernels=target_kernels,
                              source_kernels=source_kernels,
                              value_dtypes=value_dtype)
Exemple #9
0
    def map_int_g(self, expr):
        source = self.places.get_geometry(expr.source)
        source_discr = self.places.get_discretization(expr.source)
        target_discr = self.places.get_discretization(expr.target)

        if source_discr is not target_discr:
            raise NotImplementedError()

        rec_density = self.blk_mapper.rec(expr.density)
        if is_zero(rec_density):
            return 0

        if not np.isscalar(rec_density):
            raise NotImplementedError()

        kernel = expr.kernel
        kernel_args = _get_layer_potential_args(self.mat_mapper, expr, None)

        from sumpy.expansion.local import LineTaylorLocalExpansion
        local_expn = LineTaylorLocalExpansion(kernel, source.qbx_order)

        from sumpy.qbx import LayerPotentialMatrixBlockGenerator
        mat_gen = LayerPotentialMatrixBlockGenerator(self.queue.context,
                                                     (local_expn, ))

        assert abs(expr.qbx_forced_limit) > 0
        centers, radii = _get_centers_and_expansion_radii(
            self.queue, source, target_discr, expr.qbx_forced_limit)

        _, (mat, ) = mat_gen(self.queue,
                             targets=target_discr.nodes(),
                             sources=source_discr.nodes(),
                             centers=centers,
                             expansion_radii=radii,
                             index_set=self.index_set,
                             **kernel_args)

        waa = _get_weights_and_area_elements(self.queue, source, source_discr)
        mat *= waa[self.index_set.linear_col_indices]
        mat = rec_density * mat.get(self.queue)

        return mat
Exemple #10
0
    def map_int_g(self, expr):
        lpot_source = self.places.get_geometry(expr.source)
        source_discr = self.places.get_discretization(expr.source)
        target_discr = self.places.get_discretization(expr.target)

        rec_density = self.rec(expr.density)
        if is_zero(rec_density):
            return 0

        assert isinstance(rec_density, np.ndarray)
        if not self.is_kind_matrix(rec_density):
            raise NotImplementedError("layer potentials on non-variables")

        kernel = expr.kernel
        kernel_args = _get_layer_potential_args(self, expr, lpot_source)

        from sumpy.expansion.local import LineTaylorLocalExpansion
        local_expn = LineTaylorLocalExpansion(kernel, lpot_source.qbx_order)

        from sumpy.qbx import LayerPotentialMatrixGenerator
        mat_gen = LayerPotentialMatrixGenerator(self.queue.context,
                                                (local_expn, ))

        assert abs(expr.qbx_forced_limit) > 0
        centers, radii = _get_centers_and_expansion_radii(
            self.queue, lpot_source, target_discr, expr.qbx_forced_limit)

        _, (mat, ) = mat_gen(self.queue,
                             targets=target_discr.nodes(),
                             sources=source_discr.nodes(),
                             centers=centers,
                             expansion_radii=radii,
                             **kernel_args)
        mat = mat.get()

        waa = _get_weights_and_area_elements(self.queue, lpot_source,
                                             source_discr)
        mat[:, :] *= waa.get(self.queue)
        mat = mat.dot(rec_density)

        return mat
Exemple #11
0
def test_qbx_direct(ctx_factory, factor, lpot_id):
    logging.basicConfig(level=logging.INFO)

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

    ndim = 2
    nblks = 10
    order = 12
    mode_nr = 25

    from sumpy.kernel import LaplaceKernel, DirectionalSourceDerivative
    if lpot_id == 1:
        knl = LaplaceKernel(ndim)
    elif lpot_id == 2:
        knl = LaplaceKernel(ndim)
        knl = DirectionalSourceDerivative(knl, dir_vec_name="dsource_vec")
    else:
        raise ValueError("unknow lpot_id")

    from sumpy.expansion.local import LineTaylorLocalExpansion
    lknl = LineTaylorLocalExpansion(knl, order)

    from sumpy.qbx import LayerPotential
    lpot = LayerPotential(ctx, [lknl])

    from sumpy.qbx import LayerPotentialMatrixGenerator
    mat_gen = LayerPotentialMatrixGenerator(ctx, [lknl])

    from sumpy.qbx import LayerPotentialMatrixBlockGenerator
    blk_gen = LayerPotentialMatrixBlockGenerator(ctx, [lknl])

    for n in [200, 300, 400]:
        targets, sources, centers, expansion_radii, sigma = \
                _build_geometry(queue, n, mode_nr, target_radius=1.2)

        h = 2 * np.pi / n
        strengths = (sigma * h, )

        tgtindices = _build_block_index(queue, n, nblks, factor)
        srcindices = _build_block_index(queue, n, nblks, factor)
        index_set = MatrixBlockIndexRanges(ctx, tgtindices, srcindices)

        extra_kwargs = {}
        if lpot_id == 2:
            from pytools.obj_array import make_obj_array
            extra_kwargs["dsource_vec"] = \
                    vector_to_device(queue, make_obj_array(np.ones((ndim, n))))

        _, (result_lpot, ) = lpot(queue,
                                  targets=targets,
                                  sources=sources,
                                  centers=centers,
                                  expansion_radii=expansion_radii,
                                  strengths=strengths,
                                  **extra_kwargs)
        result_lpot = result_lpot.get()

        _, (mat, ) = mat_gen(queue,
                             targets=targets,
                             sources=sources,
                             centers=centers,
                             expansion_radii=expansion_radii,
                             **extra_kwargs)
        mat = mat.get()
        result_mat = mat.dot(strengths[0].get())

        _, (blk, ) = blk_gen(queue,
                             targets=targets,
                             sources=sources,
                             centers=centers,
                             expansion_radii=expansion_radii,
                             index_set=index_set,
                             **extra_kwargs)
        blk = blk.get()

        rowindices = index_set.linear_row_indices.get(queue)
        colindices = index_set.linear_col_indices.get(queue)

        eps = 1.0e-10 * la.norm(result_lpot)
        assert la.norm(result_mat - result_lpot) < eps
        assert la.norm(blk - mat[rowindices, colindices]) < eps
Exemple #12
0
def main():
    import logging
    logging.basicConfig(level=logging.INFO)

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

    if 1:
        ext = 0.5
        mesh = generate_regular_rect_mesh(a=(-ext / 2, -ext / 2),
                                          b=(ext / 2, ext / 2),
                                          n=(int(ext / h), int(ext / h)))
    else:
        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.mesh import BTAG_ALL
    from meshmode.discretization.connection import (make_face_restriction,
                                                    make_same_mesh_connection)
    bdry_connection = make_face_restriction(
        vol_discr, InterpolatoryQuadratureSimplexGroupFactory(bdry_quad_order),
        BTAG_ALL)

    bdry_discr = bdry_connection.to_discr

    vol_to_ovsmp_vol = make_same_mesh_connection(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(
        mesh.ambient_dim))(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
        from pymbolic import var

        d = make_sym_vector("d", 3)
        r = pymbolic_real_norm_2(d[:-1])
        # r3d = pymbolic_real_norm_2(d)
        #expr = var("log")(r3d)

        log = var("log")
        sqrt = var("sqrt")

        a = d[-1]

        expr = log(r)
        expr = log(sqrt(r**2 + a**2))
        expr = log(sqrt(r + a**2))
        #expr = log(sqrt(r**2 + a**2))-a**2/2/(r**2+a**2)
        #expr = 2*log(sqrt(r**2 + a**2))

        scaling = 1 / (2 * var("pi"))

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

    laplace_2d_in_3d_kernel = get_kernel()

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

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

    center_dist = 0.125 * np.min(
        cl.clmath.sqrt(
            bind(vol_discr, p.area_element(mesh.ambient_dim,
                                           mesh.dim))(queue)).get())

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

    print(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(mesh.ambient_dim, mesh.dim) * p.QWeight())(queue)

    print("volume: %d source nodes, %d target nodes" %
          (ovsmp_vol_discr.nnodes, vol_discr.nnodes))
    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), ),
        expansion_radii=np.zeros(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", dtype=np.float64),
                         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)