def _setup_fault_source(): """ Builds a fault source using the PEER Bending Fault case. """ point_order_dipping_east = [ Point(-64.78365, -0.45236), Point(-64.80164, -0.45236), Point(-64.90498, -0.36564), Point(-65.0000, -0.16188), Point(-65.0000, 0.0000) ] trace_dip_east = Line(point_order_dipping_east) fault_surface1 = SimpleFaultSurface.from_fault_data( trace_dip_east, 0.0, 12.0, 60., 1.0) # Activity Rates # cm per km2 area = 60. * 12.0 / np.sin(np.radians(60.)) cm2perkm2 = (100. * 1000.)**2. mo1 = 3.0E11 * 0.2 * (area * cm2perkm2) mo_m6p75 = 10.0**(16.05 + 1.5 * 6.75) rate1 = mo1 / mo_m6p75 mfd1 = EvenlyDiscretizedMFD(6.75, 0.01, [rate1]) tom = PoissonTOM(1.0) aspect = 2.0 rake = 90.0 src = SimpleFaultSource("PEER_FLT_EAST", "PEER Bending Fault Dipping East", "Active Shallow Crust", mfd1, 1.0, PeerMSR(), 2.0, tom, 0.0, 12.0, trace_dip_east, 60.0, rake) src.num_ruptures = src.count_ruptures() return src
def test(self): sitecol = SiteCollection([Site(Point(-65.13490, 0.0), vs30=760., z1pt0=48.0, z2pt5=0.607, vs30measured=True)]) mfd = ArbitraryMFD([6.0], [0.01604252]) trace = Line([Point(-65.0000, -0.11240), Point(-65.000, 0.11240)]) # 1.0 km Mesh Spacing mesh_spacing = 1.0 msr = PeerMSR() sources = [SimpleFaultSource("001", "PEER Fault Set 2.5", "Active Shallow Crust", mfd, mesh_spacing, msr, 2.0, PoissonTOM(1.0), 0.0, 12., trace, 90., 0.)] imtls = {"PGA": [0.001, 0.01, 0.05, 0.1, 0.2, 0.4, 0.6, 0.8, 1.0, 1.25, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 6.0, 7.0]} gmpe = ChiouYoungs2014PEER() gmpe.mixture_model = {"factors": [0.8, 1.2], "weights": [0.5, 0.5]} hcm = calc_hazard_curves(sources, sitecol, imtls, {"Active Shallow Crust": gmpe}) # Match against the benchmark is not exact - but differences in the # log space should be on the order of less than 0.04% expected = numpy.array([-4.140470001, -4.140913368, -4.259457496, -4.724733842, -5.900747959, -7.734816415, -9.019329629, -10.03864778, -10.90333404, -11.83885783, -12.65826442, -14.05429951, -15.22535996, -16.23988897, -17.94685518, -19.36079032, -20.57460101, -21.64201335]) expected = numpy.around(expected, 5) hcm_lnpga = numpy.around(numpy.log(hcm["PGA"].flatten()), 5) perc_diff = 100.0 * ((hcm_lnpga / expected) - 1.0) numpy.testing.assert_allclose(perc_diff, numpy.zeros(len(perc_diff)), atol=0.04)
def test_case_5(self): # only mfd differs from case 2 sources = [SimpleFaultSource(source_id='fault1', name='fault1', tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST, mfd=test_data.SET1_CASE5_MFD, rupture_mesh_spacing=1.0, magnitude_scaling_relationship=PeerMSR(), rupture_aspect_ratio=test_data.SET1_RUPTURE_ASPECT_RATIO, temporal_occurrence_model=PoissonTOM(1.), upper_seismogenic_depth=test_data.SET1_CASE1TO9_UPPER_SEISMOGENIC_DEPTH, lower_seismogenic_depth=test_data.SET1_CASE1TO9_LOWER_SEISMOGENIC_DEPTH, fault_trace=test_data.SET1_CASE1TO9_FAULT_TRACE, dip=test_data.SET1_CASE1TO9_DIP, rake=test_data.SET1_CASE1TO9_RAKE )] sites = SiteCollection([ test_data.SET1_CASE1TO9_SITE1, test_data.SET1_CASE1TO9_SITE2, test_data.SET1_CASE1TO9_SITE3, test_data.SET1_CASE1TO9_SITE4, test_data.SET1_CASE1TO9_SITE5, test_data.SET1_CASE1TO9_SITE6, test_data.SET1_CASE1TO9_SITE7 ]) gsims = {const.TRT.ACTIVE_SHALLOW_CRUST: SadighEtAl1997()} truncation_level = 0 imts = {str(test_data.IMT): test_data.SET1_CASE5_IMLS} curves = calc_hazard_curves( sources, sites, imts, gsims, truncation_level) s1hc, s2hc, s3hc, s4hc, s5hc, s6hc, s7hc = curves[str(test_data.IMT)] assert_hazard_curve_is(self, s1hc, test_data.SET1_CASE5_SITE1_POES, atol=1e-3, rtol=1e-5) assert_hazard_curve_is(self, s2hc, test_data.SET1_CASE5_SITE2_POES, atol=1e-3, rtol=1e-5) assert_hazard_curve_is(self, s3hc, test_data.SET1_CASE5_SITE3_POES, atol=1e-3, rtol=1e-5) assert_hazard_curve_is(self, s4hc, test_data.SET1_CASE5_SITE4_POES, atol=1e-3, rtol=1e-5) assert_hazard_curve_is(self, s5hc, test_data.SET1_CASE5_SITE5_POES, atol=1e-3, rtol=1e-5) assert_hazard_curve_is(self, s6hc, test_data.SET1_CASE5_SITE6_POES, atol=1e-3, rtol=1e-5) assert_hazard_curve_is(self, s7hc, test_data.SET1_CASE5_SITE7_POES, atol=1e-3, rtol=1e-5)
def setUp(self): """ """ mspa = 2.5 # # Simple fault source mfd = EvenlyDiscretizedMFD(6.0, 0.1, [1.]) msr = WC1994() tom = PoissonTOM(1.0) trace = Line([Point(10, 45.), Point(10., 45.2)]) sfs = SimpleFaultSource(source_id='1', name='1', tectonic_region_type='none', mfd=mfd, rupture_mesh_spacing=mspa, magnitude_scaling_relationship=msr, rupture_aspect_ratio=1.0, temporal_occurrence_model=tom, upper_seismogenic_depth=0., lower_seismogenic_depth=10., fault_trace=trace, dip=90., rake=90) self.srcs = [sfs] # # mfd = EvenlyDiscretizedMFD(6.0, 0.1, [1.]) msr = WC1994() tom = PoissonTOM(1.0) trace = Line([Point(10.2, 45.), Point(10.2, 45.2)]) sfs = SimpleFaultSource(source_id='2', name='2', tectonic_region_type='none', mfd=mfd, rupture_mesh_spacing=mspa, magnitude_scaling_relationship=msr, rupture_aspect_ratio=1.0, temporal_occurrence_model=tom, upper_seismogenic_depth=0., lower_seismogenic_depth=10., fault_trace=trace, dip=90., rake=90) self.srcs.append(sfs) # # mfd = EvenlyDiscretizedMFD(6.0, 0.1, [1.]) msr = WC1994() tom = PoissonTOM(1.0) trace = Line([Point(10.4, 45.), Point(10.4, 45.2)]) sfs = SimpleFaultSource(source_id='3', name='3', tectonic_region_type='none', mfd=mfd, rupture_mesh_spacing=mspa, magnitude_scaling_relationship=msr, rupture_aspect_ratio=1.0, temporal_occurrence_model=tom, upper_seismogenic_depth=0., lower_seismogenic_depth=10., fault_trace=trace, dip=90., rake=90) self.srcs.append(sfs) # # mfd = EvenlyDiscretizedMFD(6.0, 0.1, [1.]) msr = WC1994() tom = PoissonTOM(1.0) trace = Line([Point(10.5, 45.), Point(10.6, 45.2)]) sfs = SimpleFaultSource(source_id='4', name='4', tectonic_region_type='none', mfd=mfd, rupture_mesh_spacing=mspa, magnitude_scaling_relationship=msr, rupture_aspect_ratio=1.0, temporal_occurrence_model=tom, upper_seismogenic_depth=0., lower_seismogenic_depth=10., fault_trace=trace, dip=90., rake=90) self.srcs.append(sfs)
def get_fault_sources(filename, slip_rate_class, bin_width=0.1, m_low=6.5, b_gr=1.0, rupture_mesh_spacing=2.0, upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, msr=WC1994(), rupture_aspect_ratio=2.0, temporal_occurrence_model=PoissonTOM(1.0), aseismic_coeff=0.9, oqsource=False): """ :parameter filename: The name of the .geojson file with fault data :parameter slip_rate_class: TODO: so far works only for slip_rate_class = "suggested/preferred" """ logging.info('Reading %s and slip_type = %s' % (filename, slip_rate_class)) with open(filename, 'r') as data_file: data = json.load(data_file) print('---------------------------------------' '---------------------------------------') # Configuration parameters to create the sources # TODO: # use b_gr values from the area_sources and not a generic value # to test the whole processing # LOOP over the faults/traces srcl = [] for idf, feature in enumerate(data['features']): source_id = '{0:d}'.format(idf) tectonic_region_type = TRT.ACTIVE_SHALLOW_CRUST fs_name = '' ns_name = '' # get fault name[s] - id if feature['properties']['fs_name'] is not None: fs_name = feature['properties']['fs_name'] if feature['properties']['fs_name'] is not None: ns_name = feature['properties']['fs_name'] name = '{0:s} | {1:s}'.format(fs_name, ns_name) if 'ogc_fid' in feature['properties']: id_fault = feature['properties']['ogc_fid'] else: id_fault = '%d' % (idf) # get fault slip type if feature['properties']['slip_type'] is not None: slipt = feature['properties']['slip_type'] msg = 'Slip type value is [%s] for fault with name' % slipt msg += '%s and id %s' % (name, id_fault) logging.info(msg) else: msg = 'Slip type value is missing for fault with name' msg += '%s and id %s' % (name, id_fault) logging.warning(msg) # get dip direction if feature['properties']['ns_dip_dir'] is not None: dip_dir = feature['properties']['ns_dip_dir'] print("'dip_dir'= ", dip_dir) else: msg = 'Dip direction value is missing for fault with name' msg += '%s and id %s' % (name, id_fault) logging.warning(msg) # JUST FOR TESTING REASONS dip_dir = "N" print("dip_dir fazzula= ", dip_dir) # continue # Get the tuples dipt = get_tples(feature['properties']['ns_average_dip']) print("dipt= ", dipt) raket = get_tples(feature['properties']['ns_average_rake']) print("raket= ", raket) sliprt = get_tples(feature['properties']['ns_net_slip_rate']) print("sliprt= ", sliprt) shor_rd = get_tples(feature['properties']['ns_shortening_rate']) print("shortening_rate= ", shor_rd) vert_rd = get_tples(feature['properties']['ns_vert_slip_rate']) print("vertical_slip_rate= ", vert_rd) stk_rd = get_tples(feature['properties']['ns_strike_slip_rate']) print("strike_slip_rate= ", stk_rd) # Set the value to be used [suggested, min, max] if slip_rate_class is 'suggested': valid_dip = False # Dip values dip = dipt[0] if dip is not None: valid_dip = _is_valid_dip(dip) if valid_dip: print("Dip value = ", dip) msg = 'Dip value is [%s] for fault with name' % (dip) msg += '%s and id %s' % (name, id_fault) logging.info(msg) # if dip is None, but slip_type is available elif (dip) is None and (slipt) is not None: dip = get_dip_from_slip_type(slipt) print('Dip value for id= %s is missing and was computed using ' 'slipt= %s, new dip= %s ' % (id_fault, slipt, dip)) # if dip is None, but slip_type is available elif (dip) is None and (slipt) is None: msg = ('Dip value is missing and could not be computed for' ' fault with name ') msg += '%s and id %s' % (name, id_fault) logging.warning(msg) continue valid_rake = False # Rake values rake = raket[0] if rake is not None: valid_rake = _is_valid_rake(rake) if valid_rake: print("Rake value = ", dip) msg = 'Rake value is [%s] for fault with name' % rake msg += '%s and id %s' % (name, id_fault) logging.info(msg) # if rake is None, but slip_type is available elif (rake) is None and (slipt) is not None: rake = get_rake_from_rup_type(RAKE_CLASS, slipt) print('Rake value for id= %s is missing and was computed using' ' slipt= %s, new rake= %s ' % (id_fault, slipt, rake)) msg = ('Rake value is [%s] for slip_type= %s for fault with' ' name' % (rake, slipt)) msg += '%s and id %s' % (name, id_fault) logging.info(msg) # if rake and slip_type are not available elif (rake) is None and (slipt) is None: msg = ('Rake value is missing or could not be computed for' ' fault with name ') msg += '%s and id %s' % (name, id_fault) logging.warning(msg) continue # Slip rate values [shortening, vertical, strike_slip, net_slip] # If net_slip value is not available, a value is computed when # other component are present in the database slipr = sliprt[0] shor_rv = shor_rd[0] stk_rv = stk_rd[0] vert_rv = vert_rd[0] msg = ('slipr= %s, shor_rv= %s , stk_rv= %s, vert_rv= %s for' ' fault with name ' % (slipr, shor_rv, stk_rv, vert_rv)) msg += '%s and id %s' % (name, id_fault) logging.info(msg) if (slipr) is None and (shor_rv, stk_rv, vert_rv): print('slipr= %s' % slipr) print('shor_rv= %s , stk_rv= %s, vert_rv= %s ' % (shor_rv, stk_rv, vert_rv)) slipr = get_net_slip(dip, rake, shor_rv, stk_rv, vert_rv) if slipr is None: msg = 'net_slip value is missing or can not be computed' msg += 'for fault with name %s and id %s' % (name, id_fault) logging.warning(msg) continue # Finally the net_slip is penalized using the aseismic_coeff net_slip = aseismic_coeff * float(slipr) print('net_slip value for id= %s is net_slip= %s [slipr = %s] ' % (id_fault, net_slip, slipt)) msg = ('net_slip value [%.2f] computed for fault with name ' % (net_slip)) msg += ' %s and id %s' % (name, id_fault) logging.info(msg) elif slip_rate_class is 'min': # Dip values dip = dipt[1] if (dip) is None and (slipt): # MN: get_dip_from_slip_dir UNDEFINED, probably the # method name is changed dip = get_dip_from_slip_dir(slipt) print('Dip value for id= %s is missing and was computed using' ' slipt= %s, new dip= %s ' % (id_fault, slipt, dip)) else: msg = 'Dip value is missing for fault with name ' msg += '%s and id %s' % (name, id_fault) logging.warning(msg) # continue # Rake values rake = raket[1] if (rake) is None and (slipt): rake = get_rake_from_rup_type(RAKE_CLASS, slipt) print('Rake value for id= %s is missing and was computed using' ' slipt= %s, new rake= %s ' % (id_fault, slipt, rake)) else: msg = 'Rake value is missing for fault with name ' msg += '%s and id %s' % (name, id_fault) logging.warning(msg) # continue # Slip rate values [shortening, vertical, strike_slip, net_slip] # If net_slip value is not available, a value is computed when # other component are present in the database slipr = sliprt[1] shor_rd = shor_rv[1] stk_rd = stk_rv[1] vert_rv = vert_rd[1] if (slipr) is None and (shor_rv, stk_rv, vert_rv): slipr = get_net_slip(shor_rv, stk_rv, vert_rv) else: msg = 'net_slip value is missing or not can be computed' msg += 'for fault with name %s and id %s' % (name, id_fault) logging.warning(msg) continue # Finally the net_slip is penalized using the aseismic_coeff net_slip = aseismic_coeff * float(slipr) elif slip_rate_class is 'max': # Dip values dip = dipt[2] if (dip) is None and (slipt): # MN: get_dip_from_slip_dir undefined dip = get_dip_from_slip_dir(slipt) print('Dip value for id= %s is missing and was computed using ' 'slipt= %s, new dip= %s ' % (id_fault, slipt, dip)) else: msg = 'Dip value is missing for fault with name ' msg += '%s and id %s' % (name, id_fault) logging.warning(msg) # continue # Rake values rake = raket[2] if (rake) is None and (slipt): rake = get_rake_from_rup_type(RAKE_CLASS, slipt) print('Rake value for id= %s is missing and was computed ' 'using slipt= %s, new rake= %s ' % (id_fault, slipt, rake)) else: msg = 'Rake value is missing for fault with name ' msg += '%s and id %s' % (name, id_fault) logging.warning(msg) # continue # Slip rate values [shortening, vertical, strike_slip, net_slip] # If net_slip value is not available, a value is computed when # other component are present in the database slipr = sliprt[2] shor_rd = shor_rv[2] stk_rd = stk_rv[2] vert_rv = vert_rd[0] if (slipr) is None and (shor_rv, stk_rv, vert_rv): slipr = get_net_slip(shor_rv, stk_rv, vert_rv) else: msg = 'net_slip value is missing or not can be computed' msg += 'for fault with name %s and id %s' % (name, id_fault) logging.warning(msg) continue # Finally the net_slip is penalized using the aseismic_coeff net_slip = aseismic_coeff * float(slipr) else: raise ValueError('Invalid slip_rate_class') # Get fault trace geometry fault_trace = get_line(numpy.array(feature['geometry']['coordinates'])) # Get dip direction angle from literal and strike from trace geometry mean_az_from_trace = _get_mean_az_from_trace(fault_trace) valid_az = False valid_az = _is_valid_strike(mean_az_from_trace) if valid_az: # print("Mean azimuth value from trace = ", mean_az_from_trace) msg = ('Mean azimuth value is [%s] for fault with name' % (mean_az_from_trace)) msg += '%s and id %s' % (name, id_fault) logging.info(msg) dip_dir_angle = _get_dip_dir_from_literal(dip_dir) # Check if it's necessary to revert the fault trace if (dip_dir_angle is not None and _need_to_revert(mean_az_from_trace, dip_dir_angle)): new_fault_trace = _revert_fault_trace(fault_trace) logging.info('The fault trace for id= %s was reverted' % id_fault) else: new_fault_trace = fault_trace if new_fault_trace: fault_trace = new_fault_trace # Get L from srl - See Table 5 of Leonard 2010 # SRL: surface rupture length [km] # RLD: Subsurface horizontal rupture length [km] # IF SRL/RLD < 5. km the fault will be exclused srl = fault_trace.get_length() rld = 10**((numpy.log10(srl) + 0.275) / 1.1) if rld < 5.0: msg = 'SRL/RLD value is < 5.0 km for fault with name ' msg += '%s and id %s' % (name, id_fault) logging.warning(msg) continue # Witdh width, cl = get_width_from_length(rld, slipt) # print("id=, %s, srl=, %.2f, rld=, %.2f, width=, %.2f, # slipt=, %s, cl=,%s "%(id_fault, srl, rld, width, slipt,cl)) msg = ("id=, %s, srl=, %.2f, rld=, %.2f, width=, %.2f, slipt=, %s," " cl=,%s " % (id_fault, srl, rld, width, slipt, cl)) logging.info(msg) # Get lower seismogenic depth from length lsd = width * numpy.sin(numpy.radians(float(dip))) lower_seismogenic_depth = lsd # create the surface from fault data sfce = SimpleFaultSurface.from_fault_data(fault_trace, upper_seismogenic_depth, lower_seismogenic_depth, dip, rupture_mesh_spacing) # compute the area of the surface area = sfce.get_area() # compute the Mmax m_upp = msr.get_median_mag(sfce.get_area(), rake) if m_upp < m_low: msg = 'Mx [%.2f] is lesser than Mmin [%.2f] for fault with name '\ % (m_upp, m_low) msg += '%s and id %s' % (name, id_fault) logging.warning(msg) tstr = '%3s - %-40s %5.2f' % (id_fault, name, m_upp) logging.info(tstr) if net_slip is not None: slip_rate = net_slip print("slip_rate= ", slip_rate) else: continue # constrainig the computation # Mx > Mmin=m_low # slip_rate >= 1e-10 if slip_rate is not None and slip_rate >= 1e-10 and m_upp > m_low: # compute rates rates = rates_for_double_truncated_mfd(area, slip_rate, m_low, m_upp, b_gr, bin_width) # MFD mfd = EvenlyDiscretizedMFD(m_low + bin_width / 2, bin_width, rates) # Source if oqsource: src = SimpleFaultSource( source_id, name, tectonic_region_type, mfd, rupture_mesh_spacing, msr, rupture_aspect_ratio, temporal_occurrence_model, upper_seismogenic_depth, lower_seismogenic_depth, fault_trace, dip, rake) else: src = OQtSource(source_id, source_type='SimpleFaultSource') src.name = name src.tectonic_region_type = tectonic_region_type src.mfd = mfd src.rupture_mesh_spacing = rupture_mesh_spacing src.slip_rate = slip_rate src.msr = msr src.rupture_aspect_ratio = rupture_aspect_ratio src.temporal_occurrence_model = temporal_occurrence_model src.upper_seismogenic_depth = upper_seismogenic_depth src.lower_seismogenic_depth = lower_seismogenic_depth src.trace = fault_trace src.dip = dip src.rake = rake print('right') srcl.append(src) return srcl
def test_case_2(self): sources = [ SimpleFaultSource( source_id='fault1', name='fault1', tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST, mfd=test_data.SET1_CASE2_MFD, rupture_mesh_spacing=1.0, magnitude_scaling_relationship=PeerMSR(), rupture_aspect_ratio=test_data.SET1_RUPTURE_ASPECT_RATIO, upper_seismogenic_depth=test_data. SET1_CASE1TO9_UPPER_SEISMOGENIC_DEPTH, lower_seismogenic_depth=test_data. SET1_CASE1TO9_LOWER_SEISMOGENIC_DEPTH, fault_trace=test_data.SET1_CASE1TO9_FAULT_TRACE, dip=test_data.SET1_CASE1TO9_DIP, rake=test_data.SET1_CASE1TO9_RAKE) ] sites = SiteCollection([ test_data.SET1_CASE1TO9_SITE1, test_data.SET1_CASE1TO9_SITE2, test_data.SET1_CASE1TO9_SITE3, test_data.SET1_CASE1TO9_SITE4, test_data.SET1_CASE1TO9_SITE5, test_data.SET1_CASE1TO9_SITE6, test_data.SET1_CASE1TO9_SITE7 ]) gsims = {const.TRT.ACTIVE_SHALLOW_CRUST: SadighEtAl1997()} truncation_level = 0 time_span = 1.0 imts = {test_data.IMT: test_data.SET1_CASE2_IMLS} curves = hazard_curves(sources, sites, imts, time_span, gsims, truncation_level) s1hc, s2hc, s3hc, s4hc, s5hc, s6hc, s7hc = curves[test_data.IMT] assert_hazard_curve_is(self, s1hc, test_data.SET1_CASE2_SITE1_POES, tolerance=3e-3) assert_hazard_curve_is(self, s2hc, test_data.SET1_CASE2_SITE2_POES, tolerance=2e-5) assert_hazard_curve_is(self, s3hc, test_data.SET1_CASE2_SITE3_POES, tolerance=2e-5) assert_hazard_curve_is(self, s4hc, test_data.SET1_CASE2_SITE4_POES, tolerance=1e-3) assert_hazard_curve_is(self, s5hc, test_data.SET1_CASE2_SITE5_POES, tolerance=1e-3) assert_hazard_curve_is(self, s6hc, test_data.SET1_CASE2_SITE6_POES, tolerance=1e-3) assert_hazard_curve_is(self, s7hc, test_data.SET1_CASE2_SITE7_POES, tolerance=2e-5)