Source code for shakelib.virtualipe
import copy
import numpy as np
from openquake.hazardlib.gsim.base import GMPE
from openquake.hazardlib.imt import PGA, PGV, SA, MMI
from openquake.hazardlib import const
from shakelib.utils.exception import ShakeLibException
[docs]class VirtualIPE(GMPE):
"""
Implements a virtual IPE that is the combination of a MultiGMPE
and a GMICE. Will first attempt to use PGV for the intensities,
and then will try PGA, and then SA(1.0), and then will bail out.
Uncertainty is computed by combining the uncertainty of the GMPE
with the uncertainty of the GMICE. Standard error propagation
techniques are used (see the ShakeMap manual for a detailed
explanation). For the intra- and inter-event components of total
uncertainty, we assign all of GMICE uncertaninty to the intra-event
term, and none to the inter-event term. This choice is conservative,
and seems appropriate until GMICE are produced with separate inter-
and intra-event terms.
Note that the combined inter- and intra-event uncertainties will
only approximately equal the total uncertainty because the GMPEs
will only produce combined uncertainties that are approximately
equal to their total uncertainty.
"""
#: The OpenQuake IMT this module can produce ('MMI' only).
DEFINED_FOR_INTENSITY_MEASURE_TYPES = set([MMI])
#: The OpenQuake standard deviation types that may be produced (will
#: depend on the GMPE provided).
DEFINED_FOR_STANDARD_DEVIATION_TYPES = set([const.StdDev.TOTAL])
#: Distance measures required (will depend on the GMPE provided).
REQUIRES_DISTANCES = None
#: OpenQuake IMC used (will depend on the GMPE, but "Larger" is
#: typical).
DEFINED_FOR_INTENSITY_MEASURE_COMPONENT = None
#: Determined by the GMPE selected.
DEFINED_FOR_TECTONIC_REGION_TYPE = None
#: Determined by the GMPE selected.
REQUIRES_RUPTURE_PARAMETERS = None
#: Determined by the GMPE selected.
REQUIRES_SITES_PARAMETERS = None
@classmethod
def __fromFuncs__(cls, gmpe, gmice):
"""
Creates a new VirtualIPE object with the specified MultiGMPE and
GMICE. There is no default constructor, you must use this method.
Args:
gmpe: An instance of the MultiGMPE object.
gmice: An instance of a GMICE object.
Returns:
:class:`VirtualIPE`: A new instance of a VirtualIPE object.
"""
self = cls()
self.gmpe = gmpe
self.gmice = gmice
if (
gmpe.ALL_GMPES_HAVE_PGV is True
and PGV in gmice.DEFINED_FOR_INTENSITY_MEASURE_TYPES
):
self.imt = PGV()
elif (
PGA in gmpe.DEFINED_FOR_INTENSITY_MEASURE_TYPES
and PGA in gmice.DEFINED_FOR_INTENSITY_MEASURE_TYPES
):
self.imt = PGA()
elif (
SA in gmpe.DEFINED_FOR_INTENSITY_MEASURE_TYPES
and SA in gmice.DEFINED_FOR_INTENSITY_MEASURE_TYPES
):
self.imt = SA(1.0)
else:
raise ShakeLibException(
"The supplied GMPE and GMICE do not have a common IMT"
)
self.DEFINED_FOR_STANDARD_DEVIATION_TYPES = (
gmpe.DEFINED_FOR_STANDARD_DEVIATION_TYPES.copy()
)
self.REQUIRES_DISTANCES = gmpe.REQUIRES_DISTANCES.copy()
self.REQUIRES_RUPTURE_PARAMETERS = gmpe.REQUIRES_RUPTURE_PARAMETERS.copy()
self.REQUIRES_SITES_PARAMETERS = gmpe.REQUIRES_SITES_PARAMETERS.copy()
self.DEFINED_FOR_INTENSITY_MEASURE_COMPONENT = copy.copy(
gmpe.DEFINED_FOR_INTENSITY_MEASURE_COMPONENT
)
self.DEFINED_FOR_TECTONIC_REGION_TYPE = copy.copy(
gmpe.DEFINED_FOR_TECTONIC_REGION_TYPE
)
return self
[docs] def get_mean_and_stddevs(self, sx, rx, dx, imt, stddev_types, fd=None):
"""
See superclass
`method <http://docs.openquake.org/oq-hazardlib/master/gsim/index.html#openquake.hazardlib.gsim.base.GroundShakingIntensityModel.get_mean_and_stddevs>`__
for parameter definitions. The only acceptable IMT is MMI.
Additional subclass argument is "fd", which is the directivity
amplification factor in natural log units. This is optional,
and must be a numpy array with the same dimentions as the
sites and is added to the ground motions before conversion to
MMI.
Returns:
ndarray, list of ndarray:
mmi (ndarray): Ground motions predicted by the MultiGMPE using
the supplied parameters are converted to MMI using the GMICE.
mmi_sd (list of ndarrays): The uncertainty of the combined
prediction/conversion process. The prediction uncertainty will
typically be either OpenQuake's TOTAL or INTRA_EVENT. But can
be any set that the MultiGMPE supports. See the ShakeMap manual
for a detailed discussion of the way the uncertainty is computed.
""" # noqa
if imt != MMI():
raise ValueError("imt must be MMI")
#
# Get the mean ground motions and stddev for the preferred IMT
#
mgm, sdev = self.gmpe.get_mean_and_stddevs(sx, rx, dx, self.imt, stddev_types)
if fd is not None:
mgm = mgm + fd
#
# Get the MMI and the dMMI/dPGM from the GMICE
#
if hasattr(dx, "rrup"):
dist4gmice = dx.rrup
else:
dist4gmice = dx.rhypo
mmi, dmda = self.gmice.getMIfromGM(mgm, self.imt, dist4gmice, rx.mag)
#
# Compute the uncertainty of the combined prediction/conversion
# Total and intra-event uncertanty are inflated by the uncertainty
# of the conversion; inter-event uncertainty is not.
#
ntypes = len(stddev_types)
nsd = len(sdev)
mmi_sd = [None] * nsd
gm2mi_var = (self.gmice.getGM2MIsd()[self.imt]) ** 2
dmda *= dmda
for i in range(nsd):
gm_var_in_mmi = dmda * sdev[i] ** 2
if stddev_types[i % ntypes] == const.StdDev.INTER_EVENT:
mmi_sd[i] = np.sqrt(gm_var_in_mmi)
else:
mmi_sd[i] = np.sqrt(gm2mi_var + gm_var_in_mmi)
return mmi, mmi_sd