コード例 #1
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)
コード例 #2
0
    def test_invalid_surface_polygon_case3(self):
        # intermediate edge has opposite strike than top and bottom
        edges = [
            Line([Point(0, 0), Point(0, 2)]),
            Line([Point(0.1, 2, 10), Point(0.1, 0, 10)]),
            Line([Point(0.2, 0, 20), Point(0.2, 2, 20)])
        ]

        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))
コード例 #3
0
    def setUp(self):
        '''
        '''
        self.simple_edge = Line(
            [Point(10.5, 10.5, 1.0),
             Point(11.35, 11.45, 2.0)])

        top_edge = Line([Point(10.5, 10.5, 1.0), Point(11.35, 11.45, 2.0)])
        int_edge = Line([Point(10.5, 10.5, 20.0), Point(11.35, 11.45, 21.0)])
        low_edge = Line([Point(10.5, 10.5, 40.0), Point(11.35, 11.45, 40.0)])

        self.complex_edge = [top_edge, int_edge, low_edge]
コード例 #4
0
ファイル: nrml04_parser.py プロジェクト: tieganh/oq-engine
def linestring_node_to_line(node, with_depth=False):
    """
    Returns an instance of a Linestring node to :class:
    openquake.hazardlib.geo.line.Line
    """
    assert "LineString" in node.tag
    crds = [float(x) for x in node.nodes[0].text.split()]
    if with_depth:
        return Line([Point(crds[iloc], crds[iloc + 1], crds[iloc + 2])
                     for iloc in range(0, len(crds), 3)])
    else:
        return Line([Point(crds[iloc], crds[iloc + 1])
                     for iloc in range(0, len(crds), 2)])
コード例 #5
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)],
     ])
コード例 #6
0
 def setUp(self):
     '''
     Creates a complex fault typology
     '''
     x0 = Point(30., 30., 0.)
     x1 = x0.point_at(30., 0., 30.)
     x2 = x1.point_at(30., 0., 60.)
     upper_edge = Line([x0, x1, x2])
     lower_edge = Line([x0.point_at(40., 20., 130.),
                        x1.point_at(42., 25., 130.),
                        x2.point_at(41., 22., 130.)])
     self.edges = [upper_edge, lower_edge]
     self.fault = None
コード例 #7
0
 def test_non_positive_mesh_spacing(self):
     edges = [
         Line([Point(0, 0), Point(0, 1)]),
         Line([Point(0, 0, 1), Point(0, 1, 1)])
     ]
     self.assertRaises(ValueError,
                       ComplexFaultSurface.from_fault_data,
                       edges,
                       mesh_spacing=0)
     self.assertRaises(ValueError,
                       ComplexFaultSurface.from_fault_data,
                       edges,
                       mesh_spacing=-1)
コード例 #8
0
    def get_target_sites_mesh(self, maximum_distance, spacing, vs30,
                              vs30measured=True, z1pt0=None, z2pt5=None,
                              backarc=False):
        """
        Renders a two dimensional mesh of points over the rupture surface
        """
        # Get bounding box of dilated rupture
        lowx, highx, lowy, highy = self._get_limits_maximum_rjb(
            maximum_distance)
        # Create bounding box lines and then resample at spacing
        ewline = Line([Point(lowx, highy, 0.), Point(highx, highy, 0.)])
        nsline = Line([Point(lowx, highy, 0.), Point(lowx, lowy, 0.)])
        ewline = ewline.resample(spacing)
        nsline = nsline.resample(spacing)
        xvals = np.array([pnt.longitude for pnt in ewline.points])
        yvals = np.array([pnt.latitude for pnt in nsline.points])

        gridx, gridy = np.meshgrid(xvals, yvals)

        numx, numy = np.shape(gridx)
        npts = numx * numy
        gridx = (np.reshape(gridx, npts, 1)).flatten()
        gridy = (np.reshape(gridy, npts, 1)).flatten()
        site_list = []

        if not z1pt0:
            #z1pt0 = vs30_to_z1pt0_as08(vs30)
            z1pt0 = vs30_to_z1pt0_cy14(vs30)

        if not z2pt5:
            #z2pt5 = z1pt0_to_z2pt5(z1pt0)
            z2pt5 = vs30_to_z2pt5_cb14(vs30)

        for iloc in range(0, npts):
            site_list.append(Site(Point(gridx[iloc], gridy[iloc], 0.),
                                  vs30,
                                  vs30measured,
                                  z1pt0,
                                  z2pt5,
                                  backarc=backarc))
        self.target_sites = SiteCollection(site_list)
        self.target_sites_config = {
            "TYPE": "Mesh",
            "RMAX": maximum_distance,
            "SPACING": spacing,
            "VS30": vs30,
            "VS30MEASURED": vs30measured,
            "Z1.0": z1pt0,
            "Z2.5": z2pt5,
            "BACKARC": backarc}
        return self.target_sites
