pmesh.domain module

Domain Decomposition in Gaepsi

currently we have a GridND decomposition algorithm.

A few concepts:

  • local and ghost. A data entry is local if it is stored on the current rank. A data entry is ghost if it is stored on another rank.
  • primary and padding. A spatial position is primary if it is within the spatial boundary the current rank. If it is not, then it is in the padding region, which is determined by the smoothing parameter of decompose. If it is further out, there must have been an error.

local and primary are not necessarily the same set of entries.

class pmesh.domain.GridND(edges, comm=<mpi4py.MPI.Intracomm object>, periodic=True, DomainAssign=None)[source]

Bases: object

GridND is domain decomposition on a uniform grid of N dimensions.

The total number of domains is prod([ len(dir) - 1 for dir in edges]).

Attributes:
edges : list (Ndim)

A list of edges of the edges in each dimension. edges[i] is the edges on direction i. edges[i] includes 0 and BoxSize.

comm : MPI.Comm

MPI Communicator, default is MPI.COMM_WORLD

periodic : boolean

Is the domain decomposition periodic? If so , edges[i][-1] is the period.

decompose(pos, smoothing=0, transform=None)[source]

Decompose particles into domains.

Create a decomposition layout for particles at pos.

Parameters:
pos : array_like (, ndim)

position of particles, ndim can be more than the dimenions of the domains, in which case only the first few directions are used.

smoothing : float, or array_like

Smoothing of particles. Any particle that intersects a domain will be transported to the domain. Smoothing is in the coordinate system of the edges. if array_like, smoothing per dimension.

transform : callable

Apply the transformation on pos before the decompostion. transform(pos[:, 3]) -> domain_pos[:, 3] transform is needed if pos and the domain edges are of different units. For example, pos in physical simulation units and domain edges on a mesh unit.

Returns:
layout : Layout object that can be used to exchange data
isprimary(pos, transform=None)[source]
Returns a boolean, True if the position falls into the primary region
of the current rank.
Parameters:
pos : array_like (, ndim)

position of particles, ndim can be more than the dimenions of the domains, in which case only the first few directions are used.

Returns:
isprimary: array_like, boolean. Whether the position falls into

the primary region of the rank.

load(pos, transform=None, gamma=2)[source]

Returns the load of each domain, assuming that the load is a power-law N^gamma, where N is the number of particles within it.

Parameters:
pos : array_like (, ndim)

position of particles, ndim can be more than the dimenions of the domains, in which case only the first few directions are used.

Returns:
domainload : array_like

The load of each domain.

loadbalance(domainload)[source]

Balancing the load of different ranks given the load of each domain. The result is recorded in self.DomainAssign.

Parameters:
domainload : array_like

The load of each domain. Can be calculated from self.load()

classmethod uniform(BoxSize, comm=<mpi4py.MPI.Intracomm object>, periodic=True)[source]
class pmesh.domain.Layout(comm, oldlength, sendcounts, indices, recvcounts=None)[source]

Bases: object

The communication layout of a domain decomposition.

Given a set of particles, Layout object knows how to move particles around. Do not create a Layout object directly. Always use GridND.decompose().

Useful methods are exchange(), and gather().

exchange(data)[source]

Deliever data to the intersecting domains.

Parameters:
data : array_like (, extra_dimensions)

The data to be delievered. It shall be of the same length and of the same ordering of the input position that builds the layout. Each element is a matching element of the position used in the call to GridND.decompose()

Returns:
newdata : array_like

The data delievered to the domain. Ghosts are created if a particle intersects multiple domains. Refer to gather() for collecting data of ghosts.

gather(data, mode='sum', out=None)[source]

Pull the data from other ranks back to its original hosting rank.

Returns:
gathered : array_like

gathered data. It is of the same length and ordering of the original positions used in domain.decompose(). When mode is ‘all’, all gathered particles (corresponding to self.indices) are returned.

Attributes:
data : array_like

data for each received particles.

mode : string ‘sum’, ‘any’, ‘mean’, ‘all’, ‘local’, or any numpy ufunc.

'all' is to return all results, local and ghosts, without any reduction 'sum' is to reduce the ghosts to the local with sum. 'local' is to remove ghosts, keeping only local 'any' is to reduce the ghosts to the local, by using any one local or ghost 'mean' is to reduce the ghosts, to use the mean (sum divided by the total number) any numpy.ufunc is to reduce the ghosts, with the ufunc. ‘sum’ is equivalent to numpy.ufunc.add

out : array_like or None

stores the result of the gather operation.

pmesh.domain.bincountv(x, weights, minlength=None, dtype=None, out=None)[source]

bincount with vector weights

pmesh.domain.promote(data, comm)[source]