Petrophysically guided inversion: Joint linear example with nonlinear relationships#

We do a comparison between the classic least-squares inversion and our formulation of a petrophysically guided inversion. We explore it through coupling two linear problems whose respective physical properties are linked by polynomial relationships that change between rock units.

Problem 1, Problem 2, Petrophysical Distribution, Problem 1, Problem 2, Petrophysical Distribution, Problem 1, Problem 2, Petro Distribution
SimPEG.InvProblem will set Regularization.reference_model to m0.
SimPEG.InvProblem will set Regularization.reference_model to m0.
SimPEG.InvProblem will set Regularization.reference_model to m0.

                    SimPEG.InvProblem is setting bfgsH0 to the inverse of the eval2Deriv.
                    ***Done using the default solver Pardiso and no solver_opts.***

Alpha scales: [3.466585984471505, 0.0, 3.497667477042771e-06, 0.0]
Calculating the scaling parameter.
Scale Multipliers:  [0.10253344 0.89746656]
<class 'SimPEG.regularization.pgi.PGIsmallness'>
Initial data misfit scales:  [0.10253344 0.89746656]
model has any nan: 0
=============================== Projected GNCG ===============================
  #     beta     phi_d     phi_m       f      |proj(x-g)-x|  LS    Comment
-----------------------------------------------------------------------------
x0 has any nan: 0
   0  1.97e+01  3.00e+05  0.00e+00  3.00e+05    1.41e+02      0
geophys. misfits: 976.3 (target 30.0 [False]); 75.5 (target 30.0 [False]) | smallness misfit: 2987.0 (target: 200.0 [False])
Beta cooling evaluation: progress: [976.3  75.5]; minimum progress targets: [240000. 240000.]
   1  1.97e+01  1.68e+02  4.11e+01  9.79e+02    9.62e+01      0
geophys. misfits: 450.0 (target 30.0 [False]); 17.6 (target 30.0 [True]) | smallness misfit: 1375.5 (target: 200.0 [False])
Beta cooling evaluation: progress: [450.   17.6]; minimum progress targets: [781.   60.4]
Updating scaling for data misfits by  1.708075361874646
New scales: [0.16328045 0.83671955]
   2  1.97e+01  8.82e+01  3.98e+01  8.73e+02    8.12e+01      0   Skip BFGS
geophys. misfits: 233.8 (target 30.0 [False]); 17.3 (target 30.0 [True]) | smallness misfit: 1264.2 (target: 200.0 [False])
Beta cooling evaluation: progress: [233.8  17.3]; minimum progress targets: [360.  30.]
Updating scaling for data misfits by  1.73480762458182
New scales: [0.25291544 0.74708456]
   3  1.97e+01  7.20e+01  4.12e+01  8.84e+02    7.80e+01      0
geophys. misfits: 128.9 (target 30.0 [False]); 17.6 (target 30.0 [True]) | smallness misfit: 1189.0 (target: 200.0 [False])
Beta cooling evaluation: progress: [128.9  17.6]; minimum progress targets: [187.  30.]
Updating scaling for data misfits by  1.7020492337099165
New scales: [0.36556512 0.63443488]
   4  1.97e+01  5.83e+01  4.22e+01  8.91e+02    7.70e+01      0
geophys. misfits: 80.8 (target 30.0 [False]); 18.7 (target 30.0 [True]) | smallness misfit: 1131.5 (target: 200.0 [False])
Beta cooling evaluation: progress: [80.8 18.7]; minimum progress targets: [103.1  30. ]
Updating scaling for data misfits by  1.6069709546804007
New scales: [0.48077468 0.51922532]
   5  1.97e+01  4.85e+01  4.29e+01  8.95e+02    7.39e+01      0   Skip BFGS
geophys. misfits: 58.9 (target 30.0 [False]); 20.5 (target 30.0 [True]) | smallness misfit: 1083.9 (target: 200.0 [False])
Beta cooling evaluation: progress: [58.9 20.5]; minimum progress targets: [64.6 30. ]
Updating scaling for data misfits by  1.4662958220227225
New scales: [0.5758598 0.4241402]
   6  1.97e+01  4.26e+01  4.33e+01  8.97e+02    6.95e+01      0   Skip BFGS
geophys. misfits: 48.7 (target 30.0 [False]); 22.9 (target 30.0 [True]) | smallness misfit: 1044.7 (target: 200.0 [False])
Beta cooling evaluation: progress: [48.7 22.9]; minimum progress targets: [47.1 30. ]
Decreasing beta to counter data misfit decrase plateau.
Updating scaling for data misfits by  1.3128511097465423
New scales: [0.64060739 0.35939261]
   7  9.87e+00  3.94e+01  4.35e+01  4.69e+02    9.23e+01      0   Skip BFGS
