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
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')
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,