# FMM driver¶

boxtree.fmm.drive_fmm(traversal, expansion_wrangler, src_weights, timing_data=None)

Top-level driver routine for a fast multipole calculation.

In part, this is intended as a template for custom FMMs, in the sense that you may copy and paste its source code as a starting point.

Nonetheless, many common applications (such as point-to-point FMMs) can be covered by supplying the right expansion_wrangler to this routine.

Parameters: traversal – A boxtree.traversal.FMMTraversalInfo instance. expansion_wrangler – An object exhibiting the ExpansionWranglerInterface. src_weights – Source ‘density/weights/charges’. Passed unmodified to expansion_wrangler. timing_data – Either None, or a dict that is populated with timing information for the stages of the algorithm (in the form of TimingResult), if such information is available.

Returns the potentials computed by expansion_wrangler.

class boxtree.fmm.ExpansionWranglerInterface

Abstract expansion handling interface for use with drive_fmm().

See this test code for a very simple sample implementation.

Will usually hold a reference (and thereby be specific to) a boxtree.Tree instance.

Functions that support returning timing data return a value supporting the TimingFuture interface.

Changed in version 2018.1: Changed (a subset of) functions to return timing data.

multipole_expansion_zeros()

Return an expansions array (which must support addition) capable of holding one multipole or local expansion for every box in the tree.

local_expansion_zeros()

Return an expansions array (which must support addition) capable of holding one multipole or local expansion for every box in the tree.

output_zeros()

Return a potentials array (which must support addition) capable of holding a potential value for each target in the tree. Note that drive_fmm() makes no assumptions about potential other than that it supports addition–it may consist of potentials, gradients of the potential, or arbitrary other per-target output data.

reorder_sources(source_array)

Return a copy of source_array in tree source order. source_array is in user source order.

reorder_potentials(potentials)

Return a copy of potentials in user target order. source_weights is in tree target order.

form_multipoles(level_start_source_box_nrs, source_boxes, src_weights)

Return an expansions array (compatible with multipole_expansion_zeros()) containing multipole expansions in source_boxes due to sources with src_weights. All other expansions must be zero.

Returns: A pair (mpoles, timing_future).
coarsen_multipoles(level_start_source_parent_box_nrs, source_parent_boxes, mpoles)

For each box in source_parent_boxes, gather (and translate) the box’s children’s multipole expansions in mpole and add the resulting expansion into the box’s multipole expansion in mpole.

Returns: A pair (mpoles, timing_future).
eval_direct(target_boxes, neighbor_sources_starts, neighbor_sources_lists, src_weights)

For each box in target_boxes, evaluate the influence of the neighbor sources due to src_weights, which use CSR-like interaction list storage and are indexed like target_boxes.

Returns: A pair (pot, timing_future), where pot is a a new potential array, see output_zeros().
multipole_to_local(level_start_target_or_target_parent_box_nrs, target_or_target_parent_boxes, starts, lists, mpole_exps)

For each box in target_or_target_parent_boxes, translate and add the influence of the multipole expansion in mpole_exps into a new array of local expansions. starts and lists use CSR-like interaction list storage, and starts is indexed like target_or_target_parent_boxes.

Returns: A pair (pot, timing_future) where pot is a new (local) expansion array, see local_expansion_zeros().
eval_multipoles(target_boxes_by_source_level, from_sep_smaller_by_level, mpole_exps)

For a level i, each box in target_boxes_by_source_level[i], evaluate the multipole expansion in mpole_exps in the nearby boxes given in from_sep_smaller_by_level, and return a new potential array. starts and lists in from_sep_smaller_by_level[i] use CSR-like interaction list storage and starts is indexed like target_boxes_by_source_level[i].

Returns: A pair (pot, timing_future) where pot is a new potential array, see output_zeros().
form_locals(level_start_target_or_target_parent_box_nrs, target_or_target_parent_boxes, starts, lists, src_weights)

For each box in target_or_target_parent_boxes, form local expansions due to the sources in the nearby boxes given in starts and lists, and return a new local expansion array. starts and lists use CSR-like interaction list storage and starts is indexed like target_or_target_parent_boxes.

Returns: A pair (pot, timing_future) where pot is a new local expansion array, see local_expansion_zeros().
refine_locals(level_start_target_or_target_parent_box_nrs, target_or_target_parent_boxes, local_exps)

For each box in child_boxes, translate the box’s parent’s local expansion in local_exps and add the resulting expansion into the box’s local expansion in local_exps.

Returns: A pair (local_exps, timing_future).
eval_locals(level_start_target_box_nrs, target_boxes, local_exps)

For each box in target_boxes, evaluate the local expansion in local_exps and return a new potential array.

Returns: A pair (pot, timing_future) where pot is a new potential array, see output_zeros().
finalize_potentials(potentials)

Postprocess the reordered potentials. This is where global scaling factors could be applied. This is distinct from reorder_potentials() because some derived FMMs (notably the QBX FMM) do their own reordering.

class boxtree.fmm.TimingResult(*args, **kwargs)

Interface for returned timing data.

This supports accessing timing results via a mapping interface, along with combining results via merge().

merge(other)

Merge this result with another by adding together common fields.

See constructor for dict.

class boxtree.fmm.TimingFuture

Returns timing data for a potentially asynchronous operation.

result()

Return a TimingResult. May block.

done()

Return True if the operation is complete.

## Integration with PyFMMLib¶

Integrates boxtree with pyfmmlib.

class boxtree.pyfmmlib_integration.FMMLibExpansionWrangler(tree, helmholtz_k, fmm_level_to_nterms=None, ifgrad=False, dipole_vec=None, dipoles_already_reordered=False, nterms=None)

Implements the boxtree.fmm.ExpansionWranglerInterface by using pyfmmlib.

Timing results returned by this wrangler contains the values wall_elapsed and (optionally, if supported) process_elapsed, which measure wall time and process time in seconds, respectively.

Parameters: fmm_level_to_nterms – a callable that, upon being passed the tree and the tree level as an integer, returns the value of nterms for the multipole and local expansions on that level.