.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "tutorials/b_fundamentals/b02_cross_section.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_tutorials_b_fundamentals_b02_cross_section.py: Building a Model from Scratch ================================ Building a model from scratch, one borehole reading at a time The Basics tutorial builds a model from a ready-made CSV file. Here, there's no file -- just a conceptual 2D cross-section with three boreholes, read off an image one point at a time. This is a more realistic starting point for a lot of real projects, and it also surfaces gempy concepts that a clean CSV import skips over entirely: how much data is actually needed before a model can be computed at all, and how a handful of alternative geological hypotheses can all fit the same sparse observations. .. GENERATED FROM PYTHON SOURCE LINES 16-23 .. code-block:: Python import numpy as np import matplotlib.pyplot as plt import matplotlib.image as mpimg import gempy as gp import gempy_viewer as gpv .. GENERATED FROM PYTHON SOURCE LINES 24-29 The cross-section -------------------- The model below is based on a conceptual cross-section with data from three boreholes in a line. Here it is, loaded as a plain image -- for this example, the image's pixel dimensions double as the real extent of the data: .. GENERATED FROM PYTHON SOURCE LINES 31-35 .. code-block:: Python img = mpimg.imread('boreholes_concept.png') plt.imshow(img, origin='upper', alpha=.8) img.shape[:2] .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_001.png :alt: b02 cross section :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none (582, 780) .. GENERATED FROM PYTHON SOURCE LINES 36-46 Model setup ------------- A model needs a name, an extent, and either a resolution or a refinement level (see the Grids tutorial for what each of those actually controls) -- and, since there's no CSV to import here, an explicitly initialized default structural frame instead of an ``importer_helper``. The extent should align with the cross-section: X runs parallel to it, Z (depth) negative since we're modeling the subsurface, and Y an arbitrary narrow band centered on 0 since the section carries no real Y information: .. GENERATED FROM PYTHON SOURCE LINES 48-55 .. code-block:: Python geo_model = gp.create_geomodel( project_name='Model1', extent=[0, 780, -200, 200, -582, 0], resolution=(50, 50, 50), structural_frame=gp.data.StructuralFrame.initialize_default_structure() ) .. GENERATED FROM PYTHON SOURCE LINES 56-59 ``initialize_default_structure()`` gives the model one placeholder surface and the ever-present ``basement`` unit, both in a single default structural group (see the Basics tutorial for what these classes actually are): .. GENERATED FROM PYTHON SOURCE LINES 61-63 .. code-block:: Python geo_model.structural_frame.structural_elements .. rst-class:: sphx-glr-script-out .. code-block:: none [Element( name=surface1, color=#015482, is_active=True ), Element( name=basement, color=#9f0052, is_active=True )] .. GENERATED FROM PYTHON SOURCE LINES 64-66 Let's rename and recolor that placeholder to a real lithology -- say, the uppermost unit in the cross-section is a limestone, shown in blue: .. GENERATED FROM PYTHON SOURCE LINES 68-73 .. code-block:: Python geo_model.structural_frame.structural_elements[0].color = '#33ABFF' geo_model.structural_frame.structural_elements[1].color = '#570987' geo_model.structural_frame.structural_elements[0].name = 'Limestone' geo_model.structural_frame.structural_groups[0].name = 'Deposit_Series' .. GENERATED FROM PYTHON SOURCE LINES 74-79 Reading points off the cross-section --------------------------------------- With the model set up, surface points can be added by simply reading their coordinates off the image. Overlaying the model's own (currently empty) 2D plot on top of the cross-section, with a grid for reference, makes this easy: .. GENERATED FROM PYTHON SOURCE LINES 81-89 .. code-block:: Python p2d = gpv.plot_2d(geo_model, show=False) p2d.axes[0].imshow(img, origin='upper', alpha=.8, extent=(0, 780, -582, 0)) p2d.axes[0].grid(which='both') p2d.axes[0].minorticks_on() p2d.axes[0].grid(which='major', linestyle='--', linewidth='0.8', color='gray') p2d.axes[0].grid(which='minor', linestyle=':', linewidth='0.4', color='gray') plt.show() .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_002.png :alt: Cell Number: mid Direction: y :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 90-93 The first borehole's limestone contact (the top boundary shown as a blue dot) reads at roughly X=225, 95 m deep. Since each surface in gempy marks the *bottom* of a unit, and we're assuming no variation in Y, this becomes: .. GENERATED FROM PYTHON SOURCE LINES 95-105 .. code-block:: Python gp.add_surface_points(geo_model=geo_model, x=[225], y=[0], z=[-95], elements_names=['Limestone']) p2d = gpv.plot_2d(geo_model, show=False) p2d.axes[0].imshow(img, origin='upper', alpha=.8, extent=(0, 780, -582, 0)) p2d.axes[0].grid(which='both') p2d.axes[0].minorticks_on() p2d.axes[0].grid(which='major', linestyle='--', linewidth='0.8', color='gray') p2d.axes[0].grid(which='minor', linestyle=':', linewidth='0.4', color='gray') plt.show() .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_003.png :alt: Cell Number: mid Direction: y :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_003.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 106-109 The point sits right on top of the borehole dot, as expected. The same call adds several points at once, so the other two boreholes' limestone contacts can be added together: .. GENERATED FROM PYTHON SOURCE LINES 111-121 .. code-block:: Python gp.add_surface_points(geo_model=geo_model, x=[460, 617], y=[0, 0], z=[-100, -10], elements_names=['Limestone', 'Limestone']) p2d = gpv.plot_2d(geo_model, show=False) p2d.axes[0].imshow(img, origin='upper', alpha=.8, extent=(0, 780, -582, 0)) p2d.axes[0].grid(which='both') p2d.axes[0].minorticks_on() p2d.axes[0].grid(which='major', linestyle='--', linewidth='0.8', color='gray') p2d.axes[0].grid(which='minor', linestyle=':', linewidth='0.4', color='gray') plt.show() .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_004.png :alt: Cell Number: mid Direction: y :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_004.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 122-137 How much data is actually needed? ------------------------------------ Three points down, but is that enough to compute a model yet? Not quite. gempy's interpolation needs, at minimum: - **Two surface points** for at least one surface in a structural group - **One orientation** somewhere in that same group Once one surface has two points and the group has an orientation, any *additional* surface in the same group needs as little as one more point -- it borrows the group's orientation information from there. So: one orientation is still missing. Between the first two limestone points, a roughly horizontal orientation is a reasonable assumption (there's no real Y-direction data to say otherwise): .. GENERATED FROM PYTHON SOURCE LINES 139-156 .. code-block:: Python gp.add_orientations( geo_model=geo_model, x=[350], y=[0], z=[-120], elements_names=['Limestone'], pole_vector=[np.array([0, 0, 1])] ) p2d = gpv.plot_2d(geo_model, show=False) p2d.axes[0].imshow(img, origin='upper', alpha=.8, extent=(0, 780, -582, 0)) p2d.axes[0].grid(which='both') p2d.axes[0].minorticks_on() p2d.axes[0].grid(which='major', linestyle='--', linewidth='0.8', color='gray') p2d.axes[0].grid(which='minor', linestyle=':', linewidth='0.4', color='gray') plt.show() .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_005.png :alt: Cell Number: mid Direction: y :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_005.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 157-160 Computing the first version ------------------------------ That's enough to compute a first version of the model: .. GENERATED FROM PYTHON SOURCE LINES 162-165 .. code-block:: Python geo_model.update_transform(gp.data.GlobalAnisotropy.NONE) gp.compute_model(geo_model) .. rst-class:: sphx-glr-script-out .. code-block:: none Setting Backend To: AvailableBackends.PYTORCH GPU enabled. Using device: cuda GPU device count: 1 Current GPU device: 0 .. raw:: html
Solutions: 4 Octree Levels, 1 DualContouringMeshes


