Time-lapse 3D survey

To invert time-lapse survey there are two modes: reg_mode == 1 or reg_mode == 2 (see R3t documentation). - reg_mode == 1 is refered to as ‘background constrained’ inversion where the subsequente survey are penalized from departure from the reference survey. - reg_mode == 2 (default in ResIPy) is refered to as ‘difference inversion’ but, for 3D, this requires to modify the protocol.dat to compute \(d - d_0 + f(m_0)\) where \(d_0\) is the observed transfer resitance of the reference survey, \(d\) is the observed transfer resistances of the survey to be inverted, \(f(m_0)\) represent the forward response (in terms of transfer resistances) of the inverted reference model. While R2 and cR2 do d-d0+f(m0) internally, R3t does not. But ResIPy has this build-in, hence no special initiative is required from the user if you want to use reg_mode == 2. You will see the --- Computing d-d0+f(m0) ---- when calling Project.invert().

import warnings
warnings.filterwarnings('ignore')
import os
import sys
sys.path.append((os.path.relpath('../src'))) # add here the relative path of the API folder
testdir = '../src/examples/'
from resipy import Project
import pyvista as pv # for 3D plots
import numpy as np # to specify np.infty
API path =  /media/jkl/data/phd/tmp/resipy/src/resipy
ResIPy version =  3.2.0
cR2.exe found and up to date.
R3t.exe found and up to date.
cR3t.exe found and up to date.
# difference inversion - see d-d0+f(m0) in the log
k = Project(typ='R3t')
k.createTimeLapseSurvey([testdir + 'dc-3d-timelapse-protocol/data/protocol3D-1.dat',
                         testdir + 'dc-3d-timelapse-protocol/data/protocol3D-2.dat'],
                         ftype='ProtocolDC')
k.importElec(testdir + 'dc-3d-timelapse-protocol/elec/electrodes3D-1.csv')
k.createMesh()
k.invert()
# by default `reg_mode == 2` (difference inversion)
print(k.param['reg_mode'])
should_run_async will not call transform_cell automatically in the future. Please pass the result to transformed_cell argument and any exception that happen during thetransform in preprocessing_exc_tuple in IPython 7.17 and above.
Working directory is: /media/jkl/data/phd/tmp/resipy/src/resipy
clearing dirname
2/2 imported
Creating tetrahedral mesh...fmd in gmshWrap.py: 16.343534
writing .geo to file completed, save location:
/media/jkl/data/phd/tmp/resipy/src/resipy/invdir

Reading mesh3d.msh
Gmsh version == 3.x
reading node coordinates...
Determining element type...Tetrahedra
Reading connection matrix...
ignoring 7581 elements in the mesh file, as they are not required for R2/R3t
Finished reading .msh file
interpolating topography onto mesh using triangulate interpolation...done
Done
ResIPy Estimated RAM usage = 0.164347 Gb
done
Writing .in file and protocol.dat... Matching quadrupoles between surveys for difference inversion...644 in common...done in 0.014881s
done!
------------ INVERTING REFERENCE SURVEY ---------------


 >> R 3 t     E R T    M o d e l    v 2.30 <<

 >> Date: 19-01-2021
 >> My beautiful 3D survey
 >> I n v e r s e   S o l u t i o n   S e l e c t e d <<
 >> A d v a n c e d   M e s h   I n p u t <<
 >> T e t r a h e d r a l   E l e m e n t   M e s h <<

 >> Reading mesh file
 >> Determining storage needed for finite element conductance matrix
 >> Generating index array for finite element conductance matrix
 >> Reading resistivity model from res0.dat

 >> L o g - D a t a   I n v e r s i o n <<
 >> N o r m a l   R e g u l a r i s a t i o n <<

 >> Memory estimates:
    For   1000 measurements the memory needed is:          0.250 Gb
    For   2000 measurements the memory needed is:          0.491 Gb
    For   5000 measurements the memory needed is:          1.213 Gb
    For  10000 measurements the memory needed is:          2.417 Gb

 >> Forming roughness matrix

 >> Number of measurements read:  644

 >> Total Memory required is:          0.164 Gb


 Processing frame   1 - output to file f001.dat

   Iteration   1
     Initial RMS Misfit:         2.41      Number of data ignored:     0
     Alpha:          67.701   RMS Misfit:        0.54  Roughness:        3.208
     Step length set to      1.000
     Final RMS Misfit:        0.54
     Final RMS Misfit:        1.01

 Solution converged - Outputing results to file

 Calculating sensitivity map

 End of data:  Terminating


 >> Program ended normally