geophys. misfits: 25.6 (target 30.0 [True]); 16.8 (target 30.0 [True]) | smallness misfit: 1100.7 (target: 200.0 [False])
Beta cooling evaluation: progress: [25.6 16.8]; minimum progress targets: [39. 30.]
Warming alpha_pgi to favor clustering:  1.4784430570260136
   8  9.87e+00  2.24e+01  4.58e+01  4.74e+02    4.17e+01      0
geophys. misfits: 25.4 (target 30.0 [True]); 20.2 (target 30.0 [True]) | smallness misfit: 985.3 (target: 200.0 [False])
Beta cooling evaluation: progress: [25.4 20.2]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  1.9732502654200745
   9  9.87e+00  2.35e+01  4.67e+01  4.84e+02    7.70e+01      0
geophys. misfits: 25.2 (target 30.0 [True]); 23.5 (target 30.0 [True]) | smallness misfit: 898.0 (target: 200.0 [False])
Beta cooling evaluation: progress: [25.2 23.5]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  2.4299925361475583
  10  9.87e+00  2.46e+01  4.74e+01  4.93e+02    7.43e+01      0   Skip BFGS
geophys. misfits: 25.1 (target 30.0 [True]); 26.7 (target 30.0 [True]) | smallness misfit: 832.4 (target: 200.0 [False])
Beta cooling evaluation: progress: [25.1 26.7]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  2.817109952670229
  11  9.87e+00  2.57e+01  4.80e+01  4.99e+02    5.60e+01      0   Skip BFGS
geophys. misfits: 25.1 (target 30.0 [True]); 29.3 (target 30.0 [True]) | smallness misfit: 785.8 (target: 200.0 [False])
Beta cooling evaluation: progress: [25.1 29.3]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  3.129877772141576
  12  9.87e+00  2.66e+01  4.84e+01  5.04e+02    3.63e+01      0   Skip BFGS
geophys. misfits: 25.0 (target 30.0 [True]); 31.5 (target 30.0 [False]) | smallness misfit: 752.5 (target: 200.0 [False])
Beta cooling evaluation: progress: [25.  31.5]; minimum progress targets: [30. 30.]
Decreasing beta to counter data misfit increase.
Updating scaling for data misfits by  1.198529568044168
New scales: [0.59794405 0.40205595]
  13  4.93e+00  2.76e+01  4.83e+01  2.66e+02    8.76e+01      0   Skip BFGS
geophys. misfits: 19.8 (target 30.0 [True]); 18.3 (target 30.0 [True]) | smallness misfit: 855.5 (target: 200.0 [False])
Beta cooling evaluation: progress: [19.8 18.3]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  4.9358512209031025
  14  4.93e+00  1.92e+01  5.28e+01  2.80e+02    6.23e+01      0
geophys. misfits: 19.9 (target 30.0 [True]); 23.1 (target 30.0 [True]) | smallness misfit: 708.0 (target: 200.0 [False])
Beta cooling evaluation: progress: [19.9 23.1]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  6.922849426719274
  15  4.93e+00  2.12e+01  5.52e+01  2.94e+02    6.80e+01      0
geophys. misfits: 20.5 (target 30.0 [True]); 29.7 (target 30.0 [True]) | smallness misfit: 600.8 (target: 200.0 [False])
Beta cooling evaluation: progress: [20.5 29.7]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  8.557932009373166
  16  4.93e+00  2.42e+01  5.65e+01  3.03e+02    8.55e+01      0
geophys. misfits: 20.9 (target 30.0 [True]); 34.2 (target 30.0 [False]) | smallness misfit: 531.3 (target: 200.0 [False])
Beta cooling evaluation: progress: [20.9 34.2]; minimum progress targets: [30. 30.]
Decreasing beta to counter data misfit increase.
Updating scaling for data misfits by  1.4360536637893107
New scales: [0.50875087 0.49124913]
  17  2.47e+00  2.74e+01  5.60e+01  1.65e+02    9.40e+01      0   Skip BFGS
geophys. misfits: 18.8 (target 30.0 [True]); 18.8 (target 30.0 [True]) | smallness misfit: 633.3 (target: 200.0 [False])
Beta cooling evaluation: progress: [18.8 18.8]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  13.647381256803174
  18  2.47e+00  1.88e+01  6.51e+01  1.79e+02    8.74e+01      0
geophys. misfits: 19.6 (target 30.0 [True]); 23.8 (target 30.0 [True]) | smallness misfit: 483.5 (target: 200.0 [False])
Beta cooling evaluation: progress: [19.6 23.8]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  19.045404598769014
  19  2.47e+00  2.17e+01  6.88e+01  1.91e+02    8.65e+01      0
