Skip to main content

Differentiable Gaussian random field generation in PyTorch

Project description

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 a meshio.Mesh or a path to any meshio-compatible file (.msh, .vtk, .xdmf, ...); evaluate at vertices (location='points') or cell centroids (location='cells'). Requires the optional meshio dependency (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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

diffgrf-1.0.0.tar.gz (16.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

diffgrf-1.0.0-py3-none-any.whl (10.7 kB view details)

Uploaded Python 3

File details

Details for the file diffgrf-1.0.0.tar.gz.

File metadata

  • Download URL: diffgrf-1.0.0.tar.gz
  • Upload date:
  • Size: 16.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for diffgrf-1.0.0.tar.gz
Algorithm Hash digest
SHA256 26fc6640e0a5dae0bdef2474ab53a3050e5b9556f223dc6f14e999baf51c3afe
MD5 08e1e3f2acfed578ef7bfbe2b09be927
BLAKE2b-256 7307d1800a22f042e935dcd530955ec3d177c6659f8c656eaf871df3ea8fc97b

See more details on using hashes here.

File details

Details for the file diffgrf-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: diffgrf-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 10.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for diffgrf-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 857a0376d260a473c9258cc1f66f6d6a42480abc7fb89481f867291216d73b0b
MD5 238812b7f92b3f055bf7ed19daeca648
BLAKE2b-256 c6a98a0d2625a24f0cd61a08807b289741f405fe5a871ef1112b8611b1eb5554

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page