Ejemplo n.º 1
0
def run_parallel_generate_ruptures(
        home, project_name, run_name, fault_name, slab_name, mesh_name,
        load_distances, distances_name, UTM_zone, tMw, model_name, hurst, Ldip,
        Lstrike, num_modes, Nrealizations, rake, buffer_factor,
        rise_time_depths0, rise_time_depths1, time_epi, max_slip,
        source_time_function, lognormal, slip_standard_deviation, scaling_law,
        ncpus, force_magnitude, force_area, mean_slip_name, hypocenter,
        slip_tol, force_hypocenter, no_random, shypo, use_hypo_fraction,
        shear_wave_fraction, max_slip_rule, rank, size):
    '''
    Depending on user selected flags parse the work out to different functions
    '''

    from numpy import load, save, genfromtxt, log10, cos, sin, deg2rad, savetxt, zeros, where
    from time import gmtime, strftime
    from numpy.random import shuffle
    from mudpy import fakequakes
    from obspy import UTCDateTime
    from obspy.taup import TauPyModel
    import warnings

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

    # Fix input formats
    rank = int(rank)
    size = int(size)
    if time_epi == 'None':
        time_epi = None
    else:
        time_epi = UTCDateTime(time_epi)
    rise_time_depths = [rise_time_depths0, rise_time_depths1]
    #hypocenter=[hypocenter_lon,hypocenter_lat,hypocenter_dep]
    tMw = tMw.split(',')
    target_Mw = zeros(len(tMw))
    for rMw in range(len(tMw)):
        target_Mw[rMw] = float(tMw[rMw])

    #Should I calculate or load the distances?
    if load_distances == 1:
        Dstrike = load(home + project_name + '/data/distances/' +
                       distances_name + '.strike.npy')
        Ddip = load(home + project_name + '/data/distances/' + distances_name +
                    '.dip.npy')
    else:
        Dstrike, Ddip = fakequakes.subfault_distances_3D(
            home, project_name, fault_name, slab_name, UTM_zone)
        save(
            home + project_name + '/data/distances/' + distances_name +
            '.strike.npy', Dstrike)
        save(
            home + project_name + '/data/distances/' + distances_name +
            '.dip.npy', Ddip)

    #Read fault and prepare output variable
    whole_fault = genfromtxt(home + project_name + '/data/model_info/' +
                             fault_name)

    #Get structure model
    vel_mod_file = home + project_name + '/structure/' + model_name

    #Get TauPyModel
    velmod = TauPyModel(model=home + project_name + '/structure/' +
                        model_name.split('.')[0])

    #Now loop over the number of realizations
    realization = 0
    if rank == 0:
        print('Generating rupture scenarios')
    for kmag in range(len(target_Mw)):
        if rank == 0:
            print('... Calculating ruptures for target magnitude Mw = ' +
                  str(target_Mw[kmag]))
        for kfault in range(Nrealizations):
            if kfault % 1 == 0 and rank == 0:
                print('... ... working on ruptures ' +
                      str(ncpus * realization) + ' to ' +
                      str(ncpus * (realization + 1) - 1) + ' of ' +
                      str(Nrealizations * size * len(target_Mw)))
                #print '... ... working on ruptures '+str(ncpus*realization+rank)+' of '+str(Nrealizations*size-1)

            #Prepare output
            fault_out = zeros((len(whole_fault), 14))
            fault_out[:, 0:8] = whole_fault[:, 0:8]
            fault_out[:, 10:12] = whole_fault[:, 8:]

            #Sucess criterion
            success = False
            while success == False:
                #Select only a subset of the faults based on magnitude scaling
                current_target_Mw = target_Mw[kmag]
                ifaults, hypo_fault, Lmax, Wmax, Leff, Weff = fakequakes.select_faults(
                    whole_fault,
                    Dstrike,
                    Ddip,
                    current_target_Mw,
                    buffer_factor,
                    num_modes,
                    scaling_law,
                    force_area,
                    no_shallow_epi=False,
                    no_random=no_random,
                    subfault_hypocenter=shypo,
                    use_hypo_fraction=use_hypo_fraction)
                fault_array = whole_fault[ifaults, :]
                Dstrike_selected = Dstrike[ifaults, :][:, ifaults]
                Ddip_selected = Ddip[ifaults, :][:, ifaults]

                #Determine correlation lengths from effective length.width Leff and Weff
                if Lstrike == 'auto':  #Use scaling
                    #Ls=10**(-2.43+0.49*target_Mw)
                    Ls = 2.0 + (1. / 3) * Leff
                elif Lstrike == 'MH2019':
                    Ls = 17.7 + 0.34 * Leff
                else:
                    Ls = Lstrike
                if Ldip == 'auto':  #Use scaling
                    #Ld=10**(-1.79+0.38*target_Mw)
                    Ld = 1.0 + (1. / 3) * Weff
                elif Ldip == 'MH2019':
                    Ld = 6.8 + 0.4 * Weff
                else:
                    Ld = Ldip

                #Get the mean uniform slip for the target magnitude
                if mean_slip_name == None:
                    mean_slip, mu = fakequakes.get_mean_slip(
                        target_Mw[kmag], fault_array, vel_mod_file)
                else:
                    foo, mu = fakequakes.get_mean_slip(target_Mw[kmag],
                                                       fault_array,
                                                       vel_mod_file)
                    mean_fault = genfromtxt(mean_slip_name)
                    mean_slip = (mean_fault[:, 8]**2 +
                                 mean_fault[:, 9]**2)**0.5

                    #keep onlt faults that have man slip inside the fault_array seelcted faults
                    mean_slip = mean_slip[ifaults]

                    #get the area in those selected faults
                    area = fault_array[:, -2] * fault_array[:, -1]

                    #get the moment in those selected faults
                    moment_on_selected = (area * mu * mean_slip).sum()

                    #target moment
                    target_moment = 10**(1.5 * target_Mw[kmag] + 9.1)

                    #How much do I need to upscale?
                    scale_factor = target_moment / moment_on_selected

                    #rescale the slip
                    mean_slip = mean_slip * scale_factor

                    #Make sure mean_slip has no zero slip faults
                    izero = where(mean_slip == 0)[0]
                    mean_slip[izero] = slip_tol

                #Get correlation matrix
                C = fakequakes.vonKarman_correlation(Dstrike_selected,
                                                     Ddip_selected, Ls, Ld,
                                                     hurst)

                # Lognormal or not?
                if lognormal == False:
                    #Get covariance matrix
                    C_nonlog = fakequakes.get_covariance(
                        mean_slip, C, target_Mw[kmag], fault_array,
                        vel_mod_file, slip_standard_deviation)
                    #Get eigen values and eigenvectors
                    eigenvals, V = fakequakes.get_eigen(C_nonlog)
                    #Generate fake slip pattern
                    rejected = True
                    while rejected == True:
                        #                        slip_unrectified,success=make_KL_slip(fault_array,num_modes,eigenvals,V,mean_slip,max_slip,lognormal=False,seed=kfault)
                        slip_unrectified, success = fakequakes.make_KL_slip(
                            fault_array,
                            num_modes,
                            eigenvals,
                            V,
                            mean_slip,
                            max_slip,
                            lognormal=False,
                            seed=None)
                        slip, rejected, percent_negative = fakequakes.rectify_slip(
                            slip_unrectified, percent_reject=13)
                        if rejected == True:
                            print(
                                '... ... ... negative slip threshold exceeeded with %d%% negative slip. Recomputing...'
                                % (percent_negative))
                else:
                    #Get lognormal values
                    C_log, mean_slip_log = fakequakes.get_lognormal(
                        mean_slip, C, target_Mw[kmag], fault_array,
                        vel_mod_file, slip_standard_deviation)
                    #Get eigen values and eigenvectors
                    eigenvals, V = fakequakes.get_eigen(C_log)
                    #Generate fake slip pattern
                    #                    slip,success=make_KL_slip(fault_array,num_modes,eigenvals,V,mean_slip_log,max_slip,lognormal=True,seed=kfault)
                    slip, success = fakequakes.make_KL_slip(fault_array,
                                                            num_modes,
                                                            eigenvals,
                                                            V,
                                                            mean_slip_log,
                                                            max_slip,
                                                            lognormal=True,
                                                            seed=None)

                #Slip pattern sucessfully made, moving on.
                #Rigidities
                foo, mu = fakequakes.get_mean_slip(target_Mw[kmag],
                                                   whole_fault, vel_mod_file)
                fault_out[:, 13] = mu

                #Calculate moment and magnitude of fake slip pattern
                M0 = sum(slip * fault_out[ifaults, 10] *
                         fault_out[ifaults, 11] * mu[ifaults])
                Mw = (2. / 3) * (log10(M0) - 9.1)

                #Check max_slip_rule
                if max_slip_rule == True:

                    max_slip_from_rule = 10**(-4.94 + 0.71 * Mw
                                              )  #From Allen & Hayes, 2017
                    max_slip_tolerance = 3

                    if slip.max() > max_slip_tolerance * max_slip_from_rule:
                        success = False
                        print(
                            '... ... ... max slip condition violated max_slip_rule, recalculating...'
                        )

                #Force to target magnitude
                if force_magnitude == True:
                    M0_target = 10**(1.5 * target_Mw[kmag] + 9.1)
                    M0_ratio = M0_target / M0
                    #Multiply slip by ratio
                    slip = slip * M0_ratio
                    #Recalculate
                    M0 = sum(slip * fault_out[ifaults, 10] *
                             fault_out[ifaults, 11] * mu[ifaults])
                    Mw = (2. / 3) * (log10(M0) - 9.1)

                #check max_slip again
                if slip.max() > max_slip:
                    success = False
                    print(
                        '... ... ... max slip condition violated due to force_magnitude=True, recalculating...'
                    )

            #Get stochastic rake vector
            stoc_rake = fakequakes.get_stochastic_rake(rake, len(slip))

            #Place slip values in output variable
            fault_out[ifaults, 8] = slip * cos(deg2rad(stoc_rake))
            fault_out[ifaults, 9] = slip * sin(deg2rad(stoc_rake))

            #Move hypocenter to somewhere with a susbtantial fraction of peak slip
            #            slip_fraction=0.25
            #            islip=where(slip>slip.max()*slip_fraction)[0]
            #            shuffle(islip) #randomize
            #            hypo_fault=ifaults[islip[0]] #select first from randomized vector

            #Calculate and scale rise times
            rise_times = fakequakes.get_rise_times(M0, slip, fault_array,
                                                   rise_time_depths, stoc_rake)

            #Place rise_times in output variable
            fault_out[:, 7] = 0
            fault_out[ifaults, 7] = rise_times

            #Calculate rupture onset times
            if force_hypocenter == False:  #Use random hypo, otehrwise force hypo to user specified
                hypocenter = whole_fault[hypo_fault, 1:4]

            t_onset = fakequakes.get_rupture_onset(home, project_name, slip,
                                                   fault_array, model_name,
                                                   hypocenter,
                                                   rise_time_depths, M0,
                                                   velmod)
            fault_out[:, 12] = 0
            fault_out[ifaults, 12] = t_onset

            #Calculate location of moment centroid
            centroid_lon, centroid_lat, centroid_z = fakequakes.get_centroid(
                fault_out)

            #Write to file
            run_number = str(ncpus * realization + rank).rjust(6, '0')
            outfile = home + project_name + '/output/ruptures/' + run_name + '.' + run_number + '.rupt'
            savetxt(
                outfile,
                fault_out,
                fmt=
                '%d\t%10.6f\t%10.6f\t%8.4f\t%7.2f\t%7.2f\t%4.1f\t%5.2f\t%5.2f\t%5.2f\t%10.2f\t%10.2f\t%5.2f\t%.6e',
                header=
                'No,lon,lat,z(km),strike,dip,rise,dura,ss-slip(m),ds-slip(m),ss_len(m),ds_len(m),rupt_time(s),rigidity(Pa)'
            )

            #Write log file
            logfile = home + project_name + '/output/ruptures/' + run_name + '.' + run_number + '.log'
            f = open(logfile, 'w')
            f.write('Scenario calculated at ' +
                    strftime("%Y-%m-%d %H:%M:%S", gmtime()) + ' GMT\n')
            f.write('Project name: ' + project_name + '\n')
            f.write('Run name: ' + run_name + '\n')
            f.write('Run number: ' + run_number + '\n')
            f.write('Velocity model: ' + model_name + '\n')
            f.write('No. of KL modes: ' + str(num_modes) + '\n')
            f.write('Hurst exponent: ' + str(hurst) + '\n')
            f.write('Corr. length used Lstrike: %.2f km\n' % Ls)
            f.write('Corr. length used Ldip: %.2f km\n' % Ld)
            f.write('Slip std. dev.: %.3f km\n' % slip_standard_deviation)
            f.write('Maximum length Lmax: %.2f km\n' % Lmax)
            f.write('Maximum width Wmax: %.2f km\n' % Wmax)
            f.write('Effective length Leff: %.2f km\n' % Leff)
            f.write('Effective width Weff: %.2f km\n' % Weff)
            f.write('Target magnitude: Mw %.4f\n' % target_Mw[kmag])
            f.write('Actual magnitude: Mw %.4f\n' % Mw)
            f.write('Hypocenter (lon,lat,z[km]): (%.6f,%.6f,%.2f)\n' %
                    (hypocenter[0], hypocenter[1], hypocenter[2]))
            f.write('Hypocenter time: %s\n' % time_epi)
            f.write('Centroid (lon,lat,z[km]): (%.6f,%.6f,%.2f)\n' %
                    (centroid_lon, centroid_lat, centroid_z))
            f.write('Source time function type: %s' % source_time_function)
            f.close()

            realization += 1
