Skip to content

Commit 0c82662

Browse files
committed
[WIP] Split the logic for gravity inversion
1 parent 3af285a commit 0c82662

File tree

6 files changed

+218
-75
lines changed

6 files changed

+218
-75
lines changed

examples/examples/_aux_func_gravity_inversion.py

Lines changed: 0 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import numpy as np
2-
from sklearn.linear_model import LinearRegression
31

42
import numpy as np
53

@@ -8,29 +6,6 @@
86
from vector_geology.model_building_functions import optimize_nuggets_for_group
97

108

11-
def calculate_scale_shift(a: np.ndarray, b: np.ndarray) -> tuple:
12-
# Reshape arrays for sklearn
13-
a_reshaped = a.reshape(-1, 1)
14-
b_reshaped = b.reshape(-1, 1)
15-
16-
# Linear regression
17-
model = LinearRegression().fit(a_reshaped, b_reshaped)
18-
19-
# Get scale and shift
20-
s = model.coef_[0][0]
21-
c = model.intercept_[0]
22-
23-
return s, c
24-
25-
26-
def gaussian_kernel(locations, length_scale, variance):
27-
import torch
28-
# Compute the squared Euclidean distance between each pair of points
29-
locations = torch.tensor(locations.values)
30-
distance_squared = torch.cdist(locations, locations, p=2).pow(2)
31-
# Compute the covariance matrix using the Gaussian kernel
32-
covariance_matrix = variance * torch.exp(-0.5 * distance_squared / length_scale ** 2)
33-
return covariance_matrix
349

3510

