Skip to content

Commit ff6b910

Browse files
authored
[ENH] Add AD showcase tests, compute_grads config option, and documentation (#1094)
# Description Adds `compute_grads` as a configurable option in `GemPyEngineConfig` and threads it through to `BackendTensor.change_backend_gempy` when calling `compute_model`. This allows gradient computation to be explicitly controlled via the engine config rather than being hardcoded or inferred. The nugget optimizer is updated to handle backends that may not support the `grads` keyword argument gracefully, falling back to a call without it while still setting `BackendTensor.COMPUTE_GRADS = True` directly. A new AD (automatic differentiation) test suite is introduced under `test/test_modules/test_ad/`, covering: - **Scenario A**: Baseline AD smoke test and regression guard — verifies gradient existence, finiteness, and deterministic norm ranges for surface points and orientations. - **Scenario B**: Full-grid Jacobian spatial sensitivity — computes the Jacobian of the scalar field with respect to all surface-point coordinates and identifies the most influential points. - **Scenario C**: Numerical vs. autograd gradient comparison — validates AD correctness against central finite differences with coordinate-space scaling applied. - **Scenario D**: Multi-target derivatives — compares gradients from the scalar field and lithology block targets, including cosine similarity between gradient vectors. - **Scenario E**: Dual contouring intermediate sensitivity — backpropagates through DC edge gradients to surface-point coordinates. A second visualization-focused test file (`test_ad_II.py`) is added, demonstrating AD gradients rendered as PyVista glyph arrows on both a fold model and a combination model, with highlighted mesh vertices, mocked borehole cylinders, and logarithmically scaled gradient magnitude colormaps. Relates to # # Checklist - [x] My code uses type hinting for function and method arguments and return values. - [x] I have created tests which cover my code. - [x] The test code either 1. demonstrates at least one valuable use case (e.g. integration tests) or 2. verifies that outputs are as expected for given inputs (e.g. unit tests). - [x] New tests pass locally with my changes.
2 parents 61b5af5 + 280bb4f commit ff6b910

8 files changed

Lines changed: 664 additions & 17 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,3 +183,5 @@ examples/tutorials/z_other_tutorials/json_io/combination_model.json
183183
examples/tutorials/z_other_tutorials/json_io/combination_model_computed.json
184184
/test/temp/
185185
test/test_modules/run_test.py
186+
187+
.junie

gempy/API/compute_API.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,16 @@ def compute_model(gempy_model: GeoModel, engine_config: Optional[GemPyEngineConf
3232
Returns:
3333
Solutions: The computed geological model.
3434
"""
35-
engine_config = engine_config or GemPyEngineConfig(use_gpu=False)
35+
engine_config: GemPyEngineConfig = engine_config or GemPyEngineConfig(use_gpu=False)
3636

3737
match engine_config.backend:
3838
case AvailableBackends.numpy | AvailableBackends.PYTORCH:
3939

4040
BackendTensor.change_backend_gempy(
4141
engine_backend=engine_config.backend,
4242
use_gpu=engine_config.use_gpu,
43-
dtype=engine_config.dtype
43+
dtype=engine_config.dtype,
44+
grads=engine_config.compute_grads
4445
)
4546

4647
# TODO: To decide what to do with this.

gempy/core/data/gempy_engine_config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ class GemPyEngineConfig:
1010
backend: AvailableBackends = config.DEFAULT_BACKEND # ? This can be grabbed from gempy.config file?
1111
use_gpu: bool = False
1212
dtype: Optional[str] = None #: The data type used in the engine. If None, the default data type of the backend is used.
13+
compute_grads: Optional[bool] = False
1314

gempy/modules/optimize_nuggets/_optimizer.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,20 @@ def nugget_optimizer(
2121
Returns the final nugget effect value.
2222
"""
2323
# 1) Backend setup (ideally done once, not every call)
24-
BackendTensor.change_backend_gempy(
25-
engine_backend=engine_cfg.backend,
26-
use_gpu=engine_cfg.use_gpu,
27-
dtype=engine_cfg.dtype,
28-
grads=True
29-
)
24+
BackendTensor.COMPUTE_GRADS = True
25+
try:
26+
BackendTensor.change_backend_gempy(
27+
engine_backend=engine_cfg.backend,
28+
use_gpu=engine_cfg.use_gpu,
29+
dtype=engine_cfg.dtype,
30+
grads=True
31+
)
32+
except TypeError:
33+
BackendTensor.change_backend_gempy(
34+
engine_backend=engine_cfg.backend,
35+
use_gpu=engine_cfg.use_gpu,
36+
dtype=engine_cfg.dtype
37+
)
3038

3139
# 2) Prepare data
3240

requirements/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# This install also numpy
2-
gempy_engine>=2026.0.1dev0,<2026.1.0
2+
gempy_engine>=2026.0.2dev0

test/test_model_types/test_example_models_I.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
1-
from typing import Any
2-
3-
from numpy import dtype, ndarray
1+
import pytest
2+
from gempy_viewer import GemPyToVista
43

54
import gempy as gp
6-
from gempy.core.data import GeoModel
75
from gempy.core.data.enumerators import ExampleModel
86
from gempy.optional_dependencies import require_gempy_viewer
97
from gempy_engine.core.data.interp_output import InterpOutput
10-
from gempy_viewer import GemPyToVista
11-
12-
from test.verify_helper import gempy_verify_array
13-
import pytest
148
from test.conftest import TEST_SPEED, TestSpeed
9+
from test.verify_helper import gempy_verify_array
1510

1611
# ! When importing the model is computed
1712

0 commit comments

Comments
 (0)