.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/02_comparing_models.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_auto_examples_02_comparing_models.py: Comparing Two Models ==================== Load two solver runs of the same region: a reverse-fault experiment and a normal-fault experiment. Plot their principal directions on one stereonet. Then overlay a fracture population and see which model is more consistent with the measurements. .. GENERATED FROM PYTHON SOURCE LINES 12-14 Setup ----- .. GENERATED FROM PYTHON SOURCE LINES 14-24 .. code-block:: Python import os import matplotlib.pyplot as plt import mplstereonet # noqa: F401 from fem2geo import Model, dir_testdata from fem2geo.internal.io import load_structural_csv from fem2geo.plots import stereo_axes, stereo_pole .. GENERATED FROM PYTHON SOURCE LINES 25-30 Loading two models ------------------ Both files live in the tutorials data directory. They use the same schema. .. GENERATED FROM PYTHON SOURCE LINES 30-41 .. code-block:: Python reverse = Model.from_file( os.path.join(dir_testdata, "reverse_fault.vtu"), schema="adeli3" ) normal = Model.from_file( os.path.join(dir_testdata, "normal_fault.vtu"), schema="adeli3" ) print("reverse:", reverse.n_cells, "cells") print("normal: ", normal.n_cells, "cells") .. rst-class:: sphx-glr-script-out .. code-block:: none reverse: 52388 cells normal: 42106 cells .. GENERATED FROM PYTHON SOURCE LINES 42-43 We plot a slice for each model at the same place. .. GENERATED FROM PYTHON SOURCE LINES 43-64 .. code-block:: Python sl = reverse.grid.slice(normal="y", origin=(0, 5000, 0)) sl.plot( scalars="u", component=2, cpos="xz", zoom=1.4, text="Reverse fault", scalar_bar_args={"title": "u_z (m)"}, ) sl = normal.grid.slice(normal="y", origin=(0, 5000, 0)) sl.plot( scalars="u", component=2, cpos="xz", zoom=1.4, text="Normal fault", scalar_bar_args={"title": "u_z (m)"}, ) .. rst-class:: sphx-glr-horizontal * .. image-sg:: /auto_examples/images/sphx_glr_02_comparing_models_001.png :alt: 02 comparing models :srcset: /auto_examples/images/sphx_glr_02_comparing_models_001.png :class: sphx-glr-multi-img * .. image-sg:: /auto_examples/images/sphx_glr_02_comparing_models_002.png :alt: 02 comparing models :srcset: /auto_examples/images/sphx_glr_02_comparing_models_002.png :class: sphx-glr-multi-img .. GENERATED FROM PYTHON SOURCE LINES 65-70 Picking a common site --------------------- The two models share the same geometry, so the same center and radius work for both. .. GENERATED FROM PYTHON SOURCE LINES 70-77 .. code-block:: Python center = [8000, 6000, -1500] radius = 300 site_rev = reverse.extract(center=center, radius=radius) site_nor = normal.extract(center=center, radius=radius) .. GENERATED FROM PYTHON SOURCE LINES 78-85 Principal stress in both models ------------------------------- One call per model gives the eigenvalues and eigenvectors of the averaged stress tensor at the site. Since the site is the same, any difference is purely due to the loading conditions of each experiment. .. GENERATED FROM PYTHON SOURCE LINES 85-89 .. code-block:: Python _, vec_rev = site_rev.avg_principals("stress") _, vec_nor = site_nor.avg_principals("stress") .. GENERATED FROM PYTHON SOURCE LINES 90-94 Both on one stereonet --------------------- Drop both sets of axes into the same stereonet with different colors. .. GENERATED FROM PYTHON SOURCE LINES 94-112 .. code-block:: Python fig = plt.figure(figsize=(7, 7)) ax = fig.add_subplot(111, projection="stereonet") ax.grid(True) stereo_axes( ax, vec_rev, style={"color": "red", "markersize": 12}, labels=(r"$\sigma_1$ reverse", r"$\sigma_2$ reverse", r"$\sigma_3$ reverse"), ) stereo_axes( ax, vec_nor, style={"color": "blue", "markersize": 12}, labels=(r"$\sigma_1$ normal", r"$\sigma_2$ normal", r"$\sigma_3$ normal"), ) ax.legend() ax.set_title("Principal stress: reverse vs normal", y=1.08) .. image-sg:: /auto_examples/images/sphx_glr_02_comparing_models_003.png :alt: Principal stress: reverse vs normal :srcset: /auto_examples/images/sphx_glr_02_comparing_models_003.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Text(0.5, 1.08, 'Principal stress: reverse vs normal') .. GENERATED FROM PYTHON SOURCE LINES 113-119 Loading fracture measurements ----------------------------- A CSV with strike and dip columns becomes a ``FractureData`` object via ``load_structural_csv``. The ``.planes`` attribute is a ``(N, 2)`` numpy array of [strike, dip]. .. GENERATED FROM PYTHON SOURCE LINES 119-126 .. code-block:: Python fractures = load_structural_csv( os.path.join(dir_testdata, "fractures_c.csv") ) print(fractures) print("shape:", fractures.planes.shape) .. rst-class:: sphx-glr-script-out .. code-block:: none FractureData(20 measurements) shape: (20, 2) .. GENERATED FROM PYTHON SOURCE LINES 127-134 Fractures vs both models ------------------------ Draw the fractures poles (one point per plane) and place the principal directions of each model on top. A fracture population that aligns with :math:`\sigma_3` of a model is consistent with that stress state. .. GENERATED FROM PYTHON SOURCE LINES 134-164 .. code-block:: Python fig = plt.figure(figsize=(8, 8)) ax = fig.add_subplot(111, projection="stereonet") ax.grid(True) # fractures as poles stereo_pole( ax, fractures.planes, marker="o", color="grey", markersize=4, alpha=0.5, label="fracture poles", ) # reverse model principal directions stereo_axes( ax, vec_rev, style={"color": "red", "markersize": 14, "markeredgecolor": "k"}, labels=(r"$\sigma_1$ reverse", r"$\sigma_2$ reverse", r"$\sigma_3$ reverse"), ) # normal model principal directions stereo_axes( ax, vec_nor, style={"color": "blue", "markersize": 14, "markeredgecolor": "k"}, labels=(r"$\sigma_1$ normal", r"$\sigma_2$ normal", r"$\sigma_3$ normal"), ) ax.set_title("Fractures vs two stress states", y=1.08) ax.legend(loc="upper left", bbox_to_anchor=(1.0, 1.0), fontsize=9) plt.tight_layout() .. image-sg:: /auto_examples/images/sphx_glr_02_comparing_models_004.png :alt: Fractures vs two stress states :srcset: /auto_examples/images/sphx_glr_02_comparing_models_004.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none /home/docs/checkouts/readthedocs.org/user_builds/fem2geo/checkouts/stable/tutorials/examples/02_comparing_models.py:162: UserWarning: This figure includes Axes that are not compatible with tight_layout, so results might be incorrect. plt.tight_layout() .. GENERATED FROM PYTHON SOURCE LINES 165-169 At multiple sites ----------------- Here are two sites side by side, each comparing the two models against the fractures. .. GENERATED FROM PYTHON SOURCE LINES 169-204 .. code-block:: Python sites_info = [ ("Site 1 (shallow)", [8000, 6000, -1500]), ("Site 2 (deep)", [8000, 6000, -2500]), ] fig, axes = plt.subplots( 1, 2, figsize=(14, 7), subplot_kw={"projection": "stereonet"}, ) for ax, (name, ctr) in zip(axes, sites_info): sub_r = reverse.extract(center=ctr, radius=radius) sub_n = normal.extract(center=ctr, radius=radius) _, vectors_r = sub_r.avg_principals("stress") _, vectors_n = sub_n.avg_principals("stress") ax.grid(True) stereo_pole( ax, fractures.planes, marker="o", color="grey", markersize=4, alpha=0.5, ) stereo_axes( ax, vectors_r, style={"color": "red", "markersize": 12, "markeredgecolor": "k"}, labels=(r"$\sigma_1$ rev", r"$\sigma_2$ rev", r"$\sigma_3$ rev"), ) stereo_axes( ax, vectors_n, style={"color": "blue", "markersize": 12, "markeredgecolor": "k"}, labels=(r"$\sigma_1$ nor", r"$\sigma_2$ nor", r"$\sigma_3$ nor"), ) ax.set_title(name, y=1.08) .. image-sg:: /auto_examples/images/sphx_glr_02_comparing_models_005.png :alt: Site 1 (shallow), Site 2 (deep) :srcset: /auto_examples/images/sphx_glr_02_comparing_models_005.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 205-211 Slip tendency for two fault sets -------------------------------- Each model has its own stress state at each site. We plot the slip tendency field of that stress state as a stereonet contour, then overlay the observed fault poles on top. .. GENERATED FROM PYTHON SOURCE LINES 211-256 .. code-block:: Python from fem2geo.plots import stereo_field from fem2geo.utils.tensor import slip_tendency from fem2geo.utils.transform import grid_nodes, grid_centers faults_a = load_structural_csv(os.path.join(dir_testdata, "faults.csv")) faults_b = load_structural_csv(os.path.join(dir_testdata, "faults_b.csv")) ms, md = grid_nodes(180, 45) cs, cd = grid_centers(ms, md) fig, axes = plt.subplots( 2, 2, figsize=(12, 12), subplot_kw={"projection": "stereonet"}, ) cases = [ ("Site 1 shallow", [8000, 6000, -1500], faults_a), ("Site 2 deep", [8000, 6000, -2500], faults_b), ] for row, (name, ctr, fd) in enumerate(cases): sub_r = reverse.extract(center=ctr, radius=radius) sub_n = normal.extract(center=ctr, radius=radius) T_r = sub_r.avg_tensor("stress") T_n = sub_n.avg_tensor("stress") ts_r = slip_tendency(T_r, cs.ravel(), cd.ravel()).reshape(cs.shape) ts_n = slip_tendency(T_n, cs.ravel(), cd.ravel()).reshape(cs.shape) for col, (vals, label) in enumerate([(ts_r, "reverse"), (ts_n, "normal")]): ax = axes[row, col] ax.grid(True) stereo_field( ax, ms, md, vals, cmap="magma", vmin=0.0, vmax=1.0, cbar=True, cbar_label=r"$T'_s$", cbar_kwargs={"shrink": 0.7}, ) stereo_pole( ax, fd.planes[:, 0], fd.planes[:, 1], marker="+", color="green", markersize=10, ) ax.set_title(f"{name} — {label}", y=1.08) plt.tight_layout() .. image-sg:: /auto_examples/images/sphx_glr_02_comparing_models_006.png :alt: Site 1 shallow — reverse, Site 1 shallow — normal, Site 2 deep — reverse, Site 2 deep — normal :srcset: /auto_examples/images/sphx_glr_02_comparing_models_006.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none /home/docs/checkouts/readthedocs.org/user_builds/fem2geo/checkouts/stable/tutorials/examples/02_comparing_models.py:256: UserWarning: This figure includes Axes that are not compatible with tight_layout, so results might be incorrect. plt.tight_layout() .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 1.407 seconds) .. _sphx_glr_download_auto_examples_02_comparing_models.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: 02_comparing_models.ipynb <02_comparing_models.ipynb>` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: 02_comparing_models.py <02_comparing_models.py>` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: 02_comparing_models.zip <02_comparing_models.zip>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_