# Geological Modeling (`geobrain.geomodel`)

The `geomodel` module generates synthetic geological property fields
(porosity, permeability, facies, etc.) using geostatistics and deep
generative models.

## Geostatistics

### FFT-MA (Fast Fourier Transform Moving Average)

Efficient spectral-domain Gaussian simulation supporting large 2D/3D grids:

```python
from geobrain.geomodel import Simulator, SimulationConfig

config = SimulationConfig(
    shape=(64, 64, 64),
    lh=20.0,                # Horizontal correlation length
    lv=5.0,                 # Vertical correlation length
    mean=0.0,
    std=1.0,
    seed=42,
)

sim = Simulator.create("fft_ma")
field = sim.simulate(config)
```

```{figure} ../../examples/figs/01_realizations.png
:width: 100%
:name: fig-fftma-realizations

Multiple realizations generated by FFT-MA simulation.
```

### Co-Simulation

Generate correlated multi-variable fields:

```python
import torch
from geobrain.geomodel import Simulator, CoSimConfig

corr = torch.tensor([[1.0, 0.7], [0.7, 1.0]])

config = CoSimConfig(
    shape=(64, 64, 128),
    n_variables=2,
    correlation_matrix=corr,
    field_names=["phi", "vsand"],
    lh=20, lv=5,
    seed=2025,
)

sim = Simulator.create("fft_ma")
fields = sim.simulate(config)
```

```{figure} ../../examples/figs/02_cosim_properties.png
:width: 100%
:name: fig-cosim-properties

Co-simulated porosity and sand volume fields.
```

### Sequential Gaussian Simulation (SGS)

Classical geostatistical simulation with Simple Kriging or Ordinary Kriging,
supporting unconditional and conditional (well data) simulation:

```python
# Unconditional SGS
sim = Simulator.create("sgs", kriging_type="ok")
fields = sim.simulate(config)

# Conditional SGS (honoring well data)
sim.set_conditioning(well_values, well_locations)
fields_cond = sim.simulate(config)
```

### Variogram Models

Build composite variogram models for spatial correlation analysis:

```python
from geobrain.geomodel import VariogramModel, VariogramStructure

vario = VariogramModel(
    nugget=0.1,
    structures=[
        VariogramStructure('spherical', contribution=0.6, range_h=30.0, range_v=10.0),
        VariogramStructure('exponential', contribution=0.3, range_h=80.0, range_v=20.0),
    ]
)
print(f"Sill: {vario.sill}")
print(f"C(10,0,0) = {vario.covariance_3d(10, 0, 0):.4f}")
```

```{figure} ../../examples/figs/02_variogram_models.png
:width: 100%
:name: fig-variogram-models

Variogram model comparison: spherical, exponential, Gaussian.
```

## Implicit Geological Modeling

The `implicit` submodule builds geological models from sparse surface contact
points and orientation measurements using differentiable Universal Cokriging:

```python
import torch
from geobrain.geomodel.implicit import (
    ImplicitModel, ImplicitModelConfig,
    SeriesDefinition, SurfacePointData, OrientationData,
)

config = ImplicitModelConfig(
    extent=(0.0, 1.0, 0.0, 1.0),
    resolution=(80, 80),
    dtype="float64",
)

sp = SurfacePointData(
    coords=torch.tensor([[0.2, 0.55], [0.5, 0.50], [0.8, 0.45]],
                         dtype=torch.float64),
    surface_id=torch.tensor([0, 0, 0]),
)
ori = OrientationData(
    coords=torch.tensor([[0.35, 0.52], [0.65, 0.48]], dtype=torch.float64),
    gradients=torch.tensor([[0.0, 1.0], [0.0, 1.0]], dtype=torch.float64),
)

model = ImplicitModel(config, series=[SeriesDefinition("strata", sp, ori)])
result = model(soft=True, temperature=50.0)
```

```{figure} ../../examples/figs/03_multi_series.png
:width: 100%
:name: fig-multi-series-implicit

Multi-series implicit geological model with erosion.
```

Supports multi-series stacking (ERODE / ONLAP), fault displacement via
`FaultDefinition`, and end-to-end differentiability for gradient-based
inversion of geological parameters.

## Generative Models

The `geogen` submodule provides deep learning-based geological model
generators:

| Model | Class | Description |
|-------|-------|-------------|
| Variational Autoencoder | `VAESimulator` | Latent-space geological modeling |
| Generative Adversarial Network | `GANSimulator` | Adversarial training for realistic geology |
| Diffusion Model | `DiffusionSimulator` | Score-based diffusion for geology generation |

## Data Transforms

Transform Gaussian fields to physical ranges:

```python
from geobrain.data.transforms import sigmoid_transform

# Map Gaussian to [0.05, 0.40] for porosity
transformed = sigmoid_transform(
    fields_tensor,
    ranges=[(0.05, 0.40)],
)
```
