DiffGRF
Differentiable Gaussian random field generation in PyTorch.
DiffGRF implements the spectral randomization method for Gaussian random field (GRF) synthesis (Kraichnan 1970; Hesse et al. 2014) with full PyTorch autograd support. Gradients flow analytically through every physical parameter — variance, correlation length(s), anisotropy, rotation angles and the Matérn smoothness — so the generator can be used as a differentiable building block in inverse problems, design optimisation, and torch-native training pipelines.
Features
- Gaussian and Matérn kernels
- 1D, 2D, and 3D spatial domains
- Isotropic or per-axis anisotropic correlation lengths
- Differentiable rotation (2D angle, 3D Tait–Bryan triplet)
- Structured (regular grid), unstructured (arbitrary points), and
mesh-native (
meshio/ gmsh.msh) sampling - CPU, CUDA, and Apple MPS device support
- End-to-end autograd through all physical parameters
Installation
pip install diffgrf
Or from source:
git clone https://github.com/EJRicketts/diffgrf.git
cd diffgrf
pip install -e .[dev]
Requires Python ≥ 3.10, PyTorch ≥ 2.0, NumPy ≥ 1.22.
GPU acceleration is available via device="cuda" (NVIDIA) or
device="mps" (Apple Silicon). MPS does not support float64, so
pass dtype=torch.float32 when using MPS:
import torch
from diffgrf import DifferentiableGRF
grf = DifferentiableGRF(
kernel="gau", dim=2, variance=1.0, len_scale=10.0, seed=0,
device="mps", dtype=torch.float32,
)
field = grf.structured([256, 256])
Observed speedups on Apple M-series over CPU: 4–5× at 128²–256² 2D, ~10× at 96³ 3D.
Quickstart
Generate a 2D Gaussian random field on a regular grid:
from diffgrf import DifferentiableGRF
grf = DifferentiableGRF(
kernel="gau", dim=2, variance=1.0, len_scale=10.0, seed=0,
)
field = grf.structured([128, 128])
# field is a torch.Tensor of shape (128, 128)
Flow gradients through the correlation length:
import torch
from diffgrf import DifferentiableGRF
len_scale = torch.tensor(10.0, requires_grad=True)
grf = DifferentiableGRF(
kernel="gau", dim=2, variance=1.0, len_scale=len_scale, seed=0,
)
field = grf.structured([128, 128])
loss = field.var()
loss.backward()
print(len_scale.grad) # analytical gradient via spectral reparameterisation
Evaluate a field directly on an unstructured mesh (requires meshio,
pip install diffgrf[mesh]):
import meshio
from diffgrf import DifferentiableGRF
grf = DifferentiableGRF(
kernel="mat", dim=2, variance=1.0, len_scale=5.0, nu=1.5, seed=0,
)
# Accepts a meshio.Mesh OR any path readable by meshio.read.
# Evaluate at vertices (default) or cell centroids.
field_at_nodes = grf.on_mesh(meshio.read("domain.msh"))
field_at_cells = grf.on_mesh("domain.msh", location="cells")
Recover a correlation length from a target sample by gradient descent:
import torch
from diffgrf import DifferentiableGRF
target = DifferentiableGRF(
"gau", 2, 1.0, 12.0, seed=0,
).structured([128, 128])
ell = torch.tensor(5.0, requires_grad=True)
opt = torch.optim.Adam([ell], lr=0.2)
for _ in range(200):
opt.zero_grad()
pred = DifferentiableGRF("gau", 2, 1.0, ell, seed=0).structured([128, 128])
loss = (pred - target).pow(2).mean()
loss.backward()
opt.step()
print(float(ell)) # -> ~12
API
DifferentiableGRF(kernel, dim, variance, len_scale, ...)
The single entry point. See diffgrf/core.py for full signature and
docstrings.
Methods:
.structured(grid_dim)— generate on a regular grid..unstructured(points)— generate at arbitrary spatial points..on_mesh(mesh, location='points')— generate on ameshio.Meshor a path to any meshio-compatible file (.msh,.vtk,.xdmf, ...); evaluate at vertices (location='points') or cell centroids (location='cells'). Requires the optionalmeshiodependency (pip install diffgrf[mesh]).
Citation
If you use DiffGRF in published work, please cite:
@software{diffgrf,
author = {Ricketts, Evan John},
title = {DiffGRF: Differentiable Gaussian random field generation in PyTorch},
year = {2026},
url = {https://github.com/EJRicketts/diffgrf},
}
A peer-reviewed SoftwareX paper describing DiffGRF is in preparation; the citation will be updated once published.
License
MIT. See LICENSE.
Metadata
Release files for diffgrf 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| diffgrf-1.0.0.tar.gz | 16.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| diffgrf-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 27.2 kB
Release files / diffgrf-1.0.0.tar.gz
| Download URL | diffgrf-1.0.0.tar.gz |
|---|---|
| Size | 16.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
26fc6640e0a5dae0bdef2474ab53a3050e5b9556f223dc6f14e999baf51c3afe
|
|
BLAKE2b-256 checksum How to use checksums |
7307d1800a22f042e935dcd530955ec3d177c6659f8c656eaf871df3ea8fc97b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|
Release files / diffgrf-1.0.0-py3-none-any.whl
| Download URL | diffgrf-1.0.0-py3-none-any.whl |
|---|---|
| Size | 10.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
857a0376d260a473c9258cc1f66f6d6a42480abc7fb89481f867291216d73b0b
|
|
BLAKE2b-256 checksum How to use checksums |
c6a98a0d2625a24f0cd61a08807b289741f405fe5a871ef1112b8611b1eb5554
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|