Beispiel #1
0
    def test_generate_fault_source_model_complex(self):
        '''
        Tests the function to turn fault model into mtkSimpleFault or
        mtkComplexFault
        '''
        self.fault = mtkActiveFault('001',
                                    'A Fault',
                                    self.complex_fault, [(5.0, 1.0)],
                                    0.,
                                    None,
                                    aseismic=0.,
                                    msr_sigma=[(0.0, 1.0)],
                                    neotectonic_fault=None,
                                    scale_rel=[(WC1994(), 1.0)],
                                    aspect_ratio=1.0,
                                    shear_modulus=[(30., 1.0)],
                                    disp_length_ratio=[(1.25E-5, 1.0)])
        # Define simple placeholder MFD
        rec_models = [
            IncrementalMFD(5.0, 0.1, 1.0 * np.ones(10)),
            IncrementalMFD(5.0, 0.1, 2.0 * np.ones(10))
        ]
        self.fault.mfd = (rec_models, [0.5, 0.5], [WC1994(), WC1994()])

        # Run model
        source_model, weights = self.fault.generate_fault_source_model()
        self.assertEqual(len(source_model), 2)
        self.assertTrue(isinstance(source_model[0], mtkComplexFaultSource))
        for iloc, model in enumerate(source_model):
            self.assertEqual(model.id, '001')
            self.assertTrue(isinstance(model.mfd, EvenlyDiscretizedMFD))
            np.testing.assert_array_almost_equal(model.mfd.occurrence_rates,
                                                 rec_models[iloc].occur_rates)
            self.assertAlmostEqual(weights[iloc], 0.5)
Beispiel #2
0
    def collapse_branches(self, mmin, bin_width, mmax):
        '''
        Collapse the logic tree branches into a single IncrementalMFD

        :param float mmin:
            Minimum magnitude of reference mfd
        :param float bin_width:
            Bin width of reference mfd
        :param float mmax:
            Maximum magnitude of reference mfd

        :returns:
            :class: openquake.hmtk.models.IncrementalMFD
        '''
        master_mags = np.arange(mmin, mmax + (bin_width / 2.), bin_width)
        master_rates = np.zeros(len(master_mags), dtype=float)
        for model in self.mfd_models:
            id0 = np.logical_and(
                master_mags >= np.min(model.magnitudes) - 1E-9,
                master_mags <= np.max(model.magnitudes) + 1E-9)
            # Use interpolation in log10-y values

            yvals = np.log10(model.recurrence.occur_rates)
            interp_y = np.interp(master_mags[id0],
                                 model.magnitudes,
                                 yvals)
            master_rates[id0] = master_rates[id0] + (model.weight *
                                                     10. ** interp_y)
        return IncrementalMFD(mmin, bin_width, master_rates)
Beispiel #3
0
    def get_recurrence(self, config):
        '''
        Calculates the recurrence model for the given settings as
        an instance of the openquake.hmtk.models.IncrementalMFD

        :param dict config:
            Configuration settings of the magnitude frequency distribution.
        '''
        model = MFD_MAP[config['Model_Name']]()
        model.setUp(config)
        model.get_mmax(config, self.msr, self.rake, self.area)
        model.mmax = model.mmax + (self.msr_sigma * model.mmax_sigma)
        # As the Anderson & Luco arbitrary model requires the input of the
        # displacement to length ratio

        if 'AndersonLucoAreaMmax' in config['Model_Name']:
            if not self.disp_length_ratio:
                # If not defined then default to 1.25E-5
                self.disp_length_ratio = 1.25E-5
            min_mag, bin_width, occur_rates = model.get_mfd(
                self.slip,
                self.area, self.shear_modulus, self.disp_length_ratio)

        else:
            min_mag, bin_width, occur_rates = model.get_mfd(self.slip,
                                                            self.area,
                                                            self.shear_modulus)

        self.recurrence = IncrementalMFD(min_mag, bin_width, occur_rates)
        self.magnitudes = min_mag + np.cumsum(
            bin_width *
            np.ones(len(occur_rates), dtype=float)) - bin_width
        self.max_mag = np.max(self.magnitudes)