geophys. misfits: 20.5 (target 30.0 [True]); 25.7 (target 30.0 [True]) | smallness misfit: 407.0 (target: 200.0 [False])
Beta cooling evaluation: progress: [20.5 25.7]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  25.045740275743086
  20  2.47e+00  2.31e+01  7.29e+01  2.03e+02    9.08e+01      0   Skip BFGS
geophys. misfits: 21.0 (target 30.0 [True]); 27.2 (target 30.0 [True]) | smallness misfit: 339.1 (target: 200.0 [False])
Beta cooling evaluation: progress: [21.  27.2]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  31.722142767214407
  21  2.47e+00  2.40e+01  7.68e+01  2.13e+02    9.80e+01      0
geophys. misfits: 22.2 (target 30.0 [True]); 29.0 (target 30.0 [True]) | smallness misfit: 300.9 (target: 200.0 [False])
Beta cooling evaluation: progress: [22.2 29. ]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  37.82019981845879
  22  2.47e+00  2.56e+01  7.96e+01  2.22e+02    1.01e+02      0
geophys. misfits: 23.1 (target 30.0 [True]); 29.2 (target 30.0 [True]) | smallness misfit: 244.9 (target: 200.0 [False])
Beta cooling evaluation: progress: [23.1 29.2]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  43.95066985849938
  23  2.47e+00  2.61e+01  8.15e+01  2.27e+02    9.91e+01      0
geophys. misfits: 23.7 (target 30.0 [True]); 31.7 (target 30.0 [False]) | smallness misfit: 231.9 (target: 200.0 [False])
Beta cooling evaluation: progress: [23.7 31.7]; minimum progress targets: [30. 30.]
Decreasing beta to counter data misfit increase.
Updating scaling for data misfits by  1.2665719494814376
New scales: [0.44984254 0.55015746]
  24  1.23e+00  2.81e+01  8.06e+01  1.28e+02    1.07e+02      0
geophys. misfits: 21.3 (target 30.0 [True]); 19.0 (target 30.0 [True]) | smallness misfit: 257.6 (target: 200.0 [False])
Beta cooling evaluation: progress: [21.3 19. ]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  65.70376545749437
  25  1.23e+00  2.00e+01  9.68e+01  1.39e+02    1.05e+02      0
geophys. misfits: 22.3 (target 30.0 [True]); 16.9 (target 30.0 [True]) | smallness misfit: 233.0 (target: 200.0 [False])
Beta cooling evaluation: progress: [22.3 16.9]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  102.4300759001624
  26  1.23e+00  1.93e+01  1.14e+02  1.60e+02    1.10e+02      0
geophys. misfits: 22.6 (target 30.0 [True]); 16.1 (target 30.0 [True]) | smallness misfit: 202.7 (target: 200.0 [False])
Beta cooling evaluation: progress: [22.6 16.1]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  163.69186464532837
  27  1.23e+00  1.90e+01  1.40e+02  1.92e+02    1.20e+02      0
geophys. misfits: 23.7 (target 30.0 [True]); 15.5 (target 30.0 [True]) | smallness misfit: 187.1 (target: 200.0 [True])
All targets have been reached
Beta cooling evaluation: progress: [23.7 15.5]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  262.2468013455045
------------------------- STOP! -------------------------
1 : |fc-fOld| = 0.0000e+00 <= tolF*(1+|f0|) = 3.0000e+04
0 : |xc-x_last| = 3.5166e-01 <= tolX*(1+|x0|) = 1.0000e-06
0 : |proj(x-g)-x|    = 1.1983e+02 <= tolG          = 1.0000e-01
0 : |proj(x-g)-x|    = 1.1983e+02 <= 1e3*eps       = 1.0000e-02
0 : maxIter   =      50    <= iter          =     28
------------------------- DONE! -------------------------
SimPEG.InvProblem will set Regularization.reference_model to m0.
SimPEG.InvProblem will set Regularization.reference_model to m0.
SimPEG.InvProblem will set Regularization.reference_model to m0.

                    SimPEG.InvProblem is setting bfgsH0 to the inverse of the eval2Deriv.
                    ***Done using the default solver Pardiso and no solver_opts.***

Alpha scales: [0.00034499025026179766, 0.0, 3.7949084087632494e-06, 0.0]
Calculating the scaling parameter.
Scale Multipliers:  [0.10253344 0.89746656]
<class 'SimPEG.regularization.pgi.PGIsmallness'>
Initial data misfit scales:  [0.10253344 0.89746656]
model has any nan: 0
=============================== Projected GNCG ===============================
  #     beta     phi_d     phi_m       f      |proj(x-g)-x|  LS    Comment
