1
+ import os
2
+ import dotenv
3
+
4
+ import time
5
+ import numpy as np
6
+ import gempy as gp
7
+ from gempy .API .io_API import read_surface_points
8
+
9
+ dotenv .load_dotenv ()
10
+
11
+ # Load data
12
+ def test_2025_3 ():
13
+
14
+ path_to_data = os .getenv ("TEST_DATA" )
15
+ path_to_data = r"C:/Users/Benjamink/OneDrive - Mira Geoscience Limited/Documents/projects/implicit modelling/Nutrien/demo_terranigma/from_miguel"
16
+
17
+ data = {
18
+ "a" : read_surface_points (f"{ path_to_data } /a.dat" ),
19
+ "b" : read_surface_points (f"{ path_to_data } /b.dat" ),
20
+ "c" : read_surface_points (f"{ path_to_data } /c.dat" ),
21
+ "d" : read_surface_points (f"{ path_to_data } /d.dat" ),
22
+ "e" : read_surface_points (f"{ path_to_data } /e.dat" ),
23
+ "f" : read_surface_points (f"{ path_to_data } /f.dat" ),
24
+ }
25
+
26
+ # Build structural frame
27
+
28
+ color_generator = gp .core .data .ColorsGenerator ()
29
+ elements = []
30
+ for event , pts in data .items ():
31
+ orientations = gp .data .OrientationsTable .initialize_empty ()
32
+ element = gp .core .data .StructuralElement (
33
+ name = event ,
34
+ color = next (color_generator ),
35
+ surface_points = pts ,
36
+ orientations = orientations ,
37
+ )
38
+ elements .append (element )
39
+
40
+ group = gp .core .data .StructuralGroup (
41
+ name = "Series1" ,
42
+ elements = elements ,
43
+ structural_relation = gp .core .data .StackRelationType .ERODE ,
44
+ fault_relations = gp .core .data .FaultsRelationSpecialCase .OFFSET_FORMATIONS ,
45
+ )
46
+ structural_frame = gp .core .data .StructuralFrame (
47
+ structural_groups = [group ], color_gen = color_generator
48
+ )
49
+
50
+ # create cell centers with similar size to the BlockMesh used for Nutrien modelling
51
+
52
+ xmin = 525816
53
+ xmax = 543233
54
+ ymin = 5652470
55
+ ymax = 5657860
56
+ zmin = - 780 - 40
57
+ zmax = - 636 + 40
58
+
59
+ x = np .arange (xmin , xmax , 50 )
60
+ y = np .arange (ymin , ymax , 50 )
61
+ z = np .arange (zmin , zmax , 1 )
62
+ X , Y , Z = np .meshgrid (x , y , z )
63
+ centers = np .c_ [X .flatten (), Y .flatten (), Z .flatten ()]
64
+
65
+ # Create geomodel
66
+
67
+ geo_model = gp .create_geomodel (
68
+ project_name = "test" ,
69
+ extent = [xmin , xmax , ymin , ymax , zmin , zmax ],
70
+ refinement = 6 ,
71
+ structural_frame = structural_frame ,
72
+ )
73
+ gp .add_orientations (
74
+ geo_model = geo_model ,
75
+ x = [525825 ],
76
+ y = [5651315 ],
77
+ z = [- 686 ],
78
+ pole_vector = [[0 , 0 , 1 ]],
79
+ elements_names = ["a" ]
80
+ )
81
+
82
+ # Ignore surface creation in timing lithology block creation
83
+ geo_model .interpolation_options .evaluation_options .mesh_extraction = False
84
+
85
+ # Time interpolation into octree cells
86
+
87
+ tic = time .perf_counter ()
88
+ solution = gp .compute_model (
89
+ geo_model ,
90
+ engine_config = gp .data .GemPyEngineConfig (
91
+ backend = gp .data .AvailableBackends .PYTORCH ,
92
+ use_gpu = True ,
93
+ ),
94
+ )
95
+ toc = time .perf_counter ()
96
+ elapsed = toc - tic
97
+ print (f"Octree interpolation runtime: { int (elapsed / 60 )} minutes { int (elapsed % 60 )} seconds." )
98
+
99
+ # Time extra interpolation on regular grid centers. I was expecting/hoping that this second step
100
+ # would just be an evaluation of the continuous scalar field solution from first step.
101
+
102
+ tic = time .perf_counter ()
103
+ model = gp .compute_model_at (
104
+ geo_model ,
105
+ at = centers ,
106
+ engine_config = gp .data .GemPyEngineConfig (
107
+ backend = gp .data .AvailableBackends .PYTORCH ,
108
+ use_gpu = True ,
109
+ ),
110
+ )
111
+ toc = time .perf_counter ()
112
+ elapsed = toc - tic
113
+ print (f"Evaluate model on regular grid centers: { int (elapsed / 60 )} minutes { int (elapsed % 60 )} seconds" )
0 commit comments