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
Running inversion with SimPEG v0.25.2.dev9+g43b0120dd
Alpha scales: [np.float64(3.491829047521848), np.float64(0.0), np.float64(3.5189375267533188e-06), np.float64(0.0)]
Calculating the scaling parameter.
Scale Multipliers:  [0.10096782 0.89903218]
<class 'simpeg.regularization.pgi.PGIsmallness'>
Initial data misfit scales:  [0.10096782 0.89903218]
================================================= Projected GNCG =================================================
  #     beta     phi_d     phi_m       f      |proj(x-g)-x|  LS   iter_CG   CG |Ax-b|/|b|  CG |Ax-b|   Comment
-----------------------------------------------------------------------------------------------------------------
   0  1.99e+01  3.00e+05  0.00e+00  3.00e+05                         0           inf          inf
   1  1.99e+01  1.79e+03  1.69e+02  5.13e+03    1.41e+02      0      19       9.68e-04     9.08e+03
geophys. misfits: 8329.3 (target 30.0 [False]); 1050.9 (target 30.0 [False]) | smallness misfit: 3982.8 (target: 200.0 [False])
Beta cooling evaluation: progress: [8329.3 1050.9]; minimum progress targets: [240000. 240000.]
   2  1.99e+01  6.12e+01  4.06e+01  8.68e+02    1.40e+02      0     100       2.79e-03     2.53e+01   Skip BFGS
geophys. misfits: 475.7 (target 30.0 [False]); 14.7 (target 30.0 [True]) | smallness misfit: 1377.7 (target: 200.0 [False])
Beta cooling evaluation: progress: [475.7  14.7]; minimum progress targets: [6663.4  840.7]
Updating scaling for data misfits by  2.0454061133079002
New scales: [0.18680272 0.81319728]
   3  1.99e+01  4.82e+01  4.16e+01  8.75e+02    8.59e+01      0     100       1.40e-02     7.08e+00   Skip BFGS
geophys. misfits: 196.5 (target 30.0 [False]); 14.2 (target 30.0 [True]) | smallness misfit: 1132.6 (target: 200.0 [False])
Beta cooling evaluation: progress: [196.5  14.2]; minimum progress targets: [380.6  30. ]
Updating scaling for data misfits by  2.119786367854586
New scales: [0.3274799 0.6725201]
   4  1.99e+01  3.79e+01  4.29e+01  8.90e+02    8.21e+01      0     100       2.23e-01     1.16e+02
geophys. misfits: 85.5 (target 30.0 [False]); 14.8 (target 30.0 [True]) | smallness misfit: 1074.6 (target: 200.0 [False])
Beta cooling evaluation: progress: [85.5 14.8]; minimum progress targets: [157.2  30. ]
Updating scaling for data misfits by  2.033251004699464
New scales: [0.49750769 0.50249231]
   5  1.99e+01  3.16e+01  4.36e+01  8.98e+02    8.23e+01      0     100       3.13e-02     1.33e+01   Skip BFGS
geophys. misfits: 46.7 (target 30.0 [False]); 16.7 (target 30.0 [True]) | smallness misfit: 1017.6 (target: 200.0 [False])
Beta cooling evaluation: progress: [46.7 16.7]; minimum progress targets: [68.4 30. ]
Updating scaling for data misfits by  1.8017555577268096
New scales: [0.64078944 0.35921056]
   6  1.99e+01  2.89e+01  4.39e+01  9.01e+02    7.67e+01      0     100       5.62e-02     1.26e+01   Skip BFGS
geophys. misfits: 33.7 (target 30.0 [False]); 20.3 (target 30.0 [True]) | smallness misfit: 968.5 (target: 200.0 [False])
Beta cooling evaluation: progress: [33.7 20.3]; minimum progress targets: [37.4 30. ]
Updating scaling for data misfits by  1.4808472768239511
New scales: [0.72539977 0.27460023]
   7  1.99e+01  2.78e+01  4.40e+01  9.02e+02    6.51e+01      0     100       1.26e-01     1.37e+01   Skip BFGS
