Source code for openquake.hmtk.faults.mfd.youngs_coppersmith

# -*- coding: utf-8 -*-
# vim: tabstop=4 shiftwidth=4 softtabstop=4

#
# LICENSE
#
# Copyright (C) 2010-2023 GEM Foundation, G. Weatherill, M. Pagani,
# D. Monelli.
#
# The Hazard Modeller's Toolkit 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.
#
# You should have received a copy of the GNU Affero General Public License
# along with OpenQuake. If not, see <http://www.gnu.org/licenses/>
#
# DISCLAIMER
#
# The software Hazard Modeller's Toolkit (openquake.hmtk) provided herein
# is released as a prototype implementation on behalf of
# scientists and engineers working within the GEM Foundation (Global
# Earthquake Model).
#
# It is distributed for the purpose of open collaboration and in the
# hope that it will be useful to the scientific, engineering, disaster
# risk and software design communities.
#
# The software is NOT distributed as part of GEM's OpenQuake suite
# (https://www.globalquakemodel.org/tools-products) and must be considered as a
# separate entity. The software provided herein is designed and implemented
# by scientific staff. It is not developed to the design standards, nor
# subject to same level of critical review by professional software
# developers, as GEM's OpenQuake software suite.
#
# Feedback and contribution to the software is welcome, and can be
# directed to the hazard scientific staff of the GEM Model Facility
# (hazard@globalquakemodel.org).
#
# The Hazard Modeller's Toolkit (openquake.hmtk) is therefore distributed WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# The GEM Foundation, and the authors of the software, assume no
# liability for use of the software.


"""
Module :mod: openquake.hmtk.faults.mfd.youngs_coppersmith implements class
YoungsCoppersmithExponential and YoungsCoppersmithCharacteristic, the
exponential and characteristic forms of the Youngs & Coppersmith (1985)
models for calculating earthquake recurrence from slip rate

Youngs, R. R., and Coppersmith, K., J. (1985) "Implications of Fault Slip Rates
and Earthquake Recurrence Models to Probabilistic Seismic Hazard Estimates"
Bull. Seis. Soc. Am. 75(4) 939 - 964

"""

import numpy as np
from math import exp, log
from openquake.hmtk.faults.mfd.base import _scale_moment, BaseMFDfromSlip
from openquake.hazardlib.mfd.youngs_coppersmith_1985 import \
    YoungsCoppersmith1985MFD
C_VALUE = 16.05
D_VALUE = 1.5


