Skip to content

qten.geometries.fourier

Module reference for qten.geometries.fourier.

fourier

Fourier-transform helpers connecting finite real-space and momentum-space geometry.

This module provides the Fourier phase-factor machinery used to move between discrete momentum points and finite real-space offsets in QTen. Its core role is to build the finite Fourier kernel associated with a bounded lattice and to package that kernel into Tensor objects whose legs are labeled by the repository's symbolic MomentumSpace and HilbertSpace objects.

Two related APIs are defined here:

  • fourier_kernel computes the raw phase matrix \(\exp(-\mathrm{i}\, k \cdot r)\) for momentum points and real-space offsets.
  • fourier_transform lifts that kernel into a labeled (K, B, R) tensor that maps a region basis into a Bloch basis.
  • region_restrict rebuilds an existing Fourier-transform tensor on a different real-space region while preserving the momentum and Bloch-space structure.

The implementation follows the repository's reciprocal-lattice convention: Momentum.to_vec() already uses Cartesian reciprocal coordinates containing the \(2\pi\) factor induced by Lattice.dual. As a result, the Fourier phase is evaluated as \(\exp(-\mathrm{i}\, k_{\mathrm{cart}}\cdot r_{\mathrm{cart}})\), which is equivalent to \(\exp(-2\pi\mathrm{i}\,\kappa\cdot n)\) in fractional direct/reciprocal coordinates. In code, the exponent is assembled from the Cartesian arrays as -1j * torch.matmul(ten_K, ten_R).

In matrix form, the sampled kernel has entries \(K_{\alpha\beta} = \exp(-\mathrm{i}\, k_\alpha \cdot r_\beta) = \exp(-2\pi\mathrm{i}\, \kappa_\alpha \cdot n_\beta)\).

Repository usage

This module sits at the junction of geometry and tensor assembly:

  • Finite-region Hilbert spaces contribute the real-space offsets whose phases are sampled against a discrete MomentumSpace.
  • Bloch-space labeling is recovered through mapping_matrix, allowing the raw Fourier kernel to be embedded into a tensor with explicit symbolic legs.
  • Region-changing workflows can rebuild the rightmost real-space leg without modifying the momentum grid or Bloch labeling by calling region_restrict.
Notes

The functions in this module assume a finite sampled momentum set and a finite real-space region supplied by the surrounding geometry/symbolics layers. They therefore implement the discrete Fourier transform conventions used by the repository's bounded-lattice workflows rather than a continuum transform API.

fourier_kernel

fourier_kernel(
    K: tuple[Momentum, ...],
    R: tuple[Offset, ...],
    *,
    device: Optional[Device] = None,
) -> torch.Tensor

Compute the raw discrete Fourier kernel for momentum points and offsets.

Momentum.to_vec() uses the reciprocal basis, which already carries the \(2\pi\) convention via Lattice.dual, so the phase is computed as \(\exp(-\mathrm{i}\, k_{\mathrm{cart}}\cdot r_{\mathrm{cart}})\). Equivalently, in fractional coordinates this is \(\exp(-2\pi\mathrm{i}\,\kappa\cdot n)\). In code this is the torch.exp of -1j * torch.matmul(ten_K, ten_R).

The returned matrix is \(K_{\alpha\beta} = \exp(-\mathrm{i}\, k_\alpha \cdot r_\beta)\).

Parameters:

Name Type Description Default
K Tuple[Momentum, ...]

Momentum points for the raw-kernel form fourier_kernel(K, R).

required
R Tuple[Offset, ...]

Real-space offsets for the raw-kernel form fourier_kernel(K, R).

required

Returns:

Type Description
Tensor

Complex tensor of shape (len(K), len(R)) with elements \(\exp(-\mathrm{i}\, k_{\mathrm{cart}}\cdot r_{\mathrm{cart}})\) (equivalently \(\exp(-2\pi\mathrm{i}\,\kappa\cdot n)\) in fractional coordinates).