-----------------------------------------------------------------------------
x0 has any nan: 0
   0  1.97e+03  3.00e+05  0.00e+00  3.00e+05    1.41e+02      0
geophys. misfits: 84899.9 (target 30.0 [False]); 63769.0 (target 30.0 [False]) | smallness misfit: 307.0 (target: 200.0 [False])
Beta cooling evaluation: progress: [84899.9 63769. ]; minimum progress targets: [240000. 240000.]
   1  1.97e+03  6.59e+04  7.14e-01  6.73e+04    8.95e+01      0
geophys. misfits: 561.9 (target 30.0 [False]); 14.5 (target 30.0 [True]) | smallness misfit: 75.2 (target: 200.0 [True])
Beta cooling evaluation: progress: [561.9  14.5]; minimum progress targets: [67919.9 51015.2]
Updating scaling for data misfits by  2.0742079849535013
New scales: [0.19157515 0.80842485]
   2  1.97e+03  1.19e+02  1.99e-01  5.10e+02    1.12e+02      0   Skip BFGS
geophys. misfits: 52.4 (target 30.0 [False]); 14.5 (target 30.0 [True]) | smallness misfit: 50.4 (target: 200.0 [True])
Beta cooling evaluation: progress: [52.4 14.5]; minimum progress targets: [449.5  30. ]
Updating scaling for data misfits by  2.0657867057786627
New scales: [0.32865019 0.67134981]
   3  1.97e+03  2.70e+01  1.41e-01  3.04e+02    8.52e+01      0   Skip BFGS
geophys. misfits: 32.2 (target 30.0 [False]); 15.0 (target 30.0 [True]) | smallness misfit: 59.6 (target: 200.0 [True])
Beta cooling evaluation: progress: [32.2 15. ]; minimum progress targets: [42. 30.]
Updating scaling for data misfits by  2.005372276424505
New scales: [0.49538346 0.50461654]
   4  1.97e+03  2.35e+01  1.68e-01  3.54e+02    8.94e+01      0
geophys. misfits: 25.4 (target 30.0 [True]); 17.0 (target 30.0 [True]) | smallness misfit: 48.3 (target: 200.0 [True])
All targets have been reached
Beta cooling evaluation: progress: [25.4 17. ]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  1.47406056633217
------------------------- STOP! -------------------------
1 : |fc-fOld| = 0.0000e+00 <= tolF*(1+|f0|) = 3.0000e+04
0 : |xc-x_last| = 1.6960e-01 <= tolX*(1+|x0|) = 1.0000e-06
0 : |proj(x-g)-x|    = 8.9403e+01 <= tolG          = 1.0000e-01
0 : |proj(x-g)-x|    = 8.9403e+01 <= 1e3*eps       = 1.0000e-02
0 : maxIter   =      50    <= iter          =      5
------------------------- DONE! -------------------------
SimPEG.InvProblem will set Regularization.reference_model to m0.
SimPEG.InvProblem will set Regularization.reference_model to m0.

                    SimPEG.InvProblem is setting bfgsH0 to the inverse of the eval2Deriv.
                    ***Done using the default solver Pardiso and no solver_opts.***

Alpha scales: [3.5188574849327586e-05, 0.0, 3.4826374354602616e-05, 0.0]
Calculating the scaling parameter.
Scale Multipliers:  [0.10253344 0.89746656]
/home/vsts/work/1/s/SimPEG/directives/directives.py:332: UserWarning:

There is no PGI regularization. Smallness target is turned off (TriggerSmall flag)

Initial data misfit scales:  [0.10253344 0.89746656]
model has any nan: 0
=============================== Projected GNCG ===============================
  #     beta     phi_d     phi_m       f      |proj(x-g)-x|  LS    Comment
-----------------------------------------------------------------------------
x0 has any nan: 0
   0  1.07e+06  3.00e+05  0.00e+00  3.00e+05    1.41e+02      0
geophys. misfits: 53866.9 (target 30.0 [False]); 36983.1 (target 30.0 [False])
   1  2.13e+05  3.87e+04  4.18e-02  4.76e+04    1.38e+02      0
geophys. misfits: 7708.0 (target 30.0 [False]); 4065.3 (target 30.0 [False])
   2  4.27e+04  4.44e+03  1.06e-01  8.95e+03    1.31e+02      0   Skip BFGS
geophys. misfits: 509.1 (target 30.0 [False]); 260.0 (target 30.0 [False])
   3  8.53e+03  2.86e+02  1.40e-01  1.48e+03    1.05e+02      0   Skip BFGS
