Skip to content

Commit f495564

Browse files
committed
[DOC] Added fault tutorial script
1 parent 2adca2a commit f495564

File tree

1 file changed

+386
-0
lines changed

1 file changed

+386
-0
lines changed
Lines changed: 386 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,386 @@
1+
"""
2+
Video Tutorial "code-along": Faults
3+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4+
"""
5+
6+
7+
# %%
8+
# This tutorial demonstrates step-by-step how to add faults to our geological models created with `gempy`.
9+
# It follows the Video tutorial series available on the [gempy YouTube channel](https://www.youtube.com/@GemPy3D).
10+
# Please follow the first part of the tutorial to learn the basics of modeling with gempy before diving into this tutorial.
11+
12+
13+
# %%
14+
# Video tutorial faults: Introduction
15+
# """"""""""""""""""""""""""""""""""""
16+
#
17+
# The first video introduces the concept of modeling faults with GemPy - please view online before starting the tutorial.
18+
#
19+
#
20+
21+
# %%
22+
# .. raw:: html
23+
#
24+
# <iframe width="560" height="315"
25+
# src="https://www.youtube.com/embed/LAaL_2feAiA?si=wyMorsZLts7hXB2S"
26+
# title="YouTube video player"
27+
# frameborder="0"
28+
# allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
29+
# allowfullscreen>
30+
# </iframe>
31+
#
32+
#
33+
34+
# %%
35+
36+
# Required imports
37+
import gempy as gp
38+
import gempy_viewer as gpv
39+
import numpy as np
40+
41+
42+
# %%
43+
44+
# Path to input data
45+
data_path = "https://raw.githubusercontent.com/cgre-aachen/gempy_data/master/"
46+
path_to_data = data_path + "/data/input_data/video_tutorials_v3/"
47+
48+
49+
# %%
50+
51+
# Create instance of geomodel
52+
geo_model = gp.create_geomodel(
53+
project_name = 'tutorial_model_faults',
54+
extent=[0,3000,0,1000,0,1000],
55+
resolution=[90,30,30],
56+
importer_helper=gp.data.ImporterHelper(
57+
path_to_orientations=path_to_data + "tutorial_model_faults_1_orientations.csv",
58+
path_to_surface_points=path_to_data + "tutorial_model_faults_1_surface_points.csv"
59+
)
60+
)
61+
62+
63+
# %%
64+
65+
66+
# Display a basic cross section of input data
67+
gpv.plot_2d(geo_model);
68+
69+
70+
# %%
71+
72+
73+
# Map geological series to surfaces
74+
gp.map_stack_to_surfaces(
75+
gempy_model=geo_model,
76+
mapping_object={
77+
"Fault_Series1" : ('fault'),
78+
"Strat_Series1": ('rock3'),
79+
"Strat_Series2": ('rock2', 'rock1'),
80+
}
81+
)
82+
83+
84+
# %%
85+
86+
87+
# Define youngest structural group as fault
88+
gp.set_is_fault(geo_model, ["Fault_Series1"])
89+
90+
91+
# %%
92+
93+
94+
# Compute a solution for the model
95+
gp.compute_model(geo_model)
96+
97+
98+
# %%
99+
100+
101+
# Display the result in 2d section
102+
gpv.plot_2d(geo_model, cell_number=20)
103+
# gpv.plot_3d(geo_model)
104+
105+
106+
# %%
107+
108+
109+
# Display the scalar field of the fault in 2d section
110+
gpv.plot_2d(geo_model, show_scalar=True, show_lith=False, series_n=0)
111+
gpv.plot_2d(geo_model, show_scalar=True, show_lith=False, series_n=1)
112+
gpv.plot_2d(geo_model, show_scalar=True, show_lith=False, series_n=2)
113+
114+
115+
# %%
116+
# Video tutorial 9: Fault relations
117+
# """"""""""""""""""""""""""""
118+
119+
# %%
120+
# .. raw:: html
121+
#
122+
# <iframe width="560" height="315"
123+
# src="https://www.youtube.com/embed/AKpEefP9Ff0?si=7Jeiz5pfHQhXH4jF"
124+
# title="YouTube video player"
125+
# frameborder="0"
126+
# allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
127+
# allowfullscreen>
128+
# </iframe>
129+
#
130+
#
131+
132+
# ***Warning***: In the following section we will make several changes to the existing model. This includes adding new elements, groups, surface points and orientation and reordering the structural frame. Executing these cells more than once can lead to errors as things will be added twice.
133+
134+
# %%
135+
136+
137+
# Creating a new strucutral element with surface point and orientation data
138+
new_element = gp.data.StructuralElement(
139+
name='fault0',
140+
color=next(geo_model.structural_frame.color_generator),
141+
surface_points=gp.data.SurfacePointsTable.from_arrays(
142+
x=np.array([2750, 2750, 2750]),
143+
y=np.array([0, 500, 1000]),
144+
z=np.array([400, 400, 400]),
145+
names=['fault0']*3
146+
),
147+
orientations=gp.data.OrientationsTable.from_arrays(
148+
x=np.array([2750]),
149+
y=np.array([500]),
150+
z=np.array([400]),
151+
G_x=np.array([0.8]),
152+
G_y=np.array([0]),
153+
G_z=np.array([0.6]),
154+
names=['fault0']
155+
)
156+
)
157+
158+
# Creating a new structural group that contains the new element
159+
group_fault0 = gp.data.StructuralGroup(
160+
name='Fault_Series0',
161+
elements=[new_element],
162+
structural_relation=gp.data.StackRelationType.ERODE,
163+
)
164+
165+
# Insert the fault group into the structural frame at first position (index 0)
166+
geo_model.structural_frame.insert_group(index=0, group=group_fault0);
167+
168+
169+
# %%
170+
171+
172+
# Define youngest structural group as fault
173+
gp.set_is_fault(geo_model, ["Fault_Series0"])
174+
175+
176+
# %%
177+
178+
179+
# Add additional information for exisitng elements on other side of fault
180+
gp.add_surface_points(
181+
geo_model=geo_model,
182+
x=[2950, 2950, 2950],
183+
y=[0, 500, 1000],
184+
z=[500, 500, 500],
185+
elements_names=['rock2']*3
186+
);
187+
188+
gp.add_surface_points(
189+
geo_model=geo_model,
190+
x=[2950, 2950, 2950],
191+
y=[0, 500, 1000],
192+
z=[350, 350, 350],
193+
elements_names=['rock1']*3
194+
);
195+
196+
gp.add_surface_points(
197+
geo_model=geo_model,
198+
x=[2950, 2950, 2950],
199+
y=[0, 500, 1000],
200+
z=[550, 500, 500],
201+
elements_names=['rock3']*3
202+
);
203+
204+
205+
# %%
206+
207+
208+
# Display input data with the new fault and the additional input data for the other elements
209+
gpv.plot_2d(geo_model, show_data=True, show_boundaries=False, show_lith=False)
210+
211+
212+
# %%
213+
214+
215+
# Recompute the model with the new information
216+
gp.compute_model(geo_model)
217+
218+
219+
# %%
220+
221+
222+
# Display the new result
223+
gpv.plot_2d(geo_model)
224+
225+
226+
# %%
227+
228+
229+
# Switching the order by adding a new group containing rock3 on top
230+
gp.add_structural_group(
231+
model=geo_model,
232+
group_index=0,
233+
structural_group_name="Strat_Series0",
234+
elements=[
235+
geo_model.structural_frame.get_element_by_name("rock3")
236+
],
237+
structural_relation=gp.data.StackRelationType.ERODE
238+
)
239+
240+
# Removing the old group that contained rock3
241+
gp.remove_structural_group_by_name(geo_model, group_name="Strat_Series1")
242+
243+
244+
# %%
245+
246+
247+
# Recompute the model with new order
248+
gp.compute_model(geo_model)
249+
250+
251+
# %%
252+
253+
254+
# Display the new result
255+
gpv.plot_2d(geo_model)
256+
257+
258+
# %%
259+
260+
261+
# Set fault relations manually
262+
gp.set_fault_relation(
263+
frame=geo_model.structural_frame,
264+
rel_matrix=np.array([
265+
[0, 0, 0, 0],
266+
[0, 0, 0, 0],
267+
[0, 0, 0, 1],
268+
[0, 0, 0, 0]
269+
]
270+
)
271+
)
272+
273+
274+
# %%
275+
276+
277+
# Recompute model
278+
gp.compute_model(geo_model)
279+
280+
281+
# %%
282+
283+
284+
# Display result
285+
gpv.plot_2d(geo_model)
286+
287+
288+
# %%
289+
# Video tutorial 10: Fault groups and cross-cutting faults
290+
# """"""""""""""""""""""""""""""""""""
291+
292+
# %%
293+
# .. raw:: html
294+
#
295+
# <iframe width="560" height="315"
296+
# src="https://www.youtube.com/embed/PuxoH5EKUrQ?si=P8OhnXEUS8ZWVrGp"
297+
# title="YouTube video player"
298+
# frameborder="0"
299+
# allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
300+
# allowfullscreen>
301+
# </iframe>
302+
#
303+
#
304+
305+
# %%
306+
307+
308+
# Create instance of new geomodel
309+
geo_model_cross = gp.create_geomodel(
310+
project_name = 'tutorial_model_faults_2',
311+
extent=[0,1000,0,500,0,1000],
312+
resolution=[50,25,50],
313+
importer_helper=gp.data.ImporterHelper(
314+
path_to_orientations=path_to_data + "tutorial_model_faults_2_orientations.csv",
315+
path_to_surface_points=path_to_data + "tutorial_model_faults_2_surface_points.csv"
316+
)
317+
)
318+
319+
320+
# %%
321+
322+
323+
# Map geological series to surfaces
324+
gp.map_stack_to_surfaces(
325+
gempy_model=geo_model_cross,
326+
mapping_object={
327+
"Fault_Series2" : ('fault3', 'fault2'),
328+
"Fault_Series1" : ('fault1'),
329+
"Strat_Series": ('rock3', 'rock2', 'rock1'),
330+
}
331+
)
332+
333+
# Define youngest structural group as fault
334+
gp.set_is_fault(geo_model_cross, ["Fault_Series1", "Fault_Series2"])
335+
336+
# Change color of basement for better visibility
337+
geo_model_cross.structural_frame.basement_color="#F7B529"
338+
geo_model_cross.structural_frame.structural_elements[0].color = '#000000'
339+
geo_model_cross.structural_frame.structural_elements[1].color = '#36454F'
340+
geo_model_cross.structural_frame.structural_elements[2].color = '#D3D3D3'
341+
342+
343+
# %%
344+
345+
346+
geo_model_cross.structural_frame
347+
348+
349+
# %%
350+
351+
352+
# Set fault relations manually
353+
gp.set_fault_relation(
354+
frame=geo_model_cross.structural_frame,
355+
rel_matrix=np.array([
356+
[0, 1, 1],
357+
[0, 0, 1],
358+
[0, 0, 0],
359+
]
360+
)
361+
)
362+
363+
364+
# %%
365+
366+
367+
# Display input data on cross section
368+
gpv.plot_2d(geo_model_cross)
369+
370+
371+
# %%
372+
373+
374+
# Compute model
375+
gp.compute_model(geo_model_cross)
376+
377+
378+
# %%
379+
380+
381+
# Display reusult on cross section
382+
gpv.plot_2d(geo_model_cross)
383+
384+
385+
# sphinx_gallery_thumbnail_number = -1
386+

0 commit comments

Comments
 (0)