示例#1
0
def site_term(self, ctx, dists, imt):
    """
    Site term as used to calculate site coefficients for NBCC2015:

    For Vs30 > 760 m/s use log-log interpolation of the 760-to-2000
    factor of AA13.

    For Vs30 < 760 m/s use the site term of Boore and Atkinson 2008.

    Original site term is relative to Vs30 = 760m/s so needs to be made
    relative to Vs30 = 450 m/s by dividing by the site term at Vs30 = 450.
    Assume PGA_760 = 0.1g for Vs30 > 450 m/s. Also need to correct PGA at
    site class C to 760 m/s. Cap PGA_450 at 0.1 - 0.5g.
    """
    imls_pga = _return_tables(self, ctx.mag, PGA(), "IMLs")
    PGA450 = _get_mean(self.kind, self.distance_type, imls_pga, ctx, dists)
    imls_SA02 = _return_tables(self, ctx.mag, SA(0.2), "IMLs")
    SA02 = _get_mean(self.kind, self.distance_type, imls_SA02, ctx, dists)

    PGA450[SA02 / PGA450 < 2.0] = PGA450[SA02 / PGA450 < 2.0] * 0.8

    pgas = np.array([0.1, 0.2, 0.3, 0.4, 0.5])
    pga_cors = np.array([0.083, 0.165, 0.248, 0.331, 0.414])
    PGA760 = np.interp(PGA450, pgas, pga_cors)
    PGA760_ref = np.copy(PGA760)
    PGA760_ref[ctx.vs30 > 450.] = 0.1

    vs30ref = np.zeros_like(ctx.vs30)
    vs30ref += 450.0

    C = self.COEFFS_2000_to_BC[imt]
    site_term = (AB06_BA08(C, ctx.vs30, imt, PGA760_ref) /
                 AB06_BA08(C, vs30ref, imt, PGA760_ref))
    return np.log(site_term)
示例#2
0
 def test_retreival_tables_outside_period_range(self):
     """
     Tests that an error is raised when inputting a period value
     outside the supported range
     """
     gsim = GMPETable(gmpe_table=self.TABLE_FILE)
     with self.assertRaises(ValueError) as ve:
         _return_tables(gsim, 6.0, imt_module.SA(2.5), "IMLs")
     self.assertEqual(
         str(ve.exception),
         "Spectral period 2.500 outside of valid range (0.100 to 2.000)")
示例#3
0
 def test_retreival_tables_outside_mag_range(self):
     """
     Tests that an error is raised when inputting a magnitude value
     outside the supported range
     """
     gsim = GMPETable(gmpe_table=self.TABLE_FILE)
     with self.assertRaises(ValueError) as ve:
         _return_tables(gsim, 4.5, imt_module.PGA(), "IMLs")
     self.assertEqual(
         str(ve.exception),
         "Magnitude 4.50 outside of supported range (5.00 to 7.00)")
示例#4
0
 def test_retreival_tables_good_interp(self):
     """
     Tests the retreival of the IML tables for 'good' conditions with
     magnitude interpolations
     """
     gsim = GMPETable(gmpe_table=self.TABLE_FILE)
     expected_table_pgv = np.array(
         [midpoint(20., 40.),
          midpoint(10., 20.),
          midpoint(5., 10.)])
     np.testing.assert_array_almost_equal(
         _return_tables(gsim, 6.5, imt_module.PGV(), "IMLs"),
         expected_table_pgv, 5)
     expected_table_sa1 = np.array(
         [midpoint(2., 4.),
          midpoint(1., 2.),
          midpoint(0.5, 1.)])
     np.testing.assert_array_almost_equal(
         _return_tables(gsim, 6.5, imt_module.SA(1.0), "IMLs"),
         expected_table_sa1)
示例#5
0
def get_hard_rock_mean(self, ctx, imt):
    """
    Returns the mean and standard deviations for the reference very hard
    rock condition (Vs30 = 3000 m/s)
    """
    # Return Distance Tables
    imls = _return_tables(self, ctx.mag, imt, "IMLs")
    # Get distance vector for the given magnitude
    idx = np.searchsorted(self.m_w, ctx.mag)
    dists = self.distances[:, 0, idx - 1]
    # Get mean and standard deviations
    mean = _get_mean(self.kind, self.distance_type, imls, ctx, dists)
    return np.log(mean)