geophys. misfits: 42.8 (target 30.0 [False]); 27.0 (target 30.0 [True])
Updating scaling for data misfits by  1.109305984673468
New scales: [0.11248033 0.88751967]
   4  1.71e+03  2.88e+01  1.51e-01  2.86e+02    8.56e+01      0   Skip BFGS
geophys. misfits: 18.4 (target 30.0 [True]); 10.7 (target 30.0 [True])
All targets have been reached
------------------------- STOP! -------------------------
1 : |fc-fOld| = 0.0000e+00 <= tolF*(1+|f0|) = 3.0000e+04
0 : |xc-x_last| = 4.3953e-01 <= tolX*(1+|x0|) = 1.0000e-06
0 : |proj(x-g)-x|    = 8.5526e+01 <= tolG          = 1.0000e-01
0 : |proj(x-g)-x|    = 8.5526e+01 <= 1e3*eps       = 1.0000e-02
0 : maxIter   =      50    <= iter          =      5
------------------------- DONE! -------------------------
/home/vsts/work/1/s/examples/10-pgi/plot_inv_1_PGI_Linear_1D_joint_WithRelationships.py:301: UserWarning:

marker is redundantly defined by the 'marker' keyword argument and the fmt string "b.-" (-> marker='.'). The keyword argument will take precedence.

/home/vsts/work/1/s/examples/10-pgi/plot_inv_1_PGI_Linear_1D_joint_WithRelationships.py:308: UserWarning:

marker is redundantly defined by the 'marker' keyword argument and the fmt string "r.-" (-> marker='.'). The keyword argument will take precedence.

/home/vsts/work/1/s/examples/10-pgi/plot_inv_1_PGI_Linear_1D_joint_WithRelationships.py:346: UserWarning:

marker is redundantly defined by the 'marker' keyword argument and the fmt string "b.-" (-> marker='.'). The keyword argument will take precedence.

/home/vsts/work/1/s/examples/10-pgi/plot_inv_1_PGI_Linear_1D_joint_WithRelationships.py:353: UserWarning:

marker is redundantly defined by the 'marker' keyword argument and the fmt string "r.-" (-> marker='.'). The keyword argument will take precedence.

/home/vsts/work/1/s/examples/10-pgi/plot_inv_1_PGI_Linear_1D_joint_WithRelationships.py:360: UserWarning:

The following kwargs were not used by contour: 'label'

/home/vsts/work/1/s/examples/10-pgi/plot_inv_1_PGI_Linear_1D_joint_WithRelationships.py:368: UserWarning:

The following kwargs were not used by contour: 'label'

/home/vsts/work/1/s/examples/10-pgi/plot_inv_1_PGI_Linear_1D_joint_WithRelationships.py:402: UserWarning:

marker is redundantly defined by the 'marker' keyword argument and the fmt string "b.-" (-> marker='.'). The keyword argument will take precedence.

/home/vsts/work/1/s/examples/10-pgi/plot_inv_1_PGI_Linear_1D_joint_WithRelationships.py:409: UserWarning:

marker is redundantly defined by the 'marker' keyword argument and the fmt string "r.-" (-> marker='.'). The keyword argument will take precedence.

import discretize as Mesh
import matplotlib.pyplot as plt
import numpy as np
from SimPEG import (
    data_misfit,
    directives,
    inverse_problem,
    inversion,
    maps,
    optimization,
    regularization,
    simulation,
    utils,
)

# Random seed for reproductibility
np.random.seed(1)
# Mesh
N = 100
mesh = Mesh.TensorMesh([N])

# Survey design parameters
nk = 30
jk = np.linspace(1.0, 59.0, nk)
p = -0.25
q = 0.25


# Physics
def g(k):
    return np.exp(p * jk[k] * mesh.cell_centers_x) * np.cos(
        np.pi * q * jk[k] * mesh.cell_centers_x
    )


G = np.empty((nk, mesh.nC))

for i in range(nk):
    G[i, :] = g(i)

m0 = np.zeros(mesh.nC)
m0[20:41] = np.linspace(0.0, 1.0, 21)
m0[41:57] = np.linspace(-1, 0.0, 16)

poly0 = maps.PolynomialPetroClusterMap(coeffyx=np.r_[0.0, -4.0, 4.0])
poly1 = maps.PolynomialPetroClusterMap(coeffyx=np.r_[-0.0, 3.0, 6.0, 6.0])
poly0_inverse = maps.PolynomialPetroClusterMap(coeffyx=-np.r_[0.0, -4.0, 4.0])
poly1_inverse = maps.PolynomialPetroClusterMap(coeffyx=-np.r_[0.0, 3.0, 6.0, 6.0])
cluster_mapping = [maps.IdentityMap(), poly0_inverse, poly1_inverse]