3611
def initialize_geo_model(structural_elements: list[gp.data.StructuralElement], extent: list[float],
@@ -105,56 +80,6 @@ def initialize_geo_model(structural_elements: list[gp.data.StructuralElement], e
10580

10681
return geo_model
10782

108-
109-
def optimize_nuggets_for_whole_project(geo_model: gp.data.GeoModel):
110-
geo_model.interpolation_options.kernel_options.range = 0.7
111-
geo_model.interpolation_options.kernel_options.c_o = 4
112-
optimize_nuggets_for_group(
113-
geo_model=geo_model,
114-
structural_group=geo_model.structural_frame.get_group_by_name('Red'),
115-
plot_evaluation=False,
116-
plot_result=True
117-
)
118-
geo_model.interpolation_options.kernel_options.range = 2
119-
geo_model.interpolation_options.kernel_options.c_o = 4
120-
optimize_nuggets_for_group(
121-
geo_model=geo_model,
122-
structural_group=geo_model.structural_frame.get_group_by_name('Blue'),
123-
plot_evaluation=False,
124-
plot_result=False
125-
)
126-
if False:
127-
optimize_nuggets_for_group(
128-
geo_model=geo_model,
129-
structural_group=geo_model.structural_frame.get_group_by_name('Green'),
130-
plot_evaluation=False,
131-
plot_result=True
132-
)
133-
134-
135-
def apply_optimized_nuggets(geo_model: gp.data.GeoModel, loaded_nuggets_red, loaded_nuggets_blue, loaded_nuggets_green):
136-
gp.modify_surface_points(
137-
geo_model,
138-
slice=None,
139-
elements_names=[element.name for element in geo_model.structural_frame.get_group_by_name('Red').elements],
140-
nugget=loaded_nuggets_red
141-
)
142-
if True: # Ignore OB
143-
gp.modify_surface_points(
144-
geo_model,
145-
slice=None,
146-
elements_names=[element.name for element in geo_model.structural_frame.get_group_by_name('Blue').elements],
147-
nugget=loaded_nuggets_blue
148-
)
149-
if False:
150-
gp.modify_surface_points(
151-
geo_model,
152-
slice=None,
153-
elements_names=[element.name for element in geo_model.structural_frame.get_group_by_name('Green').elements],
154-
nugget=loaded_nuggets_green
155-
)
156-
157-
15883
def setup_geophysics(env_path: str, geo_model: gp.data.GeoModel):
15984
import pandas as pd
16085
from dotenv import dotenv_values

examples/examples/_nugget_stuff.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import gempy as gp
2+
from vector_geology.model_building_functions import optimize_nuggets_for_group
3+
import gempy as gp
4+
import numpy as np
5+
6+
7+
def optimize_nuggets_for_group(geo_model: gp.data.GeoModel, structural_group: gp.data.StructuralGroup,
8+
plot_evaluation: bool = False, plot_result: bool = False) -> None:
9+
temp_structural_frame = gp.data.StructuralFrame(
10+
structural_groups=[structural_group],
11+
color_gen=gp.data.ColorsGenerator()
12+
)
13+
14+
previous_structural_frame = geo_model.structural_frame
15+
16+
geo_model.structural_frame = temp_structural_frame
17+
18+
gp.API.compute_API.optimize_and_compute(
19+
geo_model=geo_model,
20+
engine_config=gp.data.GemPyEngineConfig(
21+
backend=gp.data.AvailableBackends.PYTORCH,
22+
),
23+
max_epochs=100,
24+
convergence_criteria=1e5
25+
)
26+
27+
nugget_effect = geo_model.taped_interpolation_input.surface_points.nugget_effect_scalar.detach().numpy()
28+
np.save(f"temp/nuggets_{structural_group.name}", nugget_effect)
29+
30+
if plot_evaluation:
31+
import matplotlib.pyplot as plt
32+
33+
plt.hist(nugget_effect, bins=50, color='black', alpha=0.7, log=True)
34+
plt.xlabel('Eigenvalue')
35+
plt.ylabel('Frequency')
36+
plt.title('Histogram of Eigenvalues (nugget-grad)')
37+
plt.show()
38+
39+
if plot_result:
40+
import gempy_viewer as gpv
41+
import pyvista as pv
42+
43+
gempy_vista = gpv.plot_3d(
44+
model=geo_model,
45+
show=False,
46+
kwargs_plot_structured_grid={'opacity': 0.3}
47+
)
48+
49+
# Create a point cloud mesh
50+
surface_points_xyz = geo_model.surface_points_copy.df[['X', 'Y', 'Z']].to_numpy()
51+
52+
point_cloud = pv.PolyData(surface_points_xyz[0:])
53+
point_cloud['values'] = nugget_effect
54+
55+
gempy_vista.p.add_mesh(
56+
point_cloud,
57+
scalars='values',
58+
cmap='inferno',
59+
point_size=25,
60+
)
61+
62+
gempy_vista.p.show()
63+
64+
geo_model.structural_frame = previous_structural_frame
65+
return nugget_effect
66+
67+
68+
def optimize_nuggets_for_whole_project(geo_model: gp.data.GeoModel):
69+
geo_model.interpolation_options.kernel_options.range = 0.7
70+
geo_model.interpolation_options.kernel_options.c_o = 4
71+
optimize_nuggets_for_group(
72+
geo_model=geo_model,
73+
structural_group=geo_model.structural_frame.get_group_by_name('Red'),
74+
plot_evaluation=False,
75+
plot_result=True
76+
)
77+
geo_model.interpolation_options.kernel_options.range = 2
78+
geo_model.interpolation_options.kernel_options.c_o = 4
79+
optimize_nuggets_for_group(
80+
geo_model=geo_model,
81+
structural_group=geo_model.structural_frame.get_group_by_name('Blue'),
82+
plot_evaluation=False,
83+
plot_result=False
84+
)
85+
if False:
86+
optimize_nuggets_for_group(
87+
geo_model=geo_model,
88+
structural_group=geo_model.structural_frame.get_group_by_name('Green'),
89+
plot_evaluation=False,
90+
plot_result=True
91+
)
92+
93+
94+
def apply_optimized_nuggets(geo_model: gp.data.GeoModel, loaded_nuggets_red, loaded_nuggets_blue, loaded_nuggets_green):
95+
gp.modify_surface_points(
96+
geo_model,
97+
slice=None,
98+
elements_names=[element.name for element in geo_model.structural_frame.get_group_by_name('Red').elements],
99+
nugget=loaded_nuggets_red
100+
)
101+
if True: # Ignore OB
102+
gp.modify_surface_points(
103+
geo_model,
104+
slice=None,
105+
elements_names=[element.name for element in geo_model.structural_frame.get_group_by_name('Blue').elements],
106+
nugget=loaded_nuggets_blue
107+
)
108+
if False:
109+
gp.modify_surface_points(
110+
geo_model,
111+
slice=None,
112+
elements_names=[element.name for element in geo_model.structural_frame.get_group_by_name('Green').elements],
113+
nugget=loaded_nuggets_green
114+
)
115+

examples/examples/gravity_inversion.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,17 @@
6060
# %%
6161
# Configure GemPy for geological modeling with PyTorch backend
6262
BackendTensor.change_backend_gempy(engine_backend=gp.data.AvailableBackends.PYTORCH, dtype="float64")
63+
6364
geo_model = initialize_geo_model(
6465
structural_elements=structural_elements,
6566
extent=(np.array(global_extent)),
6667
topography=(xr.open_dataset(os.path.join(path, "Topography.nc"))),
6768
load_nuggets=False
6869
)
6970

71+
# TODO: Here is where we are setting the nuggets
72+
# * ============================================
73+
7074
# %%
7175
# Setup geophysics configuration for the model
7276
geophysics_input = setup_geophysics(
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
"""
2+
Probabilistic Inversion Example: Geological Model: Making the model stable
3+
--------------------------------------------------------------------------
4+
5+
6+
"""
7+
8+
9+
import os
10+
import time
11+
12+
import arviz as az
13+
import numpy as np
14+
import pyro
15+
import pyro.distributions as dist
16+
import torch
17+
import xarray as xr
18+
from dotenv import dotenv_values
19+
from matplotlib import pyplot as plt
20+
from pyro.infer import MCMC, NUTS, Predictive
21+
22+
import gempy as gp
23+
import gempy_engine
24+
import gempy_viewer as gpv
25+
26+
from examples.examples._aux_func_gravity_inversion import calculate_scale_shift, gaussian_kernel, initialize_geo_model, setup_geophysics
27+
from examples.examples._aux_func_gravity_inversion_II import process_file
28+
29+
from gempy_engine.core.backend_tensor import BackendTensor
30+
from gempy_probability.modules.plot.plot_posterior import default_red, default_blue
31+
32+
# %%
33+
# Config
34+
seed = 123456
35+
torch.manual_seed(seed)
36+
pyro.set_rng_seed(seed)
37+
38+
# %%
39+
# Start the timer for benchmarking purposes
40+
start_time = time.time()
41+
42+
# %%
43+
# Load necessary configuration and paths from environment variables
44+
config = dotenv_values()
45+
path = config.get("PATH_TO_MODEL_1_Subsurface")
46+
47+
# %%
48+
# Initialize lists to store structural elements for the geological model
49+
structural_elements = []
50+
global_extent = None
51+
color_gen = gp.data.ColorsGenerator()
52+
53+
# %%
54+
# Process each .nc file in the specified directory for model construction
55+
for filename in os.listdir(path):
56+
base, ext = os.path.splitext(filename)
57+
if ext == '.nc':
58+
structural_element, global_extent = process_file(os.path.join(path, filename), global_extent, color_gen)
59+
structural_elements.append(structural_element)
60+
61+
# %%
62+
# Configure GemPy for geological modeling with PyTorch backend
63+
BackendTensor.change_backend_gempy(engine_backend=gp.data.AvailableBackends.PYTORCH, dtype="float64")
64+
65+
geo_model = initialize_geo_model(
66+
structural_elements=structural_elements,
67+
extent=(np.array(global_extent)),
68+
topography=(xr.open_dataset(os.path.join(path, "Topography.nc"))),
69+
load_nuggets=False
70+
)
71+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from ._utils import calculate_scale_shift, gaussian_kernel
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import numpy as np
2+
from sklearn.linear_model import LinearRegression
3+
4+
def calculate_scale_shift(a: np.ndarray, b: np.ndarray) -> tuple:
5+
# Reshape arrays for sklearn
6+
a_reshaped = a.reshape(-1, 1)
7+
b_reshaped = b.reshape(-1, 1)
8+
9+
# Linear regression
10+
model = LinearRegression().fit(a_reshaped, b_reshaped)
11+
12+
# Get scale and shift
13+
s = model.coef_[0][0]
14+
c = model.intercept_[0]
15+
16+
return s, c
17+
18+
19+
def gaussian_kernel(locations, length_scale, variance):
20+
import torch
21+
# Compute the squared Euclidean distance between each pair of points
22+
locations = torch.tensor(locations.values)
23+
distance_squared = torch.cdist(locations, locations, p=2).pow(2)
24+
# Compute the covariance matrix using the Gaussian kernel
25+
covariance_matrix = variance * torch.exp(-0.5 * distance_squared / length_scale ** 2)
26+
return covariance_matrix
27+

0 commit comments

Comments
 (0)