Solves the 2D wave equation on a square domain with zero boundary conditions. Uses implicit time stepping with a Gauss-Seidel iterative solver, parallelized via MPI 2D Cartesian domain decomposition.
# 1. Install MPI (Ubuntu/Debian)
sudo apt install libopenmpi-dev
# or (Arch)
sudo pacman -S openmpi
# 2. Download the prebuilt tensogram C library (from GitHub releases)
make tensogram
# 3. Create the Python venv and install tensogram from PyPI
make py-setup
# 4. Build and run (16 MPI ranks by default)
make runmake alone will also build everything; the separate targets above just
make the two one-time installation steps visible.
The project uses a Makefile with configurable variables:
| Variable | Default | Description |
|---|---|---|
NP |
16 |
Number of MPI ranks (must be a perfect square) |
VENV |
.venv |
Python virtualenv directory (auto-used if present) |
PYTHON |
$(VENV)/bin/python3 or python3 |
Python interpreter for visualization scripts |
SKIP |
10 |
Frame skip for GIF generation |
FRAME |
150 |
Frame index for static benchmark plots |
FILE |
bench_raw.tgm |
Input file for viz/viz-save targets |
NETCDF |
0 |
Set to 1 to link NetCDF |
TGM_VERSION |
0.21.0 |
Tensogram release to download |
make # Build wave.x (auto-downloads tensogram if needed)
make tensogram # Download + unpack the prebuilt tensogram C library
make py-setup # Create .venv and pip install tensogram, numpy, matplotlib, Pillow
make run # Build + run simulation
make bench # Full pipeline: run + plots + gifs (sequential)
make plots # Static benchmark PNGs (comparison + errors)
make gifs # Animated GIF per codec
make viz # Interactive visualizer (default: bench_raw.tgm)
make viz-save # Save visualizer output as GIF
make print-tgm # Debug: show resolved tensogram paths
make clean # Remove wave.x
make distclean # Remove wave.x + outputs + .tensogram + venvOverride any variable: make run NP=4, make gifs SKIP=5, make viz FILE=bench_zstd-3.tgm.
Makefile Build, run, and visualization targets
waveEq.c Main solver (MPI topology, Gauss-Seidel, time loop)
config.h Simulation parameters and output toggles
io_tensogram.h Tensogram benchmark (included when write_tensogram=1)
io_netcdf.h NetCDF output (included when write_netcdf=1)
.tensogram/ Prebuilt tensogram install prefix (gitignored, see `make tensogram`)
lib/ libtensogram.so + libtensogram.a + pkg-config
include/tensogram/ tensogram.h (C API header)
visualize_tgm.py Animate a single .tgm file (PIL-optimized GIFs)
plot_bench.py Benchmark report: comparison PNGs + per-codec GIFs
benchmark.md Compression benchmark results (auto-generated)
Controlled by flags in config.h. Set to 1 to enable, 0 to disable.
| Flag | Default | Output file | Requires |
|---|---|---|---|
write_posix |
0 | t_NNNN.txt |
nothing |
write_netcdf |
0 | grid.nc |
libnetcdf |
write_tensogram |
1 | bench_*.tgm |
libtensogram (prebuilt GitHub release asset) |
Tensogram is a binary format for N-dimensional tensors with built-in compression, published as:
- prebuilt C/C++ tarballs on GitHub releases —
libtensogram+tensogram.h tensogramon PyPI — the Python bindings
The C side is installed by downloading the release tarball for the
current platform (linux-x86_64, linux-aarch64, or macos-aarch64)
into the local .tensogram/ prefix:
make tensogramNo Rust toolchain, no sudo, no system-wide install. The version is
pinned by TGM_VERSION in the Makefile (currently 0.21.0); override
it on the command line to try another release:
make tensogram TGM_VERSION=0.21.0If you prefer a system-wide install instead, follow the
C API guide
and unpack the tarball into /usr/local.
Set write_netcdf to 1 and write_tensogram to 0 in config.h, then:
make NETCDF=1Set both write_netcdf and write_tensogram to 0 in config.h:
mpicc -O3 -march=native waveEq.c -o wave.x -lmWhen write_tensogram is enabled, the solver captures simulation frames
and benchmarks all 21 compression codecs. Each codec writes a separate
bench_<name>.tgm file and results are printed as a Markdown table and
saved to benchmark.md.
The codecs tested include:
- Lossless: raw, lz4, zstd (levels 1/3/9), blosc2
- Lossless + shuffle: byte shuffle with zstd, lz4, blosc2
- Lossy quantization: simple_packing at 24/16/12 bits per value, combined with zstd, lz4, or szip
- Floating-point lossy: ZFP (fixed rate, fixed accuracy), SZ3 (absolute and relative error bounds)
See benchmark.md for the full results table.
The Python scripts need the tensogram PyPI package plus numpy /
matplotlib / Pillow. make py-setup installs all of these into a local
.venv/:
make py-setupManual equivalent:
python3 -m venv .venv
.venv/bin/pip install tensogram numpy matplotlib Pillowmake viz # Interactive window (bench_raw.tgm)
make viz FILE=bench_zstd-3.tgm # Visualize a specific codec
make viz-save # Save as GIF
make viz-save SKIP=5 # Save with custom frame skip
# Zoom into a sub-region using range decode
.venv/bin/python3 visualize_tgm.py bench_raw.tgm 10 --zoom 100:400,100:400 --savemake plots # Static PNGs (codec grid + error heatmaps)
make gifs # Animated GIF per codec
make bench # Full pipeline: run + plots + gifsncview grid.ncThe number of MPI ranks must be a perfect square (1, 4, 9, 16, ...) and
the grid size (528 by default) must be divisible by sqrt(ranks).
make run NP=1 # single process
make run NP=4 # 2x2 decomposition
make run NP=16 # 4x4 decomposition (recommended)All parameters are in config.h.
| Parameter | Default | Description |
|---|---|---|
dx |
0.00594998 | Grid spacing (gives 528x528 grid) |
dt |
0.001 | Time step |
f_to_go |
3.14159 (pi) | Domain size |
t_to_go |
3.0 | Total simulation time |
gerr_max |
1e-6 | Gauss-Seidel convergence tolerance |
| Parameter | Default | Description |
|---|---|---|
write_posix |
0 | Enable POSIX text file output |
write_netcdf |
0 | Enable NetCDF output |
write_tensogram |
1 | Enable Tensogram compression benchmark |
write_interval |
10 | Write every Nth solver step (reduces output size) |
tgm_bench_steps |
0 | Max frames to capture (0 = all) |
The solver runs 3001 steps for t=3.0. write_interval controls how many are captured:
| write_interval | Frames | Raw size | Covers |
|---|---|---|---|
| 1 | 3001 | 6.69 GB | every step |
| 10 | 301 | 671 MB | every 10th step |
| 20 | 151 | 337 MB | every 20th step |