m1 = np.zeros(100)
m1[20:41] = 1.0 + (poly0 * np.vstack([m0[20:41], m1[20:41]]).T)[:, 1]
m1[41:57] = -1.0 + (poly1 * np.vstack([m0[41:57], m1[41:57]]).T)[:, 1]

model2d = np.vstack([m0, m1]).T
m = utils.mkvc(model2d)

clfmapping = utils.GaussianMixtureWithNonlinearRelationships(
    mesh=mesh,
    n_components=3,
    covariance_type="full",
    tol=1e-8,
    reg_covar=1e-3,
    max_iter=1000,
    n_init=100,
    init_params="kmeans",
    random_state=None,
    warm_start=False,
    means_init=np.array(
        [
            [0, 0],
            [m0[20:41].mean(), m1[20:41].mean()],
            [m0[41:57].mean(), m1[41:57].mean()],
        ]
    ),
    verbose=0,
    verbose_interval=10,
    cluster_mapping=cluster_mapping,
)
clfmapping = clfmapping.fit(model2d)

clfnomapping = utils.WeightedGaussianMixture(
    mesh=mesh,
    n_components=3,
    covariance_type="full",
    tol=1e-8,
    reg_covar=1e-3,
    max_iter=1000,
    n_init=100,
    init_params="kmeans",
    random_state=None,
    warm_start=False,
    verbose=0,
    verbose_interval=10,
)
clfnomapping = clfnomapping.fit(model2d)

wires = maps.Wires(("m1", mesh.nC), ("m2", mesh.nC))

relatrive_error = 0.01
noise_floor = 0.0

prob1 = simulation.LinearSimulation(mesh, G=G, model_map=wires.m1)
survey1 = prob1.make_synthetic_data(
    m, relative_error=relatrive_error, noise_floor=noise_floor, add_noise=True
)

prob2 = simulation.LinearSimulation(mesh, G=G, model_map=wires.m2)
survey2 = prob2.make_synthetic_data(
    m, relative_error=relatrive_error, noise_floor=noise_floor, add_noise=True
)


dmis1 = data_misfit.L2DataMisfit(simulation=prob1, data=survey1)
dmis2 = data_misfit.L2DataMisfit(simulation=prob2, data=survey2)
dmis = dmis1 + dmis2
minit = np.zeros_like(m)

# Distance weighting
wr1 = np.sum(prob1.G**2.0, axis=0) ** 0.5 / mesh.cell_volumes
wr1 = wr1 / np.max(wr1)
wr2 = np.sum(prob2.G**2.0, axis=0) ** 0.5 / mesh.cell_volumes
wr2 = wr2 / np.max(wr2)

reg_simple = regularization.PGI(
    mesh=mesh,
    gmmref=clfmapping,
    gmm=clfmapping,
    approx_gradient=True,
    wiresmap=wires,
    non_linear_relationships=True,
    weights_list=[wr1, wr2],
)

opt = optimization.ProjectedGNCG(
    maxIter=50,
    tolX=1e-6,
    maxIterCG=100,
    tolCG=1e-3,
    lower=-10,
    upper=10,
)

invProb = inverse_problem.BaseInvProblem(dmis, reg_simple, opt)

# directives
scales = directives.ScalingMultipleDataMisfits_ByEig(
    chi0_ratio=np.r_[1.0, 1.0], verbose=True, n_pw_iter=10
)
scaling_schedule = directives.JointScalingSchedule(verbose=True)
alpha0_ratio = np.r_[1e6, 1e4, 1, 1]
alphas = directives.AlphasSmoothEstimate_ByEig(
    alpha0_ratio=alpha0_ratio, n_pw_iter=10, verbose=True
)
beta = directives.BetaEstimate_ByEig(beta0_ratio=1e-5, n_pw_iter=10)
betaIt = directives.PGI_BetaAlphaSchedule(
    verbose=True,
    coolingFactor=2.0,
    progress=0.2,
)
targets = directives.MultiTargetMisfits(verbose=True)
petrodir = directives.PGI_UpdateParameters(update_gmm=False)

# Setup Inversion
inv = inversion.BaseInversion(
    invProb,
    directiveList=[alphas, scales, beta, petrodir, targets, betaIt, scaling_schedule],
)

mcluster_map = inv.run(minit)

# Inversion with no nonlinear mapping
reg_simple_no_map = regularization.PGI(
    mesh=mesh,
    gmmref=clfnomapping,
    gmm=clfnomapping,
    approx_gradient=True,
    wiresmap=wires,
    non_linear_relationships=False,
    weights_list=[wr1, wr2],
)

