Transporter - Parallel Transport with MPI Halo Exchange
This module provides parallel transport operations for lattice gauge theory. Unlike stencils (which are local), transporters handle MPI communication for accessing neighbors across rank boundaries.
Key concepts:
- Shifter: Shift fields in a direction (no gauge link multiplication)
- Transporter: Parallel transport with gauge link multiplication (covariant)
- HaloBuffer: Communication buffers for boundary exchange
Design Philosophy:
- Explicit direction handling with compile-time safety
- Support for forward (+) and backward (-) transport
- Covariant derivatives: D_μ ψ = (U_μ(x) ψ(x+μ) - ψ(x)) / a
- AoSoA-aware for SIMD vectorization
- Multi-device and MPI compatible
Example usage:
# Create shifters for all directions let shifters = newShifters(field, len=1) # Shift field forward in direction 0 let shifted = shifters[0] ^* field # Create transporters with gauge links let transporters = newTransporters(gaugeField, field, len=1) # Parallel transport: U_μ(x) * ψ(x+μ) let transported = transporters[0] ^* field # Covariant derivative in direction μ let Dpsi = covariantDerivative(gaugeField, psi, mu)
Inspired by QEX's transporters but with a cleaner API for LGT.
Types
CovariantDerivativeDir = enum cdForward, cdBackward, cdSymmetric
- Direction type for covariant derivative
HaloRegion[D] = object dim*: int direction*: int thickness*: int localGeom*: array[D, int] lo*: array[D, int] hi*: array[D, int] nSites*: int
- Description of a halo region for communication
ShiftDir = object dim*: int len*: int
- Direction and displacement for shifting/transport
Shifter[D; T] = object dim*: int len*: int indices*: ShiftIndices[D] sendBuf*: seq[T] recvBuf*: seq[T]
-
Shifter for moving fields in a direction
Handles MPI communication for boundary sites. Use ^* operator to apply: shifted = shifter ^* field
ShiftIndices[D] = object dim*: int len*: int localGeom*: array[D, int] nSites*: int localIdx*: seq[int32] isLocal*: seq[bool] sendSites*: seq[int32] recvSites*: seq[int32] nSendSites*: int nRecvSites*: int
-
Pre-computed indices for a shift operation
For each local site, stores where to get the shifted value:
Transporter[D; U; F] = object dim*: int len*: int indices*: ShiftIndices[D] link*: ptr U sendBuf*: seq[F] recvBuf*: seq[F]
-
Transporter for gauge-covariant field shifting
Multiplies by gauge link during transport:
- Forward: U_μ(x) * ψ(x+μ)
- Backward: U_μ(x-μ)†* ψ(x-μ)
TransportPattern[D] = object stencil*: Stencil[D] shiftIndices*: seq[ShiftIndices[D]]
-
A pattern of transport operations
Combines stencil geometry with gauge link information for efficient multi-direction transport.
Procs
proc applyShiftLocal[D: static int; T](shifter: Shifter[D, T]; source: openArray[T]; dest: var openArray[T])
-
Apply shift operation (local sites only, no MPI)
For sites that need data from other ranks, uses periodic wrapping within the local domain (single-rank mode).
proc backwardShiftIdx(pattern: TransportPattern; dim: int): int {.inline.}
- Get index of backward shift indices for dimension dim
proc covariantShiftBackward[T](gaugeLinkShifted: T; psiShifted: T): T {.inline.}
-
Backward covariant shift: U_μ(x-μ)†* ψ(x-μ)
Note: gaugeLinkShifted should already be the adjoint of U_μ(x-μ)
proc covariantShiftForward[T](gaugeLink: T; psiShifted: T): T {.inline.}
-
Forward covariant shift: U_μ(x) * ψ(x+μ)
This is the basic building block for covariant derivatives and Wilson-Dirac operators.
proc forwardShiftIdx(pattern: TransportPattern; dim: int): int {.inline.}
- Get index of forward shift indices for dimension dim
proc newBackwardShifters[D: static int; T](localGeom: array[D, int]; len: int = 1): array[D, Shifter[D, T]]
- Create backward shifters for all D directions
proc newHaloRegion[D: static int](dim: int; direction: int; thickness: int; localGeom: array[D, int]): HaloRegion[D]
- Create a halo region description
proc newShifter[D: static int; T](localGeom: array[D, int]; dim: int; len: int = 1): Shifter[D, T]
- Create a shifter for the given direction and length
proc newShifters[D: static int; T](localGeom: array[D, int]; len: int = 1): array[ D, Shifter[D, T]]
- Create shifters for all D directions
proc newShiftIndices[D: static int](dim: int; len: int; localGeom: array[D, int]): ShiftIndices[ D]
-
Create pre-computed shift indices
For shift in dimension dim by len sites. Positive len = forward shift (access site at x+len) Negative len = backward shift (access site at x-len)
proc newTransporter[D: static int; U, F](localGeom: array[D, int]; gaugeField: ptr U; dim: int; len: int = 1): Transporter[D, U, F]
- Create a transporter for the given direction
proc newTransportPattern[D: static int](localGeom: array[D, int]; len: int = 1): TransportPattern[ D]
- Create transport pattern for nearest-neighbor transport
Exports
-
newLatticeStencil, newLatticeStencil, UseOpenCL, LatticeStencil, newLatticeStencil, nLanes, Y, pathToStencil, addPoint, fwd, ==, localToPadded, newStencilView, backward, hash, nPoints, newLatticeStencil, idx, Z, bwd, $, $, directions, $, shift, allDirections, neighborOffset, offsetBufferSize, rectanglePath, forEachNeighbor, addPoint, nearestNeighborStencil, paddedToLocal, bwd, forwardStencil, VectorWidth, neighborSimd, Stencil, nearestNeighborStencil, StencilPattern, laplacianStencil, Direction, nOuter, SignedDirection, backwardStencil, StencilEntry, StencilPoint, neighbor, step, newLatticeStencil, T, plaquettePath, StencilBackend, paddedToLocal, forwardStencil, fwd, backwardStencil, forward, points, laplacianStencil, getEntry, newStencilPattern, UseSYCL, newStencilPoint, X, getOffsetBuffer, $, localToPadded, shift, StencilShift, StencilView, nSites, newStencil, neighbors, newStencilPoint, addPoint, isGhostNeighbor, PathStep, sites, UseOpenMP