示例#6
0
 def test_retreival_tables_good_no_interp(self):
     """
     Tests the retreival of the IML tables for 'good' conditions without
     applying magnitude interpolations
     """
     gsim = GMPETable(gmpe_table=self.TABLE_FILE)
     # PGA
     np.testing.assert_array_almost_equal(
         _return_tables(gsim, 6.0, imt_module.PGA(), "IMLs"),
         np.array([2., 1., 0.5]))
     # PGV
     np.testing.assert_array_almost_equal(
         _return_tables(gsim, 6.0, imt_module.PGV(), "IMLs"),
         np.array([20., 10., 5.]), 5)
     # SA(1.0)
     np.testing.assert_array_almost_equal(
         _return_tables(gsim, 6.0, imt_module.SA(1.0), "IMLs"),
         np.array([2.0, 1., 0.5]))
     # Also for standard deviations
     np.testing.assert_array_almost_equal(
         _return_tables(gsim, 6.0, imt_module.PGA(), 0), 0.5 * np.ones(3))
     np.testing.assert_array_almost_equal(
         _return_tables(gsim, 6.0, imt_module.SA(1.0), 0), 0.8 * np.ones(3))
示例#7
0
 def compute(self, ctx, imts, mean, sig, tau, phi):
     """
     Returns the mean and standard deviations
     """
     stds = [sig, tau, phi]
     stdis = [
         const.StdDev.idx[sdt]
         for sdt in self.DEFINED_FOR_STANDARD_DEVIATION_TYPES
     ]
     for m, imt in enumerate(imts):
         # Return Distance Tables
         imls = _return_tables(self, ctx.mag, imt, "IMLs")
         # Get distance vector for the given magnitude
         idx = np.searchsorted(self.m_w, ctx.mag)
         dists = self.distances[:, 0, idx - 1]
         # Get mean and standard deviations
         mean[m] = np.log(
             _get_mean(self.kind, self.distance_type, imls, ctx,
                       dists)) + site_term(self, ctx, dists, imt)
         stddevs = _get_stddevs(self, dists, ctx, imt, stdis)
         for s in stdis:
             stds[s][m] = stddevs[s]