geophys. misfits: 29.0 (target 30.0 [True]); 24.7 (target 30.0 [True]) | smallness misfit: 930.7 (target: 200.0 [False])
Beta cooling evaluation: progress: [29.  24.7]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  1.1251683149444558
   8  1.99e+01  2.84e+01  4.42e+01  9.07e+02    2.51e+01      0     100       4.58e-01     1.19e+01   Skip BFGS
geophys. misfits: 28.9 (target 30.0 [True]); 27.1 (target 30.0 [True]) | smallness misfit: 904.8 (target: 200.0 [False])
Beta cooling evaluation: progress: [28.9 27.1]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  1.2078417970919952
   9  1.99e+01  2.87e+01  4.44e+01  9.11e+02    1.72e+01      0     100       6.49e-01     1.12e+01   Skip BFGS
geophys. misfits: 28.8 (target 30.0 [True]); 28.7 (target 30.0 [True]) | smallness misfit: 889.1 (target: 200.0 [False])
Beta cooling evaluation: progress: [28.8 28.7]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  1.2607230158404406
  10  1.99e+01  2.90e+01  4.45e+01  9.13e+02    1.31e+01      0     100       7.03e-01     9.18e+00   Skip BFGS
geophys. misfits: 28.7 (target 30.0 [True]); 29.8 (target 30.0 [True]) | smallness misfit: 879.6 (target: 200.0 [False])
Beta cooling evaluation: progress: [28.7 29.8]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  1.29428625574706
  11  1.99e+01  2.91e+01  4.45e+01  9.14e+02    9.35e+00      0     100       1.21e+00     1.13e+01   Skip BFGS
geophys. misfits: 28.6 (target 30.0 [True]); 30.4 (target 30.0 [False]) | smallness misfit: 873.7 (target: 200.0 [False])
Beta cooling evaluation: progress: [28.6 30.4]; minimum progress targets: [30. 30.]
Decreasing beta to counter data misfit increase.
Updating scaling for data misfits by  1.047548086814322
New scales: [0.7160505 0.2839495]
  12  9.93e+00  1.52e+01  4.55e+01  4.67e+02    9.15e+01      0     100       1.24e-02     4.93e+00
geophys. misfits: 14.4 (target 30.0 [True]); 17.1 (target 30.0 [True]) | smallness misfit: 953.2 (target: 200.0 [False])
Beta cooling evaluation: progress: [14.4 17.1]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  2.4804535043827047
  13  9.93e+00  1.76e+01  4.77e+01  4.91e+02    6.59e+01      0     100       1.10e-01     1.39e+01
geophys. misfits: 14.1 (target 30.0 [True]); 26.6 (target 30.0 [True]) | smallness misfit: 804.8 (target: 200.0 [False])
Beta cooling evaluation: progress: [14.1 26.6]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  4.045460463842888
  14  9.93e+00  2.16e+01  5.00e+01  5.18e+02    7.46e+01      0     100       3.91e-01     6.29e+01
geophys. misfits: 14.1 (target 30.0 [True]); 40.6 (target 30.0 [False]) | smallness misfit: 685.1 (target: 200.0 [False])
Beta cooling evaluation: progress: [14.1 40.6]; minimum progress targets: [30. 30.]
Decreasing beta to counter data misfit increase.
Updating scaling for data misfits by  2.130943278543393
New scales: [0.5419982 0.4580018]
  15  4.97e+00  1.30e+01  5.15e+01  2.69e+02    9.40e+01      0     100       9.42e+00     2.05e+03
geophys. misfits: 10.5 (target 30.0 [True]); 16.0 (target 30.0 [True]) | smallness misfit: 792.3 (target: 200.0 [False])
Beta cooling evaluation: progress: [10.5 16. ]; minimum progress targets: [30.  32.4]
Warming alpha_pgi to favor clustering:  9.55046179940674
  16  4.97e+00  1.79e+01  5.96e+01  3.14e+02    9.84e+01      0     100       5.24e-01     1.09e+03
