Lattice field theory in modern C++.
A header-only C++20 Template Lattice framework. Write the physics as mathematical expressions — TempLat compiles it into fused kernels and runs it on CPU threads, NVIDIA and AMD GPUs, and across thousands of MPI ranks. Same source, any machine.
Features
Built for the physics, not the plumbing.
TempLat is the computational core behind CosmoLattice. It handles all the background tasks, memory, devices, halos and FFTs, while your code stays close to the equations.
Expressions, not loops
The energy density $\mathcal{e} = \tfrac12\pi^2 + \tfrac12(\nabla\phi)^2 + \tfrac12m^2\phi^2$ of a Klein-Gordon field, using TempLat's vocabulary:
auto expression = 0.5 * pow<2>(pi) + 0.5 * Grad2(phi) + 0.5 * m2 * pow<2>(phi);
TempLat builds the actual loop over the lattice for you. Expression templates fuse the whole right-hand side into one kernel — no temporaries, no hand-written indices, and deep optimization at compile time.
One source, any device
TempLat builds on Kokkos for shared-memory parallelism performance portability. TempLat supports CUDA, HIP, OpenMP, C++ threads or serial execution. TempLat automatically detects what your machine provides; override auto-detection easily via CMake flags.
Scales from your laptop to exascale clusters
Automatic domain decomposition across any number of MPI nodes, with ghost cells exchanged automatically when an expression needs it — GPU/NVLink-aware where the interconnect allows it.
Distributed FFTs
Parallel transforms through ParaFaFT, with support for CPU and multi-GPU. FFTW3 and KokkosFFT on a single node. Automatically dispatches FFTs when expressions operate in Fourier space.
Gauge fields included
SU(2) and U(1) link algebras, complex and matrix algebras, plaquettes, covariant and spatial derivatives, coordinate and momentum-space views — all as first-class expression types.
Output and measurements
Parallel HDF5 snapshots, measurement tools, projectors, spectra, a parameter-file reader and a rank-aware logger. The scaffolding around a simulation, already written.
How to use
Three steps to a running lattice simulation.
TempLat is header-only. You need CMake ≥ 3.16 and a C++20 compiler — clang,
g++ or equivalent. There is nothing to install: CMake fetches and configures it inside your own
build.
Add it to your CMake project
FetchContent downloads TempLat and builds it as part of your project. Link your executable
against TempLat::TempLat and every include path, definition and dependency comes with it.
cmake_minimum_required(VERSION 3.16) project(my_project LANGUAGES CXX) include(FetchContent) set(FETCHCONTENT_QUIET ON) FetchContent_Declare(TempLat GIT_REPOSITORY https://github.com/cosmolattice/templat.git GIT_TAG main) FetchContent_MakeAvailable(TempLat) # Add your executable and link it against TempLat add_executable(my_executable main.cpp) target_link_libraries(my_executable PRIVATE TempLat::TempLat)
Write your first program
SessionGuard brings up MPI and the device backend and tears them down again when it goes out
of scope. MemoryToolBox owns the lattice geometry — here a 128³ grid with one layer of ghost
cells — and every Field built from it shares that decomposition. The assignment is a single
fused kernel: a scalar plus a Gaussian random configuration, evaluated once per site. average
reduces over the whole lattice, across all ranks, and sayMPI prints once from rank 0 with a
timestamp and source location.
#include "TempLat.h" int main(int argc, char *argv[]) { using namespace TempLat; SessionGuard guard(argc, argv); auto toolBox = MemoryToolBox<3>::makeShared(128, 1); Field<double, 3> phi("phi", toolBox); phi = 2 + RandomGaussianFieldConfig<double, 3>("seed", toolBox); const double result = average(phi); sayMPI << "Hello, TempLat! <phi> = " << result << "\n"; return 0; };
mkdir build && cd build cmake .. make -j ./my_executable
(0.000s) Using FFTW backend for FFTs. (0.000s) MPI Rank 0 - memorytoolbox.h:209 --> Using the following domain decomposition:(1 1 1 ). (0.086s) MPI Rank 0 - main.cpp:15 --> Hello, TempLat! <phi> = 1.99973
The mean comes back at 1.99973 rather than exactly 2 because the Gaussian noise averages to zero only up to the sampling error of a finite lattice.
Pick your backend
The hardware and software you build for is chosen when you configure your project — for example
cmake -DMPI=ON -DHDF5=ON .. — so there is nothing to configure inside TempLat itself. Leave
the device flags off and it auto-detects: GPU first (CUDA, then HIP), then OpenMP, then C++ threads, then
serial.
| Flag | What it enables | Default |
|---|---|---|
| MPI | Distributed runs across ranks | OFF |
| CUDA | NVIDIA GPUs (needs the CUDA toolkit or NVHPC SDK) | OFF |
| HIP | AMD GPUs — also set CXX=hipcc |
OFF |
| OPENMP | OpenMP CPU parallelisation | OFF |
| PARAFAFT | ParaFaFT parallel FFTs | $MPI |
| HDF5 | Parallel HDF5 output | OFF |
| TEMPLAT_TEST | Build TempLat's own test suite for ctest |
OFF |
Offline compilation for a cluster architecture, the runtime environment variables and the full flag table are explained in the README ↗. Testing is documented in TEST.md ↗.
Paper & citation
If TempLat helped your work, please cite it.
TempLat is developed by researchers. Citations are what make that sustainable.
TODO — paper title fill in
TODO — journal, volume, page (year) · arXiv:TODO
@article{TempLat,
author = "TODO",
title = "{TODO}",
eprint = "TODO",
archivePrefix = "arXiv",
primaryClass = "hep-ph",
doi = "TODO",
journal = "TODO",
volume = "TODO",
pages = "TODO",
year = "TODO"
}
TempLat grew out of, and powers, CosmoLattice. If you used it through CosmoLattice, please cite that code as well: arXiv:2102.01031.
People
Who builds TempLat.
TempLat is developed as part of the CosmoLattice project.
Franz R. Sattler
Bielefeld University, Germany
Contributors
Jorge Baeza-Ballesteros
DESY, Zeuthen, Germany
Wessel Valkenburg
Enjoying la vida loca out of academia