TERRANOETIS

Earthquake ground motion (BSSA14 GMPE ShakeMap)

Platform v3.0.0 Docs v3.0.0 MEASURED LOCALLY

Full description: Read the full narrative

The scenario is a 2D seismic-hazard computation, not a wave-physics animation: the kernel evaluates the median ground-motion prediction equation (GMPE) of Boore, Stewart, Seyhan & Atkinson (NGA-West2 base case, BSSA14 / PEER 2013/05) on a regular grid around a user-pinned epicentre, applies linear and nonlinear site response for the chosen Vs30, converts to Modified Mercalli Intensity with the USGS instrumental rules, and writes PGA / PGV / Sa(1 s) / MMI grids plus an animated PGA series timed by S-wave arrival.

Execution mode
Local CPU (python3) — no Kaggle token required server/kaggle/simRunner.ts:126-141 (LOCAL_SIM_TYPES)
Verification
MEASURED — executed directly and end-to-end through the job API
Wire scenario type
earthquake_swarm — contract at src/services/kaggleSim.ts:28-240; job API at Simulation job API
Evidence legend

MEASURED marks values produced by executing the actual code on this machine (commands in Reproduction; raw logs summarised in Methodology → Evidence runs).

Governing equations and coefficients

Source attribution as stated in the kernel header (verbatim):

PGA, PGV and Sa(1.0 s): the Boore, Stewart, Seyhan & Atkinson NGA-West2 GMPE (BSSA14; PEER 2013/05, published as Boore et al. 2014, BSSA 104(2), doi:10.1785/0120130065). … ln Y = FE(M,mech) + FP(R,M) + FS(VS30,M,R) with the full linear + nonlinear site response; unspecified fault mechanism; base-case (no regional anelastic / basin-depth terms). Validity: M 3-9.7, shallow crustal, VS30 150-1500 m/s.
kaggle-kernels/earthquake-sim/main.py:14-21
R = R_hyp = sqrt(R_epi² + depth²) [km]
Point-source hypocentral distance (no fault-geometry Rjb/Rrup terms). kaggle-kernels/earthquake-sim/main.py:12,272-273
ln Y = FE(M) + FP(R, M) + FS(VS30, M, R) [ln of cm/s² or cm/s]
BSSA14 additive form for PGA, PGV and Sa(1.0 s). kaggle-kernels/earthquake-sim/main.py:72-81,102-124
FE = e0 + e4·(M−Mh) + e5·(M−Mh)² (M ≤ Mh); FE = e0 + e6·(M−Mh) (M > Mh)
Magnitude scaling, base case (unspecified mechanism — fault-type terms e1–e3 are stored but unused). kaggle-kernels/earthquake-sim/main.py:109-113,85-93
FP = [c1 + c2·(M−Mref)]·ln(R/Rref) + c3·(R−Rref)
Attenuation; R floored at 0.1 km. kaggle-kernels/earthquake-sim/main.py:108,115
lnFlin = c·ln(min(VS30, Vc)/Vref); lnFnl = f1 + f2·ln((PGA_r+f3)/f3), f2 = f4·[exp(f5·(min(VS30,760)−360)) − exp(f5·(760−360))]
Linear + nonlinear site response; PGA_r is the Vs30 = 760 m/s reference-rock PGA. kaggle-kernels/earthquake-sim/main.py:120-129,94-99
MMI = max(MMI_PGA, MMI_PGV) [unitless, 1…10]
USGS instrumental intensity: Worden et al. 2012 (doi:10.1785/0120110156) + global GMICE Caprio et al. 2015 (doi:10.1785/0120140286). kaggle-kernels/earthquake-sim/main.py:23-25,144-153,282

Coefficients and named constants

