예제 #1
0
    def weights_and_area_elements(self):
        from pytential import bind, sym
        with cl.CommandQueue(self.cl_context) as queue:
            waa = bind(self,
                       sym.weights_and_area_elements(self.ambient_dim))(queue)

            return waa.with_queue(None)
예제 #2
0
 def weights_and_area_elements(self):
     from pytential import bind, sym
     with cl.CommandQueue(self.cl_context) as queue:
         return bind(
             self,
             sym.weights_and_area_elements(
                 self.ambient_dim, dofdesc=sym.QBX_SOURCE_QUAD_STAGE2))(
                     queue).with_queue(None)
예제 #3
0
파일: matrix.py 프로젝트: isuruf/pytential
    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)
예제 #4
0
def get_flat_strengths_from_densities(
        actx, places, evaluate, densities, dofdesc=None):
    from pytential import bind, sym
    waa = bind(
            places,
            sym.weights_and_area_elements(places.ambient_dim, dofdesc=dofdesc),
            )(actx)
    strength_vecs = [waa * evaluate(density) for density in densities]

    return [flatten(strength, actx) for strength in strength_vecs]
예제 #5
0
파일: matrix.py 프로젝트: isuruf/pytential
    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
예제 #6
0
    def exec_compute_potential_insn_direct(self, actx: PyOpenCLArrayContext,
                                           insn, bound_expr, evaluate):
        kernel_args = {}

        for arg_name, arg_expr in insn.kernel_arguments.items():
            kernel_args[arg_name] = flatten(evaluate(arg_expr),
                                            actx,
                                            leaf_class=DOFArray)

        from pytential import bind, sym
        waa = bind(
            bound_expr.places,
            sym.weights_and_area_elements(self.ambient_dim,
                                          dofdesc=insn.source))(actx)
        strengths = [waa * evaluate(density) for density in insn.densities]
        flat_strengths = [flatten(strength, actx) for strength in strengths]

        results = []
        p2p = None

        for o in insn.outputs:
            target_discr = bound_expr.places.get_discretization(
                o.target_name.geometry, o.target_name.discr_stage)

            if p2p is None:
                p2p = self.get_p2p(actx,
                                   source_kernels=insn.source_kernels,
                                   target_kernels=insn.target_kernels)

            evt, output_for_each_kernel = p2p(
                actx.queue,
                targets=flatten(target_discr.nodes(),
                                actx,
                                leaf_class=DOFArray),
                sources=flatten(self.density_discr.nodes(),
                                actx,
                                leaf_class=DOFArray),
                strength=flat_strengths,
                **kernel_args)

            from meshmode.discretization import Discretization
            result = output_for_each_kernel[o.target_kernel_index]
            if isinstance(target_discr, Discretization):
                template_ary = thaw(target_discr.nodes()[0], actx)
                result = unflatten(template_ary, result, actx, strict=False)

            results.append((o.name, result))

        timing_data = {}
        return results, timing_data
예제 #7
0
    def exec_compute_potential_insn_direct(self, actx: PyOpenCLArrayContext,
            insn, bound_expr, evaluate):
        kernel_args = {}

        from pytential.utils import flatten_if_needed
        from meshmode.dof_array import flatten, thaw, unflatten

        for arg_name, arg_expr in insn.kernel_arguments.items():
            kernel_args[arg_name] = flatten_if_needed(actx, evaluate(arg_expr))

        from pytential import bind, sym
        waa = bind(bound_expr.places, sym.weights_and_area_elements(
            self.ambient_dim, dofdesc=insn.source))(actx)
        strengths = waa * evaluate(insn.density)
        flat_strengths = flatten(strengths)

        results = []
        p2p = None

        for o in insn.outputs:
            target_discr = bound_expr.places.get_discretization(
                    o.target_name.geometry, o.target_name.discr_stage)

            if p2p is None:
                p2p = self.get_p2p(actx, insn.kernels)

            evt, output_for_each_kernel = p2p(actx.queue,
                    flatten_if_needed(actx, target_discr.nodes()),
                    flatten(thaw(actx, self.density_discr.nodes())),
                    [flat_strengths], **kernel_args)

            from meshmode.discretization import Discretization
            result = output_for_each_kernel[o.kernel_index]
            if isinstance(target_discr, Discretization):
                result = unflatten(actx, target_discr, result)

            results.append((o.name, result))

        timing_data = {}
        return results, timing_data