geophys. misfits: 11.3 (target 30.0 [True]); 25.6 (target 30.0 [True]) | smallness misfit: 611.6 (target: 200.0 [False])
Beta cooling evaluation: progress: [11.3 25.6]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  18.242355180359997
  17  4.97e+00  1.71e+01  7.10e+01  3.70e+02    1.03e+02      0     100       3.66e-01     4.28e+02
geophys. misfits: 11.4 (target 30.0 [True]); 23.9 (target 30.0 [True]) | smallness misfit: 494.5 (target: 200.0 [False])
Beta cooling evaluation: progress: [11.4 23.9]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  35.458940030540404
  18  4.97e+00  2.28e+01  8.70e+01  4.55e+02    1.17e+02      0     100       1.78e+01     1.76e+04
geophys. misfits: 14.8 (target 30.0 [True]); 32.2 (target 30.0 [False]) | smallness misfit: 366.8 (target: 200.0 [False])
Beta cooling evaluation: progress: [14.8 32.2]; minimum progress targets: [30. 30.]
Decreasing beta to counter data misfit increase.
Updating scaling for data misfits by  2.0278720191540045
New scales: [0.36851392 0.63148608]
  19  2.48e+00  2.13e+01  8.70e+01  2.37e+02    1.08e+02      0     100       7.95e-02     9.51e+02
geophys. misfits: 15.5 (target 30.0 [True]); 24.7 (target 30.0 [True]) | smallness misfit: 343.7 (target: 200.0 [False])
Beta cooling evaluation: progress: [15.5 24.7]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  55.78422544263968
  20  2.48e+00  2.47e+01  1.02e+02  2.77e+02    1.04e+02      0     100       2.16e+00     2.25e+03
geophys. misfits: 17.4 (target 30.0 [True]); 29.0 (target 30.0 [True]) | smallness misfit: 283.2 (target: 200.0 [False])
Beta cooling evaluation: progress: [17.4 29. ]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  77.05678672597305
  21  2.48e+00  3.38e+01  1.12e+02  3.13e+02    1.08e+02      0     100       1.62e+00     3.76e+03
geophys. misfits: 24.2 (target 30.0 [True]); 39.4 (target 30.0 [False]) | smallness misfit: 243.1 (target: 200.0 [False])
Beta cooling evaluation: progress: [24.2 39.4]; minimum progress targets: [30. 30.]
Decreasing beta to counter data misfit increase.
Updating scaling for data misfits by  1.2383539494813824
New scales: [0.32030283 0.67969717]
  22  1.24e+00  1.98e+01  1.19e+02  1.68e+02    1.01e+02      0     100       9.83e-01     3.22e+03
geophys. misfits: 15.3 (target 30.0 [True]); 21.9 (target 30.0 [True]) | smallness misfit: 236.6 (target: 200.0 [False])
Beta cooling evaluation: progress: [15.3 21.9]; minimum progress targets: [30.  31.5]
Warming alpha_pgi to favor clustering:  128.12579950834123
  23  1.24e+00  2.34e+01  1.46e+02  2.04e+02    1.05e+02      0     100       1.67e+00     5.40e+03
geophys. misfits: 22.1 (target 30.0 [True]); 24.0 (target 30.0 [True]) | smallness misfit: 226.2 (target: 200.0 [False])
Beta cooling evaluation: progress: [22.1 24. ]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  167.0954247923413
  24  1.24e+00  2.34e+01  1.61e+02  2.24e+02    1.09e+02      1     100       5.31e-01     2.89e+03
geophys. misfits: 22.7 (target 30.0 [True]); 23.7 (target 30.0 [True]) | smallness misfit: 206.8 (target: 200.0 [False])
Beta cooling evaluation: progress: [22.7 23.7]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  216.4393096032495
  25  1.24e+00  2.44e+01  1.82e+02  2.50e+02    1.14e+02      1     100       2.60e-01     1.08e+03
