Source code for shakelib.conversions.imc.beyer_bommer_2006


from openquake.hazardlib import const

import numpy as np


[docs]class BeyerBommer2006(object): """ Implements conversion for various "Intensity Measure Components" (IMCs) per Beyer and Bommer (2006). IMC equivalencies: +---------------------------+------------------------+ | OpenQuake | Beyer & Bommer | +===========================+========================+ | AVERAGE_HORIZONTAL | GMxy (Geometric mean) | +---------------------------+------------------------+ | HORIZONTAL | Random? | +---------------------------+------------------------+ | MEDIAN_HORIZONTAL | AMxy (Arithmetic mean) | +---------------------------+------------------------+ | GMRotI50 | GMRotI50 | +---------------------------+------------------------+ | RotD50 | GMRotD50 | +---------------------------+------------------------+ | RANDOM_HORIZONTAL | Random | +---------------------------+------------------------+ | GREATER_OF_TWO_HORIZONTAL | Env_xy | +---------------------------+------------------------+ | VERTICAL | --- | +---------------------------+------------------------+ Notes - AVERAGE_HORIZONTAL is the "reference" type. - The OQ IMC "HORIZONAL" indicates that the horizontal IMC category may be ambiguous. In these cases, we are assuming that it is a random horizontal component as a default. To do - Inherit from ConvertIMC class. References Beyer, K., & Bommer, J. J. (2006). Relationships between median values and between aleatory variabilities for different definitions of the horizontal component of motion. Bulletin of the Seismological Society of America, 96(4A), 1512-1522. `[link] <http://www.bssaonline.org/content/96/4A/1512.short>`__ """ # c12 = median ratio # c34 = std. of log ratio # R = ratio of sigma_pga values __pga_pgv_col_names = ['c12', 'c34', 'R'] __sa_col_names = ['c1', 'c2', 'c3', 'c4', 'R'] __pga_dict = { const.IMC.MEDIAN_HORIZONTAL: dict(list(zip(__pga_pgv_col_names, [1.0, 0.01, 1.00]))), const.IMC.GMRotI50: dict(list(zip(__pga_pgv_col_names, [1.0, 0.02, 1.00]))), const.IMC.RotD50: dict(list(zip(__pga_pgv_col_names, [1.0, 0.02, 1.00]))), const.IMC.RANDOM_HORIZONTAL: dict(list(zip(__pga_pgv_col_names, [1.0, 0.07, 1.03]))), const.IMC.HORIZONTAL: dict(list(zip(__pga_pgv_col_names, [1.0, 0.07, 1.03]))), const.IMC.GREATER_OF_TWO_HORIZONTAL: dict(list(zip(__pga_pgv_col_names, [1.1, 0.05, 1.02])))} __pgv_dict = { const.IMC.MEDIAN_HORIZONTAL: dict(list(zip(__pga_pgv_col_names, [1.0, 0.01, 1.00]))), const.IMC.GMRotI50: dict(list(zip(__pga_pgv_col_names, [1.0, 0.02, 1.00]))), const.IMC.RotD50: dict(list(zip(__pga_pgv_col_names, [1.0, 0.02, 1.00]))), const.IMC.RANDOM_HORIZONTAL: dict(list(zip(__pga_pgv_col_names, [1.0, 0.07, 1.03]))), const.IMC.HORIZONTAL: dict(list(zip(__pga_pgv_col_names, [1.0, 0.07, 1.03]))), const.IMC.GREATER_OF_TWO_HORIZONTAL: dict(list(zip(__pga_pgv_col_names, [1.1, 0.05, 1.02])))} __sa_dict = { const.IMC.MEDIAN_HORIZONTAL: dict(list(zip(__sa_col_names, [1.0, 1.0, 0.01, 0.02, 1.00]))), const.IMC.GMRotI50: dict(list(zip(__sa_col_names, [1.0, 1.0, 0.03, 0.04, 1.00]))), const.IMC.RotD50: dict(list(zip(__sa_col_names, [1.0, 1.0, 0.02, 0.03, 1.00]))), const.IMC.RANDOM_HORIZONTAL: dict(list(zip(__sa_col_names, [1.0, 1.0, 0.07, 0.11, 1.05]))), const.IMC.HORIZONTAL: dict(list(zip(__sa_col_names, [1.0, 1.0, 0.07, 0.11, 1.05]))), const.IMC.GREATER_OF_TWO_HORIZONTAL: dict(list(zip(__sa_col_names, [1.1, 1.2, 0.04, 0.07, 1.02])))}
[docs] @staticmethod def ampIMCtoIMC(amps, imc_in, imc_out, imt): """ Returns amps converted from one IMC to another. **Important**: - Assumes the input amps are in natural log (not linear) space - IMC type 'VERTICAL' is not supported Args: amps (array): Numpy array of ground motion amplitudes. imc_in (IMC): OpenQuake IMC type of the input amp array. `[link] <http://docs.openquake.org/oq-hazardlib/master/const.html?highlight=imc#openquake.hazardlib.const.IMC>`__ imc_out (IMC): Desired OpenQuake IMC type of the output amps. `[link] <http://docs.openquake.org/oq-hazardlib/master/const.html?highlight=imc#openquake.hazardlib.const.IMC>`__ imt (IMT): OpenQuake IMT of the input amps (must be one of PGA, PGV, or SA). `[link] <http://docs.openquake.org/oq-hazardlib/master/imt.html>` Returns: array: Numpy array of amps converted from imc_in to imc_out. """ # noqa denom = BeyerBommer2006.__GM2other(imt, imc_in) numer = BeyerBommer2006.__GM2other(imt, imc_out) return amps + np.log(numer / denom)
[docs] @staticmethod def sigmaIMCtoIMC(sigmas, imc_in, imc_out, imt): """ Returns standard deviations converted from one IMC to another. **Important**: - Assumes the input sigmas are in natural log space - IMC types 'VERTICAL' and 'HORIZONTAL' are not supported Args: sigmas (array): Numpy array of standard deviations. imc_in (IMC): OpenQuake IMC type of the input sigmas array. `[link] <http://docs.openquake.org/oq-hazardlib/master/const.html?highlight=imc#openquake.hazardlib.const.IMC>`__ imc_out (IMC): Desired OpenQuake IMC type of the output sigmas. `[link] <http://docs.openquake.org/oq-hazardlib/master/const.html?highlight=imc#openquake.hazardlib.const.IMC>`__ imt (IMT): OpenQuake IMT of the input sigmas (must be one of PGA, PGV, or SA) `[link] <http://docs.openquake.org/oq-hazardlib/master/imt.html>`__ Returns: array: Numpy array of standard deviations converted from imc_in to imc_out. """ # noqa # --------------------------------------------------------------------- # Take input sigma to geometric mean sigma. # Solve eqn 8 for sigma_GM2, which is sigma_logSa_GM # This is the sigma converted to geometric mean # (i.e., reference component). # --------------------------------------------------------------------- R, sig_log_ratio = BeyerBommer2006.__GM2otherSigma(imt, imc_in) sigma_GM2 = (sigmas**2 - sig_log_ratio**2) / R**2 # --------------------------------------------------------------------- # Evaluate equation 8 to go from GM to requested IMC # --------------------------------------------------------------------- R, sig_log_ratio = BeyerBommer2006.__GM2otherSigma(imt, imc_out) sigma_out = np.sqrt(sigma_GM2 * R**2 + sig_log_ratio**2) return sigma_out
@staticmethod def __checkIMC(imc): """ Check that the requested IMC is available. """ if imc != const.IMC.GREATER_OF_TWO_HORIZONTAL and \ imc != const.IMC.MEDIAN_HORIZONTAL and \ imc != const.IMC.GMRotI50 and \ imc != const.IMC.RotD50 and \ imc != const.IMC.RANDOM_HORIZONTAL and \ imc != const.IMC.HORIZONTAL: raise ValueError('unknown IMC %r' % imc) @staticmethod def __GM2other(imt, imc): """ Helper function to extract coefficients from the parameters for converting the median ground motions. Args: imt (IMT): OQ intensity measure type. imc (IMC): OQ Intensity measure component. Returns: float: Median ratios. This is directly from Table 2 for PGA and PGV, and computed from coefficients in Table 3 along with eqn 10 for Sa. """ if imc == const.IMC.AVERAGE_HORIZONTAL: # The amps are already in the B&B "reference" type ("GM", i.e., # geometric mean) return 1. BeyerBommer2006.__checkIMC(imc) if 'PGA' in imt: return BeyerBommer2006.__pga_dict[imc]['c12'] elif 'PGV' in imt: return BeyerBommer2006.__pgv_dict[imc]['c12'] elif 'SA' in imt: pp = imt.period if pp <= 0.15: return BeyerBommer2006.__sa_dict[imc]['c1'] elif pp < 0.8: c1 = BeyerBommer2006.__sa_dict[imc]['c1'] c2 = BeyerBommer2006.__sa_dict[imc]['c2'] return c1 + (c2 - c1) * np.log(pp / 0.15) / np.log(0.8 / 0.15) elif pp <= 5.0: return BeyerBommer2006.__sa_dict[imc]['c2'] else: # Not sure what's right here; should probably raise an error # but for now let's just use c2 return BeyerBommer2006.__sa_dict[imc]['c2'] else: raise ValueError('unknown IMT %r' % imt) @staticmethod def __GM2otherSigma(imt, imc): """ Helper function to extract coefficients from the parameters for converting standard deviations. Args: imt (IMT): OQ intensity measure type. imc (IMC): OQ intensity measure component. Returns: tuple: Coefficients: R (ratio of sigma values), standard deviation of sigma ratios. """ if imc == const.IMC.AVERAGE_HORIZONTAL: # The amps are already in the B&B "reference" type ("GM", i.e., # geometric mean) return 1., 0. BeyerBommer2006.__checkIMC(imc) if 'PGA' in imt: return BeyerBommer2006.__pga_dict[imc]['R'],\ BeyerBommer2006.__pga_dict[imc]['c34'] elif 'PGV' in imt: return BeyerBommer2006.__pgv_dict[imc]['R'],\ BeyerBommer2006.__pgv_dict[imc]['c34'] elif 'SA' in imt: R = BeyerBommer2006.__sa_dict[imc]['R'] pp = imt.period if pp <= 0.15: return R, BeyerBommer2006.__sa_dict[imc]['c3'] elif pp < 0.8: c3 = BeyerBommer2006.__sa_dict[imc]['c3'] c4 = BeyerBommer2006.__sa_dict[imc]['c4'] return R, c3 + (c4 - c3) * np.log(pp / 0.15) /\ np.log(0.8 / 0.15) elif pp <= 5.0: return R, BeyerBommer2006.__sa_dict[imc]['c4'] else: # Not sure what's right here; should probably raise an error # but for now let's just use c4 return R, BeyerBommer2006.__sa_dict[imc]['c4'] else: raise ValueError('unknown IMT %r' % imt)