BSSA14 base-case coefficients, read from the PEER 2013/05 appendix tables. Order e0,e1,e2,e3,e4,e5,e6,Mh,c1,c2,c3,Mref,Rref,h.
IMe0e4e5e6Mhc1c2c3MrefRrefh
PGA0.44731.4310.05053−0.16625.5−1.1340.1917−0.008094.51.04.5
PGV5.0371.073−0.15360.22526.2−1.2430.1489−0.003444.51.05.3
Sa(1 s)0.39321.5004−0.189830.178956.2−1.1930.10248−0.001214.51.05.74
Site-response coefficients (c, Vc, Vref, f1, f3, f4, f5); reference rock VS30_REF = 760 m/s.
IMcVcVreff1f3f4f5
PGA−0.5150925.00760.00.00.1−0.1500−0.00701
PGV−0.8050950.00760.00.00.1−0.1000−0.00844
Sa(1 s)−1.0361967.51760.00.00.1−0.1052−0.00844
MMI upper bounds used by the intensity mapping. PGA in g; PGV bounds in cm/s (medians also tabulated).
QuantityValues
PGA upper bounds, MMI 2…10 [g]0.000464, 0.00135, 0.00297, 0.0276, 0.115, 0.215, 0.401, 0.747, 1.39
PGV upper bounds, MMI 2…10 [cm/s]0.0215, 0.135, 1.41, 4.65, 9.64, 20.0, 41.4, 85.8, 178.0
PGV medians, MMI 1…10 [cm/s]0.010, 0.054, 0.437, 2.56, 6.70, 13.9, 28.8, 59.6, 123.6, 267.0

Parameter contract

Earthquake parameters: UI control → wire field → unit → valid range → default → physical meaning. Shared request envelope (validated at the client boundary before dispatch).

Earthquake parameters: UI control → wire field → unit → valid range → default → physical meaning.
UI controlWire fieldUnitValid range (UI · wire · kernel)DefaultPhysical meaningSource
Mag (mainshock) slidermagnitudeM (moment/local)UI 3.0–9.5 step 0.1, default 8.0; wire 3.0–9.7; kernel raises outside 3.0–9.7UI 8.0 · kernel 6.5Mainshock magnitude driving GMPE magnitude scalingsrc/components/scenarios/ScenarioEditor.tsx:62-68 src/services/kaggleSim.ts:94 kaggle-kernels/earthquake-sim/main.py:238,244-245
Depth (mainshock) sliderdepth_kmkmUI 1–300 (auto-overwritten to clamp(5, 50, 5·M) by the form derivation); wire 0.5–700; kernel validates 0.5–700UI 30 · kernel 12Hypocentral depth; enters R_hypsrc/components/scenarios/ScenarioEditor.tsx:62-68 src/services/kaggleSim.ts:95,600 kaggle-kernels/earthquake-sim/main.py:239,246-247
Site Vs30 (NEHRP) slidervs30 (optional)m/s150–1500 step 10760Time-averaged shear velocity to 30 m; drives linear + nonlinear site amplificationsrc/components/scenarios/ScenarioEditor.tsx:62-68 src/services/kaggleSim.ts:97 kaggle-kernels/earthquake-sim/main.py:242,248-249
Min Magnitude / Min Depth sliders— (not sent)M / km1–8 / 0–1002.5 / 5Catalog context shown in the panel; the wire carries only the mainshock pairsrc/components/scenarios/ScenarioEditor.tsx:62-68 src/services/kaggleSim.ts:455-464
Epicentre (globe click)epi_frac_x, epi_frac_y (optional)fraction of box0–1, clamped0.5, 0.5Column = x eastward, row = y southward; GMPE distance field radiates from this cellsrc/services/kaggleSim.ts:98-106 kaggle-kernels/earthquake-sim/main.py:262-267

Outputs

Files written per run (also served by GET /api/kaggle/simulate/:jobId/grid/:name and …/geotiff/:name)
FieldUnitMeaningSource
pga_cm_s2.npycm/s²Peak ground acceleration grid (median prediction)kaggle-kernels/earthquake-sim/main.py:409-420
pgv_cm_s.npycm/sPeak ground velocity gridkaggle-kernels/earthquake-sim/main.py:409-420
sa_1s_cm_s2.npycm/s²5 %-damped spectral acceleration at T = 1.0 skaggle-kernels/earthquake-sim/main.py:409-420
mmi.npyMMI 1–10 (float)Instrumental Modified Mercalli intensity grid (max of PGA- and PGV-derived)kaggle-kernels/earthquake-sim/main.py:282,409-420
snapshots_pga.npy + snapshot_times.npycm/s²; sPGA reveal frames timed by S-arrival (t = R_hyp / Vs, Vs = 3.5 km/s, smoothstep onset)kaggle-kernels/earthquake-sim/main.py:297-314,303
metadata.jsonparams (incl. cell_size_m, epi fracs), model/source strings, final_stats, validation resultskaggle-kernels/earthquake-sim/main.py:319-335,425-433