コード例 #9
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)
コード例 #10
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)
        )
コード例 #11
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)
コード例 #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)
コード例 #13
0
ファイル: cross_sections.py プロジェクト: ftbernales/oq-mbtk
 def get_grd_nodes_within_buffer(self, x, y, buffer_distance, minlo, maxlo,
                                 minla, maxla):
     """
     :parameter x:
         An iterable containing the longitudes of the points defining the
         polyline
     :parameter y:
         An iterable containing the latitudes of the points defining the
         polyline
     :parameter buffer_distance:
         Horizontal buffer_distance used to select earthquakes included in
         the catalogue [in km]
     :parameter minlo:
     :parameter minla:
     :parameter maxlo:
     :parameter maxla:
     """
     line = Line([Point(lo, la) for lo, la in zip(self.plo, self.pla)])
     idxs = numpy.nonzero((x > minlo) & (x < maxlo) & (y > minla)
                          & (y < maxla))
     xs = x[idxs[0]]
     ys = y[idxs[0]]
     coo = [(lo, la) for lo, la in zip(list(xs), list(ys))]
     if len(coo):
         dst = get_min_distance(line, numpy.array(coo))
         return idxs[0][abs(dst) <= buffer_distance]
     else:
         print('   Warning: no nodes found around the cross-section')
         return None
コード例 #14
0
ファイル: nrml04_parser.py プロジェクト: lcui24/hmtk
    def _parse_edge_to_line(cls, edge_string, dimension=2):
        '''
        For a string returned from the _xpath function, convert to an
        instance of a line class
        :param edge_string:
            List of nodes in format returned from _xpath
        :param int dimension:
            Number of dimenions - 2 (Long, Lat) or 3 (Long, Lat, Depth)

        '''
        coords = edge_string.text.split()

        if dimension == 3:
            # Long lat and depth
            edge = [
                Point(float(coords[iloc]), float(coords[iloc + 1]),
                      float(coords[iloc + 2]))
                for iloc in range(0, len(coords), dimension)
            ]
        else:
            # Only long & lat
            edge = [
                Point(float(coords[iloc]), float(coords[iloc + 1]))
                for iloc in range(0, len(coords), dimension)
            ]

        return Line(edge)
コード例 #15
0
    def make_rupture(self):
        # Create the rupture surface.
        upper_seismogenic_depth = 3.
        lower_seismogenic_depth = 15.
        dip = 90.
        mesh_spacing = 1.

        fault_trace_start = Point(28.531397, 40.8790859336)
        fault_trace_end = Point(28.85, 40.9)
        fault_trace = Line([fault_trace_start, fault_trace_end])
        default_arguments = {
            'mag':
            6.5,
            'rake':
            180.,
            'tectonic_region_type':
            const.TRT.STABLE_CONTINENTAL,
            'hypocenter':
            Point(28.709146553353872, 40.890863701462457, 11.0),
            'surface':
            SimpleFaultSurface.from_fault_data(fault_trace,
                                               upper_seismogenic_depth,
                                               lower_seismogenic_depth,
                                               dip=dip,
                                               mesh_spacing=mesh_spacing),
            'rupture_slip_direction':
            0.,
            'occurrence_rate':
            0.01,
            'temporal_occurrence_model':
            PoissonTOM(50)
        }
        kwargs = default_arguments
        rupture = ParametricProbabilisticRupture(**kwargs)
        return rupture
