Coverage for /usr/local/lib/python3.11/dist-packages/pyrocko/scenario/sources/pseudodynrupture.py: 83%

59 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-09-30 08:22 +0000

1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

4# ---|P------/S----------~Lg---------- 

5 

6''' 

7Pseudo dynamic rupture random source generator. 

8''' 

9 

10import numpy as num 

11 

12from pyrocko.guts import Float, Int 

13from pyrocko import gf 

14 

15from .base import SourceGenerator 

16 

17km = 1e3 

18guts_prefix = 'pf.scenario' 

19 

20 

21class PseudoDynamicRuptureGenerator(SourceGenerator): 

22 depth_min = Float.T( 

23 default=0.0) 

24 depth_max = Float.T( 

25 default=5*km) 

26 decimation_factor = Int.T( 

27 default=1) 

28 

29 slip_min = Float.T( 

30 optional=True) 

31 slip_max = Float.T( 

32 optional=True) 

33 

34 strike = Float.T( 

35 optional=True) 

36 dip = Float.T( 

37 optional=True) 

38 rake = Float.T( 

39 optional=True) 

40 depth = Float.T( 

41 optional=True) 

42 nx = Int.T( 

43 default=5, 

44 optional=True) 

45 ny = Int.T( 

46 default=5, 

47 optional=True) 

48 nucleation_x = Float.T( 

49 optional=True) 

50 nucleation_y = Float.T( 

51 optional=True) 

52 

53 width = Float.T( 

54 optional=True) 

55 length = Float.T( 

56 optional=True) 

57 

58 gamma = Float.T( 

59 default=0.8) 

60 

61 def draw_slip(self, rstate): 

62 if self.slip_min is not None and self.slip_max is not None: 

63 return rstate.uniform(self.slip_min, self.slip_max) 

64 else: 

65 return rstate.rand() 

66 

67 def get_source(self, ievent): 

68 rstate = self.get_rstate(ievent) 

69 time = rstate.uniform(self.time_min, self.time_max) 

70 lat, lon = self.get_latlon(ievent) 

71 depth = rstate.uniform(self.depth_min, self.depth_max) 

72 nucleation_x = self.nucleation_x if self.nucleation_x is not None \ 

73 else rstate.uniform(-1., 1.) 

74 nucleation_y = self.nucleation_y if self.nucleation_y is not None \ 

75 else rstate.uniform(-1., 1.) 

76 

77 def scale_from_slip(slip, a, b): 

78 return 10**((num.log10(slip) - a) / b) 

79 

80 if self.slip_min is not None and self.slip_max is not None: 

81 slip = self.draw_slip(rstate) 

82 # After K. Thingbaijam et al. (2017) - Tab. 2, Normal faulting 

83 length = scale_from_slip(slip, a=-2.302, b=1.302) 

84 width = scale_from_slip(slip, a=-3.698, b=2.512) 

85 

86 else: 

87 slip = self.draw_slip(rstate) 

88 length = scale_from_slip(slip, a=-2.302, b=1.302) 

89 width = scale_from_slip(slip, a=-3.698, b=2.512) 

90 

91 length = length if not self.length else self.length 

92 width = width if not self.width else self.width 

93 depth = depth if not self.depth else self.depth 

94 

95 if self.strike is None and self.dip is None and self.rake is None: 

96 strike, rake = rstate.uniform(-180., 180., 2) 

97 dip = rstate.uniform(0., 90.) 

98 else: 

99 if None in (self.strike, self.dip, self.rake): 

100 raise ValueError( 

101 'PseudoDynamicRuptureGenerator: ' 

102 'strike, dip, rake must be used in combination.') 

103 

104 strike = self.strike 

105 dip = self.dip 

106 rake = self.rake 

107 

108 source = gf.PseudoDynamicRupture( 

109 time=float(time), 

110 lat=float(lat), 

111 lon=float(lon), 

112 anchor='top', 

113 depth=float(depth), 

114 length=float(length), 

115 width=float(width), 

116 strike=float(strike), 

117 dip=float(dip), 

118 rake=float(rake), 

119 slip=slip, 

120 nucleation_x=float(nucleation_x), 

121 nucleation_y=float(nucleation_y), 

122 nx=self.nx, 

123 ny=self.ny, 

124 decimation_factor=self.decimation_factor, 

125 smooth_rupture=True, 

126 gamma=self.gamma) 

127 

128 return source 

129 

130 def add_map_artists(self, automap): 

131 for source in self.get_sources(): 

132 automap.gmt.psxy( 

133 in_rows=source.outline(cs='lonlat'), 

134 L='+p2p,black', 

135 W='1p,black', 

136 G='black', 

137 t=50, 

138 *automap.jxyr)