opt = optimization.ProjectedGNCG(
    maxIter=50,
    tolX=1e-6,
    maxIterCG=100,
    tolCG=1e-3,
    lower=-10,
    upper=10,
)

invProb = inverse_problem.BaseInvProblem(dmis, reg_simple_no_map, opt)

# directives
scales = directives.ScalingMultipleDataMisfits_ByEig(
    chi0_ratio=np.r_[1.0, 1.0], verbose=True, n_pw_iter=10
)
scaling_schedule = directives.JointScalingSchedule(verbose=True)
alpha0_ratio = np.r_[100.0 * np.ones(2), 1, 1]
alphas = directives.AlphasSmoothEstimate_ByEig(
    alpha0_ratio=alpha0_ratio, n_pw_iter=10, verbose=True
)
beta = directives.BetaEstimate_ByEig(beta0_ratio=1e-5, n_pw_iter=10)
betaIt = directives.PGI_BetaAlphaSchedule(
    verbose=True,
    coolingFactor=2.0,
    progress=0.2,
)
targets = directives.MultiTargetMisfits(
    chiSmall=1.0, TriggerSmall=True, TriggerTheta=False, verbose=True
)
petrodir = directives.PGI_UpdateParameters(update_gmm=False)

# Setup Inversion
inv = inversion.BaseInversion(
    invProb,
    directiveList=[alphas, scales, beta, petrodir, targets, betaIt, scaling_schedule],
)

mcluster_no_map = inv.run(minit)

# WeightedLeastSquares Inversion

reg1 = regularization.WeightedLeastSquares(
    mesh, alpha_s=1.0, alpha_x=1.0, mapping=wires.m1, weights={"cell_weights": wr1}
)

reg2 = regularization.WeightedLeastSquares(
    mesh, alpha_s=1.0, alpha_x=1.0, mapping=wires.m2, weights={"cell_weights": wr2}
)

reg = reg1 + reg2

opt = optimization.ProjectedGNCG(
    maxIter=50,
    tolX=1e-6,
    maxIterCG=100,
    tolCG=1e-3,
    lower=-10,
    upper=10,
)

invProb = inverse_problem.BaseInvProblem(dmis, reg, opt)

# directives
alpha0_ratio = np.r_[1, 1, 1, 1]
alphas = directives.AlphasSmoothEstimate_ByEig(
    alpha0_ratio=alpha0_ratio, n_pw_iter=10, verbose=True
)
scales = directives.ScalingMultipleDataMisfits_ByEig(
    chi0_ratio=np.r_[1.0, 1.0], verbose=True, n_pw_iter=10
)
scaling_schedule = directives.JointScalingSchedule(verbose=True)
beta = directives.BetaEstimate_ByEig(beta0_ratio=1e-5, n_pw_iter=10)
beta_schedule = directives.BetaSchedule(coolingFactor=5.0, coolingRate=1)
targets = directives.MultiTargetMisfits(
    TriggerSmall=False,
    verbose=True,
)

# Setup Inversion
inv = inversion.BaseInversion(
    invProb,
    directiveList=[alphas, scales, beta, targets, beta_schedule, scaling_schedule],
)

mtik = inv.run(minit)


# Final Plot
fig, axes = plt.subplots(3, 4, figsize=(25, 15))
axes = axes.reshape(12)
left, width = 0.25, 0.5
bottom, height = 0.25, 0.5
right = left + width
top = bottom + height

axes[0].set_axis_off()
axes[0].text(
    0.5 * (left + right),
    0.5 * (bottom + top),
    ("Using true nonlinear\npetrophysical relationships"),
    horizontalalignment="center",
    verticalalignment="center",
    fontsize=20,
    color="black",
    transform=axes[0].transAxes,
)

axes[1].plot(mesh.cell_centers_x, wires.m1 * mcluster_map, "b.-", ms=5, marker="v")
axes[1].plot(mesh.cell_centers_x, wires.m1 * m, "k--")
axes[1].set_title("Problem 1")
axes[1].legend(["Recovered Model", "True Model"], loc=1)
axes[1].set_xlabel("X")
axes[1].set_ylabel("Property 1")

axes[2].plot(mesh.cell_centers_x, wires.m2 * mcluster_map, "r.-", ms=5, marker="v")
axes[2].plot(mesh.cell_centers_x, wires.m2 * m, "k--")
axes[2].set_title("Problem 2")
axes[2].legend(["Recovered Model", "True Model"], loc=1)
axes[2].set_xlabel("X")
axes[2].set_ylabel("Property 2")