コード例 #16
0
 def test_fault_trace_points(self):
     """
     The fault trace must have at least two points.
     """
     fault_trace = Line([Point(0.0, 0.0)])
     self.assertRaises(ValueError, SimpleFaultSurface.check_fault_data,
                       fault_trace, 0.0, 1.0, 90.0, 1.0)
コード例 #17
0
    def test_get_dip_2(self):
        p1 = Point(0.0, 0.0)
        p2 = Point(0.0635916966572, 0.0635916574897)

        surface = SimpleFaultSurface.from_fault_data(Line([p1, p2]), 1.0, 6.0,
                                                     30.0, 1.0)

        self.assertAlmostEquals(30.0, surface.get_dip(), 1)
コード例 #18
0
    def test_get_strike_1(self):
        p1 = Point(0.0, 0.0)
        p2 = Point(0.0635916966572, 0.0635916574897)

        surface = SimpleFaultSurface.from_fault_data(Line([p1, p2]), 1.0, 6.0,
                                                     89.9, 1.0)

        self.assertAlmostEquals(45.0, surface.get_strike(), delta=1e-4)
コード例 #19
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)
コード例 #20
0
 def test_inclined_non_planar_surface(self):
     p1 = Point(0.1, 0.1, 0.0)
     p2 = Point(0.1, 0.117986432118, 0.0)
     p3 = Point(0.117986470254, 0.117986426305, 0.0)
     p4 = Point(0.117986470254, 0.0999999941864, 0.0)
     surface = SimpleFaultSurface.from_fault_data(Line([p1, p2, p3, p4]),
                                                  2.0, 4.0, 30.0, 1.0)
     self.assertAlmostEqual(surface.get_width(), 4.0, places=2)
コード例 #21
0
    def test_get_strike_2(self):
        p1 = Point(0.0, 0.0)
        p2 = Point(0.0635916966572, 0.0635916574897)
        p3 = Point(0.0860747816618, 0.102533437776)

        surface = SimpleFaultSurface.from_fault_data(Line([p1, p2, p3]), 1.0,
                                                     6.0, 89.9, 1.0)

        self.assertAlmostEqual(40.0, surface.get_strike(), delta=0.02)
コード例 #22
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)
        )
コード例 #23
0
    def test_get_dip_1(self):
        p1 = Point(0.0, 0.0)
        p2 = Point(0.0635916966572, 0.0635916574897)
        p3 = Point(0.0860747816618, 0.102533437776)

        surface = SimpleFaultSurface.from_fault_data(Line([p1, p2, p3]), 1.0,
                                                     6.0, 90.0, 1.0)

        self.assertAlmostEquals(90.0, surface.get_dip(), delta=1e-6)
コード例 #24
0
    def test_get_mesh_5(self):
        p1 = Point(179.9, 0.0)
        p2 = Point(180.0, 0.0)
        p3 = Point(-179.9, 0.0)

        fault = SimpleFaultSurface.from_fault_data(Line([p1, p2, p3]), 1.0,
                                                   6.0, 90.0, 1.0)

        self.assert_mesh_is(fault, test_data.TEST_5_MESH)
コード例 #25
0
    def test_get_fault_vertices_3d(self):
        p0, p1, p2, p3 = SimpleFaultSurface.get_fault_patch_vertices(
            Line([Point(10., 45.2),
                  Point(10.5, 45.3),
                  Point(10., 45.487783)]),
            upper_seismogenic_depth=0.,
            lower_seismogenic_depth=14.,
            dip=30,
            index_patch=1.)
        p4, p5, p6, p7 = SimpleFaultSurface.get_fault_patch_vertices(
            Line([Point(10., 45.2),
                  Point(10.5, 45.3),
                  Point(10., 45.487783)]),
            upper_seismogenic_depth=0.,
            lower_seismogenic_depth=14.,
            dip=30,
            index_patch=2.)
        # Test for the first patch
        self.assertAlmostEqual(p0.longitude, 10., delta=0.1)
        self.assertAlmostEqual(p0.latitude, 45.2, delta=0.1)
        self.assertAlmostEqual(p0.depth, 0., delta=0.1)
        self.assertAlmostEqual(p1.longitude, 10.5, delta=0.1)
        self.assertAlmostEqual(p1.latitude, 45.3, delta=0.1)
        self.assertAlmostEqual(p1.depth, 0., delta=0.1)
        self.assertAlmostEqual(p2.longitude, 10.81, delta=0.1)
        self.assertAlmostEqual(p2.latitude, 45.2995, delta=0.1)
        self.assertAlmostEqual(p2.depth, 14., delta=0.1)
        self.assertAlmostEqual(p3.longitude, 10.31, delta=0.1)
        self.assertAlmostEqual(p3.latitude, 45.1995, delta=0.1)
        self.assertAlmostEqual(p3.depth, 14., delta=0.1)

        # Test for the second patch
        self.assertAlmostEqual(p4.longitude, 10.5, delta=0.1)
        self.assertAlmostEqual(p4.latitude, 45.3, delta=0.1)
        self.assertAlmostEqual(p4.depth, 0., delta=0.1)
        self.assertAlmostEqual(p5.longitude, 10.0, delta=0.1)
        self.assertAlmostEqual(p5.latitude, 45.4877, delta=0.1)
        self.assertAlmostEqual(p5.depth, 0., delta=0.1)
        self.assertAlmostEqual(p6.longitude, 10.311, delta=0.1)
        self.assertAlmostEqual(p6.latitude, 45.4873, delta=0.1)
        self.assertAlmostEqual(p6.depth, 14., delta=0.1)
        self.assertAlmostEqual(p7.longitude, 10.81, delta=0.1)
        self.assertAlmostEqual(p7.latitude, 45.2995, delta=0.1)
        self.assertAlmostEqual(p7.depth, 14., delta=0.1)
コード例 #26
0
 def test_dip_90_three_points(self):
     polygon = SimpleFaultSurface.surface_projection_from_fault_data(
         Line([Point(1, -20), Point(1, -20.2), Point(2, -19.7)]),
         dip=90,
         upper_seismogenic_depth=30, lower_seismogenic_depth=50,
     )
     elons = [1, 1, 2]
     elats = [-20.2, -20., -19.7]
     numpy.testing.assert_allclose(polygon.lons, elons)
     numpy.testing.assert_allclose(polygon.lats, elats)
コード例 #27
0
 def test_dip_90_self_intersection(self):
     polygon = SimpleFaultSurface.surface_projection_from_fault_data(
         Line([Point(1, -2), Point(2, -1.9), Point(3, -2.1), Point(4, -2)]),
         dip=90,
         upper_seismogenic_depth=10, lower_seismogenic_depth=20,
     )
     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)
コード例 #28
0
    def test_get_mesh_topo(self):
        p1 = Point(0.0, 0.0, -2.0)
        p2 = Point(0.0, 0.0359728811759, -2.0)
        p3 = Point(0.0190775080917, 0.0550503815182, -2.0)
        p4 = Point(0.03974514139, 0.0723925718856, -2.0)

        fault = SimpleFaultSurface.from_fault_data(Line([p1, p2, p3, p4]),
                                                   -2.0, 2.0, 90.0, 1.0)

        self.assert_mesh_is(fault, test_data.TEST_TOPO_MESH)
コード例 #29
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))
コード例 #30
0
    def test_get_mesh_1(self):
        p1 = Point(0.0, 0.0, 0.0)
        p2 = Point(0.0, 0.0359728811759, 0.0)
        p3 = Point(0.0190775080917, 0.0550503815182, 0.0)
        p4 = Point(0.03974514139, 0.0723925718856, 0.0)

        fault = SimpleFaultSurface.from_fault_data(
            Line([p1, p2, p3, p4]), 0.0, 4.2426406871192848, 45.0, 1.0)

        self.assert_mesh_is(fault, test_data.TEST_1_MESH)
コード例 #31
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)
コード例 #32
0
ファイル: configure.py プロジェクト: luisera/gmpe-smtk
    def get_target_sites_mesh(self, maximum_distance, spacing, vs30,
                              vs30measured=True, z1pt0=None, z2pt5=None):
        """
        Renders a two dimensional mesh of points over the rupture surface
        """
        # Get bounding box of dilated rupture
        lowx, highx, lowy, highy = self._get_limits_maximum_rjb(
            maximum_distance)
        # Create bounding box lines and then resample at spacing
        ewline = Line([Point(lowx, highy, 0.), Point(highx, highy, 0.)])
        nsline = Line([Point(lowx, highy, 0.), Point(lowx, lowy, 0.)])
        ewline = ewline.resample(spacing)
        nsline = nsline.resample(spacing)
        xvals = np.array([pnt.longitude for pnt in ewline.points])
        yvals = np.array([pnt.latitude for pnt in nsline.points])

        gridx, gridy = np.meshgrid(xvals, yvals)

        numx, numy = np.shape(gridx)
        npts = numx * numy
        gridx = (np.reshape(gridx, npts, 1)).flatten()
        gridy = (np.reshape(gridy, npts, 1)).flatten()
        site_list = []

        if not z1pt0:
            z1pt0 = vs30_to_z1pt0_as08(vs30)

        if not z2pt5:
            z2pt5 = z1pt0_to_z2pt5(z1pt0)

        for iloc in range(0, npts):
            site_list.append(Site(Point(gridx[iloc], gridy[iloc], 0.),
                                  vs30,
                                  vs30measured,
                                  z1pt0,
                                  z2pt5))
        self.target_sites = SiteCollection(site_list)
        return self.target_sites
コード例 #33
0
    def read_fault_geometry(self, geo_dict, mesh_spacing=1.0):
        '''
        Creates the fault geometry from the parameters specified in the
        dictionary.

        :param dict geo_dict:
            Sub-dictionary of main fault dictionary containing only
            the geometry attributes
        :param float mesh_spacing:
            Fault mesh spacing (km)
        :returns:
            Instance of SimpleFaultGeometry or ComplexFaultGeometry, depending
            on typology
        '''
        if geo_dict['Fault_Typology'] == 'Simple':
            # Simple fault geometry
            raw_trace = geo_dict['Fault_Trace']
            trace = Line([Point(raw_trace[ival], raw_trace[ival + 1])
                          for ival in range(0, len(raw_trace), 2)])
            geometry = SimpleFaultGeometry(trace,
                                           geo_dict['Dip'],
                                           geo_dict['Upper_Depth'],
                                           geo_dict['Lower_Depth'],
                                           mesh_spacing)

        elif geo_dict['Fault_Typology'] == 'Complex':
            # Complex Fault Typology
            trace = []
            for raw_trace in geo_dict['Fault_Trace']:
                fault_edge = Line(
                    [Point(raw_trace[ival], raw_trace[ival + 1],
                           raw_trace[ival + 2]) for ival in range(0, len(raw_trace),
                                                                  3)])
                trace.append(fault_edge)
            geometry = ComplexFaultGeometry(trace, mesh_spacing)
        else:
            raise ValueError('Unrecognised or unsupported fault geometry!')
        return geometry