Ejemplo n.º 1
0
 def refiner_code_container(self):
     from pytential.qbx.refinement import RefinerCodeContainer
     return RefinerCodeContainer(self.cl_context, self.tree_code_container)
Ejemplo n.º 2
0
 def make_container():
     from pytential.qbx.refinement import RefinerCodeContainer
     return RefinerCodeContainer(self._setup_actx,
                                 self.tree_code_container)
Ejemplo n.º 3
0
def run_source_refinement_test(ctx_factory, mesh, order, helmholtz_k=None):
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)

    from meshmode.discretization import Discretization
    from meshmode.discretization.poly_element import (
        InterpolatoryQuadratureSimplexGroupFactory)

    factory = InterpolatoryQuadratureSimplexGroupFactory(order)

    discr = Discretization(cl_ctx, mesh, factory)

    from pytential.qbx.refinement import (RefinerCodeContainer,
                                          refine_for_global_qbx)

    from pytential.qbx.utils import TreeCodeContainer

    lpot_source = QBXLayerPotentialSource(
        discr,
        qbx_order=order,  # not used in refinement
        fine_order=order)
    del discr

    expansion_disturbance_tolerance = 0.025
    refiner_extra_kwargs = {
        "expansion_disturbance_tolerance": expansion_disturbance_tolerance,
    }
    if helmholtz_k is not None:
        refiner_extra_kwargs["kernel_length_scale"] = 5 / helmholtz_k

    lpot_source, conn = refine_for_global_qbx(
        lpot_source,
        RefinerCodeContainer(cl_ctx,
                             TreeCodeContainer(cl_ctx)).get_wrangler(queue),
        factory, **refiner_extra_kwargs)

    discr_nodes = lpot_source.density_discr.nodes().get(queue)
    fine_discr_nodes = \
            lpot_source.quad_stage2_density_discr.nodes().get(queue)

    int_centers = bind(lpot_source,
                       sym.expansion_centers(lpot_source.ambient_dim,
                                             -1))(queue)
    int_centers = np.array([axis.get(queue) for axis in int_centers])
    ext_centers = bind(lpot_source,
                       sym.expansion_centers(lpot_source.ambient_dim,
                                             +1))(queue)
    ext_centers = np.array([axis.get(queue) for axis in ext_centers])

    expansion_radii = bind(lpot_source,
                           sym.expansion_radii(
                               lpot_source.ambient_dim))(queue).get()
    source_danger_zone_radii = bind(
        lpot_source,
        sym._source_danger_zone_radii(
            lpot_source.ambient_dim,
            dofdesc=sym.GRANULARITY_ELEMENT))(queue).get()

    quad_res = bind(
        lpot_source,
        sym._quad_resolution(lpot_source.ambient_dim,
                             dofdesc=sym.GRANULARITY_ELEMENT))(queue)

    # {{{ check if satisfying criteria

    def check_disk_undisturbed_by_sources(centers_panel, sources_panel):
        if centers_panel.element_nr == sources_panel.element_nr:
            # Same panel
            return

        my_int_centers = int_centers[:, centers_panel.discr_slice]
        my_ext_centers = ext_centers[:, centers_panel.discr_slice]
        all_centers = np.append(my_int_centers, my_ext_centers, axis=-1)

        nodes = discr_nodes[:, sources_panel.discr_slice]

        # =distance(centers of panel 1, panel 2)
        dist = (la.norm(
            (all_centers[..., np.newaxis] - nodes[:, np.newaxis, ...]).T,
            axis=-1).min())

        # Criterion:
        # A center cannot be closer to another panel than to its originating
        # panel.

        rad = expansion_radii[centers_panel.discr_slice]
        assert (dist >= rad * (1-expansion_disturbance_tolerance)).all(), \
                (dist, rad, centers_panel.element_nr, sources_panel.element_nr)

    def check_sufficient_quadrature_resolution(centers_panel, sources_panel):
        dz_radius = source_danger_zone_radii[sources_panel.element_nr]

        my_int_centers = int_centers[:, centers_panel.discr_slice]
        my_ext_centers = ext_centers[:, centers_panel.discr_slice]
        all_centers = np.append(my_int_centers, my_ext_centers, axis=-1)

        nodes = fine_discr_nodes[:, sources_panel.discr_slice]

        # =distance(centers of panel 1, panel 2)
        dist = (la.norm(
            (all_centers[..., np.newaxis] - nodes[:, np.newaxis, ...]).T,
            axis=-1).min())

        # Criterion:
        # The quadrature contribution from each panel is as accurate
        # as from the center's own source panel.
        assert dist >= dz_radius, \
                (dist, dz_radius, centers_panel.element_nr, sources_panel.element_nr)

    def check_quad_res_to_helmholtz_k_ratio(panel):
        # Check wavenumber to panel size ratio.
        assert quad_res[panel.element_nr] * helmholtz_k <= 5

    for i, panel_1 in enumerate(iter_elements(lpot_source.density_discr)):
        for panel_2 in iter_elements(lpot_source.density_discr):
            check_disk_undisturbed_by_sources(panel_1, panel_2)
        for panel_2 in iter_elements(lpot_source.quad_stage2_density_discr):
            check_sufficient_quadrature_resolution(panel_1, panel_2)
        if helmholtz_k is not None:
            check_quad_res_to_helmholtz_k_ratio(panel_1)