Fortran implementation of H/V spectral ratio and surface-wave dispersion, with a thin Python wrapper. The Python API mirrors the original CLI and offers simple functions.
- Original authors: HV‑INV project team (see headers in
HV.f90) - Modifications and API: Shihao Yuan (
syuan@mines.edu)
This is a development build. The code may contain errors or unstable functionality. Contributions and feedback are welcome.
src/hvswdpy/: Python package (wrapper)src/hvswdpy/_fortran/: Fortran sources and f2py interface (hvdfa.pyf)src/cli/: Fortran CLI sources (HV.f90,cli_args*.f90, optional drivers)src/Makefile: build targets (hv_orig,python,python-dev)bin/: built CLI executable (bin/hv_orig)examples/: scripts and notebooksexamples/results/: output plots
- gfortran (install via conda:
conda install -c conda-forge gfortran_linux-64for Linux orgfortran_osx-arm64/gfortran_osx-64for macOS) - Python 3.9+ with NumPy 1.20+ or NumPy 2.x (tested with NumPy 1.25.2 and 2.2.6)
- macOS/Linux (tested on macOS ARM with Conda)
-
Install gfortran:
- Linux:
conda install -c conda-forge gfortran_linux-64 - macOS (ARM):
conda install -c conda-forge gfortran_osx-arm64 - macOS (Intel):
conda install -c conda-forge gfortran_osx-64 - Or use your system package manager (e.g.,
apt-get install gfortranon Ubuntu/Debian)
- Linux:
-
Activate your conda environment (if using conda):
conda activate your_environment
cd src
make hv_origThis creates the executable at bin/hv_orig.
cd src
make pythonThis builds the Python extension in-place without installing the package. Useful for testing changes.
cd src
make python-devThis installs the package in editable mode and builds the compiled extensions. The package will be available system-wide in your Python environment.
cd src
make allThis builds both the CLI executable and Python extension.
You can customize the build behavior using environment variables:
-
Disable OpenMP (if you encounter OpenMP-related issues):
USE_OPENMP=0 make python-dev
-
Custom optimization level:
OPT=-O3 make python-dev
- API arrays:
vp(m/s),vs(m/s),rho(kg/m³),thickness(m) for all layers except halfspace- At least 2 layers (including halfspace) so
thicknesshas lengthnlayers-1
- CLI
model.txt(used by examples):- First line:
N_LAYERS - Next lines:
THICKNESS VP VS RHO, withTHICKNESS=0for the halfspace
- First line:
# Build from src/
cd src && make hv_orig
# Run from repo root
bin/hv_orig -f examples/model.txt -fmin 0.1 -fmax 100 -nf 100 -logsam -nmr 3 -nml 3 -prec 1.0 -nks 0 -ph -hv > examples/HV.dat
# Outputs in examples/: Rph.dat (Rayleigh slowness), Lph.dat (Love slowness), HV.dat (freq, hv)import numpy as np
import hvswdpy as hv
vp = np.array([300., 1500.])
vs = np.array([150., 800.])
rho = np.array([1800., 2200.])
thickness = np.array([20.]) # nlayers-1 values (halfspace excluded)
f = np.logspace(-1, 2, 100)
# H/V spectral ratio
hv_curve, status = hv.hv(
frequencies_hz=f,
vp=vp, vs=vs, rho=rho, thickness=thickness,
n_rayleigh_modes=1, n_love_modes=0, precision_percent=1.0,
)- Components
comps = hv.hv_components(f, vp, vs, rho, thickness)
- Dispersion (convert slowness to velocity via 1/slowness)
disp = hv.dispersion( frequencies_hz=f, vp=vp, vs=vs, rho=rho, thickness=thickness, n_rayleigh_modes=1, n_love_modes=0, precision_percent=1.0, ) mask = (disp.rayleigh_valid[:, 0] != 0) rayleigh_vel_mode1 = 1.0 / disp.rayleigh_slowness[mask, 0]
Troubleshooting imports in notebooks:
- If running from a subfolder (e.g.,
examples/), make sure the project root is onsys.pathorPYTHONPATHsoimport hvswdpyworks:import os, sys ROOT = os.path.abspath(os.path.join(os.getcwd(), "..")) if ROOT not in sys.path: sys.path.insert(0, ROOT) import hvswdpy
- Compare HV and dispersion (CLI vs API) — generates plots into
examples/results/:jupyter notebook examples/compare_API_CLI.ipynb
examples/results/compare_hv.pngexamples/results/compare_rayleigh_dispersion.png(phase velocity vs frequency)examples/results/compare_love_dispersion.png(if Love modes requested)
This project is licensed under the MIT License. See LICENSE for details.