예제 #8
0
    def exec_compute_potential_insn_direct(self, actx, insn, bound_expr,
                                           evaluate, return_timing_data):
        from pytential import bind, sym
        if return_timing_data:
            from pytential.source import UnableToCollectTimingData
            from warnings import warn
            warn("Timing data collection not supported.",
                 category=UnableToCollectTimingData)

        lpot_applier = self.get_lpot_applier(insn.target_kernels,
                                             insn.source_kernels)
        p2p = None
        lpot_applier_on_tgt_subset = None

        from pytential.utils import flatten_if_needed
        kernel_args = {}
        for arg_name, arg_expr in insn.kernel_arguments.items():
            kernel_args[arg_name] = flatten_if_needed(actx, evaluate(arg_expr))

        waa = bind(
            bound_expr.places,
            sym.weights_and_area_elements(self.ambient_dim,
                                          dofdesc=insn.source))(actx)
        strength_vecs = [waa * evaluate(density) for density in insn.densities]

        from meshmode.discretization import Discretization
        flat_strengths = [flatten(strength) for strength in strength_vecs]

        source_discr = bound_expr.places.get_discretization(
            insn.source.geometry, insn.source.discr_stage)

        # FIXME: Do this all at once
        results = []
        for o in insn.outputs:
            source_dd = insn.source.copy(discr_stage=o.target_name.discr_stage)
            target_discr = bound_expr.places.get_discretization(
                o.target_name.geometry, o.target_name.discr_stage)
            density_discr = bound_expr.places.get_discretization(
                source_dd.geometry, source_dd.discr_stage)

            is_self = density_discr is target_discr
            if is_self:
                # QBXPreprocessor is supposed to have taken care of this
                assert o.qbx_forced_limit is not None
                assert abs(o.qbx_forced_limit) > 0

                expansion_radii = bind(
                    bound_expr.places,
                    sym.expansion_radii(self.ambient_dim,
                                        dofdesc=o.target_name))(actx)
                centers = bind(
                    bound_expr.places,
                    sym.expansion_centers(self.ambient_dim,
                                          o.qbx_forced_limit,
                                          dofdesc=o.target_name))(actx)

                evt, output_for_each_kernel = lpot_applier(
                    actx.queue,
                    flatten(thaw(actx, target_discr.nodes())),
                    flatten(thaw(actx, source_discr.nodes())),
                    flatten(centers),
                    flat_strengths,
                    expansion_radii=flatten(expansion_radii),
                    **kernel_args)

                result = output_for_each_kernel[o.target_kernel_index]
                if isinstance(target_discr, Discretization):
                    result = unflatten(actx, target_discr, result)

                results.append((o.name, result))
            else:
                # no on-disk kernel caching
                if p2p is None:
                    p2p = self.get_p2p(actx, insn.target_kernels,
                                       insn.source_kernels)
                if lpot_applier_on_tgt_subset is None:
                    lpot_applier_on_tgt_subset = self.get_lpot_applier_on_tgt_subset(
                        insn.target_kernels, insn.source_kernels)

                queue = actx.queue

                flat_targets = flatten_if_needed(actx, target_discr.nodes())
                flat_sources = flatten(thaw(actx, source_discr.nodes()))

                evt, output_for_each_kernel = p2p(queue, flat_targets,
                                                  flat_sources, flat_strengths,
                                                  **kernel_args)

                qbx_forced_limit = o.qbx_forced_limit
                if qbx_forced_limit is None:
                    qbx_forced_limit = 0

                target_discrs_and_qbx_sides = ((target_discr,
                                                qbx_forced_limit), )
                geo_data = self.qbx_fmm_geometry_data(
                    bound_expr.places,
                    insn.source.geometry,
                    target_discrs_and_qbx_sides=target_discrs_and_qbx_sides)

                # center-related info is independent of targets

                # First ncenters targets are the centers
                tgt_to_qbx_center = (
                    geo_data.user_target_to_center()[geo_data.ncenters:].copy(
                        queue=queue).with_queue(queue))

                qbx_tgt_numberer = self.get_qbx_target_numberer(
                    tgt_to_qbx_center.dtype)
                qbx_tgt_count = cl.array.empty(queue, (), np.int32)
                qbx_tgt_numbers = cl.array.empty_like(tgt_to_qbx_center)

                qbx_tgt_numberer(tgt_to_qbx_center,
                                 qbx_tgt_numbers,
                                 qbx_tgt_count,
                                 queue=queue)

                qbx_tgt_count = int(qbx_tgt_count.get())

                if (o.qbx_forced_limit is not None
                        and abs(o.qbx_forced_limit) == 1
                        and qbx_tgt_count < target_discr.ndofs):
                    raise RuntimeError("Did not find a matching QBX center "
                                       "for some targets")

                qbx_tgt_numbers = qbx_tgt_numbers[:qbx_tgt_count]
                qbx_center_numbers = tgt_to_qbx_center[qbx_tgt_numbers]
                qbx_center_numbers.finish()

                tgt_subset_kwargs = kernel_args.copy()
                for i, res_i in enumerate(output_for_each_kernel):
                    tgt_subset_kwargs[f"result_{i}"] = res_i

                if qbx_tgt_count:
                    lpot_applier_on_tgt_subset(
                        queue,
                        targets=flat_targets,
                        sources=flat_sources,
                        centers=geo_data.flat_centers(),
                        expansion_radii=geo_data.flat_expansion_radii(),
                        strengths=flat_strengths,
                        qbx_tgt_numbers=qbx_tgt_numbers,
                        qbx_center_numbers=qbx_center_numbers,
                        **tgt_subset_kwargs)

                result = output_for_each_kernel[o.target_kernel_index]
                if isinstance(target_discr, Discretization):
                    result = unflatten(actx, target_discr, result)

                results.append((o.name, result))

        timing_data = {}
        return results, timing_data
