def _sumpy_kernel_init(param): name, dim, order = param.name, param.dim, param.order # TODO: add other kernels assert name == "m2l" from sumpy.expansion.multipole import ( LinearPDEConformingVolumeTaylorMultipoleExpansion, ) from sumpy.expansion.local import LinearPDEConformingVolumeTaylorLocalExpansion from sumpy.kernel import LaplaceKernel from sumpy import E2EFromCSR ctx = cl.create_some_context() np.random.seed(17) knl = LaplaceKernel(dim) local_expn_class = LinearPDEConformingVolumeTaylorLocalExpansion mpole_expn_class = LinearPDEConformingVolumeTaylorMultipoleExpansion m_expn = mpole_expn_class(knl, order=order) l_expn = local_expn_class(knl, order=order) m2l = E2EFromCSR(ctx, m_expn, l_expn, name="loopy_kernel") m2l.get_translation_loopy_insns() m2l.ctx = None m2l.device = None return m2l
def m2l(self, src_order, tgt_order): return E2EFromCSR(self.cl_context, self.multipole_expansion(src_order), self.local_expansion(tgt_order))
def get_l2l(self, from_order, to_order): from sumpy import E2EFromCSR return E2EFromCSR( self.cl_context, self.local_expn_class(self.no_target_deriv_kernel, from_order), self.local_expn_class(self.no_target_deriv_kernel, to_order))
def test_translations(ctx_factory, knl, local_expn_class, mpole_expn_class): logging.basicConfig(level=logging.INFO) from sympy.core.cache import clear_cache clear_cache() ctx = ctx_factory() queue = cl.CommandQueue(ctx) np.random.seed(17) res = 20 nsources = 15 out_kernels = [knl] extra_kwargs = {} if isinstance(knl, HelmholtzKernel): extra_kwargs["k"] = 0.05 if isinstance(knl, StokesletKernel): extra_kwargs["mu"] = 0.05 # Just to make sure things also work away from the origin origin = np.array([2, 1, 0][:knl.dim], np.float64) sources = (0.7 * (-0.5 + np.random.rand(knl.dim, nsources).astype(np.float64)) + origin[:, np.newaxis]) strengths = np.ones(nsources, dtype=np.float64) * (1 / nsources) pconv_verifier_p2m2p = PConvergenceVerifier() pconv_verifier_p2m2m2p = PConvergenceVerifier() pconv_verifier_p2m2m2l2p = PConvergenceVerifier() pconv_verifier_full = PConvergenceVerifier() from sumpy.visualization import FieldPlotter eval_offset = np.array([5.5, 0.0, 0][:knl.dim]) centers = ( np.array( [ # box 0: particles, first mpole here [0, 0, 0][:knl.dim], # box 1: second mpole here np.array([-0.2, 0.1, 0][:knl.dim], np.float64), # box 2: first local here eval_offset + np.array([0.3, -0.2, 0][:knl.dim], np.float64), # box 3: second local and eval here eval_offset ], dtype=np.float64) + origin).T.copy() del eval_offset from sumpy.expansion import VolumeTaylorExpansionBase if isinstance(knl, HelmholtzKernel) and \ issubclass(local_expn_class, VolumeTaylorExpansionBase): # FIXME: Embarrassing--but we run out of memory for higher orders. orders = [2, 3] else: orders = [2, 3, 4] nboxes = centers.shape[-1] def eval_at(e2p, source_box_nr, rscale): e2p_target_boxes = np.array([source_box_nr], dtype=np.int32) # These are indexed by global box numbers. e2p_box_target_starts = np.array([0, 0, 0, 0], dtype=np.int32) e2p_box_target_counts_nonchild = np.array([0, 0, 0, 0], dtype=np.int32) e2p_box_target_counts_nonchild[source_box_nr] = ntargets evt, (pot, ) = e2p( queue, src_expansions=mpoles, src_base_ibox=0, target_boxes=e2p_target_boxes, box_target_starts=e2p_box_target_starts, box_target_counts_nonchild=e2p_box_target_counts_nonchild, centers=centers, targets=targets, rscale=rscale, out_host=True, **extra_kwargs) return pot for order in orders: m_expn = mpole_expn_class(knl, order=order) l_expn = local_expn_class(knl, order=order) from sumpy import P2EFromSingleBox, E2PFromSingleBox, P2P, E2EFromCSR p2m = P2EFromSingleBox(ctx, m_expn) m2m = E2EFromCSR(ctx, m_expn, m_expn) m2p = E2PFromSingleBox(ctx, m_expn, out_kernels) m2l = E2EFromCSR(ctx, m_expn, l_expn) l2l = E2EFromCSR(ctx, l_expn, l_expn) l2p = E2PFromSingleBox(ctx, l_expn, out_kernels) p2p = P2P(ctx, out_kernels, exclude_self=False) fp = FieldPlotter(centers[:, -1], extent=0.3, npoints=res) targets = fp.points # {{{ compute (direct) reference solution evt, (pot_direct, ) = p2p(queue, targets, sources, (strengths, ), out_host=True, **extra_kwargs) # }}} m1_rscale = 0.5 m2_rscale = 0.25 l1_rscale = 0.5 l2_rscale = 0.25 # {{{ apply P2M p2m_source_boxes = np.array([0], dtype=np.int32) # These are indexed by global box numbers. p2m_box_source_starts = np.array([0, 0, 0, 0], dtype=np.int32) p2m_box_source_counts_nonchild = np.array([nsources, 0, 0, 0], dtype=np.int32) evt, (mpoles, ) = p2m( queue, source_boxes=p2m_source_boxes, box_source_starts=p2m_box_source_starts, box_source_counts_nonchild=p2m_box_source_counts_nonchild, centers=centers, sources=sources, strengths=(strengths, ), nboxes=nboxes, rscale=m1_rscale, tgt_base_ibox=0, #flags="print_hl_wrapper", out_host=True, **extra_kwargs) # }}} ntargets = targets.shape[-1] pot = eval_at(m2p, 0, m1_rscale) err = la.norm((pot - pot_direct) / res**2) err = err / (la.norm(pot_direct) / res**2) pconv_verifier_p2m2p.add_data_point(order, err) # {{{ apply M2M m2m_target_boxes = np.array([1], dtype=np.int32) m2m_src_box_starts = np.array([0, 1], dtype=np.int32) m2m_src_box_lists = np.array([0], dtype=np.int32) evt, (mpoles, ) = m2m( queue, src_expansions=mpoles, src_base_ibox=0, tgt_base_ibox=0, ntgt_level_boxes=mpoles.shape[0], target_boxes=m2m_target_boxes, src_box_starts=m2m_src_box_starts, src_box_lists=m2m_src_box_lists, centers=centers, src_rscale=m1_rscale, tgt_rscale=m2_rscale, #flags="print_hl_cl", out_host=True, **extra_kwargs) # }}} pot = eval_at(m2p, 1, m2_rscale) err = la.norm((pot - pot_direct) / res**2) err = err / (la.norm(pot_direct) / res**2) pconv_verifier_p2m2m2p.add_data_point(order, err) # {{{ apply M2L m2l_target_boxes = np.array([2], dtype=np.int32) m2l_src_box_starts = np.array([0, 1], dtype=np.int32) m2l_src_box_lists = np.array([1], dtype=np.int32) evt, (mpoles, ) = m2l( queue, src_expansions=mpoles, src_base_ibox=0, tgt_base_ibox=0, ntgt_level_boxes=mpoles.shape[0], target_boxes=m2l_target_boxes, src_box_starts=m2l_src_box_starts, src_box_lists=m2l_src_box_lists, centers=centers, src_rscale=m2_rscale, tgt_rscale=l1_rscale, #flags="print_hl_cl", out_host=True, **extra_kwargs) # }}} pot = eval_at(l2p, 2, l1_rscale) err = la.norm((pot - pot_direct) / res**2) err = err / (la.norm(pot_direct) / res**2) pconv_verifier_p2m2m2l2p.add_data_point(order, err) # {{{ apply L2L l2l_target_boxes = np.array([3], dtype=np.int32) l2l_src_box_starts = np.array([0, 1], dtype=np.int32) l2l_src_box_lists = np.array([2], dtype=np.int32) evt, (mpoles, ) = l2l( queue, src_expansions=mpoles, src_base_ibox=0, tgt_base_ibox=0, ntgt_level_boxes=mpoles.shape[0], target_boxes=l2l_target_boxes, src_box_starts=l2l_src_box_starts, src_box_lists=l2l_src_box_lists, centers=centers, src_rscale=l1_rscale, tgt_rscale=l2_rscale, #flags="print_hl_wrapper", out_host=True, **extra_kwargs) # }}} pot = eval_at(l2p, 3, l2_rscale) err = la.norm((pot - pot_direct) / res**2) err = err / (la.norm(pot_direct) / res**2) pconv_verifier_full.add_data_point(order, err) for name, verifier in [ ("p2m2p", pconv_verifier_p2m2p), ("p2m2m2p", pconv_verifier_p2m2m2p), ("p2m2m2l2p", pconv_verifier_p2m2m2l2p), ("full", pconv_verifier_full), ]: print(30 * "-") print(name) print(30 * "-") print(verifier) print(30 * "-") verifier()