Source code for openquake.hazardlib.gsim.derras_2014
# -*- coding: utf-8 -*-# vim: tabstop=4 shiftwidth=4 softtabstop=4## Copyright (C) 2013-2025 GEM Foundation## OpenQuake 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.## OpenQuake is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU Affero General Public License for more details.## You should have received a copy of the GNU Affero General Public License# along with OpenQuake. If not, see <http://www.gnu.org/licenses/>."""Module exports :class:`DerrasEtAl2014`"""importnumpyasnpfromscipy.constantsimportgfromopenquake.hazardlibimportconstfromopenquake.hazardlib.gsim.baseimportGMPE,CoeffsTablefromopenquake.hazardlib.imtimportPGA,PGV,SA# Constants used to normalise the input parametersCONSTANTS={"minMw":3.6,"maxMw":7.6,"logMinR":np.log10(0.1),"logMaxR":np.log10(547.0),"minD":0.0,"maxD":25.0,"logMinVs30":np.log10(92.0),"logMaxVs30":np.log10(1597.7),"minFM":1.0,"maxFM":4.0}
[docs]defrhypo_to_rjb(rhypo,mag):""" Converts hypocentral distance to an equivalent Joyner-Boore distance dependent on the magnitude """epsilon=rhypo-(4.853+1.347E-6*mag**8.163)rjb=np.zeros_like(rhypo)idx=epsilon>=3.rjb[idx]=np.sqrt((epsilon[idx]**2.)-9.0)rjb[rjb<0.0]=0.0returnrjb
def_get_normalised_term(pval,pmax,pmin):""" Normalisation of a variable between its minimum and maximum using: 2.0 * ((p - p_min) / (p_max - p_min)) - 1 N.B. This is given as 0.5 * (...) - 1 in the paper, but the Electronic Supplement implements it as 2.0 * (...) - 1 """return2.0*(pval-pmin)/(pmax-pmin)-1def_get_sof_dummy_variable(rake):""" Authors use a style of faulting dummy variable of 1 for normal faulting, 2 for reverse faulting and 3 for strike-slip """res=np.full_like(rake,4.0)# strike slipres[(rake>45.0)&(rake<135.0)]=3.0# reverseres[(rake<-45.)&(rake>-135.)]=1.0# normalreturnres
[docs]defget_pn(region,ctx,sof):""" Normalise the input parameters within their upper and lower defined range. :returns: an array of shape (N, 5) with rjb, magn, vs30, depth, sof """p_n=np.zeros((len(ctx),5))rjb=np.copy(ctx.rjb)ifregion=='germany':rjb[ctx.width<=1E-3]=rhypo_to_rjb(ctx.rhypo,ctx.mag)[ctx.width<=1E-3]rjb[rjb<0.1]=0.1# must be clipped at 0.1 kmp_n[:,0]=_get_normalised_term(np.log10(rjb),CONSTANTS["logMaxR"],CONSTANTS["logMinR"])p_n[:,1]=_get_normalised_term(ctx.mag,CONSTANTS["maxMw"],CONSTANTS["minMw"])p_n[:,2]=_get_normalised_term(np.log10(ctx.vs30),CONSTANTS["logMaxVs30"],CONSTANTS["logMinVs30"])p_n[:,3]=_get_normalised_term(ctx.hypo_depth,CONSTANTS["maxD"],CONSTANTS["minD"])p_n[:,4]=_get_normalised_term(sof,CONSTANTS["maxFM"],CONSTANTS["minFM"])returnp_n# must be clipped at 0.1 km
[docs]defget_mean(region,W_1,B_1,C,ctx):""" Returns the mean ground motion in terms of log10 m/s/s, implementing equation 2 (page 502) """w_2=np.array([C["W_21"],C["W_22"],C["W_23"],C["W_24"],C["W_25"]])p_n=get_pn(region,ctx,_get_sof_dummy_variable(ctx.rake))mean=np.zeros_like(ctx.rhypoifregion=="germany"elsectx.rjb)fori,p_n_iinenumerate(p_n):mean[i]=(w_2@np.tanh(W_1@p_n_i+B_1)+C["B_2"]+1.0)*(C["tmax"]-C["tmin"])/2+C["tmin"]returnmean
[docs]classDerrasEtAl2014(GMPE):""" Implements GMPE developed by: B. Derras, P. Y. Bard, F. Cotton (2014) "Toward fully data driven ground- motion prediction models for Europe", Bulletin of Earthquake Engineering 12, 495-516 The GMPE is derived from an artifical neural network approach, and therefore does not assume the form of source, path and site scaling that is conventionally adopted by GMPEs. Instead the influence of each variable is modelled via a hyperbolic tangent-sigmoid function which is then applied to the vector of normalised predictor variables. As a consequence the expected ground motion for each site is derived from a set of matrix products from the respective weighting and bias vectors. This means that vectorisation by ctx cannot be achieved and a loop is implemented instead. """region="base"#: The supported tectonic region type is active shallow crustDEFINED_FOR_TECTONIC_REGION_TYPE=const.TRT.ACTIVE_SHALLOW_CRUST#: The supported intensity measure types are PGA, PGV, and SADEFINED_FOR_INTENSITY_MEASURE_TYPES={PGA,PGV,SA}#: The supported intensity measure component is 'average horizontal',DEFINED_FOR_INTENSITY_MEASURE_COMPONENT=const.IMC.GEOMETRIC_MEAN#: The supported standard deviations are total, inter and intra eventDEFINED_FOR_STANDARD_DEVIATION_TYPES={const.StdDev.TOTAL,const.StdDev.INTER_EVENT,const.StdDev.INTRA_EVENT}#: The required site parameter is vs30REQUIRES_SITES_PARAMETERS={'vs30'}#: The required rupture parameters are rake and magnitudeREQUIRES_RUPTURE_PARAMETERS={'rake','mag','hypo_depth'}#: The required distance parameter is 'Joyner-Boore' distanceREQUIRES_DISTANCES={'rjb'}adjustment_factor=0.
[docs]defcompute(self,ctx:np.recarray,imts,mean,sig,tau,phi):""" See :meth:`superclass method <.base.GroundShakingIntensityModel.compute>` for spec of input and result values. """form,imtinenumerate(imts):C=self.COEFFS[imt]# Get the meanmean[m]=get_mean(self.region,self.W_1,self.B_1,C,ctx)ifimt.string=="PGV":# Convert from log10 m/s to ln cm/smean[m]=np.log(10.0**mean[m]*100.)else:# convert from log10 m/s/s to ln gmean[m]=np.log(10.0**mean[m]/g)mean[m]+=self.adjustment_factor# Get the standard deviations, originally given# in terms of log_10, so converting to log_et=C["tau"]p=C["phi"]sig[m]=np.log(10.0**np.sqrt(t**2+p**2))tau[m]=np.log(10.0**t),phi[m]=np.log(10.0**p)
[docs]classDerrasEtAl2014RhypoGermany(DerrasEtAl2014):""" Re-calibration of the Derras et al. (2014) GMPE taking hypocentral distance as an input and converting to Rjb """region="germany"#: The required distance parameter is hypocentral distanceREQUIRES_DISTANCES={'rjb','rhypo'}REQUIRES_RUPTURE_PARAMETERS={"rake","mag","hypo_depth","width"}def__init__(self,adjustment_factor=1.0):self.adjustment_factor=np.log(adjustment_factor)