geophys. misfits: 24.6 (target 30.0 [True]); 24.3 (target 30.0 [True]) | smallness misfit: 186.5 (target: 200.0 [True])
All targets have been reached
Beta cooling evaluation: progress: [24.6 24.3]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  265.4455967768883
------------------------- STOP! -------------------------
1 : |fc-fOld| = 5.5080e+00 <= tolF*(1+|f0|) = 3.0000e+04
0 : |xc-x_last| = 3.1223e-01 <= tolX*(1+|x0|) = 1.0000e-06
0 : |proj(x-g)-x|    = 1.1362e+02 <= tolG          = 1.0000e-01
0 : |proj(x-g)-x|    = 1.1362e+02 <= 1e3*eps       = 1.0000e-02
0 : maxIter   =      50    <= iter          =     25
------------------------- DONE! -------------------------

Running inversion with SimPEG v0.25.2.dev9+g43b0120dd
Alpha scales: [np.float64(0.00034866048567845284), np.float64(0.0), np.float64(3.4877913684558853e-06), np.float64(0.0)]
Calculating the scaling parameter.
Scale Multipliers:  [0.10096782 0.89903218]
<class 'simpeg.regularization.pgi.PGIsmallness'>
Initial data misfit scales:  [0.10096782 0.89903218]
================================================= Projected GNCG =================================================
  #     beta     phi_d     phi_m       f      |proj(x-g)-x|  LS   iter_CG   CG |Ax-b|/|b|  CG |Ax-b|   Comment
-----------------------------------------------------------------------------------------------------------------
   0  2.01e+03  3.00e+05  0.00e+00  3.00e+05                         0           inf          inf
   1  2.01e+03  6.77e+04  2.17e+01  1.11e+05    1.41e+02      0      15       3.26e-04     3.06e+03
geophys. misfits: 90756.6 (target 30.0 [False]); 65086.5 (target 30.0 [False]) | smallness misfit: 249.1 (target: 200.0 [False])
Beta cooling evaluation: progress: [90756.6 65086.5]; minimum progress targets: [240000. 240000.]
   2  2.01e+03  7.95e+01  5.52e-01  1.19e+03    1.35e+02      0     100       1.60e-02     4.42e+02   Skip BFGS
geophys. misfits: 604.2 (target 30.0 [False]); 20.5 (target 30.0 [True]) | smallness misfit: 123.9 (target: 200.0 [True])
Beta cooling evaluation: progress: [604.2  20.5]; minimum progress targets: [72605.3 52069.2]
Updating scaling for data misfits by  1.4611213240493328
New scales: [0.14096321 0.85903679]
   3  2.01e+03  2.88e+01  1.35e-01  3.00e+02    1.13e+02      0     100       1.49e+00     3.83e+03   Skip BFGS
geophys. misfits: 70.4 (target 30.0 [False]); 22.0 (target 30.0 [True]) | smallness misfit: 68.2 (target: 200.0 [True])
Beta cooling evaluation: progress: [70.4 22. ]; minimum progress targets: [483.3  30. ]
Updating scaling for data misfits by  1.3630837374236162
New scales: [0.18278924 0.81721076]
   4  2.01e+03  2.63e+01  1.31e-01  2.90e+02    1.05e+02      0     100       8.25e-03     3.58e+01
geophys. misfits: 48.4 (target 30.0 [False]); 21.3 (target 30.0 [True]) | smallness misfit: 54.0 (target: 200.0 [True])
Beta cooling evaluation: progress: [48.4 21.3]; minimum progress targets: [56.3 30. ]
Updating scaling for data misfits by  1.4067636808329327
New scales: [0.23934545 0.76065455]
   5  2.01e+03  2.42e+01  1.32e-01  2.88e+02    7.35e+01      0     100       1.36e-02     7.34e+00