Source code in src/qten/geometries/fourier.py
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
def fourier_kernel(
    K: Tuple[Momentum, ...], R: Tuple[Offset, ...], *, device: Optional[Device] = None
) -> torch.Tensor:
    r"""
    Compute the raw discrete Fourier kernel for momentum points and offsets.

    `Momentum.to_vec()` uses the reciprocal basis, which already carries the
    \(2\pi\) convention via `Lattice.dual`, so the phase is computed as
    \(\exp(-\mathrm{i}\, k_{\mathrm{cart}}\cdot r_{\mathrm{cart}})\).
    Equivalently, in fractional coordinates this is
    \(\exp(-2\pi\mathrm{i}\,\kappa\cdot n)\).
    In code this is the `torch.exp` of `-1j * torch.matmul(ten_K, ten_R)`.

    The returned matrix is
    \(K_{\alpha\beta} = \exp(-\mathrm{i}\, k_\alpha \cdot r_\beta)\).

    Parameters
    ----------
    K : Tuple[Momentum, ...]
        Momentum points for the raw-kernel form
        [`fourier_kernel(K, R)`][qten.geometries.fourier.fourier_kernel].
    R : Tuple[Offset, ...]
        Real-space offsets for the raw-kernel form
        [`fourier_kernel(K, R)`][qten.geometries.fourier.fourier_kernel].

    Returns
    -------
    torch.Tensor
        Complex tensor of shape `(len(K), len(R))` with elements
        \(\exp(-\mathrm{i}\, k_{\mathrm{cart}}\cdot r_{\mathrm{cart}})\)
        (equivalently \(\exp(-2\pi\mathrm{i}\,\kappa\cdot n)\) in
        fractional coordinates).
    """
    precision = get_precision_config()
    torch_device = device.torch_device() if device is not None else None

    # Batch-extract K Cartesian coordinates via numpy matrix multiply
    # instead of per-element sympy to_vec calls.
    k_space = K[0].space
    k_dim = k_space.dim
    k_basis_np = np.array(k_space.basis.evalf(), dtype=precision.np_float)
    k_frac = np.array(
        [[float(k.rep[j, 0]) for j in range(k_dim)] for k in K],
        dtype=precision.np_float,
    )
    ten_K = torch.from_numpy(k_frac @ k_basis_np.T).to(  # (K, d)
        device=torch_device
    )

    ten_R = torch.from_numpy(  # (d, R)
        np.stack(
            [
                np.array(
                    (r - r.fractional()).to_vec(np.ndarray), dtype=precision.np_float
                ).reshape(-1)
                for r in R
            ],
            axis=1,
        )
    ).to(device=torch_device)
    # `ten_K` is already in Cartesian reciprocal coordinates (includes 2π),
    # so multiplying by `2π` here would double count the phase.
    exponent = -1j * torch.matmul(ten_K, ten_R)  # (K, R)
    return torch.exp(exponent)  # (K, R)

fourier_transform

fourier_transform(
    k_space: MomentumSpace,
    bloch_space: HilbertSpace,
    region_space: HilbertSpace,
    *,
    device: Optional[Device] = None,
) -> Tensor

Build the labeled Fourier transform tensor for symbolic Hilbert spaces.

This function is the high-level symbolic wrapper around fourier_kernel. It enumerates momentum points from k_space, collects real-space offsets from region_space, evaluates the raw Fourier kernel, and maps region modes into bloch_space with mapping_matrix.

Parameters:

Name Type Description Default
k_space MomentumSpace

Momentum space defining the k points.

required
bloch_space HilbertSpace

Bloch space to map region modes into.

required
region_space HilbertSpace

Real-space region defining offsets.

required

Returns:

Type Description
Tensor

Tensor with data shape (K, B, R) and dims (k_space, bloch_space, region_space).

See Also

fourier_kernel Low-level Fourier phase matrix used internally by this function.

