ElasticFDSG.jl
ElasticFDSG.jl is a Julia package for simulating elastic wave propagation in 2D and 3D heterogeneous anisotropic media. It solves the elastic wave equation in the velocity–stress formulation using a finite-difference staggered-grid (FDSG) scheme.
The package was developed with a focus on a clean, user-friendly workflow: simulations are fully described by a velocity model and a configuration dictionary (or YAML file), and results are returned as a Julia struct or saved to HDF5.
Features
- 2D and 3D elastic forward modelling on regular grids.
- Vendor-neutral CPU and GPU kernels (CUDA, Metal, AMDGPU, oneAPI) via KernelAbstractions.jl.
- Spatial finite-difference operators of order 2 to 20 (stencil half-width 1–10).
- Second-order leapfrog time integration.
- Elastic isotropic and VTI 2D models parameterised via Thomsen parameters ($\epsilon$, $\delta$).
- Elastic isotropic, VTI, and orthorhombic 3D models parameterised via Tsvankin parameters ($\epsilon_{1,2}$, $\gamma_{1,2}$, $\delta_{1,2,3}$).
- Fully heterogeneous media — stiffness tensors are compressed using a unique-tensor lookup.
- Convolutional Perfectly Matched Layer (C-PML) absorbing boundaries.
- Moment tensor sources with Ricker or Gaussian derivative wavelets.
- Geophone receivers (point particle velocity).
- DAS receivers (axial strain along coordinate-aligned profiles).
- Wavefield snapshots at arbitrary time steps.
- Results serialised to HDF5 or returned directly as a Julia struct.
A step-by-step user guide can be found in the User Guide. Working examples are available in the examples/ directory of the repository.
Installation
julia> using Pkg
julia> Pkg.add(url="https://github.com/wtegtow/ElasticFDSG.jl")Quick start
using ElasticFDSG
# Build a minimal 2D velocity model (7 × nx × nz)
nx, nz = 200, 200
h = 10.0 # grid spacing [m]
xc = range(0.0, step=h, length=nx)
zc = range(0.0, step=h, length=nz)
X = repeat(xc, 1, nz)
Z = repeat(reshape(zc, 1, :), nx, 1)
velmod = zeros(7, nx, nz)
velmod[1,:,:] .= X; velmod[2,:,:] .= Z
velmod[3,:,:] .= 3000; velmod[4,:,:] .= 1800 # vp, vs [m/s]
velmod[5,:,:] .= 2500 # density [kg/m³]
# indices 6 & 7 (Thomsen ε, δ) left at zero → isotropic
# Build a configuration dictionary
config = config_template_2d(
device = "cpu",
precision = "Float32",
fd_order = 4,
verbose = true,
output_file = nothing, # return struct instead of saving
t_start = 0.0,
t_end = 0.5,
dt = 0.001,
fdom = 30.0,
wavelet = "ricker",
wavelet_center = 0.05,
seismic_moment = 1e6,
src_x = 1000.0,
src_z = 500.0,
Mxx = 0.0, Mxz = 1.0, Mzz = 0.0,
anisotropic = false,
xstart = "absorbing", xend = "absorbing",
zstart = "absorbing", zend = "absorbing",
pml_layer = 10,
geophones = [Dict("x"=>1500.0,"z"=>500.0)],
das_x_aligned = [
Dict("x" => 500, "z" => Dict("start"=>0, "step"=>5, "end"=>2000)),
Dict("x" => 250, "z" => Dict("start"=>0, "step"=>5, "end"=>2000)),
],
das_z_aligned = [],
snapshot_times = [0.25, 0.5],
snapshot_fields = ["vx", "vz"],
)
# Run simulation — dimension is auto-detected from the velmod array
fdsg = runsim(config, velmod) Citing
If you find ElasticFDSG.jl usefull for your research, consider citing:
@misc{ElasticFDSG,
author = {William Tegtow},
title = {ElasticFDSG.jl: Simulating elastic wave propagation in 2D and 3D anisotropic media.},
year = {2025},
doi = {https://doi.org/10.5281/zenodo.14872584}
}