def _get_base_rates(self, base_params): ''' Defines the base moment rate that should be assigned to places of zero strain (i.e. Intraplate regions). In Bird et al (2010) this is taken as basic rate of Intraplate events in GCMT catalogue above the threshold magnitude :param dict base_params: Parameters needed for calculating the base rate. Requires: 'CMT_EVENTS': The number of CMT events 'area': Total area (km ^ 2) of the region class 'CMT_duration': Duration of reference catalogue 'CMT_moment': Moment rate from CMT catalogue 'corner_mag': Corner magnitude of Tapered G-R for region 'beta': Beta value of tapered G-R for distribution ''' base_ipl_rate = base_params['CMT_EVENTS'] / ( base_params['area'] * base_params['CMT_duration']) base_rate = np.zeros(self.number_magnitudes, dtype=float) for iloc in range(0, self.number_magnitudes): base_rate[iloc] = base_ipl_rate * calculate_taper_function( base_params['CMT_moment'], self.threshold_moment[iloc], moment_function(base_params['corner_mag']), base_params['beta']) return base_rate
def continuum_seismicity(self, threshold_moment, e1h, e2h, err, region_params): ''' Function to implement the continuum seismicity calculation given vectors of input rates e1h, e2h [np.ndarray] and a dictionary of the corresponding regionalisation params returns a vector of the corresponding seismicity rates Python implementation of the CONTINUUM_SEISMICITY subroutine of SHIFT_GSRM.f90 :param float threshold_moment: Target moment for calculation of activity rate :param np.ndarray e1h: First principal strain rate :param np.ndarray e1h: Second principal strain rate :param np.ndarray err: Vertical strain rate :param dict region_params: Activity rate parameters specific to the tectonic region under consideration :returns: Cumulative seismicity rate greater than or equal to the threshold magnitude ''' strain_values = np.column_stack([e1h, e2h, err]) e1_rate = np.amin(strain_values, axis=1) e3_rate = np.amax(strain_values, axis=1) e2_rate = 0. - e1_rate - e3_rate # Pre-allocate seismicity rate with zeros seismicity_rate = np.zeros( [np.shape(strain_values)[0], len(threshold_moment)], dtype=float) # Calculate moment rate per unit area temp_e_rate = 2.0 * (-e1_rate) id0 = np.where(e2_rate < 0.0)[0] temp_e_rate[id0] = 2.0 * e3_rate[id0] M_persec_per_m2 = region_params['assumed_mu'] * temp_e_rate *\ region_params['coupled_thickness'] # Calculate seismicity rate at the threshold moment of the CMT # catalogue - Eq 6 in Bird et al (2010) seismicity_at_cmt_threshold = region_params['CMT_pure_event_rate'] * \ (M_persec_per_m2 / region_params['tGR_moment_rate']) # Adjust forecast rate to desired rate using tapered G-R model # Taken from Eq 7 (Bird et al. 2010) and Eq 9 (Bird & Kagan, 2004) for iloc, moment_thresh in enumerate(threshold_moment): g_function = calculate_taper_function( region_params['CMT_moment'], moment_thresh, region_params['corner_moment'], region_params['beta']) seismicity_rate[:, iloc] = g_function * seismicity_at_cmt_threshold return seismicity_rate
def continuum_seismicity(self, threshold_moment, e1h, e2h, err, region_params): ''' Function to implement the continuum seismicity calculation given vectors of input rates e1h, e2h [np.ndarray] and a dictionary of the corresponding regionalisation params returns a vector of the corresponding seismicity rates Python implementation of the CONTINUUM_SEISMICITY subroutine of SHIFT_GSRM.f90 :param float threshold_moment: Target moment for calculation of activity rate :param np.ndarray e1h: First principal strain rate :param np.ndarray e1h: Second principal strain rate :param np.ndarray err: Vertical strain rate :param dict region_params: Activity rate parameters specific to the tectonic region under consideration :returns: Cumulative seismicity rate greater than or equal to the threshold magnitude ''' strain_values = np.column_stack([e1h, e2h, err]) e1_rate = np.amin(strain_values, axis=1) e3_rate = np.amax(strain_values, axis=1) e2_rate = 0. - e1_rate - e3_rate # Pre-allocate seismicity rate with zeros seismicity_rate = np.zeros( [np.shape(strain_values)[0], len(threshold_moment)], dtype=float) # Calculate moment rate per unit area temp_e_rate = 2.0 * (-e1_rate) id0 = np.where(e2_rate < 0.0)[0] temp_e_rate[id0] = 2.0 * e3_rate[id0] M_persec_per_m2 = (region_params['assumed_mu'] * temp_e_rate * region_params['coupled_thickness']) # Calculate seismicity rate at the threshold moment of the CMT # catalogue - Eq 6 in Bird et al (2010) seismicity_at_cmt_threshold = region_params['CMT_pure_event_rate'] * \ (M_persec_per_m2 / region_params['tGR_moment_rate']) # Adjust forecast rate to desired rate using tapered G-R model # Taken from Eq 7 (Bird et al. 2010) and Eq 9 (Bird & Kagan, 2004) for iloc, moment_thresh in enumerate(threshold_moment): g_function = calculate_taper_function( region_params['CMT_moment'], moment_thresh, region_params['corner_moment'], region_params['beta']) seismicity_rate[:, iloc] = g_function * seismicity_at_cmt_threshold return seismicity_rate
def test_calculate_taper_function_zero_case(self): ''' Test case when g_function is 0.0. g_function is 0 when (obs - sel) < -100.0 * corner_mo This scenario seems to occur when the selected moment is significantly greater than the corner magnitude ''' self.assertAlmostEqual( 0.0, calculate_taper_function(moment_function(5.0), moment_function(8.0), moment_function(6.0), self.beta))
def test_calculate_taper_function_zero_case(self): ''' Test case when g_function is 0.0. g_function is 0 when (obs - sel) < -100.0 * corner_mo This scenario seems to occur when the selected moment is significantly greater than the corner magnitude ''' self.assertAlmostEqual(0.0, calculate_taper_function( moment_function(5.0), moment_function(8.0), moment_function(6.0), self.beta))
def test_calculate_taper_function(self): ''' Tests the function to calculate the taper part of the Tapered Gutenberg & Richter model with exhaustive data set ''' obs_mo = moment_function(np.arange(5.0, 9.5, 1.0)) sel_mo = moment_function(np.arange(5.0, 9.5, 1.0)) obs_data = np.zeros([len(obs_mo), len(sel_mo)], dtype=float) corner_mo = moment_function(8.5) for iloc, obs in enumerate(obs_mo): for jloc, sel in enumerate(sel_mo): obs_data[iloc, jloc] = calculate_taper_function( obs, sel, corner_mo, self.beta) np.testing.assert_array_almost_equal(TAPER_FUNCTION_DATA, np.log10(obs_data))
def test_calculate_taper_function(self): ''' Tests the function to calculate the taper part of the Tapered Gutenberg & Richter model with exhaustive data set ''' obs_mo = moment_function(np.arange(5.0, 9.5, 1.0)) sel_mo = moment_function(np.arange(5.0, 9.5, 1.0)) obs_data = np.zeros([len(obs_mo), len(sel_mo)], dtype=float) corner_mo = moment_function(8.5) for iloc, obs in enumerate(obs_mo): for jloc, sel in enumerate(sel_mo): obs_data[iloc, jloc] = calculate_taper_function(obs, sel, corner_mo, self.beta) np.testing.assert_array_almost_equal(TAPER_FUNCTION_DATA, np.log10(obs_data))