Source code for openquake.pfd.secondary_surf_rup.rodriguez2023

# -*- coding: utf-8 -*-
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (C) 2024-2026 Yen-Shin Chen, OGS
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

"""
Module :mod:`openquake.pfd.secondary_surf_rup.rodriguez2023` implements
the model of Rodriguez Padilla and Oskin (2023) in :class:`Rodriguez2023SecondarySR`

Supported Fault Styles: Strike-slip only

References
----------
Rodriguez Padilla, A. M., & Oskin, M. E. (2023). Displacement hazard from
distributed ruptures in strike-slip earthquakes. Bulletin of the
Seismological Society of America, 113(6), 2730-2745.
https://doi.org/10.1785/0120230044
"""

import numpy as np
from openquake.pfd.secondary_surf_rup.base import BaseSecondarySurfRup


[docs]class Rodriguez2023SecondarySR(BaseSecondarySurfRup): """ Implementation of the Rodriguez Padilla and Oskin (2023) model for strike-slip faults. """ # Coefficients for 1m pixel size (median probability) COEFFS = { 1: {'a': 0.13, 'b': 6.7, 'c': -1.19} } def get_prob(self, r, pixel_size=1): """ Calculates probability of distributed surface rupture for strike-slip faults. This model estimates the median probability of distributed faulting as a function of distance from the principal fault trace. The model was developed for immature strike-slip fault systems. :param r: Distance to the principal fault trace in km (scalar or array). :param pixel_size: Size of the analysis pixel in meters. Currently only 1m is supported. :return: Probability of distributed surface rupture (0-1). """ # Validate pixel_size if pixel_size not in self.COEFFS: raise ValueError( f"Invalid pixel_size '{pixel_size}'. " f"This model is only calibrated for pixel_size=1 m." ) # Get coefficients coeffs = self.COEFFS[pixel_size] a, b, c = coeffs['a'], coeffs['b'], coeffs['c'] # Convert r to array and from km to metres: Eq. 2 of the paper is # nu(x) = nu0 * ((x + x_fr)/x_fr)^-gamma with x and x_fr in metres # (Table 1 gives x_fr = 6.7 m for the general model). r_m = np.atleast_1d(np.asarray(r, dtype=float)) * 1000.0 # Compute probability using the power-law model (Eq. 2) prob = a * ((r_m + b) / b) ** c # Clip probability to valid range [0, 1] prob = np.clip(prob, 0.0, 1.0) return prob.item() if prob.size == 1 else prob