def run_parallel_synthetics(home, project_name, station_file, model_name, integrate, static, tsunami, time_epi, beta, custom_stf, impulse, rank, size, insar=False, okada=False, mu_okada=45e9): ''' Use green functions and compute synthetics at stations for a single source and multiple stations. This code makes an external system call to syn.c first it will make the external call for the strike-slip component then a second externall call will be made for the dip-slip component. The unit amount of moment is 1e15 which corresponds to Mw=3.9333... IN: source: 1-row numpy array containig informaiton aboutt he source, lat, lon, depth, etc... station_file: File name with the station coordinates green_path: Directopry where GFs are stored model_file: File containing the Earth velocity structure integrate: =0 if youw ant velocity waveforms, =1 if you want displacements static: =0 if computing full waveforms, =1 if computing only the static field subfault: String indicating the subfault being worked on coord_type: =0 if problem is in cartesian coordinates, =1 if problem is in lat/lon OUT: log: Sysytem standard output and standard error for log ''' import os import subprocess from mudpy.forward import get_mu from numpy import array, genfromtxt, loadtxt, savetxt, log10 from obspy import read from shlex import split from mudpy.green import src2sta, rt2ne, origin_time, okada_synthetics from glob import glob from mudpy.green import silentremove from os import remove #What parameters are we using? if rank == 0: out = '''Running all processes with: home = %s project_name = %s station_file = %s model_name = %s integrate = %s static = %s tsunami = %s time_epi = %s beta = %d custom_stf = %s impulse = %s insar = %s okada = %s mu = %.2e ''' % (home, project_name, station_file, model_name, str(integrate), str(static), str(tsunami), str(time_epi), beta, custom_stf, impulse, insar, okada, mu_okada) print(out) #Read your corresponding source file mpi_source = genfromtxt(home + project_name + '/data/model_info/mpi_source.' + str(rank) + '.fault') #Constant parameters rakeDS = 90 + beta #90 is thrust, -90 is normal rakeSS = 0 + beta #0 is left lateral, 180 is right lateral tb = 50 #Number of samples before first arrival (should be 50, NEVER CHANGE, if you do then adjust in fk.pl) #Figure out custom STF if custom_stf.lower() != 'none': custom_stf = home + project_name + '/GFs/STFs/' + custom_stf else: custom_stf = None #Load structure model_file = home + project_name + '/structure/' + model_name structure = loadtxt(model_file, ndmin=2) for ksource in range(len(mpi_source)): source = mpi_source[ksource, :] #Parse the soruce information num = str(int(source[0])).rjust(4, '0') xs = source[1] ys = source[2] zs = source[3] strike = source[4] dip = source[5] rise = source[6] if impulse == True: duration = 0 else: duration = source[7] ss_length = source[8] ds_length = source[9] ss_length_in_km = ss_length / 1000. ds_length_in_km = ds_length / 1000. strdepth = '%.4f' % zs subfault = str(int(source[0])).rjust(4, '0') if static == 0 and tsunami == 0: #Where to save dynamic waveforms green_path = home + project_name + '/GFs/dynamic/' + model_name + "_" + strdepth + ".sub" + subfault + "/" if static == 1 and tsunami == 1: #Where to save dynamic waveforms green_path = home + project_name + '/GFs/tsunami/' + model_name + "_" + strdepth + ".sub" + subfault + "/" if static == 1 and tsunami == 0: #Where to save statics green_path = home + project_name + '/GFs/static/' + model_name + "_" + strdepth + ".sub" + subfault + "/" staname = genfromtxt(station_file, dtype="U", usecols=0) if staname.shape == (): #Single staiton file staname = array([staname]) #Compute distances and azimuths d, az, lon_sta, lat_sta = src2sta(station_file, source, output_coordinates=True) #Get moment corresponding to 1 meter of slip on subfault mu = get_mu(structure, zs) Mo = mu * ss_length * ds_length * 1.0 Mw = (2. / 3) * (log10(Mo) - 9.1) #Move to output folder os.chdir(green_path) print('Processor ' + str(rank) + ' is working on subfault ' + str(int(source[0])) + ' and ' + str(len(d)) + ' stations ') for k in range(len(d)): if static == 0: #Compute full waveforms diststr = '%.6f' % d[ k] #Need current distance in string form for external call #Form the strings to be used for the system calls according to user desired options if integrate == 1: #Make displ. #First Stike-Slip GFs if custom_stf == None: commandSS="syn -I -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeSS)+" -D"+str(duration)+ \ "/"+str(rise)+" -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".SS.disp.x -G"+green_path+diststr+".grn.0" commandSS = split( commandSS ) #Split string into lexical components for system call #Now dip slip commandDS="syn -I -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeDS)+" -D"+str(duration)+ \ "/"+str(rise)+" -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".DS.disp.x -G"+green_path+diststr+".grn.0" commandDS = split(commandDS) else: commandSS="syn -I -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeSS)+" -S"+custom_stf+ \ " -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".SS.disp.x -G"+green_path+diststr+".grn.0" commandSS = split( commandSS ) #Split string into lexical components for system call #Now dip slip commandDS="syn -I -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeDS)+" -S"+custom_stf+ \ " -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".DS.disp.x -G"+green_path+diststr+".grn.0" commandDS = split(commandDS) else: #Make vel. #First Stike-Slip GFs if custom_stf == None: commandSS="syn -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeSS)+" -D"+str(duration)+ \ "/"+str(rise)+" -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".SS.vel.x -G"+green_path+diststr+".grn.0" commandSS = split(commandSS) #Now dip slip commandDS="syn -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeDS)+" -D"+str(duration)+ \ "/"+str(rise)+" -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".DS.vel.x -G"+green_path+diststr+".grn.0" commandDS = split(commandDS) else: commandSS="syn -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeSS)+" -S"+custom_stf+ \ " -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".SS.vel.x -G"+green_path+diststr+".grn.0" commandSS = split(commandSS) #Now dip slip commandDS="syn -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeDS)+" -S"+custom_stf+ \ " -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".DS.vel.x -G"+green_path+diststr+".grn.0" commandDS = split(commandDS) #Run the strike- and dip-slip commands (make system calls) p = subprocess.Popen(commandSS) p.communicate() p = subprocess.Popen(commandDS) p.communicate() #Result is in RTZ system (+Z is down) rotate to NEZ with +Z up and scale to m or m/s if integrate == 1: #'tis displacememnt #Strike slip if duration > 0: #Is there a source time fucntion? Yes! r = read(staname[k] + ".subfault" + num + '.SS.disp.r') t = read(staname[k] + ".subfault" + num + '.SS.disp.t') z = read(staname[k] + ".subfault" + num + '.SS.disp.z') else: #No! This is the impulse response! r = read(staname[k] + ".subfault" + num + '.SS.disp.ri') t = read(staname[k] + ".subfault" + num + '.SS.disp.ti') z = read(staname[k] + ".subfault" + num + '.SS.disp.zi') ntemp, etemp = rt2ne(r[0].data, t[0].data, az[k]) #Scale to m and overwrite with rotated waveforms n = r.copy() n[0].data = ntemp / 100 e = t.copy() e[0].data = etemp / 100 z[0].data = z[0].data / 100 n = origin_time(n, time_epi, tb) e = origin_time(e, time_epi, tb) z = origin_time(z, time_epi, tb) n.write(staname[k] + ".subfault" + num + '.SS.disp.n', format='SAC') e.write(staname[k] + ".subfault" + num + '.SS.disp.e', format='SAC') z.write(staname[k] + ".subfault" + num + '.SS.disp.z', format='SAC') silentremove(staname[k] + ".subfault" + num + '.SS.disp.r') silentremove(staname[k] + ".subfault" + num + '.SS.disp.t') if impulse == True: silentremove(staname[k] + ".subfault" + num + '.SS.disp.ri') silentremove(staname[k] + ".subfault" + num + '.SS.disp.ti') silentremove(staname[k] + ".subfault" + num + '.SS.disp.zi') #Dip Slip if duration > 0: #Is there a source time fucntion? Yes! r = read(staname[k] + ".subfault" + num + '.DS.disp.r') t = read(staname[k] + ".subfault" + num + '.DS.disp.t') z = read(staname[k] + ".subfault" + num + '.DS.disp.z') else: #No! This is the impulse response! r = read(staname[k] + ".subfault" + num + '.DS.disp.ri') t = read(staname[k] + ".subfault" + num + '.DS.disp.ti') z = read(staname[k] + ".subfault" + num + '.DS.disp.zi') ntemp, etemp = rt2ne(r[0].data, t[0].data, az[k]) n = r.copy() n[0].data = ntemp / 100 e = t.copy() e[0].data = etemp / 100 z[0].data = z[0].data / 100 n = origin_time(n, time_epi, tb) e = origin_time(e, time_epi, tb) z = origin_time(z, time_epi, tb) n.write(staname[k] + ".subfault" + num + '.DS.disp.n', format='SAC') e.write(staname[k] + ".subfault" + num + '.DS.disp.e', format='SAC') z.write(staname[k] + ".subfault" + num + '.DS.disp.z', format='SAC') silentremove(staname[k] + ".subfault" + num + '.DS.disp.r') silentremove(staname[k] + ".subfault" + num + '.DS.disp.t') if impulse == True: silentremove(staname[k] + ".subfault" + num + '.DS.disp.ri') silentremove(staname[k] + ".subfault" + num + '.DS.disp.ti') silentremove(staname[k] + ".subfault" + num + '.DS.disp.zi') else: #Waveforms are velocity, as before, rotate from RT-Z to NE+Z and scale to m/s #Strike slip if duration > 0: #Is there a source time fucntion? Yes! r = read(staname[k] + ".subfault" + num + '.SS.vel.r') t = read(staname[k] + ".subfault" + num + '.SS.vel.t') z = read(staname[k] + ".subfault" + num + '.SS.vel.z') else: #No! This is the impulse response! r = read(staname[k] + ".subfault" + num + '.SS.vel.ri') t = read(staname[k] + ".subfault" + num + '.SS.vel.ti') z = read(staname[k] + ".subfault" + num + '.SS.vel.zi') ntemp, etemp = rt2ne(r[0].data, t[0].data, az[k]) n = r.copy() n[0].data = ntemp / 100 e = t.copy() e[0].data = etemp / 100 z[0].data = z[0].data / 100 n = origin_time(n, time_epi, tb) e = origin_time(e, time_epi, tb) z = origin_time(z, time_epi, tb) n.write(staname[k] + ".subfault" + num + '.SS.vel.n', format='SAC') e.write(staname[k] + ".subfault" + num + '.SS.vel.e', format='SAC') z.write(staname[k] + ".subfault" + num + '.SS.vel.z', format='SAC') silentremove(staname[k] + ".subfault" + num + '.SS.vel.r') silentremove(staname[k] + ".subfault" + num + '.SS.vel.t') if impulse == True: silentremove(staname[k] + ".subfault" + num + '.SS.vel.ri') silentremove(staname[k] + ".subfault" + num + '.SS.vel.ti') silentremove(staname[k] + ".subfault" + num + '.SS.vel.zi') #Dip Slip if duration > 0: #Is there a source time fucntion? Yes! r = read(staname[k] + ".subfault" + num + '.DS.vel.r') t = read(staname[k] + ".subfault" + num + '.DS.vel.t') z = read(staname[k] + ".subfault" + num + '.DS.vel.z') else: #No! This is the impulse response! r = read(staname[k] + ".subfault" + num + '.DS.vel.ri') t = read(staname[k] + ".subfault" + num + '.DS.vel.ti') z = read(staname[k] + ".subfault" + num + '.DS.vel.zi') ntemp, etemp = rt2ne(r[0].data, t[0].data, az[k]) n = r.copy() n[0].data = ntemp / 100 e = t.copy() e[0].data = etemp / 100 z[0].data = z[0].data / 100 n = origin_time(n, time_epi, tb) e = origin_time(e, time_epi, tb) z = origin_time(z, time_epi, tb) n.write(staname[k] + ".subfault" + num + '.DS.vel.n', format='SAC') e.write(staname[k] + ".subfault" + num + '.DS.vel.e', format='SAC') z.write(staname[k] + ".subfault" + num + '.DS.vel.z', format='SAC') silentremove(staname[k] + ".subfault" + num + '.DS.vel.r') silentremove(staname[k] + ".subfault" + num + '.DS.vel.t') if impulse == True: silentremove(staname[k] + ".subfault" + num + '.DS.vel.ri') silentremove(staname[k] + ".subfault" + num + '.DS.vel.ti') silentremove(staname[k] + ".subfault" + num + '.DS.vel.zi') else: #Compute static synthetics if okada == False: #Layered earth model temp_pipe = [] diststr = '%.1f' % d[ k] #Need current distance in string form for external call if insar == True: green_file = green_path + model_name + ".static." + strdepth + ".sub" + subfault + '.insar' #Output dir else: #GPS green_file = green_path + model_name + ".static." + strdepth + ".sub" + subfault + '.gps' #Output dir statics = loadtxt(green_file) #Load GFs if len(statics) < 1: print('ERROR: Empty GF file') break #Print static GFs into a pipe and pass into synthetics command try: temp_pipe = statics[k, :] except: temp_pipe = statics inpipe = '' for j in range(len(temp_pipe)): inpipe = inpipe + ' %.6e' % temp_pipe[j] #Form command for external call commandDS="syn -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeDS)+\ " -A"+str(az[k])+" -P" commandSS="syn -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeSS)+\ " -A"+str(az[k])+" -P" commandSS = split(commandSS) #Lexical split commandDS = split(commandDS) #Make system calls, one for DS, one for SS ps = subprocess.Popen( ['printf', inpipe], stdout=subprocess.PIPE ) #This is the statics pipe, pint stdout to syn's stdin p = subprocess.Popen( commandSS, stdin=ps.stdout, stdout=open( green_path + staname[k] + '.subfault' + num + '.SS.static.rtz', 'w')) p.communicate() ps = subprocess.Popen( ['printf', inpipe], stdout=subprocess.PIPE ) #This is the statics pipe, pint stdout to syn's stdin p = subprocess.Popen( commandDS, stdin=ps.stdout, stdout=open( green_path + staname[k] + '.subfault' + num + '.DS.static.rtz', 'w')) p.communicate() #Rotate radial/transverse to East/North, correct vertical and scale to m statics = loadtxt(green_path + staname[k] + '.subfault' + num + '.SS.static.rtz') u = statics[2] / 100 r = statics[3] / 100 t = statics[4] / 100 ntemp, etemp = rt2ne(array([r, r]), array([t, t]), az[k]) n = ntemp[0] e = etemp[0] savetxt( green_path + staname[k] + '.subfault' + num + '.SS.static.neu', (n, e, u, beta)) statics = loadtxt(green_path + staname[k] + '.subfault' + num + '.DS.static.rtz') u = statics[2] / 100 r = statics[3] / 100 t = statics[4] / 100 ntemp, etemp = rt2ne(array([r, r]), array([t, t]), az[k]) n = ntemp[0] e = etemp[0] savetxt(green_path + staname[k] + '.subfault' + num + '.DS.static.neu', (n, e, u, beta), header='north(m),east(m),up(m),beta(degs)') else: #Okada half space solutions #SS n, e, u = okada_synthetics(strike, dip, rakeSS, ss_length_in_km, ds_length_in_km, xs, ys, zs, lon_sta[k], lat_sta[k], mu_okada) savetxt(staname[k] + '.subfault' + num + '.SS.static.neu', (n, e, u, beta), header='north(m),east(m),up(m),beta(degs)') #DS n, e, u = okada_synthetics(strike, dip, rakeDS, ss_length_in_km, ds_length_in_km, xs, ys, zs, lon_sta[k], lat_sta[k], mu_okada) savetxt(staname[k] + '.subfault' + num + '.DS.static.neu', (n, e, u, beta), header='north(m),east(m),up(m),beta(degs)')
def run_parallel_synthetics(home,project_name,station_file,model_name,integrate,static,tsunami,time_epi, beta,custom_stf,impulse,rank,size,insar=False,okada=False,mu_okada=45e9): ''' Use green functions and compute synthetics at stations for a single source and multiple stations. This code makes an external system call to syn.c first it will make the external call for the strike-slip component then a second externall call will be made for the dip-slip component. The unit amount of moment is 1e15 which corresponds to Mw=3.9333... IN: source: 1-row numpy array containig informaiton aboutt he source, lat, lon, depth, etc... station_file: File name with the station coordinates green_path: Directopry where GFs are stored model_file: File containing the Earth velocity structure integrate: =0 if youw ant velocity waveforms, =1 if you want displacements static: =0 if computing full waveforms, =1 if computing only the static field subfault: String indicating the subfault being worked on coord_type: =0 if problem is in cartesian coordinates, =1 if problem is in lat/lon OUT: log: Sysytem standard output and standard error for log ''' import os import subprocess from pandas import DataFrame as df from mudpy.forward import get_mu from numpy import array,genfromtxt,loadtxt,savetxt,log10,zeros,sin,cos,ones,deg2rad from obspy import read from shlex import split from mudpy.green import src2sta,rt2ne,origin_time,okada_synthetics from glob import glob from mudpy.green import silentremove from os import remove #What parameters are we using? if rank==0: out='''Running all processes with: home = %s project_name = %s station_file = %s model_name = %s integrate = %s static = %s tsunami = %s time_epi = %s beta = %d custom_stf = %s impulse = %s insar = %s okada = %s mu = %.2e ''' %(home,project_name,station_file,model_name,str(integrate),str(static),str(tsunami),str(time_epi),beta,custom_stf,impulse,insar,okada,mu_okada) print(out) #Read your corresponding source file mpi_source=genfromtxt(home+project_name+'/data/model_info/mpi_source.'+str(rank)+'.fault') #Constant parameters rakeDS=90+beta #90 is thrust, -90 is normal rakeSS=0+beta #0 is left lateral, 180 is right lateral tb=50 #Number of samples before first arrival (should be 50, NEVER CHANGE, if you do then adjust in fk.pl) #Figure out custom STF if custom_stf.lower()!='none': custom_stf=home+project_name+'/GFs/STFs/'+custom_stf else: custom_stf=None #Load structure model_file=home+project_name+'/structure/'+model_name structure=loadtxt(model_file,ndmin=2) #this keeps track of statics dataframe write_df=False for ksource in range(len(mpi_source)): source=mpi_source[ksource,:] #Parse the soruce information num=str(int(source[0])).rjust(4,'0') xs=source[1] ys=source[2] zs=source[3] strike=source[4] dip=source[5] rise=source[6] if impulse==True: duration=0 else: duration=source[7] ss_length=source[8] ds_length=source[9] ss_length_in_km=ss_length/1000. ds_length_in_km=ds_length/1000. strdepth='%.4f' % zs subfault=str(int(source[0])).rjust(4,'0') if static==0 and tsunami==0: #Where to save dynamic waveforms green_path=home+project_name+'/GFs/dynamic/'+model_name+"_"+strdepth+".sub"+subfault+"/" if static==1 and tsunami==1: #Where to save dynamic waveforms green_path=home+project_name+'/GFs/tsunami/'+model_name+"_"+strdepth+".sub"+subfault+"/" if static==1 and tsunami==0: #Where to save statics green_path=home+project_name+'/GFs/static/'+model_name+"_"+strdepth+".sub"+subfault+"/" staname=genfromtxt(station_file,dtype="U",usecols=0) if staname.shape==(): #Single staiton file staname=array([staname]) #Compute distances and azimuths d,az,lon_sta,lat_sta=src2sta(station_file,source,output_coordinates=True) #Get moment corresponding to 1 meter of slip on subfault mu=get_mu(structure,zs) Mo=mu*ss_length*ds_length*1.0 Mw=(2./3)*(log10(Mo)-9.1) #Move to output folder os.chdir(green_path) print('Processor '+str(rank)+' is working on subfault '+str(int(source[0]))+' and '+str(len(d))+' stations ') #This is looping over "sites" for k in range(len(d)): if static==0: #Compute full waveforms diststr='%.6f' % d[k] #Need current distance in string form for external call #Form the strings to be used for the system calls according to user desired options if integrate==1: #Make displ. #First Stike-Slip GFs if custom_stf==None: commandSS="syn -I -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeSS)+" -D"+str(duration)+ \ "/"+str(rise)+" -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".SS.disp.x -G"+green_path+diststr+".grn.0" commandSS=split(commandSS) #Split string into lexical components for system call #Now dip slip commandDS="syn -I -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeDS)+" -D"+str(duration)+ \ "/"+str(rise)+" -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".DS.disp.x -G"+green_path+diststr+".grn.0" commandDS=split(commandDS) else: commandSS="syn -I -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeSS)+" -S"+custom_stf+ \ " -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".SS.disp.x -G"+green_path+diststr+".grn.0" commandSS=split(commandSS) #Split string into lexical components for system call #Now dip slip commandDS="syn -I -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeDS)+" -S"+custom_stf+ \ " -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".DS.disp.x -G"+green_path+diststr+".grn.0" commandDS=split(commandDS) else: #Make vel. #First Stike-Slip GFs if custom_stf==None: commandSS="syn -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeSS)+" -D"+str(duration)+ \ "/"+str(rise)+" -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".SS.vel.x -G"+green_path+diststr+".grn.0" commandSS=split(commandSS) #Now dip slip commandDS="syn -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeDS)+" -D"+str(duration)+ \ "/"+str(rise)+" -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".DS.vel.x -G"+green_path+diststr+".grn.0" commandDS=split(commandDS) else: commandSS="syn -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeSS)+" -S"+custom_stf+ \ " -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".SS.vel.x -G"+green_path+diststr+".grn.0" commandSS=split(commandSS) #Now dip slip commandDS="syn -M"+str(Mw)+"/"+str(strike)+"/"+str(dip)+"/"+str(rakeDS)+" -S"+custom_stf+ \ " -A"+str(az[k])+" -O"+staname[k]+".subfault"+num+".DS.vel.x -G"+green_path+diststr+".grn.0" commandDS=split(commandDS) #Run the strike- and dip-slip commands (make system calls) p=subprocess.Popen(commandSS) p.communicate() p=subprocess.Popen(commandDS) p.communicate() #Result is in RTZ system (+Z is down) rotate to NEZ with +Z up and scale to m or m/s if integrate==1: #'tis displacememnt #Strike slip if duration>0: #Is there a source time fucntion? Yes! r=read(staname[k]+".subfault"+num+'.SS.disp.r') t=read(staname[k]+".subfault"+num+'.SS.disp.t') z=read(staname[k]+".subfault"+num+'.SS.disp.z') else: #No! This is the impulse response! r=read(staname[k]+".subfault"+num+'.SS.disp.ri') t=read(staname[k]+".subfault"+num+'.SS.disp.ti') z=read(staname[k]+".subfault"+num+'.SS.disp.zi') ntemp,etemp=rt2ne(r[0].data,t[0].data,az[k]) #Scale to m and overwrite with rotated waveforms n=r.copy() n[0].data=ntemp/100 e=t.copy() e[0].data=etemp/100 z[0].data=z[0].data/100 # get rid of numerical "noise" in the first tb samples n[0].data[0:tb]=0 e[0].data[0:tb]=0 z[0].data[0:tb]=0 n=origin_time(n,time_epi,tb) e=origin_time(e,time_epi,tb) z=origin_time(z,time_epi,tb) n.write(staname[k]+".subfault"+num+'.SS.disp.n',format='SAC') e.write(staname[k]+".subfault"+num+'.SS.disp.e',format='SAC') z.write(staname[k]+".subfault"+num+'.SS.disp.z',format='SAC') silentremove(staname[k]+".subfault"+num+'.SS.disp.r') silentremove(staname[k]+".subfault"+num+'.SS.disp.t') if impulse==True: silentremove(staname[k]+".subfault"+num+'.SS.disp.ri') silentremove(staname[k]+".subfault"+num+'.SS.disp.ti') silentremove(staname[k]+".subfault"+num+'.SS.disp.zi') #Dip Slip if duration>0: #Is there a source time fucntion? Yes! r=read(staname[k]+".subfault"+num+'.DS.disp.r') t=read(staname[k]+".subfault"+num+'.DS.disp.t') z=read(staname[k]+".subfault"+num+'.DS.disp.z') else: #No! This is the impulse response! r=read(staname[k]+".subfault"+num+'.DS.disp.ri') t=read(staname[k]+".subfault"+num+'.DS.disp.ti') z=read(staname[k]+".subfault"+num+'.DS.disp.zi') ntemp,etemp=rt2ne(r[0].data,t[0].data,az[k]) n=r.copy() n[0].data=ntemp/100 e=t.copy() e[0].data=etemp/100 z[0].data=z[0].data/100 n=origin_time(n,time_epi,tb) e=origin_time(e,time_epi,tb) z=origin_time(z,time_epi,tb) n.write(staname[k]+".subfault"+num+'.DS.disp.n',format='SAC') e.write(staname[k]+".subfault"+num+'.DS.disp.e',format='SAC') z.write(staname[k]+".subfault"+num+'.DS.disp.z',format='SAC') silentremove(staname[k]+".subfault"+num+'.DS.disp.r') silentremove(staname[k]+".subfault"+num+'.DS.disp.t') if impulse==True: silentremove(staname[k]+".subfault"+num+'.DS.disp.ri') silentremove(staname[k]+".subfault"+num+'.DS.disp.ti') silentremove(staname[k]+".subfault"+num+'.DS.disp.zi') else: #Waveforms are velocity, as before, rotate from RT-Z to NE+Z and scale to m/s #Strike slip if duration>0: #Is there a source time fucntion? Yes! r=read(staname[k]+".subfault"+num+'.SS.vel.r') t=read(staname[k]+".subfault"+num+'.SS.vel.t') z=read(staname[k]+".subfault"+num+'.SS.vel.z') else: #No! This is the impulse response! r=read(staname[k]+".subfault"+num+'.SS.vel.ri') t=read(staname[k]+".subfault"+num+'.SS.vel.ti') z=read(staname[k]+".subfault"+num+'.SS.vel.zi') ntemp,etemp=rt2ne(r[0].data,t[0].data,az[k]) n=r.copy() n[0].data=ntemp/100 e=t.copy() e[0].data=etemp/100 z[0].data=z[0].data/100 n=origin_time(n,time_epi,tb) e=origin_time(e,time_epi,tb) z=origin_time(z,time_epi,tb) n.write(staname[k]+".subfault"+num+'.SS.vel.n',format='SAC') e.write(staname[k]+".subfault"+num+'.SS.vel.e',format='SAC') z.write(staname[k]+".subfault"+num+'.SS.vel.z',format='SAC') silentremove(staname[k]+".subfault"+num+'.SS.vel.r') silentremove(staname[k]+".subfault"+num+'.SS.vel.t') if impulse==True: silentremove(staname[k]+".subfault"+num+'.SS.vel.ri') silentremove(staname[k]+".subfault"+num+'.SS.vel.ti') silentremove(staname[k]+".subfault"+num+'.SS.vel.zi') #Dip Slip if duration>0: #Is there a source time fucntion? Yes! r=read(staname[k]+".subfault"+num+'.DS.vel.r') t=read(staname[k]+".subfault"+num+'.DS.vel.t') z=read(staname[k]+".subfault"+num+'.DS.vel.z') else: #No! This is the impulse response! r=read(staname[k]+".subfault"+num+'.DS.vel.ri') t=read(staname[k]+".subfault"+num+'.DS.vel.ti') z=read(staname[k]+".subfault"+num+'.DS.vel.zi') ntemp,etemp=rt2ne(r[0].data,t[0].data,az[k]) n=r.copy() n[0].data=ntemp/100 e=t.copy() e[0].data=etemp/100 z[0].data=z[0].data/100 n=origin_time(n,time_epi,tb) e=origin_time(e,time_epi,tb) z=origin_time(z,time_epi,tb) n.write(staname[k]+".subfault"+num+'.DS.vel.n',format='SAC') e.write(staname[k]+".subfault"+num+'.DS.vel.e',format='SAC') z.write(staname[k]+".subfault"+num+'.DS.vel.z',format='SAC') silentremove(staname[k]+".subfault"+num+'.DS.vel.r') silentremove(staname[k]+".subfault"+num+'.DS.vel.t') if impulse==True: silentremove(staname[k]+".subfault"+num+'.DS.vel.ri') silentremove(staname[k]+".subfault"+num+'.DS.vel.ti') silentremove(staname[k]+".subfault"+num+'.DS.vel.zi') else: #Compute static synthetics if okada==False: #Layered earth model #this is because when I first wrote this code it processed each #source/station pair independently but now that it's vectorized #it's does ALL stations in one fell swoop, given the logic it's #easier to just keep this inside the for loop and use the if to #run it jsut the first time for all sites if k==0: #initalize output variables staticsSS = zeros((len(d),4)) staticsDS = zeros((len(d),4)) write_df=True #read GFs file if insar==True: green_file=green_path+model_name+".static."+strdepth+".sub"+subfault+'.insar' #Output dir else: #GPS green_file=green_path+model_name+".static."+strdepth+".sub"+subfault+'.gps' #Output statics=loadtxt(green_file) #Load GFs Nsites=len(statics) if len(statics)<1: print('ERROR: Empty GF file') break #Now get radiation pattern terms, there will be 3 terms #for each direction so 9 terms total. THis comes from funtion #dc_radiat() in radiats.c from fk radiation_pattern_ss = zeros((Nsites,9)) radiation_pattern_ds = zeros((Nsites,9)) rakeSSrad = deg2rad(rakeSS) rakeDSrad = deg2rad(rakeDS) dip_rad = deg2rad(dip) pseudo_strike = deg2rad(az-strike) #Let's do SS first r = rakeSSrad #trigonometric terms following nomenclature used in radiats.c sstk=sin(pseudo_strike) ; cstk=cos(pseudo_strike) sdip=sin(dip_rad) ; cdip=cos(dip_rad) srak=sin(r) ; crak=cos(r) sstk2=2*sstk*cstk ; cstk2=cstk*cstk-sstk*sstk sdip2=2*sdip*cdip ; cdip2=cdip*cdip-sdip*sdip # terms for up component u_dd = 0.5*srak*sdip2*ones(Nsites) u_ds = -sstk*srak*cdip2+cstk*crak*cdip u_ss = -sstk2*crak*sdip-0.5*cstk2*srak*sdip2 #terms for r component r_dd = u_dd.copy() r_ds = u_ds.copy() r_ss = u_ss.copy() #terms for t component t_dd = zeros(Nsites) t_ds = cstk*srak*cdip2+sstk*crak*cdip t_ss = cstk2*crak*sdip-0.5*sstk2*srak*sdip2 #assemble in one variable radiation_pattern_ss[:,0] = u_dd radiation_pattern_ss[:,1] = u_ds radiation_pattern_ss[:,2] = u_ss radiation_pattern_ss[:,3] = r_dd radiation_pattern_ss[:,4] = r_ds radiation_pattern_ss[:,5] = r_ss radiation_pattern_ss[:,6] = t_dd radiation_pattern_ss[:,7] = t_ds radiation_pattern_ss[:,8] = t_ss #Now radiation pattern for DS r = rakeDSrad #trigonometric terms following nomenclature used in radiats.c sstk=sin(pseudo_strike) ; cstk=cos(pseudo_strike) sdip=sin(dip_rad) ; cdip=cos(dip_rad) srak=sin(r) ; crak=cos(r) sstk2=2*sstk*cstk ; cstk2=cstk*cstk-sstk*sstk sdip2=2*sdip*cdip ; cdip2=cdip*cdip-sdip*sdip # terms for up component u_dd = 0.5*srak*sdip2*ones(Nsites) u_ds = -sstk*srak*cdip2+cstk*crak*cdip u_ss = -sstk2*crak*sdip-0.5*cstk2*srak*sdip2 #terms for r component r_dd = u_dd.copy() r_ds = u_ds.copy() r_ss = u_ss.copy() #terms for t component t_dd = zeros(Nsites) t_ds = cstk*srak*cdip2+sstk*crak*cdip t_ss = cstk2*crak*sdip-0.5*sstk2*srak*sdip2 #assemble in one variable radiation_pattern_ds[:,0] = u_dd radiation_pattern_ds[:,1] = u_ds radiation_pattern_ds[:,2] = u_ss radiation_pattern_ds[:,3] = r_dd radiation_pattern_ds[:,4] = r_ds radiation_pattern_ds[:,5] = r_ss radiation_pattern_ds[:,6] = t_dd radiation_pattern_ds[:,7] = t_ds radiation_pattern_ds[:,8] = t_ss #Now define the scalng based on magnitude this is variable #"coef" in the syn.c original source code scale = 10**(1.5*Mw+16.1-20) #definition used in syn.c #Scale radiation patterns accordingly radiation_pattern_ss *= scale radiation_pattern_ds *= scale #Now multiply each GF component by the appropriate SCALED #radiation pattern term and add em up to get the displacements # also /100 to convert to meters up_ss = radiation_pattern_ss[:,0:3]*statics[:,[1,4,7]] up_ss = up_ss.sum(axis=1) / 100 up_ds = radiation_pattern_ds[:,0:3]*statics[:,[1,4,7]] up_ds = up_ds.sum(axis=1) / 100 radial_ss = radiation_pattern_ss[:,3:6]*statics[:,[2,5,8]] radial_ss = radial_ss.sum(axis=1) / 100 radial_ds = radiation_pattern_ds[:,3:6]*statics[:,[2,5,8]] radial_ds = radial_ds.sum(axis=1) / 100 tangential_ss = radiation_pattern_ss[:,6:9]*statics[:,[3,6,9]] tangential_ss = tangential_ss.sum(axis=1) / 100 tangential_ds = radiation_pattern_ds[:,6:9]*statics[:,[3,6,9]] tangential_ds = tangential_ds.sum(axis=1) / 100 #rotate to neu n_ss,e_ss=rt2ne(radial_ss,tangential_ss,az) n_ds,e_ds=rt2ne(radial_ds,tangential_ds,az) #put in output variables staticsSS[:,0]=n_ss staticsSS[:,1]=e_ss staticsSS[:,2]=up_ss staticsSS[:,3]=beta*ones(Nsites) staticsDS[:,0]=n_ds staticsDS[:,1]=e_ds staticsDS[:,2]=up_ds staticsDS[:,3]=beta*ones(Nsites) else: pass else: #Okada half space solutions #SS n,e,u=okada_synthetics(strike,dip,rakeSS,ss_length_in_km,ds_length_in_km,xs,ys, zs,lon_sta[k],lat_sta[k],mu_okada) savetxt(staname[k]+'.subfault'+num+'.SS.static.neu',(n,e,u,beta),header='north(m),east(m),up(m),beta(degs)') #DS n,e,u=okada_synthetics(strike,dip,rakeDS,ss_length_in_km,ds_length_in_km,xs,ys, zs,lon_sta[k],lat_sta[k],mu_okada) savetxt(staname[k]+'.subfault'+num+'.DS.static.neu',(n,e,u,beta),header='north(m),east(m),up(m),beta(degs)') if write_df==True and static ==1: #Note to self: stop using 0,1 and swithc to True/False #Strike slip SSdf = df(data=None, index=None, columns=['staname','n','e','u','beta']) SSdf.staname=staname SSdf.n=staticsSS[:,0] SSdf.e=staticsSS[:,1] SSdf.u=staticsSS[:,2] SSdf.beta=staticsSS[:,3] SSdf.to_csv(green_path+'subfault'+num+'.SS.static.neu',sep='\t',index=False,header=False) DSdf = df(data=None, index=None, columns=['staname','n','e','u','beta']) DSdf.staname=staname DSdf.n=staticsDS[:,0] DSdf.e=staticsDS[:,1] DSdf.u=staticsDS[:,2] DSdf.beta=staticsDS[:,3] DSdf.to_csv(green_path+'subfault'+num+'.DS.static.neu',sep='\t',index=False,header=False)