Source code for openquake.hazardlib.imt

# -*- coding: utf-8 -*-
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (C) 2012-2021 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 :mod:`openquake.hazardlib.imt` defines different intensity measure
types.
"""
import ast
import operator
import functools
import numpy

# NB: (MS) the management of the IMTs implemented here is complex, it would
# be better to have a single IMT class, but it is as it is for legacy reasons

registry = {}  # IMT string -> IMT class


[docs]def positivefloat(val): """ Raise a ValueError if val <= 0 """ if val <= 0: raise ValueError(val)
[docs]def imt2tup(string): """ >>> imt2tup('PGA') ('PGA',) >>> imt2tup('SA(1.0)') ('SA', 1.0) >>> imt2tup('SA(1)') ('SA', 1.0) """ s = string.strip() if not s.endswith(')'): # no parenthesis, PGA is considered the same as PGA() return (s,) name, rest = s.split('(', 1) return (name,) + tuple(float(x) for x in ast.literal_eval(rest[:-1] + ','))
[docs]def from_string(imt): """ Convert an IMT string into an hazardlib object. :param str imt: Intensity Measure Type. """ tup = imt2tup(imt) return registry[tup[0]](*tup[1:])
[docs]class IMTMeta(type): """ Metaclass setting __slots__, __new__ and the properties of IMT classes """ def __new__(mcs, name, bases, dct): dct['__slots__'] = () cls = type.__new__(mcs, name, bases, dct) fields = '' for index, (field, check) in enumerate(cls._fields): setattr(cls, field, property(operator.itemgetter(index + 1))) fields += field + ',' evaldic = {} code = '''def __new__(cls, %s): self = tuple.__new__(cls, (%r, %s)) for arg, (field, check) in zip(self[1:], self._fields): check(arg) return self ''' % (fields, name, fields) exec(code, evaldic) cls.__new__ = evaldic['__new__'] cls.__new__.__defaults__ = cls._defaults registry[name] = cls return cls
[docs]@functools.total_ordering class IMT(tuple, metaclass=IMTMeta): """ Base class for intensity measure type. Subclasses may define class attribute ``_fields`` as a tuple with names of parameters the specific intensity measure type requires (if there are any). """ _fields = () _defaults = None @property def name(self): """The name of the Intensity Measure Type (ex. "PGA", "SA", ...)""" return self[0] def __getnewargs__(self): return tuple(getattr(self, field) for field, check in self._fields) def __lt__(self, other): if not self._fields: return self[0] < other[0] # ordered by name return (self[0], self[1] or 0, self[2] or 0) < ( other[0], other[1] or 0, other[2] or 0) def __repr__(self): if not self._fields: # return the name return self[0] return '%s(%s)' % (type(self).__name__, ', '.join(str(getattr(self, field)) for field, check in self._fields))
[docs]class PGA(IMT): """ Peak ground acceleration during an earthquake measured in units of ``g``, times of gravitational acceleration. """ period = 0.0
[docs]class PGV(IMT): """ Peak ground velocity during an earthquake measured in units of ``cm/sec``. """
[docs]class PGD(IMT): """ Peak ground displacement during an earthquake measured in units of ``cm``. """
[docs]class SA(IMT): """ Spectral acceleration, defined as the maximum acceleration of a damped, single-degree-of-freedom harmonic oscillator. Units are ``g``, times of gravitational acceleration. :param period: The natural period of the oscillator in seconds. :param damping: The degree of damping for the oscillator in percents. :raises ValueError: if period or damping is not positive. """ _fields = (('period', positivefloat), ('damping', positivefloat)) _defaults = (5.0,) # damping def __repr__(self): if self.damping != 5.0: return '%s(%s, %s)' % (self.name, self.period, self.damping) else: return '%s(%s)' % (self.name, self.period)
[docs]class AvgSA(IMT): """ Dummy spectral acceleration to compute average ground motion over several spectral ordinates. """
[docs]class IA(IMT): """ Arias intensity. Determines the intensity of shaking by measuring the acceleration of transient seismic waves. Units are ``m/s``. """
[docs]class CAV(IMT): """ Cumulative Absolute Velocity. Defins the integral of the absolute acceleration time series. Units are "g-sec" """
[docs]class RSD(IMT): """ Relative significant duration, 5-95% of :class:`Arias intensity <IA>`, in seconds. """
[docs]class RSD595(IMT): """ Alias for RSD """
[docs]class RSD575(IMT): """ Relative significant duration, 5-75% of :class:`Arias intensity <IA>`, in seconds. """
[docs]class RSD2080(IMT): """ Relative significant duration, 20-80% of :class:`Arias intensity <IA>`, in seconds. """
[docs]class MMI(IMT): """ Modified Mercalli intensity, a Roman numeral describing the severity of an earthquake in terms of its effects on the earth's surface and on humans and their structures. """
[docs]class JMA(IMT): """ Modified Mercalli intensity, a Roman numeral describing the severity of an earthquake in terms of its effects on the earth's surface and on humans and their structures. """
# Volcanic IMTs
[docs]class ASH(IMT): """ Level of the ash fall in millimeters """
# secondary perils
[docs]class Disp(IMT): """ Displacement """
[docs]class DispProb(IMT): """ Displacement probability """
[docs]class LiqProb(IMT): """ Liquefaction probability """
[docs]class PGDMax(IMT): """ Maximum between vert_settlement and lat_spread """ def __call__(self, vert_settlement, lat_spread): return numpy.maximum(vert_settlement, lat_spread)
[docs]class PGDGeomMean(IMT): """ Geometric mean between vert_settlement and lat_spread """ def __call__(cls, vert_settlement, lat_spread): return numpy.sqrt(vert_settlement * lat_spread)