@@ -110,9 +110,15 @@ class MPIFFTND(_MPIBaseFFTND):
110110
111111 Notes
112112 -----
113- The MPIFFTND operator (using ``norm="none"``) applies the N-dimensional forward
114- Fourier transform to a multidimensional array. Considering an N-dimensional
115- signal :math:`d(x_1, \ldots, x_N)`. The MPIFFTND in forward mode is:
113+ The MPIFFTND operator performs forward and adjoint passes on a
114+ :class:`pylops_mpi.DistributedArray`, which is internally reshaped to the N-dimensional layout
115+ defined by ``dims``. The N-dimensional FFT is then applied across MPI ranks using ``mpi4py_fft``'s
116+ :class:`mpi4py_fft.mpifft.PFFT` class, with the global array decomposed via a pencil decomposition.
117+ :class:`mpi4py_fft.pencil.Subcomm` selects the axis of distribution: ``axis=0`` by default,
118+ shifting to ``axis=1`` if ``axes[-1] == 0`` to avoid a conflict between the transform and
119+ decomposition axes.
120+
121+ In the forward pass, :meth:`PFFT.forward` is called with ``normalize=False``, computing:
116122
117123 .. math::
118124 D(k_1, \ldots, k_N) = \mathscr{F} (d) =
@@ -121,8 +127,10 @@ class MPIFFTND(_MPIBaseFFTND):
121127 e^{-j2\pi k_1 x_1} \cdots
122128 e^{-j 2 \pi k_N x_N} \,\mathrm{d}x_1 \cdots \mathrm{d}x_N
123129
124- Similarly, the N-dimensional inverse Fourier transform is applied to
125- the Fourier spectrum :math:`D(k_1, \ldots, k_N)` in adjoint mode:
130+ When ``norm="1/n"``, the result is additionally scaled by :math:`1/N_F`.
131+
132+ In the adjoint pass, :meth:`PFFT.backward` is called with ``normalize=True``, so ``PFFT``
133+ internally divides by :math:`N_F = \prod_i N_i`, computing:
126134
127135 .. math::
128136 d(x_1, \ldots, x_N) = \mathscr{F}^{-1} (D) = \frac{1}{N_F}
@@ -131,32 +139,10 @@ class MPIFFTND(_MPIBaseFFTND):
131139 e^{j2\pi k_1 x_1} \cdots
132140 e^{j 2 \pi k_N x_N} \,\mathrm{d}k_1 \cdots \mathrm{d}k_N
133141
134- where :math:`N_F` is the number of samples in the Fourier domain given by the
135- product of the elements of ``nffts``.
136-
137- Both operators are effectively discretized and solved by a fast iterative
138- algorithm known as Fast Fourier Transform. Note that when using ``norm="none"``,
139- the adjoint is **not** the inverse of the forward mode; instead, the inverse
140- requires an explicit :math:`1/N_F` scaling factor (applied in the adjoint/inverse).
141-
142- **MPI Parallelization**
143-
144- The distributed N-dimensional FFT relies on ``mpi4py_fft``'s
145- :class:`mpi4py_fft.mpifft.PFFT` (Parallel FFT) class. The global array is
146- decomposed across MPI ranks using a *pencil decomposition* managed by
147- :class:`mpi4py_fft.pencil.Subcomm`, which distributes along a single
148- axis at a time. By default, the input domain is distributed along
149- ``axis=0``; if ``axes[-1] == 0``, distribution shifts to ``axis=1``
150- to avoid a conflict between the transform and decomposition axes.
151-
152- In the forward pass, the input is redistributed to match the axis
153- along which :attr:`fft` (a :class:`mpi4py_fft.mpifft.PFFT` instance)
154- expects its input, and :meth:`PFFT.forward` is called with
155- ``normalize=False``. In the adjoint pass, :meth:`PFFT.backward` is
156- called with ``normalize=True``, meaning ``PFFT`` divides by
157- :math:`N_F` internally. All inter-rank data movement (pencil transfer) is
158- handled internally by ``mpi4py_fft``.
159-
142+ When ``norm="none"``, the adjoint multiplies by :math:`N_F` to cancel this internal scaling,
143+ returning a true unscaled adjoint. The result is then flattened back to a 1D
144+ :class:`pylops_mpi.DistributedArray`. All inter-rank data movement is handled internally by
145+ ``mpi4py_fft``.
160146 """
161147 def __init__ (
162148 self ,
0 commit comments