Source code for openquake.hazardlib.gsim.abrahamson_silva_2008
# -*- coding: utf-8 -*-# vim: tabstop=4 shiftwidth=4 softtabstop=4## Copyright (C) 2012-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:`AbrahamsonSilva2008`."""importnumpyasnpfromopenquake.hazardlib.gsim.baseimportGMPE,CoeffsTablefromopenquake.hazardlibimportconstfromopenquake.hazardlib.imtimportPGA,PGV,SA#: equation constants (that are IMT independent)#: coefficients in table 4, page 84CONSTS={'c1':6.75,'c4':4.5,'a3':0.265,'a4':-0.231,'a5':-0.398,'n':1.18,'c':1.88,'c2':50,'sigma_amp':0.3}def_compute_base_term(C,ctx):""" Compute and return base model term, that is the first term in equation 1, page 74. The calculation of this term is explained in paragraph 'Base Model', page 75. """c1=CONSTS['c1']R=np.sqrt(ctx.rrup**2+CONSTS['c4']**2)base_term=(C['a1']+C['a8']*((8.5-ctx.mag)**2)+(C['a2']+CONSTS['a3']*(ctx.mag-c1))*np.log(R))extra_term=np.where(ctx.mag<=c1,CONSTS['a4']*(ctx.mag-c1),CONSTS['a5']*(ctx.mag-c1))returnbase_term+extra_termdef_compute_faulting_style_term(C,ctx):""" Compute and return faulting style term, that is the sum of the second and third terms in equation 1, page 74. """# ranges of rake values for each faulting mechanism are specified in# table 2, page 75return(C['a12']*((ctx.rake>30)&(ctx.rake<150))+C['a13']*((ctx.rake>-120)&(ctx.rake<-60)))def_compute_site_response_term(C,imt,ctx,pga1100):""" Compute and return site response model term, that is the fifth term in equation 1, page 74. """site_resp_term=np.zeros_like(ctx.vs30)vs30_star,_=_compute_vs30_star_factor(imt,ctx.vs30)vlin,c,n=C['VLIN'],CONSTS['c'],CONSTS['n']a10,b=C['a10'],C['b']idx=ctx.vs30<vlinarg=vs30_star[idx]/vlinsite_resp_term[idx]=(a10*np.log(arg)-b*np.log(pga1100[idx]+c)+b*np.log(pga1100[idx]+c*(arg**n)))idx=ctx.vs30>=vlinsite_resp_term[idx]=(a10+b*n)*np.log(vs30_star[idx]/vlin)returnsite_resp_termdef_compute_hanging_wall_term(C,ctx):""" Compute and return hanging wall model term, that is the sixth term in equation 1, page 74. The calculation of this term is explained in paragraph 'Hanging-Wall Model', page 77. """idx=(ctx.rx>0)&(ctx.dip!=90.0)Fhw=np.zeros_like(ctx.rx)Fhw[idx]=1# equation 8, page 77T1=np.zeros_like(ctx.rx)idx1=(ctx.rjb<30.0)&idxT1[idx1]=1.0-ctx.rjb[idx1]/30.0# equation 9, page 77T2=np.ones_like(ctx.rx)idx2=(ctx.rx<=ctx.width*np.cos(np.radians(ctx.dip)))&idxT2[idx2]=0.5+ctx.rx[idx2]/(2*ctx.width[idx2]*np.cos(np.radians(ctx.dip[idx2])))# equation 10, page 78T3=np.ones_like(ctx.rx)idx3=(ctx.rx<ctx.ztor)&idxT3[idx3]=ctx.rx[idx3]/ctx.ztor[idx3]# equation 11, page 78T4=ctx.mag-6T4[ctx.mag<=6.]=0.T4[ctx.mag>=7.]=1.0# equation 5, in AS08_NGA_errata.pdfT5=np.where(ctx.dip>=30,1.0-(ctx.dip-30.0)/60.0,1.0)returnFhw*C['a14']*T1*T2*T3*T4*T5def_compute_top_of_rupture_depth_term(C,ctx):""" Compute and return top of rupture depth term, that is the seventh term in equation 1, page 74. The calculation of this term is explained in paragraph 'Depth-to-Top of Rupture Model', page 78. """returnnp.where(ctx.ztor>=10,C['a16'],C['a16']*ctx.ztor/10.0)def_compute_large_distance_term(C,ctx):""" Compute and return large distance model term, that is the 8-th term in equation 1, page 74. The calculation of this term is explained in paragraph 'Large Distance Model', page 78. """# equation 15, page 79T6=0.5*(6.5-ctx.mag)+0.5T6[ctx.mag<5.5]=1.0T6[ctx.mag>=6.5]=0.5# equation 14, page 79large_distance_term=np.zeros_like(ctx.rrup)idx=ctx.rrup>=100.0large_distance_term[idx]=C['a18']*(ctx.rrup[idx]-100.0)*T6[idx]returnlarge_distance_termdef_get_basin_term(C,ctx,region,imt,v1100=None):""" Compute and return soil depth model term, that is the 9-th term in equation 1, page 74. The calculation of this term is explained in paragraph 'Soil Depth Model', page 79. """ifv1100isNone:vs30=ctx.vs30else:vs30=v1100a21=_compute_a21_factor(C,imt,ctx.z1pt0,vs30)a22=_compute_a22_factor(imt)median_z1pt0=_compute_median_z1pt0(vs30)soil_depth_term=a21*np.log((ctx.z1pt0+CONSTS['c2'])/(median_z1pt0+CONSTS['c2']))idx=ctx.z1pt0>=200soil_depth_term[idx]+=a22*np.log(ctx.z1pt0[idx]/200)returnsoil_depth_termdef_compute_imt1100(C_PGA,ctx):""" Compute and return mean imt value for rock conditions (vs30 = 1100 m/s) """imt=PGA()vs30_1100=np.zeros_like(ctx.vs30)+1100vs30_star,_=_compute_vs30_star_factor(imt,vs30_1100)mean=(_compute_base_term(C_PGA,ctx)+_compute_faulting_style_term(C_PGA,ctx)+_compute_hanging_wall_term(C_PGA,ctx)+_compute_top_of_rupture_depth_term(C_PGA,ctx)+_compute_large_distance_term(C_PGA,ctx)+_get_basin_term(C_PGA,ctx,None,imt,vs30_1100)+# this is the site response term in case of vs30=1100((C_PGA['a10']+C_PGA['b']*CONSTS['n'])*np.log(vs30_star/C_PGA['VLIN'])))returnmeandef_get_stddevs(C,C_PGA,pga1100,ctx):""" Return standard deviations as described in paragraph 'Equations for standard deviation', page 81. """std_intra=_compute_intra_event_std(C,C_PGA,pga1100,ctx.mag,ctx.vs30,ctx.vs30measured)std_inter=_compute_inter_event_std(C,C_PGA,pga1100,ctx.mag,ctx.vs30)return[np.sqrt(std_intra**2+std_inter**2),std_inter,std_intra]def_compute_intra_event_std(C,C_PGA,pga1100,mag,vs30,vs30measured):""" Compute intra event standard deviation (equation 24) as described in the errata and not in the original paper. """sigma_b=_compute_sigma_b(C,mag,vs30measured)sigma_b_pga=_compute_sigma_b(C_PGA,mag,vs30measured)delta_amp=_compute_partial_derivative_site_amp(C,pga1100,vs30)std_intra=np.sqrt(sigma_b**2+CONSTS['sigma_amp']**2+(delta_amp**2)*(sigma_b_pga**2)+2*delta_amp*sigma_b*sigma_b_pga*C['rho'])returnstd_intradef_compute_inter_event_std(C,C_PGA,pga1100,mag,vs30):""" Compute inter event standard deviation, equation 25, page 82. """tau_0=_compute_std_0(C['s3'],C['s4'],mag)tau_b_pga=_compute_std_0(C_PGA['s3'],C_PGA['s4'],mag)delta_amp=_compute_partial_derivative_site_amp(C,pga1100,vs30)std_inter=np.sqrt(tau_0**2+(delta_amp**2)*(tau_b_pga**2)+2*delta_amp*tau_0*tau_b_pga*C['rho'])returnstd_interdef_compute_sigma_b(C,mag,vs30measured):""" Equation 23, page 81. """sigma_0=_compute_sigma_0(C,mag,vs30measured)sigma_amp=CONSTS['sigma_amp']returnnp.sqrt(sigma_0**2-sigma_amp**2)def_compute_sigma_0(C,mag,vs30measured):""" Equation 27, page 82. """s1=np.zeros_like(vs30measured,dtype=float)s2=np.zeros_like(vs30measured,dtype=float)idx=vs30measured==1s1[idx]=C['s1mea']s2[idx]=C['s2mea']idx=vs30measured==0s1[idx]=C['s1est']s2[idx]=C['s2est']return_compute_std_0(s1,s2,mag)def_compute_std_0(c1,c2,mag):""" Common part of equations 27 and 28, pag 82. """res=c1+(c2-c1)*(mag-5)/2res[mag<5]=c1[mag<5]ifisinstance(c1,np.ndarray)elsec1res[mag>7]=c2[mag>7]ifisinstance(c2,np.ndarray)elsec2returnresdef_compute_partial_derivative_site_amp(C,pga1100,vs30):""" Partial derivative of site amplification term with respect to PGA on rock (equation 26), as described in the errata and not in the original paper. """delta_amp=np.zeros_like(vs30)vlin=C['VLIN']c=CONSTS['c']b=C['b']n=CONSTS['n']idx=vs30<vlindelta_amp[idx]=(-b*pga1100[idx]/(pga1100[idx]+c)+b*pga1100[idx]/(pga1100[idx]+c*((vs30[idx]/vlin)**n)))returndelta_ampdef_compute_a21_factor(C,imt,z1pt0,vs30):""" Compute and return a21 factor, equation 18, page 80. """e2=_compute_e2_factor(imt,vs30)a21=e2.copy()vs30_star,v1=_compute_vs30_star_factor(imt,vs30)median_z1pt0=_compute_median_z1pt0(vs30)numerator=((C['a10']+C['b']*CONSTS['n'])*np.log(vs30_star/np.min([v1,1000])))denominator=np.log((z1pt0+CONSTS['c2'])/(median_z1pt0+CONSTS['c2']))idx=numerator+e2*denominator<0a21[idx]=-numerator[idx]/denominator[idx]idx=vs30>=1000a21[idx]=0.0returna21def_compute_vs30_star_factor(imt,vs30):""" Compute and return vs30 star factor, equation 5, page 77. """v1=_compute_v1_factor(imt)vs30_star=vs30.copy()vs30_star[vs30_star>=v1]=v1returnvs30_star,v1def_compute_v1_factor(imt):""" Compute and return v1 factor, equation 6, page 77. """ifimt.string[:2]=="SA":t=imt.periodift<=0.50:v1=1500.0elift>0.50andt<=1.0:v1=np.exp(8.0-0.795*np.log(t/0.21))elift>1.0andt<2.0:v1=np.exp(6.76-0.297*np.log(t))else:v1=700.0elifimt.string=="PGA":v1=1500.0else:# this is for PGVv1=862.0returnv1def_compute_e2_factor(imt,vs30):""" Compute and return e2 factor, equation 19, page 80. """e2=np.zeros_like(vs30)ifimt.string=="PGV":period=1elifimt.string=="PGA":period=0else:period=imt.periodifperiod<0.35:returne2else:idx=vs30<=1000ifperiod>=0.35andperiod<=2.0:e2[idx]=(-0.25*np.log(vs30[idx]/1000)*np.log(period/0.35))elifperiod>2.0:e2[idx]=(-0.25*np.log(vs30[idx]/1000)*np.log(2.0/0.35))returne2def_compute_median_z1pt0(vs30):""" Compute and return median z1pt0 (in m), equation 17, pqge 79. """z1pt0_median=np.zeros_like(vs30)+6.745idx=np.where((vs30>=180.0)&(vs30<=500.0))z1pt0_median[idx]=6.745-1.35*np.log(vs30[idx]/180.0)idx=vs30>500.0z1pt0_median[idx]=5.394-4.48*np.log(vs30[idx]/500.0)returnnp.exp(z1pt0_median)def_compute_a22_factor(imt):""" Compute and return the a22 factor, equation 20, page 80. """ifimt.string=='PGV':return0.0period=imt.periodifperiod<2.0:return0.0else:return0.0625*(period-2.0)
[docs]classAbrahamsonSilva2008(GMPE):""" Implements GMPE developed by Norman Abrahamson and Walter Silva and published as "Summary of the Abrahamson & Silva NGA Ground-Motion Relations" (2008, Earthquakes Spectra, Volume 24, Number 1, pages 67-97). This class implements only the equations for mainshock/foreshocks/swarms type events, that is the aftershock term (4th term in equation 1, page 74) is set to zero. The constant displacement model (page 80) is also not implemented (that is equation 1, page 74 is used for all periods and no correction is applied for periods greater than the constant displacement period). This class implements also the corrections (for standard deviation and hanging wall term calculation) as described in: http://peer.berkeley.edu/products/abrahamson-silva_nga_report_files/ AS08_NGA_errata.pdf """#: Supported tectonic region type is active shallow crust, see paragraph#: 'Data Set Selection', see page 68.DEFINED_FOR_TECTONIC_REGION_TYPE=const.TRT.ACTIVE_SHALLOW_CRUST#: Supported intensity measure types are spectral acceleration, peak#: ground velocity and peak ground acceleration, see tables 5a and 5b#: pages 84, 85, respectively.DEFINED_FOR_INTENSITY_MEASURE_TYPES={PGA,PGV,SA}#: Supported intensity measure component is orientation-independent#: average horizontal :attr:`~openquake.hazardlib.const.IMC.GMRotI50`,#: see abstract, page 67.DEFINED_FOR_INTENSITY_MEASURE_COMPONENT=const.IMC.GMRotI50#: Supported standard deviation types are inter-event, intra-event#: and total, see paragraph "Equations for standard deviations", page 81.DEFINED_FOR_STANDARD_DEVIATION_TYPES={const.StdDev.TOTAL,const.StdDev.INTER_EVENT,const.StdDev.INTRA_EVENT}#: Required site parameters are Vs30, Vs30 type (measured or inferred),#: and Z1.0, see paragraph 'Soil Depth Model', page 79, and table 6,#: page 86.REQUIRES_SITES_PARAMETERS={'vs30','vs30measured','z1pt0'}#: Required rupture parameters are magnitude, rake, dip, ztor, and width#: (see table 2, page 75)REQUIRES_RUPTURE_PARAMETERS={'mag','rake','dip','ztor','width'}#: Required distance measures are Rrup, Rjb and Rx (see Table 2, page 75).REQUIRES_DISTANCES={'rrup','rjb','rx'}
[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. """C_PGA=self.COEFFS[PGA()]# compute median pga on rock (vs30=1100), needed for site response# term calculationpga1100=np.exp(_compute_imt1100(C_PGA,ctx))form,imtinenumerate(imts):C=self.COEFFS[imt]mean[m]=(_compute_base_term(C,ctx)+_compute_faulting_style_term(C,ctx)+_compute_site_response_term(C,imt,ctx,pga1100)+_compute_hanging_wall_term(C,ctx)+_compute_top_of_rupture_depth_term(C,ctx)+_compute_large_distance_term(C,ctx)+_get_basin_term(C,ctx,None,imt))sig[m],tau[m],phi[m]=_get_stddevs(C,C_PGA,pga1100,ctx)