# -*- coding: utf-8 -*-
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (c) 2013-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:`HongGoda2007RotD100`.
"""
import numpy as np
from openquake.hazardlib.gsim.base import GMPE, CoeffsTable
from openquake.hazardlib import const
from openquake.hazardlib.imt import PGA, PGV, SA
CONSTS = {"Vref": 760.0, "v1": 180.0, "v2": 300.0}
def _compute_pga_rock(C_PGA, mag, rjb):
"""
Returns the PGA (g) on rock, as defined in equation 15
"""
return np.exp(_compute_linear_magnitude_term(C_PGA, mag) +
_compute_simple_distance_term(C_PGA, rjb))
def _compute_linear_magnitude_term(C, mag):
"""
Computes the linear part of the magnitude term
"""
return C["b1"] + C["b2"] * (mag - 7.0)
def _compute_nonlinear_magnitude_term(C, mag):
"""
Computes the non-linear magnitude term
"""
return _compute_linear_magnitude_term(C, mag) + C["b3"] * (
(mag - 7.0) ** 2.)
def _compute_simple_distance_term(C, rjb):
"""
The distance term for the PGA case ignores magnitude (equation 15)
"""
return C["b4"] * np.log(np.sqrt(rjb ** 2. + C["h"] ** 2.))
def _compute_magnitude_distance_term(C, rjb, mag):
"""
Returns the magntude dependent distance term
"""
rval = np.sqrt(rjb ** 2. + C["h"] ** 2.)
return (C["b4"] + C["b5"] * (mag - 4.5)) * np.log(rval)
def _get_site_amplification(C_AMP, vs30, pga_rock):
"""
Gets the site amplification term based on equations 7 and 8 of
Atkinson & Boore (2006)
"""
# Get nonlinear term
bnl = _get_bnl(C_AMP, vs30)
#
f_nl_coeff = np.log(60.0 / 100.0) * np.ones_like(vs30)
idx = pga_rock > 60.0
f_nl_coeff[idx] = np.log(pga_rock[idx] / 100.0)
return np.log(np.exp(
C_AMP["blin"] * np.log(vs30 / CONSTS["Vref"]) + bnl * f_nl_coeff))
def _get_bnl(C_AMP, vs30):
"""
Gets the nonlinear term, given by equation 8 of Atkinson & Boore 2006
"""
# Default case 8d
bnl = np.zeros_like(vs30)
if np.all(vs30 >= CONSTS["Vref"]):
return bnl
# Case 8a
bnl[vs30 < CONSTS["v1"]] = C_AMP["b1sa"]
# Cade 8b
idx = np.logical_and(vs30 > CONSTS["v1"],
vs30 <= CONSTS["v2"])
if np.any(idx):
bnl[idx] = (C_AMP["b1sa"] - C_AMP["b2sa"]) *\
(np.log(vs30[idx] / CONSTS["v2"]) /
np.log(CONSTS["v1"] / CONSTS["v2"])) + C_AMP["b2sa"]
# Case 8c
idx = np.logical_and(vs30 > CONSTS["v2"],
vs30 < CONSTS["Vref"])
if np.any(idx):
bnl[idx] = C_AMP["b2sa"] *\
np.log(vs30[idx] / CONSTS["Vref"]) /\
np.log(CONSTS["v2"] / CONSTS["Vref"])
return bnl
def _get_stddevs(C):
"""
Returns the standard deviations given in Table 2
"""
return [C["sigtot"], C['sig1'], C['sig2']]
[docs]class HongGoda2007(GMPE):
"""
Implements GMPE developed for RotD100 ground motion as defined by
Hong, H. P. and Goda, K. (2007), "Orientation-Dependent Ground Motion
Measure for Seismic Hazard Assessment", Bull. Seism. Soc. Am. 97(5),
1525 - 1538
This is really an experimental GMPE in which the amplification term
is taken directly from Atkinson & Boore (2006) rather than constrained
by the records themselves. There may exist a possible units issue as
the amplification function for AB2006 is in cm/s/s whereas the
GMPE here is given in g
"""
#: The supported tectonic region type is active shallow crust
DEFINED_FOR_TECTONIC_REGION_TYPE = const.TRT.ACTIVE_SHALLOW_CRUST
#: The supported intensity measure types are PGA, PGV, and SA
DEFINED_FOR_INTENSITY_MEASURE_TYPES = {PGA, PGV, SA}
#: The supported intensity measure component is RotD100
DEFINED_FOR_INTENSITY_MEASURE_COMPONENT = const.IMC.RotD100
#: The supported standard deviations are total, inter and intra event, see
#: table 4.a, pages 22-23
DEFINED_FOR_STANDARD_DEVIATION_TYPES = {
const.StdDev.TOTAL, const.StdDev.INTER_EVENT, const.StdDev.INTRA_EVENT}
#: The required site parameter is vs30, see equation 1, page 20.
REQUIRES_SITES_PARAMETERS = {'vs30'}
#: The required rupture parameters are magnitude
REQUIRES_RUPTURE_PARAMETERS = {'mag'}
#: The required distance parameter is 'Joyner-Boore' distance
REQUIRES_DISTANCES = {'rjb'}
#: GMPE not tested against independent implementation
non_verified = True
[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.
Implements equation 14 of Hong & Goda (2007)
"""
C_PGA = self.COEFFS[PGA()]
# Gets the PGA on rock - need to convert from g to cm/s/s
pga_rock = _compute_pga_rock(C_PGA, ctx.mag, ctx.rjb) * 980.665
for m, imt in enumerate(imts):
C = self.COEFFS[imt]
C_AMP = self.COEFFS_AMP[imt]
# Get the mean ground motion value
mean[m] = (_compute_nonlinear_magnitude_term(C, ctx.mag) +
_compute_magnitude_distance_term(C, ctx.rjb, ctx.mag) +
_get_site_amplification(C_AMP, ctx.vs30, pga_rock))
# Get standard deviations
sig[m], tau[m], phi[m] = _get_stddevs(C)
COEFFS = CoeffsTable(sa_damping=5, table="""\
imt b1 b2 b3 b4 b5 h sig1 sig2 sigtot
pga 1.365 0.349 0.000 -1.123 0.062 5.9 0.184 0.449 0.485
pgv 5.540 0.931 0.000 -0.866 -0.009 3.8 0.248 0.494 0.553
0.10 2.305 -0.084 -0.054 -1.461 0.167 8.2 0.218 0.467 0.515
0.15 2.605 -0.045 -0.044 -1.514 0.179 8.6 0.218 0.473 0.521
0.20 2.514 0.234 -0.053 -1.204 0.067 8.4 0.166 0.499 0.526
0.25 2.228 0.369 0.000 -1.118 0.057 6.9 0.170 0.495 0.523
0.30 1.762 0.515 0.000 -0.878 0.003 4.7 0.182 0.510 0.541
0.40 1.608 0.577 0.000 -0.898 0.012 4.9 0.234 0.528 0.577
0.50 1.713 0.837 0.000 -0.843 -0.041 6.0 0.216 0.542 0.584
0.60 1.451 0.924 -0.030 -0.755 -0.066 5.0 0.274 0.557 0.621
0.70 1.138 0.740 -0.093 -0.838 -0.014 4.2 0.320 0.581 0.664
0.80 0.781 0.549 -0.182 -0.834 0.005 3.4 0.316 0.591 0.670
0.90 0.763 0.484 -0.197 -0.960 0.052 4.0 0.324 0.594 0.677
1.00 0.763 0.359 -0.270 -1.024 0.067 4.9 0.326 0.593 0.677
1.10 0.827 0.596 -0.333 -0.819 -0.032 4.6 0.346 0.584 0.679
1.20 0.853 0.845 -0.328 -0.689 -0.093 4.3 0.358 0.578 0.680
1.30 0.682 0.921 -0.322 -0.634 -0.108 4.0 0.362 0.576 0.681
1.40 0.540 0.954 -0.303 -0.635 -0.103 3.8 0.362 0.574 0.678
1.50 0.433 1.005 -0.294 -0.617 -0.109 3.7 0.352 0.568 0.668
1.60 0.289 0.988 -0.302 -0.617 -0.103 3.6 0.364 0.566 0.673
1.70 0.102 0.976 -0.301 -0.611 -0.093 3.4 0.378 0.564 0.679
1.80 -0.098 0.965 -0.310 -0.588 -0.088 3.0 0.380 0.560 0.676
1.90 -0.216 0.936 -0.325 -0.601 -0.079 2.9 0.380 0.561 0.677
2.00 -0.379 0.693 -0.308 -0.759 -0.001 2.7 0.364 0.562 0.670
2.20 -0.549 0.643 -0.336 -0.776 0.011 2.5 0.378 0.570 0.684
2.40 -0.663 0.772 -0.325 -0.706 -0.016 2.3 0.402 0.570 0.697
2.60 -0.747 0.909 -0.302 -0.655 -0.039 2.3 0.404 0.575 0.703
2.80 -0.883 1.024 -0.259 -0.630 -0.045 2.2 0.414 0.584 0.716
3.00 -0.955 1.027 -0.265 -0.677 -0.029 2.3 0.420 0.594 0.728
""")
COEFFS_AMP = CoeffsTable(sa_damping=5, table="""\
imt blin b1sa b2sa
pgv -0.60000 -0.49500 -0.06000
pga -0.36100 -0.64100 -0.14400
0.02500 -0.33000 -0.62400 -0.11500
0.03125 -0.32200 -0.61800 -0.10800
0.04000 -0.31400 -0.60900 -0.10500
0.05000 -0.28600 -0.64300 -0.10500
0.06289 -0.24900 -0.64200 -0.10500
0.07937 -0.23200 -0.63700 -0.11700
0.10000 -0.25000 -0.59500 -0.13200
0.12500 -0.26000 -0.56000 -0.14000
0.15873 -0.28000 -0.52800 -0.18500
0.20000 -0.30600 -0.52100 -0.18500
0.25000 -0.39000 -0.51800 -0.16000
0.31250 -0.44500 -0.51300 -0.13000
0.40000 -0.50000 -0.50800 -0.09500
0.50000 -0.60000 -0.49500 -0.06000
0.62500 -0.67000 -0.48000 -0.03100
0.76923 -0.69000 -0.46500 -0.00200
1.00000 -0.70000 -0.44000 0.00000
1.58730 -0.72600 -0.39500 0.00000
2.00000 -0.73000 -0.37500 0.00000
3.12500 -0.74000 -0.33000 0.00000
4.00000 -0.74500 -0.31000 0.00000
5.00000 -0.75200 -0.30000 0.00000
""")