Skip to content

Commit c0dd1e2

Browse files
committed
Added teleseismic modeling to fakequakes
1 parent ffa28c7 commit c0dd1e2

8 files changed

Lines changed: 469 additions & 18 deletions

File tree

src/python/mudpy/fakequakes.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,8 @@ def get_rise_times(M0,slip,fault_array,rise_time_depths,stoc_rake,rise_time_std=
800800

801801
def get_rupture_onset(home,project_name,slip,fault_array,model_name,hypocenter,
802802
rise_time_depths,M0,velmod,sigma_rise_time=0.2,shear_wave_fraction_shallow=0.49,shear_wave_fraction_deep=0.8):
803+
804+
home,project_name,slip,fault_array,model_name,hypocenter,rise_time_depths,M0,velmod,shear_wave_fraction_shallow,shear_wave_fraction_deep
803805
'''
804806
Using a custom built tvel file ray trace from hypocenter to determine rupture
805807
onset times
@@ -834,6 +836,7 @@ def get_rupture_onset(home,project_name,slip,fault_array,model_name,hypocenter,
834836
# rupture_multiplier[i]=slope*depth_to_top[i]+intercept
835837

836838

839+
837840
#Get rupture speed shear-wave multipliers
838841
rupture_multiplier=zeros(len(vel))
839842
# Shallow
@@ -849,7 +852,6 @@ def get_rupture_onset(home,project_name,slip,fault_array,model_name,hypocenter,
849852
rupture_multiplier[i]=slope*depth_to_top[i]+intercept
850853

851854

852-
853855
#Perturb depths of the hypocenter so that faults at the same depth are not zero onset
854856
delta=0.00001
855857
i_same_as_hypo=where(fault_array[:,3]==hypocenter[2])[0]

src/python/mudpy/forward.py

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,57 @@ def waveforms_fakequakes(home,project_name,fault_name,rupture_list,GF_list,
324324
#Write output
325325
write_fakequakes_waveforms(home,project_name,rupture_name,waveforms,GF_list,NFFT,time_epi,dt)
326326

327+
328+
329+
330+
def tele_waveforms(home,project_name,fault_name,rupture_list,GF_list_teleseismic,
331+
model_name,run_name,G_from_file,G_name,source_time_function='dreger',zeta=0.2,
332+
stf_falloff_rate=4.0,rupture_name=None,epicenter=None,time_epi=None,
333+
hot_start=0,decimation_factor=1):
334+
'''
335+
336+
'''
337+
from numpy import genfromtxt,array
338+
import datetime
339+
340+
print('Solving for kinematic problem(s)')
341+
#Time for log file
342+
now=datetime.datetime.now()
343+
now=now.strftime('%b-%d-%H%M')
344+
345+
#load source names
346+
if rupture_list==None:
347+
all_sources=array([rupture_name])
348+
else:
349+
all_sources=genfromtxt(home+project_name+'/data/'+rupture_list,dtype='U')
350+
351+
#Load all synthetics
352+
print('... loading all synthetics into memory')
353+
Nss,Ess,Zss,Nds,Eds,Zds=load_fakequakes_tele_synthetics(home,project_name,fault_name,model_name,GF_list_teleseismic,G_from_file,G_name,decimation_factor)
354+
print('... ... done')
355+
356+
Npoints=Nss[0].stats.npts
357+
dt=Nss[0].stats.delta
358+
#Now loop over rupture models
359+
for ksource in range(hot_start,len(all_sources)):
360+
print('... solving for source '+str(ksource)+' of '+str(len(all_sources)))
361+
rupture_name=all_sources[ksource]
362+
print(rupture_name)
363+
364+
if rupture_list!=None:
365+
#Get epicentral time
366+
epicenter,time_epi=read_fakequakes_hypo_time(home,project_name,rupture_name)
367+
forward=False
368+
else:
369+
forward=True #This controls where we look for the rupture file
370+
371+
# Put in matrix
372+
m,G=get_fakequakes_G_and_m(Nss,Ess,Zss,Nds,Eds,Zds,home,project_name,rupture_name,time_epi,GF_list_teleseismic,epicenter,Npoints,source_time_function,stf_falloff_rate,zeta,forward=forward)
373+
# Solve
374+
waveforms=G.dot(m)
375+
#Write output
376+
write_fakequakes_waveforms(home,project_name,rupture_name,waveforms,GF_list_teleseismic,Npoints,time_epi,dt)
377+
327378

328379

329380
def waveforms_fakequakes_dynGF(home,project_name,fault_name,rupture_list,GF_list,dynamic_GFlist,dist_threshold,
@@ -880,6 +931,115 @@ def load_fakequakes_synthetics(home,project_name,fault_name,model_name,GF_list,G
880931

881932

882933

934+
def load_fakequakes_tele_synthetics(home,project_name,fault_name,model_name,GF_list_teleseismic,G_from_file,G_name,decimation_factor):
935+
''''
936+
Load the miniseed files with all the synthetics
937+
'''
938+
from numpy import genfromtxt,loadtxt
939+
from obspy import read,Stream
940+
941+
if G_from_file==True: #load from file
942+
Eds=read(home+project_name+'/GFs/matrices/'+G_name+'.Eds.tele.mseed')
943+
Nds=read(home+project_name+'/GFs/matrices/'+G_name+'.Nds.tele.mseed')
944+
Zds=read(home+project_name+'/GFs/matrices/'+G_name+'.Zds.tele.mseed')
945+
Ess=read(home+project_name+'/GFs/matrices/'+G_name+'.Ess.tele.mseed')
946+
Nss=read(home+project_name+'/GFs/matrices/'+G_name+'.Nss.tele.mseed')
947+
Zss=read(home+project_name+'/GFs/matrices/'+G_name+'.Zss.tele.mseed')
948+
else: #assemble G one data type at a time, just displacememnt right now
949+
#Load station info
950+
station_file=home+project_name+'/data/station_info/'+GF_list_teleseismic
951+
staname=genfromtxt(station_file,dtype="U",usecols=0)
952+
Nsta=len(staname)
953+
#Load fault model
954+
source=loadtxt(home+project_name+'/data/model_info/'+fault_name,ndmin=2)
955+
Nfaults=source.shape[0] #Number of subfaults
956+
kindex=0
957+
958+
for ksta in range(Nsta):
959+
960+
print('Reading green functions for station #'+str(ksta+1)+' of '+str(Nsta))
961+
962+
for kfault in range(Nfaults):
963+
964+
#Get subfault GF directory
965+
nsub='sub'+str(int(source[kfault,0])).rjust(4,'0')
966+
nfault='subfault'+str(int(source[kfault,0])).rjust(4,'0')
967+
strdepth='%.4f' % source[kfault,3]
968+
syn_path=home+project_name+'/GFs/dynamic/'+model_name+'_'+strdepth+'.'+nsub+'/'
969+
970+
#Get synthetics
971+
if kfault==0 and ksta==0: #It's the first one, initalize stream object
972+
SS=read(syn_path+staname[ksta]+'.'+nfault+'.SS.mseed')
973+
DS=read(syn_path+staname[ksta]+'.'+nfault+'.DS.mseed')
974+
975+
for trace in SS:
976+
977+
if decimation_factor >1:
978+
trace.decimate(factor=decimation_factor)
979+
980+
981+
if trace.stats.channel=='BXE':
982+
Ess=Stream(trace)
983+
if trace.stats.channel=='BXN':
984+
Nss=Stream(trace)
985+
if trace.stats.channel=='BXZ':
986+
Zss=Stream(trace)
987+
988+
for trace in DS:
989+
990+
if decimation_factor >1:
991+
trace.decimate(factor=decimation_factor)
992+
993+
if trace.stats.channel=='BXE':
994+
Eds=Stream(trace)
995+
if trace.stats.channel=='BXN':
996+
Nds=Stream(trace)
997+
if trace.stats.channel=='BXZ':
998+
Zds=Stream(trace)
999+
1000+
1001+
else: #Just add to stream object
1002+
1003+
SS=read(syn_path+staname[ksta]+'.'+nfault+'.SS.mseed')
1004+
DS=read(syn_path+staname[ksta]+'.'+nfault+'.DS.mseed')
1005+
1006+
for trace in SS:
1007+
1008+
if decimation_factor >1:
1009+
trace.decimate(factor=decimation_factor)
1010+
1011+
if trace.stats.channel=='BXE':
1012+
Ess+=trace
1013+
if trace.stats.channel=='BXN':
1014+
Nss+=trace
1015+
if trace.stats.channel=='BXZ':
1016+
Zss+=trace
1017+
1018+
for trace in DS:
1019+
1020+
if decimation_factor >1:
1021+
trace.decimate(factor=decimation_factor)
1022+
1023+
if trace.stats.channel=='BXE':
1024+
Eds+=trace
1025+
if trace.stats.channel=='BXN':
1026+
Nds+=trace
1027+
if trace.stats.channel=='BXZ':
1028+
Zds+=trace
1029+
kindex+=1
1030+
print('Writting synthetics to miniSEED, hang on this might take a minute or two.')
1031+
Ess.write(home+project_name+'/GFs/matrices/'+G_name+'.Ess.tele.mseed',format='MSEED')
1032+
Nss.write(home+project_name+'/GFs/matrices/'+G_name+'.Nss.tele.mseed',format='MSEED')
1033+
Zss.write(home+project_name+'/GFs/matrices/'+G_name+'.Zss.tele.mseed',format='MSEED')
1034+
Eds.write(home+project_name+'/GFs/matrices/'+G_name+'.Eds.tele.mseed',format='MSEED')
1035+
Nds.write(home+project_name+'/GFs/matrices/'+G_name+'.Nds.tele.mseed',format='MSEED')
1036+
Zds.write(home+project_name+'/GFs/matrices/'+G_name+'.Zds.tele.mseed',format='MSEED')
1037+
return Nss,Ess,Zss,Nds,Eds,Zds
1038+
1039+
1040+
1041+
1042+
8831043
def get_fakequakes_G_and_m(Nss,Ess,Zss,Nds,Eds,Zds,home,project_name,rupture_name,time_epi,GF_list,epicenter,NFFT,
8841044
source_time_function,stf_falloff_rate,zeta=0.2,forward=False):
8851045
'''
@@ -938,6 +1098,9 @@ def get_fakequakes_G_and_m(Nss,Ess,Zss,Nds,Eds,Zds,home,project_name,rupture_nam
9381098

9391099
for ksource in range(len(i_non_zero)):
9401100

1101+
if ksource % 50 == 0:
1102+
print('... ... ... subfault %d of %d' % (ksource,len(i_non_zero)))
1103+
9411104
#Get synthetics
9421105
nss=Nss[read_start+i_non_zero[ksource]].copy()
9431106
ess=Ess[read_start+i_non_zero[ksource]].copy()

src/python/mudpy/generate_ruptures_parallel.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,9 @@ def run_parallel_generate_ruptures(home,project_name,run_name,fault_name,slab_na
226226
else:
227227
hypocenter=whole_fault[shypo,1:4]
228228

229-
t_onset=fakequakes.get_rupture_onset(home,project_name,slip,fault_array,model_name,hypocenter,rise_time_depths,M0,velmod,shear_wave_fraction_shallow,shear_wave_fraction_deep)
229+
t_onset=fakequakes.get_rupture_onset(home,project_name,slip,fault_array,model_name,hypocenter,rise_time_depths,
230+
M0,velmod,shear_wave_fraction_shallow=shear_wave_fraction_shallow,
231+
shear_wave_fraction_deep=shear_wave_fraction_deep)
230232
fault_out[:,12]=0
231233
fault_out[ifaults,12]=t_onset
232234

src/python/mudpy/gmttools.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,7 @@ def read_neic_param(fault_file):
718718

719719

720720

721-
def triangular_rupt_2_gmt(meshfile,slipfile,outfile,kinematic_out_folder=None):
721+
def triangular_rupt_2_gmt(meshfile,slipfile,outfile,kinematic_out_folder=None,percentage=0):
722722

723723
'''
724724
DM Note: Modified from Brendan's script because he refused to do a pull request :)
@@ -815,11 +815,12 @@ def triangular_rupt_2_gmt(meshfile,slipfile,outfile,kinematic_out_folder=None):
815815
#Total slip model
816816
moment = 0
817817
fso = open(outfile,'w')
818+
slip_threshold=(percentage/100)*TOTS.max()
818819
for i in range(0, numpy.amax(MESN)):
819820
a1 = numpy.where(MESN[i] == INVN)[0]
820821
totslip = numpy.sum(TOTS[a1])
821822
# print (i+1,totslip*100)
822-
if (totslip >= 0.0):
823+
if (totslip >= slip_threshold):
823824
moment = moment+FA[i]*1000*1000*numpy.mean(RIG[a1])*totslip
824825
lon1 = "{0:.4f}".format(meshlon1[i])
825826
lon2 = "{0:.4f}".format(meshlon2[i])

0 commit comments

Comments
 (0)