def planar_fault_surface_from_dict(data, mesh_spacing=1.): """ Builds a planar fault surface from the json load """ assert "PlanarSurface" in data top_left = Point(data["top_left"][0], data["top_left"][1], data["top_left"][2]) top_right = Point(data["top_right"][0], data["top_right"][1], data["top_right"][2]) bottom_left = Point(data["bottom_left"][0], data["bottom_left"][1], data["bottom_left"][2]) bottom_right = Point(data["bottom_right"][0], data["bottom_right"][1], data["bottom_right"][2]) return PlanarSurface.from_corner_points(mesh_spacing, top_left, top_right, bottom_right, bottom_left)
def _setup_peer_test_bending_fault_config(): """ The GC2 tests will be based on variations of the PEER bending fault test case: (Fault is dipping east north east Point 5 (-65.0, 0.0, 0.0) o | | | o Point 4 (-65.0, -0.16188, 0) \ \ \ \ \ o Point 3 (-64.90498, -0.36564, 0.0) \__ \__ \__ \__ \__Point 2 (-64.80164, -0.45236, 0.0) \o---o Point 1 (-64.78365, -0.45236, 0.0) """ # Build separate faults # Get down-dip points - dipping east-noth-east strike1 = PNT1.azimuth(PNT2) dipdir1 = (strike1 + 90.) % 360.0 strike2 = PNT2.azimuth(PNT3) dipdir2 = (strike2 + 90.) % 360.0 strike3 = PNT3.azimuth(PNT4) dipdir3 = (strike3 + 90.) % 360.0 strike4 = PNT4.azimuth(PNT5) dipdir4 = (strike4 + 90.) % 360.0 global_strike = PNT1.azimuth(PNT5) global_dipdir = (global_strike + 90.) % 360.0 # Get lower trace usd = 0.0 lsd = 12.0 dip = 60.0 as_length = lsd / numpy.tan(numpy.radians(dip)) PNT1b = PNT1.point_at(as_length, lsd, global_dipdir) PNT2b = PNT2.point_at(as_length, lsd, global_dipdir) PNT3b = PNT3.point_at(as_length, lsd, global_dipdir) PNT4b = PNT4.point_at(as_length, lsd, global_dipdir) PNT5b = PNT5.point_at(as_length, lsd, global_dipdir) # As simple fault dipping east mesh_spacing = 0.5 simple_fault1 = SimpleFaultSurface.from_fault_data( Line([PNT1, PNT2, PNT3, PNT4, PNT5]), usd, lsd, dip, mesh_spacing) # As a set of planes describing a concordant "Stirling fault" stirling_planes = [ PlanarSurface.from_corner_points(PNT1, PNT2, PNT2b, PNT1b), PlanarSurface.from_corner_points(PNT2, PNT3, PNT3b, PNT2b), PlanarSurface.from_corner_points(PNT3, PNT4, PNT4b, PNT3b), PlanarSurface.from_corner_points(PNT4, PNT5, PNT5b, PNT4b) ] stirling_fault1 = MultiSurface(stirling_planes) # As a set of planes describing a concordant "Frankel Fault" # In the Frankel fault each segment is projected to the local dip direction dipdir2b = (dipdir2 + 180.) % 360.0 frankel_planes = [ PlanarSurface.from_corner_points( PNT1, PNT2, PNT2.point_at(as_length, lsd, dipdir1), PNT1.point_at(as_length, lsd, dipdir1)), PlanarSurface.from_corner_points( PNT2, PNT3, PNT3.point_at(as_length, lsd, dipdir2), PNT2.point_at(as_length, lsd, dipdir2)), PlanarSurface.from_corner_points( PNT3, PNT4, PNT4.point_at(as_length, lsd, dipdir3), PNT3.point_at(as_length, lsd, dipdir3)), PlanarSurface.from_corner_points( PNT4, PNT5, PNT5.point_at(as_length, lsd, dipdir4), PNT4.point_at(as_length, lsd, dipdir4)) ] frankel_fault1 = MultiSurface(frankel_planes) # Test the case of a discordant Frankel plane # Swapping the strike of the second segment to change the dip direction # Also increasing the dip from 60 degrees to 75 degrees as_length_alt = lsd / numpy.tan(numpy.radians(75.0)) frankel_discordant = [ PlanarSurface.from_corner_points( PNT1, PNT2, PNT2.point_at(as_length, lsd, dipdir1), PNT1.point_at(as_length, lsd, dipdir1)), PlanarSurface.from_corner_points( PNT3, PNT2, PNT2.point_at(as_length_alt, lsd, dipdir2b), PNT3.point_at(as_length_alt, lsd, dipdir2b)), PlanarSurface.from_corner_points( PNT3, PNT4, PNT4.point_at(as_length, lsd, dipdir3), PNT3.point_at(as_length, lsd, dipdir3)), PlanarSurface.from_corner_points( PNT4, PNT5, PNT5.point_at(as_length, lsd, dipdir4), PNT4.point_at(as_length, lsd, dipdir4)) ] frankel_fault2 = MultiSurface(frankel_discordant) return simple_fault1, stirling_fault1, frankel_fault1, frankel_fault2
def _setup_peer_test_bending_fault_config(): """ The GC2 tests will be based on variations of the PEER bending fault test case: (Fault is dipping east north east Point 5 (-65.0, 0.0, 0.0) o | | | o Point 4 (-65.0, -0.16188, 0) \ \ \ \ \ o Point 3 (-64.90498, -0.36564, 0.0) \__ \__ \__ \__ \__Point 2 (-64.80164, -0.45236, 0.0) \o---o Point 1 (-64.78365, -0.45236, 0.0) """ # Build separate faults # Get down-dip points - dipping east-noth-east strike1 = PNT1.azimuth(PNT2) dipdir1 = (strike1 + 90.) % 360.0 strike2 = PNT2.azimuth(PNT3) dipdir2 = (strike2 + 90.) % 360.0 strike3 = PNT3.azimuth(PNT4) dipdir3 = (strike3 + 90.) % 360.0 strike4 = PNT4.azimuth(PNT5) dipdir4 = (strike4 + 90.) % 360.0 global_strike = PNT1.azimuth(PNT5) global_dipdir = (global_strike + 90.) % 360.0 # Get lower trace usd = 0.0 lsd = 12.0 dip = 60.0 as_length = lsd / numpy.tan(numpy.radians(dip)) PNT1b = PNT1.point_at(as_length, lsd, global_dipdir) PNT2b = PNT2.point_at(as_length, lsd, global_dipdir) PNT3b = PNT3.point_at(as_length, lsd, global_dipdir) PNT4b = PNT4.point_at(as_length, lsd, global_dipdir) PNT5b = PNT5.point_at(as_length, lsd, global_dipdir) # As simple fault dipping east mesh_spacing = 0.5 simple_fault1 = SimpleFaultSurface.from_fault_data( Line([PNT1, PNT2, PNT3, PNT4, PNT5]), usd, lsd, dip, mesh_spacing) # As a set of planes describing a concordant "Stirling fault" stirling_planes = [ PlanarSurface.from_corner_points(1.0, PNT1, PNT2, PNT2b, PNT1b), PlanarSurface.from_corner_points(1.0, PNT2, PNT3, PNT3b, PNT2b), PlanarSurface.from_corner_points(1.0, PNT3, PNT4, PNT4b, PNT3b), PlanarSurface.from_corner_points(1.0, PNT4, PNT5, PNT5b, PNT4b) ] stirling_fault1 = MultiSurface(stirling_planes) # As a set of planes describing a concordant "Frankel Fault" # In the Frankel fault each segment is projected to the local dip direction dipdir2b = (dipdir2 + 180.) % 360.0 frankel_planes = [ PlanarSurface.from_corner_points( 1.0, PNT1, PNT2, PNT2.point_at(as_length, lsd, dipdir1), PNT1.point_at(as_length, lsd, dipdir1) ), PlanarSurface.from_corner_points( 1.0, PNT2, PNT3, PNT3.point_at(as_length, lsd, dipdir2), PNT2.point_at(as_length, lsd, dipdir2) ), PlanarSurface.from_corner_points( 1.0, PNT3, PNT4, PNT4.point_at(as_length, lsd, dipdir3), PNT3.point_at(as_length, lsd, dipdir3) ), PlanarSurface.from_corner_points( 1.0, PNT4, PNT5, PNT5.point_at(as_length, lsd, dipdir4), PNT4.point_at(as_length, lsd, dipdir4) ) ] frankel_fault1 = MultiSurface(frankel_planes) # Test the case of a discordant Frankel plane # Swapping the strike of the second segment to change the dip direction # Also increasing the dip from 60 degrees to 75 degrees as_length_alt = lsd / numpy.tan(numpy.radians(75.0)) frankel_discordant = [ PlanarSurface.from_corner_points( 1.0, PNT1, PNT2, PNT2.point_at(as_length, lsd, dipdir1), PNT1.point_at(as_length, lsd, dipdir1) ), PlanarSurface.from_corner_points( 1.0, PNT3, PNT2, PNT2.point_at(as_length_alt, lsd, dipdir2b), PNT3.point_at(as_length_alt, lsd, dipdir2b) ), PlanarSurface.from_corner_points( 1.0, PNT3, PNT4, PNT4.point_at(as_length, lsd, dipdir3), PNT3.point_at(as_length, lsd, dipdir3) ), PlanarSurface.from_corner_points( 1.0, PNT4, PNT5, PNT5.point_at(as_length, lsd, dipdir4), PNT4.point_at(as_length, lsd, dipdir4) ) ] frankel_fault2 = MultiSurface(frankel_discordant) return simple_fault1, stirling_fault1, frankel_fault1, frankel_fault2
def build_ruptures(self, centroid, strikes, dips, lengths, widths, hypo_locs): """ Builds the rupture set """ ruptures = [] rstrikes = strikes * np.pi / 180. rdips = dips * np.pi / 180. for (strike, rstrike, dip, rdip, length, width, hypo_loc) in zip(strikes, rstrikes, dips, rdips, lengths, widths, hypo_locs): # Deal with the dip part first area = length * width updip_width = hypo_loc[1] * width downdip_width = (1.0 - hypo_loc[1]) * width updip_depth_change = updip_width * np.sin(rdip) downdip_depth_change = downdip_width * np.sin(rdip) if centroid.depth < updip_depth_change: # This would move the rupture above the top surface # readjust offset = updip_depth_change - centroid.depth updip_depth_change = centroid.depth downdip_depth_change += offset if downdip_depth_change > (self.lsd - centroid.depth): if (updip_depth_change + downdip_depth_change) >\ self.thickness: # Determine excess width offset = (centroid.depth + downdip_depth_change) - self.lsd offset_area = length * (offset / np.sin(rdip)) rw_max = self.thickness / np.sin(rdip) length += (offset_area / rw_max) updip_depth_change = centroid.depth downdip_depth_change = self.lsd - centroid.depth else: # This would move the rupture below the lower surface offset = (centroid.depth + downdip_depth_change) - self.lsd downdip_depth_change = self.lsd - centroid.depth updip_depth_change += offset updip_surface_length = updip_depth_change / np.tan(rdip) downdip_surface_length = downdip_depth_change / np.tan(rdip) # Now deal with strike parts left_length = hypo_loc[0] * length right_length = (1.0 - hypo_loc[0]) * length # Build corner points downdip_dir = (dip + 90.0) % 360 updip_dir = (dip - 90.0) % 360 mid_left = centroid.point_at(left_length, 0.0, (strike + 180.) % 360.) mid_right = centroid.point_at(right_length, 0.0, strike) top_left = mid_left.point_at(updip_surface_length, -updip_depth_change, updip_dir) top_right = mid_right.point_at(updip_surface_length, -updip_depth_change, updip_dir) bottom_left = mid_left.point_at(downdip_surface_length, downdip_depth_change, downdip_dir) bottom_right = mid_right.point_at(downdip_surface_length, downdip_depth_change, downdip_dir) try: surface = PlanarSurface.from_corner_points( top_left, top_right, bottom_right, bottom_left) except: print(strike, dip, length, width, hypo_loc) print(top_left, top_right, bottom_right, bottom_left) raise ValueError ruptures.append(surface) return ruptures