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-10-04 09:52 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2023-10-04 09:52 +0000
1# http://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6'''
7Pseudo dynamic rupture random source generator.
8'''
10import numpy as num
12from pyrocko.guts import Float, Int
13from pyrocko import gf
15from .base import SourceGenerator
17km = 1e3
18guts_prefix = 'pf.scenario'
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)
29 slip_min = Float.T(
30 optional=True)
31 slip_max = Float.T(
32 optional=True)
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)
53 width = Float.T(
54 optional=True)
55 length = Float.T(
56 optional=True)
58 gamma = Float.T(
59 default=0.8)
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()
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.)
77 def scale_from_slip(slip, a, b):
78 return 10**((num.log10(slip) - a) / b)
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)
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)
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
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.')
104 strike = self.strike
105 dip = self.dip
106 rake = self.rake
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)
128 return source
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)