----------------- Computing d-d0+f(m0) ---------------
Writing .in file and mesh.dat... done!
Writing protocol.dat... done!
Running forward model...

 >> R 3 t     E R T    M o d e l    v 2.30 <<

 >> Date: 19-01-2021
 >> My beautiful 3D survey
 >> F o r w a r d   S o l u t i o n   S e l e c t e d <<
 >> A d v a n c e d   M e s h   I n p u t <<
 >> T e t r a h e d r a l   E l e m e n t   M e s h <<

 >> Reading mesh file
 >> Determining storage needed for finite element conductance matrix
 >> Generating index array for finite element conductance matrix
 >> Reading resistivity model from resistivity.dat

 >> Memory estimates:
    For   1000 measurements the memory needed is:          0.006 Gb
    For   2000 measurements the memory needed is:          0.006 Gb
    For   5000 measurements the memory needed is:          0.006 Gb
    For  10000 measurements the memory needed is:          0.006 Gb

 >> Number of measurements read:  644

 >> Total Memory required is:          0.006 Gb


 >> Program ended normally

0/644 reciprocal measurements found.
0/644 reciprocal measurements found.
Forward modelling done.Matching quadrupoles between surveys for difference inversion...644 in common...done in 0.020808s

--------------------- MAIN INVERSION ------------------


 >> R 3 t     E R T    M o d e l    v 2.30 <<

 >> Date: 19-01-2021
 >> My beautiful 3D survey
 >> I n v e r s e   S o l u t i o n   S e l e c t e d <<
 >> A d v a n c e d   M e s h   I n p u t <<
 >> T e t r a h e d r a l   E l e m e n t   M e s h <<

 >> Reading mesh file
 >> Determining storage needed for finite element conductance matrix
 >> Generating index array for finite element conductance matrix
 >> Reading resistivity model from Start_res.dat

 >> L o g - D a t a   I n v e r s i o n <<
 >> D i f f e r e n c e   R e g u l a r i s a t i o n <<

 >> Memory estimates:
    For   1000 measurements the memory needed is:          0.250 Gb
    For   2000 measurements the memory needed is:          0.491 Gb
    For   5000 measurements the memory needed is:          1.213 Gb
    For  10000 measurements the memory needed is:          2.417 Gb

 >> Forming roughness matrix

 >> Number of measurements read:  644

 >> Total Memory required is:          0.164 Gb


 Processing frame   1 - output to file f001.dat

   Iteration   1
     Initial RMS Misfit:         1.40      Number of data ignored:     0
     Alpha:          69.072   RMS Misfit:        0.16  Roughness:        0.871
     Step length set to      1.000
     Final RMS Misfit:        0.16
     Final RMS Misfit:        1.00

 Solution converged - Outputing results to file

 Calculating sensitivity map

 End of data:  Terminating


 >> Program ended normally

2/2 results parsed (2 ok; 0 failed)
2
k.showResults(index=1, pvslices=[[10,20,30,40],[0],[]], attr='difference(percent)',
             color_map='bwr', vmin=-10, vmax=10)
should_run_async will not call transform_cell automatically in the future. Please pass the result to transformed_cell argument and any exception that happen during thetransform in preprocessing_exc_tuple in IPython 7.17 and above.
Converting np.character to a dtype is deprecated. The current result is np.dtype(np.str_) which is not strictly correct. Note that np.character is generally deprecated and 'S1' should be used.
Converting np.character to a dtype is deprecated. The current result is np.dtype(np.str_) which is not strictly correct. Note that np.character is generally deprecated and 'S1' should be used.
../_images/nb_3d-time-lapse_0.png