[docs]class YoungsCoppersmithExponential(BaseMFDfromSlip): ''' Calculates the activity rate on a fault with a given slip assuming the exponential model described in Youngs & Coppersmith (1985) Eq. 11 :param str mfd_model: Type of magnitude frequency distribution :param float mfd_weight: Weight of the mfd distribution (for subsequent logic tree processing) :param float bin_width: Width of the magnitude bin (rates are given for the centre point) :param float mmin: Minimum magnitude :param float mmax: Maximum magnitude :param float mmax_sigma: Uncertainty on maximum magnitude :param float b_value: Exponent (b-value) for the magnitude frequency distribution :param float b_value_sigma: Uncertainty on exponent (b-value) for the magnitude frequency distribution :param numpy.ndarray occurrence_rate: Activity rates for magnitude in the range mmin to mmax in steps of bin_width '''
[docs] def setUp(self, mfd_conf): ''' Input core configuration parameters as specified in the configuration file :param dict mfd_conf: Configuration file containing the following attributes: * 'Model_Weight' - Logic tree weight of model type (float) * 'MFD_spacing' - Width of MFD bin (float) * 'Minimum_Magnitude' - Minimum magnitude of activity rates (float) * 'b_value' - Tuple of (b-value, b-value uncertainty) * 'Maximum_Magnitude' - Maximum magnitude on fault (if not defined will use scaling relation) * 'Maximum_Magnitude_Uncertainty' - Uncertainty on maximum magnitude (If not defined and the MSR has a sigma term then this will be taken from sigma) ''' self.mfd_model = 'Youngs & Coppersmith Exponential' self.mfd_weight = mfd_conf['Model_Weight'] self.bin_width = mfd_conf['MFD_spacing'] self.mmin = mfd_conf['Minimum_Magnitude'] self.mmax = None self.mmax_sigma = None self.b_value = mfd_conf['b_value'][0] self.b_value_sigma = mfd_conf['b_value'][1] self.occurrence_rate = None
[docs] def get_mmax(self, mfd_conf, msr, rake, area): ''' Gets the mmax for the fault - reading directly from the config file or using the msr otherwise :param dict mfd_config: Configuration file (see setUp for parameters) :param msr: Instance of :class: nhlib.scalerel :param float rake: Rake of the fault (in range -180 to 180) :param float area: Area of the fault surface (km^2) ''' if mfd_conf['Maximum_Magnitude']: self.mmax = mfd_conf['Maximum_Magnitude'] else: self.mmax = msr.get_median_mag(area, rake) self.mmax_sigma = (mfd_conf.get('Maximum_Magnitude_Uncertainty', None) or msr.get_std_dev_mag(None, rake))
[docs] def get_mfd(self, slip, area, shear_modulus=30.0): ''' Calculates activity rate on the fault :param float slip: Slip rate in mm/yr :param area: Width of the fault (km) :param float shear_modulus: Shear modulus of the fault (GPa) :returns: * Minimum Magnitude (float) * Bin width (float) * Occurrence Rates (numpy.ndarray) ''' # Working in Nm so convert: shear_modulus - GPa -> Nm # area - km ** 2. -> m ** 2. # slip - mm/yr -> m/yr moment_rate = (shear_modulus * 1.E9) * (area * 1.E6) * (slip / 1000.) moment_mag = _scale_moment(self.mmax, in_nm=True) beta = self.b_value * log(10.) mag = np.arange(self.mmin - (self.bin_width / 2.), self.mmax + self.bin_width, self.bin_width) if self.b_value > 1.5: print('b-value larger than 1.5 will produce invalid results in ' 'Anderson & Luco models') self.occurrence_rate = np.nan * np.ones(len(mag) - 1) return self.mmin, self.bin_width, self.occurrence_rate self.occurrence_rate = np.zeros(len(mag) - 1, dtype=float) for ival in range(0, len(mag) - 1): self.occurrence_rate[ival] = ( self.cumulative_value(mag[ival], moment_rate, beta, moment_mag) - self.cumulative_value( mag[ival + 1], moment_rate, beta, moment_mag)) return self.mmin, self.bin_width, self.occurrence_rate
[docs] def cumulative_value(self, mag_val, moment_rate, beta, moment_mag): ''' Calculates the cumulative rate of events with M > m0 using equation 11 of Youngs & Coppersmith (1985) :param float mag_val: Magnitude :param float moment_rate: Moment rate on fault (in Nm) from slip rate :param float beta: Exponent (b log(10) :param float moment_mag: Moment of the upper bound magnitude ''' exponent = exp(-beta * (self.mmax - mag_val)) return (moment_rate * (D_VALUE - self.b_value) * (1. - exponent)) /\ (self.b_value * moment_mag * exponent)
[docs]class YoungsCoppersmithCharacteristic(BaseMFDfromSlip): ''' Calculates the activity rate on a fault with a given slip assuming the characteristic model described in Youngs & Coppersmith (1985) Eqs. 16 and 17 :param str mfd_type: Type of magnitude frequency distribution :param float mfd_weight: Weight of the mfd distribution (for subsequent logic tree processing) :param float bin_width: Width of the magnitude bin (rates are given for the centre point) :param float mmin: Minimum magnitude :param float mmax: Maximum magnitude :param float mmax_sigma: Uncertainty on maximum magnitude :param float b_value: Exponent (b-value) for the exponential magnitude frequency distribution :param float b_value_sigma: Uncertainty on exponent (b-value) for the magnitude frequency distribution :param numpy.ndarray occurrence_rate: Activity rates for magnitude in the range mmin to mmax in steps of bin_width :param model: Maintains present instance of :class: YoungsCoppersmith1985MFD '''
[docs] def setUp(self, mfd_conf): ''' Input core configuration parameters as specified in the configuration file :param dict mfd_conf: Configuration file containing the following attributes: * 'Model_Weight' - Logic tree weight of model type (float) * 'MFD_spacing' - Width of MFD bin (float) * 'Minimum_Magnitude' - Minimum magnitude of activity rates (float) * 'b_value' - Tuple of (b-value, b-value uncertainty) * 'Maximum_Magnitude' - Characteristic magnitude on fault (if not defined, will use scaling relation) * 'Maximum_Magnitude_Uncertainty' - Uncertainty on maximum magnitude (If not defined and the MSR has a sigma term then this will be taken from sigma) ''' self.mfd_type = 'Youngs & Coppersmith (1985) Characteristic' self.mfd_weight = mfd_conf['Model_Weight'] self.bin_width = mfd_conf['MFD_spacing'] self.mmin = mfd_conf['Minimum_Magnitude'] self.mmax = None self.mmax_sigma = None self.b_value = mfd_conf['b_value'][0] self.b_value_sigma = mfd_conf['b_value'][1] self.occurrence_rate = None self.model = None
[docs] def get_mmax(self, mfd_conf, msr, rake, area): ''' Gets the mmax for the fault - reading directly from the config file or using the msr otherwise :param dict mfd_config: Configuration file (see setUp for paramters) :param msr: Instance of :class: nhlib.scalerel :param float rake: Rake of the fault (in range -180 to 180) :param float area: Area of the fault surface (km^2) ''' if mfd_conf['Maximum_Magnitude']: self.mmax = mfd_conf['Maximum_Magnitude'] else: self.mmax = msr.get_median_mag(area, rake) self.mmax_sigma = (mfd_conf.get('Maximum_Magnitude_Uncertainty', None) or msr.get_std_dev_mag(None, rake))
[docs] def get_mfd(self, slip, area, shear_modulus=30.0): ''' Calculates activity rate on the fault :param float slip: Slip rate in mm/yr :param area: Area of the fault (km) :param float shear_modulus: Shear modulus of the fault (GPa) :returns: * Minimum Magnitude (float) * Bin width (float) * Occurrence Rates (numpy.ndarray) Behavioural Notes: To use the openquake.hazardlib implementation the magnitudes returned will be the mid_point of the bins and not the original edge points. The minimum magnitude is update to reflect this! ''' # Calculate moment rate in N-m / year moment_rate = (shear_modulus * 1.E9) * (area * 1.E6) * (slip / 1000.) # Get Youngs & Coppersmith rate from # youngs_coppersmith.YoungsCoppersmith1985MFD.from_total_moment_rate self.model = YoungsCoppersmith1985MFD.from_total_moment_rate( self.mmin - (self.bin_width / 2.), self.b_value, self.mmax - 0.25, moment_rate, self.bin_width) temp_data = self.model.get_annual_occurrence_rates() self.occurrence_rate = np.array([value[1] for value in temp_data]) self.mmin = np.min(np.array([value[0] for value in temp_data])) return self.mmin, self.bin_width, self.occurrence_rate