x, y = np.mgrid[-1:1:0.01, -4:2:0.01]
pos = np.empty(x.shape + (2,))
pos[:, :, 0] = x
pos[:, :, 1] = y
CS = axes[3].contour(
    x,
    y,
    np.exp(clfmapping.score_samples(pos.reshape(-1, 2)).reshape(x.shape)),
    100,
    alpha=0.25,
    cmap="viridis",
)
axes[3].scatter(wires.m1 * mcluster_map, wires.m2 * mcluster_map, marker="v")
axes[3].set_title("Petrophysical Distribution")
CS.collections[0].set_label("")
axes[3].legend(["True Petrophysical Distribution", "Recovered model crossplot"])
axes[3].set_xlabel("Property 1")
axes[3].set_ylabel("Property 2")

axes[4].set_axis_off()
axes[4].text(
    0.5 * (left + right),
    0.5 * (bottom + top),
    ("Using a pure\nGaussian distribution"),
    horizontalalignment="center",
    verticalalignment="center",
    fontsize=20,
    color="black",
    transform=axes[4].transAxes,
)

axes[5].plot(mesh.cell_centers_x, wires.m1 * mcluster_no_map, "b.-", ms=5, marker="v")
axes[5].plot(mesh.cell_centers_x, wires.m1 * m, "k--")
axes[5].set_title("Problem 1")
axes[5].legend(["Recovered Model", "True Model"], loc=1)
axes[5].set_xlabel("X")
axes[5].set_ylabel("Property 1")

axes[6].plot(mesh.cell_centers_x, wires.m2 * mcluster_no_map, "r.-", ms=5, marker="v")
axes[6].plot(mesh.cell_centers_x, wires.m2 * m, "k--")
axes[6].set_title("Problem 2")
axes[6].legend(["Recovered Model", "True Model"], loc=1)
axes[6].set_xlabel("X")
axes[6].set_ylabel("Property 2")

CSF = axes[7].contour(
    x,
    y,
    np.exp(clfmapping.score_samples(pos.reshape(-1, 2)).reshape(x.shape)),
    100,
    alpha=0.5,
    label="True Petro. Distribution",
)
CS = axes[7].contour(
    x,
    y,
    np.exp(clfnomapping.score_samples(pos.reshape(-1, 2)).reshape(x.shape)),
    500,
    cmap="viridis",
    linestyles="--",
    label="Modeled Petro. Distribution",
)
axes[7].scatter(
    wires.m1 * mcluster_no_map,
    wires.m2 * mcluster_no_map,
    marker="v",
    label="Recovered model crossplot",
)
axes[7].set_title("Petrophysical Distribution")
axes[7].legend()
axes[7].set_xlabel("Property 1")
axes[7].set_ylabel("Property 2")

# Tikonov

axes[8].set_axis_off()
axes[8].text(
    0.5 * (left + right),
    0.5 * (bottom + top),
    ("Least-Squares\n~Using a single cluster"),
    horizontalalignment="center",
    verticalalignment="center",
    fontsize=20,
    color="black",
    transform=axes[8].transAxes,
)

axes[9].plot(mesh.cell_centers_x, wires.m1 * mtik, "b.-", ms=5, marker="v")
axes[9].plot(mesh.cell_centers_x, wires.m1 * m, "k--")
axes[9].set_title("Problem 1")
axes[9].legend(["Recovered Model", "True Model"], loc=1)
axes[9].set_xlabel("X")
axes[9].set_ylabel("Property 1")

axes[10].plot(mesh.cell_centers_x, wires.m2 * mtik, "r.-", ms=5, marker="v")
axes[10].plot(mesh.cell_centers_x, wires.m2 * m, "k--")
axes[10].set_title("Problem 2")
axes[10].legend(["Recovered Model", "True Model"], loc=1)
axes[10].set_xlabel("X")
axes[10].set_ylabel("Property 2")

CS = axes[11].contour(
    x,
    y,
    np.exp(clfmapping.score_samples(pos.reshape(-1, 2)).reshape(x.shape)),
    100,
    alpha=0.25,
    cmap="viridis",
)
axes[11].scatter(wires.m1 * mtik, wires.m2 * mtik, marker="v")
axes[11].set_title("Petro Distribution")
CS.collections[0].set_label("")
axes[11].legend(["True Petro Distribution", "Recovered model crossplot"])
axes[11].set_xlabel("Property 1")
axes[11].set_ylabel("Property 2")
plt.subplots_adjust(wspace=0.3, hspace=0.3, top=0.85)
plt.show()

Total running time of the script: (0 minutes 55.403 seconds)

Estimated memory usage: 17 MB

Gallery generated by Sphinx-Gallery