def test_dip_over_90_degree(self): top = [Point(0, -0.01), Point(0, 0.01)] bottom = [Point(-0.01, -0.01, 1.11), Point(-0.01, 0.01, 1.11)] mesh = RectangularMesh.from_points_list([top, bottom]) dip, strike = mesh.get_mean_inclination_and_azimuth() # dip must be still in a range 0..90 self.assertAlmostEqual(dip, 45, delta=0.05) # strike must be reversed self.assertAlmostEqual(strike, 180, delta=0.05)
def test_dip_over_90_degree(self): top = [Point(0, -0.01), Point(0, 0.01)] bottom = [Point(-0.01, -0.01, 1.11), Point(-0.01, 0.01, 1.11)] mesh = RectangularMesh.from_points_list([top, bottom]) dip, strike = mesh.get_mean_inclination_and_azimuth() # dip must be still in a range 0..90 self.assertAlmostEqual(dip, 45, delta=0.05) # strike must be reversed self.assertAlmostEqual(strike, 180, delta=0.05)
def test_from_points_list(self): lons = [[0, 1], [2, 3], [4, 5]] lats = [[1, 2], [-1, -2], [10, 20]] depths = [[11.1, 11.2], [11.3, 11.4], [11.5, 11.6]] points = [[ Point(lons[i][j], lats[i][j], depths[i][j]) for j in xrange(len(lons[i])) ] for i in xrange(len(lons))] mesh = RectangularMesh.from_points_list(points) self.assertTrue((mesh.lons == lons).all()) self.assertTrue((mesh.lats == lats).all()) self.assertTrue((mesh.depths == depths).all()) points = [[ Point(lons[i][j], lats[i][j], depth=0) for j in xrange(len(lons[i])) ] for i in xrange(len(lons))] mesh = RectangularMesh.from_points_list(points) self.assertTrue((mesh.lons == lons).all()) self.assertTrue((mesh.lats == lats).all()) self.assertIsNone(mesh.depths)
def from_fault_data(cls, fault_trace, upper_seismogenic_depth, lower_seismogenic_depth, dip, mesh_spacing): """ Create and return a fault surface using fault source data. :param fault_trace: Geographical line representing the intersection between the fault surface and the earth surface, an instance of :class:`nhlib.Line`. :param upper_seismo_depth: Minimum depth ruptures can reach, in km (i.e. depth to fault's top edge). :param lower_seismo_depth: Maximum depth ruptures can reach, in km (i.e. depth to fault's bottom edge). :param dip: Dip angle (i.e. angle between fault surface and earth surface), in degrees. :param mesh_spacing: Distance between two subsequent points in a mesh, in km. :returns: An instance of :class:`SimpleFaultSurface` created using that data. Uses :meth:`check_fault_data` for checking parameters. """ cls.check_fault_data(fault_trace, upper_seismogenic_depth, lower_seismogenic_depth, dip, mesh_spacing) # Loops over points in the top edge, for each point # on the top edge compute corresponding point on the bottom edge, then # computes equally spaced points between top and bottom points. vdist_top = upper_seismogenic_depth vdist_bottom = lower_seismogenic_depth hdist_top = vdist_top / math.tan(math.radians(dip)) hdist_bottom = vdist_bottom / math.tan(math.radians(dip)) strike = fault_trace[0].azimuth(fault_trace[-1]) azimuth = (strike + 90.0) % 360 mesh = [] for point in fault_trace.resample(mesh_spacing): top = point.point_at(hdist_top, vdist_top, azimuth) bottom = point.point_at(hdist_bottom, vdist_bottom, azimuth) mesh.append(top.equally_spaced_points(bottom, mesh_spacing)) # number of rows corresponds to number of points along dip # number of columns corresponds to number of points along strike surface_points = numpy.array(mesh).transpose().tolist() mesh = RectangularMesh.from_points_list(surface_points) assert 1 not in mesh.shape return cls(mesh)
def test_one_cell(self): top = [Point(0, -0.01), Point(0, 0.01)] bottom = [Point(0.01, -0.01, 1.11), Point(0.01, 0.01, 1.11)] mesh = RectangularMesh.from_points_list([top, bottom]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertAlmostEqual(dip, 45, delta=0.05) self.assertAlmostEqual(strike, 0, delta=0.05) row1 = [Point(45, -0.1), Point(45.2, 0.1)] row2 = [Point(45, -0.1, 1), Point(45.2, 0.1, 1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertAlmostEqual(dip, 90) self.assertAlmostEqual(strike, 45, delta=0.1) row1 = [Point(90, -0.1), Point(90, 0.1)] row2 = [Point(90, -0.1, 1), Point(90, 0.1, 1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertAlmostEqual(dip, 90) self.assertAlmostEqual(strike, 0, delta=0.1)
def test_one_cell(self): top = [Point(0, -0.01), Point(0, 0.01)] bottom = [Point(0.01, -0.01, 1.11), Point(0.01, 0.01, 1.11)] mesh = RectangularMesh.from_points_list([top, bottom]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertAlmostEqual(dip, 45, delta=0.05) self.assertAlmostEqual(strike, 0, delta=0.05) row1 = [Point(45, -0.1), Point(45.2, 0.1)] row2 = [Point(45, -0.1, 1), Point(45.2, 0.1, 1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertAlmostEqual(dip, 90) self.assertAlmostEqual(strike, 45, delta=0.1) row1 = [Point(90, -0.1), Point(90, 0.1)] row2 = [Point(90, -0.1, 1), Point(90, 0.1, 1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertAlmostEqual(dip, 90) self.assertAlmostEqual(strike, 0, delta=0.1)
def from_fault_data(cls, fault_trace, upper_seismogenic_depth, lower_seismogenic_depth, dip, mesh_spacing): """ Create and return a fault surface using fault source data. :param nhlib.geo.line.Line fault_trace: Geographical line representing the intersection between the fault surface and the earth surface. :param upper_seismo_depth: Minimum depth ruptures can reach, in km (i.e. depth to fault's top edge). :param lower_seismo_depth: Maximum depth ruptures can reach, in km (i.e. depth to fault's bottom edge). :param dip: Dip angle (i.e. angle between fault surface and earth surface), in degrees. :param mesh_spacing: Distance between two subsequent points in a mesh, in km. :returns: An instance of :class:`SimpleFaultSurface` created using that data. Uses :meth:`check_fault_data` for checking parameters. """ cls.check_fault_data(fault_trace, upper_seismogenic_depth, lower_seismogenic_depth, dip, mesh_spacing) # Loops over points in the top edge, for each point # on the top edge compute corresponding point on the bottom edge, then # computes equally spaced points between top and bottom points. vdist_top = upper_seismogenic_depth vdist_bottom = lower_seismogenic_depth hdist_top = vdist_top / math.tan(math.radians(dip)) hdist_bottom = vdist_bottom / math.tan(math.radians(dip)) strike = fault_trace[0].azimuth(fault_trace[-1]) azimuth = (strike + 90.0) % 360 mesh = [] for point in fault_trace.resample(mesh_spacing): top = point.point_at(hdist_top, vdist_top, azimuth) bottom = point.point_at(hdist_bottom, vdist_bottom, azimuth) mesh.append(top.equally_spaced_points(bottom, mesh_spacing)) # number of rows corresponds to number of points along dip # number of columns corresponds to number of points along strike surface_points = numpy.array(mesh).transpose().tolist() mesh = RectangularMesh.from_points_list(surface_points) assert 1 not in mesh.shape return cls(mesh)
def test_one_cell_unequal_area(self): # top-left triangle is vertical, has dip of 90 degrees, zero # strike and area of 1 by 1 over 2. bottom-right one has dip # of atan2(1, sqrt(2) / 2.0) which is 54.73561 degrees, strike # of 45 degrees and area that is 1.73246136 times area of the # first one's. weighted mean dip is 67.5 degrees and weighted # mean strike is 28.84 degrees top = [Point(0, -0.01), Point(0, 0.01)] bottom = [Point(0, -0.01, 2.22), Point(0.02, 0.01, 2.22)] mesh = RectangularMesh.from_points_list([top, bottom]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertAlmostEqual(dip, 67.5, delta=0.05) self.assertAlmostEqual(strike, 28.84, delta=0.05)
def test_from_points_list(self): lons = [[0, 1], [2, 3], [4, 5]] lats = [[1, 2], [-1, -2], [10, 20]] depths = [[11.1, 11.2], [11.3, 11.4], [11.5, 11.6]] points = [ [Point(lons[i][j], lats[i][j], depths[i][j]) for j in xrange(len(lons[i]))] for i in xrange(len(lons)) ] mesh = RectangularMesh.from_points_list(points) self.assertTrue((mesh.lons == lons).all()) self.assertTrue((mesh.lats == lats).all()) self.assertTrue((mesh.depths == depths).all()) points = [ [Point(lons[i][j], lats[i][j], depth=0) for j in xrange(len(lons[i]))] for i in xrange(len(lons)) ] mesh = RectangularMesh.from_points_list(points) self.assertTrue((mesh.lons == lons).all()) self.assertTrue((mesh.lats == lats).all()) self.assertIsNone(mesh.depths)
def test_one_cell_unequal_area(self): # top-left triangle is vertical, has dip of 90 degrees, zero # strike and area of 1 by 1 over 2. bottom-right one has dip # of atan2(1, sqrt(2) / 2.0) which is 54.73561 degrees, strike # of 45 degrees and area that is 1.73246136 times area of the # first one's. weighted mean dip is 67.5 degrees and weighted # mean strike is 28.84 degrees top = [Point(0, -0.01), Point(0, 0.01)] bottom = [Point(0, -0.01, 2.22), Point(0.02, 0.01, 2.22)] mesh = RectangularMesh.from_points_list([top, bottom]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertAlmostEqual(dip, 67.5, delta=0.05) self.assertAlmostEqual(strike, 28.84, delta=0.05)
def from_fault_data(cls, edges, mesh_spacing): """ Create and return a fault surface using fault source data. :param edges: A list of at least two horizontal edges of the surface as instances of :class:`nhlib.geo.line.Line`. The list should be in top-to-bottom order (the shallowest edge first). :param mesh_spacing: Distance between two subsequent points in a mesh, in km. :returns: An instance of :class:`ComplexFaultSurface` created using that data. :raises ValueError: If requested mesh spacing is too big for the surface geometry (doesn't allow to put a single mesh cell along length and/or width). Uses :meth:`check_fault_data` for checking parameters. """ cls.check_fault_data(edges, mesh_spacing) mean_length = numpy.mean([edge.get_length() for edge in edges]) num_hor_points = int(round(mean_length / mesh_spacing)) + 1 if num_hor_points <= 1: raise ValueError( 'mesh spacing %.1f km is too big for mean length %.1f km' % (mesh_spacing, mean_length)) edges = [ edge.resample_to_num_points(num_hor_points).points for i, edge in enumerate(edges) ] vert_edges = [Line(v_edge) for v_edge in zip(*edges)] mean_width = numpy.mean([v_edge.get_length() for v_edge in vert_edges]) num_vert_points = int(round(mean_width / mesh_spacing)) + 1 if num_vert_points <= 1: raise ValueError( 'mesh spacing %.1f km is too big for mean width %.1f km' % (mesh_spacing, mean_width)) points = zip(*[ v_edge.resample_to_num_points(num_vert_points).points for v_edge in vert_edges ]) mesh = RectangularMesh.from_points_list(points) assert 1 not in mesh.shape return cls(mesh)
def from_fault_data(cls, edges, mesh_spacing): """ Create and return a fault surface using fault source data. :param edges: A list of at least two horizontal edges of the surface as instances of :class:`nhlib.geo.line.Line`. The list should be in top-to-bottom order (the shallowest edge first). :param mesh_spacing: Distance between two subsequent points in a mesh, in km. :returns: An instance of :class:`ComplexFaultSurface` created using that data. :raises ValueError: If requested mesh spacing is too big for the surface geometry (doesn't allow to put a single mesh cell along length and/or width). Uses :meth:`check_fault_data` for checking parameters. """ cls.check_fault_data(edges, mesh_spacing) mean_length = numpy.mean([edge.get_length() for edge in edges]) num_hor_points = int(round(mean_length / mesh_spacing)) + 1 if num_hor_points <= 1: raise ValueError( 'mesh spacing %.1f km is too big for mean length %.1f km' % (mesh_spacing, mean_length) ) edges = [edge.resample_to_num_points(num_hor_points).points for i, edge in enumerate(edges)] vert_edges = [Line(v_edge) for v_edge in zip(*edges)] mean_width = numpy.mean([v_edge.get_length() for v_edge in vert_edges]) num_vert_points = int(round(mean_width / mesh_spacing)) + 1 if num_vert_points <= 1: raise ValueError( 'mesh spacing %.1f km is too big for mean width %.1f km' % (mesh_spacing, mean_width) ) points = zip(*[v_edge.resample_to_num_points(num_vert_points).points for v_edge in vert_edges]) mesh = RectangularMesh.from_points_list(points) assert 1 not in mesh.shape return cls(mesh)
def test_two_cells(self): top = [Point(0, -0.01), Point(0, 0.01)] middle = [Point(0.01, -0.01, 1.11), Point(0.01, 0.01, 1.11)] bottom = [Point(0.01, -0.01, 2.22), Point(0.01, 0.01, 2.22)] mesh = RectangularMesh.from_points_list([top, middle, bottom]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertAlmostEqual(dip, math.degrees(math.atan2(2, 1)), delta=0.1) self.assertAlmostEqual(strike, 0, delta=0.02) bottom = [Point(0.01, -0.01, 3.33), Point(0.01, 0.01, 3.33)] mesh = RectangularMesh.from_points_list([top, middle, bottom]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertAlmostEqual(dip, math.degrees(math.atan2(3, 1)), delta=0.1) self.assertAlmostEqual(strike, 0, delta=0.02) row1 = [Point(90, -0.1), Point(90, 0), Point(90, 0.1)] row2 = [Point(90, -0.1, 1), Point(90, 0, 1), Point(90, 0.1, 1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertAlmostEqual(dip, 90) assert_angles_equal(self, strike, 360, delta=1e-7) row1 = [Point(-90.1, -0.1), Point(-90, 0), Point(-89.9, 0.1)] row2 = [ Point(-90.0, -0.1, 1), Point(-89.9, 0, 1), Point(-89.8, 0.1, 1) ] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertAlmostEqual(strike, 45, delta=1e-4) row1 = [Point(-90.1, -0.1), Point(-90, 0), Point(-89.9, 0.1)] row2 = [ Point(-90.0, -0.1, 1), Point(-89.9, 0, 1), Point(-89.8, 0.1, 1) ] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertAlmostEqual(strike, 45, delta=1e-3) row1 = [Point(-90.1, -0.1), Point(-90, 0), Point(-89.9, 0.1)] row2 = [Point(-90.2, -0.1, 1), Point(-90.1, 0, 1), Point(-90, 0.1, 1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertAlmostEqual(strike, 225, delta=1e-3)
def test_on_surface(self): row1 = [Point(0, 0), Point(0, 1)] row2 = [Point(1, 0), Point(1, 1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertEqual(dip, 0) self.assertAlmostEqual(strike, 0, delta=0.5) row1 = [Point(0, 0), Point(0, -1)] row2 = [Point(1, 0), Point(1, -1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertEqual(dip, 0) self.assertAlmostEqual(strike, 180, delta=0.5) row1 = [Point(0, 0), Point(1, 1)] row2 = [Point(1, 0), Point(2, 1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertEqual(dip, 0) self.assertAlmostEqual(strike, 45, delta=0.01) row1 = [Point(0, 0), Point(1, -1)] row2 = [Point(1, 0), Point(2, -1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertEqual(dip, 0) self.assertAlmostEqual(strike, 135, delta=0.01) row1 = [Point(0, 0), Point(-1, -1)] row2 = [Point(-1, 0), Point(-2, -1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertEqual(dip, 0) self.assertAlmostEqual(strike, 225, delta=0.01) row1 = [Point(0, 0), Point(-1, 1)] row2 = [Point(-1, 0), Point(-2, 1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertEqual(dip, 0) self.assertAlmostEqual(strike, 315, delta=0.01)
def test_on_surface(self): row1 = [Point(0, 0), Point(0, 1)] row2 = [Point(1, 0), Point(1, 1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertEqual(dip, 0) self.assertAlmostEqual(strike, 0, delta=0.5) row1 = [Point(0, 0), Point(0, -1)] row2 = [Point(1, 0), Point(1, -1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertEqual(dip, 0) self.assertAlmostEqual(strike, 180, delta=0.5) row1 = [Point(0, 0), Point(1, 1)] row2 = [Point(1, 0), Point(2, 1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertEqual(dip, 0) self.assertAlmostEqual(strike, 45, delta=0.01) row1 = [Point(0, 0), Point(1, -1)] row2 = [Point(1, 0), Point(2, -1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertEqual(dip, 0) self.assertAlmostEqual(strike, 135, delta=0.01) row1 = [Point(0, 0), Point(-1, -1)] row2 = [Point(-1, 0), Point(-2, -1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertEqual(dip, 0) self.assertAlmostEqual(strike, 225, delta=0.01) row1 = [Point(0, 0), Point(-1, 1)] row2 = [Point(-1, 0), Point(-2, 1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertEqual(dip, 0) self.assertAlmostEqual(strike, 315, delta=0.01)
def test_two_cells(self): top = [Point(0, -0.01), Point(0, 0.01)] middle = [Point(0.01, -0.01, 1.11), Point(0.01, 0.01, 1.11)] bottom = [Point(0.01, -0.01, 2.22), Point(0.01, 0.01, 2.22)] mesh = RectangularMesh.from_points_list([top, middle, bottom]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertAlmostEqual(dip, math.degrees(math.atan2(2, 1)), delta=0.1) self.assertAlmostEqual(strike, 0, delta=0.02) bottom = [Point(0.01, -0.01, 3.33), Point(0.01, 0.01, 3.33)] mesh = RectangularMesh.from_points_list([top, middle, bottom]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertAlmostEqual(dip, math.degrees(math.atan2(3, 1)), delta=0.1) self.assertAlmostEqual(strike, 0, delta=0.02) row1 = [Point(90, -0.1), Point(90, 0), Point(90, 0.1)] row2 = [Point(90, -0.1, 1), Point(90, 0, 1), Point(90, 0.1, 1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertAlmostEqual(dip, 90) assert_angles_equal(self, strike, 360, delta=1e-7) row1 = [Point(-90.1, -0.1), Point(-90, 0), Point(-89.9, 0.1)] row2 = [Point(-90.0, -0.1, 1), Point(-89.9, 0, 1), Point(-89.8, 0.1, 1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertAlmostEqual(strike, 45, delta=1e-4) row1 = [Point(-90.1, -0.1), Point(-90, 0), Point(-89.9, 0.1)] row2 = [Point(-90.0, -0.1, 1), Point(-89.9, 0, 1), Point(-89.8, 0.1, 1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertAlmostEqual(strike, 45, delta=1e-3) row1 = [Point(-90.1, -0.1), Point(-90, 0), Point(-89.9, 0.1)] row2 = [Point(-90.2, -0.1, 1), Point(-90.1, 0, 1), Point(-90, 0.1, 1)] mesh = RectangularMesh.from_points_list([row1, row2]) dip, strike = mesh.get_mean_inclination_and_azimuth() self.assertAlmostEqual(strike, 225, delta=1e-3)
def _create_mesh(self): points = [[Point(*coordinates) for coordinates in row] for row in self.coordinates_list] return RectangularMesh.from_points_list(points)
def _create_mesh(self): points = [[Point(*coordinates) for coordinates in row] for row in self.coordinates_list] return RectangularMesh.from_points_list(points)