In background constrained inversion (reg_mode == 1), the difference(percent) attribute is not computed by R3t. In order to have it computed by ResIPy, it is needed to tell R3t to output the full mesh (so that ResIPy can match the mesh elements between reference and other surveys). To do this set Project.param['num_xy_poly'] = 0 and set zmin and zmax to \(-\infty\) and \(+\infty\) respectively, just before Project.invert(). If you don’t change that, R3t will crop the mesh by default and ResIPy will output a message saying it couldn’t compute ‘difference(percent)’.

Note that setting num_xy_poly to 0 and changing zmin/zmax does not change the vizualisation. It just changes the .vtk and .dat files produced by R3t.

# background constrained - see d-d0+f(m0) in the log
k = Project(typ='R3t')
k.createTimeLapseSurvey([testdir + 'dc-3d-timelapse-protocol/data/protocol3D-1.dat',
                         testdir + 'dc-3d-timelapse-protocol/data/protocol3D-2.dat'],
                         ftype='ProtocolDC')
k.importElec(testdir + 'dc-3d-timelapse-protocol/elec/electrodes3D-1.csv')
k.createMesh()
k.param['reg_mode'] = 1
k.param['num_xy_poly'] = 0 # tells R3t to no crop the mesh
k.param['zmin'] = -np.inf
k.param['zmax'] = np.inf
k.invert()
Working directory is: /media/jkl/data/phd/tmp/resipy/src/resipy
clearing dirname
2/2 imported
Creating tetrahedral mesh...fmd in gmshWrap.py: 16.343534
writing .geo to file completed, save location:
/media/jkl/data/phd/tmp/resipy/src/resipy/invdir

Reading mesh3d.msh
Gmsh version == 3.x
reading node coordinates...
Determining element type...Tetrahedra
Reading connection matrix...
ignoring 7581 elements in the mesh file, as they are not required for R2/R3t
Finished reading .msh file
interpolating topography onto mesh using triangulate interpolation...done
Done
ResIPy Estimated RAM usage = 0.164347 Gb
done
Writing .in file and protocol.dat... done!
------------ INVERTING REFERENCE SURVEY ---------------


 >> R 3 t     E R T    M o d e l    v 2.30 <<

 >> Date: 19-01-2021
 >> My beautiful 3D survey
 >> I n v e r s e   S o l u t i o n   S e l e c t e d <<
 >> A d v a n c e d   M e s h   I n p u t <<
 >> T e t r a h e d r a l   E l e m e n t   M e s h <<

 >> Reading mesh file
 >> Determining storage needed for finite element conductance matrix
 >> Generating index array for finite element conductance matrix
 >> Reading resistivity model from res0.dat

 >> L o g - D a t a   I n v e r s i o n <<
 >> N o r m a l   R e g u l a r i s a t i o n <<

 >> Memory estimates:
    For   1000 measurements the memory needed is:          0.250 Gb
    For   2000 measurements the memory needed is:          0.491 Gb
    For   5000 measurements the memory needed is:          1.213 Gb
    For  10000 measurements the memory needed is:          2.417 Gb

 >> Forming roughness matrix

 >> Number of measurements read:  644

 >> Total Memory required is:          0.164 Gb


 Processing frame   1 - output to file f001.dat

   Iteration   1
     Initial RMS Misfit:         2.41      Number of data ignored:     0
     Alpha:          67.701   RMS Misfit:        0.54  Roughness:        3.208
     Step length set to      1.000
     Final RMS Misfit:        0.54
     Final RMS Misfit:        1.01

 Solution converged - Outputing results to file

 Calculating sensitivity map

 End of data:  Terminating


 >> Program ended normally