Source code in src/qten/geometries/fourier.py
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
def fourier_transform(
    k_space: MomentumSpace,
    bloch_space: HilbertSpace,
    region_space: HilbertSpace,
    *,
    device: Optional[Device] = None,
) -> Tensor:
    """
    Build the labeled Fourier transform tensor for symbolic Hilbert spaces.

    This function is the high-level symbolic wrapper around
    [`fourier_kernel`][qten.geometries.fourier.fourier_kernel]. It enumerates
    momentum points from `k_space`, collects real-space offsets from
    `region_space`, evaluates the raw Fourier kernel, and maps region modes
    into `bloch_space` with
    [`mapping_matrix`][qten.linalg.tensors.mapping_matrix].

    Parameters
    ----------
    k_space : MomentumSpace
        Momentum space defining the k points.
    bloch_space : HilbertSpace
        Bloch space to map region modes into.
    region_space : HilbertSpace
        Real-space region defining offsets.

    Returns
    -------
    Tensor
        Tensor with data shape `(K, B, R)` and dims
        (k_space, bloch_space, region_space).

    See Also
    --------
    [`fourier_kernel`][qten.geometries.fourier.fourier_kernel]
        Low-level Fourier phase matrix used internally by this function.
    """
    K: Tuple[Momentum, ...] = k_space.elements()
    R: Tuple[Offset, ...] = tuple(
        cast(U1Basis, el).irrep_of(Offset) for el in region_space.elements()
    )
    f = fourier_kernel(K, R, device=device)  # (K, R)

    region_to_bloch: Dict[U1Basis, U1Basis] = matchby(
        region_space,
        bloch_space,
        lambda psi: _bloch_key(cast(U1Basis, psi)),
    )

    map = mapping_matrix(
        region_space, bloch_space, region_to_bloch, device=device
    ).transpose(0, 1)  # (B, R)
    # (K, 1, R) * (1, B, R)
    f = f.to(map.data.device).unsqueeze(1) * map.data.unsqueeze(0)
    return Tensor(data=f, dims=(k_space, bloch_space, region_space))  # (K, B, R)

region_restrict

region_restrict(
    tensor: Tensor,
    R: HilbertSpace,
    *,
    side: Literal["left", "right"] = "left",
    device: Optional[Device] = None,
) -> Tensor
region_restrict(
    tensor: Tensor,
    region: tuple[Offset, ...],
    *,
    side: Literal["left", "right"] = "left",
    device: Optional[Device] = None,
) -> Tensor

Rebuild a Fourier transform tensor on a different real-space region.

Supported forms

region_restrict(tensor, R) Rebuild the Fourier transform tensor on the target real-space HilbertSpace R, reusing the momentum and Bloch spaces from tensor.

region_restrict(tensor, region) Accept a tuple of Offset values, construct the corresponding real-space HilbertSpace via region_hilbert, then rebuild the transform on that region. Here region means the target finite real-space region written explicitly as an ordered tuple of offsets, for example (r0, r1, r2), rather than as a preconstructed HilbertSpace.

Parameters:

Name Type Description Default
tensor Tensor

Fourier transform tensor with dims (MomentumSpace, HilbertSpace, HilbertSpace), or a rank-3 tensor whose leading dim is a MomentumBlockSpace.

required
R HilbertSpace

Target real-space region used as the new rightmost dimension for the form region_restrict(tensor, R).

required
side Literal['left', 'right']

Which Fourier-transform side to sample from tensor. side="left" uses tensor.dims[1]; side="right" uses tensor.dims[2]. If the leading dim is a MomentumBlockSpace, the corresponding unique momentum projection is used: MomentumBlockSpace.left() for side="left" and MomentumBlockSpace.right() for side="right". The default is "left".

'left'
device Optional[Device]

Device on which to construct the rebuilt transform.

None

Returns:

Type Description
Tensor

Plain Fourier transform tensor with dims (K, B, R) where B is taken from the selected Hilbert leg of tensor and K is either the leading MomentumSpace or the side-selected unique projection of a leading MomentumBlockSpace.

Raises:

Type Description
ValueError

If tensor is not rank 3.

TypeError

If the side-selected dims of tensor are not MomentumSpace/MomentumBlockSpace and HilbertSpace, respectively.

Notes

The generated API docs for this module show overload signatures, but the prose is rendered from this public implementation docstring. The overload accepting a tuple of Offset first converts that tuple into a HilbertSpace and then dispatches here. In that overload, region is the explicit tuple of target real-space offsets.

When the input tensor has a leading MomentumBlockSpace, this function still returns a plain Fourier Tensor. The block-pair axis is projected to a unique MomentumSpace using the side selected by side, which makes the result suitable for products such as F @ MBT or MBT @ F.h(...).

