Source code for pygmm.akkar_sandikkaya_bommer_2014
"""Akkar, Sandikkaya, & Bommer (2014, :cite:`akkar14`) model."""
import collections
import numpy as np
from . import model
__author__ = "Albert Kottke"
[docs]
class AkkarSandikkayaBommer2014(model.GroundMotionModel):
"""Akkar, Sandikkaya, & Bommer (2014, :cite:`akkar14`) model.
The model is specified for three different distance metrics. However,
the implementation uses only one distance metric. They are used in
the following order:
1. `dist_jb`
2. `dist_hyp`
3. `dist_epi`
This order was selected based on evaluation of the total standard
deviation. To compute the response for differing metrics, call the
model multiple times with different keywords.
Parameters
----------
scenario : :class:`pygmm.model.Scenario`
earthquake scenario
"""
NAME = "Akkar, Sandikkaya, & Bommer (2014)"
ABBREV = "ASB14"
# Reference velocity (m/sec)
V_REF = 750.0
# Load the coefficients for the model
COEFF = collections.OrderedDict(
(k, model.load_data_file("akkar-sandikkaya-bommer-2014-%s.csv" % k, 2))
for k in ["dist_jb", "dist_hyp", "dist_epi"]
)
PERIODS = np.array(COEFF["dist_jb"].period)
INDICES_PSA = np.arange(2, 64)
INDEX_PGA = 0
INDEX_PGV = 1
PARAMS = [
model.NumericParameter("dist_jb", False, 0, 200),
model.NumericParameter("dist_epi", False, 0, 200),
model.NumericParameter("dist_hyp", False, 0, 200),
model.NumericParameter("mag", True, 4, 8),
model.NumericParameter("v_s30", True, 150, 1200),
model.CategoricalParameter("mechanism", True, ["SS", "NS", "RS"]),
]
[docs]
def __init__(self, scenario: model.Scenario):
"""Initialize the model."""
super().__init__(scenario)
s = self._scenario
for k in self.COEFF:
if s[k] is not None:
dist = s[k]
c = self.COEFF[k]
break
else:
raise NotImplementedError("Must provide at least one distance metric.")
# Compute the reference response
ln_resp_ref = (
c.a_1
+ c.a_3 * (8.5 - s.mag) ** 2
+ (c.a_4 + c.a_5 * (s.mag - c.c_1)) * np.log(np.sqrt(dist**2 + c.a_6**2))
)
mask = s.mag <= c.c_1
ln_resp_ref[mask] += (c.a_2 * (s.mag - c.c_1))[mask]
ln_resp_ref[~mask] += (c.a_7 * (s.mag - c.c_1))[~mask]
if s.mechanism == "NS":
ln_resp_ref += c.a_8
elif s.mechanism == "RS":
ln_resp_ref += c.a_9
pga_ref = np.exp(ln_resp_ref[self.INDEX_PGA])
# Compute the nonlinear site term
if s.v_s30 <= self.V_REF:
vs_ratio = s.v_s30 / self.V_REF
site = c.b_1 * np.log(vs_ratio) + c.b_2 * np.log(
(pga_ref + c.c * vs_ratio**c.n) / ((pga_ref + c.c) * vs_ratio**c.n)
)
else:
site = c.b_1 * np.log(np.minimum(s.v_s30, c.v_con) / self.V_REF)
self._ln_resp = ln_resp_ref + site
self._ln_std = np.array(c.sd_total)