Beispiel #4
0
 def _build_mock_recurrence_branches(self):
     '''
     Given the mock branches return information necessary to define a
     collapse model
     '''
     # Build test data
     mags = COLLAPSE_DATA[0, :-1]
     weights = COLLAPSE_DATA[1:-1, -1]
     rates = COLLAPSE_DATA[1:-1:, :-1]
     expected_rate = COLLAPSE_DATA[-1, :-1]
     test_fault = mtkActiveFault('001', 'A Fault', self.simple_fault,
                                 [(5.0, 1.0)], 0., None)
     test_fault.mfd_models = []
     for (iloc, weight) in enumerate(weights):
         idx = rates[iloc, :] > 0
         model = RecurrenceBranch(None,
                                  None,
                                  None,
                                  None,
                                  None,
                                  weight=weight)
         model.recurrence = IncrementalMFD(np.min(rates[iloc, idx]), 0.1,
                                           rates[iloc, idx])
         model.magnitudes = mags[idx]
         test_fault.mfd_models.append(model)
     return test_fault, expected_rate, np.min(mags), np.max(mags), weights
Beispiel #5
0
    def generate_recurrence_models(
            self, collapse=False, bin_width=0.1,
            config=None, rendered_msr=None):
        '''
        Iterates over the lists of values defining epistemic uncertainty
        in the parameters and calculates the corresponding recurrence model
        At present epistemic uncertainty is supported for: 1) slip rate,
        2) magnitude scaling relation, 3) shear modulus, 4) displacement
        to length ratio) and 5) recurrence model.

        :param list config:
            List of MFD model configurations
        :param bool collapse:
            Boolean flag indicating whether to collapse the logic tree branches
        :param float bin_width:
            If collapsing the logic tree branches the reference mfd must be
            defined. The minimum and maximum magnitudes are updated from the
            model, but the bin width must be specified here
        :param list/dict config:
            Configuration (or sets of configurations) of the recurrence
            calculations
        :param rendered_msr:
            If collapsing the logic tree branches a resulting magnitude
            scaling relation must be defined as instance of
            :class: openquake.hazardlib.scalerel.base.BaseASR
        '''
        if collapse and not rendered_msr:
            raise ValueError('Collapsing logic tree branches requires input '
                             'of a single msr for rendering sources')

        # Generate a set of tuples with corresponding weights
        if config is not None:
            self.generate_config_set(config)
        if not isinstance(self.config, list):
            raise ValueError('MFD configuration missing or incorrectly '
                             'formatted')

        # Generate the branching index
        branch_index, _number_branches = self._generate_branching_index()
        mmin = np.inf
        mmax = -np.inf
        for idx in branch_index:
            tuple_list = []
            # Get slip
            tuple_list.append(self.slip[idx[0]])
            # Get msr
            tuple_list.append(self.msr[idx[1]])
            # Get shear modulus
            tuple_list.append(self.shear_modulus[idx[2]])
            # Get displacement length ratio
            tuple_list.append(self.disp_length_ratio[idx[3]])
            # Get msr sigma
            tuple_list.append(self.msr_sigma[idx[4]])
            # Get config
            tuple_list.append(self.config[idx[5]])
            # Calculate branch weight as product of tuple weights
            branch_weight = np.prod(np.array([val[1] for val in tuple_list]))
            # Instantiate recurrence model
            model = RecurrenceBranch(self.area,
                                     tuple_list[0][0],
                                     tuple_list[1][0],
                                     self.rake,
                                     tuple_list[2][0],
                                     tuple_list[3][0],
                                     tuple_list[4][0],
                                     weight=branch_weight)
            model.get_recurrence(tuple_list[5][0])
            self.mfd_models.append(model)
            # Update the total minimum and maximum magnitudes for the fault
            if model.recurrence.min_mag < mmin:
                mmin = model.recurrence.min_mag
            if np.max(model.magnitudes) > mmax:
                mmax = np.max(model.magnitudes)
        if collapse:
            self.mfd = ([self.collapse_branches(mmin, bin_width, mmax)],
                        [1.0],
                        [rendered_msr])
        else:
            mfd_mods = []
            mfd_wgts = []
            mfd_msr = []
            for model in self.mfd_models:
                mfd_mods.append(IncrementalMFD(model.recurrence.min_mag,
                                               model.recurrence.bin_width,
                                               model.recurrence.occur_rates))
                mfd_wgts.append(model.weight)
                mfd_msr.append(model.msr)
            self.mfd = (mfd_mods, mfd_wgts, mfd_msr)