Source code for openquake.hazardlib.gsim.kotha_2016

# -*- coding: utf-8 -*-
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (C) 2014-2023 GEM Foundation
#
# OpenQuake 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.
#
# OpenQuake 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 OpenQuake. If not, see <http://www.gnu.org/licenses/>.

"""
Module exports :class:`KothaEtAl2016`,
               :class:`KothaEtAl2016Italy`,
               :class:`KothaEtAl2016Turkey`,
               :class:`KothaEtAl2016Others`,
"""
import os
import numpy as np
from scipy.constants import g

from openquake.hazardlib.gsim.base import GMPE, CoeffsTable
from openquake.hazardlib import const
from openquake.hazardlib.imt import PGA, PGV, SA

KOTHA_CSV = os.path.join(os.path.dirname(__file__), 'kotha_2016.csv')

CONSTS = {"Mh": 6.75, "Mref": 5.5, "Rref": 1.0}


def _get_anelastic_coeff(kind, C):
    """
    This function is a regionalisable parameter - will be modified in
    other classes
    """
    if kind == "base":
        return C["c3"]
    elif kind == "ITA":
        return C["c3"] + C["Dc3IT"]
    elif kind == "TUR":
        return C["c3"] + C["Dc3TR"]
    elif kind == "other":
        return C["c3"] + C["Dc3OTH"]


def _get_distance_term(kind, C, rjb, mag):
    """
    Returns the general distance scaling term - equation 2
    """
    c_3 = _get_anelastic_coeff(kind, C)
    rval = np.sqrt(rjb ** 2. + C["h"] ** 2.)
    return (C["c1"] + C["c2"] * (mag - CONSTS["Mref"])) *\
        np.log(rval / CONSTS["Rref"]) + c_3 * (rval - CONSTS["Rref"])


def _get_magnitude_term(C, mag):
    """
    Returns the magnitude scaling term - equation 3
    """
    return np.where(mag >= CONSTS["Mh"],
                    C["e1"] + C["b3"] * (mag - CONSTS["Mh"]),
                    C["e1"] + C["b1"] * (mag - CONSTS["Mh"]) +
                    C["b2"] * (mag - CONSTS["Mh"]) ** 2.)


def _get_regional_site_term(kind, C):
    """
    Region specific site term - modified in subclasses
    """
    if kind == "base":
        return 0., 0.
    elif kind == "ITA":
        return C["Dg1IT"], C["Dg2IT"]
    elif kind == "TUR":
        return C["Dg1TR"], C["Dg2TR"]
    elif kind == "other":
        return C["Dg1OTH"], C["Dg2OTH"]


def _get_site_term(kind, C, vs30):
    """
    Returns only a linear site amplification term
    """
    dg1, dg2 = _get_regional_site_term(kind, C)
    return (C["g1"] + dg1) + (C["g2"] + dg2) * np.log(vs30)


[docs]class KothaEtAl2016(GMPE): """ Implements unregionalised form of the European GMPE of: Kotha, S. R., Bindi, D. and Cotton, F. (2016) "Partially non-ergodic region specific GMPE for Europe and the Middle-East", Bull. Earthquake Eng. 14: 1245 - 1263 """ #: Supported tectonic region type is 'active shallow crust' DEFINED_FOR_TECTONIC_REGION_TYPE = const.TRT.ACTIVE_SHALLOW_CRUST #: Set of :mod:`intensity measure types <openquake.hazardlib.imt>` #: this GSIM can calculate. A set should contain classes from module #: :mod:`openquake.hazardlib.imt`. DEFINED_FOR_INTENSITY_MEASURE_TYPES = {PGA, PGV, SA} #: Supported intensity measure component is the geometric mean of two #: horizontal components DEFINED_FOR_INTENSITY_MEASURE_COMPONENT = const.IMC.GEOMETRIC_MEAN #: Supported standard deviation types are inter-event, intra-event #: and total DEFINED_FOR_STANDARD_DEVIATION_TYPES = { const.StdDev.TOTAL, const.StdDev.INTER_EVENT, const.StdDev.INTRA_EVENT} #: Required site parameter is only Vs30 REQUIRES_SITES_PARAMETERS = {'vs30'} #: Required rupture parameters are magnitude only (eq. 1). REQUIRES_RUPTURE_PARAMETERS = {'mag'} #: Required distance measure is Rjb (eq. 1). REQUIRES_DISTANCES = {'rjb'} kind = "base"
[docs] def compute(self, ctx: np.recarray, imts, mean, sig, tau, phi): """ See :meth:`superclass method <.base.GroundShakingIntensityModel.compute>` for spec of input and result values. """ for m, imt in enumerate(imts): C = self.COEFFS[imt] mean[m] = (_get_magnitude_term(C, ctx.mag) + _get_distance_term(self.kind, C, ctx.rjb, ctx.mag) + _get_site_term(self.kind, C, ctx.vs30)) # Units of GMPE are in terms of m/s (corrected in an Erratum) # Convert to g if imt.string.startswith(('PGA', 'SA')): mean[m] = np.log(np.exp(mean[m]) / g) else: # For PGV convert from m/s to cm/s/s mean[m] = np.log(np.exp(mean[m]) * 100.) # Get standard deviations sig[m] = C['sigma'] tau[m] = C['tau'] phi[m] = np.sqrt(C['phi0'] ** 2. + C["phiS2S"] ** 2.)
COEFFS = CoeffsTable(sa_damping=5, table=open(KOTHA_CSV).read())
[docs]class KothaEtAl2016Italy(KothaEtAl2016): """ Regional varient of the Kotha et al. (2016) GMPE for the Italy case """ kind = "ITA"
[docs]class KothaEtAl2016Turkey(KothaEtAl2016): """ Regional varient of the Kotha et al. (2016) GMPE for the Turkey case """ kind = "TUR"
[docs]class KothaEtAl2016Other(KothaEtAl2016): """ Regional varient of the Kotha et al. (2016) GMPE for the "Other" case """ kind = "other"