Ejemplo n.º 2
0
from numpy import genfromtxt,deg2rad,cos,sin,savetxt
from mudpy import fakequakes as fq

f=genfromtxt(u'/Users/dmelgar/Coquimbo2015/coquimbo_FQ_3km.rupt')
fmoment=genfromtxt('/Volumes/Illapel/FQ/illapel/output/ruptures/illapel.000000.rupt',usecols=13)
fout=u'/Users/dmelgar/Coquimbo2015/coquimbo_FQ_3km_stoc.0000.rupt'
home='/Volumes/Illapel/FQ/'
project_name='illapel'
run_name='illapel'
model_name='maule.mod' 
hypocenter=[-71.654,-31.570,29.8]

#Get stochastic rake vector
stoc_rake=fq.get_stochastic_rake(90,len(f))

slip=f[:,9]
Mw=8.3
M0=10**(1.5*Mw+9.1)
rise_times=fq.get_rise_times(M0,slip,f,[5,8],stoc_rake)
t_onset=fq.get_rupture_onset(home,project_name,slip,f,model_name,hypocenter,[5,8],M0)

f[:,8]=slip*cos(deg2rad(stoc_rake))
f[:,9]=slip*sin(deg2rad(stoc_rake))
f[:,7]=rise_times
f[:,12]=t_onset
f[:,13]=fmoment

#   1	-72.5799	-30.0132	7.8040	3.19	6.65	0.50	5.00	0.00	5.59	2692.58	2692.58	0.00	0.00
savetxt(fout,f,fmt='%i\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f\t%.4e\t')
Ejemplo n.º 3
0
    M0 = sum(slip * fault_array[:, 10] * fault_array[:, 11] * mu)
    velmod = TauPyModel(model=home + project_name + '/structure/' +
                        model_name.split('.')[0])

    f = open(r, 'r')
    header = f.readline().rstrip('\n')

    # Create empty array to store new onset times in
    # new_onset = np.array([])

    new_onset = fakequakes.get_rupture_onset(
        home,
        project_name,
        slip,
        fault_array,
        model_name,
        hypocenter,
        rise_time_depths,
        M0,
        velmod,
        sigma_rise_time=0.2,
        shear_wave_fraction_shallow=shear_wave_fraction_shallow)

    # Change rupt_time column to be new rupture onset times
    fault_array[:, 12] = new_onset

    # Save new .rupt file
    rupt_name = r.split('/')[-1]
    np.savetxt(f'{rupt_dir}/{rupt_name}',
               fault_array,
               delimiter='\t',
               header=header,