fmmlib unhappy about empty interaction list
When trying to evaluate a layer potential using fmm_backend='fmmlib'
, if the sibling interaction lists are empty I get an error.
For example, this error appears when evaluating a single layer potential over a unit sphere at target points on an enclosing cube, both of which have rather coarse meshes (see attached files enclosed_sphere.msh and enclosing_cube.msh). Here is the file and error produced (created using reprexpy
):
import numpy as np
import pyopencl as cl
from meshmode.mesh.io import read_gmsh
from meshmode.discretization import Discretization
from meshmode.discretization.poly_element import \
InterpolatoryQuadratureSimplexGroupFactory
cl_ctx = cl.create_some_context()
queue = cl.CommandQueue(cl_ctx)
# Get target
from pytential.target import PointsTarget
target_mesh = read_gmsh('enclosing_cube.msh')
target = PointsTarget(target_mesh.vertices)
# Read mesh and make source discretization
source_mesh = read_gmsh('enclosed_sphere.msh')
ambient_dim = 3
bdry_quad_order = 1
fine_order = 1
qbx_order = 1
fmm_order = 3
pre_density_discr = Discretization(
cl_ctx,
source_mesh,
InterpolatoryQuadratureSimplexGroupFactory(bdry_quad_order))
from pytential.qbx import QBXLayerPotentialSource
# Make qbx -- nb that this bug only appears when fmm_backend='fmmlib' is set
qbx, _ = QBXLayerPotentialSource(
pre_density_discr, fine_order=fine_order, qbx_order=qbx_order,
fmm_order=fmm_order, fmm_backend='fmmlib',
).with_refinement()
#> /home/bensepan/py_proj/inducer/pytential/pytential/symbolic/compiler.py:540: UserWarning: mishandling CSE scope
#> warn("mishandling CSE scope")
density_discr = qbx.density_discr
from pytential import sym, bind
from sumpy.kernel import LaplaceKernel
# Bind layer potential operator
op = sym.S(LaplaceKernel(ambient_dim),
sym.var("sigma"),
qbx_forced_limit=None)
bound_op = bind((qbx, target), op)
sigma = cl.array.to_device(queue, np.zeros(density_discr.nnodes))
bound_op(queue, sigma=sigma)
#> Traceback (most recent call last):
#> ~/py_proj/firedrake-complex/lib/python3.6/site-packages/pytools/__init__.py in wrapper(obj, *args, **kwargs)
#> 581 try:
#> --> 582 return getattr(obj, cache_dict_name)[key]
#> 583 except AttributeError:
#> AttributeError: 'QBXFMMLibExpansionWrangler' object has no attribute '_memoize_dic_m2l_rotation_matrices'
#> During handling of the above exception, another exception occurred:
#> Traceback (most recent call last):
#> <ipython-input-28-b5ab809e6f4a> in <module>
#> ----> 1 bound_op(queue, sigma=sigma)
#> ~/py_proj/inducer/pytential/pytential/symbolic/execution.py in __call__(self, queue, **args)
#> 729 :class:`pyopencl.array.Array`, or an object array of these.
#> 730 """
#> --> 731 return self.eval(queue, args)
#> 732
#> 733
#> ~/py_proj/inducer/pytential/pytential/symbolic/execution.py in eval(self, queue, context, timing_data)
#> 719 exec_mapper = EvaluationMapper(
#> 720 self, queue, context, timing_data=timing_data)
#> --> 721 return self.code.execute(exec_mapper)
#> 722
#> 723 def __call__(self, queue, **args):
#> ~/py_proj/inducer/pytential/pytential/symbolic/compiler.py in execute(self, exec_mapper, pre_assign_check)
#> 390 self.get_exec_function(insn, exec_mapper)
#> 391 (exec_mapper.queue, insn, exec_mapper.bound_expr,
#> --> 392 exec_mapper))
#> 393
#> 394 assignees = insn.get_assignees()
#> ~/py_proj/inducer/pytential/pytential/symbolic/execution.py in exec_compute_potential_insn(self, queue, insn, bound_expr, evaluate)
#> 312 result, timing_data = (
#> 313 source.exec_compute_potential_insn(
#> --> 314 queue, insn, bound_expr, evaluate, return_timing_data))
#> 315
#> 316 if return_timing_data:
#> ~/py_proj/inducer/pytential/pytential/qbx/__init__.py in exec_compute_potential_insn(self, queue, insn, bound_expr, evaluate, return_timing_data)
#> 558
#> 559 return self._dispatch_compute_potential_insn(
#> --> 560 queue, insn, bound_expr, evaluate, func, extra_args)
#> 561
#> 562 def cost_model_compute_potential_insn(self, queue, insn, bound_expr, evaluate):
#> ~/py_proj/inducer/pytential/pytential/qbx/__init__.py in _dispatch_compute_potential_insn(self, queue, insn, bound_expr, evaluate, func, extra_args)
#> 602 extra_args = {}
#> 603
#> --> 604 return func(queue, insn, bound_expr, evaluate, **extra_args)
#> 605
#> 606 @property
#> ~/py_proj/inducer/pytential/pytential/qbx/__init__.py in exec_compute_potential_insn_fmm(self, queue, insn, bound_expr, evaluate, fmm_driver)
#> 736 all_potentials_on_every_target, extra_outputs = (
#> 737 fmm_driver(
#> --> 738 wrangler, strengths, geo_data, fmm_kernel, kernel_extra_kwargs))
#> 739
#> 740 result = []
#> ~/py_proj/inducer/pytential/pytential/qbx/__init__.py in drive_fmm(***failed resolving arguments***)
#> 553 else:
#> 554 timing_data = None
#> --> 555 return drive_fmm(wrangler, strengths, timing_data), timing_data
#> 556
#> 557 extra_args["fmm_driver"] = drive_fmm
#> ~/py_proj/inducer/pytential/pytential/qbx/fmm.py in drive_fmm(expansion_wrangler, src_weights, timing_data, traversal)
#> 463 traversal.from_sep_siblings_starts,
#> 464 traversal.from_sep_siblings_lists,
#> --> 465 mpole_exps)
#> 466
#> 467 recorder.add("multipole_to_local", timing_future)
#> ~/py_proj/firedrake-complex/lib/python3.6/site-packages/pytools/__init__.py in wrapper(*args, **kwargs)
#> 2266 self.logger,
#> 2267 self.description or wrapped.__name__):
#> -> 2268 return wrapped(*args, **kwargs)
#> 2269
#> 2270 from functools import update_wrapper
#> ~/py_proj/inducer/boxtree/boxtree/tools.py in wrapper(*args, **kwargs)
#> 561 def wrapper(*args, **kwargs):
#> 562 timer = ProcessTimer()
#> --> 563 retval = wrapped(*args, **kwargs)
#> 564 timer.done()
#> 565
#> ~/py_proj/inducer/boxtree/boxtree/pyfmmlib_integration.py in multipole_to_local(self, level_start_target_or_target_parent_box_nrs, target_or_target_parent_boxes, starts, lists, mpole_exps)
#> 727 # Precomputed rotation matrices (matrices of larger order can be used
#> 728 # for translations of smaller order)
#> --> 729 rotmatf, rotmatb, rotmat_order = self.m2l_rotation_matrices()
#> 730
#> 731 for lev in range(self.tree.nlevels):
#> ~/py_proj/firedrake-complex/lib/python3.6/site-packages/pytools/__init__.py in wrapper(obj, *args, **kwargs)
#> 582 return getattr(obj, cache_dict_name)[key]
#> 583 except AttributeError:
#> --> 584 result = function(obj, *args, **kwargs)
#> 585 setattr(obj, cache_dict_name, {key: result})
#> 586 return result
#> ~/py_proj/inducer/boxtree/boxtree/pyfmmlib_integration.py in m2l_rotation_matrices(self)
#> 705
#> 706 ier, rotmatf = (
#> --> 707 rotmat_builder(rotmat_order, m2l_rotation_angles))
#> 708 assert (0 == ier).all()
#> 709
#> ValueError: failed to create intent(cache|hide)|optional array-- must have defined dimensions but got (0,)
Created on 2020-02-25 by the reprexpy package
I've attached the python script fmmlib_empty_interaction_list_reprex.py and traceback in case you find this format more helpful.