Skip to content

Add validate-sfile, a checker for SW4 velocity models - #137

Draft
lispandfound wants to merge 1 commit into
nzvm/config-plumbingfrom
nzvm/sfile-validator
Draft

Add validate-sfile, a checker for SW4 velocity models#137
lispandfound wants to merge 1 commit into
nzvm/config-plumbingfrom
nzvm/sfile-validator

Conversation

@lispandfound

@lispandfound lispandfound commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Adds an sfile validator, which runs a number of checks over an SW4 velocity model, namely:

  • All required attributes and groups exist, and the declared ngrid count matches the number of supplied grids.
  • The types of the datasets match what SW4 is expecting to read. This is more important that it looks because SW4 inherits the C-style coding culture of never checking anything. So, if a double is read into a float memory buffer, it will silently write into garbage and stack smash.
  • NaN and inf checks for all arrays.
  • All interfaces between mesh refinements are checked to ensure they are in increasing order of depth and don't clip each other, or that the topographic gradients are not too high.
  • Check that the material density is greater than zero.
  • Check Vp, Vs, Qp, Qs > 0 and Vp/Vs >= 1.
  • That each grid is at least two gridpoints thick.
  • That the grid corners of the velocity model align with geographic coordinates.

An sfile that SW4 accepts at load time can still crash it thousands of
steps in, or -- worse -- run to completion having quietly solved the
wrong problem. The failures that cost the most time are all detectable
up front from the file alone:

  Structure    required groups/attributes, dataset counts match ngrids
  Attributes   types, value ranges, NaN/Inf
  Z_interfaces strict monotonicity at every (i, j), zero/negative
               thickness layers (which trigger an hv=0 division in
               SW4), large topographic gradients, agreement between the
               Min/max depth attribute and the data
  Material     Rho > 0 (zero density is the most common SW4 crash),
               Cp > 0, Cs >= 0, Qp/Qs > 0 under attenuation, Vp/Vs >= 1,
               nk >= 2 (nk=1 gives 0*inf=NaN in SW4's interpolation)
  Boundaries   grid corners in geographic coordinates

Interfaces stored at different resolutions are nearest-resampled onto a
common grid rather than skipped, because crossed and pinched layers
cluster at exactly the grid-refinement boundaries where the resolutions
differ. Nearest, not bilinear: it preserves every stored node value, so
a crossing sitting on a single coarse node is never smoothed away.

Material datasets are scanned in row chunks -- they do not fit in
memory for any real domain.

Standalone: imports nothing from `workflow`, and exits non-zero if any
check reports an error, so it can gate a run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant