A high-performance Fortran library for calculating adjoint sources in seismic waveform inversion, providing efficient implementations of various misfit functions and their corresponding adjoint sources.
-
Multiple Misfit Functions: Comprehensive implementations of various misfit measurements
- Exponentiated Phase Misfit
- Multitaper Travel-time Misfit
- Cross-correlation Travel-time Misfit
- Waveform Misfit (L2 norm)
- Waveform Convolution Misfit
- Receiver Function Misfit
-
High Performance: Optimized Fortran implementations with efficient memory management
-
CMake Build System: Cross-platform compilation with multiple compiler support
-
SAC Format Support: Native support for SAC seismogram format
-
Python Integration: Compatible with pyadjoint for validation and comparison
- Fortran Compiler: Modern Fortran compiler (gfortran 9+, ifort 19+, or similar)
- CMake: Version 3.20 or higher
- LAPACK: Linear algebra package
# Clone the repository
git clone https://github.com/xumi1993/ForAdjoint.git
cd ForAdjoint
# Create build directory
mkdir build && cd build
# Configure with CMake
cmake ..
# Build the library and examples
make
# Optional: Run tests
make testThe build system automatically configures optimal flags for different compilers:
- GNU Fortran:
-std=f2008 -O3 -fimplicit-none -pedantic - Intel Fortran:
-std08 -O3 -xHost -fpe0 -assume buffered_io - NVIDIA Fortran:
-std=f2008 -O3 -Mcpu=auto -implicitnone
program example
use exponentiated_phase_misfit
use sacio
implicit none
type(ExponentiatedPhaseMisfit) :: epm
real(kind=dp), dimension(:), allocatable :: observed, synthetic
real(kind=dp), dimension(1,2) :: time_window
real(kind=dp) :: dt
integer :: ier
type(sachead) :: header
! Load seismogram data (SAC format)
call sacio_readsac("observed.sac", header, observed, ier)
call sacio_readsac("synthetic.sac", header, synthetic, ier)
dt = header%delta
tb = header%b
! Define time window [start_time, end_time]
time_window(1,:) = [50.0, 100.0] - tb
! Calculate adjoint source
call epm%calc_adjoint_source(observed, synthetic, dt, time_window)
! Access results
print *, "Total misfit:", epm%total_misfit
print *, "Adjoint source length:", size(epm%adj_src)
end programAfter building, executable tools are available in the bin/ directory:
# Exponentiated phase misfit
./bin/xex_exp_ph_misfit observed.sac synthetic.sac 5.0 50.0 42.8 91.1 output_dir/
# Cross-correlation travel-time misfit
./bin/xex_cc_misfit observed.sac synthetic.sac 5.0 50.0 42.8 91.1 output_dir/Parameters:
observed.sac: Path to observed seismogramsynthetic.sac: Path to synthetic seismogram5.0 50.0: Filter periods (short_period long_period)42.8 91.1: Time window (start_time end_time)output_dir/: Output directory for adjoint source
Measures phase and amplitude differences simultaneously using complex-valued approach:
Features:
- Robust to amplitude variations
- Suitable for regional and teleseismic waveforms
- Water-level stabilization for envelope normalization
Uses multitaper method for stable frequency-domain measurements:
Features:
- Multiple orthogonal tapers for spectral estimation
- Travel-time and amplitude anomaly measurements
- Statistical error estimation
- Cycle-skipping detection
Classic cross-correlation based travel-time measurement:
Features:
- Maximum cross-correlation lag measurement
- Amplitude ratio estimation
- Robust time-shift detection
Simple L2 norm waveform difference:
Specialized for receiver function analysis:
Features:
- Deconvolution-based receiver function calculation
- Time domain iterative deconvolution
Measures waveform differences via cross-convolution:
Features:
- Utilizes radial and vertical components
- Source effects mitigation
- Cycle-skipping avoidance
The library includes comprehensive test cases and validation against pyadjoint:
Example validation for exponentiated phase misfit:
import pyadjoint
import obspy
# Load test data
observed = obspy.read("example_data/TA.A38.BXZ.sac.obs")[0]
synthetic = obspy.read("example_data/TA.A38.BXZ.sac.syn")[0]
# Calculate with pyadjoint
config = pyadjoint.get_config(adjsrc_type="exponentiated_phase",
min_period=5., max_period=50.,
taper_percentage=0.3, taper_type="hann")
adj_tt = pyadjoint.calculate_adjoint_source(config=config,
observed=observed, synthetic=synthetic,
window=[42.8, 91.1])
# Compare with ForAdjoint results
# Results should match within numerical precisionForAdjoint/
โโโ CMakeLists.txt # Main CMake configuration
โโโ LICENSE # MIT License
โโโ README.md # This file
โโโ bin/ # Compiled executables
โโโ build/ # Build directory (generated)
โโโ src/ # Source code
โ โโโ adjoint_source_types/ # Misfit function implementations
โ โ โโโ exponentiated_phase_misfit.f90
โ โ โโโ mt_tt_misfit.f90
โ โ โโโ cc_tt_misfit.f90
โ โ โโโ waveform_misfit.f90
โ โ โโโ waveform_conv_misfit.f90
โ โ โโโ rf_misfit.f90
โ โโโ utils/ # Utility modules
โ โโโ adj_config.f90 # Configuration parameters
โ โโโ sacio.f90 # SAC I/O operations
โ โโโ signal.f90 # Signal processing
โ โโโ fftpack.f90 # FFT routines
โ โโโ dpss.f90 # Multitaper sequences
โโโ examples/ # Example programs
โ โโโ ex_exp_ph_misfit.f90
โ โโโ ex_cc_misfit.f90
โโโ tests/ # Test cases and validation
โโโ example_data/ # Sample seismograms
ForAdjoint is designed for:
- Full Waveform Inversion (FWI): High-resolution subsurface imaging
- Adjoint Tomography: Large-scale seismic structure inversion
- Receiver Function Analysis: Crustal and mantle discontinuity imaging
We welcome contributions! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow Fortran 2008 standard
- Include comprehensive comments
- Add test cases for new features
- Ensure memory management is handled properly
- Validate against pyadjoint when applicable
-
Adjoint Methods: Tromp, J., Tape, C., & Liu, Q. (2005). Seismic tomography, adjoint methods, time reversal and banana-doughnut kernels. Geophysical Journal International. DOI:j.1365-246X.2004.02453.x
-
Exponentiated Phase: Yuan, Y. O., Bozdaฤ, E., Ciardelli, C., Gao, F., & Simons, F. J. (2020). The exponentiated phase measurement, and objective-function hybridization for adjoint waveform tomography. Geophysical Journal International. DOI: 10.1093/gji/ggaa063
-
Multitaper Method: Park, J., et al. (1987). Multitaper spectral analysis of highโfrequency seismograms. Journal of Geophysical Research. DOI: 10.1029/JB092iB12p12675
-
Receiver Function: Xu, M., Wang, K., Chen, J., Yu, D., & Tong, P. (2023). Receiver Function Adjoint Tomography for Three-Dimensional High-Resolution Seismic Array Imaging: Methodology and Applications in Southeastern Tibet. Geophysical Research Letters. DOI: 10.1029/2023GL104077
This project is licensed under the MIT License - see the LICENSE file for details.
- Mijian Xu - Main Developer - xumi1993
- pyadjoint team for reference implementations
- ObsPy community for seismological data handling standards
- The broader seismological community for theoretical foundations
For questions, suggestions, or collaboration opportunities:
- Issues: GitHub Issues