.. GENERATED FROM PYTHON SOURCE LINES 166-168 .. code-block:: Python gpv.plot_2d(geo_model, cell_number='mid') .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_006.png :alt: Cell Number: mid Direction: y :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_006.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 169-171 Overlaid on the original cross-section, the computed interface runs right through the three points, shaped by the one orientation: .. GENERATED FROM PYTHON SOURCE LINES 173-181 .. code-block:: Python p2d = gpv.plot_2d(geo_model, show=False) p2d.axes[0].imshow(img, origin='upper', alpha=.8, extent=(0, 780, -582, 0)) p2d.axes[0].grid(which='both') p2d.axes[0].minorticks_on() p2d.axes[0].grid(which='major', linestyle='--', linewidth='0.8', color='gray') p2d.axes[0].grid(which='minor', linestyle=':', linewidth='0.4', color='gray') plt.show() .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_007.png :alt: Cell Number: mid Direction: y :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_007.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 182-184 .. code-block:: Python gpv.plot_3d(geo_model, show_surfaces=True) .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_008.png :alt: b02 cross section :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_008.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 185-188 One lithological interface down. The scalar field behind it -- the continuous function whose isosurface *is* this interface -- is worth a look before adding more data, to get a feel for how it responds as new units and points are added: .. GENERATED FROM PYTHON SOURCE LINES 190-192 .. code-block:: Python gpv.plot_2d(geo_model, series_n=0, show_data=True, show_scalar=True, show_lith=False) .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_009.png :alt: Cell Number: mid Direction: y :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_009.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 193-199 Adding a second lithological unit ------------------------------------ A new unit needs a new ``StructuralElement`` -- ``add_surface_points`` only adds points to a unit that already exists (see the Basics tutorial for the class itself). Let's assume the next unit down is a siltstone, colored to match the cross-section, and append it to the same group as the limestone: .. GENERATED FROM PYTHON SOURCE LINES 201-224 .. code-block:: Python element2 = gp.data.StructuralElement( name='Siltstone', color='#FFA833', surface_points=gp.data.SurfacePointsTable.from_arrays( x=np.array([460]), y=np.array([0]), z=np.array([-280]), names='Siltstone' ), orientations=gp.data.OrientationsTable.initialize_empty() ) geo_model.structural_frame.structural_groups[0].append_element(element2) gp.compute_model(geo_model) p2d = gpv.plot_2d(geo_model, cell_number='mid', show=False) p2d.axes[0].imshow(img, origin='upper', alpha=.8, extent=(0, 780, -582, 0)) p2d.axes[0].grid(which='both') p2d.axes[0].minorticks_on() p2d.axes[0].grid(which='major', linestyle='--', linewidth='0.8', color='gray') p2d.axes[0].grid(which='minor', linestyle=':', linewidth='0.4', color='gray') plt.show() .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_010.png :alt: Cell Number: mid Direction: y :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_010.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Setting Backend To: AvailableBackends.PYTORCH GPU enabled. Using device: cuda GPU device count: 1 Current GPU device: 0 .. GENERATED FROM PYTHON SOURCE LINES 225-229 With only one point so far, the siltstone's bottom interface simply follows the limestone's shape and orientation -- a direct consequence of both sharing one scalar field. It already lines up reasonably well with the first borehole. Let's add the missing point, plus a third unit while we're at it: .. GENERATED FROM PYTHON SOURCE LINES 231-256 .. code-block:: Python gp.add_surface_points(geo_model=geo_model, x=[225], y=[0], z=[-270], elements_names=['Siltstone']) element3 = gp.data.StructuralElement( name='Sandstone', color='#72A533', surface_points=gp.data.SurfacePointsTable.from_arrays( x=np.array([225, 460]), y=np.array([0, 0]), z=np.array([-436, -441]), names='Sandstone' ), orientations=gp.data.OrientationsTable.initialize_empty() ) geo_model.structural_frame.structural_groups[0].append_element(element3) gp.compute_model(geo_model) p2d = gpv.plot_2d(geo_model, show=False) p2d.axes[0].imshow(img, origin='upper', alpha=.8, extent=(0, 780, -582, 0)) p2d.axes[0].grid(which='both') p2d.axes[0].minorticks_on() p2d.axes[0].grid(which='major', linestyle='--', linewidth='0.8', color='gray') p2d.axes[0].grid(which='minor', linestyle=':', linewidth='0.4', color='gray') plt.show() .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_011.png :alt: Cell Number: mid Direction: y :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_011.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Setting Backend To: AvailableBackends.PYTORCH GPU enabled. Using device: cuda GPU device count: 1 Current GPU device: 0 .. GENERATED FROM PYTHON SOURCE LINES 257-259 .. code-block:: Python gpv.plot_3d(geo_model, show_surfaces=True) .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_012.png :alt: b02 cross section :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_012.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 260-269 Discontinuities: combining scalar fields -------------------------------------------- All three units so far share one scalar field, which only ever produces smoothly conformable layers. Real geology is rarely that tidy. gempy handles this by letting separate structural groups -- each with its own scalar field -- interact with each other, which is exactly what's needed for the sparse, ambiguous data on the right side of the cross-section. Let's define one more element there to explore this: .. GENERATED FROM PYTHON SOURCE LINES 271-291 .. code-block:: Python element_discont = gp.data.StructuralElement( name='Discont_Surface', color='#990000', surface_points=gp.data.SurfacePointsTable.from_arrays( x=np.array([550, 650]), y=np.array([0, 0]), z=np.array([-30, -200]), names='Discont_Surface' ), orientations=gp.data.OrientationsTable.from_arrays( x=np.array([600]), y=np.array([0]), z=np.array([-100]), G_x=np.array([.3]), G_y=np.array([0]), G_z=np.array([.3]), names='Discont_Surface' ) ) .. GENERATED FROM PYTHON SOURCE LINES 292-294 Placing it in its own group, inserted above the existing one, keeps it in a separate scalar field entirely: .. GENERATED FROM PYTHON SOURCE LINES 296-304 .. code-block:: Python group_discont = gp.data.StructuralGroup( name='Discontinuity', elements=[element_discont], structural_relation=gp.data.StackRelationType.ERODE, ) geo_model.structural_frame.insert_group(0, group_discont) geo_model.structural_frame .. raw:: html
Structural Groups: StructuralGroup:
Name:Discontinuity
Structural Relation:StackRelationType.ERODE
Elements:
StructuralElement:
Name:Discont_Surface

