def eval_direct(self, target_boxes, neighbor_sources_starts, neighbor_sources_lists, src_weights): pot = self.potential_zeros() from pyfmmlib import hpotgrad2dall_vec for itgt_box, tgt_ibox in enumerate(target_boxes): tgt_pslice = self._get_target_slice(tgt_ibox) if tgt_pslice.stop - tgt_pslice.start == 0: continue tgt_result = np.zeros(tgt_pslice.stop - tgt_pslice.start, np.complex128) start, end = neighbor_sources_starts[itgt_box:itgt_box+2] for src_ibox in neighbor_sources_lists[start:end]: src_pslice = self._get_source_slice(src_ibox) if src_pslice.stop - src_pslice.start == 0: continue tmp_pot, _, _ = hpotgrad2dall_vec( ifgrad=False, ifhess=False, sources=self._get_sources(src_pslice), charge=src_weights[src_pslice], targets=self._get_targets(tgt_pslice), zk=self.helmholtz_k) tgt_result += tmp_pot pot[tgt_pslice] = tgt_result return pot
def eval_direct(self, target_boxes, neighbor_sources_starts, neighbor_sources_lists, src_weights): pot = self.potential_zeros() from pyfmmlib import hpotgrad2dall_vec for itgt_box, tgt_ibox in enumerate(target_boxes): tgt_pslice = self._get_target_slice(tgt_ibox) if tgt_pslice.stop - tgt_pslice.start == 0: continue tgt_result = np.zeros(tgt_pslice.stop - tgt_pslice.start, np.complex128) start, end = neighbor_sources_starts[itgt_box:itgt_box + 2] for src_ibox in neighbor_sources_lists[start:end]: src_pslice = self._get_source_slice(src_ibox) if src_pslice.stop - src_pslice.start == 0: continue tmp_pot, _, _ = hpotgrad2dall_vec( ifgrad=False, ifhess=False, sources=self._get_sources(src_pslice), charge=src_weights[src_pslice], targets=self._get_targets(tgt_pslice), zk=self.helmholtz_k) tgt_result += tmp_pot pot[tgt_pslice] = tgt_result return pot
def test_pyfmmlib_fmm(ctx_getter): logging.basicConfig(level=logging.INFO) from pytest import importorskip importorskip("pyfmmlib") ctx = ctx_getter() queue = cl.CommandQueue(ctx) nsources = 3000 ntargets = 1000 dims = 2 dtype = np.float64 helmholtz_k = 2 sources = p_normal(queue, nsources, dims, dtype, seed=15) targets = ( p_normal(queue, ntargets, dims, dtype, seed=18) + np.array([2, 0])) sources_host = particle_array_to_host(sources) targets_host = particle_array_to_host(targets) from boxtree import TreeBuilder tb = TreeBuilder(ctx) tree, _ = tb(queue, sources, targets=targets, max_particles_in_box=30, debug=True) from boxtree.traversal import FMMTraversalBuilder tbuild = FMMTraversalBuilder(ctx) trav, _ = tbuild(queue, tree, debug=True) trav = trav.get(queue=queue) from pyopencl.clrandom import PhiloxGenerator rng = PhiloxGenerator(queue.context, seed=20) weights = rng.uniform(queue, nsources, dtype=np.float64).get() #weights = np.ones(nsources) logger.info("computing direct (reference) result") from pyfmmlib import hpotgrad2dall_vec ref_pot, _, _ = hpotgrad2dall_vec(ifgrad=False, ifhess=False, sources=sources_host.T, charge=weights, targets=targets_host.T, zk=helmholtz_k) from boxtree.pyfmmlib_integration import Helmholtz2DExpansionWrangler wrangler = Helmholtz2DExpansionWrangler(trav.tree, helmholtz_k, nterms=10) from boxtree.fmm import drive_fmm pot = drive_fmm(trav, wrangler, weights) rel_err = la.norm(pot - ref_pot) / la.norm(ref_pot) logger.info("relative l2 error: %g" % rel_err) assert rel_err < 1e-5
def test_translations(): nterms = 15 zk = 3 rscale = 1 n = 40 # centered at the origin, extent [-.5,.5] sources = np.random.uniform(size=(n, 2)) - 0.5 charges = np.random.uniform(size=n) targets_center = np.array([10, 0]) targets = np.random.uniform(size=(n, 2)) - 0.5 + targets_center from pyfmmlib import (h2dformmp, h2dmpmp_vec, h2dmploc_vec, h2dlocloc_vec, h2dtaeval_vec, hpotgrad2dall_vec, h2dmpeval_vec) ref_value, _, _ = hpotgrad2dall_vec(ifgrad=False, ifhess=False, sources=sources.T, charge=charges, targets=targets.T, zk=zk) # {{{ multipole 1 mp1_center = np.array([0, 0]) ier, mp1 = h2dformmp(zk, rscale, sources.T, charges, mp1_center, nterms) assert ier == 0 mp1_value, _, _ = h2dmpeval_vec(zk, rscale, mp1_center, mp1, ztarg=targets.T, ifgrad=False, ifhess=False) assert la.norm(mp1_value - ref_value) / la.norm(ref_value) < 1e-12 # }}} # {{{ multipole 2 mp2_center = np.array([2, 0]) mp2 = h2dmpmp_vec(zk, rscale, mp1_center, mp1, rscale, mp2_center, nterms) mp2_value, _, _ = h2dmpeval_vec(zk, rscale, mp2_center, mp2, ztarg=targets.T, ifgrad=False, ifhess=False) assert la.norm(mp2_value - ref_value) / la.norm(ref_value) < 3e-5 # }}} # {{{ local 1 loc1_center = targets_center - np.array([1, 0]) loc1 = h2dmploc_vec(zk, rscale, mp2_center, mp2, rscale, loc1_center, nterms) loc1_value, _, _ = h2dtaeval_vec(zk, rscale, loc1_center, loc1, ztarg=targets.T, ifgrad=False, ifhess=False) assert la.norm(loc1_value - ref_value) / la.norm(ref_value) < 3e-5 # }}} # {{{ local 2 loc2_center = targets_center loc2 = h2dlocloc_vec(zk, rscale, loc1_center, loc1, rscale, loc2_center, nterms) loc2_value, _, _ = h2dtaeval_vec(zk, rscale, loc2_center, loc2, ztarg=targets.T, ifgrad=False, ifhess=False) assert la.norm(loc2_value - ref_value) / la.norm(ref_value) < 1e-4
def test_pyfmmlib_fmm(ctx_getter): logging.basicConfig(level=logging.INFO) from pytest import importorskip importorskip("pyfmmlib") ctx = ctx_getter() queue = cl.CommandQueue(ctx) nsources = 3000 ntargets = 1000 dims = 2 dtype = np.float64 helmholtz_k = 2 sources = p_normal(queue, nsources, dims, dtype, seed=15) targets = (p_normal(queue, ntargets, dims, dtype, seed=18) + np.array([2, 0])) sources_host = particle_array_to_host(sources) targets_host = particle_array_to_host(targets) from boxtree import TreeBuilder tb = TreeBuilder(ctx) tree, _ = tb(queue, sources, targets=targets, max_particles_in_box=30, debug=True) from boxtree.traversal import FMMTraversalBuilder tbuild = FMMTraversalBuilder(ctx) trav, _ = tbuild(queue, tree, debug=True) trav = trav.get(queue=queue) from pyopencl.clrandom import RanluxGenerator rng = RanluxGenerator(queue, seed=20) weights = rng.uniform(queue, nsources, dtype=np.float64).get() #weights = np.ones(nsources) logger.info("computing direct (reference) result") from pyfmmlib import hpotgrad2dall_vec ref_pot, _, _ = hpotgrad2dall_vec(ifgrad=False, ifhess=False, sources=sources_host.T, charge=weights, targets=targets_host.T, zk=helmholtz_k) from boxtree.pyfmmlib_integration import Helmholtz2DExpansionWrangler wrangler = Helmholtz2DExpansionWrangler(trav.tree, helmholtz_k, nterms=10) from boxtree.fmm import drive_fmm pot = drive_fmm(trav, wrangler, weights) rel_err = la.norm(pot - ref_pot) / la.norm(ref_pot) logger.info("relative l2 error: %g" % rel_err) assert rel_err < 1e-5