def test_rupture_close_to_south_pole(self): # data taken from real example and causing "surface's angles are not # right" error mfd = EvenlyDiscretizedMFD(min_mag=5., bin_width=0.1, occurrence_rates=[2.180e-07]) nodal_plane_dist = PMF([(1., NodalPlane(135., 20., 90.))]) src = PointSource(source_id='1', name='pnt', tectonic_region_type='asc', mfd=mfd, rupture_mesh_spacing=1, magnitude_scaling_relationship=WC1994(), rupture_aspect_ratio=1., temporal_occurrence_model=PoissonTOM(50.), upper_seismogenic_depth=0, lower_seismogenic_depth=26, location=Point(-165.125, -83.600), nodal_plane_distribution=nodal_plane_dist, hypocenter_distribution=PMF([(1., 9.)])) ruptures = list(src.iter_ruptures()) self.assertEqual(len(ruptures), 1)
def test(self): d = os.path.dirname(os.path.dirname(__file__)) source_model = os.path.join(d, 'source_model/multi-point-source.xml') groups = nrml.to_python( source_model, SourceConverter(investigation_time=50., rupture_mesh_spacing=2.)) site = Site(Point(0.1, 0.1), 800, z1pt0=100., z2pt5=1.) sitecol = SiteCollection([site]) imtls = DictArray({'PGA': [0.01, 0.02, 0.04, 0.08, 0.16]}) gsim_by_trt = {'Stable Continental Crust': Campbell2003()} hcurves = calc_hazard_curves(groups, sitecol, imtls, gsim_by_trt) expected = [ 9.999978e-01, 9.084040e-01, 1.489753e-01, 3.690966e-03, 2.763261e-05 ] npt.assert_allclose(hcurves['PGA'][0], expected, rtol=3E-4) # splitting in point sources [[mps1, mps2]] = groups psources = list(mps1) + list(mps2) hcurves = calc_hazard_curves(psources, sitecol, imtls, gsim_by_trt) npt.assert_allclose(hcurves['PGA'][0], expected, rtol=3E-4)
def _test_ruptures(self, expected_ruptures, source): ruptures = list(source.iter_ruptures()) for rupture in ruptures: self.assertIsInstance(rupture, ParametricProbabilisticRupture) self.assertIs(rupture.temporal_occurrence_model, self.TOM) self.assertIs(rupture.tectonic_region_type, self.TRT) self.assertEqual(rupture.rake, self.RAKE) self.assertEqual(len(expected_ruptures), source.count_ruptures()) for i in range(len(expected_ruptures)): expected_rupture, rupture = expected_ruptures[i], ruptures[i] self.assertAlmostEqual(rupture.mag, expected_rupture['mag']) self.assertAlmostEqual(rupture.rake, expected_rupture['rake']) self.assertAlmostEqual(rupture.occurrence_rate, expected_rupture['occurrence_rate']) assert_mesh_is(self, rupture.surface, expected_rupture['surface']) self.assertEqual(rupture.hypocenter, Point(*expected_rupture['hypocenter'])) assert_angles_equal(self, rupture.surface.get_strike(), expected_rupture['strike'], delta=0.5) assert_angles_equal(self, rupture.surface.get_dip(), expected_rupture['dip'], delta=3)
def _iter_ruptures_at_location(self, temporal_occurrence_model, location, rate_scaling_factor=1): """ The common part of :meth: `openquake.hazardlib.source.point.Point.iter_ruptures` shared between point source and :class:`~openquake.hazardlib.source.area.AreaSource`. :param temporal_occurrence_model: The same object as given to :meth: `openquake.hazardlib.source.base.BaseSeismicSource.iter_ruptures`. :param location: A :class:`~openquake.hazardlib.geo.point.Point` object representing the hypocenter location. In case of :class:`PointSource` it is the one provided to constructor, and for area source the location points are taken from polygon discretization. :param rate_scaling_factor: Positive float number to multiply occurrence rates by. It is used by area source to scale the occurrence rates with respect to number of locations. Point sources use no scaling (``rate_scaling_factor = 1``). """ assert 0 < rate_scaling_factor, rate_scaling_factor for mag, mag_occ_rate in self.get_annual_occurrence_rates(): for np_prob, np in self.nodal_plane_distribution.data: for hc_prob, hc_depth in self.hypocenter_distribution.data: hypocenter = Point(latitude=location.latitude, longitude=location.longitude, depth=hc_depth) occurrence_rate = (mag_occ_rate * np_prob * hc_prob * rate_scaling_factor) surface = self._get_rupture_surface(mag, np, hypocenter) yield ParametricProbabilisticRupture( mag, np.rake, self.tectonic_region_type, hypocenter, surface, occurrence_rate, self.temporal_occurrence_model)
def get_hypo_location(self, mesh_spacing, hypo_loc=None): """ The method determines the location of the hypocentre within the rupture :param mesh: :class:`~openquake.hazardlib.geo.mesh.Mesh` of points :param mesh_spacing: The desired distance between two adjacent points in source's ruptures' mesh, in km. Mainly this parameter allows to balance the trade-off between time needed to compute the distance between the rupture surface and a site and the precision of that computation. :param hypo_loc: Hypocentre location as fraction of rupture plane, as a tuple of (Along Strike, Down Dip), e.g. a hypocentre located in the centroid of the rupture would be input as (0.5, 0.5), whereas a hypocentre located in a position 3/4 along the length, and 1/4 of the way down dip of the rupture plane would be entered as (0.75, 0.25). :returns: Hypocentre location as instance of :class:`~openquake.hazardlib.geo.point.Point` """ mesh = self.mesh centroid = mesh.get_middle_point() if hypo_loc is None: return centroid total_len_y = (len(mesh.depths) - 1) * mesh_spacing y_distance = hypo_loc[1] * total_len_y y_node = int(numpy.round(y_distance / mesh_spacing)) total_len_x = (len(mesh.lons[y_node]) - 1) * mesh_spacing x_distance = hypo_loc[0] * total_len_x x_node = int(numpy.round(x_distance / mesh_spacing)) hypocentre = Point(mesh.lons[y_node][x_node], mesh.lats[y_node][x_node], mesh.depths[y_node][x_node]) return hypocentre
def iter_ruptures(self, hcdist=True, npdist=True): """ Generate one rupture for each combination of magnitude, nodal plane and hypocenter depth. """ for mag, mag_occ_rate in self.get_annual_occurrence_rates(): for np_prob, np in self.nodal_plane_distribution.data: for hc_prob, hc_depth in self.hypocenter_distribution.data: hypocenter = Point(latitude=self.location.latitude, longitude=self.location.longitude, depth=hc_depth) occurrence_rate = (mag_occ_rate * (np_prob if npdist else 1) * (hc_prob if hcdist else 1)) surface = self._get_rupture_surface(mag, np, hypocenter) yield ParametricProbabilisticRupture( mag, np.rake, self.tectonic_region_type, hypocenter, surface, occurrence_rate, self.temporal_occurrence_model) if not hcdist: break if not npdist: break
def test_get_dppvalue(self): rupture = self.make_rupture_fordpp( ParametricProbabilisticRupture, occurrence_rate=0.01, temporal_occurrence_model=PoissonTOM(50)) # Load the testing site. data_path = os.path.dirname(__file__) filename = os.path.join(data_path, "./data/geo_cycs_ss3_testing_site.csv") data = numpy.genfromtxt(filename, dtype=float, delimiter=',', names=True, skip_header=6675, skip_footer=6673) for loc in range(len(data)): lon = data[loc][0] lat = data[loc][1] ref_dpp = data[loc][2] dpp = rupture.get_dppvalue(Point(lon, lat)) self.assertAlmostEqual(dpp, ref_dpp, delta=0.1)
def _get_rupture(self, min_mag, max_mag, hypocenter_depth, aspect_ratio, dip, rupture_mesh_spacing, upper_seismogenic_depth=2, lower_seismogenic_depth=16): source_id = name = 'test-source' trt = TRT.ACTIVE_SHALLOW_CRUST mfd = TruncatedGRMFD(a_val=2, b_val=1, min_mag=min_mag, max_mag=max_mag, bin_width=1) location = Point(0, 0) nodal_plane = NodalPlane(strike=45, dip=dip, rake=-123.23) nodal_plane_distribution = PMF([(1, nodal_plane)]) hypocenter_distribution = PMF([(1, hypocenter_depth)]) magnitude_scaling_relationship = PeerMSR() rupture_aspect_ratio = aspect_ratio tom = PoissonTOM(time_span=50) point_source = PointSource( source_id, name, trt, mfd, rupture_mesh_spacing, magnitude_scaling_relationship, rupture_aspect_ratio, tom, upper_seismogenic_depth, lower_seismogenic_depth, location, nodal_plane_distribution, hypocenter_distribution) ruptures = list(point_source.iter_ruptures()) self.assertEqual(len(ruptures), 1) [rupture] = ruptures self.assertIs(rupture.temporal_occurrence_model, tom) self.assertIs(rupture.tectonic_region_type, trt) self.assertEqual(rupture.rake, nodal_plane.rake) self.assertIsInstance(rupture.surface, PlanarSurface) self.assertEqual(rupture.surface.mesh_spacing, rupture_mesh_spacing) return rupture
def make_point_source(**kwargs): default_arguments = { 'source_id': 'source_id', 'name': 'source name', 'tectonic_region_type': TRT.SUBDUCTION_INTRASLAB, 'mfd': TruncatedGRMFD(a_val=1, b_val=2, min_mag=3, max_mag=5, bin_width=1), 'location': Point(1.2, 3.4, 5.6), 'nodal_plane_distribution': PMF([(1, NodalPlane(1, 2, 3))]), 'hypocenter_distribution': PMF([(1, 4)]), 'upper_seismogenic_depth': 1.3, 'lower_seismogenic_depth': 4.9, 'magnitude_scaling_relationship': PeerMSR(), 'rupture_aspect_ratio': 1.333, 'rupture_mesh_spacing': 1.234 } default_arguments.update(kwargs) kwargs = default_arguments ps = PointSource(**kwargs) assert_pickleable(ps) return ps
def test(self): source = self._make_source() ruptures = [rup for rup in source.iter_ruptures()] self.assertTrue(len(ruptures) == source.count_ruptures()) self.assertTrue(ruptures[0].mag == 5.0) self.assertTrue(ruptures[1].mag == 5.1) self.assertTrue(ruptures[2].mag == 5.2) for i in range(3): self.assertTrue(ruptures[i].rake == self.RAKE) self.assertTrue(ruptures[i].tectonic_region_type == self.TRT) self.assertTrue(ruptures[i].hypocenter == Point(0., 0., 5.)) self.assertTrue(ruptures[i].surface.strike == self.STRIKE) self.assertTrue(ruptures[i].surface.dip == self.DIP) numpy.testing.assert_equal(ruptures[i].surface.corner_lons, self.CORNER_LONS) numpy.testing.assert_equal(ruptures[i].surface.corner_lats, self.CORNER_LATS) numpy.testing.assert_equal(ruptures[i].surface.corner_depths, self.CORNER_DEPTHS) self.assertTrue(ruptures[i].occurrence_rate == self.RATES[i]) self.assertTrue(ruptures[i].temporal_occurrence_model == self.TOM)
class PlanarSurfaceGetClosestPointsTestCase(unittest.TestCase): corners = [ Point(-0.1, -0.1, 0), Point(0.1, -0.1, 0), Point(0.1, 0.1, 2), Point(-0.1, 0.1, 2) ] surface = PlanarSurface(10, 90, 45, *corners) def test_point_above_surface(self): sites = Mesh.from_points_list([Point(0, 0), Point(-0.03, 0.05, 0.5)]) res = self.surface.get_closest_points(sites) self.assertIsInstance(res, Mesh) aae = numpy.testing.assert_almost_equal aae(res.lons, [0, -0.03], decimal=4) aae(res.lats, [-0.00081824, 0.04919223]) aae(res.depths, [1.0113781, 1.50822185]) def test_corner_is_closest(self): sites = Mesh.from_points_list([ Point(-0.11, 0.11), Point(0.14, -0.12, 10), Point(0.3, 0.2, 0.5), Point(-0.6, -0.6, 0.3) ]) res = self.surface.get_closest_points(sites) aae = numpy.testing.assert_almost_equal aae(res.lons, [-0.1, 0.1, 0.1, -0.1], decimal=4) aae(res.lats, [0.1, -0.1, 0.1, -0.1]) aae(res.depths, [2, 0, 2, 0], decimal=5) def test_top_or_bottom_edge_is_closest(self): sites = Mesh.from_points_list( [Point(-0.04, -0.28, 0), Point(0.033, 0.15, 0)]) res = self.surface.get_closest_points(sites) aae = numpy.testing.assert_almost_equal aae(res.lons, [-0.04, 0.033], decimal=5) aae(res.lats, [-0.1, 0.1], decimal=5) aae(res.depths, [0, 2], decimal=2) def test_left_or_right_edge_is_closest(self): sites = Mesh.from_points_list( [Point(-0.24, -0.08, 0.55), Point(0.17, 0.07, 0)]) res = self.surface.get_closest_points(sites) aae = numpy.testing.assert_almost_equal aae(res.lons, [-0.1, 0.1], decimal=5) aae(res.lats, [-0.08, 0.07], decimal=3) aae(res.depths, [0.20679306, 1.69185737]) def test_against_mesh_to_mesh(self): corners = [ Point(2.6, 3.7, 20), Point(2.90102155, 3.99961567, 20), Point(3.2, 3.7, 75), Point(2.89905849, 3.40038407, 75) ] surface = PlanarSurface(0.5, 45, 70, *corners) lons, lats = numpy.meshgrid(numpy.linspace(2.2, 3.6, 7), numpy.linspace(3.4, 4.2, 7)) sites = Mesh(lons, lats, depths=None) res1 = surface.get_closest_points(sites) res2 = super(PlanarSurface, surface).get_closest_points(sites) aae = numpy.testing.assert_almost_equal # precision up to ~1 km aae(res1.lons, res2.lons, decimal=2) aae(res1.lats, res2.lats, decimal=2) aae(res1.depths, res2.depths, decimal=0)
def setUp(self): """ This creates a fault dipping to north """ self.profiles1 = [] tmp = [ Point(0.0, 0.00, 0.0), Point(0.0, 0.05, 5.0), Point(0.0, 0.10, 10.0), Point(0.0, 0.15, 15.0) ] self.profiles1.append(Line(tmp)) tmp = [ Point(0.3, 0.00, 0.0), Point(0.3, 0.05, 5.0), Point(0.3, 0.10, 10.0), Point(0.3, 0.15, 15.0) ] self.profiles1.append(Line(tmp)) tmp = [ Point(0.5, 0.00, 0.0), Point(0.5, 0.05, 5.0), Point(0.5, 0.10, 10.0), Point(0.5, 0.15, 15.0) ] self.profiles1.append(Line(tmp)) self.profiles2 = [] tmp = [Point(0.0, 0.000, 0.0), Point(0.0, 0.001, 15.0)] self.profiles2.append(Line(tmp)) tmp = [Point(0.5, 0.000, 0.0), Point(0.5, 0.001, 15.0)] self.profiles2.append(Line(tmp))
def bottom_right(self): return Point(self.corner_lons[3], self.corner_lats[3], self.corner_depths[3])
def top_right(self): return Point(self.corner_lons[1], self.corner_lats[1], self.corner_depths[1])
Generalized coordinate systems require an additional level of testing under a variety of fault conditions - we separate these out away from the main fault surface testing modules """ import os import unittest import numpy from openquake.hazardlib.geo.surface.multi import MultiSurface from openquake.hazardlib.geo import Mesh, Point, Line, PlanarSurface,\ SimpleFaultSurface from openquake.hazardlib.geo.surface.base import (downsample_mesh, downsample_trace) PNT1 = Point(-64.78365, -0.45236, 0.0) PNT2 = Point(-64.80164, -0.45236, 0.0) PNT3 = Point(-64.90498, -0.36564, 0.0) PNT4 = Point(-65.00000, -0.16188, 0.0) PNT5 = Point(-65.00000, 0.00000, 0.0) AS_ARRAY = numpy.array([[pnt.longitude, pnt.latitude, pnt.depth] for pnt in [PNT1, PNT2, PNT3, PNT4, PNT5]]) class CartesianTestingMultiSurface(MultiSurface): """ This test surface is used to verify the values given by Spudich & Chiou in their report. Here, the fault is built directly from the cartesian points so we over-ride the call to the function to render the coordinates to cartesian
def test_rupture_topo(self): rupture = make_rupture(BaseRupture, hypocenter=Point(5, 6, -2)) self.assertEqual(rupture.hypocenter.depth, -2)
def get_rx_distance(self, mesh): """ Compute distance between each point of mesh and surface's great circle arc. Distance is measured perpendicular to the rupture strike, from the surface projection of the updip edge of the rupture, with the down dip direction being positive (this distance is usually called ``Rx``). In other words, is the horizontal distance to top edge of rupture measured perpendicular to the strike. Values on the hanging wall are positive, values on the footwall are negative. :param mesh: :class:`~openquake.hazardlib.geo.mesh.Mesh` of points to calculate Rx-distance to. :returns: Numpy array of distances in km. """ top_edge = self.mesh[0:1] dists = [] if top_edge.lons.shape[1] < 3: i = 0 p1 = Point(top_edge.lons[0, i], top_edge.lats[0, i], top_edge.depths[0, i]) p2 = Point(top_edge.lons[0, i + 1], top_edge.lats[0, i + 1], top_edge.depths[0, i + 1]) azimuth = p1.azimuth(p2) dists.append( geodetic.distance_to_arc(p1.longitude, p1.latitude, azimuth, mesh.lons, mesh.lats)) else: for i in range(top_edge.lons.shape[1] - 1): p1 = Point(top_edge.lons[0, i], top_edge.lats[0, i], top_edge.depths[0, i]) p2 = Point(top_edge.lons[0, i + 1], top_edge.lats[0, i + 1], top_edge.depths[0, i + 1]) # Swapping if i == 0: pt = p1 p1 = p2 p2 = pt # Computing azimuth and distance if i == 0 or i == top_edge.lons.shape[1] - 2: azimuth = p1.azimuth(p2) tmp = geodetic.distance_to_semi_arc( p1.longitude, p1.latitude, azimuth, mesh.lons, mesh.lats) else: tmp = geodetic.min_distance_to_segment( numpy.array([p1.longitude, p2.longitude]), numpy.array([p1.latitude, p2.latitude]), mesh.lons, mesh.lats) # Correcting the sign of the distance if i == 0: tmp *= -1 dists.append(tmp) # Computing distances dists = numpy.array(dists) iii = abs(dists).argmin(axis=0) dst = dists[iii, list(range(dists.shape[1]))] return dst
def test_point_outside(self): corners = [ Point(0.1, -0.1, 1), Point(-0.1, -0.1, 1), Point(-0.1, 0.1, 2), Point(0.1, 0.1, 2) ] surface = PlanarSurface(1, 270, 45, *corners) sites = Mesh.from_points_list([ Point(-0.2, -0.2), Point(1, 1, 1), Point(4, 5), Point(0.8, 0.01), Point(0.2, -0.15), Point(0.02, -0.12), Point(-0.14, 0), Point(-3, 3), Point(0.05, 0.15, 10) ]) dists = surface.get_joyner_boore_distance(sites) expected_dists = [ Point(-0.2, -0.2).distance(Point(-0.1, -0.1)), Point(1, 1).distance(Point(0.1, 0.1)), Point(4, 5).distance(Point(0.1, 0.1)), Point(0.8, 0.01).distance(Point(0.1, 0.01)), Point(0.2, -0.15).distance(Point(0.1, -0.1)), Point(0.02, -0.12).distance(Point(0.02, -0.1)), Point(-0.14, 0).distance(Point(-0.1, 0)), Point(-3, 3).distance(Point(-0.1, 0.1)), Point(0.05, 0.15).distance(Point(0.05, 0.1)) ] self.assertTrue(numpy.allclose(dists, expected_dists, atol=0.05))
def _get_cluster_correction(dat, C, ctx, imt): """ Get cluster correction. The use can specify various options through the cluster parameter. The available options are: - cluster = None In this case the code finds the most appropriate correction using the rupture position - cluster = 0 No cluster correction - cluser = 1 or 4 or 5 The code uses the correction for the given cluster """ cluster = dat.cluster shape = ctx.sids.shape correction = np.zeros_like(shape) # st.dev. tau_L2L = np.zeros(shape) Bp_model = np.zeros(shape) phi_P2P = np.zeros(shape) # No cluster correction if cluster == 0: tau_L2L = C['tau_L2L'] phi_P2P = C['phi_P2P'] return correction, tau_L2L, Bp_model, phi_P2P # the code finds the most appropriate correction if cluster is None: mesh = Mesh(np.array([ctx.hypo_lon]), np.array([ctx.hypo_lat])) # midp = ctx.surface.get_middle_point() # mesh = Mesh(np.array([midp.longitude]),np.array([midp.latitude])) for key in REGIONS: coo = np.array(REGIONS[key]) pnts = [Point(lo, la) for lo, la in zip(coo[:, 0], coo[:, 1])] poly = Polygon(pnts) within = poly.intersects(mesh) if all(within): cluster = int(key) break # if OUT clusters do not apply corrections if cluster is None: tau_L2L = C['tau_L2L'] phi_P2P = C['phi_P2P'] return correction, tau_L2L, Bp_model, phi_P2P else: # if IN clusters apply corrections # Cluster coefficients fname = 'P_model_cluster{:d}.csv'.format(cluster) fname = os.path.join(DATA_FOLDER, fname) data = np.loadtxt(fname, delimiter=",", skiprows=1) # for st.dev. fname2 = 'beta_dP2P_cluster{:d}.csv'.format(cluster) fname2 = os.path.join(DATA_FOLDER, fname2) data2 = np.loadtxt(fname2, delimiter=",", skiprows=1) # Compute the coefficients correction = np.zeros(shape) per = imt.period for idx in np.unique(dat.idxs): tmp = data[int(idx)] correction[dat.idxs == idx] = np.interp(per, dat.PERIODS, tmp[0:5]) # Adding L2L correction label = "dL2L_cluster{:d}".format(cluster) correction += C[label] # compute st.dev. for idx in np.unique(dat.idxs): tmp2 = data2[int(idx)] Bp_model[dat.idxs == idx] = np.interp(per, dat.PERIODS, tmp2[0:5]) return correction, tau_L2L, Bp_model, phi_P2P
def test2_site_on_the_foot_wall(self): surface = self._test1to7surface() sites = Mesh.from_points_list([Point(0.05, -0.05), Point(-140, -0.05)]) dists = surface.get_rx_distance(sites) expected_dists = [-5.559752615413244] * 2 self.assertTrue(numpy.allclose(dists, expected_dists))
def test_non_parametric_source(self): # non-parametric source equivalent to case 2 simple fault source data = test_data.SET1_CASE2_SOURCE_DATA ruptures = [] for i in range(data['num_rups_dip']): for j in range(data['num_rups_strike']): lons = data['lons'] lats = data['lats'][j] depths = data['depths'][i] mesh = RectangularMesh(lons, lats, depths) surf = SimpleFaultSurface(mesh) hypo = Point(data['hypo_lons'][i, j], data['hypo_lats'][i, j], data['hypo_depths'][i, j]) rup = BaseRupture(data['mag'], data['rake'], data['tectonic_region_type'], hypo, surf) ruptures.append((rup, data['pmf'])) npss = NonParametricSeismicSource('id', 'name', data['tectonic_region_type'], ruptures) 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_CASE2_IMLS} curves = calc_hazard_curves([npss], 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_CASE2_SITE1_POES, atol=3e-3, rtol=1e-5) assert_hazard_curve_is(self, s2hc, test_data.SET1_CASE2_SITE2_POES, atol=2e-5, rtol=1e-5) assert_hazard_curve_is(self, s3hc, test_data.SET1_CASE2_SITE3_POES, atol=2e-5, rtol=1e-5) assert_hazard_curve_is(self, s4hc, test_data.SET1_CASE2_SITE4_POES, atol=1e-3, rtol=1e-5) assert_hazard_curve_is(self, s5hc, test_data.SET1_CASE2_SITE5_POES, atol=1e-3, rtol=1e-5) assert_hazard_curve_is(self, s6hc, test_data.SET1_CASE2_SITE6_POES, atol=1e-3, rtol=1e-5) assert_hazard_curve_is(self, s7hc, test_data.SET1_CASE2_SITE7_POES, atol=2e-5, rtol=1e-5)
def test3_site_on_centroid(self): surface = self._test1to7surface() sites = Mesh.from_points_list([Point(0.05, 0)]) self.assertAlmostEqual(surface.get_rx_distance(sites)[0], 0)
def top_left(self): return Point(self.corner_lons[0], self.corner_lats[0], self.corner_depths[0])
def test6_one_degree_distance(self): surface = self._test1to7surface() sites = Mesh.from_points_list([Point(0.05, -1), Point(20, 1)]) dists = surface.get_rx_distance(sites) expected_dists = [-111.19505230826488, +111.19505230826488] self.assertTrue(numpy.allclose(dists, expected_dists))
def bottom_left(self): return Point(self.corner_lons[2], self.corner_lats[2], self.corner_depths[2])
def test7_ten_degrees_distance(self): surface = self._test1to7surface() sites = Mesh.from_points_list([Point(0, -10), Point(-15, 10)]) dists = surface.get_rx_distance(sites) expected_dists = [-1111.9505230826488, +1111.9505230826488] self.assertTrue(numpy.allclose(dists, expected_dists))
def get_rx_distance(self, mesh): """ Compute distance between each point of mesh and surface's great circle arc. Distance is measured perpendicular to the rupture strike, from the surface projection of the updip edge of the rupture, with the down dip direction being positive (this distance is usually called ``Rx``). In other words, is the horizontal distance to top edge of rupture measured perpendicular to the strike. Values on the hanging wall are positive, values on the footwall are negative. :param mesh: :class:`~openquake.hazardlib.geo.mesh.Mesh` of points to calculate Rx-distance to. :returns: Numpy array of distances in km. """ top_edge = self.mesh[0:1] dists = [] ia = 0 ib = top_edge.lons.shape[1] - 2 if (self.__class__.__name__ == 'KiteSurface'): idxs = numpy.nonzero(numpy.isfinite(top_edge.lons[0, :]))[0] ia = min(idxs) ib = sorted(idxs)[-2] if top_edge.lons.shape[1] < 3: i = 0 if ((self.__class__.__name__ == 'KiteSurface') and (numpy.isnan(top_edge.lons[0, i]) or numpy.isnan(top_edge.lons[0, i + 1]))): msg = 'Rx calculation. Top of rupture has less than two points' raise ValueError(msg) p1 = Point(top_edge.lons[0, i], top_edge.lats[0, i], top_edge.depths[0, i]) p2 = Point(top_edge.lons[0, i + 1], top_edge.lats[0, i + 1], top_edge.depths[0, i + 1]) azimuth = p1.azimuth(p2) dists.append( geodetic.distance_to_arc(p1.longitude, p1.latitude, azimuth, mesh.lons, mesh.lats)) else: for i in range(top_edge.lons.shape[1] - 1): if ((self.__class__.__name__ == 'KiteSurface') and (numpy.isnan(top_edge.lons[0, i]) or numpy.isnan(top_edge.lons[0, i + 1]))): continue p1 = Point(top_edge.lons[0, i], top_edge.lats[0, i], top_edge.depths[0, i]) p2 = Point(top_edge.lons[0, i + 1], top_edge.lats[0, i + 1], top_edge.depths[0, i + 1]) # Swapping if i == 0: pt = p1 p1 = p2 p2 = pt # Computing azimuth and distance if i == ia or i == ib: azimuth = p1.azimuth(p2) tmp = geodetic.distance_to_semi_arc( p1.longitude, p1.latitude, azimuth, mesh.lons, mesh.lats) else: tmp = geodetic.min_distance_to_segment( numpy.array([p1.longitude, p2.longitude]), numpy.array([p1.latitude, p2.latitude]), mesh.lons, mesh.lats) # Correcting the sign of the distance if i == 0: tmp *= -1 dists.append(tmp) # Computing distances dists = numpy.array(dists) iii = abs(dists).argmin(axis=0) dst = dists[iii, list(range(dists.shape[1]))] if numpy.any(numpy.isnan(dst)): raise ValueError('NaN in Rx') return dst
def test_areasource(self): nodalplane = NodalPlane(strike=0.0, dip=90.0, rake=0.0) src = AreaSource(source_id='src_1', name='area source', tectonic_region_type='Active Shallow Crust', mfd=TruncatedGRMFD(a_val=3.5, b_val=1.0, min_mag=5.0, max_mag=6.5, bin_width=0.1), nodal_plane_distribution=PMF([(1.0, nodalplane)]), hypocenter_distribution=PMF([(1.0, 5.0)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship=WC1994(), rupture_aspect_ratio=1.0, polygon=Polygon([ Point(-0.5, -0.5), Point(-0.5, 0.5), Point(0.5, 0.5), Point(0.5, -0.5) ]), area_discretization=9.0, rupture_mesh_spacing=1.0, temporal_occurrence_model=PoissonTOM(50.)) site = Site(location=Point(0.0, 0.0), vs30=800.0, vs30measured=True, z1pt0=500.0, z2pt5=2.0) gsims = {'Active Shallow Crust': BooreAtkinson2008()} imt = SA(period=0.1, damping=5.0) iml = 0.2 truncation_level = 3.0 n_epsilons = 3 mag_bin_width = 0.2 # in km dist_bin_width = 10.0 # in decimal degree coord_bin_width = 0.2 # compute disaggregation bin_edges, diss_matrix = disagg.disaggregation( [src], site, imt, iml, gsims, truncation_level, n_epsilons, mag_bin_width, dist_bin_width, coord_bin_width) mag_bins, dist_bins, lon_bins, lat_bins, eps_bins, trt_bins = bin_edges numpy.testing.assert_almost_equal( mag_bins, [5., 5.2, 5.4, 5.6, 5.8, 6., 6.2, 6.4, 6.6]) numpy.testing.assert_almost_equal( dist_bins, [0., 10., 20., 30., 40., 50., 60., 70., 80.]) numpy.testing.assert_almost_equal( lat_bins, [-0.6, -0.4, -0.2, 0., 0.2, 0.4, 0.6]) numpy.testing.assert_almost_equal( lon_bins, [-0.6, -0.4, -0.2, 0., 0.2, 0.4, 0.6]) numpy.testing.assert_almost_equal(eps_bins, [-3., -1., 1., 3.]) self.assertEqual(trt_bins, ['Active Shallow Crust']) expected_matrix = numpy.fromstring( codecs.decode( codecs.decode( b"""\ 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\ """, 'base64'), 'zip')).reshape((8, 8, 6, 6, 3, 1)) numpy.testing.assert_almost_equal(diss_matrix, expected_matrix)
def test_point_sources(self): sources = [ openquake.hazardlib.source.PointSource( source_id='point1', name='point1', tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST, mfd=openquake.hazardlib.mfd.EvenlyDiscretizedMFD( min_mag=4, bin_width=1, occurrence_rates=[5]), nodal_plane_distribution=openquake.hazardlib.pmf.PMF([ (1, openquake.hazardlib.geo.NodalPlane(strike=0.0, dip=90.0, rake=0.0)) ]), hypocenter_distribution=openquake.hazardlib.pmf.PMF([(1, 10)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship=openquake.hazardlib.scalerel. PeerMSR(), rupture_aspect_ratio=2, temporal_occurrence_model=PoissonTOM(1.), rupture_mesh_spacing=1.0, location=Point(10, 10)), openquake.hazardlib.source.PointSource( source_id='point2', name='point2', tectonic_region_type=const.TRT.ACTIVE_SHALLOW_CRUST, mfd=openquake.hazardlib.mfd.EvenlyDiscretizedMFD( min_mag=4, bin_width=2, occurrence_rates=[5, 6, 7]), nodal_plane_distribution=openquake.hazardlib.pmf.PMF([ (1, openquake.hazardlib.geo.NodalPlane(strike=0, dip=90, rake=0.0)), ]), hypocenter_distribution=openquake.hazardlib.pmf.PMF([(1, 10)]), upper_seismogenic_depth=0.0, lower_seismogenic_depth=10.0, magnitude_scaling_relationship=openquake.hazardlib.scalerel. PeerMSR(), rupture_aspect_ratio=2, temporal_occurrence_model=PoissonTOM(1.), rupture_mesh_spacing=1.0, location=Point(10, 11)), ] sites = [ openquake.hazardlib.site.Site(Point(11, 10), 1, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 16), 2, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 10.6), 3, True, 2, 3), openquake.hazardlib.site.Site(Point(10, 10.7), 4, True, 2, 3) ] sitecol = openquake.hazardlib.site.SiteCollection(sites) from openquake.hazardlib.gsim.sadigh_1997 import SadighEtAl1997 gsims = {const.TRT.ACTIVE_SHALLOW_CRUST: SadighEtAl1997()} truncation_level = 1 imts = {'PGA': [0.1, 0.5, 1.3]} from openquake.hazardlib.calc import filters source_site_filter = self.SitesCounterSourceFilter( filters.source_site_distance_filter(30)) rupture_site_filter = self.SitesCounterRuptureFilter( filters.rupture_site_distance_filter(30)) calc_hazard_curves(sources, sitecol, imts, gsims, truncation_level, source_site_filter=source_site_filter, rupture_site_filter=rupture_site_filter) # there are two sources and four sites. The first source contains only # one rupture, the second source contains three ruptures. # # the first source has 'maximum projection radius' of 0.707 km # the second source has 'maximum projection radius' of 500.0 km # # the epicentral distances for source 1 are: [ 109.50558394, # 667.16955987, 66.71695599, 77.83644865] # the epicentral distances for source 2 are: [ 155.9412148 , # 555.97463322, 44.47797066, 33.35847799] # # Considering that the source site filtering distance is set to 30 km, # for source 1, all sites have epicentral distance larger than # 0.707 + 30 km. This means that source 1 ('point 1') is not considered # in the calculation because too far. # for source 2, the 1st, 3rd and 4th sites have epicentral distances # smaller than 500.0 + 30 km. This means that source 2 ('point 2') is # considered in the calculation for site 1, 3, and 4. # # JB distances for rupture 1 in source 2 are: [ 155.43860273, # 555.26752644, 43.77086388, 32.65137121] # JB distances for rupture 2 in source 2 are: [ 150.98882575, # 548.90356541, 37.40690285, 26.28741018] # JB distances for rupture 3 in source 2 are: [ 109.50545819, # 55.97463322, 0. , 0. ] # # Considering that the rupture site filtering distance is set to 30 km, # rupture 1 (magnitude 4) is not considered because too far, rupture 2 # (magnitude 6) affect only the 4th site, rupture 3 (magnitude 8) # affect the 3rd and 4th sites. self.assertEqual(source_site_filter.counts, [('point2', [1, 3, 4])]) self.assertEqual(rupture_site_filter.counts, [(6, [4]), (8, [3, 4])])
def setUp(self): """ This creates a fault dipping to north """ self.profiles1 = [] tmp = [ Point(0.0, 0.00, 0.0), Point(0.0, 0.05, 5.0), Point(0.0, 0.10, 10.0), Point(0.0, 0.20, 20.0) ] self.profiles1.append(Line(tmp)) tmp = [ Point(0.17, 0.00, 0.0), Point(0.17, 0.05, 5.0), Point(0.17, 0.10, 10.0), Point(0.17, 0.15, 15.0) ] self.profiles1.append(Line(tmp)) tmp = [ Point(0.20, 0.00, 0.0), Point(0.20, 0.05, 5.0), Point(0.20, 0.10, 10.0), Point(0.20, 0.15, 15.0) ] tmp = [ Point(0.23, 0.13, 0.0), Point(0.23, 0.18, 5.0), Point(0.23, 0.23, 10.0), Point(0.23, 0.28, 15.0) ] self.profiles1.append(Line(tmp))