Пример #1
0
def get_mean_slip(target_Mw,fault_array,vel_mod):
    '''
    Depending on the target magnitude calculate the necessary uniform slip
    on the fault given the 1D layered Earth velocity model
    '''
    
    from numpy import genfromtxt,zeros,ones
    from mudpy.forward import get_mu
    
    vel=genfromtxt(vel_mod)
    areas=fault_array[:,8]*fault_array[:,9]
    mu=zeros(len(fault_array))
    for k in range(len(mu)):
        mu[k]=get_mu(vel,fault_array[k,3])
    target_moment=10**(1.5*target_Mw+9.1)
    mean_slip=ones(len(fault_array))*target_moment/sum(areas*mu)
    
    return mean_slip,mu
Пример #2
0
def run_syn(home,
            project_name,
            source,
            station_file,
            green_path,
            model_name,
            integrate,
            static,
            tsunami,
            subfault,
            time_epi,
            beta,
            impulse=False,
            okada=False,
            okada_mu=45e9,
            insar=False):
    '''
    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 string import rjust
    from numpy import array, genfromtxt, loadtxt, savetxt, log10, argmin
    from obspy import read
    from shlex import split

    #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
    #Load structure
    model_file = home + project_name + '/structure/' + model_name
    structure = loadtxt(model_file, ndmin=2)
    #Parse the soruce information
    num = rjust(str(int(source[0])), 4, '0')
    xs = source[1]
    ys = source[2]
    zs = source[3]
    strike = source[4]
    dip = source[5]
    rise = source[6]
    if impulse == True:  #Impulse GFs or apply rise time
        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
    if static == 0 and tsunami == 0:  #Where to save dynamic waveforms
        green_path = green_path + 'dynamic/' + model_name + "_" + strdepth + ".sub" + subfault + "/"
    if static == 0 and tsunami == 1:  #Where to save dynamic waveforms
        green_path = green_path + 'tsunami/' + model_name + "_" + strdepth + ".sub" + subfault + "/"
    print("--> Computing synthetics at stations for the source at (" +
          str(xs) + " , " + str(ys) + ")")
    staname = genfromtxt(station_file, dtype="S6", 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
    Mw = (2. / 3) * (log10(Mo) - 9.1)
    #Move to output folder
    log = ''  #Initalize log
    os.chdir(green_path)
    for k in range(len(d)):
        if static == 0:  #Compute full waveforms
            diststr = '%.3f' % d[
                k]  #Need current distance in string form for external call
            #Form the strings to be used for the system calls according to suer desired options
            if integrate == 1:  #Make displ.
                #First Stike-Slip GFs
                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"
                print commandSS  #Output to screen so I know we're underway
                log = log + commandSS + '\n'  #Append to log
                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"
                print commandDS
                log = log + commandDS + '\n'
                commandDS = split(commandDS)
            else:  #Make vel.
                #First Stike-Slip GFs
                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"
                print commandSS
                log = log + commandSS + '\n'
                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"
                print commandDS
                log = log + commandDS + '\n'
                commandDS = split(commandDS)
            #Run the strike- and dip-slip commands (make system calls)
            p = subprocess.Popen(commandSS,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
            out, err = p.communicate()
            p = subprocess.Popen(commandDS,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
            out, err = 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:
                    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:
                    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:
                    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:
                    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
            os.chdir(green_path + 'static/')  #Move to appropriate dir
            if okada == False:
                diststr = '%.1f' % d[
                    k]  #Need current distance in string form for external call

                if insar == True:
                    green_file = model_name + ".static." + strdepth + ".sub" + subfault + '.insar'  #Output dir
                else:  #GPS
                    green_file = model_name + ".static." + strdepth + ".sub" + subfault + '.gps'  #Output dir

                print green_file
                log = log + green_file + '\n'  #Append to log
                statics = loadtxt(green_file)  #Load GFs
                #Print static GFs into a pipe and pass into synthetics command
                station_index = argmin(abs(statics[:, 0] -
                                           d[k]))  #Look up by distance
                try:
                    temp_pipe = statics[station_index, :]
                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"
                print staname[k]
                print commandSS
                print commandDS
                log = log + staname[
                    k] + '\n' + commandSS + '\n' + commandDS + '\n'  #Append to log
                commandSS = split(commandSS)  #Lexical split
                commandDS = split(commandDS)
                #Make system calls, one for DS, one for SS, and save log
                ps = subprocess.Popen(
                    ['printf', inpipe],
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE
                )  #This is the statics pipe, pint stdout to syn's stdin
                p = subprocess.Popen(commandSS,
                                     stdin=ps.stdout,
                                     stdout=open(
                                         staname[k] + '.subfault' + num +
                                         '.SS.static.rtz', 'w'),
                                     stderr=subprocess.PIPE)
                out, err = p.communicate()
                log = log + str(out) + str(err)
                ps = subprocess.Popen(
                    ['printf', inpipe],
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE
                )  #This is the statics pipe, pint stdout to syn's stdin
                p = subprocess.Popen(commandDS,
                                     stdin=ps.stdout,
                                     stdout=open(
                                         staname[k] + '.subfault' + num +
                                         '.DS.static.rtz', 'w'),
                                     stderr=subprocess.PIPE)
                out, err = p.communicate()
                log = log + str(out) + str(err)
                #Rotate radial/transverse to East/North, correct vertical and scale to m
                statics = loadtxt(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(staname[k] + '.subfault' + num + '.SS.static.neu',
                        (n, e, u, beta),
                        header='north(m),east(m),up(m),beta(degs)')
                statics = loadtxt(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(staname[k] + '.subfault' + num + '.DS.static.neu',
                        (n, e, u, beta),
                        header='north(m),east(m),up(m),beta(degs)')
            else:
                #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],
                                           okada_mu)
                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],
                                           okada_mu)
                savetxt(staname[k] + '.subfault' + num + '.DS.static.neu',
                        (n, e, u, beta),
                        header='north(m),east(m),up(m),beta(degs)')
    return log
Пример #3
0
def stochastic_simulation(home,project_name,rupture_name,GF_list,time_epi,model_name,
        rise_time_depths,moho_depth_in_km,total_duration=100,hf_dt=0.01,stress_parameter=50,
        kappa=0.04,Qexp=0.6,component='N',Pwave=False): 
    '''
    Run stochastic HF sims
    
    stress parameter is in bars
    '''
    
    from numpy import genfromtxt,pi,logspace,log10,mean,where,exp,arange,zeros,argmin,rad2deg,arctan2
    from pyproj import Geod
    from obspy.geodetics import kilometer2degrees
    from obspy.taup import taup_create,TauPyModel
    from mudpy.forward import get_mu
    from obspy import Stream,Trace
    from matplotlib import pyplot as plt
    
    #initalize  output object
    st=Stream()
    
    #Load the source
    fault=genfromtxt(home+project_name+'/output/ruptures/'+rupture_name)    
    
    #Onset times for each subfault
    onset_times=fault[:,12]
    
    #Load stations
    sta=genfromtxt(home+project_name+'/data/station_info/'+GF_list,usecols=[0],dtype='S')
    lonlat=genfromtxt(home+project_name+'/data/station_info/'+GF_list,usecols=[1,2])
    
    #load velocity structure
    structure=genfromtxt(home+project_name+'/structure/'+model_name)
    
    #Frequencies vector
    f=logspace(log10(hf_dt),log10(1/(2*hf_dt))+0.01,50)
    omega=2*pi*f
    
    #Output time vector (0 is origin time)
    t=arange(0,total_duration,hf_dt)
    
    #Projection object for distance calculations
    g=Geod(ellps='WGS84')
    
    #Create taup velocity model object, paste on top of iaspei91
    #taup_create.build_taup_model(home+project_name+'/structure/bbp_norcal.tvel',output_folder=home+project_name+'/structure/')
    velmod=TauPyModel(model=home+project_name+'/structure/bbp_norcal',verbose=True)
    
    #Moments
    slip=(fault[:,8]**2+fault[:,9]**2)**0.5
    subfault_M0=slip*fault[:,10]*fault[:,11]*fault[:,13]
    subfault_M0=subfault_M0*1e7 #to dyne-cm
    M0=subfault_M0.sum()
    relative_subfault_M0=subfault_M0/M0
    
    #Corner frequency scaling
    i=where(slip>0)[0] #Non-zero faults
    N=len(i) #number of subfaults
    dl=mean((fault[:,10]+fault[:,11])/2) #perdominant length scale
    dl=dl/1000 # to km
    
    # Frankel 95 scaling of corner frequency #verified this looks the same in GP
    # Right now this applies the same factor to all faults
    # Move inside the loop with right dl????
    fc_scale=(M0)/(N*stress_parameter*dl**3*1e21) #Frankel scaling
    
    #Move this inisde loop?
    small_event_M0 = stress_parameter*dl**3*1e21
    
    #Tau=p perturbation
    tau_perturb=0.1
    
    #Loop over stations
    for ksta in range(len(lonlat)):
    
        print '... working on '+component+' component semistochastic waveform for station '+sta[ksta]
    
        #initalize output seismogram
        tr=Trace()
        tr.stats.station=sta[ksta]
        tr.stats.delta=hf_dt
        tr.stats.starttime=time_epi
        hf=zeros(len(t))
        
        #Loop over subfaults
        for kfault in range(len(fault)):
            
            #Include only subfaults with non-zero slip
            if subfault_M0[kfault]>0:
            
                #Get subfault to station distance
                lon_source=fault[kfault,1]
                lat_source=fault[kfault,2]
                azimuth,baz,dist=g.inv(lon_source,lat_source,lonlat[ksta,0],lonlat[ksta,1])
                dist_in_degs=kilometer2degrees(dist/1000.)
                
                #Get rho, alpha, beta at subfault depth
                zs=fault[kfault,3]
                mu,alpha,beta=get_mu(structure,zs,return_speeds=True)
                rho=mu/beta**2
                
                #Get radiation scale factor
                Spartition=1/2**0.5
                if component=='N' :
                    component_angle=0
                elif component=='E':
                    component_angle=90
                
                rho=rho/1000 #to g/cm**3
                beta=(beta/1000)*1e5 #to cm/s
                alpha=(alpha/1000)*1e5
                
                #Verified this produces same value as in GP
                CS=(2*Spartition)/(4*pi*(rho)*(beta**3))
                CP=2/(4*pi*(rho)*(alpha**3))
                
                #Get local subfault rupture speed
                beta=beta/100 #to m/s
                vr=get_local_rupture_speed(zs,beta,rise_time_depths)
                vr=vr/1000 #to km/s
                dip_factor=get_dip_factor(fault[kfault,5],fault[kfault,8],fault[kfault,9])
                
                #Subfault corner frequency
                c0=2.0 #GP2015 value
                fc_subfault=(c0*vr)/(dip_factor*pi*dl)
                
                #get subfault source spectrum
                #S=((relative_subfault_M0[kfault]*M0/N)*f**2)/(1+fc_scale*(f/fc_subfault)**2)
                S=small_event_M0*(omega**2/(1+(f/fc_subfault)**2))
                frankel_conv_operator= fc_scale*((fc_subfault**2+f**2)/(fc_subfault**2+fc_scale*f**2))
                S=S*frankel_conv_operator
                
                #get high frequency decay
                P=exp(-pi*kappa*f)
                
                #get quarter wavelength amplificationf actors
                # pass rho in kg/m^3 (this units nightmare is what I get for following Graves' code)
                I=get_amplification_factors(f,structure,zs,beta,rho*1000)
                
                #Get other geometric parameters necessar for radiation pattern
                strike=fault[kfault,4]
                dip=fault[kfault,5]
                ss=fault[kfault,8]
                ds=fault[kfault,9]
                rake=rad2deg(arctan2(ds,ss))
                
                #Get ray paths for all direct S arrivals
                Ppaths=velmod.get_ray_paths(zs,dist_in_degs,phase_list=['P','p'])
                
                #Get ray paths for all direct S arrivals
                try:
                    Spaths=velmod.get_ray_paths(zs,dist_in_degs,phase_list=['S','s'])
                except:
                    Spaths=velmod.get_ray_paths(zs+tau_perturb,dist_in_degs,phase_list=['S','s'])

                #Get direct s path and moho reflection
                mohoS=None
                directS=Spaths[0]
                directP=Ppaths[0]
                #print len(Spaths)
                if len(Spaths)==1: #only direct S
                    pass
                else:
                    #turn_depth=zeros(len(Spaths)-1) #turning depth of other non-direct rays
                    #for k in range(1,len(Spaths)):
                    #    turn_depth[k-1]=Spaths[k].path['depth'].max()
                    ##If there's a ray that turns within 2km of Moho, callt hat guy the Moho reflection
                    #deltaz=abs(turn_depth-moho_depth_in_km)
                    #i=argmin(deltaz)
                    #if deltaz[i]<2: #Yes, this is a moho reflection
                    #    mohoS=Spaths[i+1]
                    #else:
                    #    mohoS=None
                    mohoS=Spaths[-1]
                     
 
                #######         Build Direct P ray           ######
                if Pwave==True:
                    take_off_angle_P=directP.takeoff_angle
                    
                    #Get attenuation due to geometrical spreading (from the path length)
                    path_length_P=get_path_length(directP,zs,dist_in_degs)
                    path_length_P=path_length_P*100 #to cm
                    
                    #Get effect of intrinsic aptimeenuation for that ray (path integrated)
                    Q_P=get_attenuation(f,structure,directS,Qexp,Qtype='P')
                    
                    #Build the entire path term
                    G_P=(I*Q_P)/path_length_P
    
                    #Get conically averaged radiation pattern terms
                    RP=conically_avg_P_radiation_pattern(strike,dip,rake,azimuth,take_off_angle_P)
                    RP=abs(RP)
                       
                    #Get partition of Pwave into Z and N,E components 
                    incidence_angle=directP.incident_angle
                    Npartition,Epartition,Zpartition=get_P_wave_partition(incidence_angle,azimuth)
                    if component=='Z':
                       Ppartition=Zpartition 
                    elif component=='N':
                        Ppartition=Npartition
                    else:
                        Ppartition=Epartition
                        
                    #And finally multiply everything together to get the subfault amplitude spectrum
                    AP=CP*S*G_P*P*RP*Ppartition           
    
                    #Generate windowed time series
                    duration=1./fc_subfault+0.09*(dist/1000)
                    w=windowed_gaussian(duration,hf_dt,window_type='saragoni_hart')
                    
                    #Go to frequency domain, apply amplitude spectrum and ifft for final time series
                    hf_seis_P=apply_spectrum(w,AP,f,hf_dt)
                    
                    #What time after OT should this time series start at?
                    time_insert=directP.path['time'][-1]+onset_times[kfault]
                    i=argmin(abs(t-time_insert))
                    j=i+len(hf_seis_P)
                    
                    #Add seismogram
                    hf[i:j]=hf[i:j]+hf_seis_P                    
                                               
                                                                      
                                                                                                                    
                              
                #######         Build Direct S ray           ######
                take_off_angle_S=directS.takeoff_angle
                
                #Get attenuation due to geometrical spreading (from the path length)
                path_length_S=get_path_length(directS,zs,dist_in_degs)
                path_length_S=path_length_S*100 #to cm
                
                #Get effect of intrinsic aptimeenuation for that ray (path integrated)
                Q_S=get_attenuation(f,structure,directS,Qexp)
                
                #Build the entire path term
                G_S=(I*Q_S)/path_length_S

                #Get conically averaged radiation pattern terms
                if component=='Z':
                    RP_vert=conically_avg_vert_radiation_pattern(strike,dip,rake,azimuth,take_off_angle_S)
                    #And finally multiply everything together to get the subfault amplitude spectrum
                    AS=CS*S*G_S*P*RP_vert   
                else:
                    RP=conically_avg_radiation_pattern(strike,dip,rake,azimuth,take_off_angle_S,component_angle)
                    RP=abs(RP)
                    #And finally multiply everything together to get the subfault amplitude spectrum
                    AS=CS*S*G_S*P*RP                

                #Generate windowed time series
                duration=1./fc_subfault+0.063*(dist/1000)
                w=windowed_gaussian(duration,hf_dt,window_type='saragoni_hart')
                #w=windowed_gaussian(3*duration,hf_dt,window_type='cua',ptime=Ppaths[0].path['time'][-1],stime=Spaths[0].path['time'][-1])
                
                #Go to frequency domain, apply amplitude spectrum and ifft for final time series
                hf_seis_S=apply_spectrum(w,AS,f,hf_dt)
                
                #What time after OT should this time series start at?
                time_insert=directS.path['time'][-1]+onset_times[kfault]
                #print 'ts = '+str(time_insert)+' , Td = '+str(duration)
                #time_insert=Ppaths[0].path['time'][-1]
                i=argmin(abs(t-time_insert))
                j=i+len(hf_seis_S)
                
                #Add seismogram
                hf[i:j]=hf[i:j]+hf_seis_S
                
                
                #######         Build Moho reflected S ray           ######
    #            if mohoS==None:
    #                pass
    #            else:
    #                if kfault%100==0:
    #                    print '... ... building Moho reflected S wave'
    #                take_off_angle_mS=mohoS.takeoff_angle
    #                
    #                #Get attenuation due to geometrical spreading (from the path length)
    #                path_length_mS=get_path_length(mohoS,zs,dist_in_degs)
    #                path_length_mS=path_length_mS*100 #to cm
    #                
    #                #Get effect of intrinsic aptimeenuation for that ray (path integrated)
    #                Q_mS=get_attenuation(f,structure,mohoS,Qexp)
    #                
    #                #Build the entire path term
    #                G_mS=(I*Q_mS)/path_length_mS
    #
    #                #Get conically averaged radiation pattern terms
    #                if component=='Z':
    #                    RP_vert=conically_avg_vert_radiation_pattern(strike,dip,rake,azimuth,take_off_angle_mS)
    #                    #And finally multiply everything together to get the subfault amplitude spectrum
    #                    A=C*S*G_mS*P*RP_vert   
    #                else:
    #                    RP=conically_avg_radiation_pattern(strike,dip,rake,azimuth,take_off_angle_mS,component_angle)
    #                    RP=abs(RP)
    #                    #And finally multiply everything together to get the subfault amplitude spectrum
    #                    A=C*S*G_mS*P*RP                
    #
    #                #Generate windowed time series
    #                duration=1./fc_subfault+0.063*(dist/1000)
    #                w=windowed_gaussian(duration,hf_dt,window_type='saragoni_hart')
    #                #w=windowed_gaussian(3*duration,hf_dt,window_type='cua',ptime=Ppaths[0].path['time'][-1],stime=Spaths[0].path['time'][-1])
    #                
    #                #Go to frequency domain, apply amplitude spectrum and ifft for final time series
    #                hf_seis=apply_spectrum(w,A,f,hf_dt)
    #                
    #                #What time after OT should this time series start at?
    #                time_insert=mohoS.path['time'][-1]+onset_times[kfault]
    #                #print 'ts = '+str(time_insert)+' , Td = '+str(duration)
    #                #time_insert=Ppaths[0].path['time'][-1]
    #                i=argmin(abs(t-time_insert))
    #                j=i+len(hf_seis)
    #                
    #                #Add seismogram
    #                hf[i:j]=hf[i:j]+hf_seis
    #                
    #                #Done, reset
    #                mohoS=None
                
        #Done add to trace and stream
        tr.data=hf/100 #convert to m/s**2
        st+=tr
    
    return st
Пример #4
0
def run_parallel_hfsims(home,project_name,rupture_name,N,M0,sta,sta_lon,sta_lat,component,model_name,
                        rise_time_depths0,rise_time_depths1,moho_depth_in_km,total_duration,
                        hf_dt,stress_parameter,kappa,Qexp,Pwave,Swave,high_stress_depth,
                        Qmethod,scattering,Qc_exp,baseline_Qc,rank,size): 
    '''
    Run stochastic HF sims
    
    stress parameter is in bars
    '''
    
    from numpy import genfromtxt,pi,logspace,log10,mean,where,exp,arange,zeros,argmin,rad2deg,arctan2,real,savetxt,c_
    from pyproj import Geod
    from obspy.geodetics import kilometer2degrees
    from obspy.taup import TauPyModel
    from mudpy.forward import get_mu, read_fakequakes_hypo_time
    from mudpy import hfsims
    from obspy import Stream,Trace
    from sys import stdout
    from os import path,makedirs
    from mudpy.hfsims import is_subfault_in_smga
    import warnings

    rank=int(rank)
    
    if rank==0 and component=='N':
        #print out what's going on:
        out='''Running with input parameters:
        home = %s
        project_name = %s
        rupture_name = %s
        N = %s
        M0 (N-m) = %s
        sta = %s
        sta_lon = %s
        sta_lat = %s
        model_name = %s
        rise_time_depths = %s
        moho_depth_in_km = %s
        total_duration = %s
        hf_dt = %s
        stress_parameter = %s
        kappa = %s
        Qexp = %s
        component = %s
        Pwave = %s
        Swave = %s
        high_stress_depth = %s
        Qmethod = %s
        scattering = %s
        Qc_exp = %s
        baseline_Qc = %s
        '''%(home,project_name,rupture_name,str(N),str(M0/1e7),sta,str(sta_lon),str(sta_lat),model_name,str([rise_time_depths0,rise_time_depths1]),
        str(moho_depth_in_km),str(total_duration),str(hf_dt),str(stress_parameter),str(kappa),str(Qexp),str(component),str(Pwave),str(Swave),
        str(high_stress_depth),str(Qmethod),str(scattering),str(Qc_exp),str(baseline_Qc))
        print(out)

    if rank==0:
        out='''
        Rupture_Name = %s
        Station = %s
        Component (N,E,Z) = %s
        Sample rate = %sHz
        Duration = %ss
        '''%(rupture_name,sta,component,str(1/hf_dt),str(total_duration))
        print(out)
        
    #print 'stress is '+str(stress_parameter)

    #I don't condone it but this cleans up the warnings
    warnings.filterwarnings("ignore")
    
    
    #Fix input formats:
    rise_time_depths=[rise_time_depths0,rise_time_depths1]
    #Load the source
    mpi_rupt=home+project_name+'/output/ruptures/mpi_rupt.'+str(rank)+'.'+rupture_name
    fault=genfromtxt(mpi_rupt)  
    
    #Onset times for each subfault
    onset_times=fault[:,12]
    
    #load velocity structure
    structure=genfromtxt(home+project_name+'/structure/'+model_name)
    
    #Frequencies vector
    f=logspace(log10(1/total_duration),log10(1/(2*hf_dt))+0.01,100)
    omega=2*pi*f
    
    #Output time vector (0 is origin time)
    t=arange(0,total_duration,hf_dt)
    
    #Projection object for distance calculations
    g=Geod(ellps='WGS84')
    
    #Create taup velocity model object, paste on top of iaspei91
    #taup_create.build_taup_model(home+project_name+'/structure/bbp_norcal.tvel',output_folder=home+project_name+'/structure/')
#    velmod=TauPyModel(model=home+project_name+'/structure/iquique',verbose=True)
    velmod = TauPyModel(model=home+project_name+'/structure/'+model_name.split('.')[0]+'.npz')
    
    #Get epicentral time
    epicenter,time_epi=read_fakequakes_hypo_time(home,project_name,rupture_name)
    
    #Moments
    slip=(fault[:,8]**2+fault[:,9]**2)**0.5
    subfault_M0=slip*fault[:,10]*fault[:,11]*fault[:,13]
    subfault_M0=subfault_M0*1e7 #to dyne-cm
    relative_subfault_M0=subfault_M0/M0
    Mw=(2./3)*(log10(M0*1e-7)-9.1)
    
    #Corner frequency scaling
    i=where(slip>0)[0] #Non-zero faults
    dl=mean((fault[:,10]+fault[:,11])/2) #predominant length scale
    dl=dl/1000 # to km
    
    #Tau=p perturbation
    tau_perturb=0.1
    
    #Deep faults receive a higher stress
    stress_multiplier=1

    #initalize output seismogram
    tr=Trace()
    tr.stats.station=sta
    tr.stats.delta=hf_dt
    tr.stats.starttime=time_epi
    #info for sac header (added at the end)
    az,backaz,dist_m=g.inv(epicenter[0],epicenter[1],sta_lon,sta_lat)
    dist_in_km=dist_m/1000.    
    
    hf=zeros(len(t))
    
    #Loop over subfaults
    for kfault in range(len(fault)):
        if rank==0:
            #Print status to screen            
            if kfault % 25 == 0:
                if kfault==0:
                    stdout.write('      [.')
                    stdout.flush()
                stdout.write('.')
                stdout.flush()
            if kfault==len(fault)-1:
                stdout.write('.]\n')
                stdout.flush()                
        
        #Include only subfaults with non-zero slip
        if subfault_M0[kfault]>0:
            
            #Get subfault to station distance
            lon_source=fault[kfault,1]
            lat_source=fault[kfault,2]
            azimuth,baz,dist=g.inv(lon_source,lat_source,sta_lon,sta_lat)
            dist_in_degs=kilometer2degrees(dist/1000.)
            
            #Source depth?
            z_source=fault[kfault,3]
            
            #No change
            stress=stress_parameter
            
            #Is subfault in an SMGA?
            #SMGA1
#            radius_in_km=15.0
#            smga_center_lon=-71.501
#            smga_center_lat=-30.918
            
            
            #SMGA2
#            radius_in_km=15.0
#            smga_center_lon=-71.863
#            smga_center_lat=-30.759
            
            #smga3
#            radius_in_km=7.5  
#            smga_center_lon=-72.3923
#            smga_center_lat=-30.58
            
            
            #smga4
            # radius_in_km=7.5  
            # smga_center_lon=-72.3923
            # smga_center_lat=-30.61
            
            # in_smga=is_subfault_in_smga(lon_source,lat_source,smga_center_lon,smga_center_lat,radius_in_km)
            
            # ###Apply multiplier?
            # if in_smga==True:
            #     stress=stress_parameter*stress_multiplier
            #     print("%.4f,%.4f is in SMGA, stress is %d" % (lon_source,lat_source,stress))
            # else:
            #     stress=stress_parameter
            
            #Apply multiplier?
            #if slip[kfault]>7.5:
            #    stress=stress_parameter*stress_multiplier
            ##elif lon_source>-72.057 and lon_source<-71.2 and lat_source>-30.28:
            ##    stress=stress_parameter*stress_multiplier
            #else:
            #    stress=stress_parameter
                
            #Apply multiplier?
            #if z_source>high_stress_depth:
            #    stress=stress_parameter*stress_multiplier
            #else:
            #    stress=stress_parameter
            
            # Frankel 95 scaling of corner frequency #verified this looks the same in GP
            # Right now this applies the same factor to all faults
            fc_scale=(M0)/(N*stress*dl**3*1e21) #Frankel scaling
            small_event_M0 = stress*dl**3*1e21
            
        

            
            #Get rho, alpha, beta at subfault depth
            zs=fault[kfault,3]
            mu,alpha,beta=get_mu(structure,zs,return_speeds=True)
            rho=mu/beta**2
            
            #Get radiation scale factor
            Spartition=1/2**0.5
            if component=='N' :
                component_angle=0
            elif component=='E':
                component_angle=90
            
            rho=rho/1000 #to g/cm**3
            beta=(beta/1000)*1e5 #to cm/s
            alpha=(alpha/1000)*1e5
            
            # print('rho = '+str(rho))
            # print('beta = '+str(beta))
            # print('alpha = '+str(alpha))
            
            #Verified this produces same value as in GP
            CS=(2*Spartition)/(4*pi*(rho)*(beta**3))
            CP=2/(4*pi*(rho)*(alpha**3))

            
            #Get local subfault rupture speed
            beta=beta/100 #to m/s
            vr=hfsims.get_local_rupture_speed(zs,beta,rise_time_depths)
            vr=vr/1000 #to km/s
            dip_factor=hfsims.get_dip_factor(fault[kfault,5],fault[kfault,8],fault[kfault,9])
            
            #Subfault corner frequency
            c0=2.0 #GP2015 value
            fc_subfault=(c0*vr)/(dip_factor*pi*dl)
            
            #get subfault source spectrum
            #S=((relative_subfault_M0[kfault]*M0/N)*f**2)/(1+fc_scale*(f/fc_subfault)**2)
            S=small_event_M0*(omega**2/(1+(f/fc_subfault)**2))
            frankel_conv_operator= fc_scale*((fc_subfault**2+f**2)/(fc_subfault**2+fc_scale*f**2))
            S=S*frankel_conv_operator
            
            #get high frequency decay
            P=exp(-pi*kappa*f)
            
            
            #Get other geometric parameters necessar for radiation pattern
            strike=fault[kfault,4]
            dip=fault[kfault,5]
            ss=fault[kfault,8]
            ds=fault[kfault,9]
            rake=rad2deg(arctan2(ds,ss))
            
            #Get ray paths for all direct P arrivals
            Ppaths=velmod.get_ray_paths(zs,dist_in_degs,phase_list=['P','p'])
            
            #Get ray paths for all direct S arrivals
            try:
                Spaths=velmod.get_ray_paths(zs,dist_in_degs,phase_list=['S','s'])
            except:
                Spaths=velmod.get_ray_paths(zs+tau_perturb,dist_in_degs,phase_list=['S','s'])
            
            #sometimes there's no S, weird I know. Check twice.
            if len(Spaths)==0:
                Spaths=velmod.get_ray_paths(zs+tau_perturb,dist_in_degs,phase_list=['S','s'])
            if len(Spaths)==0:
                Spaths=velmod.get_ray_paths(zs+5*tau_perturb,dist_in_degs,phase_list=['S','s'])   
            if len(Spaths)==0:
                Spaths=velmod.get_ray_paths(zs-5*tau_perturb,dist_in_degs,phase_list=['S','s'])
            if len(Spaths)==0:
                Spaths=velmod.get_ray_paths(zs+5*tau_perturb,dist_in_degs,phase_list=['S','s'])  
            if len(Spaths)==0:
                Spaths=velmod.get_ray_paths(zs-10*tau_perturb,dist_in_degs,phase_list=['S','s'])
            if len(Spaths)==0:
                Spaths=velmod.get_ray_paths(zs+10*tau_perturb,dist_in_degs,phase_list=['S','s']) 
            if len(Spaths)==0:
                Spaths=velmod.get_ray_paths(zs-50*tau_perturb,dist_in_degs,phase_list=['S','s'])
            if len(Spaths)==0:
                Spaths=velmod.get_ray_paths(zs+50*tau_perturb,dist_in_degs,phase_list=['S','s']) 
            if len(Spaths)==0:
                Spaths=velmod.get_ray_paths(zs-75*tau_perturb,dist_in_degs,phase_list=['S','s'])
            if len(Spaths)==0:
                Spaths=velmod.get_ray_paths(zs+75*tau_perturb,dist_in_degs,phase_list=['S','s']) 
            if len(Spaths)==0:
                print('ERROR: I give up, no direct S in spite of multiple attempts at subfault '+str(kfault))

            #Which ray should I keep? 
            
            #This is the fastest arriving P
            directP=Ppaths[0]
            
            #Get moho depth from velmod
            moho_depth  = velmod.model.moho_depth
            
            # In this method here are the rules:
            #For S do not allow Moho turning rays, keep the fastest non Moho turning ray. If
            #only Moho rays are available, then keep the one that turns the shallowest.
            if Qmethod == 'no_moho':
            
                #get turning depths and arrival times of S rays
                turning_depths = zeros(len(Spaths))
                S_ray_times = zeros(len(Spaths))
                
                for kray in range(len(Spaths)):
                    turning_depths[kray] = Spaths[kray].path['depth'].max()
                    S_ray_times[kray] = Spaths[kray].path['time'].max()
                    
                #Keep only rays that turn above Moho
                i=where(turning_depths < moho_depth)[0]
                
                if len(i) == 0: #all rays turn below Moho, keep shallowest turning
                    i_min_depth = argmin(turning_depths)
                    directS = Spaths[i_min_depth]
                
                else:  #Keep fastest arriving ray that turns above Moho
                    Spaths = [Spaths[j] for j in i]  #Rays turning above Moho, NOTE: I hate list comprehension
                    S_ray_times = S_ray_times[i]
                    i_min_time = argmin(S_ray_times)
                    directS = Spaths[i_min_time]
                    
            elif Qmethod =='shallowest':
                                
                #get turning depths and arrival times of S rays
                turning_depths = zeros(len(Spaths))
                
                for kray in range(len(Spaths)):
                    turning_depths[kray] = Spaths[kray].path['depth'].max()

                i_min_depth = argmin(turning_depths)
                directS = Spaths[i_min_depth]
                
            elif Qmethod == 'fastest' or Qmethod=='direct':   #Pick first arriving S wave
                
                directS = Spaths[0]
                
                
            
            #directS=Spaths[0]  #this is the old way, kept fastest S
            mohoS=None
            
            # #print len(Spaths)
            # if len(Spaths)==1: #only direct S
            #     pass
            # else:
            #     #turn_depth=zeros(len(Spaths)-1) #turning depth of other non-direct rays
            #     #for k in range(1,len(Spaths)):
            #     #    turn_depth[k-1]=Spaths[k].path['depth'].max()
            #     ##If there's a ray that turns within 2km of Moho, callt hat guy the Moho reflection
            #     #deltaz=abs(turn_depth-moho_depth_in_km)
            #     #i=argmin(deltaz)
            #     #if deltaz[i]<2: #Yes, this is a moho reflection
            #     #    mohoS=Spaths[i+1]
            #     #else:
            #     #    mohoS=None
            #     mohoS=Spaths[-1]
                

                 
 
            #######         Build Direct P ray           ######
            if Pwave==True:
                take_off_angle_P=directP.takeoff_angle
                
                # #Get attenuation due to geometrical spreading (from the path length)
                # path_length_P=hfsims.get_path_length(directP,zs,dist_in_degs)
                # path_length_P=path_length_P*100 #to cm
                
                # #Get effect of intrinsic attenuation for that ray (path integrated)
                # #Q_P=hfsims.get_attenuation(f,structure,directP,Qexp,Qtype='P')   <- This causes problems and I don't know why underlying assumptions might be bad
                # Q_P=hfsims.get_attenuation(f,structure,directS,Qexp,Qtype='S')
                
                # #get quarter wavelength amplificationf actors
                # # pass rho in kg/m^3 (this units nightmare is what I get for following Graves' code)
                # I_P=hfsims.get_amplification_factors(f,structure,zs,alpha,rho*1000)
                
                # #Build the entire path term
                # G_P=(I_P*Q_P)/path_length_P
                
                #Get attenuation due to geometrical spreading (from the path length)
                path_length_S=hfsims.get_path_length(directS,zs,dist_in_degs)
                path_length_S=path_length_S*100 #to cm
                
                #Get effect of intrinsic aptimeenuation for that ray (path integrated)
                Q_S=hfsims.get_attenuation(f,structure,directS,Qexp)
                
                #get quarter wavelength amplificationf actors
                # pass rho in kg/m^3 (this units nightmare is what I get for following Graves' code)
                I_S=hfsims.get_amplification_factors(f,structure,zs,beta,rho*1000)
                
                #Build the entire path term
                # G_S=(I_S*Q_S)/path_length_S
                G_S=(1*Q_S)/path_length_S
                
                

                #Get conically averaged radiation pattern terms
                RP=hfsims.conically_avg_P_radiation_pattern(strike,dip,rake,azimuth,take_off_angle_P)
                RP=abs(RP)
                   
                #Get partition of Pwave into Z and N,E components 
                incidence_angle=directP.incident_angle
                Npartition,Epartition,Zpartition=hfsims.get_P_wave_partition(incidence_angle,azimuth)
                if component=='Z':
                   Ppartition=Zpartition 
                elif component=='N':
                    Ppartition=Npartition
                else:
                    Ppartition=Epartition
                    
                #And finally multiply everything together to get the subfault amplitude spectrum
                AP=CP*S*G_S*P*RP*Ppartition           

                #Generate windowed time series
                duration=1./fc_subfault+0.09*(dist/1000)
                w=hfsims.windowed_gaussian(duration,hf_dt,window_type='saragoni_hart')
                
                #Go to frequency domain, apply amplitude spectrum and ifft for final time series
                hf_seis_P=hfsims.apply_spectrum(w,AP,f,hf_dt)
                
                #save thigns to check
                # if sta=='AL2H':
                #     path_out = '/Users/dmelgarm/FakeQuakes/ONC_debug/analysis/frequency/Pwave/'
                #     path_out = path_out+str(kfault)
                #     # savetxt(path_out+'.all',c_[f,AP])
                #     # savetxt(path_out+'.source',c_[f,CP*S])
                #     # savetxt(path_out+'.path',c_[f,G_P])
                #     # savetxt(path_out+'.site',c_[f,P])
                
                
                #What time after OT should this time series start at?
                time_insert=directP.path['time'][-1]+onset_times[kfault]
                i=argmin(abs(t-time_insert))
                j=i+len(hf_seis_P)
                
                #Check seismogram doesn't go past last sample
                if i<len(hf)-1: #if i (the beginning of the seimogram) is less than the length
                    if j>len(hf): #seismogram goes past total_duration length, trim it
                        len_paste=len(hf)-i
                        j=len(hf)
                        #Add seismogram
                        hf[i:j]=hf[i:j]+real(hf_seis_P[0:len_paste])
                    else: #Lengths are fine
                        hf[i:j]=hf[i:j]+real(hf_seis_P)      
                else: #Seismogram starts after end of available space
                    pass   
                
                                           
                                                                  
                                                                                                                
                          
            #######         Build Direct S ray           ######

            if Swave==True:
                take_off_angle_S=directS.takeoff_angle
                
                #Get attenuation due to geometrical spreading (from the path length)
                path_length_S=hfsims.get_path_length(directS,zs,dist_in_degs)
                path_length_S=path_length_S*100 #to cm
                
                #Get effect of intrinsic aptimeenuation for that ray (path integrated)
                if Qmethod == 'direct':#No ray tracing use bulka ttenuation along path
                    Q_S = hfsims.get_attenuation_linear(f,structure,zs,dist,Qexp,Qtype='S')
                else: #Use ray tracing
                    Q_S=hfsims.get_attenuation(f,structure,directS,Qexp,scattering=scattering,
                                               Qc_exp=Qc_exp,baseline_Qc=baseline_Qc)
                
                #get quarter wavelength amplificationf actors
                # pass rho in kg/m^3 (this units nightmare is what I get for following Graves' code)
                I_S=hfsims.get_amplification_factors(f,structure,zs,beta,rho*1000)
                
                #Build the entire path term
                G_S=(I_S*Q_S)/path_length_S
                # G_S=(1*Q_S)/path_length_S
    
                #Get conically averaged radiation pattern terms
                if component=='Z':
                    RP_vert=hfsims.conically_avg_vert_radiation_pattern(strike,dip,rake,azimuth,take_off_angle_S)
                    #And finally multiply everything together to get the subfault amplitude spectrum
                    AS=CS*S*G_S*P*RP_vert   
                    # print('... RP_vert = '+str(RP_vert))
                else:
                    RP=hfsims.conically_avg_radiation_pattern(strike,dip,rake,azimuth,take_off_angle_S,component_angle)
                    RP=abs(RP)
                    # print('... RP_horiz = '+str(RP))
                    #And finally multiply everything together to get the subfault amplitude spectrum
                    AS=CS*S*G_S*P*RP                
    
                #Generate windowed time series
                duration=1./fc_subfault+0.063*(dist/1000)
                w=hfsims.windowed_gaussian(duration,hf_dt,window_type='saragoni_hart')
                #w=windowed_gaussian(3*duration,hf_dt,window_type='cua',ptime=Ppaths[0].path['time'][-1],stime=Spaths[0].path['time'][-1])
                
                #Go to frequency domain, apply amplitude spectrum and ifft for final time series
                hf_seis_S=hfsims.apply_spectrum(w,AS,f,hf_dt)
                
                #save thigns to check
                # if sta=='AL2H':
                #     path_out = '/Users/dmelgarm/FakeQuakes/ONC_debug/analysis/frequency/Swave/'
                #     path_out = path_out+str(kfault)
                #     # savetxt(path_out+'.soverp',c_[f,(CS*S)/(CP*S)])
                #     savetxt(path_out+'.all',c_[f,AS])
                #     savetxt(path_out+'.source',c_[f,CS*S])
                #     savetxt(path_out+'.path',c_[f,G_S])
                #     savetxt(path_out+'.site',c_[f,P])
                
                #What time after OT should this time series start at?
                time_insert=directS.path['time'][-1]+onset_times[kfault]
                #print 'ts = '+str(time_insert)+' , Td = '+str(duration)
                #time_insert=Ppaths[0].path['time'][-1]
                i=argmin(abs(t-time_insert))
                j=i+len(hf_seis_S)
                
                
                #Check seismogram doesn't go past last sample
                if i<len(hf)-1: #if i (the beginning of the seimogram) is less than the length
                    if j>len(hf): #seismogram goes past total_duration length, trim it
                        len_paste=len(hf)-i
                        j=len(hf)
                        #Add seismogram
                        hf[i:j]=hf[i:j]+real(hf_seis_S[0:len_paste])
                    else: #Lengths are fine
                        hf[i:j]=hf[i:j]+real(hf_seis_S)
                else: #Beginning of seismogram is past end of available space
                    pass

            
            
            #######         Build Moho reflected S ray           ######
#            if mohoS==None:
#                pass
#            else:
#                if kfault%100==0:
#                    print '... ... building Moho reflected S wave'
#                take_off_angle_mS=mohoS.takeoff_angle
#                
#                #Get attenuation due to geometrical spreading (from the path length)
#                path_length_mS=get_path_length(mohoS,zs,dist_in_degs)
#                path_length_mS=path_length_mS*100 #to cm
#                
#                #Get effect of intrinsic aptimeenuation for that ray (path integrated)
#                Q_mS=get_attenuation(f,structure,mohoS,Qexp)
#                
#                #Build the entire path term
#                G_mS=(I*Q_mS)/path_length_mS
#
#                #Get conically averaged radiation pattern terms
#                if component=='Z':
#                    RP_vert=conically_avg_vert_radiation_pattern(strike,dip,rake,azimuth,take_off_angle_mS)
#                    #And finally multiply everything together to get the subfault amplitude spectrum
#                    A=C*S*G_mS*P*RP_vert   
#                else:
#                    RP=conically_avg_radiation_pattern(strike,dip,rake,azimuth,take_off_angle_mS,component_angle)
#                    RP=abs(RP)
#                    #And finally multiply everything together to get the subfault amplitude spectrum
#                    A=C*S*G_mS*P*RP                
#
#                #Generate windowed time series
#                duration=1./fc_subfault+0.063*(dist/1000)
#                w=windowed_gaussian(duration,hf_dt,window_type='saragoni_hart')
#                #w=windowed_gaussian(3*duration,hf_dt,window_type='cua',ptime=Ppaths[0].path['time'][-1],stime=Spaths[0].path['time'][-1])
#                
#                #Go to frequency domain, apply amplitude spectrum and ifft for final time series
#                hf_seis=apply_spectrum(w,A,f,hf_dt)
#                
#                #What time after OT should this time series start at?
#                time_insert=mohoS.path['time'][-1]+onset_times[kfault]
#                #print 'ts = '+str(time_insert)+' , Td = '+str(duration)
#                #time_insert=Ppaths[0].path['time'][-1]
#                i=argmin(abs(t-time_insert))
#                j=i+len(hf_seis)
#                
#                #Add seismogram
#                hf[i:j]=hf[i:j]+hf_seis
#                
#                #Done, reset
#                mohoS=None        
           
    #Done
    tr.data=hf/100 #convert to m/s**2
    #Add station location, event location, and first P-wave arrival time to SAC header
    tr.stats.update({'sac':{'stlo':sta_lon,'stla':sta_lat,'evlo':epicenter[0],'evla':epicenter[1],'evdp':epicenter[2],'dist':dist_in_km,'az':az,'baz':backaz,'mag':Mw}}) #,'idep':"ACC (m/s^2)" not sure why idep won't work
    
    #Write out to file 
    #old
    rupture=rupture_name.split('.')[0]+'.'+rupture_name.split('.')[1]
    #new
    rupture=rupture_name.rsplit('.',1)[0]
    if not path.exists(home+project_name+'/output/waveforms/'+rupture+'/'):
        makedirs(home+project_name+'/output/waveforms/'+rupture+'/')
    if rank < 10:
        tr.write(home+project_name+'/output/waveforms/'+rupture+'/'+sta+'.HN'+component+'.00'+str(rank)+'.sac',format='SAC')
    elif rank < 100:
        tr.write(home+project_name+'/output/waveforms/'+rupture+'/'+sta+'.HN'+component+'.0'+str(rank)+'.sac',format='SAC')
    else:
        tr.write(home+project_name+'/output/waveforms/'+rupture+'/'+sta+'.HN'+component+'.'+str(rank)+'.sac',format='SAC')
Пример #5
0
def run_syn(home,project_name,source,station_file,green_path,model_name,integrate,static,tsunami,
        subfault,time_epi,beta,impulse=False,okada=False,okada_mu=45e9,insar=False):
    '''
    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 string import rjust
    from numpy import array,genfromtxt,loadtxt,savetxt,log10,argmin
    from obspy import read
    from shlex import split
    
    #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
    #Load structure
    model_file=home+project_name+'/structure/'+model_name
    structure=loadtxt(model_file,ndmin=2)
    #Parse the soruce information
    num=rjust(str(int(source[0])),4,'0')
    xs=source[1]
    ys=source[2]
    zs=source[3]
    strike=source[4]
    dip=source[5]
    rise=source[6]
    if impulse==True:  #Impulse GFs or apply rise time
        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
    if static==0 and tsunami==0:  #Where to save dynamic waveforms
        green_path=green_path+'dynamic/'+model_name+"_"+strdepth+".sub"+subfault+"/"
    if static==0 and tsunami==1:  #Where to save dynamic waveforms
        green_path=green_path+'tsunami/'+model_name+"_"+strdepth+".sub"+subfault+"/"
    print("--> Computing synthetics at stations for the source at ("+str(xs)+" , "+str(ys)+")")
    staname=genfromtxt(station_file,dtype="S6",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
    Mw=(2./3)*(log10(Mo)-9.1)
    #Move to output folder
    log='' #Initalize log
    os.chdir(green_path)
    for k in range(len(d)):
        if static==0: #Compute full waveforms
            diststr='%.3f' % d[k] #Need current distance in string form for external call
            #Form the strings to be used for the system calls according to suer desired options
            if integrate==1: #Make displ.
                #First Stike-Slip GFs
                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"
                print commandSS #Output to screen so I know we're underway
                log=log+commandSS+'\n' #Append to log
                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"
                print commandDS
                log=log+commandDS+'\n'
                commandDS=split(commandDS)
            else: #Make vel.
                #First Stike-Slip GFs
                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"
                print commandSS
                log=log+commandSS+'\n'
                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"
                print commandDS
                log=log+commandDS+'\n'
                commandDS=split(commandDS)
            #Run the strike- and dip-slip commands (make system calls)
            p=subprocess.Popen(commandSS,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
            out,err=p.communicate() 
            p=subprocess.Popen(commandDS,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
            out,err=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:
                    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:
                    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:
                    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:
                    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
            os.chdir(green_path+'static/') #Move to appropriate dir
            if okada==False:
                diststr='%.1f' % d[k] #Need current distance in string form for external call
                
                
                if insar==True:
                    green_file=model_name+".static."+strdepth+".sub"+subfault+'.insar' #Output dir
                else: #GPS
                    green_file=model_name+".static."+strdepth+".sub"+subfault+'.gps' #Output dir
                
                
                print green_file
                log=log+green_file+'\n' #Append to log
                statics=loadtxt(green_file) #Load GFs
                #Print static GFs into a pipe and pass into synthetics command
                station_index=argmin(abs(statics[:,0]-d[k])) #Look up by distance
                try:
                    temp_pipe=statics[station_index,:]
                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"
                print staname[k]
                print commandSS
                print commandDS
                log=log+staname[k]+'\n'+commandSS+'\n'+commandDS+'\n' #Append to log
                commandSS=split(commandSS) #Lexical split
                commandDS=split(commandDS)
                #Make system calls, one for DS, one for SS, and save log
                ps=subprocess.Popen(['printf',inpipe],stdout=subprocess.PIPE,stderr=subprocess.PIPE)  #This is the statics pipe, pint stdout to syn's stdin
                p=subprocess.Popen(commandSS,stdin=ps.stdout,stdout=open(staname[k]+'.subfault'+num+'.SS.static.rtz','w'),stderr=subprocess.PIPE)     
                out,err=p.communicate()  
                log=log+str(out)+str(err)
                ps=subprocess.Popen(['printf',inpipe],stdout=subprocess.PIPE,stderr=subprocess.PIPE)  #This is the statics pipe, pint stdout to syn's stdin
                p=subprocess.Popen(commandDS,stdin=ps.stdout,stdout=open(staname[k]+'.subfault'+num+'.DS.static.rtz','w'),stderr=subprocess.PIPE)     
                out,err=p.communicate() 
                log=log+str(out)+str(err)       
                #Rotate radial/transverse to East/North, correct vertical and scale to m
                statics=loadtxt(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(staname[k]+'.subfault'+num+'.SS.static.neu',(n,e,u,beta),header='north(m),east(m),up(m),beta(degs)')
                statics=loadtxt(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(staname[k]+'.subfault'+num+'.DS.static.neu',(n,e,u,beta),header='north(m),east(m),up(m),beta(degs)')
            else:
                #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],okada_mu)
                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],okada_mu)
                savetxt(staname[k]+'.subfault'+num+'.DS.static.neu',(n,e,u,beta),header='north(m),east(m),up(m),beta(degs)')
    return log
Пример #6
0
def stochastic_simulation(home,
                          project_name,
                          rupture_name,
                          sta,
                          sta_lon,
                          sta_lat,
                          component,
                          model_name,
                          rise_time_depths,
                          moho_depth_in_km,
                          total_duration=100,
                          hf_dt=0.01,
                          stress_parameter=50,
                          kappa=0.04,
                          Qexp=0.6,
                          Pwave=False,
                          Swave=True,
                          high_stress_depth=1e4):
    '''
    Run stochastic HF sims
    
    stress parameter is in bars
    '''

    from numpy import genfromtxt, pi, logspace, log10, mean, where, exp, arange, zeros, argmin, rad2deg, arctan2, real
    from pyproj import Geod
    from obspy.geodetics import kilometer2degrees
    from obspy.taup import TauPyModel
    from mudpy.forward import get_mu, write_fakequakes_hf_waveforms_one_by_one, read_fakequakes_hypo_time
    from obspy import Stream, Trace
    from sys import stdout
    import warnings

    #print out what's going on:
    out = '''Running with input parameters:
    home = %s
    project_name = %s
    rupture_name = %s
    sta = %s
    sta_lon = %s
    sta_lat = %s
    model_name = %s
    rise_time_depths = %s
    moho_depth_in_km = %s
    total_duration = %s
    hf_dt = %s
    stress_parameter = %s
    kappa = %s
    Qexp = %s
    component = %s
    Pwave = %s
    Swave = %s
    high_stress_depth = %s
    ''' % (home, project_name, rupture_name, sta, str(sta_lon), str(sta_lat),
           model_name, str(rise_time_depths), str(moho_depth_in_km),
           str(total_duration), str(hf_dt), str(stress_parameter), str(kappa),
           str(Qexp), str(component), str(Pwave), str(Swave),
           str(high_stress_depth))
    print(out)

    #    rupture=rupture_name.split('.')[0]+'.'+rupture_name.split('.')[1]
    #    log=home+project_name+'/output/waveforms/'+rupture+'/'+sta+'.HN'+component+'.1cpu.log'
    #    logfile=open(log,'w')
    #    logfile.write(out)
    #print 'stress is '+str(stress_parameter)

    #I don't condone it but this cleans up the warnings
    warnings.filterwarnings("ignore")

    #Load the source
    fault = genfromtxt(home + project_name + '/output/ruptures/' +
                       rupture_name)

    #Onset times for each subfault
    onset_times = fault[:, 12]

    #load velocity structure
    structure = genfromtxt(home + project_name + '/structure/' + model_name)

    #Frequencies vector
    f = logspace(log10(hf_dt), log10(1 / (2 * hf_dt)) + 0.01, 50)
    omega = 2 * pi * f

    #Output time vector (0 is origin time)
    t = arange(0, total_duration, hf_dt)

    #Projection object for distance calculations
    g = Geod(ellps='WGS84')

    #Create taup velocity model object, paste on top of iaspei91
    #taup_create.build_taup_model(home+project_name+'/structure/bbp_norcal.tvel',output_folder=home+project_name+'/structure/')
    velmod = TauPyModel(model=home + project_name + '/structure/iquique',
                        verbose=True)
    #Get epicentral time
    epicenter, time_epi = read_fakequakes_hypo_time(home, project_name,
                                                    rupture_name)

    #Moments
    slip = (fault[:, 8]**2 + fault[:, 9]**2)**0.5
    subfault_M0 = slip * fault[:, 10] * fault[:, 11] * fault[:, 13]
    subfault_M0 = subfault_M0 * 1e7  #to dyne-cm
    M0 = subfault_M0.sum()
    relative_subfault_M0 = subfault_M0 / M0
    Mw = (2. / 3) * (log10(M0 * 1e-7) - 9.1)

    #Corner frequency scaling
    i = where(slip > 0)[0]  #Non-zero faults
    N = len(i)  #number of subfaults
    dl = mean((fault[:, 10] + fault[:, 11]) / 2)  #predominant length scale
    dl = dl / 1000  # to km

    #Tau=p perturbation
    tau_perturb = 0.1

    #Deep faults receive a higher stress
    stress_multiplier = 3

    print('... working on ' + component +
          ' component semistochastic waveform for station ' + sta)

    #initalize output seismogram
    tr = Trace()
    tr.stats.station = sta
    tr.stats.delta = hf_dt
    tr.stats.starttime = time_epi
    #info for sac header (added at the end)
    az, backaz, dist_m = g.inv(epicenter[0], epicenter[1], sta_lon, sta_lat)
    dist_in_km = dist_m / 1000.

    hf = zeros(len(t))

    #    out='''Parameters before we get into subfault calculations:
    #    rupture_name = %s
    #    epicenter = %s
    #    time_epi = %s
    #    M0 = %E
    #    Mw = %10.4f
    #    Num_Subfaults = %i
    #    dl = %.2f
    #    Dist_in_km = %10.4f
    #    '''%(rupture_name,str(epicenter),str(time_epi),M0,Mw,int(N),dl,dist_in_km)
    #    print out
    #    logfile.write(out)

    #Loop over subfaults
    #    earliestP=1e10  #something outrageously high
    #    earliestP_kfault=1e10
    for kfault in range(len(fault)):

        #Print status to screen
        if kfault % 150 == 0:
            if kfault == 0:
                stdout.write('      [')
                stdout.flush()
            stdout.write('.')
            stdout.flush()
        if kfault == len(fault) - 1:
            stdout.write(']\n')
            stdout.flush()

        #Include only subfaults with non-zero slip
        if subfault_M0[kfault] > 0:

            #Get subfault to station distance
            lon_source = fault[kfault, 1]
            lat_source = fault[kfault, 2]
            azimuth, baz, dist = g.inv(lon_source, lat_source, sta_lon,
                                       sta_lat)
            dist_in_degs = kilometer2degrees(dist / 1000.)

            #Source depth?
            z_source = fault[kfault, 3]

            #No change
            stress = stress_parameter

            #Is subfault in an SMGA?
            #radius_in_km=15.0
            #smga_center_lon=-69.709200
            #smga_center_lat=-19.683600
            #in_smga=is_subfault_in_smga(lon_source,lat_source,smga_center_lon,smga_center_lat,radius_in_km)
            #
            ###Apply multiplier?
            #if in_smga==True:
            #    stress=stress_parameter*stress_multiplier
            #    print "%.4f,%.4f is in SMGA, stress is %d" % (lon_source,lat_source,stress)
            #else:
            #    stress=stress_parameter

            #Apply multiplier?
            #if slip[kfault]>7.5:
            #    stress=stress_parameter*stress_multiplier
            ##elif lon_source>-72.057 and lon_source<-71.2 and lat_source>-30.28:
            ##    stress=stress_parameter*stress_multiplier
            #else:
            #    stress=stress_parameter

            #Apply multiplier?
            #if z_source>high_stress_depth:
            #    stress=stress_parameter*stress_multiplier
            #else:
            #    stress=stress_parameter

            # Frankel 95 scaling of corner frequency #verified this looks the same in GP
            # Right now this applies the same factor to all faults
            fc_scale = (M0) / (N * stress * dl**3 * 1e21)  #Frankel scaling
            small_event_M0 = stress * dl**3 * 1e21

            #Get rho, alpha, beta at subfault depth
            zs = fault[kfault, 3]
            mu, alpha, beta = get_mu(structure, zs, return_speeds=True)
            rho = mu / beta**2

            #Get radiation scale factor
            Spartition = 1 / 2**0.5
            if component == 'N':
                component_angle = 0
            elif component == 'E':
                component_angle = 90

            rho = rho / 1000  #to g/cm**3
            beta = (beta / 1000) * 1e5  #to cm/s
            alpha = (alpha / 1000) * 1e5

            #Verified this produces same value as in GP
            CS = (2 * Spartition) / (4 * pi * (rho) * (beta**3))
            CP = 2 / (4 * pi * (rho) * (alpha**3))

            #Get local subfault rupture speed
            beta = beta / 100  #to m/s
            vr = get_local_rupture_speed(zs, beta, rise_time_depths)
            vr = vr / 1000  #to km/s
            dip_factor = get_dip_factor(fault[kfault, 5], fault[kfault, 8],
                                        fault[kfault, 9])

            #Subfault corner frequency
            c0 = 2.0  #GP2015 value
            fc_subfault = (c0 * vr) / (dip_factor * pi * dl)

            #get subfault source spectrum
            #S=((relative_subfault_M0[kfault]*M0/N)*f**2)/(1+fc_scale*(f/fc_subfault)**2)
            S = small_event_M0 * (omega**2 / (1 + (f / fc_subfault)**2))
            frankel_conv_operator = fc_scale * (
                (fc_subfault**2 + f**2) / (fc_subfault**2 + fc_scale * f**2))
            S = S * frankel_conv_operator

            #get high frequency decay
            P = exp(-pi * kappa * f)

            #            if kfault==0:
            #                out='''Parameters within subfault calculations:
            #                kfault_lon = %10.4f
            #                kfault_lat = %10.4f
            #                CS = %s
            #                CP = %s
            #                S[0] = %s
            #                frankel_conv_operator[0] = %s
            #                '''%(fault[kfault,1],fault[kfault,2],str(CS),str(CP),str(S[0]),str(frankel_conv_operator[0]))
            #                print out
            #                logfile.write(out)

            #Get other geometric parameters necessar for radiation pattern
            strike = fault[kfault, 4]
            dip = fault[kfault, 5]
            ss = fault[kfault, 8]
            ds = fault[kfault, 9]
            rake = rad2deg(arctan2(ds, ss))

            #Get ray paths for all direct P arrivals
            Ppaths = velmod.get_ray_paths(zs,
                                          dist_in_degs,
                                          phase_list=['P', 'p'])

            #Get ray paths for all direct S arrivals
            try:
                Spaths = velmod.get_ray_paths(zs,
                                              dist_in_degs,
                                              phase_list=['S', 's'])
            except:
                Spaths = velmod.get_ray_paths(zs + tau_perturb,
                                              dist_in_degs,
                                              phase_list=['S', 's'])

            #sometimes there's no S, weird I know. Check twice.
            if len(Spaths) == 0:
                Spaths = velmod.get_ray_paths(zs + tau_perturb,
                                              dist_in_degs,
                                              phase_list=['S', 's'])
            if len(Spaths) == 0:
                Spaths = velmod.get_ray_paths(zs + 5 * tau_perturb,
                                              dist_in_degs,
                                              phase_list=['S', 's'])
            if len(Spaths) == 0:
                Spaths = velmod.get_ray_paths(zs - 5 * tau_perturb,
                                              dist_in_degs,
                                              phase_list=['S', 's'])
            if len(Spaths) == 0:
                Spaths = velmod.get_ray_paths(zs + 5 * tau_perturb,
                                              dist_in_degs,
                                              phase_list=['S', 's'])
            if len(Spaths) == 0:
                Spaths = velmod.get_ray_paths(zs - 10 * tau_perturb,
                                              dist_in_degs,
                                              phase_list=['S', 's'])
            if len(Spaths) == 0:
                Spaths = velmod.get_ray_paths(zs + 10 * tau_perturb,
                                              dist_in_degs,
                                              phase_list=['S', 's'])
            if len(Spaths) == 0:
                Spaths = velmod.get_ray_paths(zs - 50 * tau_perturb,
                                              dist_in_degs,
                                              phase_list=['S', 's'])
            if len(Spaths) == 0:
                Spaths = velmod.get_ray_paths(zs + 50 * tau_perturb,
                                              dist_in_degs,
                                              phase_list=['S', 's'])
            if len(Spaths) == 0:
                Spaths = velmod.get_ray_paths(zs - 75 * tau_perturb,
                                              dist_in_degs,
                                              phase_list=['S', 's'])
            if len(Spaths) == 0:
                Spaths = velmod.get_ray_paths(zs + 75 * tau_perturb,
                                              dist_in_degs,
                                              phase_list=['S', 's'])
            if len(Spaths) == 0:
                print(
                    'ERROR: I give up, no direct S in spite of multiple attempts at subfault '
                    + str(kfault))

            #Get direct s path and moho reflection
            mohoS = None
            directS = Spaths[0]
            directP = Ppaths[0]
            #print len(Spaths)
            if len(Spaths) == 1:  #only direct S
                pass
            else:
                #turn_depth=zeros(len(Spaths)-1) #turning depth of other non-direct rays
                #for k in range(1,len(Spaths)):
                #    turn_depth[k-1]=Spaths[k].path['depth'].max()
                ##If there's a ray that turns within 2km of Moho, callt hat guy the Moho reflection
                #deltaz=abs(turn_depth-moho_depth_in_km)
                #i=argmin(deltaz)
                #if deltaz[i]<2: #Yes, this is a moho reflection
                #    mohoS=Spaths[i+1]
                #else:
                #    mohoS=None
                mohoS = Spaths[-1]

            #######         Build Direct P ray           ######
            if Pwave == True:
                take_off_angle_P = directP.takeoff_angle

                #Get attenuation due to geometrical spreading (from the path length)
                path_length_P = get_path_length(directP, zs, dist_in_degs)
                path_length_P = path_length_P * 100  #to cm

                #Get effect of intrinsic attenuation for that ray (path integrated)
                Q_P = get_attenuation(f, structure, directP, Qexp, Qtype='P')

                #get quarter wavelength amplificationf actors
                # pass rho in kg/m^3 (this units nightmare is what I get for following Graves' code)
                I_P = get_amplification_factors(f, structure, zs, alpha,
                                                rho * 1000)

                #Build the entire path term
                G_P = (I_P * Q_P) / path_length_P

                #Get conically averaged radiation pattern terms
                RP = conically_avg_P_radiation_pattern(strike, dip, rake,
                                                       azimuth,
                                                       take_off_angle_P)
                RP = abs(RP)

                #Get partition of Pwave into Z and N,E components
                incidence_angle = directP.incident_angle
                Npartition, Epartition, Zpartition = get_P_wave_partition(
                    incidence_angle, azimuth)
                if component == 'Z':
                    Ppartition = Zpartition
                elif component == 'N':
                    Ppartition = Npartition
                else:
                    Ppartition = Epartition

                #And finally multiply everything together to get the subfault amplitude spectrum
                AP = CP * S * G_P * P * RP * Ppartition

                #Generate windowed time series
                duration = 1. / fc_subfault + 0.09 * (dist / 1000)
                w = windowed_gaussian(duration,
                                      hf_dt,
                                      window_type='saragoni_hart')

                #Go to frequency domain, apply amplitude spectrum and ifft for final time series
                hf_seis_P = apply_spectrum(w, AP, f, hf_dt)

                #What time after OT should this time series start at?
                time_insert = directP.path['time'][-1] + onset_times[kfault]
                #                if directP.time+onset_times[kfault] < earliestP:
                #                    earliestP=directP.time+onset_times[kfault]
                #                    earliestP_kfault=kfault
                i = argmin(abs(t - time_insert))
                j = i + len(hf_seis_P)

                #Check seismogram doesn't go past last sample
                if i < len(
                        hf
                ) - 1:  #if i (the beginning of the seimogram) is less than the length
                    if j > len(
                            hf
                    ):  #seismogram goes past total_duration length, trim it
                        len_paste = len(hf) - i
                        j = len(hf)
                        #Add seismogram
                        hf[i:j] = hf[i:j] + real(hf_seis_P[0:len_paste])
                    else:  #Lengths are fine
                        hf[i:j] = hf[i:j] + real(hf_seis_P)
                else:  #Seismogram starts after end of available space
                    pass

            #######         Build Direct S ray           ######
            if Swave == True:
                take_off_angle_S = directS.takeoff_angle

                #Get attenuation due to geometrical spreading (from the path length)
                path_length_S = get_path_length(directS, zs, dist_in_degs)
                path_length_S = path_length_S * 100  #to cm

                #Get effect of intrinsic aptimeenuation for that ray (path integrated)
                Q_S = get_attenuation(f, structure, directS, Qexp)

                #get quarter wavelength amplificationf actors
                # pass rho in kg/m^3 (this units nightmare is what I get for following Graves' code)
                I_S = get_amplification_factors(f, structure, zs, beta,
                                                rho * 1000)
                #Build the entire path term
                G_S = (I_S * Q_S) / path_length_S

                #Get conically averaged radiation pattern terms
                if component == 'Z':
                    RP_vert = conically_avg_vert_radiation_pattern(
                        strike, dip, rake, azimuth, take_off_angle_S)
                    #And finally multiply everything together to get the subfault amplitude spectrum
                    AS = CS * S * G_S * P * RP_vert
                else:
                    RP = conically_avg_radiation_pattern(
                        strike, dip, rake, azimuth, take_off_angle_S,
                        component_angle)
                    RP = abs(RP)
                    #And finally multiply everything together to get the subfault amplitude spectrum
                    AS = CS * S * G_S * P * RP

                #Generate windowed time series
                duration = 1. / fc_subfault + 0.063 * (dist / 1000)
                w = windowed_gaussian(duration,
                                      hf_dt,
                                      window_type='saragoni_hart')
                #w=windowed_gaussian(3*duration,hf_dt,window_type='cua',ptime=Ppaths[0].path['time'][-1],stime=Spaths[0].path['time'][-1])

                #Go to frequency domain, apply amplitude spectrum and ifft for final time series
                hf_seis_S = apply_spectrum(w, AS, f, hf_dt)

                #What time after OT should this time series start at?
                time_insert = directS.path['time'][-1] + onset_times[kfault]
                #print 'ts = '+str(time_insert)+' , Td = '+str(duration)
                #time_insert=Ppaths[0].path['time'][-1]
                i = argmin(abs(t - time_insert))
                j = i + len(hf_seis_S)

                #Check seismogram doesn't go past last sample
                if i < len(
                        hf
                ) - 1:  #if i (the beginning of the seimogram) is less than the length
                    if j > len(
                            hf
                    ):  #seismogram goes past total_duration length, trim it
                        len_paste = len(hf) - i
                        j = len(hf)
                        #Add seismogram
                        hf[i:j] = hf[i:j] + real(hf_seis_S[0:len_paste])
                    else:  #Lengths are fine
                        hf[i:j] = hf[i:j] + real(hf_seis_S)
                else:  #Beginning of seismogram is past end of available space
                    pass

            #######         Build Moho reflected S ray           ######


#            if mohoS==None:
#                pass
#            else:
#                if kfault%100==0:
#                    print '... ... building Moho reflected S wave'
#                take_off_angle_mS=mohoS.takeoff_angle
#
#                #Get attenuation due to geometrical spreading (from the path length)
#                path_length_mS=get_path_length(mohoS,zs,dist_in_degs)
#                path_length_mS=path_length_mS*100 #to cm
#
#                #Get effect of intrinsic aptimeenuation for that ray (path integrated)
#                Q_mS=get_attenuation(f,structure,mohoS,Qexp)
#
#                #Build the entire path term
#                G_mS=(I*Q_mS)/path_length_mS
#
#                #Get conically averaged radiation pattern terms
#                if component=='Z':
#                    RP_vert=conically_avg_vert_radiation_pattern(strike,dip,rake,azimuth,take_off_angle_mS)
#                    #And finally multiply everything together to get the subfault amplitude spectrum
#                    A=C*S*G_mS*P*RP_vert
#                else:
#                    RP=conically_avg_radiation_pattern(strike,dip,rake,azimuth,take_off_angle_mS,component_angle)
#                    RP=abs(RP)
#                    #And finally multiply everything together to get the subfault amplitude spectrum
#                    A=C*S*G_mS*P*RP
#
#                #Generate windowed time series
#                duration=1./fc_subfault+0.063*(dist/1000)
#                w=windowed_gaussian(duration,hf_dt,window_type='saragoni_hart')
#                #w=windowed_gaussian(3*duration,hf_dt,window_type='cua',ptime=Ppaths[0].path['time'][-1],stime=Spaths[0].path['time'][-1])
#
#                #Go to frequency domain, apply amplitude spectrum and ifft for final time series
#                hf_seis=apply_spectrum(w,A,f,hf_dt)
#
#                #What time after OT should this time series start at?
#                time_insert=mohoS.path['time'][-1]+onset_times[kfault]
#                #print 'ts = '+str(time_insert)+' , Td = '+str(duration)
#                #time_insert=Ppaths[0].path['time'][-1]
#                i=argmin(abs(t-time_insert))
#                j=i+len(hf_seis)
#
#                #Add seismogram
#                hf[i:j]=hf[i:j]+hf_seis
#
#                #Done, reset
#                mohoS=None
#        if kfault==0:
#            out=''' More:
#            fc_scale = %10.4f
#            subfaultM0 = %E
#            mu = %E
#            CS = %E
#            CP = %E
#            vr = %10.4f
#            dip_factor = %10.4f
#            fc_subfault = %10.4f
#            directS = %s
#            directP = %s
#            '''%(fc_scale,subfault_M0[kfault],mu,CS,CP,vr,dip_factor,fc_subfault,str(directS.time),str(directP.time))
#            print out
#            logfile.write(out)
#    logfile.close()
#Done
    tr.data = hf / 100  #convert to m/s**2
    #Add station location, event location, and first P-wave arrival time to SAC header
    tr.stats.update({
        'sac': {
            'stlo': sta_lon,
            'stla': sta_lat,
            'evlo': epicenter[0],
            'evla': epicenter[1],
            'evdp': epicenter[2],
            'dist': dist_in_km,
            'az': az,
            'baz': backaz,
            'mag': Mw
        }
    })  #,'idep':"ACC (m/s^2)" not sure why idep won't work
    #Return trace for writing to file
    #    print "Earliest P wave Comes at " + str(earliestP) + "after OT, from location " + str(fault[earliestP_kfault,1]) + ", " + str(fault[earliestP_kfault,2]) + ", " +str(fault[earliestP_kfault,3])
    return tr
Пример #7
0
def stochastic_simulation(home,project_name,rupture_name,sta,sta_lon,sta_lat,component,model_name,
        rise_time_depths,moho_depth_in_km,total_duration=100,hf_dt=0.01,stress_parameter=50,
        kappa=0.04,Qexp=0.6,Pwave=False,high_stress_depth=1e4): 
    '''
    Run stochastic HF sims
    
    stress parameter is in bars
    '''
    
    from numpy import genfromtxt,pi,logspace,log10,mean,where,exp,arange,zeros,argmin,rad2deg,arctan2,real
    from pyproj import Geod
    from obspy.geodetics import kilometer2degrees
    from obspy.taup import TauPyModel
    from mudpy.forward import get_mu, write_fakequakes_hf_waveforms_one_by_one,read_fakequakes_hypo_time
    from obspy import Stream,Trace
    from sys import stdout
    import warnings


    #print out what's going on:
    out='''Running with input parameters:
    home = %s
    project_name = %s
    rupture_name = %s
    sta = %s
    sta_lon = %s
    sta_lat = %s
    model_name = %s
    rise_time_depths = %s
    moho_depth_in_km = %s
    total_duration = %s
    hf_dt = %s
    stress_parameter = %s
    kappa = %s
    Qexp = %s
    component = %s
    Pwave = %s
    high_stress_depth = %s
    '''%(home,project_name,rupture_name,sta,str(sta_lon),str(sta_lat),model_name,str(rise_time_depths),
    str(moho_depth_in_km),str(total_duration),str(hf_dt),str(stress_parameter),
    str(kappa),str(Qexp),str(component),str(Pwave),str(high_stress_depth))
    print out

#    rupture=rupture_name.split('.')[0]+'.'+rupture_name.split('.')[1]
#    log=home+project_name+'/output/waveforms/'+rupture+'/'+sta+'.HN'+component+'.1cpu.log'
#    logfile=open(log,'w')
#    logfile.write(out)
    #print 'stress is '+str(stress_parameter)

    #I don't condone it but this cleans up the warnings
    warnings.filterwarnings("ignore")
    
    #Load the source
    fault=genfromtxt(home+project_name+'/output/ruptures/'+rupture_name)    
    
    #Onset times for each subfault
    onset_times=fault[:,12]
    
    #load velocity structure
    structure=genfromtxt(home+project_name+'/structure/'+model_name)
    
    #Frequencies vector
    f=logspace(log10(hf_dt),log10(1/(2*hf_dt))+0.01,50)
    omega=2*pi*f
    
    #Output time vector (0 is origin time)
    t=arange(0,total_duration,hf_dt)
    
    #Projection object for distance calculations
    g=Geod(ellps='WGS84')
    
    #Create taup velocity model object, paste on top of iaspei91
    #taup_create.build_taup_model(home+project_name+'/structure/bbp_norcal.tvel',output_folder=home+project_name+'/structure/')
    velmod=TauPyModel(model=home+project_name+'/structure/maule',verbose=True)
    #Get epicentral time
    epicenter,time_epi=read_fakequakes_hypo_time(home,project_name,rupture_name)
    
    #Moments
    slip=(fault[:,8]**2+fault[:,9]**2)**0.5
    subfault_M0=slip*fault[:,10]*fault[:,11]*fault[:,13]
    subfault_M0=subfault_M0*1e7 #to dyne-cm
    M0=subfault_M0.sum()
    relative_subfault_M0=subfault_M0/M0
    Mw=(2./3)*(log10(M0*1e-7)-9.1)
    
    #Corner frequency scaling
    i=where(slip>0)[0] #Non-zero faults
    N=len(i) #number of subfaults
    dl=mean((fault[:,10]+fault[:,11])/2) #predominant length scale
    dl=dl/1000 # to km
    
    #Tau=p perturbation
    tau_perturb=0.1
    
    #Deep faults receive a higher stress
    stress_multiplier=3
         
    print '... working on '+component+' component semistochastic waveform for station '+sta

    #initalize output seismogram
    tr=Trace()
    tr.stats.station=sta
    tr.stats.delta=hf_dt
    tr.stats.starttime=time_epi
    #info for sac header (added at the end)
    az,backaz,dist_m=g.inv(epicenter[0],epicenter[1],sta_lon,sta_lat)
    dist_in_km=dist_m/1000.    
    
    hf=zeros(len(t))
    
#    out='''Parameters before we get into subfault calculations:
#    rupture_name = %s
#    epicenter = %s
#    time_epi = %s
#    M0 = %E
#    Mw = %10.4f
#    Num_Subfaults = %i
#    dl = %.2f
#    Dist_in_km = %10.4f
#    '''%(rupture_name,str(epicenter),str(time_epi),M0,Mw,int(N),dl,dist_in_km)
#    print out
#    logfile.write(out)
    
    #Loop over subfaults
#    earliestP=1e10  #something outrageously high
#    earliestP_kfault=1e10
    for kfault in range(len(fault)):
        
        #Print status to screen            
        if kfault % 150 == 0:
            if kfault==0:
                stdout.write('      [')
                stdout.flush()
            stdout.write('.')
            stdout.flush()
        if kfault==len(fault)-1:
            stdout.write(']\n')
            stdout.flush()                
        
        #Include only subfaults with non-zero slip
        if subfault_M0[kfault]>0:
            
            #Get subfault to station distance
            lon_source=fault[kfault,1]
            lat_source=fault[kfault,2]
            azimuth,baz,dist=g.inv(lon_source,lat_source,sta_lon,sta_lat)
            dist_in_degs=kilometer2degrees(dist/1000.)
            
            #Source depth?
            z_source=fault[kfault,3]
            
            #No change
            stress=stress_parameter
            
            #Is subfault in an SMGA?
            #radius_in_km=15.0
            #smga_center_lon=-69.709200
            #smga_center_lat=-19.683600
            #in_smga=is_subfault_in_smga(lon_source,lat_source,smga_center_lon,smga_center_lat,radius_in_km)
            #
            ###Apply multiplier?
            #if in_smga==True:
            #    stress=stress_parameter*stress_multiplier
            #    print "%.4f,%.4f is in SMGA, stress is %d" % (lon_source,lat_source,stress)
            #else:
            #    stress=stress_parameter
            
            #Apply multiplier?
            #if slip[kfault]>7.5:
            #    stress=stress_parameter*stress_multiplier
            ##elif lon_source>-72.057 and lon_source<-71.2 and lat_source>-30.28:
            ##    stress=stress_parameter*stress_multiplier
            #else:
            #    stress=stress_parameter
                
            #Apply multiplier?
            #if z_source>high_stress_depth:
            #    stress=stress_parameter*stress_multiplier
            #else:
            #    stress=stress_parameter
            
            # Frankel 95 scaling of corner frequency #verified this looks the same in GP
            # Right now this applies the same factor to all faults
            fc_scale=(M0)/(N*stress*dl**3*1e21) #Frankel scaling
            small_event_M0 = stress*dl**3*1e21
            
        

            
            #Get rho, alpha, beta at subfault depth
            zs=fault[kfault,3]
            mu,alpha,beta=get_mu(structure,zs,return_speeds=True)
            rho=mu/beta**2
            
            #Get radiation scale factor
            Spartition=1/2**0.5
            if component=='N' :
                component_angle=0
            elif component=='E':
                component_angle=90
            
            rho=rho/1000 #to g/cm**3
            beta=(beta/1000)*1e5 #to cm/s
            alpha=(alpha/1000)*1e5
            
            #Verified this produces same value as in GP
            CS=(2*Spartition)/(4*pi*(rho)*(beta**3))
            CP=2/(4*pi*(rho)*(alpha**3))
            
            #Get local subfault rupture speed
            beta=beta/100 #to m/s
            vr=get_local_rupture_speed(zs,beta,rise_time_depths)
            vr=vr/1000 #to km/s
            dip_factor=get_dip_factor(fault[kfault,5],fault[kfault,8],fault[kfault,9])
            
            #Subfault corner frequency
            c0=2.0 #GP2015 value
            fc_subfault=(c0*vr)/(dip_factor*pi*dl)
            
            #get subfault source spectrum
            #S=((relative_subfault_M0[kfault]*M0/N)*f**2)/(1+fc_scale*(f/fc_subfault)**2)
            S=small_event_M0*(omega**2/(1+(f/fc_subfault)**2))
            frankel_conv_operator= fc_scale*((fc_subfault**2+f**2)/(fc_subfault**2+fc_scale*f**2))
            S=S*frankel_conv_operator
            
            #get high frequency decay
            P=exp(-pi*kappa*f)
            
            #get quarter wavelength amplificationf actors
            # pass rho in kg/m^3 (this units nightmare is what I get for following Graves' code)
            I=get_amplification_factors(f,structure,zs,beta,rho*1000)
            
#            if kfault==0:
#                out='''Parameters within subfault calculations:
#                kfault_lon = %10.4f
#                kfault_lat = %10.4f
#                CS = %s
#                CP = %s
#                S[0] = %s
#                frankel_conv_operator[0] = %s
#                '''%(fault[kfault,1],fault[kfault,2],str(CS),str(CP),str(S[0]),str(frankel_conv_operator[0]))
#                print out
#                logfile.write(out)
            
            #Get other geometric parameters necessar for radiation pattern
            strike=fault[kfault,4]
            dip=fault[kfault,5]
            ss=fault[kfault,8]
            ds=fault[kfault,9]
            rake=rad2deg(arctan2(ds,ss))
            
            #Get ray paths for all direct P arrivals
            Ppaths=velmod.get_ray_paths(zs,dist_in_degs,phase_list=['P','p'])
            
            #Get ray paths for all direct S arrivals
            try:
                Spaths=velmod.get_ray_paths(zs,dist_in_degs,phase_list=['S','s'])
            except:
                Spaths=velmod.get_ray_paths(zs+tau_perturb,dist_in_degs,phase_list=['S','s'])
                
            #sometimes there's no S, weird I know. Check twice.
            if len(Spaths)==0:
                Spaths=velmod.get_ray_paths(zs+tau_perturb,dist_in_degs,phase_list=['S','s'])
            if len(Spaths)==0:
                Spaths=velmod.get_ray_paths(zs+5*tau_perturb,dist_in_degs,phase_list=['S','s'])   
            if len(Spaths)==0:
                Spaths=velmod.get_ray_paths(zs-5*tau_perturb,dist_in_degs,phase_list=['S','s'])
            if len(Spaths)==0:
                Spaths=velmod.get_ray_paths(zs+5*tau_perturb,dist_in_degs,phase_list=['S','s'])  
            if len(Spaths)==0:
                Spaths=velmod.get_ray_paths(zs-10*tau_perturb,dist_in_degs,phase_list=['S','s'])
            if len(Spaths)==0:
                Spaths=velmod.get_ray_paths(zs+10*tau_perturb,dist_in_degs,phase_list=['S','s']) 
            if len(Spaths)==0:
                Spaths=velmod.get_ray_paths(zs-50*tau_perturb,dist_in_degs,phase_list=['S','s'])
            if len(Spaths)==0:
                Spaths=velmod.get_ray_paths(zs+50*tau_perturb,dist_in_degs,phase_list=['S','s']) 
            if len(Spaths)==0:
                Spaths=velmod.get_ray_paths(zs-75*tau_perturb,dist_in_degs,phase_list=['S','s'])
            if len(Spaths)==0:
                Spaths=velmod.get_ray_paths(zs+75*tau_perturb,dist_in_degs,phase_list=['S','s']) 
            if len(Spaths)==0:
                print 'ERROR: I give up, no direct S in spite of multiple attempts at subfault '+str(kfault)

            #Get direct s path and moho reflection
            mohoS=None
            directS=Spaths[0]
            directP=Ppaths[0]
            #print len(Spaths)
            if len(Spaths)==1: #only direct S
                pass
            else:
                #turn_depth=zeros(len(Spaths)-1) #turning depth of other non-direct rays
                #for k in range(1,len(Spaths)):
                #    turn_depth[k-1]=Spaths[k].path['depth'].max()
                ##If there's a ray that turns within 2km of Moho, callt hat guy the Moho reflection
                #deltaz=abs(turn_depth-moho_depth_in_km)
                #i=argmin(deltaz)
                #if deltaz[i]<2: #Yes, this is a moho reflection
                #    mohoS=Spaths[i+1]
                #else:
                #    mohoS=None
                mohoS=Spaths[-1]
                 
 
            #######         Build Direct P ray           ######
            if Pwave==True:
                take_off_angle_P=directP.takeoff_angle
                
                #Get attenuation due to geometrical spreading (from the path length)
                path_length_P=get_path_length(directP,zs,dist_in_degs)
                path_length_P=path_length_P*100 #to cm
                
                #Get effect of intrinsic attenuation for that ray (path integrated)
                Q_P=get_attenuation(f,structure,directS,Qexp,Qtype='P')
                
                #Build the entire path term
                G_P=(I*Q_P)/path_length_P

                #Get conically averaged radiation pattern terms
                RP=conically_avg_P_radiation_pattern(strike,dip,rake,azimuth,take_off_angle_P)
                RP=abs(RP)
                   
                #Get partition of Pwave into Z and N,E components 
                incidence_angle=directP.incident_angle
                Npartition,Epartition,Zpartition=get_P_wave_partition(incidence_angle,azimuth)
                if component=='Z':
                   Ppartition=Zpartition 
                elif component=='N':
                    Ppartition=Npartition
                else:
                    Ppartition=Epartition
                    
                #And finally multiply everything together to get the subfault amplitude spectrum
                AP=CP*S*G_P*P*RP*Ppartition           

                #Generate windowed time series
                duration=1./fc_subfault+0.09*(dist/1000)
                w=windowed_gaussian(duration,hf_dt,window_type='saragoni_hart')
                
                #Go to frequency domain, apply amplitude spectrum and ifft for final time series
                hf_seis_P=apply_spectrum(w,AP,f,hf_dt)
                
                #What time after OT should this time series start at?
                time_insert=directP.path['time'][-1]+onset_times[kfault]
#                if directP.time+onset_times[kfault] < earliestP:
#                    earliestP=directP.time+onset_times[kfault]
#                    earliestP_kfault=kfault
                i=argmin(abs(t-time_insert))
                j=i+len(hf_seis_P)
                
                #Check seismogram doesn't go past last sample
                if i<len(hf)-1: #if i (the beginning of the seimogram) is less than the length
                    if j>len(hf): #seismogram goes past total_duration length, trim it
                        len_paste=len(hf)-i
                        j=len(hf)
                        #Add seismogram
                        hf[i:j]=hf[i:j]+real(hf_seis_P[0:len_paste])
                    else: #Lengths are fine
                        hf[i:j]=hf[i:j]+real(hf_seis_P)      
                else: #Seismogram starts after end of available space
                    pass   
                
                                           
                                                                  
                                                                                                                
                          
            #######         Build Direct S ray           ######
            take_off_angle_S=directS.takeoff_angle
            
            #Get attenuation due to geometrical spreading (from the path length)
            path_length_S=get_path_length(directS,zs,dist_in_degs)
            path_length_S=path_length_S*100 #to cm
            
            #Get effect of intrinsic aptimeenuation for that ray (path integrated)
            Q_S=get_attenuation(f,structure,directS,Qexp)
            
            #Build the entire path term
            G_S=(I*Q_S)/path_length_S

            #Get conically averaged radiation pattern terms
            if component=='Z':
                RP_vert=conically_avg_vert_radiation_pattern(strike,dip,rake,azimuth,take_off_angle_S)
                #And finally multiply everything together to get the subfault amplitude spectrum
                AS=CS*S*G_S*P*RP_vert   
            else:
                RP=conically_avg_radiation_pattern(strike,dip,rake,azimuth,take_off_angle_S,component_angle)
                RP=abs(RP)
                #And finally multiply everything together to get the subfault amplitude spectrum
                AS=CS*S*G_S*P*RP                

            #Generate windowed time series
            duration=1./fc_subfault+0.063*(dist/1000)
            w=windowed_gaussian(duration,hf_dt,window_type='saragoni_hart')
            #w=windowed_gaussian(3*duration,hf_dt,window_type='cua',ptime=Ppaths[0].path['time'][-1],stime=Spaths[0].path['time'][-1])
            
            #Go to frequency domain, apply amplitude spectrum and ifft for final time series
            hf_seis_S=apply_spectrum(w,AS,f,hf_dt)
            
            #What time after OT should this time series start at?
            time_insert=directS.path['time'][-1]+onset_times[kfault]
            #print 'ts = '+str(time_insert)+' , Td = '+str(duration)
            #time_insert=Ppaths[0].path['time'][-1]
            i=argmin(abs(t-time_insert))
            j=i+len(hf_seis_S)
            
            
            #Check seismogram doesn't go past last sample
            if i<len(hf)-1: #if i (the beginning of the seimogram) is less than the length
                if j>len(hf): #seismogram goes past total_duration length, trim it
                    len_paste=len(hf)-i
                    j=len(hf)
                    #Add seismogram
                    hf[i:j]=hf[i:j]+real(hf_seis_S[0:len_paste])
                else: #Lengths are fine
                    hf[i:j]=hf[i:j]+real(hf_seis_S)
            else: #Beginning of seismogram is past end of available space
                pass
            
            
            #######         Build Moho reflected S ray           ######
#            if mohoS==None:
#                pass
#            else:
#                if kfault%100==0:
#                    print '... ... building Moho reflected S wave'
#                take_off_angle_mS=mohoS.takeoff_angle
#                
#                #Get attenuation due to geometrical spreading (from the path length)
#                path_length_mS=get_path_length(mohoS,zs,dist_in_degs)
#                path_length_mS=path_length_mS*100 #to cm
#                
#                #Get effect of intrinsic aptimeenuation for that ray (path integrated)
#                Q_mS=get_attenuation(f,structure,mohoS,Qexp)
#                
#                #Build the entire path term
#                G_mS=(I*Q_mS)/path_length_mS
#
#                #Get conically averaged radiation pattern terms
#                if component=='Z':
#                    RP_vert=conically_avg_vert_radiation_pattern(strike,dip,rake,azimuth,take_off_angle_mS)
#                    #And finally multiply everything together to get the subfault amplitude spectrum
#                    A=C*S*G_mS*P*RP_vert   
#                else:
#                    RP=conically_avg_radiation_pattern(strike,dip,rake,azimuth,take_off_angle_mS,component_angle)
#                    RP=abs(RP)
#                    #And finally multiply everything together to get the subfault amplitude spectrum
#                    A=C*S*G_mS*P*RP                
#
#                #Generate windowed time series
#                duration=1./fc_subfault+0.063*(dist/1000)
#                w=windowed_gaussian(duration,hf_dt,window_type='saragoni_hart')
#                #w=windowed_gaussian(3*duration,hf_dt,window_type='cua',ptime=Ppaths[0].path['time'][-1],stime=Spaths[0].path['time'][-1])
#                
#                #Go to frequency domain, apply amplitude spectrum and ifft for final time series
#                hf_seis=apply_spectrum(w,A,f,hf_dt)
#                
#                #What time after OT should this time series start at?
#                time_insert=mohoS.path['time'][-1]+onset_times[kfault]
#                #print 'ts = '+str(time_insert)+' , Td = '+str(duration)
#                #time_insert=Ppaths[0].path['time'][-1]
#                i=argmin(abs(t-time_insert))
#                j=i+len(hf_seis)
#                
#                #Add seismogram
#                hf[i:j]=hf[i:j]+hf_seis
#                
#                #Done, reset
#                mohoS=None        
#        if kfault==0:
#            out=''' More:
#            fc_scale = %10.4f
#            subfaultM0 = %E
#            mu = %E
#            CS = %E
#            CP = %E
#            vr = %10.4f
#            dip_factor = %10.4f
#            fc_subfault = %10.4f
#            directS = %s
#            directP = %s
#            '''%(fc_scale,subfault_M0[kfault],mu,CS,CP,vr,dip_factor,fc_subfault,str(directS.time),str(directP.time))
#            print out
#            logfile.write(out)
#    logfile.close()
    #Done
    tr.data=hf/100 #convert to m/s**2
    #Add station location, event location, and first P-wave arrival time to SAC header
    tr.stats.update({'sac':{'stlo':sta_lon,'stla':sta_lat,'evlo':epicenter[0],'evla':epicenter[1],'evdp':epicenter[2],'dist':dist_in_km,'az':az,'baz':backaz,'mag':Mw}}) #,'idep':"ACC (m/s^2)" not sure why idep won't work
    #Return trace for writing to file    
#    print "Earliest P wave Comes at " + str(earliestP) + "after OT, from location " + str(fault[earliestP_kfault,1]) + ", " + str(fault[earliestP_kfault,2]) + ", " +str(fault[earliestP_kfault,3])
    return tr
Пример #8
0
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)')
Пример #9
0
#means
mux = Dstrike.max() / 2
muy = Ddip.max() / 2

#Make slip
slip = exp(-((Dstrike - mux)**2 / sigmax + (Ddip - muy)**2 / sigmay))

#Get moment of the thing                          GLOBALS                             ########
home = '/Users/dmelgar/Slip_inv/'
project_name = 'Amatrice_3Dfitsgeol_final1'
fault_name = 'norcia_east.fault'
model_name = 'aci.mod'
mod = loadtxt(home + project_name + '/structure/' + model_name, ndmin=2)
mu = zeros(len(slip))
for k in range(len(slip)):
    mu[k] = forward.get_mu(mod, f[k, 3])

A = f[:, -1]**2
#Compute moments
try:
    M0 = mu * A * slip[:, 0]
except:
    M0 = mu * A * slip
#Total up and copute magnitude
M0 = M0.sum()
Mw = (2. / 3) * (log10(M0) - 9.1)

print 'Moment before scaling is ' + str(M0)

#Scale
scale = M0 / (7.32 * 10**17)
Пример #10
0
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)
Пример #11
0
def run_parallel_synthetics(home,project_name,station_file,model_name,integrate,static,tsunami,time_epi,
                beta,custom_stf,rank,size):
    '''
    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 string import rjust
    from numpy import array,genfromtxt,loadtxt,savetxt,log10
    from obspy import read
    from shlex import split
    from mudpy.green import src2sta,rt2ne,origin_time
    from glob import glob
    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
        ''' %(home,project_name,station_file,model_name,str(integrate),str(static),str(tsunami),str(time_epi),beta,custom_stf)
        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
    #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=rjust(str(int(source[0])),4,'0')
        zs=source[3]
        strike=source[4]
        dip=source[5]
        rise=source[6]
        duration=source[7]
        ss_length=source[8]
        ds_length=source[9]
        strdepth='%.4f' % zs
        subfault=rjust(str(int(source[0])),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==0 and tsunami==1:  #Where to save dynamic waveforms
            green_path=home+project_name+'/GFs/tsunami/'+model_name+"_"+strdepth+".sub"+subfault+"/"
        if static==1:  #Where to save dynamic waveforms
            green_path=home+project_name+'/GFs/static/'
        staname=genfromtxt(station_file,dtype="S6",usecols=0)
        if staname.shape==(): #Single staiton file
            staname=array([staname])
        #Compute distances and azmuths
        d,az=src2sta(station_file,source)
        #Get moment corresponding to 1 meter of slip on subfault
        mu=get_mu(structure,zs)
        Mo=mu*ss_length*ds_length*1
        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='%.3f' % d[k] #Need current distance in string form for external call
                #Form the strings to be used for the system calls according to suer 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:
                        #print "Using custom STF "+custom_stf
                        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:
                        #print "Using custom STF "+custom_stf
                        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')
                    #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')
                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')
                    #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')
            else: #Compute static synthetics
                temp_pipe=[]
                diststr='%.1f' % d[k] #Need current distance in string form for external call
                green_file=model_name+".static."+strdepth+".sub"+subfault #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(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(staname[k]+'.subfault'+num+'.DS.static.rtz','w'))     
                p.communicate()       
                #Rotate radial/transverse to East/North, correct vertical and scale to m
                statics=loadtxt(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(staname[k]+'.subfault'+num+'.SS.static.neu',(n,e,u,beta))
                statics=loadtxt(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(staname[k]+'.subfault'+num+'.DS.static.neu',(n,e,u,beta),header='north(m),east(m),up(m),beta(degs)')