StructuralGroup:
Name:Deposit_Series
Structural Relation:StackRelationType.ERODE
Elements:
StructuralElement:
Name:Limestone

StructuralElement:
Name:Siltstone

StructuralElement:
Name:Sandstone
Fault Relations:
Discontinu...Deposit_Se...
Discontinuity
Deposit_Series
True
False


.. GENERATED FROM PYTHON SOURCE LINES 305-307 Two groups, two independent scalar fields -- computing the model now lets us look at each on its own: .. GENERATED FROM PYTHON SOURCE LINES 309-311 .. code-block:: Python gp.compute_model(geo_model) .. rst-class:: sphx-glr-script-out .. code-block:: none Setting Backend To: AvailableBackends.PYTORCH GPU enabled. Using device: cuda GPU device count: 1 Current GPU device: 0 .. raw:: html
Solutions: 4 Octree Levels, 4 DualContouringMeshes


.. GENERATED FROM PYTHON SOURCE LINES 312-314 .. code-block:: Python gpv.plot_2d(geo_model, series_n=1, show_data=True, show_scalar=True, show_lith=False) .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_013.png :alt: Cell Number: mid Direction: y :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_013.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 315-317 .. code-block:: Python gpv.plot_2d(geo_model, series_n=0, show_data=True, show_scalar=True, show_lith=False) .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_014.png :alt: Cell Number: mid Direction: y :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_014.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 318-332 How two structural groups combine depends on (1) their order and (2) the younger group's ``StackRelationType`` -- how it relates to everything below it: - ``ERODE``: an erosive contact/unconformity, cutting into everything older - ``ONLAP``: the younger group onlaps onto the older one instead of cutting it - ``FAULT``: the younger group is a fault, offsetting everything older - ``BASEMENT``: treats everything older as a single basement unit The new group defaults to ``ERODE`` -- let's see what each of the other relevant options actually looks like against this same data. Erosive contact ~~~~~~~~~~~~~~~~~ Nothing needs to change for this one; it's already the default: .. GENERATED FROM PYTHON SOURCE LINES 334-342 .. code-block:: Python p2d = gpv.plot_2d(geo_model, show=False) p2d.axes[0].imshow(img, origin='upper', alpha=.8, extent=(0, 780, -582, 0)) p2d.axes[0].grid(which='both') p2d.axes[0].minorticks_on() p2d.axes[0].grid(which='major', linestyle='--', linewidth='0.8', color='gray') p2d.axes[0].grid(which='minor', linestyle=':', linewidth='0.4', color='gray') plt.show() .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_015.png :alt: Cell Number: mid Direction: y :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_015.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 343-345 .. code-block:: Python gpv.plot_3d(geo_model, show_surfaces=True, show_lith=False) .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_016.png :alt: b02 cross section :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_016.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 346-352 Every older unit stops dead at the discontinuity -- but that doesn't fit the third borehole's own point at all. Worth trying another relation type. Onlap ~~~~~~ %% .. GENERATED FROM PYTHON SOURCE LINES 352-363 .. code-block:: Python geo_model.structural_frame.structural_groups[0].structural_relation = gp.data.StackRelationType.ONLAP gp.compute_model(geo_model) p2d = gpv.plot_2d(geo_model, show=False) p2d.axes[0].imshow(img, origin='upper', alpha=.8, extent=(0, 780, -582, 0)) p2d.axes[0].grid(which='both') p2d.axes[0].minorticks_on() p2d.axes[0].grid(which='major', linestyle='--', linewidth='0.8', color='gray') p2d.axes[0].grid(which='minor', linestyle=':', linewidth='0.4', color='gray') plt.show() .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_017.png :alt: Cell Number: mid Direction: y :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_017.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Setting Backend To: AvailableBackends.PYTORCH GPU enabled. Using device: cuda GPU device count: 1 Current GPU device: 0 .. GENERATED FROM PYTHON SOURCE LINES 364-366 .. code-block:: Python gpv.plot_3d(geo_model, show_surfaces=True, show_lith=False) .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_018.png :alt: b02 cross section :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_018.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 367-373 Now the discontinuity's own unit onlaps onto the uppermost surface below and stops there -- plausible, but still not a great match for the data. One relation type left. Fault ~~~~~~ A fault additionally needs ``set_is_fault``, exactly as in the Basics tutorial: .. GENERATED FROM PYTHON SOURCE LINES 375-387 .. code-block:: Python geo_model.structural_frame.structural_groups[0].structural_relation = gp.data.StackRelationType.FAULT gp.set_is_fault(geo_model, ["Discontinuity"]) gp.compute_model(geo_model) p2d = gpv.plot_2d(geo_model, show=False) p2d.axes[0].imshow(img, origin='upper', alpha=.8, extent=(0, 780, -582, 0)) p2d.axes[0].grid(which='both') p2d.axes[0].minorticks_on() p2d.axes[0].grid(which='major', linestyle='--', linewidth='0.8', color='gray') p2d.axes[0].grid(which='minor', linestyle=':', linewidth='0.4', color='gray') plt.show() .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_019.png :alt: Cell Number: mid Direction: y :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_019.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Setting Backend To: AvailableBackends.PYTORCH GPU enabled. Using device: cuda GPU device count: 1 Current GPU device: 0 .. GENERATED FROM PYTHON SOURCE LINES 388-390 .. code-block:: Python gpv.plot_3d(geo_model, show_surfaces=True, show_lith=False) .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_020.png :alt: b02 cross section :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_020.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 391-398 This one fits: instead of a large syncline bending the whole deposit series upward, a reverse fault offsets otherwise near-horizontal layers, explaining the shallower limestone in the third borehole. The degree of offset follows directly from the surface points on each side of the fault -- with no data at all on one side, gempy assumes a very large offset. The deposit series' scalar field itself now visibly reflects the fault's offset: .. GENERATED FROM PYTHON SOURCE LINES 400-402 .. code-block:: Python gpv.plot_2d(geo_model, series_n=1, show_data=True, show_scalar=True, show_lith=False) .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_021.png :alt: Cell Number: mid Direction: y :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_021.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 403-410 Topography and geological maps --------------------------------- One more grid type worth adding here: topography. It lets a model's surfaces be intersected with real terrain, and, computed together with the model, generates a geological map of whatever crops out at the surface. A synthetic topography stands in for real data below (real rasters are supported too, via ``set_topography_from_file``): .. GENERATED FROM PYTHON SOURCE LINES 412-421 .. code-block:: Python gp.set_topography_from_random( grid=geo_model.grid, fractal_dimension=1.9, d_z=np.array([-150, 0]), topography_resolution=np.array([200, 200]) ) gpv.plot_2d(geo_model, show_topography=True) .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_022.png :alt: Cell Number: mid Direction: y :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_022.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Active grids: GridTypes.DENSE|TOPOGRAPHY|NONE .. GENERATED FROM PYTHON SOURCE LINES 422-424 .. code-block:: Python gpv.plot_3d(geo_model, show_surfaces=True, show_topography=True, show_lith=False) .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_023.png :alt: b02 cross section :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_023.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 425-428 Recomputing now intersects the topography with the model, so the units outcropping at the surface can be read directly as a geological map -- a top-down view via ``section_names=['topography']``: .. GENERATED FROM PYTHON SOURCE LINES 430-434 .. code-block:: Python gp.compute_model(geo_model) gpv.plot_2d(geo_model, section_names=['topography'], show_topography=True, show_boundaries=False) .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_024.png :alt: Geological map :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_024.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Setting Backend To: AvailableBackends.PYTORCH GPU enabled. Using device: cuda GPU device count: 1 Current GPU device: 0 .. GENERATED FROM PYTHON SOURCE LINES 435-437 .. code-block:: Python gpv.plot_3d(geo_model, show_surfaces=True, show_topography=True) .. image-sg:: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_025.png :alt: b02 cross section :srcset: /tutorials/b_fundamentals/images/sphx_glr_b02_cross_section_025.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 438-441 From three borehole readings and a hand-drawn cross-section, this is now a complete 3D model, complete with a fault, a geological map, and a surface topography -- built up one decision at a time rather than handed over in a CSV file. .. GENERATED FROM PYTHON SOURCE LINES 441-443 .. code-block:: Python # sphinx_gallery_thumbnail_number = 19 .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 19.392 seconds) .. _sphx_glr_download_tutorials_b_fundamentals_b02_cross_section.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: b02_cross_section.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: b02_cross_section.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: b02_cross_section.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_