qlat.field_analysis — Field Smearing, Sphere Summation, and Convolution

Source: qlat/qlat/field_analysis.py

Note: Update this document when updating the source file.

Outline

  1. Overview

  2. Shift Index Utilities

  3. Step-Based Smearing

  4. Momentum-Space Kernels

  5. Fourier-Based Operations

  6. Examples


Overview

field_analysis provides utilities for analysing and transforming lattice fields using Fourier-transform techniques. The main capabilities are:

  • Gaussian smearing — smear a density or observable field in coordinate space via multiplication in momentum space. Both 4D and spatial-only variants are supported.

  • Sphere summation — sum field values within a Euclidean-distance radius using an FFT-based convolution.

  • Field convolution — compute the cross-correlation of two complex fields via FFT.

  • Step-based smearing — iterative nearest-neighbour smearing that converges to a Gaussian for many steps. Both a local (single-node) and a distributed variant are provided.

All Fourier operations use qlat.mk_fft and exploit the convolution theorem: convolution in coordinate space equals pointwise multiplication in momentum space.


Shift Index Utilities

mk_shift_xg_idx_arr

mk_shift_xg_idx_arr(total_site: tuple, xg_shift: tuple) -> np.ndarray

Build an index array that maps each site to the site shifted by xg_shift (with periodic boundary conditions). Only works when the field lives on a single MPI node (no communication).

Parameter

Type

Description

total_site

tuple[int, ...]

Lattice dimensions, e.g. (4, 4, 4, 8)

xg_shift

tuple[int, ...]

Shift in each direction

Returns an integer np.ndarray of shape (total_volume,) suitable for advanced indexing: field[shift_idx] yields the shifted field.

Results are cached (up to 16 entries).


Step-Based Smearing

smear_field_step_local

smear_field_step_local(field: Field, coef: float, n_steps: int = 1) -> Field

Iterative nearest-neighbour smearing using local index arrays (no MPI communication). At each step, the field value at each site is mixed with the average of its 8 nearest neighbours (positive and negative shifts in all 4 directions).

Parameter

Type

Default

Description

field

Field

Input field (at least complex type)

coef

float

Smearing coefficient (0 = no smearing, 1 = full average)

n_steps

int

1

Number of smearing iterations

Returns a new field; the input is not modified.

Note: Requires geo.num_node() == 1.

smear_field_step

smear_field_step(field: Field, coef: float, n_steps: int = 1) -> Field

Distributed variant of nearest-neighbour smearing. Uses field.shift() which supports MPI communication. The smearing kernel is identical to smear_field_step_local.

Returns a new field; the input is not modified.


Momentum-Space Kernels

mk_smear_mom_kernel

mk_smear_mom_kernel(total_site: tuple, radius: float) -> FieldRealD

Build the 4D Gaussian smearing kernel in momentum space:

\[G(k) = \exp\!\Bigl(-\frac{r^2}{4}\sum_{\mu=0}^{3}\sin^2\!\frac{k_\mu}{2}\Bigr)\]

where \(k_\mu = 2\pi n_\mu / L_\mu\).

If radius == np.inf, the kernel is a delta function at \(k = 0\).

Results are cached (up to 128 entries).

mk_spatial_smear_mom_kernel

mk_spatial_smear_mom_kernel(total_site: tuple, radius: float) -> FieldRealD

Build the spatial-only Gaussian smearing kernel:

\[G(k) = \exp\!\Bigl(-\frac{2r^2}{3}\sum_{i=0}^{2}\sin^2\!\frac{k_i}{2}\Bigr)\]

The temporal direction is not smeared. If radius == np.inf, the kernel selects the spatial zero mode.

Results are cached (up to 128 entries).

mk_sphere_sum_mom_kernel

mk_sphere_sum_mom_kernel(
    total_site: tuple,
    radius: float,
    is_only_spatial: bool,
) -> FieldRealD

Build the momentum-space kernel for sphere summation. In coordinate space this corresponds to a sharp cutoff: sum all sites within Euclidean distance radius. The kernel is constructed by FFT of a real-space indicator function.

If radius == np.inf, every site contributes equally.

Results are cached (up to 128 entries).


Fourier-Based Operations

sphere_sum_field

