SparseFunction

SparseFunction(self, *args, **kwargs)

Tensor symbol representing a sparse array in symbolic equations.

A SparseFunction carries multi-dimensional data that are not aligned with the computational grid. As such, each data value is associated some coordinates. A SparseFunction provides symbolic interpolation routines to convert between Functions and sparse data points. These are based upon standard [bi,tri]linear interpolation.

Parameters

Name Type Description Default
name str Name of the symbol. required
npoint int Number of sparse points. required
grid Grid The computational domain from which the sparse points are sampled. required
coordinates numpy.numpy.ndarray The coordinates of each sparse point. required
space_order int Discretisation order for space derivatives. 0
shape tuple of ints Shape of the object. (npoint,)
dimensions tuple of Dimension Dimensions associated with the object. Only necessary if the SparseFunction defines a multi-dimensional tensor. required
dtype devito.data - type Any object that can be interpreted as a numpy data type. np.float32
initializer callable or any object exposing the buffer interface Data initializer. If a callable is provided, data is allocated lazily. None
allocator MemoryAllocator Controller for memory allocation. To be used, for example, when one wants to take advantage of the memory hierarchy in a NUMA architecture. Refer to default_allocator.__doc__ for more information. required

Examples

Creation

>>> from devito import Grid, SparseFunction
>>> grid = Grid(shape=(4, 4))
>>> sf = SparseFunction(name='sf', grid=grid, npoint=2)
>>> sf
sf(p_sf)

Inspection

>>> sf.data
Data([0., 0.], dtype=float32)
>>> sf.coordinates
sf_coords(p_sf, d)
>>> sf.coordinates_data
array([[0., 0.],
       [0., 0.]], dtype=float32)

Symbolic interpolation routines

>>> from devito import Function
>>> f = Function(name='f', grid=grid)
>>> exprs0 = sf.interpolate(f)
>>> exprs1 = sf.inject(f, sf)

Notes

The parameters must always be given as keyword arguments, since SymPy uses *args to (re-)create the Dimension arguments of the symbolic object. About SparseFunction and MPI. There is a clear difference between:

* Where the sparse points *physically* live, i.e., on which MPI rank. This
  depends on the user code, particularly on how the data is set up.
* and which MPI rank *logically* owns a given sparse point. The logical
  ownership depends on where the sparse point is located within ``self.grid``.

Right before running an Operator (i.e., upon a call to op.apply), a SparseFunction “scatters” its physically owned sparse points so that each MPI rank gets temporary access to all of its logically owned sparse points. A “gather” operation, executed before returning control to user-land, updates the physically owned sparse points in self.data by collecting the values computed during op.apply from different MPI ranks.

Attributes

Name Description
is_SparseFunction bool(x) -> bool
Back to top