예제 #9
0
    def exec_compute_potential_insn_fmm(self, actx: PyOpenCLArrayContext, insn,
                                        bound_expr, evaluate, fmm_driver):
        """
        :arg fmm_driver: A function that accepts four arguments:
            *wrangler*, *strength*, *geo_data*, *kernel*, *kernel_arguments*
        :returns: a tuple ``(assignments, extra_outputs)``, where *assignments*
            is a list of tuples containing pairs ``(name, value)`` representing
            assignments to be performed in the evaluation context.
            *extra_outputs* is data that *fmm_driver* may return
            (such as timing data), passed through unmodified.
        """
        target_name_and_side_to_number, target_discrs_and_qbx_sides = (
            self.get_target_discrs_and_qbx_sides(insn, bound_expr))

        geo_data = self.qbx_fmm_geometry_data(bound_expr.places,
                                              insn.source.geometry,
                                              target_discrs_and_qbx_sides)

        # FIXME Exert more positive control over geo_data attribute lifetimes using
        # geo_data.<method>.clear_cache(geo_data).

        # FIXME Synthesize "bad centers" around corners and edges that have
        # inadequate QBX coverage.

        # FIXME don't compute *all* output kernels on all targets--respect that
        # some target discretizations may only be asking for derivatives (e.g.)

        from pytential import bind, sym
        waa = bind(
            bound_expr.places,
            sym.weights_and_area_elements(self.ambient_dim,
                                          dofdesc=insn.source))(actx)
        densities = [evaluate(density) for density in insn.densities]
        strengths = [waa * density for density in densities]
        flat_strengths = tuple(flatten(strength) for strength in strengths)

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

        output_and_expansion_dtype = (self.get_fmm_output_and_expansion_dtype(
            insn.source_kernels, flat_strengths[0]))
        kernel_extra_kwargs, source_extra_kwargs = (
            self.get_fmm_expansion_wrangler_extra_kwargs(
                actx, insn.target_kernels + insn.source_kernels,
                geo_data.tree().user_source_ids, insn.kernel_arguments,
                evaluate))

        wrangler = self.expansion_wrangler_code_container(
            target_kernels=insn.target_kernels,
            source_kernels=insn.source_kernels).get_wrangler(
                actx.queue,
                geo_data,
                output_and_expansion_dtype,
                self.qbx_order,
                self.fmm_level_to_order,
                source_extra_kwargs=source_extra_kwargs,
                kernel_extra_kwargs=kernel_extra_kwargs,
                _use_target_specific_qbx=self._use_target_specific_qbx)

        from pytential.qbx.geometry import target_state
        if (actx.thaw(geo_data.user_target_to_center()) == target_state.FAILED
            ).any().get():
            raise RuntimeError("geometry has failed targets")

        # {{{ geometry data inspection hook

        if self.geometry_data_inspector is not None:
            perform_fmm = self.geometry_data_inspector(insn, bound_expr,
                                                       geo_data)
            if not perform_fmm:
                return [(o.name, 0) for o in insn.outputs]

        # }}}

        # Execute global QBX.
        all_potentials_on_every_target, extra_outputs = (fmm_driver(
            wrangler, flat_strengths, geo_data, base_kernel,
            kernel_extra_kwargs))

        results = []

        for o in insn.outputs:
            target_side_number = target_name_and_side_to_number[
                o.target_name, o.qbx_forced_limit]
            target_discr, _ = target_discrs_and_qbx_sides[target_side_number]
            target_slice = slice(*geo_data.target_info(
            ).target_discr_starts[target_side_number:target_side_number + 2])

            result = \
                all_potentials_on_every_target[o.target_kernel_index][target_slice]

            from meshmode.discretization import Discretization
            if isinstance(target_discr, Discretization):
                from meshmode.dof_array import unflatten
                result = unflatten(actx, target_discr, result)

            results.append((o.name, result))

        return results, extra_outputs
