Skip to content

Commit e133ab6

Browse files
committed
Update notes section
1 parent eaaded1 commit e133ab6

2 files changed

Lines changed: 34 additions & 62 deletions

File tree

pylops_mpi/signalprocessing/FFT2D.py

Lines changed: 17 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -101,47 +101,33 @@ class MPIFFT2D(MPIFFTND):
101101
102102
Notes
103103
-----
104-
The FFT2D operator (using ``norm="none"``) applies the two-dimensional forward
105-
Fourier transform to a signal :math:`d(y, x)` in forward mode:
104+
The MPIFFT2D operator performs forward and adjoint passes on a
105+
:class:`pylops_mpi.DistributedArray`, which is internally reshaped to the 2-dimensional layout
106+
defined by ``dims``. The 2-dimensional FFT is then applied across MPI ranks using ``mpi4py_fft``'s
107+
:class:`mpi4py_fft.mpifft.PFFT` class, with the global array decomposed via a pencil decomposition.
108+
:class:`mpi4py_fft.pencil.Subcomm` selects the axis of distribution: ``axis=0`` by default,
109+
shifting to ``axis=1`` if ``axes[-1] == 0`` to avoid a conflict between the transform and
110+
decomposition axes.
111+
112+
In the forward pass, :meth:`PFFT.forward` is called with ``normalize=False``, computing:
106113
107114
.. math::
108115
D(k_y, k_x) = \mathscr{F} (d) = \iint\limits_{-\infty}^\infty d(y, x) e^{-j2\pi k_yy}
109116
e^{-j2\pi k_xx} \,\mathrm{d}y \,\mathrm{d}x
110117
111-
Similarly, the two-dimensional inverse Fourier transform is applied to
112-
the Fourier spectrum :math:`D(k_y, k_x)` in adjoint mode:
118+
When ``norm="1/n"``, the result is additionally scaled by :math:`1/N_F`.
119+
120+
In the adjoint pass, :meth:`PFFT.backward` is called with ``normalize=True``, so ``PFFT``
121+
internally divides by :math:`N_F = N_1 \cdot N_2`, computing:
113122
114123
.. math::
115124
d(y,x) = \mathscr{F}^{-1} (D) = \frac{1}{N_F} \iint\limits_{-\infty}^\infty D(k_y, k_x) e^{j2\pi k_yy}
116125
e^{j2\pi k_xx} \,\mathrm{d}k_y \,\mathrm{d}k_x
117126
118-
where :math:`N_F` is the number of samples in the Fourier domain given by the
119-
product of the elements of ``nffts``.
120-
121-
Both operators are effectively discretized and solved by a fast iterative
122-
algorithm known as Fast Fourier Transform. Note that when using ``norm="none"``,
123-
the adjoint is **not** the inverse of the forward mode; instead, the inverse
124-
requires an explicit :math:`1/N_F` scaling factor (applied in the adjoint/inverse).
125-
126-
**MPI Parallelization**
127-
128-
The distributed 2-D FFT relies on ``mpi4py_fft``'s
129-
:class:`mpi4py_fft.mpifft.PFFT` (Parallel FFT) class. The global 2-D array is
130-
decomposed across MPI ranks using a *slab decomposition* managed by
131-
:class:`mpi4py_fft.pencil.Subcomm`, which distributes along a single
132-
axis. By default, the input domain is distributed along
133-
``axis=0``; if ``axes[-1] == 0``, distribution shifts to ``axis=1``
134-
to avoid a conflict between the transform and decomposition axes.
135-
136-
In the forward pass, the input is redistributed to match the axis
137-
along which :attr:`fft` (a :class:`mpi4py_fft.mpifft.PFFT` instance)
138-
expects its input, and :meth:`PFFT.forward` is called with
139-
``normalize=False``. In the adjoint pass, :meth:`PFFT.backward` is
140-
called with ``normalize=True``, meaning ``PFFT`` divides by
141-
:math:`N_x N_y` internally. All inter-rank data movement is
142-
handled internally by ``mpi4py_fft``.
143-
144-
127+
When ``norm="none"``, the adjoint multiplies by :math:`N_F` to cancel this internal scaling,
128+
returning a true unscaled adjoint. The result is then flattened back to a 1D
129+
:class:`pylops_mpi.DistributedArray`. All inter-rank data movement is handled internally by
130+
``mpi4py_fft``.
145131
"""
146132
def __init__(
147133
self,

pylops_mpi/signalprocessing/FFTND.py

Lines changed: 17 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)