-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #89 from PyLops/gradient
Add MPIGradient
- Loading branch information
Showing
6 changed files
with
246 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -59,6 +59,7 @@ Derivatives | |
MPIFirstDerivative | ||
MPISecondDerivative | ||
MPILaplacian | ||
MPIGradient | ||
|
||
Solvers | ||
------- | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
from typing import Union | ||
from mpi4py import MPI | ||
import numpy as np | ||
|
||
from pylops import FirstDerivative | ||
from pylops.utils import InputDimsLike, DTypeLike | ||
from pylops.utils._internal import _value_or_sized_to_tuple | ||
|
||
from pylops_mpi import MPIStackedLinearOperator | ||
from pylops_mpi.basicoperators.VStack import MPIStackedVStack | ||
from pylops_mpi.basicoperators.BlockDiag import MPIBlockDiag | ||
from pylops_mpi.basicoperators.FirstDerivative import MPIFirstDerivative | ||
from pylops_mpi.DistributedArray import ( | ||
DistributedArray, | ||
StackedDistributedArray, | ||
Partition, | ||
local_split | ||
) | ||
|
||
|
||
class MPIGradient(MPIStackedLinearOperator): | ||
r"""MPI Gradient | ||
Apply gradient operator to a multi-dimensional distributed | ||
array. | ||
.. note:: At least 2 dimensions are required, use | ||
:py:func:`pylops_mpi.MPIFirstDerivative` for 1d arrays. | ||
Parameters | ||
---------- | ||
dims : :obj:`int` or :obj:`tuple` | ||
Number of samples for each dimension. | ||
sampling : :obj:`int` or :obj:`tuple`, optional | ||
Sampling steps for each direction. | ||
edge : :obj:`bool`, optional | ||
Use reduced order derivative at edges (``True``) or ignore them (``False``). | ||
kind : :obj:`str`, optional | ||
Derivative kind (``forward``, ``centered``, or ``backward``). | ||
base_comm : : obj:`MPI.Comm`, optional | ||
MPI Base Communicator. Defaults to ``mpi4py.MPI.COMM_WORLD``. | ||
dtype : :obj:`str`, optional | ||
Type of elements in input array. | ||
Notes | ||
----- | ||
The MPIGradient operator applies a first-order derivative to each dimension of | ||
a multi-dimensional distributed array in forward mode. | ||
We utilize the :py:class:`pylops_mpi.basicoperators.MPIFirstDerivative` to | ||
calculate the first derivative along the first direction (i.e., axis=0). | ||
For all remaining axes, the :py:class:`pylops.FirstDerivative` operator is | ||
pushed into the :py:class:`pylops_mpi.basicoperators.MPIBlockDiag` operator. | ||
Finally, using the :py:class:`pylops_mpi.basicoperators.MPIStackedVStack` we vertically | ||
stack the :py:class:`pylops_mpi.basicoperators.MPIFirstDerivative` and the | ||
:py:class:`pylops_mpi.basicoperators.MPIBlockDiag` operators. | ||
For the forward mode, the matrix vector product is performed between the | ||
:py:class:`pylops_mpi.basicoperators.MPIStackedVStack` and the :py:class:`pylops_mpi.DistributedArray`. | ||
For simplicity, given a three-dimensional array, the MPIGradient in forward mode using a | ||
centered stencil can be expressed as: | ||
.. math:: | ||
\mathbf{g}_{i, j, k} = | ||
(f_{i+1, j, k} - f_{i-1, j, k}) / d_1 \mathbf{i_1} + | ||
(f_{i, j+1, k} - f_{i, j-1, k}) / d_2 \mathbf{i_2} + | ||
(f_{i, j, k+1} - f_{i, j, k-1}) / d_3 \mathbf{i_3} | ||
In adjoint mode, the adjoint matrix vector product is performed between the | ||
:py:class:`pylops_mpi.basicoperators.MPIStackedVStack` and the :py:class:`pylops_mpi.StackedDistributedArray`. | ||
""" | ||
|
||
def __init__(self, | ||
dims: Union[int, InputDimsLike], | ||
sampling: Union[int, InputDimsLike] = 1, | ||
edge: bool = False, | ||
kind: str = "centered", | ||
base_comm: MPI.Comm = MPI.COMM_WORLD, | ||
dtype: DTypeLike = "float64", | ||
): | ||
self.dims = _value_or_sized_to_tuple(dims) | ||
ndims = len(self.dims) | ||
sampling = _value_or_sized_to_tuple(sampling, repeat=ndims) | ||
self.sampling = sampling | ||
self.edge = edge | ||
self.kind = kind | ||
self.base_comm = base_comm | ||
self.dtype = np.dtype(dtype) | ||
self.Op = self._calc_stack_op(ndims) | ||
super().__init__(shape=self.Op.shape, dtype=dtype, base_comm=base_comm) | ||
|
||
def _matvec(self, x: DistributedArray) -> StackedDistributedArray: | ||
return self.Op._matvec(x) | ||
|
||
def _rmatvec(self, x: StackedDistributedArray) -> DistributedArray: | ||
return self.Op._rmatvec(x) | ||
|
||
def _calc_stack_op(self, ndims): | ||
local_dims = local_split(tuple(self.dims), self.base_comm, Partition.SCATTER, axis=0) | ||
grad_ops = [] | ||
Op1 = MPIFirstDerivative(dims=self.dims, sampling=self.sampling[0], | ||
kind=self.kind, edge=self.edge, | ||
dtype=self.dtype) | ||
grad_ops.append(Op1) | ||
for iax in range(1, ndims): | ||
diag = MPIBlockDiag([ | ||
FirstDerivative( | ||
dims=local_dims, | ||
axis=iax, | ||
sampling=self.sampling[iax], | ||
edge=self.edge, | ||
kind=self.kind, | ||
dtype=self.dtype) | ||
]) | ||
grad_ops.append(diag) | ||
return MPIStackedVStack(ops=grad_ops) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters