Example #1
0
 def modify_set_geometry(self, edges, spacing):
     """
     Modifies the complex fault geometry
     """
     ComplexFaultSurface.check_fault_data(edges, spacing)
     self.edges = edges
     self.rupture_mesh_spacing = spacing
    def __init__(
        self,
        source_id,
        name,
        tectonic_region_type,
        mfd,
        rupture_mesh_spacing,
        magnitude_scaling_relationship,
        rupture_aspect_ratio,
        temporal_occurrence_model,
        # complex fault specific parameters
        edges,
        rake,
    ):
        super(ComplexFaultSource, self).__init__(
            source_id,
            name,
            tectonic_region_type,
            mfd,
            rupture_mesh_spacing,
            magnitude_scaling_relationship,
            rupture_aspect_ratio,
            temporal_occurrence_model,
        )

        NodalPlane.check_rake(rake)
        ComplexFaultSurface.check_fault_data(edges, rupture_mesh_spacing)
        self.edges = edges
        self.rake = rake
Example #3
0
 def test_mesh_spacing_more_than_two_widthss(self):
     edge1 = Line([Point(0, 0, 0), Point(0, 0.2, 0)])
     edge2 = Line([Point(0, 0, 10), Point(0, 0.2, 20)])
     with self.assertRaises(ValueError) as ar:
         ComplexFaultSurface.from_fault_data([edge1, edge2],
                                             mesh_spacing=30.1)
     self.assertEqual(
         str(ar.exception),
         'mesh spacing 30.1 km is too big for mean width 15.0 km'
     )
Example #4
0
    def test_invalid_surface_polygon_topo(self):
        # intermediate edge has opposite strike than top and bottom
        edges = [Line([Point(0, 0, -5), Point(0, 2, -5)]),
                 Line([Point(0, 2, 5), Point(0, 0, 5)])]

        with self.assertRaises(ValueError) as cm:
            ComplexFaultSurface.from_fault_data(edges, mesh_spacing=1)
        self.assertEqual(
            'Edges points are not in the right order',
            str(cm.exception)
        )
Example #5
0
    def test_invalid_surface_polygon_case2(self):
        # inclined complex fault with top and bottom edges inverted
        edges = [Line([Point(0, 0), Point(0, 2)]),
                 Line([Point(0.2, 2, 10), Point(0.6, 0, 10)])]

        with self.assertRaises(ValueError) as cm:
            ComplexFaultSurface.from_fault_data(edges, mesh_spacing=10)
        self.assertEqual(
            'Edges points are not in the right order',
            str(cm.exception)
        )
Example #6
0
    def test_dip_left_of_fault_strike_case1(self):
        # checks that an error is raised when fault surface dips left of
        # fault strike (i.e. does not obey to Aki & Richards convention)
        # simple case of planar surface with strike 0 (pointing towards
        # north) but with surface dipping to the west
        edges = [Line([Point(0, 0), Point(0, 1)]),
                 Line([Point(-1, 0, 10), Point(-1, 1, 10)])]

        with self.assertRaises(ValueError) as cm:
            ComplexFaultSurface.from_fault_data(edges, mesh_spacing=10)
        self.assertEqual(
            'Surface does not conform with Aki & Richards convention',
            str(cm.exception)
        )
Example #7
0
    def test_2(self):
        # this is a regression test. Reference values have been obtained
        # by extracting mesh from complex surface.
        edge1 = Line([Point(0, 0, 1), Point(0, 0.02, 1)])
        edge2 = Line([Point(0.02, 0, 1.5), Point(0.02, 0.01, 1.5)])
        edge3 = Line([Point(0, 0, 2), Point(0, 0.02, 2)])
        surface = ComplexFaultSurface.from_fault_data([edge1, edge2, edge3],
                                                      mesh_spacing=1)
        self.assert_mesh_is(surface=surface, expected_mesh=[
            [(0.0, 0.0, 1.0),
             (0.0, 0.01, 1.0),
             (0.0, 0.02, 1.0)],

            [(0.008, 0.0, 1.2),
             (0.008, 0.008, 1.2),
             (0.008, 0.016, 1.2)],

            [(0.016, 0.0, 1.4),
             (0.016, 0.006, 1.4),
             (0.016, 0.012, 1.4)],

            [(0.016, 0.0, 1.6),
             (0.016, 0.006, 1.6),
             (0.016, 0.012, 1.6)],

            [(0.008, 0, 1.8),
             (0.008, 0.008, 1.8),
             (0.008, 0.016, 1.8)],

            [(0.0, 0.0, 2.0),
             (0.0, 0.01, 2.0),
             (0.0, 0.02, 2.0)],
        ])
    def test_2(self):
        edge1 = Line([Point(0, 0, 1), Point(0, 0.02, 1)])
        edge2 = Line([Point(0.02, 0, 0.5), Point(0.02, 0.01, 0.5)])
        edge3 = Line([Point(0, 0, 2), Point(0, 0.02, 2)])
        surface = ComplexFaultSurface.from_fault_data([edge1, edge2, edge3],
                                                      mesh_spacing=1)
        self.assert_mesh_is(surface=surface, expected_mesh=[
            [(0.00000000e+00, 0.00000000e+00, 1.00000000e+00),
             (0.00000000e+00, 1.00000000e-02, 1.00000000e+00),
             (0.00000000e+00, 2.00000000e-02, 1.00000000e+00)],

            [(8.70732572e-03, 5.33152318e-19, 7.82316857e-01),
             (8.67044753e-03, 7.83238825e-03, 7.83238813e-01),
             (8.57984833e-03, 1.57100762e-02, 7.85503798e-01)],

            [(1.74146514e-02, 1.06630462e-18, 5.64633714e-01),
             (1.73408950e-02, 5.66477632e-03, 5.66477626e-01),
             (1.71596963e-02, 1.14201520e-02, 5.71007595e-01)],

            [(1.47979150e-02, 3.18525318e-19, 8.90156376e-01),
             (1.48515919e-02, 6.28710212e-03, 8.86130608e-01),
             (1.49871315e-02, 1.25064345e-02, 8.75965152e-01)],

            [(7.39895749e-03, 7.71565830e-19, 1.44507819e+00),
             (7.42579599e-03, 8.14355113e-03, 1.44306530e+00),
             (7.49356586e-03, 1.62532174e-02, 1.43798258e+00)],

            [(0.00000000e+00, 0.00000000e+00, 2.00000000e+00),
             (0.00000000e+00, 1.00000000e-02, 2.00000000e+00),
             (0.00000000e+00, 2.00000000e-02, 2.00000000e+00)],
        ])
Example #9
0
 def test(self):
     edges = [Line([Point(-3.4, 5.5, 0), Point(-3.9, 5.3, 0)]),
              Line([Point(-2.4, 4.6, 10), Point(-3.6, 4.9, 20)])]
     polygon = ComplexFaultSurface.surface_projection_from_fault_data(edges)
     elons = [-2.4, -3.6, -3.9, -3.4]
     elats = [4.6,  4.9,  5.3,  5.5]
     numpy.testing.assert_allclose(polygon.lons, elons)
     numpy.testing.assert_allclose(polygon.lats, elats)
Example #10
0
 def test_surface_crossing_international_date_line(self):
     edge1 = Line([Point(179.95, 0., 0.), Point(-179.95, 0., 0.)])
     edge2 = Line([Point(179.95, 0., 10.), Point(-179.95, 0., 10.)])
     surface = ComplexFaultSurface.from_fault_data([edge1, edge2],
                                                   mesh_spacing=10.)
     self.assert_mesh_is(surface=surface, expected_mesh=[
         [(179.95, 0., 0.), (-179.95, 0., 0.)],
         [(179.95, 0., 10.), (-179.95, 0., 10.)]
     ])
Example #11
0
    def test_dip_left_of_fault_strike_topo(self):
        # when the fault is above sea level
        edges = [
            Line([
                Point(0, 1, -1),
                Point(0, 0, -1)
            ]),
            Line([
                Point(1, 1, 0),
                Point(1, 0, 0)]
            )]

        with self.assertRaises(ValueError) as cm:
            ComplexFaultSurface.from_fault_data(edges, mesh_spacing=1)
        self.assertEqual(
            'Surface does not conform with Aki & Richards convention',
            str(cm.exception)
        )
Example #12
0
 def test_surface_with_variable_width(self):
     edges = [Line([Point(0.1, 0.1, 0),
                    Point(0.459729190252, 0.0999980290582, 0.0),
                    Point(0.819458380482, 0.0999960581553, 0.0)]),
              Line([Point(0.1, 0.1, 20.0),
                    Point(0.459729190252, 0.0999980290582, 20.0),
                    Point(0.819458380482, 0.0999960581553, 43.0940107676)])]
     surface = ComplexFaultSurface.from_fault_data(edges, mesh_spacing=5.0)
     self.assertAlmostEqual(surface.get_width(), 26.0, places=0)
Example #13
0
 def test_dip_90_self_intersection(self):
     edges = [Line([Point(1, -2, 10), Point(2, -1.9, 10),
                    Point(3, -2.1, 10), Point(4, -2, 10)]),
              Line([Point(1, -2, 20), Point(2, -1.9, 20),
                    Point(3, -2.1, 20), Point(4, -2, 20)])]
     polygon = ComplexFaultSurface.surface_projection_from_fault_data(edges)
     elons = [3., 1., 2., 4.]
     elats = [-2.1, -2., -1.9, -2.]
     numpy.testing.assert_allclose(polygon.lons, elons)
     numpy.testing.assert_allclose(polygon.lats, elats)
Example #14
0
 def test_dip_90_two_points(self):
     edges = [Line([Point(2, 2, 10), Point(1, 1, 10)]),
              Line([Point(2, 2, 20), Point(1, 1, 20)])]
     polygon = ComplexFaultSurface.surface_projection_from_fault_data(edges)
     elons = [1.00003181, 0.99996821, 0.99996819, 1.99996819, 2.00003182,
              2.00003181]
     elats = [0.99996822, 0.99996819, 1.00003178, 2.0000318, 2.0000318,
              1.9999682]
     numpy.testing.assert_allclose(polygon.lons, elons)
     numpy.testing.assert_allclose(polygon.lats, elats)
Example #15
0
 def test_dip_90_three_points(self):
     edges = [Line([Point(1, -20, 30), Point(1, -20.2, 30),
                    Point(2, -19.7, 30)]),
              Line([Point(1, -20, 50), Point(1, -20.2, 50),
                    Point(2, -19.7, 50)])]
     polygon = ComplexFaultSurface.surface_projection_from_fault_data(edges)
     elons = [1, 1, 2]
     elats = [-20.2, -20., -19.7]
     numpy.testing.assert_allclose(polygon.lons, elons)
     numpy.testing.assert_allclose(polygon.lats, elats)
Example #16
0
 def test_edges_with_nonuniform_length(self):
     edges = [Line([Point(1, -20, 30), Point(1, -20.2, 30),
                    Point(2, -19.7, 30), Point(3, -19.5, 30)]),
              Line([Point(1, -20, 50), Point(1, -20.2, 50),
                    Point(2, -19.7, 50)])]
     polygon = ComplexFaultSurface.surface_projection_from_fault_data(edges)
     elons = [1, 1, 2, 3]
     elats = [-20.2, -20., -19.7, -19.5]
     numpy.testing.assert_allclose(polygon.lons, elons)
     numpy.testing.assert_allclose(polygon.lats, elats)
Example #17
0
    def test_dip_left_of_fault_strike_case2(self):
        # real example taken from wrong fault for japan model
        # ('Kanto earthquake')
        edges = [
            Line([
                Point(139.268, 35.3649682834, 10.6),
                Point(139.579014512, 35.1780000001, 10.6)
            ]),
            Line([
                Point(139.541937161, 35.378, 19.5999999911),
                Point(139.867999999, 35.2135133354, 19.6000000095)]
            )]

        with self.assertRaises(ValueError) as cm:
            ComplexFaultSurface.from_fault_data(edges, mesh_spacing=10)
        self.assertEqual(
            'Surface does not conform with Aki & Richards convention',
            str(cm.exception)
        )
Example #18
0
 def test_1(self):
     edge1 = Line([Point(0, 0), Point(0.03, 0)])
     edge2 = Line([Point(0, 0, 2.224), Point(0.03, 0, 2.224)])
     surface = ComplexFaultSurface.from_fault_data([edge1, edge2],
                                                   mesh_spacing=1.112)
     self.assertIsInstance(surface, ComplexFaultSurface)
     self.assert_mesh_is(surface=surface, expected_mesh=[
         [(0, 0, 0), (0.01, 0, 0), (0.02, 0, 0), (0.03, 0, 0)],
         [(0, 0, 1.112), (0.01, 0, 1.112),
          (0.02, 0, 1.112), (0.03, 0, 1.112)],
         [(0, 0, 2.224), (0.01, 0, 2.224),
          (0.02, 0, 2.224), (0.03, 0, 2.224)],
     ])
 def count_ruptures(self):
     """
     See :meth:
     `openquake.hazardlib.source.base.BaseSeismicSource.count_ruptures`.
     """
     whole_fault_surface = ComplexFaultSurface.from_fault_data(self.edges, self.rupture_mesh_spacing)
     whole_fault_mesh = whole_fault_surface.get_mesh()
     cell_center, cell_length, cell_width, cell_area = whole_fault_mesh.get_cell_dimensions()
     counts = 0
     for (mag, mag_occ_rate) in self.get_annual_occurrence_rates():
         rupture_area = self.magnitude_scaling_relationship.get_median_area(mag, self.rake)
         rupture_length = numpy.sqrt(rupture_area * self.rupture_aspect_ratio)
         rupture_slices = _float_ruptures(rupture_area, rupture_length, cell_area, cell_length)
         counts += len(rupture_slices)
     return counts
    def get_rupture_enclosing_polygon(self, dilation=0):
        """
        Uses :meth:`openquake.hazardlib.geo.surface.complex_fault.ComplexFaultSurface.surface_projection_from_fault_data`
        for getting the fault's surface projection and then calls
        its :meth:`~openquake.hazardlib.geo.polygon.Polygon.dilate`
        method passing in ``dilation`` parameter.

        See :meth:`superclass method
        <openquake.hazardlib.source.base.BaseSeismicSource.get_rupture_enclosing_polygon>`
        for parameter and return value definition.
        """
        polygon = ComplexFaultSurface.surface_projection_from_fault_data(self.edges)
        if dilation:
            return polygon.dilate(dilation)
        else:
            return polygon
Example #21
0
 def __init__(self, traces, mesh_spacing=1.0):
     '''
     Set up function an creates complex fault surface
     :param list traces:
         Edges of the complex fault as a list of :class:
         openquake.hazardlib.geo.line.Line. Please refer to documentation of
         openquake.hazardlib.geo.surface.complex_fault.ComplexFaultSurface
         for details.
     :param float mesh_spacing:
         Spacing (km) of the fault surface mesh
     '''
     self.typology = 'Complex'
     self.trace = traces
     self.upper_depth = None
     self.lower_depth = None
     self.surface = ComplexFaultSurface.from_fault_data(self.trace,
                                                        mesh_spacing)
     self.dip = self.surface.get_dip()
Example #22
0
    def iter_ruptures(self):
        """
        See :meth:
        `openquake.hazardlib.source.base.BaseSeismicSource.iter_ruptures`.

        Uses :func:`_float_ruptures` for finding possible rupture locations
        on the whole fault surface.
        """
        whole_fault_surface = ComplexFaultSurface.from_fault_data(
            self.edges, self.rupture_mesh_spacing
        )
        whole_fault_mesh = whole_fault_surface.get_mesh()
        cell_center, cell_length, cell_width, cell_area = (
            whole_fault_mesh.get_cell_dimensions()
        )

        for (mag, mag_occ_rate) in self.get_annual_occurrence_rates():
            rupture_area = self.magnitude_scaling_relationship.get_median_area(
                mag, self.rake
            )
            rupture_length = numpy.sqrt(
                rupture_area * self.rupture_aspect_ratio)
            rupture_slices = _float_ruptures(
                rupture_area, rupture_length, cell_area, cell_length
            )
            occurrence_rate = mag_occ_rate / float(len(rupture_slices))

            for rupture_slice in rupture_slices[self.start:self.stop]:
                mesh = whole_fault_mesh[rupture_slice]
                # XXX: use surface centroid as rupture's hypocenter
                # XXX: instead of point with middle index
                hypocenter = mesh.get_middle_point()

                try:
                    surface = ComplexFaultSurface(mesh)
                except ValueError as e:
                    raise ValueError("Invalid source with id=%s. %s" % (
                        self.source_id, str(e)))
                yield ParametricProbabilisticRupture(
                    mag, self.rake, self.tectonic_region_type, hypocenter,
                    surface, type(self),
                    occurrence_rate, self.temporal_occurrence_model
                )
    def create_geometry(self, input_geometry,  mesh_spacing=1.0):
        '''
        If geometry is defined as a numpy array then create instance of
        nhlib.geo.line.Line class, otherwise if already instance of class
        accept class

        :param input_geometry:
            List of at least two fault edges of the fault source from
            shallowest to deepest. Each edge can be represented as as either
            i) instance of nhlib.geo.polygon.Polygon class
            ii) numpy.ndarray [Longitude, Latitude, Depth]

        :param float mesh_spacing:
            Spacing of the fault mesh (km) {default = 1.0}

        '''
        if not isinstance(input_geometry, list) or len(input_geometry) < 2:
            raise ValueError('Complex fault geometry incorrectly defined')

        self.fault_edges = []
        for edge in input_geometry:
            if not isinstance(edge, Line):
                if not isinstance(edge, np.ndarray):
                    raise ValueError('Unrecognised or unsupported geometry '
                                     'definition')
                else:
                    self.fault_edges.append(Line([Point(row[0], row[1], row[2])
                                                  for row in edge]))
            else:
                self.fault_edges.append(edge)
            # Updates the upper and lower sesmogenic depths to reflect geometry
            self._get_minmax_edges(edge)
        # Build fault surface
        self.geometry = ComplexFaultSurface.from_fault_data(self.fault_edges,
                                                            mesh_spacing)
        # Get a mean dip
        self.dip = self.geometry.get_dip()
Example #24
0
 def polygon(self):
     """
     The underlying polygon
     `"""
     return ComplexFaultSurface.surface_projection_from_fault_data(
         self.edges)