def setUp(self): hsmpl = 4 vsmpl = 2 idl = False alg = False # Create the surface of each section path = os.path.join(BASE_DATA_PATH, 'profiles00') prf, _ = kst._read_profiles(path) sfc_a = KiteSurface.from_profiles(prf, vsmpl, hsmpl, idl, alg) path = os.path.join(BASE_DATA_PATH, 'profiles01') prf, _ = kst._read_profiles(path) sfc_b = KiteSurface.from_profiles(prf, vsmpl, hsmpl, idl, alg) path = os.path.join(BASE_DATA_PATH, 'profiles02') prf, _ = kst._read_profiles(path) sfc_c = KiteSurface.from_profiles(prf, vsmpl, hsmpl, idl, alg) # Sections list sections = { "0": FaultSection('0', sfc_a), "1": FaultSection('1', sfc_b), "2": FaultSection('2', sfc_c) } # Rupture indexes rup_idxs = [['0'], ['1'], ['2'], ['0', '1'], ['0', '2'], ['1', '2'], ['0', '1', '2']] # Magnitudes rup_mags = [5.8, 5.8, 5.8, 6.2, 6.2, 6.2, 6.5] rakes = [90.0, 90.0, 90.0, 90.0, 90.0, 90.0, 90.0] # Occurrence probabilities of occurrence pmfs = [ PMF([[0.90, 0], [0.10, 1]]), PMF([[0.90, 0], [0.10, 1]]), PMF([[0.90, 0], [0.10, 1]]), PMF([[0.90, 0], [0.10, 1]]), PMF([[0.90, 0], [0.10, 1]]), PMF([[0.90, 0], [0.10, 1]]), PMF([[0.90, 0], [0.10, 1]]) ] self.sections = sections self.rup_idxs = rup_idxs self.pmfs = pmfs self.mags = rup_mags self.rakes = rakes
def test_build_mesh_02(self): # Trivial case - Vertical fault # Build the fault surface p_sd = 2.5 e_sd = 5.0 srfc = KiteSurface.from_profiles(self.profiles2, p_sd, e_sd) # The fault trace has a length of 0.5 degrees at the equator (along # meridians) which corresponds to a length of 111.3/2km = 55.65km. # Using a sampling distance of 5 km we get 12 equally spaced profiles. # Along the dip the fault width is 15 km. With a sampling of 2.5km # we get exactly 7 edges. msh = srfc.mesh np.testing.assert_equal(msh.lons.shape, (7, 12)) # Note that this mesh is flipped at the construction level self.assertTrue(np.all(np.abs(msh.depths[0, :]) < 1e-3)) self.assertTrue(np.all(np.abs(msh.depths[6, :] - 15.) < 1e-3)) self.assertTrue(np.all(np.abs(msh.lons[:, -1]) < 1e-3)) self.assertTrue(np.all(np.abs(msh.lons[:, 0] - 0.5) < 1e-2)) dip = srfc.get_dip() msg = "The value of dip computed is wrong: {:.3f}".format(dip) self.assertTrue(abs(dip - 90) < 0.5, msg) strike = srfc.get_strike() msg = "The value of strike computed is wrong.\n" msg += "computed: {:.3f} expected:".format(strike) self.assertTrue(abs(strike - 270) < 0.01, msg) if PLOTTING: title = 'Trivial case - Vertical fault' ppp(self.profiles2, srfc, title)
def test_build_mesh_01(self): # Trivial case - Fault dipping at about 45 degrees # Build the fault surface p_sd = 2.0 e_sd = 5.0 msh = KiteSurface.from_profiles(self.profiles1, p_sd, e_sd) # The fault trace has a length of 0.5 degrees at the equator (along # meridians) which corresponds to a length of # 111.3/2km = 55.65km. # Using a sampling distance of 5 km we get 12 equally spaced profiles. # Along the dip the fault width is ((0.15*110.567)**2+15**2)**.5 i.e. # 22.36km. With a sampling of 2.0km we get 12 edges. np.testing.assert_equal(msh.mesh.lons.shape, (12, 12)) # We take the last index since we are flipping the mesh to comply with # the right hand rule self.assertTrue(np.all(np.abs(msh.mesh.lons[:, -1]) < 1e-3)) # Tests the position of the center pnt = msh.get_center() tmp = (abs(msh.mesh.lons - pnt.longitude) + abs(msh.mesh.lats - pnt.latitude) + abs(msh.mesh.depths - pnt.depth) * 0.01) idx = np.unravel_index(np.argmin(tmp, axis=None), tmp.shape) msg = "We computed center of the surface is wrong" self.assertEqual(idx, (6, 6), msg) if PLOTTING: title = 'Trivial case - Fault dipping at about 45 degrees' ppp(self.profiles1, msh, title)
def setUp(self): # Read the profiles and create the surface path = os.path.join(BASE_DATA_PATH, 'profiles07') self.prf, _ = _read_profiles(path) hsmpl = 4 vsmpl = 2 idl = False alg = False self.srfc = KiteSurface.from_profiles(self.prf, vsmpl, hsmpl, idl, alg) # Create the mesh of sites - No need to define their depth step = 0.005 plons = [] plats = [] for lo in np.arange(9.9, 10.4, step): tlo = [] tla = [] for la in np.arange(44.6, 45.3, step): tlo.append(lo) tla.append(la) plons.append(tlo) plats.append(tla) self.mlons = np.array(plons) self.mlats = np.array(plats) self.mesh = Mesh(lons=self.mlons.flatten(), lats=self.mlats.flatten())
def test_get_area(self): hsmpl = 4 vsmpl = 2 idl = False alg = False srfc = KiteSurface.from_profiles(self.prf, vsmpl, hsmpl, idl, alg) area = srfc.get_area() self.assertAlmostEqual(271.3134, area, places=2)
def test_get_surface_projection(self): h_sampl = 2.5 v_sampl = 2.5 idl = False alg = True srfc = KiteSurface.from_profiles(self.profiles, v_sampl, h_sampl, idl, alg) lons, lats = srfc.surface_projection
def setUp(self): lons = [[np.nan, 0.05, 0.1, 0.15, 0.20], [0.00, 0.05, 0.1, 0.15, 0.20], [0.00, 0.05, 0.1, 0.15, 0.20], [0.00, 0.05, 0.1, 0.15, np.nan], [0.00, np.nan, 0.1, 0.15, np.nan]] lats = [[np.nan, 0.0, 0.0, 0.0, 0.0], [0.05, 0.05, 0.05, 0.05, 0.05], [0.10, 0.10, 0.10, 0.10, 0.10], [0.15, 0.15, 0.15, 0.15, np.nan], [0.20, np.nan, 0.20, 0.20, np.nan]] deps = [[np.nan, 0.0, 0.0, 0.0, 0.0], [5, 5, 5, 5, 5], [10, 10, 10, 10, 10], [15, 15, 15, 15, np.nan], [20, np.nan, 20, 20, np.nan]] self.lons = np.array(lons) self.lats = np.array(lats) self.deps = np.array(deps) self.mesh = Mesh(self.lons, self.lats, self.deps) self.ksfc = KiteSurface(self.mesh)
def test_ztor(self): # Create the mesh: two parallel profiles - no top alignment hsmpl = 4 vsmpl = 2 idl = False alg = False srfc = KiteSurface.from_profiles(self.prf, vsmpl, hsmpl, idl, alg) ztor = srfc.get_top_edge_depth() self.assertAlmostEqual(20.0, ztor)
def setUp(self): path = os.path.join(BASE_DATA_PATH, 'profiles06') self.profiles, _ = _read_profiles(path) self.h_sampl = 2 self.v_sampl = 4 idl = False alg = False self.smsh = KiteSurface.from_profiles(self.profiles, self.v_sampl, self.h_sampl, idl, alg)
def test_get_width(self): # Test the calculation of the width h_sampl = 2.5 v_sampl = 2.5 idl = False alg = True srfc = KiteSurface.from_profiles(self.profiles, v_sampl, h_sampl, idl, alg) width = srfc.get_width() np.testing.assert_almost_equal(38.13112131, width)
def test_mesh_creation(self): # Create the mesh: two parallel profiles - no top alignment hsmpl = 4 vsmpl = 2 idl = False alg = False srfc = KiteSurface.from_profiles(self.prf, vsmpl, hsmpl, idl, alg) if PLOTTING: title = 'Test mesh creation' ppp(self.prf, srfc, title)
def test_build_kinked_mesh_01(self): # Trivial case - Fault dipping at about 45 degrees # Build the fault surface p_sd = 5.0 e_sd = 15.0 msh = KiteSurface.from_profiles(self.profiles1, p_sd, e_sd) if PLOTTING: title = 'Trivial case - Fault dipping at about 45 degrees' ppp(self.profiles1, msh, title)
def test_mesh_creation(self): # Create mesh from profiles for SA sampling = 40 idl = False alg = False smsh = KiteSurface.from_profiles(self.profiles, sampling, sampling, idl, alg) idx = np.isfinite(smsh.mesh.lons[:, :]) self.assertEqual(np.sum(np.sum(idx)), 205) if PLOTTING: title = 'Top of the slab' ppp(self.profiles, smsh, title)
def test_mesh_creation_no_alignment(self): """ Test construction of the mesh """ h_sampl = 4 v_sampl = 4 idl = False alg = False smsh = KiteSurface.from_profiles(self.profiles, v_sampl, h_sampl, idl, alg) self.assertTrue(np.all(~np.isnan(smsh.mesh.lons[0, :]))) if PLOTTING: title = 'Simple mesh creation - no top alignment' ppp(self.profiles, smsh, title)
def test_mesh_creation_with_alignment(self): # Test construction of the mesh h_sampl = 4 v_sampl = 4 idl = False alg = True smsh = KiteSurface.from_profiles(self.profiles, v_sampl, h_sampl, idl, alg) self.assertTrue(np.any(np.isnan(smsh.mesh.lons[0, :]))) if PLOTTING: title = 'Simple case: Top alignment' ppp(self.profiles, smsh, title)
def test_mesh_creation(self): """ Test construction of the mesh """ h_sampl = 5 v_sampl = 5 idl = False alg = False srfc = KiteSurface.from_profiles(self.profiles, v_sampl, h_sampl, idl, alg) smsh = srfc.mesh self.assertTrue(np.all(~np.isnan(smsh.lons[0, :]))) if PLOTTING: title = 'Simple case: No top alignment' ppp(self.profiles, srfc, title)
def test_mesh_creation_with_alignment(self): # Test construction of the mesh h_sampl = 2.5 v_sampl = 2.5 idl = False alg = True srfc = KiteSurface.from_profiles(self.profiles, v_sampl, h_sampl, idl, alg) self.assertTrue(np.any(np.isnan(srfc.mesh.lons[0, :]))) if PLOTTING: title = 'Simple case: Top alignment' title += '(IdealisedAsimmetricMeshTest)' ppp(self.profiles, srfc, title)
def setUp(self): path = os.path.join(BASE_DATA_PATH, 'profiles07') self.prf, _ = _read_profiles(path) hsmpl = 4 vsmpl = 2 idl = False alg = False self.srfc = KiteSurface.from_profiles(self.prf, vsmpl, hsmpl, idl, alg) coo = [] step = 0.025 for lo in np.arange(9.9, 10.4, step): for la in np.arange(44.6, 45.3, step): coo.append([lo, la]) coo = np.array(coo) self.mesh = Mesh(lons=coo[:, 0], lats=coo[:, 1])
def test_mesh_creation(self): # Create the mesh: two parallel profiles - no top alignment hsmpl = 4 vsmpl = 4 idl = False alg = False srfc = KiteSurface.from_profiles(self.prf, hsmpl, vsmpl, idl, alg) smsh = srfc.mesh # # Check the horizontal mesh spacing computed = [] for i in range(0, smsh.lons.shape[0]): tmp = [] for j in range(0, smsh.lons.shape[1] - 1): k = j + 1 dst = distance(smsh.lons[i, j], smsh.lats[i, j], smsh.depths[i, j], smsh.lons[i, k], smsh.lats[i, k], smsh.depths[i, k]) tmp.append(dst) computed.append(dst) computed = np.array(computed) self.assertTrue(np.all(abs(computed - hsmpl) / vsmpl < 0.05)) # # Check the vertical mesh spacing computed = [] for i in range(0, smsh.lons.shape[0] - 1): tmp = [] k = i + 1 for j in range(0, smsh.lons.shape[1]): dst = distance(smsh.lons[i, j], smsh.lats[i, j], smsh.depths[i, j], smsh.lons[k, j], smsh.lats[k, j], smsh.depths[k, j]) tmp.append(dst) computed.append(dst) computed = np.array(computed) self.assertTrue(np.all(abs(computed - vsmpl) / vsmpl < 0.05)) if PLOTTING: title = 'Two parallel profiles' ppp(self.prf, srfc, title)
def test_compute_joyner_boore_distance(self): # Create the mesh: two parallel profiles - no top alignment hsmpl = 2 vsmpl = 2 idl = False alg = False srfc = KiteSurface.from_profiles(self.prf, vsmpl, hsmpl, idl, alg) plons = np.array([10.0, 10.15]) plats = np.array([45.0, 45.15]) mesh = Mesh(lons=plons, lats=plats) dsts = srfc.get_joyner_boore_distance(mesh) if PLOTTING: _ = plt.figure() plt.plot(srfc.mesh.lons, srfc.mesh.lats, '.', color='gray') plt.plot(plons, plats, 'o') plt.show() # Distance computed here: # https://www.movable-type.co.uk/scripts/latlong.html expected = np.array([13.61, 0.0]) np.testing.assert_almost_equal(np.array(dsts), expected, decimal=2)
class KiteSurfaceFromMeshTest(unittest.TestCase): """ Tests the method that creates the external boundary of the rupture. """ def setUp(self): lons = [[np.nan, 0.05, 0.1, 0.15, 0.20], [0.00, 0.05, 0.1, 0.15, 0.20], [0.00, 0.05, 0.1, 0.15, 0.20], [0.00, 0.05, 0.1, 0.15, np.nan], [0.00, np.nan, 0.1, 0.15, np.nan]] lats = [[np.nan, 0.0, 0.0, 0.0, 0.0], [0.05, 0.05, 0.05, 0.05, 0.05], [0.10, 0.10, 0.10, 0.10, 0.10], [0.15, 0.15, 0.15, 0.15, np.nan], [0.20, np.nan, 0.20, 0.20, np.nan]] deps = [[np.nan, 0.0, 0.0, 0.0, 0.0], [5, 5, 5, 5, 5], [10, 10, 10, 10, 10], [15, 15, 15, 15, np.nan], [20, np.nan, 20, 20, np.nan]] self.lons = np.array(lons) self.lats = np.array(lats) self.deps = np.array(deps) self.mesh = Mesh(self.lons, self.lats, self.deps) self.ksfc = KiteSurface(self.mesh) def test_get_external_boundary(self): # This mesh does not comply with the right hand rule. In the init it # will be adjusted ksfc = self.ksfc idxs = ksfc._get_external_boundary_indexes() # Checking expected = [[0, 0], [0, 1], [0, 2], [0, 3], [1, 4], [2, 4], [3, 4], [4, 4], [3, 3], [4, 2], [4, 1], [2, 0], [1, 0]] np.testing.assert_almost_equal(expected, idxs) if PLOTTING: _, ax = plt.subplots(1, 1) ax.plot(self.lons.flatten(), self.lats.flatten(), 'o') lo, la = ksfc._get_external_boundary() ax.plot(lo, la, '-r') ax.invert_yaxis() plt.show() def test_get_dip(self): self.ksfc.get_dip() def test_get_cell_dimensions(self): ksfc = self.ksfc _, _, _, areas = ksfc.get_cell_dimensions() idx = np.isfinite(areas) # Computing the lenght and the width of the rectangle representing the # rupture surface. This includes the cells which are empty iul = (1, 0) iur = (1, -1) slen = distance(self.lons[iul], self.lats[iul], self.deps[iul], self.lons[iur], self.lats[iur], self.deps[iur]) iul = (0, 2) ill = (-1, 2) swid = distance(self.lons[iul], self.lats[iul], self.deps[iul], self.lons[ill], self.lats[ill], self.deps[ill]) # Computing the surface area as the total area minus the area of 4 # cells. Note that here we assume that cells have approx the same area expected = slen * swid / areas.size * (np.sum(idx)) perc_diff = abs(expected - np.sum(areas[idx])) / expected * 100 self.assertTrue(perc_diff < 0.5) def test_get_tor(self): """ test calculation of trace (i.e. surface projection of tor) """ lons = np.flipud([0.0, 0.05, 0.1, 0.15, 0.20]) lats = np.array([0.0, 0.0, 0.0, 0.0, 0.05]) tlo, tla = self.ksfc.get_tor() aae(lons, tlo) aae(lats, tla)