geophys. misfits: 32.8 (target 30.0 [False]); 21.5 (target 30.0 [True]) | smallness misfit: 48.6 (target: 200.0 [True])
Beta cooling evaluation: progress: [32.8 21.5]; minimum progress targets: [38.7 30. ]
Updating scaling for data misfits by  1.3933148451037627
New scales: [0.3047911 0.6952089]
   6  2.01e+03  2.31e+01  1.32e-01  2.89e+02    6.80e+01      0     100       3.86e-01     4.49e+01
geophys. misfits: 23.8 (target 30.0 [True]); 22.8 (target 30.0 [True]) | smallness misfit: 49.0 (target: 200.0 [True])
All targets have been reached
Beta cooling evaluation: progress: [23.8 22.8]; minimum progress targets: [30. 30.]
Warming alpha_pgi to favor clustering:  1.2858204207294475
------------------------- STOP! -------------------------
1 : |fc-fOld| = 3.9784e-01 <= tolF*(1+|f0|) = 3.0000e+04
0 : |xc-x_last| = 5.8077e-02 <= tolX*(1+|x0|) = 1.0000e-06
0 : |proj(x-g)-x|    = 6.8016e+01 <= tolG          = 1.0000e-01
0 : |proj(x-g)-x|    = 6.8016e+01 <= 1e3*eps       = 1.0000e-02
0 : maxIter   =      50    <= iter          =      6
------------------------- DONE! -------------------------

Running inversion with SimPEG v0.25.2.dev9+g43b0120dd
Alpha scales: [np.float64(3.973700929267243e-05), np.float64(0.0), np.float64(3.484360468950745e-05), np.float64(0.0)]
Calculating the scaling parameter.
Scale Multipliers:  [0.10096782 0.89903218]
/home/vsts/work/1/s/simpeg/directives/_directives.py:334: UserWarning: There is no PGI regularization. Smallness target is turned off (TriggerSmall flag)
  getattr(r, ruleType)()
Initial data misfit scales:  [0.10096782 0.89903218]
================================================= Projected GNCG =================================================
  #     beta     phi_d     phi_m       f      |proj(x-g)-x|  LS   iter_CG   CG |Ax-b|/|b|  CG |Ax-b|   Comment
-----------------------------------------------------------------------------------------------------------------
   0  1.05e+06  3.00e+05  0.00e+00  3.00e+05                         0           inf          inf
   1  1.05e+06  3.94e+04  4.24e-02  8.39e+04    1.41e+02      0      28       7.79e-04     7.31e+03
geophys. misfits: 52978.8 (target 30.0 [False]); 37912.3 (target 30.0 [False])
   2  2.10e+05  4.34e+03  1.07e-01  2.67e+04    1.37e+02      0     100       1.99e-02     3.63e+02   Skip BFGS
geophys. misfits: 7838.1 (target 30.0 [False]); 3947.9 (target 30.0 [False])
   3  4.19e+04  2.69e+02  1.41e-01  6.19e+03    1.31e+02      0     100       7.78e-02     4.01e+02   Skip BFGS
geophys. misfits: 508.2 (target 30.0 [False]); 242.0 (target 30.0 [False])
   4  8.39e+03  2.36e+01  1.51e-01  1.29e+03    1.03e+02      0     100       4.44e-03     5.51e+00   Skip BFGS
geophys. misfits: 31.5 (target 30.0 [False]); 22.8 (target 30.0 [True])
Updating scaling for data misfits by  1.318599036504984
New scales: [0.12898679 0.87101321]
   5  1.68e+03  1.06e+01  1.54e-01  2.69e+02    7.70e+01      0     100       8.20e-02     2.06e+01   Skip BFGS
