The code is for adjoint-state traveltime tomography (ATT) in the Cartesian coordinates. This simple version is mainly for training purpose.
The details of the algorithm can be found at Tong, P. (2021). Adjoint-state traveltime tomography: Eikonal equation-based methods and application to the Anza area in southern California. Journal of Geophysical Research: Solid Earth, 126, e2021JB021818. https://doi.org/10.1029/2021JB021818.
In order to run the codes, you have to install GNU Fortran [Operating system setup tutorials in Chinese]:
# Fedora
$ sudo dnf install gcc-gfortran
# CentOS
$ sudo yum install gfortran
# Ubuntu/Debian
$ sudo apt install gfortran
# macOS
$ brew install gfortranGeneric Mapping Tools (GMT) is used to plot figures. Refer to [GMT reference book in Chinese] for GMT installation and usage.
$ cd ./data/Prepare your data in dataInFormat_D_xyz following the designed format.
I use syntheticData.f90 to generate synthetic earthquakes and seismic stations.
$ cd dataSelection/0_commandCenter/Set the parameters in parametersData.F90.
You can select the regions for earthquakes and seismic stations.
The two regions can be different.
$ ./workflowStep.sh$ cd ../../../commandCenterYou should have the following files ready at ../data/:
sourcesreceiversnevtstarayevtstaminmaxtraveltimeReceiverGathers
Set the parameters in parametersGenerator.F90. The dimension of the forward grid,
number of multiple grids, iteration number and some others can be defined here.
You can compile and execute parametersGenerator.F90 at this time.
$ gfortran -o xpara parametersGenerator.F90
$ ./xpara
$ rm xpara$ cd ../modelIf this is for a recovery test, you can set up the target velocity model by editing velocity3d_true.F90.
$ gfortran -o xvel velocity3d_true.F90
$ ./xvel
$ rm xvelOtherwise, just define the initial model for seismic tomography by editing velocity3d.F90.
$ gfortran -o xvel velocity3d.F90
$ ./xvel
$ rm xvel$ cd ../meshEdit memeshgenerator.F90 to adjust the size of the inversion grid.
The following three parameters should be properly set.
invx = 12
invy = 3
invz = 11In general, we sample one-wavelength anomaly by 5 grid points or the grid interval is about one fourth of the anomaly wavelength.
$ gfortran -o xmesh meshgenerator.F90
$ ./xmesh
$ rm xmesh regmesh.mod$ cd ../commandCenter
# Run it if this is a recovery test
$ ./workflow_obstime.sh
$ ./workflow_inversion.shThe obtained velocity model is located at ../inversion/ as velocity3d015.
You can display the results along the cross-section set by lineEnds:
# Plot result of checkerboard test
$ ./plot-cross-section-checkerboard.sh
# Plot result of real data
$ ./plot-cross-section-real.shThe Bash script will call zCutVelocity.f90 and the gmt script vcut.gmt.
$ cd ./data/
$ cp ./dataInFormat_D_xyz_individual ./dataInFormat_D_xyz
$ cd ../commandCenter/
$ ./workflow_obstime.sh
$ ./workflow_inversion.shThen we can plot the result, select model index 1 and velocity perturbation bound 0.06.
$ cd ../figure/
$ ./plot-cross-section-checkerboard.shIn the image, (a) is velocity model after 1 round of iteration, (b) is the individual kernel, (c) is true velocity model. Red stars denote sources, blue triangles denote receivers.
First, clean the output of previous example.
$ cd ../commandCenter/
$ ./cleanup.shThen run the following code.
$ cd ../data/
$ cp ./dataInFormat_D_xyz_event ./dataInFormat_D_xyz
$ cd ../commandCenter/
$ ./workflow_obstime.sh
$ ./workflow_inversion.shThen we can plot the result,select model index 1 and velocity perturbation bound 0.06.
$ cd ../figure/
$ ./plot-cross-section-checkerboard2.shIn the image, (a) is velocity model after 1 round of iteration, (b) is the event kernel, (c) is true velocity model. Red stars denote sources, blue triangles denote receivers.
Note: In this example, we show the event kernel. By definition, it is kernel of single event and multiple receivers. In order to optimize performance, we exchange receivers and event. According to reciprocity principle, the result is equivalent. In practice, no need to do such optimization, because number of events are almost always much more than receivers.
First, clean the output of previous example.
$ cd ../commandCenter/
$ ./cleanup.shThen run the following code.
$ cd ../data/
$ cp ./dataInFormat_D_xyz_full ./dataInFormat_D_xyz
$ cd ../commandCenter/
$ ./workflow_obstime.sh
$ ./workflow_inversion.shThen we can plot the result,select model index 1 and velocity perturbation bound 0.06.
$ cd ../figure/
$ ./plot-cross-section-checkerboard.shIn the image, (a) is velocity model after 1 round of iteration, (b) is the misfit kernel, (c) is true velocity model. Red stars denote sources, blue triangles denote receivers.
This result shows velocity model after first iteration. We can edit commandCenter/parametersGenerator.F90 to run more iterations.
! Need more time to finish
niter = 15$ cd ../data/
$ cp dataInFormat_D_xyz_ridgecrest dataInFormat_D_xyzWe are now working on a different dataset, so we need to adjust the data selection parameters at data/dataSelection/0_commandCenter/parametersData.F90.
!Adjust data area
xwest=0.0, xeast=90
ysouth=0.0, ynorth=20.0
!Adjust data criteria, The earthquake must have at least NBD phases to be selected
NBD=4Then run data selection in directory data/dataSelection/0_commandCenter/
$ ./workflowStep.shin commandCenter/parametersGenerator.F90:
niter = 10 ! number of iterations
dx=0.5, dy=0.5, dz=0.5 ! forward grid size$ ./workflow_inversion.shAdjust region of cross-section, change lineEnds to
0.0 0.0 90.0 0.0
Then run:
$ ./plot-cross-section-real.sh