示例#8
0
    def get_mean_and_stddevs(self, sites, rx, dists, imt, stddev_types):
        # List of GMPE weights, which is the product of the the branch weights
        # for the seed models vs the NGA East resampled models as well as the
        # weights for the indivudual GMPES as defined by Petersen et al. (2019)
        #
        # Note that the NGA East resampled models are a function of spectral
        # period.
        #
        # NGA East Seeds (1/3)
        #     ├── B_bca10d (0.06633), wts = 0.333 * 0.06633 = 0.02208789
        #     ├── B_ab95 (0.02211), wts = 0.333 * 0.02211 = 0.00736263
        #     ...
        # NGA East Resampled or "USGS" (2/3)
        #     ├── Model 1 (0.1009 for PGA), wts = 0.667 * 0.1009 = 0.0673003
        #     ├── Model 2 (0.1606 for PGA), wts = 0.667 * 0.1606 = 0.1071202
        #     ...
        #
        wts = [0] * len(self.gmpes)

        # Is IMT PGA or PGV?
        is_pga = imt == IMT.PGA()
        is_pgv = imt == IMT.PGV()

        # Is magnitude less than 4? If so, we will need to set it to 4.0 and
        # then extrapolate the tables at the end.
        # But... in the brave new world of new OpenQuake, sites, rx, and
        # dists are all exactly the same object, so when we copy rx to
        # rup, and change it, as well as when we change the distances
        # below, we need to do it all in rup, then pass rup as all three
        # contexts when we call the gmpe.get_mean_and_stddevs()
        rup = copy.deepcopy(rx)
        if rup.mag < 4.0:
            is_small_mag = True
            delta_mag = rup.mag - 4.0
            rup.mag = 4.0
        else:
            is_small_mag = False

        for i, tp in enumerate(self.ALL_TABLE_PATHS):
            if 'usgs' in tp:
                # Get model number from i-th path using regex
                mod_num = int(re.search(r'\d+', tp).group())
                coefs = np.array(self.NGA_EAST_USGS.iloc[mod_num - 1])
                # Is the IMT PGA, PGA, or SA?
                if is_pga:
                    iweight = coefs[-2]
                elif is_pgv:
                    iweight = coefs[-1]
                else:
                    # For SA, need to interpolate; we'll use log-period and
                    # linear-weight interpolation.
                    iweight = np.interp(
                        np.log(imt.period), np.log(self.per_array),
                        coefs[self.per_idx_start:self.per_idx_end])
                wts[i] = self.NGA_EAST_USGS_WEIGHT * iweight
            else:
                # Strip off the cruft to get the string we need to match
                str_match = tp.replace('nga_east_', '').replace('.hdf5', '')
                matched = self.NGA_EAST_SEEDS[self.NGA_EAST_SEEDS['model'] ==
                                              str_match]
                if len(matched):
                    iweight = self.NGA_EAST_SEEDS[self.NGA_EAST_SEEDS['model']
                                                  == str_match].iloc[0, 1]
                    wts[i] = self.NGA_EAST_SEED_WEIGHT * iweight

        total_gmpe_weights = self.sigma_weights * wts

        if not np.allclose(np.sum(total_gmpe_weights), 1.0):
            raise ValueError('Weights must sum to 1.0.')

        mean = np.full_like(sites.vs30, 0)
        stddevs = []
        for i in range(len(stddev_types)):
            stddevs.append(np.full_like(sites.vs30, 0))

        # Apply max distance to dists.rrup -->> now rup.rrup
        np.clip(rup.rrup, 0, MAX_RRUP)

        #
        # Some models don't have PGV terms, so we will make PSA for them
        # and then use the conditional conversion to get PGV
        #
        if is_pgv:
            ab2020 = AbrahamsonBhasin2020(rup.mag)
            vimt = IMT.SA(ab2020.getTref())

        # Loop over gmpes
        for i, gm in enumerate(self.gmpes):
            if is_pgv:
                # Is PGV and also not available for gm?
                try:
                    _ = _return_tables(gm, rup.mag, imt, "IMLs")
                except KeyError:
                    #
                    # No table for PGV, compute vimt, then convert to PGV
                    #
                    vmean, vstddevs = gm.get_mean_and_stddevs(
                        rup, rup, rup, vimt, stddev_types)
                    tmean, tstddevs = ab2020.getPGVandSTDDEVS(
                        vmean, vstddevs, stddev_types, rup.rrup, rup.vs30)
                except Exception:
                    logging.error("Unexpected error:", sys.exc_info()[0])
                else:
                    #
                    # Table exists for PGV, proceed normally
                    #
                    tmean, tstddevs = gm.get_mean_and_stddevs(
                        rup, rup, rup, imt, stddev_types)
            else:
                tmean, tstddevs = gm.get_mean_and_stddevs(
                    rup, rup, rup, imt, stddev_types)

            mean += tmean * total_gmpe_weights[i]
            for j, sd in enumerate(tstddevs):
                stddevs[j] += sd * total_gmpe_weights[i]

        # Zero out values at distances beyond the range for which NGA East
        # was defined. -->> was dists.rrup, now rup.rrup
        mean[rup.rrup > MAX_RRUP] = -999.0

        # Do we need to extrapolate for small magnitude factor?
        if is_small_mag:
            if is_pga:
                slopes = np.interp(np.log(rup.rrup), np.log(self.SMALL_M_DIST),
                                   self.SMALL_M_SLOPE_PGA)
            elif is_pgv:
                slopes = np.interp(np.log(rup.rrup), np.log(self.SMALL_M_DIST),
                                   self.SMALL_M_SLOPE_PGV)
            else:
                interp_obj = RectBivariateSpline(np.log(self.SMALL_M_DIST),
                                                 np.log(self.SMALL_M_PER),
                                                 self.SMALL_M_SLOPE,
                                                 kx=1,
                                                 ky=1)
                slopes = interp_obj.ev(np.log(rup.rrup), np.log(imt.period))
            mean = mean + slopes * delta_mag

        return mean, stddevs