geophys. misfits: 8.6 (target 30.0 [True]); 10.9 (target 30.0 [True])
All targets have been reached
------------------------- STOP! -------------------------
1 : |fc-fOld| = 8.8322e+00 <= tolF*(1+|f0|) = 3.0000e+04
0 : |xc-x_last| = 2.2495e-01 <= tolX*(1+|x0|) = 1.0000e-06
0 : |proj(x-g)-x|    = 7.7022e+01 <= tolG          = 1.0000e-01
0 : |proj(x-g)-x|    = 7.7022e+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:302: UserWarning: marker is redundantly defined by the 'marker' keyword argument and the fmt string "b.-" (-> marker='.'). The keyword argument will take precedence.
  axes[1].plot(mesh.cell_centers_x, wires.m1 * mcluster_map, "b.-", ms=5, marker="v")
/home/vsts/work/1/s/examples/10-pgi/plot_inv_1_PGI_Linear_1D_joint_WithRelationships.py:309: UserWarning: marker is redundantly defined by the 'marker' keyword argument and the fmt string "r.-" (-> marker='.'). The keyword argument will take precedence.
  axes[2].plot(mesh.cell_centers_x, wires.m2 * mcluster_map, "r.-", ms=5, marker="v")
/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 "b.-" (-> marker='.'). The keyword argument will take precedence.
  axes[5].plot(mesh.cell_centers_x, wires.m1 * mcluster_no_map, "b.-", ms=5, marker="v")
/home/vsts/work/1/s/examples/10-pgi/plot_inv_1_PGI_Linear_1D_joint_WithRelationships.py:360: UserWarning: marker is redundantly defined by the 'marker' keyword argument and the fmt string "r.-" (-> marker='.'). The keyword argument will take precedence.
  axes[6].plot(mesh.cell_centers_x, wires.m2 * mcluster_no_map, "r.-", ms=5, marker="v")
/home/vsts/work/1/s/examples/10-pgi/plot_inv_1_PGI_Linear_1D_joint_WithRelationships.py:367: UserWarning: The following kwargs were not used by contour: 'label'
  CSF = axes[7].contour(
/home/vsts/work/1/s/examples/10-pgi/plot_inv_1_PGI_Linear_1D_joint_WithRelationships.py:412: UserWarning: marker is redundantly defined by the 'marker' keyword argument and the fmt string "b.-" (-> marker='.'). The keyword argument will take precedence.
  axes[9].plot(mesh.cell_centers_x, wires.m1 * mtik, "b.-", ms=5, marker="v")
/home/vsts/work/1/s/examples/10-pgi/plot_inv_1_PGI_Linear_1D_joint_WithRelationships.py:419: UserWarning: marker is redundantly defined by the 'marker' keyword argument and the fmt string "r.-" (-> marker='.'). The keyword argument will take precedence.
  axes[10].plot(mesh.cell_centers_x, wires.m2 * mtik, "r.-", ms=5, marker="v")

import discretize as Mesh
import matplotlib.pyplot as plt
import matplotlib.lines as mlines
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,
    cg_maxiter=100,
    cg_rtol=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,
    cg_maxiter=100,
    cg_rtol=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,
    cg_maxiter=100,
    cg_rtol=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",
)
cs_proxy = mlines.Line2D([], [], label="True Petrophysical Distribution")

ps = axes[3].scatter(
    wires.m1 * mcluster_map,
    wires.m2 * mcluster_map,
    marker="v",
    label="Recovered model crossplot",
)
axes[3].set_title("Petrophysical Distribution")
axes[3].legend(handles=[cs_proxy, ps])
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="--",
)
axes[7].scatter(
    wires.m1 * mcluster_no_map,
    wires.m2 * mcluster_no_map,
    marker="v",
    label="Recovered model crossplot",
)
cs_modeled_proxy = mlines.Line2D(
    [], [], linestyle="--", label="Modeled Petro. Distribution"
)

axes[7].set_title("Petrophysical Distribution")
axes[7].legend(handles=[cs_proxy, cs_modeled_proxy, ps])
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")
axes[11].legend(handles=[cs_proxy, ps])
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 29.520 seconds)

Estimated memory usage: 333 MB

Gallery generated by Sphinx-Gallery