pygmm 0.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pygmm/__init__.py +87 -0
- pygmm/abrahamson_bhasin_2020.py +158 -0
- pygmm/abrahamson_gregor_addo_2016.py +248 -0
- pygmm/abrahamson_silva_1996.py +121 -0
- pygmm/abrahamson_silva_kamai_2014.py +411 -0
- pygmm/afshari_stewart_2016.py +157 -0
- pygmm/akkar_sandikkaya_bommer_2014.py +101 -0
- pygmm/atkinson_boore_2006.py +168 -0
- pygmm/baker_jayaram_2008.py +97 -0
- pygmm/bayless_abrahamson_2018.py +91 -0
- pygmm/bayless_abrahamson_2019.py +199 -0
- pygmm/boore_stewart_seyhan_atkinson_2014.py +298 -0
- pygmm/campbell_2003.py +96 -0
- pygmm/campbell_bozorgnia_2014.py +473 -0
- pygmm/chiou_youngs_2014.py +341 -0
- pygmm/coppersmith_bommer_2014.py +113 -0
- pygmm/data/abrahamson_gregor_addo_2016.csv +25 -0
- pygmm/data/abrahamson_silva_kamai_2014.csv +27 -0
- pygmm/data/akkar-sandikkaya-bommer-2014-dist_epi.csv +67 -0
- pygmm/data/akkar-sandikkaya-bommer-2014-dist_hyp.csv +67 -0
- pygmm/data/akkar-sandikkaya-bommer-2014-dist_jb.csv +67 -0
- pygmm/data/atkinson_boore_2006-bc.csv +30 -0
- pygmm/data/atkinson_boore_2006-rock.csv +30 -0
- pygmm/data/atkinson_boore_2006-sf.csv +29 -0
- pygmm/data/atkinson_boore_2006-site.csv +27 -0
- pygmm/data/bayless_abrahamson_2018.csv +243 -0
- pygmm/data/bayless_abrahamson_2019.csv +304 -0
- pygmm/data/boore_stewart_seyhan_atkinson-2014.csv +110 -0
- pygmm/data/campbell_2003.csv +18 -0
- pygmm/data/campbell_bozorgnia_2014.csv +26 -0
- pygmm/data/chiou_youngs_2014.csv +29 -0
- pygmm/data/coppersmith_bommer_2014.csv +16 -0
- pygmm/data/derras_bard_cotton_2014.json +192 -0
- pygmm/data/gulerce_abrahamson_2011-coefficients.csv +27 -0
- pygmm/data/gulerce_abrahamson_2011-correl-between.csv +18 -0
- pygmm/data/gulerce_abrahamson_2011-correl-within.csv +18 -0
- pygmm/data/idriss_2014-large.csv +25 -0
- pygmm/data/idriss_2014-small.csv +25 -0
- pygmm/data/pezeshk_zandieh_tavakoli_2011.csv +25 -0
- pygmm/data/tavakoli_pezeshk_2005.csv +16 -0
- pygmm/derras_bard_cotton_2014.py +80 -0
- pygmm/gulerce_abrahamson_2011.py +186 -0
- pygmm/hermkes_kuehn_riggelsen_2014.py +100 -0
- pygmm/idriss_2014.py +94 -0
- pygmm/kempton_stewart_2006.py +86 -0
- pygmm/kishida_2017.py +94 -0
- pygmm/model.py +552 -0
- pygmm/pezeshk_zandieh_tavakoli_2011.py +94 -0
- pygmm/tavakoli_pezeshk_2005.py +100 -0
- pygmm/tools.py +1 -0
- pygmm/types.py +7 -0
- pygmm-0.0.0.dist-info/AUTHORS.md +12 -0
- pygmm-0.0.0.dist-info/LICENSE +21 -0
- pygmm-0.0.0.dist-info/METADATA +76 -0
- pygmm-0.0.0.dist-info/RECORD +57 -0
- pygmm-0.0.0.dist-info/WHEEL +5 -0
- pygmm-0.0.0.dist-info/top_level.txt +1 -0
pygmm/__init__.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""pyGMM: Ground motion models implemented in Python."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from importlib.metadata import version
|
|
5
|
+
|
|
6
|
+
from .abrahamson_bhasin_2020 import AbrahamsonBhasin2020
|
|
7
|
+
from .abrahamson_gregor_addo_2016 import AbrahamsonGregorAddo2016
|
|
8
|
+
from .abrahamson_silva_1996 import AbrahamsonSilva1996
|
|
9
|
+
from .abrahamson_silva_kamai_2014 import AbrahamsonSilvaKamai2014
|
|
10
|
+
from .afshari_stewart_2016 import AfshariStewart2016
|
|
11
|
+
from .akkar_sandikkaya_bommer_2014 import AkkarSandikkayaBommer2014
|
|
12
|
+
from .atkinson_boore_2006 import AtkinsonBoore2006
|
|
13
|
+
from .bayless_abrahamson_2018 import BaylessAbrahamson2018
|
|
14
|
+
from .bayless_abrahamson_2019 import BaylessAbrahamson2019
|
|
15
|
+
from .boore_stewart_seyhan_atkinson_2014 import BooreStewartSeyhanAtkinson2014
|
|
16
|
+
from .campbell_2003 import Campbell2003
|
|
17
|
+
from .campbell_bozorgnia_2014 import CampbellBozorgnia2014
|
|
18
|
+
from .chiou_youngs_2014 import ChiouYoungs2014
|
|
19
|
+
from .coppersmith_bommer_2014 import CoppersmithBommer2014
|
|
20
|
+
from .derras_bard_cotton_2014 import DerrasBardCotton2014
|
|
21
|
+
from .gulerce_abrahamson_2011 import GulerceAbrahamson2011
|
|
22
|
+
from .idriss_2014 import Idriss2014
|
|
23
|
+
from .kempton_stewart_2006 import KemptonStewart2006
|
|
24
|
+
from .model import Scenario
|
|
25
|
+
from .pezeshk_zandieh_tavakoli_2011 import PezeshkZandiehTavakoli2011
|
|
26
|
+
from .tavakoli_pezeshk_2005 import TavakoliPezeshk05
|
|
27
|
+
|
|
28
|
+
__all__ = [
|
|
29
|
+
"Scenario",
|
|
30
|
+
"AbrahamsonBhasin2020",
|
|
31
|
+
"AbrahamsonSilvaKamai2014",
|
|
32
|
+
"AbrahamsonGregorAddo2016",
|
|
33
|
+
"AfshariStewart2016",
|
|
34
|
+
"AkkarSandikkayaBommer2014",
|
|
35
|
+
"AtkinsonBoore2006",
|
|
36
|
+
"BaylessAbrahamson2018",
|
|
37
|
+
"BaylessAbrahamson2019",
|
|
38
|
+
"BooreStewartSeyhanAtkinson2014",
|
|
39
|
+
"Campbell2003",
|
|
40
|
+
"CampbellBozorgnia2014",
|
|
41
|
+
"ChiouYoungs2014",
|
|
42
|
+
"CoppersmithBommer2014",
|
|
43
|
+
"DerrasBardCotton2014",
|
|
44
|
+
"GulerceAbrahamson2011",
|
|
45
|
+
"KemptonStewart2006",
|
|
46
|
+
"Idriss2014",
|
|
47
|
+
"PezeshkZandiehTavakoli2011",
|
|
48
|
+
"TavakoliPezeshk05",
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
__author__ = "Albert Kottke"
|
|
52
|
+
__copyright__ = "Copyright 2016 Albert Kottke"
|
|
53
|
+
__license__ = "MIT"
|
|
54
|
+
__title__ = "pyGMM"
|
|
55
|
+
__version__ = version("pyGMM")
|
|
56
|
+
|
|
57
|
+
# Set default logging handler to avoid "No handler found" warnings.
|
|
58
|
+
try: # Python 2.7+
|
|
59
|
+
from logging import NullHandler
|
|
60
|
+
except ImportError:
|
|
61
|
+
|
|
62
|
+
class NullHandler(logging.Handler):
|
|
63
|
+
def emit(self, record):
|
|
64
|
+
pass
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
logging.getLogger(__name__).addHandler(NullHandler())
|
|
68
|
+
|
|
69
|
+
models = [
|
|
70
|
+
AbrahamsonSilva1996,
|
|
71
|
+
AbrahamsonSilvaKamai2014,
|
|
72
|
+
AfshariStewart2016,
|
|
73
|
+
AkkarSandikkayaBommer2014,
|
|
74
|
+
AtkinsonBoore2006,
|
|
75
|
+
BaylessAbrahamson2019,
|
|
76
|
+
BooreStewartSeyhanAtkinson2014,
|
|
77
|
+
Campbell2003,
|
|
78
|
+
CampbellBozorgnia2014,
|
|
79
|
+
ChiouYoungs2014,
|
|
80
|
+
CoppersmithBommer2014,
|
|
81
|
+
DerrasBardCotton2014,
|
|
82
|
+
GulerceAbrahamson2011,
|
|
83
|
+
KemptonStewart2006,
|
|
84
|
+
Idriss2014,
|
|
85
|
+
PezeshkZandiehTavakoli2011,
|
|
86
|
+
TavakoliPezeshk05,
|
|
87
|
+
]
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"""Abrahamson and Bhasin (2020, :cite:`abrahamson20`) model."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
from . import model
|
|
8
|
+
|
|
9
|
+
__author__ = "Albert Kottke"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AbrahamsonBhasin2020(model.Model):
|
|
13
|
+
"""Abrahamson (2020, :cite:`abrahamson20`) model.
|
|
14
|
+
|
|
15
|
+
Conditional PGV model
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
scenario : :class:`pygmm.model.Scenario`
|
|
20
|
+
earthquake scenario
|
|
21
|
+
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
NAME = "Abrahamson and Bhasin (2020)"
|
|
25
|
+
ABBREV = "AB20"
|
|
26
|
+
|
|
27
|
+
# Reference velocity (m/s)
|
|
28
|
+
V_REF = 425.0
|
|
29
|
+
|
|
30
|
+
# Load the coefficients for the model
|
|
31
|
+
COEFFS = {
|
|
32
|
+
# From Table 3.2
|
|
33
|
+
"psa(T=Tpgv)": model.Coefficients(
|
|
34
|
+
a_1=5.39,
|
|
35
|
+
a_2=0.799,
|
|
36
|
+
a_3=0.654,
|
|
37
|
+
a_4=0.479,
|
|
38
|
+
a_5=-0.062,
|
|
39
|
+
a_6=-0.359,
|
|
40
|
+
a_7=-0.134,
|
|
41
|
+
a_8=0.023,
|
|
42
|
+
phi=0.29,
|
|
43
|
+
tau=0.16,
|
|
44
|
+
),
|
|
45
|
+
"pga": model.Coefficients(
|
|
46
|
+
a_1=4.77,
|
|
47
|
+
a_2=0.738,
|
|
48
|
+
a_3=0.484,
|
|
49
|
+
a_4=0.275,
|
|
50
|
+
a_5=-0.036,
|
|
51
|
+
a_6=-0.332,
|
|
52
|
+
a_7=-0.44,
|
|
53
|
+
a_8=0,
|
|
54
|
+
phi_1=0.32,
|
|
55
|
+
phi_2=0.42,
|
|
56
|
+
tau_1=0.12,
|
|
57
|
+
tau_2=0.26,
|
|
58
|
+
M_1=5.0,
|
|
59
|
+
M_2=7.0,
|
|
60
|
+
),
|
|
61
|
+
"psa(T=1s)": model.Coefficients(
|
|
62
|
+
a_1=4.80,
|
|
63
|
+
a_2=0.82,
|
|
64
|
+
a_3=0.55,
|
|
65
|
+
a_4=0.27,
|
|
66
|
+
a_5=0.054,
|
|
67
|
+
a_6=-0.382,
|
|
68
|
+
a_7=-0.21,
|
|
69
|
+
a_8=0.0,
|
|
70
|
+
phi_1=0.28,
|
|
71
|
+
phi_2=0.38,
|
|
72
|
+
tau_1=0.12,
|
|
73
|
+
tau_2=0.17,
|
|
74
|
+
M_1=5.0,
|
|
75
|
+
M_2=7.0,
|
|
76
|
+
),
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
PARAMS = [
|
|
80
|
+
model.NumericParameter("dist_rup", True, 0, 300),
|
|
81
|
+
model.NumericParameter("mag", True, 3.0, 8.0),
|
|
82
|
+
model.NumericParameter("v_s30", True, 180, 1500),
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
def __init__(
|
|
86
|
+
self,
|
|
87
|
+
scenario: model.Scenario,
|
|
88
|
+
psa=Optional[float],
|
|
89
|
+
pga=Optional[float],
|
|
90
|
+
psa_1s=Optional[float],
|
|
91
|
+
):
|
|
92
|
+
super().__init__(scenario)
|
|
93
|
+
|
|
94
|
+
if psa is not None:
|
|
95
|
+
method = "psa(T=Tpgv)"
|
|
96
|
+
# FIXME: How to interpolate?
|
|
97
|
+
raise NotImplementedError
|
|
98
|
+
elif pga is not None:
|
|
99
|
+
method = "pga"
|
|
100
|
+
ln_gm = np.log(pga)
|
|
101
|
+
else:
|
|
102
|
+
method = "psa(T=1s)"
|
|
103
|
+
ln_gm = np.log(psa_1s)
|
|
104
|
+
|
|
105
|
+
C = self.COEFFS[method]
|
|
106
|
+
s = scenario
|
|
107
|
+
|
|
108
|
+
# Mean
|
|
109
|
+
if s.mag < 5:
|
|
110
|
+
f_1 = C.a_2
|
|
111
|
+
elif s.mag > 7.5:
|
|
112
|
+
f_1 = C.a_3
|
|
113
|
+
else:
|
|
114
|
+
f_1 = C.a_2 + (C.a_3 - C.a_2) * (s.mag - 5) / 2.5
|
|
115
|
+
|
|
116
|
+
ln_mean = (
|
|
117
|
+
C.a_1
|
|
118
|
+
+ f_1 * ln_gm
|
|
119
|
+
+ C.a_4 * (s.mag - 6)
|
|
120
|
+
+ C.a_5 * (8.5 - s.mag) ** 2
|
|
121
|
+
+ C.a_6 * np.log(s.dist_rup + 5 * np.exp(0.4 * (s.mag - 6)))
|
|
122
|
+
+ (C.a_7 + C.a_8 * (s.mag - 5)) * np.log(C.v_s30 / self.V_REF)
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
if method == "psa(T=Tpgv)":
|
|
126
|
+
phi, tau = C.phi, C.tau
|
|
127
|
+
else:
|
|
128
|
+
|
|
129
|
+
def interp(var_1, var_2):
|
|
130
|
+
if s.mag < C.mag_1:
|
|
131
|
+
val = var_1
|
|
132
|
+
elif s.mag > C.mag_2:
|
|
133
|
+
val = var_2
|
|
134
|
+
else:
|
|
135
|
+
val = var_1 + (var_2 - var_1) * (s.mag - C.mag_1) / (C.mag_2 - C.mag_1)
|
|
136
|
+
return val
|
|
137
|
+
|
|
138
|
+
phi = interp(C.phi_1, C.phi_2)
|
|
139
|
+
tau = interp(C.tau_1, C.tau_2)
|
|
140
|
+
|
|
141
|
+
ln_std = np.sqrt(phi**2 + tau**2)
|
|
142
|
+
return ln_mean, ln_std
|
|
143
|
+
|
|
144
|
+
@classmethod
|
|
145
|
+
def ln_period_pgv(cls, mag: float) -> float:
|
|
146
|
+
"""Natural logarithm of the period for calculating PGV. Equation 3.6.
|
|
147
|
+
|
|
148
|
+
Parameters
|
|
149
|
+
----------
|
|
150
|
+
mag : float
|
|
151
|
+
Magnitude
|
|
152
|
+
|
|
153
|
+
Returns
|
|
154
|
+
-------
|
|
155
|
+
ln_period_pgv : float
|
|
156
|
+
Best period for computing PGV.
|
|
157
|
+
"""
|
|
158
|
+
return -4.09 + 0.66 * mag
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"""Abrahamson, Gregor, and Addo (2016) ground motion moodel."""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from . import model
|
|
6
|
+
|
|
7
|
+
__author__ = "Albert Kottke"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AbrahamsonGregorAddo2016(model.GroundMotionModel):
|
|
11
|
+
"""Abrahamson, Gregor, and Addo (2016) ground motion moodel.
|
|
12
|
+
|
|
13
|
+
This model was developed for subduction regions and is commonly referred to
|
|
14
|
+
as the BCHydro model.
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
scenario : :class:`pygmm.model.Scenario`
|
|
19
|
+
earthquake scenario
|
|
20
|
+
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
NAME = "Abrahamson, Gregor, & Addo (2016)"
|
|
24
|
+
ABBREV = "AGA16"
|
|
25
|
+
|
|
26
|
+
# Reference shear-wave velocity in m/sec
|
|
27
|
+
V_REF = 1000.0
|
|
28
|
+
|
|
29
|
+
# Load the coefficients for the model
|
|
30
|
+
COEFF = model.load_data_file("abrahamson_gregor_addo_2016.csv", 1)
|
|
31
|
+
PERIODS = COEFF["period"]
|
|
32
|
+
|
|
33
|
+
INDEX_PGA = 0
|
|
34
|
+
INDICES_PSA = np.arange(1, 23)
|
|
35
|
+
|
|
36
|
+
# FIXME
|
|
37
|
+
LIMITS = dict(
|
|
38
|
+
mag=(3.0, 8.5),
|
|
39
|
+
dist_jb=(0.0, 300.0),
|
|
40
|
+
v_s30=(150.0, 1500.0),
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
PARAMS = [
|
|
44
|
+
model.NumericParameter("mag", True, 3, 8.5),
|
|
45
|
+
model.NumericParameter("dist_rup", False),
|
|
46
|
+
model.NumericParameter("dist_hyp", False),
|
|
47
|
+
model.NumericParameter("depth_hyp", False),
|
|
48
|
+
model.NumericParameter("v_s30", True, 150.0, 1500.0),
|
|
49
|
+
model.CategoricalParameter("event_type", True, ["interface", "intraslab"]),
|
|
50
|
+
model.CategoricalParameter(
|
|
51
|
+
"tectonic_region", False, ["forearc", "backarc", "unknown"], "unknown"
|
|
52
|
+
),
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
def __init__(self, scenario, adjust_c1=None, adjust_c4=0, scale_atten=1.0):
|
|
56
|
+
"""Initialize the model.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
scenario (:class:`pygmm.model.Scenario`): earthquake scenario.
|
|
60
|
+
"""
|
|
61
|
+
super().__init__(scenario)
|
|
62
|
+
|
|
63
|
+
n = len(self.COEFF)
|
|
64
|
+
if adjust_c1 is None:
|
|
65
|
+
# Default adjustments
|
|
66
|
+
if self.scenario.event_type == "intraslab":
|
|
67
|
+
self._adjust_c1 = -0.3 * np.ones(n)
|
|
68
|
+
else:
|
|
69
|
+
self._adjust_c1 = np.interp(
|
|
70
|
+
np.log(np.maximum(0.01, self.COEFF.period)),
|
|
71
|
+
np.log([0.3, 0.5, 1, 2, 3]),
|
|
72
|
+
[0.2, 0.1, 0, -0.1, -0.2],
|
|
73
|
+
left=0.2,
|
|
74
|
+
right=-0.2,
|
|
75
|
+
)
|
|
76
|
+
else:
|
|
77
|
+
if isinstance(adjust_c1, float):
|
|
78
|
+
self._adjust_c1 = adjust_c1 * np.ones(n)
|
|
79
|
+
else:
|
|
80
|
+
self._adjust_c1 = np.asarray(adjust_c1)
|
|
81
|
+
|
|
82
|
+
self._adjust_c4 = adjust_c4
|
|
83
|
+
self._scale_atten = scale_atten
|
|
84
|
+
|
|
85
|
+
pga_ref = np.exp(self._calc_ln_resp(np.nan)[self.INDEX_PGA])
|
|
86
|
+
self._ln_resp = self._calc_ln_resp(pga_ref)
|
|
87
|
+
self._ln_std = self._calc_ln_std()
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def adjust_c1(self):
|
|
91
|
+
return self._adjust_c1
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def adjust_c4(self):
|
|
95
|
+
return self._adjust_c4
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def scale_atten(self):
|
|
99
|
+
return self._scale_atten
|
|
100
|
+
|
|
101
|
+
def _calc_ln_resp(self, pga_ref):
|
|
102
|
+
"""Calculate the natural logarithm of the response.
|
|
103
|
+
|
|
104
|
+
Parameters
|
|
105
|
+
----------
|
|
106
|
+
pga_ref : float
|
|
107
|
+
peak ground acceleration (g) at the reference
|
|
108
|
+
condition. If :class:`np.nan`, then no site term is applied.
|
|
109
|
+
|
|
110
|
+
Returns
|
|
111
|
+
-------
|
|
112
|
+
ln_resp : class:`np.array`:
|
|
113
|
+
natural log of the response
|
|
114
|
+
|
|
115
|
+
"""
|
|
116
|
+
s = self._scenario
|
|
117
|
+
c = self.COEFF
|
|
118
|
+
|
|
119
|
+
f_event = 1 if s.event_type == "intraslab" else 0
|
|
120
|
+
dist = s.dist_hyp if s.event_type == "intraslab" else s.dist_rup
|
|
121
|
+
|
|
122
|
+
path_atten = (c.t_2 + c.t_14 * f_event + c.t_3 * (s.mag - 7.8)) * np.log(
|
|
123
|
+
dist + c.c_4 * np.exp(c.t_9 * (s.mag - 6))
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
ln_resp = (
|
|
127
|
+
c.t_1
|
|
128
|
+
+ c.t_4 * self.adjust_c1
|
|
129
|
+
+ path_atten
|
|
130
|
+
+ self._scale_atten * c.t_6 * dist
|
|
131
|
+
+ c.t_10 * f_event
|
|
132
|
+
+ self._calc_f_mag(s.mag)
|
|
133
|
+
+ self._calc_f_site(pga_ref)
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
if s.tectonic_region == "backarc":
|
|
137
|
+
ln_resp += self._calc_f_faba(dist)
|
|
138
|
+
|
|
139
|
+
if s.event_type == "intraslab":
|
|
140
|
+
ln_resp += self._calc_f_depth(s.depth_hyp)
|
|
141
|
+
|
|
142
|
+
return ln_resp
|
|
143
|
+
|
|
144
|
+
def _calc_f_mag(self, mag):
|
|
145
|
+
"""Calculate the magnitude scaling. Equation 2.
|
|
146
|
+
|
|
147
|
+
Parameters
|
|
148
|
+
----------
|
|
149
|
+
mag : float
|
|
150
|
+
moment magnitude
|
|
151
|
+
|
|
152
|
+
Returns
|
|
153
|
+
-------
|
|
154
|
+
f_mag : class:`np.array`:
|
|
155
|
+
magnitude scaling
|
|
156
|
+
|
|
157
|
+
"""
|
|
158
|
+
c = self.COEFF
|
|
159
|
+
c_1 = 7.8
|
|
160
|
+
coeff = np.select([mag <= (c_1 + self.adjust_c1), True], [c.t_4, c.t_5])
|
|
161
|
+
f_mag = coeff * (mag - (c_1 + self.adjust_c1)) + c.t_13 * (10 - mag) ** 2
|
|
162
|
+
return f_mag
|
|
163
|
+
|
|
164
|
+
def _calc_f_depth(self, depth_hyp):
|
|
165
|
+
"""Calculate the depth scaling. Equation 3.
|
|
166
|
+
|
|
167
|
+
Parameters
|
|
168
|
+
----------
|
|
169
|
+
depth_hyp : float
|
|
170
|
+
depth to hypocenter [km]
|
|
171
|
+
|
|
172
|
+
Returns
|
|
173
|
+
-------
|
|
174
|
+
f_depth : class:`np.array`:
|
|
175
|
+
depth scaling
|
|
176
|
+
|
|
177
|
+
"""
|
|
178
|
+
c = self.COEFF
|
|
179
|
+
f_depth = c.t_11 * (np.minimum(depth_hyp, 120) - 60)
|
|
180
|
+
return f_depth
|
|
181
|
+
|
|
182
|
+
def _calc_f_faba(self, dist):
|
|
183
|
+
"""Calculate the forearc/backarc scaling. Equation 4.
|
|
184
|
+
|
|
185
|
+
Parameters
|
|
186
|
+
----------
|
|
187
|
+
dist : float
|
|
188
|
+
depth to hypocenter [km]
|
|
189
|
+
|
|
190
|
+
Returns
|
|
191
|
+
-------
|
|
192
|
+
f_faba : class:`np.array`:
|
|
193
|
+
forearc/backarc scaling
|
|
194
|
+
|
|
195
|
+
"""
|
|
196
|
+
c = self.COEFF
|
|
197
|
+
if self.scenario.event_type == "intraslab":
|
|
198
|
+
f_faba = c.t_7 + c.t_8 * np.log(np.maximum(dist, 85) / 40)
|
|
199
|
+
elif self.scenario.event_type == "interface":
|
|
200
|
+
f_faba = c.t_15 + c.t_16 * np.log(np.maximum(dist, 100) / 40)
|
|
201
|
+
else:
|
|
202
|
+
raise NotImplementedError
|
|
203
|
+
|
|
204
|
+
return f_faba
|
|
205
|
+
|
|
206
|
+
def _calc_f_site(self, pga_ref):
|
|
207
|
+
"""Calculate the site amplification. Equation 5.
|
|
208
|
+
|
|
209
|
+
Parameters
|
|
210
|
+
----------
|
|
211
|
+
pga_ref : float, default: np.nan
|
|
212
|
+
reference PGA (V_s30 = 1000 m/sec). If 'np.nan', then the ground
|
|
213
|
+
motion at the reference condition is computed.
|
|
214
|
+
|
|
215
|
+
Returns
|
|
216
|
+
-------
|
|
217
|
+
f_site : class:`np.array`:
|
|
218
|
+
site scaling
|
|
219
|
+
|
|
220
|
+
"""
|
|
221
|
+
c = self.COEFF
|
|
222
|
+
v_s30 = 1000.0 if np.isnan(pga_ref) else self.scenario.v_s30
|
|
223
|
+
vs_ratio = np.minimum(v_s30, 1000) / c.v_lin
|
|
224
|
+
|
|
225
|
+
f_site = np.select(
|
|
226
|
+
[v_s30 < c.v_lin, True],
|
|
227
|
+
[
|
|
228
|
+
c.t_12 * np.log(vs_ratio)
|
|
229
|
+
- c.b * np.log(pga_ref + c.c)
|
|
230
|
+
+ c.b * np.log(pga_ref + c.c * vs_ratio**c.n),
|
|
231
|
+
(c.t_12 + c.b * c.n) * np.log(vs_ratio),
|
|
232
|
+
],
|
|
233
|
+
)
|
|
234
|
+
return f_site
|
|
235
|
+
|
|
236
|
+
def _calc_ln_std(self):
|
|
237
|
+
"""Calculate the logarithmic standard deviation.
|
|
238
|
+
|
|
239
|
+
Returns
|
|
240
|
+
-------
|
|
241
|
+
ln_std : class:`np.array`:
|
|
242
|
+
natural log standard deviation
|
|
243
|
+
|
|
244
|
+
"""
|
|
245
|
+
c = self.COEFF
|
|
246
|
+
|
|
247
|
+
ln_std = np.sqrt(c.phi**2 + c.tau**2)
|
|
248
|
+
return ln_std
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""Abrahamson and Silva (1996, :cite:`abrahamson96`) duration model."""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from . import model
|
|
6
|
+
|
|
7
|
+
__author__ = "Albert Kottke"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AbrahamsonSilva1996(model.Model):
|
|
11
|
+
"""Abrahamson and Silva (1996, :cite:`abrahamson96`) duration model.
|
|
12
|
+
|
|
13
|
+
Parameters
|
|
14
|
+
----------
|
|
15
|
+
scenario : :class:`pygmm.model.Scenario`
|
|
16
|
+
earthquake scenario
|
|
17
|
+
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
NAME = "Abrahamson Silva (1996)"
|
|
21
|
+
ABBREV = "AS96"
|
|
22
|
+
|
|
23
|
+
PARAMS = [
|
|
24
|
+
model.NumericParameter("mag", True, 4, 7.5),
|
|
25
|
+
model.NumericParameter("dist_rup", True, 0, 250),
|
|
26
|
+
# FIXME add site_cond to Scenario
|
|
27
|
+
model.CategoricalParameter("site_cond", True, ["soil", "rock"]),
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
def __init__(self, scenario):
|
|
31
|
+
super().__init__(scenario)
|
|
32
|
+
|
|
33
|
+
s = self._scenario
|
|
34
|
+
|
|
35
|
+
stress_drop = np.exp(5.204 + 0.851 * (s.mag - 6))
|
|
36
|
+
moment = 10 ** (1.5 * s.mag + 16.05)
|
|
37
|
+
|
|
38
|
+
self._ln_dur = np.log(
|
|
39
|
+
(stress_drop / moment) ** (-1 / 3) / (4.9e6 * 3.2)
|
|
40
|
+
+ 0.805 * (1 if s.site_cond == "soil" else 0)
|
|
41
|
+
+ 0.063 * max(s.dist_rup - 10, 0)
|
|
42
|
+
) + self.calc_ln_dur_incr(0.75)
|
|
43
|
+
self._std_err = 0.55
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def duration(self):
|
|
47
|
+
return np.exp(self._ln_dur)
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def std_err(self):
|
|
51
|
+
return self._std_err
|
|
52
|
+
|
|
53
|
+
@staticmethod
|
|
54
|
+
def calc_ln_dur_incr(nias):
|
|
55
|
+
# Mask out inappropriate values
|
|
56
|
+
nias = np.asarray(nias)
|
|
57
|
+
mask = (nias < 0.10) | (0.95 < nias)
|
|
58
|
+
nias[mask] = np.nan
|
|
59
|
+
|
|
60
|
+
# Compute the increment due to the difference in the normalized Arias
|
|
61
|
+
# intensity
|
|
62
|
+
ln_i_ratio = np.log((nias - 0.05) / (1 - nias))
|
|
63
|
+
ln_dur_incr = -0.532 + 0.552 * ln_i_ratio - 0.0262 * ln_i_ratio**2
|
|
64
|
+
|
|
65
|
+
return ln_dur_incr
|
|
66
|
+
|
|
67
|
+
def interp(self, nias, stds=None):
|
|
68
|
+
# Mask out inappropriate values
|
|
69
|
+
nias = np.asarray(nias)
|
|
70
|
+
mask = (nias < 0.10) | (0.95 < nias)
|
|
71
|
+
nias[mask] = np.nan
|
|
72
|
+
|
|
73
|
+
ln_dur = self._ln_dur + self.calc_ln_dur_incr(nias)
|
|
74
|
+
|
|
75
|
+
if stds is not None:
|
|
76
|
+
std_errs = np.interp(
|
|
77
|
+
nias,
|
|
78
|
+
[
|
|
79
|
+
0.10,
|
|
80
|
+
0.15,
|
|
81
|
+
0.20,
|
|
82
|
+
0.25,
|
|
83
|
+
0.30,
|
|
84
|
+
0.35,
|
|
85
|
+
0.40,
|
|
86
|
+
0.45,
|
|
87
|
+
0.50,
|
|
88
|
+
0.55,
|
|
89
|
+
0.60,
|
|
90
|
+
0.65,
|
|
91
|
+
0.70,
|
|
92
|
+
0.75,
|
|
93
|
+
0.80,
|
|
94
|
+
0.85,
|
|
95
|
+
0.90,
|
|
96
|
+
0.95,
|
|
97
|
+
],
|
|
98
|
+
[
|
|
99
|
+
0.843,
|
|
100
|
+
0.759,
|
|
101
|
+
0.713,
|
|
102
|
+
0.691,
|
|
103
|
+
0.674,
|
|
104
|
+
0.660,
|
|
105
|
+
0.646,
|
|
106
|
+
0.636,
|
|
107
|
+
0.628,
|
|
108
|
+
0.616,
|
|
109
|
+
0.605,
|
|
110
|
+
0.594,
|
|
111
|
+
0.582,
|
|
112
|
+
0.565,
|
|
113
|
+
0.545,
|
|
114
|
+
0.528,
|
|
115
|
+
0.510,
|
|
116
|
+
0.493,
|
|
117
|
+
],
|
|
118
|
+
)
|
|
119
|
+
ln_dur = ln_dur + np.array(stds)[:, np.newaxis] * std_errs
|
|
120
|
+
|
|
121
|
+
return np.exp(ln_dur)
|