Source code in src/qten/geometries/fourier.py
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
@multimethod
def region_restrict(
    tensor: Tensor,
    R: HilbertSpace,
    *,
    side: Literal["left", "right"] = "left",
    device: Optional[Device] = None,
) -> Tensor:
    """
    Rebuild a Fourier transform tensor on a different real-space region.

    Supported forms
    ---------------
    [`region_restrict(tensor, R)`][qten.geometries.fourier.region_restrict]
        Rebuild the Fourier transform tensor on the target real-space
        [`HilbertSpace`][qten.symbolics.hilbert_space.HilbertSpace] `R`,
        reusing the momentum and Bloch spaces from `tensor`.

    [`region_restrict(tensor, region)`][qten.geometries.fourier.region_restrict]
        Accept a tuple of
        [`Offset`][qten.geometries.spatials.Offset] values, construct the
        corresponding real-space
        [`HilbertSpace`][qten.symbolics.hilbert_space.HilbertSpace] via
        [`region_hilbert`][qten.symbolics.ops.region_hilbert], then rebuild
        the transform on that region. Here `region` means the target finite
        real-space region written explicitly as an ordered tuple of offsets,
        for example `(r0, r1, r2)`, rather than as a preconstructed
        [`HilbertSpace`][qten.symbolics.hilbert_space.HilbertSpace].

    Parameters
    ----------
    tensor : Tensor
        Fourier transform tensor with dims
        `(MomentumSpace, HilbertSpace, HilbertSpace)`, or a rank-3 tensor whose
        leading dim is a
        [`MomentumBlockSpace`][qten.symbolics.state_space.MomentumBlockSpace].
    R : HilbertSpace
        Target real-space region used as the new rightmost dimension for the
        form [`region_restrict(tensor, R)`][qten.geometries.fourier.region_restrict].
    side : Literal["left", "right"], optional
        Which Fourier-transform side to sample from `tensor`.
        `side="left"` uses `tensor.dims[1]`; `side="right"` uses
        `tensor.dims[2]`. If the leading dim is a
        [`MomentumBlockSpace`][qten.symbolics.state_space.MomentumBlockSpace],
        the corresponding unique momentum projection is used:
        [`MomentumBlockSpace.left()`][qten.symbolics.state_space.MomentumBlockSpace.left]
        for `side="left"` and
        [`MomentumBlockSpace.right()`][qten.symbolics.state_space.MomentumBlockSpace.right]
        for `side="right"`. The default is `"left"`.
    device : Optional[Device], optional
        Device on which to construct the rebuilt transform.

    Returns
    -------
    Tensor
        Plain Fourier transform tensor with dims `(K, B, R)` where `B` is
        taken from the selected Hilbert leg of `tensor` and `K` is either the
        leading [`MomentumSpace`][qten.symbolics.state_space.MomentumSpace] or
        the side-selected unique projection of a leading
        [`MomentumBlockSpace`][qten.symbolics.state_space.MomentumBlockSpace].

    Raises
    ------
    ValueError
        If `tensor` is not rank 3.
    TypeError
        If the side-selected dims of `tensor` are not
        `MomentumSpace`/`MomentumBlockSpace` and `HilbertSpace`,
        respectively.

    Notes
    -----
    The generated API docs for this module show overload signatures, but the
    prose is rendered from this public implementation docstring. The overload
    accepting a tuple of [`Offset`][qten.geometries.spatials.Offset] first
    converts that tuple into a
    [`HilbertSpace`][qten.symbolics.hilbert_space.HilbertSpace] and then
    dispatches here. In that overload, `region` is the explicit tuple of
    target real-space offsets.

    When the input tensor has a leading
    [`MomentumBlockSpace`][qten.symbolics.state_space.MomentumBlockSpace], this
    function still returns a plain Fourier
    [`Tensor`][qten.linalg.tensors.Tensor]. The block-pair axis is projected to
    a unique [`MomentumSpace`][qten.symbolics.state_space.MomentumSpace] using
    the side selected by `side`, which makes the result suitable for products
    such as `F @ MBT` or `MBT @ F.h(...)`.
    """
    K, B = _region_restrict_spaces(tensor, side)
    return fourier_transform(K, B, R, device=device)