Spatial-origin semantics

Simulation domain: a square of side extent_km centred on the study-box centroid; dx = extent_km·1000/grid_size m (default 500 m without extent). Rows run north→south (row 0 = north edge), columns west→east; the epi-fraction point (x = east, y = south) receives the distance origin so the strongest shaking sits on the clicked trace. lat/lon enter metadata only — never the physics. kaggle-kernels/earthquake-sim/main.py:251-270,319,330

Documented validity limits (verbatim from the code)

'point-source hypocentral distance used for the GMPE Rjb term — no fault-geometry directivity or finite-rupture effects' · 'unspecified fault mechanism; base-case only (no regional anelastic attenuation or basin-depth z1 terms)' · 'Sa reported at T=1.0 s only' · 'Worden-2012/Caprio-2015 intensity relations calibrated on California/global datasets and saturate for great-earthquake near-fields'
kaggle-kernels/earthquake-sim/main.py:344-353

Before emitting any field the kernel runs a GMPE sanity gate (attenuation monotonicity, M6.5 @ 10 km PGA in (100, 500) cm/s², soft-site amplification > 1, PGV/PGA ratio 0.05–0.2 s, MMI band round-trip). On failure it refuses to emit: "GMPE sanity gate failed — refusing to emit a ShakeMap from mis-wired attenuation relations." kaggle-kernels/earthquake-sim/main.py:194-232,400-404

Measured runs and timings

Executed on an Apple-Silicon laptop (Python 3.14.5, NumPy 2.4.2). These are observations of one environment, not performance guarantees.
Run / checkMeasured result
Kernel, M 7.5 · 12 km · Vs30 760 · 100 km box · 256²max PGA 251.0 cm/s², max PGV 27.5 cm/s, max MMI 7.0, area(MMI ≥ 6) 4,439 km²; kernel compute 0.0083 s; total wall 0.12 s (incl. interpreter start)
Boundary casesM 3.0 / 0.5 km / Vs30 150 and M 9.7 / 700 km / Vs30 1500 both complete; M 2.9 rejected with "magnitude 2.9 outside the 3.0-9.7 GMPE validity range"; depth 750 km rejected with "depth_km 750.0 outside 0.5-700 km"
End-to-end via POST /api/kaggle/simulatejob sim_44d5c7d7 (M 7.2, 128², 100 km box): status running→complete 166 ms after submission; result metadata cites "BSSA14 … doi:10.1785/0120130065"; grid + GeoTIFF endpoints returned HTTP 200 (296,648-byte npy; valid 128×128 TIFF)
DOI resolvabilityhttps://doi.org/10.1785/0120130065 responds 302 (resolvable)

Reproduction

Commands

# 1) via the running server (same path the web UI uses):
npm run dev:server    # Express on :3001

curl -s -X POST http://localhost:3001/api/kaggle/simulate \
  -H 'Content-Type: application/json' -d '{
    "type":"earthquake_swarm","lat":36.1,"lon":139.7,
    "grid_size":128,"extent_km":100,"magnitude":7.2,
    "depth_km":15,"vs30":760,"epi_frac_x":0.4,"epi_frac_y":0.5 }'
# → {"jobId":"sim_…","status":"running","streamUrl":"/api/kaggle/simulate/…/stream"}

curl -s http://localhost:3001/api/kaggle/simulate/<jobId>/results
curl -s -o pga.npy http://localhost:3001/api/kaggle/simulate/<jobId>/grid/pga_cm_s2

# 2) kernel directly (honours TERRANOETIS_OUT_DIR):
cd kaggle-kernels/earthquake-sim && mkdir -p /tmp/eq && \
  echo '{"grid_size":128,"magnitude":7.5,"depth_km":12,"vs30":760,"extent_km":100}' > /tmp/eq/params.json && \
  (cd /tmp/eq && TERRANOETIS_OUT_DIR=/tmp/eq python3 <repo>/kaggle-kernels/earthquake-sim/main.py)