Metadata-Version: 2.4
Name: diffgrf
Version: 1.0.0
Summary: Differentiable Gaussian random field generation in PyTorch
Author-email: Evan John Ricketts <rickettse1@cardiff.ac.uk>
License: MIT License
        
        Copyright (c) 2026 Evan John Ricketts
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://github.com/EJRicketts/diffgrf
Project-URL: Repository, https://github.com/EJRicketts/diffgrf
Project-URL: Issues, https://github.com/EJRicketts/diffgrf/issues
Keywords: gaussian-random-field,spectral-method,differentiable-programming,pytorch,autograd,porous-media
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Mathematics
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: torch<3.0,>=2.0
Requires-Dist: numpy>=1.22
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: matplotlib>=3.5; extra == "dev"
Requires-Dist: black>=24.0; extra == "dev"
Requires-Dist: isort>=5.12; extra == "dev"
Requires-Dist: pylint>=3.0; extra == "dev"
Provides-Extra: mesh
Requires-Dist: meshio>=5.0; extra == "mesh"
Dynamic: license-file

# 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

```bash
pip install diffgrf
```

Or from source:

```bash
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:

```python
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:

```python
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:

```python
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]`):

```python
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:

```python
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:

```bibtex
@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](LICENSE).