예제 #10
0
    def exec_compute_potential_insn_fmm(self, actx: PyOpenCLArrayContext,
            insn, bound_expr, evaluate):
        # {{{ gather unique target discretizations used

        target_name_to_index = {}
        targets = []

        for o in insn.outputs:
            assert o.qbx_forced_limit not in (-1, 1)

            if o.target_name in target_name_to_index:
                continue

            target_name_to_index[o.target_name] = len(targets)
            targets.append(bound_expr.places.get_geometry(o.target_name.geometry))

        targets = tuple(targets)

        # }}}

        # {{{ get wrangler

        geo_data = self.fmm_geometry_data(targets)

        from pytential import bind, sym
        waa = bind(bound_expr.places, sym.weights_and_area_elements(
            self.ambient_dim, dofdesc=insn.source))(actx)
        strengths = waa * evaluate(insn.density)

        from meshmode.dof_array import flatten
        flat_strengths = flatten(strengths)

        out_kernels = tuple(knl for knl in insn.kernels)
        fmm_kernel = self.get_fmm_kernel(out_kernels)
        output_and_expansion_dtype = (
                self.get_fmm_output_and_expansion_dtype(fmm_kernel, strengths))
        kernel_extra_kwargs, source_extra_kwargs = (
                self.get_fmm_expansion_wrangler_extra_kwargs(
                    actx, out_kernels, geo_data.tree().user_source_ids,
                    insn.kernel_arguments, evaluate))

        wrangler = self.expansion_wrangler_code_container(
                fmm_kernel, out_kernels).get_wrangler(
                    actx.queue,
                    geo_data.tree(),
                    output_and_expansion_dtype,
                    self.fmm_level_to_order,
                    source_extra_kwargs=source_extra_kwargs,
                    kernel_extra_kwargs=kernel_extra_kwargs)

        # }}}

        from boxtree.fmm import drive_fmm
        all_potentials_on_every_tgt = drive_fmm(
                geo_data.traversal(), wrangler, (flat_strengths,),
                timing_data=None)

        # {{{ postprocess fmm

        results = []

        for o in insn.outputs:
            target_index = target_name_to_index[o.target_name]
            target_slice = slice(*geo_data.target_info().target_discr_starts[
                    target_index:target_index+2])
            target_discr = targets[target_index]

            result = all_potentials_on_every_tgt[o.kernel_index][target_slice]

            from meshmode.discretization import Discretization
            if isinstance(target_discr, Discretization):
                from meshmode.dof_array import unflatten
                result = unflatten(actx, target_discr, result)

            results.append((o.name, result))

        # }}}

        timing_data = {}
        return results, timing_data