sphere_sum_field(
    field: Field,
    radius: float,
    *,
    is_only_spatial: bool = False,
) -> Field

Approximate sphere summation of a field via FFT convolution:

\[f_{\text{sphere-summed}}(x) \approx \sum_y \theta(|x-y| < r)\, f(y)\]

The field must be at least complex type. The result is normalised so that the sum approximates a spherical average.

smear_field

smear_field(
    field: Field,
    radius: float,
    *,
    is_only_spatial: bool = False,
) -> Field

Gaussian-smear a field in momentum space and return the result.

\[f_{\text{smear}}(x) \approx \frac{\sum_y f(y)\,\exp\!\bigl(-(x-y)^2/(2r^2)\bigr)} {\sum_y \exp\!\bigl(-y^2/(2r^2)\bigr)}\]

The field must be at least complex type. If is_only_spatial is True, only the three spatial directions are smeared.

field_convolution

field_convolution(
    f1: FieldComplexD,
    f2: FieldComplexD,
    idx1: np.ndarray = None,
    idx2: np.ndarray = None,
    *,
    is_only_spatial: bool = False,
) -> FieldComplexD

Compute the cross-correlation of two complex fields via FFT:

\[\text{ff}[x_g] = \sum_{x} f_2(x + x_g,\, \text{idx2}) \cdot f_1(x,\, \text{idx1})\]

Parameter

Type

Default

Description

f1

FieldComplexD

First field

f2

FieldComplexD

Second field (must have same total_site)

idx1

np.ndarray or None

None

Multiplicity indices for f1; defaults to all

idx2

np.ndarray or None

None

Multiplicity indices for f2; defaults to all

is_only_spatial

bool

False

If True, convolve only in spatial directions

idx1 and idx2 must have the same length. The result has multiplicity len(idx1).


Examples

Gaussian Smearing via FFT

import qlat as q
import numpy as np

size_node_list = [
    [1, 1, 1, 1],
]

q.begin_with_mpi(size_node_list)

total_site = q.Coordinate([4, 4, 4, 8])
geo = q.Geometry(total_site)

f = q.FieldComplexD(geo, 1)
f.set_zero()
f[0] = np.array([1.0 + 0.0j])

smeared = q.smear_field(f, radius=2.0)
print(f"Smeared field sum = {np.asarray(smeared).sum().real:.6f}")

q.end_with_mpi()

Sphere Summation

import qlat as q
import numpy as np

size_node_list = [
    [1, 1, 1, 1],
]

q.begin_with_mpi(size_node_list)

total_site = q.Coordinate([4, 4, 4, 8])
geo = q.Geometry(total_site)

f = q.FieldComplexD(geo, 1)
f.set_zero()
f[0] = np.array([1.0 + 0.0j])

summed = q.sphere_sum_field(f, radius=3.0)
print(f"Sphere-summed field sum = {np.asarray(summed).sum().real:.6f}")

q.end_with_mpi()

Step-Based Smearing (Single Node)

import qlat as q
import numpy as np

size_node_list = [
    [1, 1, 1, 1],
]

q.begin_with_mpi(size_node_list)

total_site = q.Coordinate([4, 4, 4, 8])
geo = q.Geometry(total_site)

f = q.FieldComplexD(geo, 1)
f.set_zero()
f[0] = np.array([1.0 + 0.0j])

smeared = q.smear_field_step_local(f, coef=0.5, n_steps=10)
print(f"Step-smeared field sum = {np.asarray(smeared).sum().real:.6f}")

q.end_with_mpi()

Field Convolution

import qlat as q
import numpy as np

size_node_list = [
    [1, 1, 1, 1],
]

q.begin_with_mpi(size_node_list)

total_site = q.Coordinate([4, 4, 4, 8])
geo = q.Geometry(total_site)

f1 = q.FieldComplexD(geo, 1)
f1.set_zero()
f1[0] = np.array([1.0 + 0.0j])

f2 = q.FieldComplexD(geo, 1)
f2.set_zero()
f2[0] = np.array([1.0 + 0.0j])

ff = q.field_convolution(f1, f2)
print(f"Convolution result at origin = {np.asarray(ff)[0]}")

q.end_with_mpi()