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