----------------- Computing d-d0+f(m0) ---------------
Writing .in file and mesh.dat... done!
Writing protocol.dat... done!
Running forward model...

 >> R 3 t     E R T    M o d e l    v 2.30 <<

 >> Date: 19-01-2021
 >> My beautiful 3D survey
 >> F o r w a r d   S o l u t i o n   S e l e c t e d <<
 >> A d v a n c e d   M e s h   I n p u t <<
 >> T e t r a h e d r a l   E l e m e n t   M e s h <<

 >> Reading mesh file
 >> Determining storage needed for finite element conductance matrix
 >> Generating index array for finite element conductance matrix
 >> Reading resistivity model from resistivity.dat

 >> Memory estimates:
    For   1000 measurements the memory needed is:          0.006 Gb
    For   2000 measurements the memory needed is:          0.006 Gb
    For   5000 measurements the memory needed is:          0.006 Gb
    For  10000 measurements the memory needed is:          0.006 Gb

 >> Number of measurements read:  644

 >> Total Memory required is:          0.006 Gb


 >> Program ended normally

0/644 reciprocal measurements found.
0/644 reciprocal measurements found.
Forward modelling done.
--------------------- MAIN INVERSION ------------------


 >> R 3 t     E R T    M o d e l    v 2.30 <<

 >> Date: 19-01-2021
 >> My beautiful 3D survey
 >> I n v e r s e   S o l u t i o n   S e l e c t e d <<
 >> A d v a n c e d   M e s h   I n p u t <<
 >> T e t r a h e d r a l   E l e m e n t   M e s h <<

 >> Reading mesh file
 >> Determining storage needed for finite element conductance matrix
 >> Generating index array for finite element conductance matrix
 >> Reading resistivity model from Start_res.dat

 >> L o g - D a t a   I n v e r s i o n <<
 >> B a c k g r o u n d   R e g u l a r i s a t i o n <<

 >> Memory estimates:
    For   1000 measurements the memory needed is:          0.250 Gb
    For   2000 measurements the memory needed is:          0.491 Gb
    For   5000 measurements the memory needed is:          1.213 Gb
    For  10000 measurements the memory needed is:          2.417 Gb

 >> Forming roughness matrix

 >> Number of measurements read:  644

 >> Total Memory required is:          0.164 Gb


 Processing frame   1 - output to file f001.dat

   Iteration   1
     Initial RMS Misfit:         1.40      Number of data ignored:     0
     Alpha:          69.072   RMS Misfit:        0.86  Roughness:        3.886
     Step length set to      1.000
     Final RMS Misfit:        0.86
     Final RMS Misfit:        1.00

 Solution converged - Outputing results to file

 Calculating sensitivity map

 End of data:  Terminating


 >> Program ended normally

2/2 results parsed (2 ok; 0 failed)
k.showResults(index=1, pvslices=[[10,20,30,40],[0],[]], attr='difference(percent)',
             color_map='bwr', vmin=-10, vmax=10)
should_run_async will not call transform_cell automatically in the future. Please pass the result to transformed_cell argument and any exception that happen during thetransform in preprocessing_exc_tuple in IPython 7.17 and above.
Converting np.character to a dtype is deprecated. The current result is np.dtype(np.str_) which is not strictly correct. Note that np.character is generally deprecated and 'S1' should be used.
Converting np.character to a dtype is deprecated. The current result is np.dtype(np.str_) which is not strictly correct. Note that np.character is generally deprecated and 'S1' should be used.
../_images/nb_3d-time-lapse_1.png

Note that the two outputs are slightly different. With the difference inversion (reg_mode == 2) being smoother thant the background constrained (reg_mode == 1). Indeed, in this last one, we haven’t inverted the differences in resistivity and the difference(percent) argument has been computed afterwards by ResIPy.

Download python script: nb_3d-time-lapse.py

Download Jupyter notebook: nb_3d-time-lapse.ipynb

View the notebook in the Jupyter nbviewer

Run this example interactively: binder