예제 #11
0
    def exec_compute_potential_insn_fmm(self, actx: PyOpenCLArrayContext, insn,
                                        bound_expr, evaluate):
        # {{{ gather unique target discretizations used

        target_name_to_index = {}
        targets = []

        for o in insn.outputs:
            assert o.qbx_forced_limit not in (-1, 1)

            if o.target_name in target_name_to_index:
                continue

            target_name_to_index[o.target_name] = len(targets)
            targets.append(
                bound_expr.places.get_geometry(o.target_name.geometry))

        targets = tuple(targets)

        # }}}

        # {{{ get wrangler

        geo_data = self.fmm_geometry_data(targets)

        from pytential import bind, sym
        waa = bind(
            bound_expr.places,
            sym.weights_and_area_elements(self.ambient_dim,
                                          dofdesc=insn.source))(actx)
        strengths = [waa * evaluate(density) for density in insn.densities]

        flat_strengths = [flatten(strength, actx) for strength in strengths]

        fmm_kernel = self.get_fmm_kernel(insn.target_kernels)
        output_and_expansion_dtype = (self.get_fmm_output_and_expansion_dtype(
            insn.target_kernels, strengths[0]))
        kernel_extra_kwargs, source_extra_kwargs = (
            self.get_fmm_expansion_wrangler_extra_kwargs(
                actx, insn.target_kernels + insn.source_kernels,
                geo_data.tree().user_source_ids, insn.kernel_arguments,
                evaluate))

        tree_indep = self._tree_indep_data_for_wrangler(
            fmm_kernel,
            target_kernels=insn.target_kernels,
            source_kernels=insn.source_kernels)

        from sumpy.fmm import SumpyExpansionWrangler
        wrangler = SumpyExpansionWrangler(
            tree_indep,
            geo_data.traversal(),
            output_and_expansion_dtype,
            self.fmm_level_to_order,
            source_extra_kwargs=source_extra_kwargs,
            kernel_extra_kwargs=kernel_extra_kwargs)

        # }}}

        from boxtree.fmm import drive_fmm
        all_potentials_on_every_tgt = drive_fmm(wrangler,
                                                flat_strengths,
                                                timing_data=None)

        # {{{ postprocess fmm

        results = []

        for o in insn.outputs:
            target_index = target_name_to_index[o.target_name]
            target_slice = slice(*geo_data.target_info(
            ).target_discr_starts[target_index:target_index + 2])
            target_discr = targets[target_index]

            result = all_potentials_on_every_tgt[
                o.target_kernel_index][target_slice]

            from meshmode.discretization import Discretization
            if isinstance(target_discr, Discretization):
                template_ary = thaw(target_discr.nodes()[0], actx)
                result = unflatten(template_ary, result, actx, strict=False)

            results.append((o.name, result))

        # }}}

        timing_data = {}
        return results, timing_data
예제 #12
0
    def map_int_g(self, expr):
        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)

        result = 0
        for kernel, density in zip(expr.source_kernels, expr.densities):
            rec_density = self._blk_mapper.rec(density)
            if is_zero(rec_density):
                continue

            if not np.isscalar(rec_density):
                raise NotImplementedError

            # NOTE: copied from pytential.symbolic.primitives.IntG
            base_kernel = kernel.get_base_kernel()
            kernel_args = base_kernel.get_args() + base_kernel.get_source_args(
            )
            kernel_args = {arg.loopy_arg.name for arg in kernel_args}

            actx = self.array_context
            kernel_args = _get_layer_potential_args(actx,
                                                    self.places,
                                                    expr,
                                                    context=self.context,
                                                    include_args=kernel_args)
            if self.exclude_self:
                kernel_args["target_to_source"] = actx.from_numpy(
                    np.arange(0, target_discr.ndofs, dtype=np.int64))

            from pytential.linalg import make_index_blockwise_product
            tgtindices, srcindices = make_index_blockwise_product(
                actx, self.index_set)

            from sumpy.p2p import P2PMatrixSubsetGenerator
            mat_gen = P2PMatrixSubsetGenerator(
                actx.context,
                source_kernels=(base_kernel, ),
                target_kernels=(expr.target_kernel.get_base_kernel(), ),
                exclude_self=self.exclude_self)

            _, (mat, ) = mat_gen(actx.queue,
                                 targets=flatten(target_discr.nodes(),
                                                 actx,
                                                 leaf_class=DOFArray),
                                 sources=flatten(source_discr.nodes(),
                                                 actx,
                                                 leaf_class=DOFArray),
                                 tgtindices=tgtindices,
                                 srcindices=srcindices,
                                 **kernel_args)

            from meshmode.discretization import Discretization
            if self.weighted and isinstance(source_discr, Discretization):
                from pytential import bind, sym
                waa = bind(
                    self.places,
                    sym.weights_and_area_elements(source_discr.ambient_dim,
                                                  dofdesc=expr.source))(actx)
                waa = flatten(waa, actx)

                mat *= waa[srcindices]

            result += actx.to_numpy(mat) * rec_density

        return result
예제 #13
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

        result = 0
        for kernel, density in zip(expr.source_kernels, expr.densities):
            rec_density = self._blk_mapper.rec(density)
            if is_zero(rec_density):
                continue

            if not np.isscalar(rec_density):
                raise NotImplementedError

            actx = self.array_context
            kernel_args = _get_layer_potential_args(actx,
                                                    self.places,
                                                    expr,
                                                    context=self.context)
            local_expn = lpot_source.get_expansion_for_qbx_direct_eval(
                kernel.get_base_kernel(), (expr.target_kernel, ))

            from pytential.linalg import make_index_blockwise_product
            tgtindices, srcindices = make_index_blockwise_product(
                actx, self.index_set)

            from sumpy.qbx import LayerPotentialMatrixSubsetGenerator
            mat_gen = LayerPotentialMatrixSubsetGenerator(
                actx.context,
                local_expn,
                source_kernels=(kernel, ),
                target_kernels=(expr.target_kernel, ))

            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)

            _, (mat, ) = mat_gen(actx.queue,
                                 targets=flatten(target_discr.nodes(),
                                                 actx,
                                                 leaf_class=DOFArray),
                                 sources=flatten(source_discr.nodes(),
                                                 actx,
                                                 leaf_class=DOFArray),
                                 centers=flatten(centers,
                                                 actx,
                                                 leaf_class=DOFArray),
                                 expansion_radii=flatten(radii, actx),
                                 tgtindices=tgtindices,
                                 srcindices=srcindices,
                                 **kernel_args)

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

            result += actx.to_numpy(mat) * rec_density

        return result
예제 #14
0
    def map_int_g(self, expr):
        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)

        result = 0
        for density, kernel in zip(expr.densities, expr.source_kernels):
            rec_density = self.rec(density)
            if is_zero(rec_density):
                continue

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

            # NOTE: copied from pytential.symbolic.primitives.IntG
            base_kernel = kernel.get_base_kernel()
            kernel_args = base_kernel.get_args() + base_kernel.get_source_args(
            )
            kernel_args = {arg.loopy_arg.name for arg in kernel_args}

            actx = self.array_context
            kernel_args = _get_layer_potential_args(actx,
                                                    self.places,
                                                    expr,
                                                    context=self.context,
                                                    include_args=kernel_args)
            if self.exclude_self:
                kernel_args["target_to_source"] = actx.from_numpy(
                    np.arange(0, target_discr.ndofs, dtype=np.int64))

            from sumpy.p2p import P2PMatrixGenerator
            mat_gen = P2PMatrixGenerator(
                actx.context,
                source_kernels=(base_kernel, ),
                target_kernels=(expr.target_kernel.get_base_kernel(), ),
                exclude_self=self.exclude_self)

            _, (mat, ) = mat_gen(actx.queue,
                                 targets=flatten(target_discr.nodes(),
                                                 actx,
                                                 leaf_class=DOFArray),
                                 sources=flatten(source_discr.nodes(),
                                                 actx,
                                                 leaf_class=DOFArray),
                                 **kernel_args)
            mat = actx.to_numpy(mat)

            from meshmode.discretization import Discretization
            if self.weighted and isinstance(source_discr, Discretization):
                from pytential import bind, sym
                waa = bind(
                    self.places,
                    sym.weights_and_area_elements(source_discr.ambient_dim,
                                                  dofdesc=expr.source))(actx)

                mat[:, :] *= actx.to_numpy(flatten(waa, actx))

            result += mat @ rec_density

        return result
예제 #15
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)

        result = 0
        for kernel, density in zip(expr.source_kernels, expr.densities):
            rec_density = self.rec(density)
            if is_zero(rec_density):
                continue

            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_args = _get_layer_potential_args(actx,
                                                    self.places,
                                                    expr,
                                                    context=self.context)
            local_expn = lpot_source.get_expansion_for_qbx_direct_eval(
                kernel.get_base_kernel(), (expr.target_kernel, ))

            from sumpy.qbx import LayerPotentialMatrixGenerator
            mat_gen = LayerPotentialMatrixGenerator(
                actx.context,
                expansion=local_expn,
                source_kernels=(kernel, ),
                target_kernels=(expr.target_kernel, ))

            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)

            _, (mat, ) = mat_gen(actx.queue,
                                 targets=flatten(target_discr.nodes(),
                                                 actx,
                                                 leaf_class=DOFArray),
                                 sources=flatten(source_discr.nodes(),
                                                 actx,
                                                 leaf_class=DOFArray),
                                 centers=flatten(centers,
                                                 actx,
                                                 leaf_class=DOFArray),
                                 expansion_radii=flatten(radii, actx),
                                 **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, actx))

            result += mat @ rec_density

        return result