cfs-python 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
cfs_lib/okada_math.py ADDED
@@ -0,0 +1,652 @@
1
+ import numpy as np
2
+
3
+ def coord_conversion(xgg, ygg, xs, ys, xf, yf, top, bottom, dip):
4
+ cx = (xf + xs) / 2.0
5
+ cy = (yf + ys) / 2.0
6
+ h = (bottom - top) / 2.0
7
+
8
+ k = np.tan(np.deg2rad(dip))
9
+ if k == 0:
10
+ k = 0.000001
11
+ d = h / k
12
+
13
+ # MATLAB: b = atan((yf-ys)./(xf-xs));
14
+ # To handle division by zero or use standard quadrant:
15
+ with np.errstate(divide='ignore', invalid='ignore'):
16
+ b = np.arctan((yf - ys) / (xf - xs))
17
+ b = np.where(np.isnan(b), np.pi/2 * np.sign(yf-ys), b)
18
+
19
+ ydipshift = np.abs(d * np.cos(b))
20
+ xdipshift = np.abs(d * np.sin(b))
21
+
22
+ if xf > xs:
23
+ if yf > ys:
24
+ cx = cx + xdipshift
25
+ cy = cy - ydipshift
26
+ else:
27
+ cx = cx - xdipshift
28
+ cy = cy - ydipshift
29
+ else:
30
+ if yf > ys:
31
+ cx = cx + xdipshift
32
+ cy = cy + ydipshift
33
+ else:
34
+ cx = cx - xdipshift
35
+ cy = cy + ydipshift
36
+
37
+ xn = (xgg - cx) * np.cos(b) + (ygg - cy) * np.sin(b)
38
+ yn = -(xgg - cx) * np.sin(b) + (ygg - cy) * np.cos(b)
39
+
40
+ if (xf - xs) < 0.0:
41
+ xn = -xn
42
+ yn = -yn
43
+
44
+ al = np.sqrt((xf - xs)**2 + (yf - ys)**2) / 2.0
45
+ aw = ((bottom - top) / 2.0) / np.sin(np.deg2rad(dip))
46
+
47
+ return xn, yn, al, aw
48
+
49
+
50
+ def tensor_trans(sinb, cosb, so):
51
+ """
52
+ so is shape (6, N)
53
+ returns sn of shape (6, N)
54
+ """
55
+ nn = so.shape[1]
56
+ t = np.zeros((6, 6))
57
+ sn = np.zeros((6, nn))
58
+
59
+ ver = np.pi / 2.0
60
+ bt = np.arcsin(sinb)
61
+
62
+ if cosb > 0.0:
63
+ xbeta, xdel = -bt, 0.0
64
+ ybeta, ydel = -bt + ver, 0.0
65
+ zbeta, zdel = -bt - ver, ver
66
+ else:
67
+ xbeta, xdel = bt - np.pi, 0.0
68
+ ybeta, ydel = bt - ver, 0.0
69
+ zbeta, zdel = bt - ver, ver
70
+
71
+ xl, xm, xn = np.cos(xdel)*np.cos(xbeta), np.cos(xdel)*np.sin(xbeta), np.sin(xdel)
72
+ yl, ym, yn = np.cos(ydel)*np.cos(ybeta), np.cos(ydel)*np.sin(ybeta), np.sin(ydel)
73
+ zl, zm, zn = np.cos(zdel)*np.cos(zbeta), np.cos(zdel)*np.sin(zbeta), np.sin(zdel)
74
+
75
+ t[0, 0] = xl * xl
76
+ t[0, 1] = xm * xm
77
+ t[0, 2] = xn * xn
78
+ t[0, 3] = 2.0 * xm * xn
79
+ t[0, 4] = 2.0 * xn * xl
80
+ t[0, 5] = 2.0 * xl * xm
81
+
82
+ t[1, 0] = yl * yl
83
+ t[1, 1] = ym * ym
84
+ t[1, 2] = yn * yn
85
+ t[1, 3] = 2.0 * ym * yn
86
+ t[1, 4] = 2.0 * yn * yl
87
+ t[1, 5] = 2.0 * yl * ym
88
+
89
+ t[2, 0] = zl * zl
90
+ t[2, 1] = zm * zm
91
+ t[2, 2] = zn * zn
92
+ t[2, 3] = 2.0 * zm * zn
93
+ t[2, 4] = 2.0 * zn * zl
94
+ t[2, 5] = 2.0 * zl * zm
95
+
96
+ t[3, 0] = yl * zl
97
+ t[3, 1] = ym * zm
98
+ t[3, 2] = yn * zn
99
+ t[3, 3] = ym * zn + zm * yn
100
+ t[3, 4] = yn * zl + zn * yl
101
+ t[3, 5] = yl * zm + zl * ym
102
+
103
+ t[4, 0] = zl * xl
104
+ t[4, 1] = zm * xm
105
+ t[4, 2] = zn * xn
106
+ t[4, 3] = xm * zn + zm * xn
107
+ t[4, 4] = xn * zl + zn * xl
108
+ t[4, 5] = xl * zm + zl * xm
109
+
110
+ t[5, 0] = xl * yl
111
+ t[5, 1] = xm * ym
112
+ t[5, 2] = xn * yn
113
+ t[5, 3] = xm * yn + ym * xn
114
+ t[5, 4] = xn * yl + yn * xl
115
+ t[5, 5] = xl * ym + yl * xm
116
+
117
+ for k in range(nn):
118
+ sn[:, k] = np.dot(t, so[:, k])
119
+
120
+ return sn
121
+
122
+ def dccon0(alpha, dip, n_cells):
123
+ p = {}
124
+
125
+ F0 = np.zeros(n_cells, dtype=np.float64)
126
+ F1 = np.ones(n_cells, dtype=np.float64)
127
+ F2 = np.ones(n_cells, dtype=np.float64) * 2.0
128
+ EPS = np.ones(n_cells, dtype=np.float64) * 1.0e-6
129
+
130
+ p['ALP1'] = (F1 - alpha) / F2
131
+ p['ALP2'] = alpha / F2
132
+ p['ALP3'] = (F1 - alpha) / alpha
133
+ p['ALP4'] = F1 - alpha
134
+ p['ALP5'] = alpha
135
+
136
+ P18 = (2.0 * np.pi) / 360.0
137
+ SD = np.sin(dip * P18)
138
+ CD = np.cos(dip * P18)
139
+
140
+ if np.isscalar(CD):
141
+ CD = np.full(n_cells, CD)
142
+ if np.isscalar(SD):
143
+ SD = np.full(n_cells, SD)
144
+
145
+ c1 = np.abs(CD) < EPS
146
+ c2 = np.abs(CD) >= EPS
147
+ s1 = SD > F0
148
+ s2 = SD == F0
149
+ s3 = SD < F0
150
+
151
+ CD = F0 * c1 + CD * c2
152
+ SD = c1 * (F1 * s1 + SD * s2 + (-1.0) * F1 * s3) + c2 * SD
153
+
154
+ p['SD'] = SD
155
+ p['CD'] = CD
156
+ p['SDSD'] = SD * SD
157
+ p['CDCD'] = CD * CD
158
+ p['SDCD'] = SD * CD
159
+ p['S2D'] = F2 * p['SDCD']
160
+ p['C2D'] = p['CDCD'] - p['SDSD']
161
+
162
+ return p
163
+
164
+ def dccon1(X, Y, D, n_cells):
165
+ # For point source station geom constants
166
+ p = {}
167
+ F0 = np.zeros(n_cells, dtype=np.float64)
168
+ F1 = np.ones(n_cells, dtype=np.float64)
169
+ F3 = np.ones(n_cells, dtype=np.float64) * 3.0
170
+ F5 = np.ones(n_cells, dtype=np.float64) * 5.0
171
+ EPS = np.ones(n_cells, dtype=np.float64) * 1.0e-6
172
+
173
+ c1 = np.abs(X) < EPS
174
+ c2 = np.abs(X) >= EPS
175
+ X = F0 * c1 + X * c2
176
+ c1 = np.abs(Y) < EPS
177
+ c2 = np.abs(Y) >= EPS
178
+ Y = F0 * c1 + Y * c2
179
+ c1 = np.abs(D) < EPS
180
+ c2 = np.abs(D) >= EPS
181
+ D = F0 * c1 + D * c2
182
+
183
+ # Need SD, CD from dccon0, handled in parent call context via arguments
184
+ # Wait, the MATLAB code uses globals SD & CD in DCCON1.
185
+ # I should pass them.
186
+ return X, Y, D
187
+
188
+ def dccon2(XI, ET, Q, SD, CD, n_cells):
189
+ p = {}
190
+ F0 = np.zeros(n_cells, dtype=np.float64)
191
+ F1 = np.ones(n_cells, dtype=np.float64)
192
+ F2 = np.ones(n_cells, dtype=np.float64) * 2.0
193
+ EPS = np.ones(n_cells, dtype=np.float64) * 1.0e-6
194
+
195
+ c1 = np.abs(XI) < EPS
196
+ c2 = np.abs(XI) >= EPS
197
+ XI = F0 * c1 + XI * c2
198
+ c1 = np.abs(ET) < EPS
199
+ c2 = np.abs(ET) >= EPS
200
+ ET = F0 * c1 + ET * c2
201
+ c1 = np.abs(Q) < EPS
202
+ c2 = np.abs(Q) >= EPS
203
+ Q = F0 * c1 + Q * c2
204
+
205
+ p['XI2'] = XI * XI
206
+ p['ET2'] = ET * ET
207
+ p['Q2'] = Q * Q
208
+ p['R2'] = p['XI2'] + p['ET2'] + p['Q2']
209
+ p['R'] = np.sqrt(p['R2'])
210
+
211
+ c1_zero = p['R'] == F0
212
+ if np.sum(c1_zero) > 0:
213
+ p['SINGULAR'] = True
214
+ else:
215
+ p['SINGULAR'] = False
216
+
217
+ p['R3'] = p['R'] * p['R2']
218
+ p['R5'] = p['R3'] * p['R2']
219
+ p['Y'] = ET * CD + Q * SD
220
+ p['D'] = ET * SD - Q * CD
221
+
222
+ c1_q = Q == F0
223
+ c2_q = Q != F0
224
+
225
+ with np.errstate(divide='ignore', invalid='ignore'):
226
+ val = np.arctan(XI * ET / (Q * p['R']))
227
+ val = np.where(np.isnan(val), 0.0, val)
228
+ p['TT'] = c1_q * F0 + c2_q * val
229
+
230
+ c1_xi = XI < F0
231
+ c3_et = ET == F0
232
+ c4_x = c1_xi & c1_q & c3_et
233
+ c5_x = ~c4_x
234
+
235
+ RXI = p['R'] + XI
236
+ with np.errstate(divide='ignore', invalid='ignore'):
237
+ lx = np.where(c4_x, -np.log(np.maximum(p['R'] - XI, 1e-12)), np.log(np.maximum(RXI, 1e-12)))
238
+ p['ALX'] = lx
239
+ x11 = np.where(c4_x, F0, F1 / (p['R'] * np.maximum(RXI, 1e-12)))
240
+ p['X11'] = x11
241
+ p['X32'] = np.where(c4_x, F0, (p['R'] + RXI) * x11 * x11 / np.maximum(p['R'], 1e-12))
242
+
243
+ c1_ett = ET < F0
244
+ c3_x = XI == F0
245
+ c4_y = c1_ett & c1_q & c3_x
246
+ c5_y = ~c4_y
247
+
248
+ RET = p['R'] + ET
249
+ with np.errstate(divide='ignore', invalid='ignore'):
250
+ le = np.where(c4_y, -np.log(np.maximum(p['R'] - ET, 1e-12)), np.log(np.maximum(RET, 1e-12)))
251
+ p['ALE'] = le
252
+ y11 = np.where(c4_y, F0, F1 / (p['R'] * np.maximum(RET, 1e-12)))
253
+ p['Y11'] = y11
254
+ p['Y32'] = np.where(c4_y, F0, (p['R'] + RET) * y11 * y11 / np.maximum(p['R'], 1e-12))
255
+
256
+ R = np.maximum(p['R'], 1e-12)
257
+ R3 = np.maximum(p['R3'], 1e-12)
258
+
259
+ p['EY'] = SD / R - p['Y'] * Q / R3
260
+ p['EZ'] = CD / R + p['D'] * Q / R3
261
+ p['FY'] = p['D'] / R3 + p['XI2'] * p['Y32'] * SD
262
+ p['FZ'] = p['Y'] / R3 + p['XI2'] * p['Y32'] * CD
263
+ p['GY'] = F2 * p['X11'] * SD - p['Y'] * Q * p['X32']
264
+ p['GZ'] = F2 * p['X11'] * CD + p['D'] * Q * p['X32']
265
+ p['HY'] = p['D'] * Q * p['X32'] + XI * Q * p['Y32'] * SD
266
+ p['HZ'] = p['Y'] * Q * p['X32'] + XI * Q * p['Y32'] * CD
267
+
268
+ return p
269
+
270
+ def UA(XI, ET, Q, DISL1, DISL2, DISL3, c0, c2, n_cells):
271
+ F0 = np.zeros(n_cells, dtype=np.float64)
272
+ F2 = np.ones(n_cells, dtype=np.float64) * 2.0
273
+ PI2 = np.ones(n_cells, dtype=np.float64) * (2.0 * np.pi)
274
+
275
+ DU = np.zeros((n_cells, 12), dtype=np.float64)
276
+ U = np.zeros((n_cells, 12), dtype=np.float64)
277
+
278
+ XY = XI * c2['Y11']
279
+ QX = Q * c2['X11']
280
+ QY = Q * c2['Y11']
281
+
282
+ # Strike Slip
283
+ c_1 = DISL1 != F0
284
+ du1 = np.zeros((n_cells, 12), dtype=np.float64)
285
+ du1[:,0] = c2['TT'] / F2 + c0['ALP2'] * XI * QY
286
+ du1[:,1] = c0['ALP2'] * Q / c2['R']
287
+ du1[:,2] = c0['ALP1'] * c2['ALE'] - c0['ALP2'] * Q * QY
288
+ du1[:,3] = -c0['ALP1'] * QY - c0['ALP2'] * c2['XI2'] * Q * c2['Y32']
289
+ du1[:,4] = -c0['ALP2'] * XI * Q / c2['R3']
290
+ du1[:,5] = c0['ALP1'] * XY + c0['ALP2'] * XI * c2['Q2'] * c2['Y32']
291
+ du1[:,6] = c0['ALP1'] * XY * c0['SD'] + c0['ALP2'] * XI * c2['FY'] + c2['D'] / F2 * c2['X11']
292
+ du1[:,7] = c0['ALP2'] * c2['EY']
293
+ du1[:,8] = c0['ALP1'] * (c0['CD'] / c2['R'] + QY * c0['SD']) - c0['ALP2'] * Q * c2['FY']
294
+ du1[:,9] = c0['ALP1'] * XY * c0['CD'] + c0['ALP2'] * XI * c2['FZ'] + c2['Y'] / F2 * c2['X11']
295
+ du1[:,10] = c0['ALP2'] * c2['EZ']
296
+ du1[:,11] = -c0['ALP1'] * (c0['SD'] / c2['R'] - QY * c0['CD']) - c0['ALP2'] * Q * c2['FZ']
297
+
298
+ for i in range(12):
299
+ U[:, i] += (DISL1 / PI2 * du1[:, i]) * c_1
300
+
301
+ # Dip Slip
302
+ c_2 = DISL2 != F0
303
+ du2 = np.zeros((n_cells, 12), dtype=np.float64)
304
+ du2[:,0] = c0['ALP2'] * Q / c2['R']
305
+ du2[:,1] = c2['TT'] / F2 + c0['ALP2'] * ET * QX
306
+ du2[:,2] = c0['ALP1'] * c2['ALX'] - c0['ALP2'] * Q * QX
307
+ du2[:,3] = -c0['ALP2'] * XI * Q / c2['R3']
308
+ du2[:,4] = -QY / F2 - c0['ALP2'] * ET * Q / c2['R3']
309
+ du2[:,5] = c0['ALP1'] / c2['R'] + c0['ALP2'] * c2['Q2'] / c2['R3']
310
+ du2[:,6] = c0['ALP2'] * c2['EY']
311
+ du2[:,7] = c0['ALP1'] * c2['D'] * c2['X11'] + XY / F2 * c0['SD'] + c0['ALP2'] * ET * c2['GY']
312
+ du2[:,8] = c0['ALP1'] * c2['Y'] * c2['X11'] - c0['ALP2'] * Q * c2['GY']
313
+ du2[:,9] = c0['ALP2'] * c2['EZ']
314
+ du2[:,10] = c0['ALP1'] * c2['Y'] * c2['X11'] + XY / F2 * c0['CD'] + c0['ALP2'] * ET * c2['GZ']
315
+ du2[:,11] = -c0['ALP1'] * c2['D'] * c2['X11'] - c0['ALP2'] * Q * c2['GZ']
316
+
317
+ for i in range(12):
318
+ U[:, i] += (DISL2 / PI2 * du2[:, i]) * c_2
319
+
320
+ # Tensile
321
+ c_3 = DISL3 != F0
322
+ du3 = np.zeros((n_cells, 12), dtype=np.float64)
323
+ du3[:,0] = -c0['ALP1'] * c2['ALE'] - c0['ALP2'] * Q * QY
324
+ du3[:,1] = -c0['ALP1'] * c2['ALX'] - c0['ALP2'] * Q * QX
325
+ du3[:,2] = c2['TT'] / F2 - c0['ALP2'] * (ET * QX + XI * QY)
326
+ du3[:,3] = -c0['ALP1'] * XY + c0['ALP2'] * XI * c2['Q2'] * c2['Y32']
327
+ du3[:,4] = -c0['ALP1'] / c2['R'] + c0['ALP2'] * c2['Q2'] / c2['R3']
328
+ du3[:,5] = -c0['ALP1'] * QY - c0['ALP2'] * Q * c2['Q2'] * c2['Y32']
329
+ du3[:,6] = -c0['ALP1'] * (c0['CD'] / c2['R'] + QY * c0['SD']) - c0['ALP2'] * Q * c2['FY']
330
+ du3[:,7] = -c0['ALP1'] * c2['Y'] * c2['X11'] - c0['ALP2'] * Q * c2['GY']
331
+ du3[:,8] = c0['ALP1'] * (c2['D'] * c2['X11'] + XY * c0['SD']) + c0['ALP2'] * Q * c2['HY']
332
+ du3[:,9] = c0['ALP1'] * (c0['SD'] / c2['R'] - QY * c0['CD']) - c0['ALP2'] * Q * c2['FZ']
333
+ du3[:,10] = c0['ALP1'] * c2['D'] * c2['X11'] - c0['ALP2'] * Q * c2['GZ']
334
+ du3[:,11] = c0['ALP1'] * (c2['Y'] * c2['X11'] + XY * c0['CD']) + c0['ALP2'] * Q * c2['HZ']
335
+
336
+ for i in range(12):
337
+ U[:, i] += (DISL3 / PI2 * du3[:, i]) * c_3
338
+
339
+ return U
340
+
341
+ def UB(XI, ET, Q, DISL1, DISL2, DISL3, c0, c2, n_cells):
342
+ F0 = np.zeros(n_cells, dtype=np.float64)
343
+ F1 = np.ones(n_cells, dtype=np.float64)
344
+ F2 = np.ones(n_cells, dtype=np.float64) * 2.0
345
+ PI2 = np.ones(n_cells, dtype=np.float64) * (2.0 * np.pi)
346
+
347
+ U = np.zeros((n_cells, 12), dtype=np.float64)
348
+
349
+ RD = c2['R'] + c2['D']
350
+ RD2 = RD * RD
351
+ D11 = F1 / (c2['R'] * np.maximum(RD, 1e-12))
352
+ AJ2 = XI * c2['Y'] / np.maximum(RD, 1e-12) * D11
353
+ AJ5 = -(c2['D'] + c2['Y'] * c2['Y'] / np.maximum(RD, 1e-12)) * D11
354
+
355
+ tempCD = np.copy(c0['CD'])
356
+ tempCDCD = np.copy(c0['CDCD'])
357
+ c_1 = c0['CD'] != F0
358
+ c_2 = c0['CD'] == F0
359
+ s_1 = XI == F0
360
+ s_2 = XI != F0
361
+
362
+ CD = c_1 * c0['CD'] + c_2 * 1.0e-12
363
+ CDCD = c_1 * c0['CDCD'] + c_2 * 1.0e-12
364
+
365
+ X = np.sqrt(c2['XI2'] + c2['Q2'])
366
+
367
+ val1 = F1 / CDCD * (XI / np.maximum(RD, 1e-12) * c0['SDCD'] + F2 * np.arctan((ET * (X + Q * CD) + X * (c2['R'] + X) * c0['SD']) / np.maximum((XI * (c2['R'] + X) * CD), 1e-12)))
368
+ val2 = XI * c2['Y'] / np.maximum(RD2 * F2, 1e-12)
369
+ AI4 = c_1 * (s_1 * F0 + s_2 * val1) + c_2 * val2
370
+
371
+ AI3 = c_1 * ((c2['Y'] * CD / np.maximum(RD, 1e-12) - c2['ALE'] + c0['SD'] * np.log(np.maximum(RD, 1e-12))) / CDCD) + c_2 * ((ET / np.maximum(RD, 1e-12) + c2['Y'] * Q / np.maximum(RD2, 1e-12) - c2['ALE']) / F2)
372
+
373
+ AK1 = c_1 * (XI * (D11 - c2['Y11'] * c0['SD']) / CD) + c_2 * (XI * Q / np.maximum(RD, 1e-12) * D11)
374
+ AK3 = c_1 * ((Q * c2['Y11'] - c2['Y'] * D11) / CD) + c_2 * (c0['SD'] / np.maximum(RD, 1e-12) * (c2['XI2'] * D11 - F1))
375
+ AJ3 = c_1 * ((AK1 - AJ2 * c0['SD']) / CD) + c_2 * (-XI / np.maximum(RD2, 1e-12) * (c2['Q2'] * D11 - F1 / F2))
376
+ AJ6 = c_1 * ((AK3 - AJ5 * c0['SD']) / CD) + c_2 * (-c2['Y'] / np.maximum(RD2, 1e-12) * (c2['XI2'] * D11 - F1 / F2))
377
+
378
+ XY = XI * c2['Y11']
379
+ AI1 = -XI / np.maximum(RD, 1e-12) * CD - AI4 * c0['SD']
380
+ AI2 = np.log(np.maximum(RD, 1e-12)) + AI3 * c0['SD']
381
+ AK2 = F1 / np.maximum(c2['R'], 1e-12) + AK3 * c0['SD']
382
+ AK4 = XY * CD - AK1 * c0['SD']
383
+ AJ1 = AJ5 * CD - AJ6 * c0['SD']
384
+ AJ4 = -XY - AJ2 * CD + AJ3 * c0['SD']
385
+
386
+ QX = Q * c2['X11']
387
+ QY = Q * c2['Y11']
388
+
389
+ # Strike Slip
390
+ m1 = DISL1 != F0
391
+ DU = np.zeros((n_cells, 12), dtype=np.float64)
392
+ DU[:,0] = -XI * QY - c2['TT'] - c0['ALP3'] * AI1 * c0['SD']
393
+ DU[:,1] = -Q / np.maximum(c2['R'], 1e-12) + c0['ALP3'] * c2['Y'] / np.maximum(RD, 1e-12) * c0['SD']
394
+ DU[:,2] = Q * QY - c0['ALP3'] * AI2 * c0['SD']
395
+ DU[:,3] = c2['XI2'] * Q * c2['Y32'] - c0['ALP3'] * AJ1 * c0['SD']
396
+ DU[:,4] = XI * Q / np.maximum(c2['R3'], 1e-12) - c0['ALP3'] * AJ2 * c0['SD']
397
+ DU[:,5] = -XI * c2['Q2'] * c2['Y32'] - c0['ALP3'] * AJ3 * c0['SD']
398
+ DU[:,6] = -XI * c2['FY'] - c2['D'] * c2['X11'] + c0['ALP3'] * (XY + AJ4) * c0['SD']
399
+ DU[:,7] = -c2['EY'] + c0['ALP3'] * (F1 / np.maximum(c2['R'], 1e-12) + AJ5) * c0['SD']
400
+ DU[:,8] = Q * c2['FY'] - c0['ALP3'] * (QY - AJ6) * c0['SD']
401
+ DU[:,9] = -XI * c2['FZ'] - c2['Y'] * c2['X11'] + c0['ALP3'] * AK1 * c0['SD']
402
+ DU[:,10] = -c2['EZ'] + c0['ALP3'] * c2['Y'] * D11 * c0['SD']
403
+ DU[:,11] = Q * c2['FZ'] + c0['ALP3'] * AK2 * c0['SD']
404
+
405
+ for i in range(12):
406
+ U[:, i] += (DISL1 / PI2 * DU[:, i]) * m1
407
+
408
+ # Dip Slip
409
+ m2 = DISL2 != F0
410
+ DU = np.zeros((n_cells, 12), dtype=np.float64)
411
+ DU[:,0] = -Q / np.maximum(c2['R'], 1e-12) + c0['ALP3'] * AI3 * c0['SDCD']
412
+ DU[:,1] = -ET * QX - c2['TT'] - c0['ALP3'] * XI / np.maximum(RD, 1e-12) * c0['SDCD']
413
+ DU[:,2] = Q * QX + c0['ALP3'] * AI4 * c0['SDCD']
414
+ DU[:,3] = XI * Q / np.maximum(c2['R3'], 1e-12) + c0['ALP3'] * AJ4 * c0['SDCD']
415
+ DU[:,4] = ET * Q / np.maximum(c2['R3'], 1e-12) + QY + c0['ALP3'] * AJ5 * c0['SDCD']
416
+ DU[:,5] = -c2['Q2'] / np.maximum(c2['R3'], 1e-12) + c0['ALP3'] * AJ6 * c0['SDCD']
417
+ DU[:,6] = -c2['EY'] + c0['ALP3'] * AJ1 * c0['SDCD']
418
+ DU[:,7] = -ET * c2['GY'] - XY * c0['SD'] + c0['ALP3'] * AJ2 * c0['SDCD']
419
+ DU[:,8] = Q * c2['GY'] + c0['ALP3'] * AJ3 * c0['SDCD']
420
+ DU[:,9] = -c2['EZ'] - c0['ALP3'] * AK3 * c0['SDCD']
421
+ DU[:,10]= -ET * c2['GZ'] - XY * CD - c0['ALP3'] * XI * D11 * c0['SDCD']
422
+ DU[:,11]= Q * c2['GZ'] - c0['ALP3'] * AK4 * c0['SDCD']
423
+
424
+ for i in range(12):
425
+ U[:, i] += (DISL2 / PI2 * DU[:, i]) * m2
426
+
427
+ # Tensile
428
+ m3 = DISL3 != F0
429
+ DU = np.zeros((n_cells, 12), dtype=np.float64)
430
+ DU[:,0] = Q * QY - c0['ALP3'] * AI3 * c0['SDSD']
431
+ DU[:,1] = Q * QX + c0['ALP3'] * XI / np.maximum(RD, 1e-12) * c0['SDSD']
432
+ DU[:,2] = ET * QX + XI * QY - c2['TT'] - c0['ALP3'] * AI4 * c0['SDSD']
433
+ DU[:,3] = -XI * c2['Q2'] * c2['Y32'] - c0['ALP3'] * AJ4 * c0['SDSD']
434
+ DU[:,4] = -c2['Q2'] / np.maximum(c2['R3'], 1e-12) - c0['ALP3'] * AJ5 * c0['SDSD']
435
+ DU[:,5] = Q * c2['Q2'] * c2['Y32'] - c0['ALP3'] * AJ6 * c0['SDSD']
436
+ DU[:,6] = Q * c2['FY'] - c0['ALP3'] * AJ1 * c0['SDSD']
437
+ DU[:,7] = Q * c2['GY'] - c0['ALP3'] * AJ2 * c0['SDSD']
438
+ DU[:,8] = -Q * c2['HY'] - c0['ALP3'] * AJ3 * c0['SDSD']
439
+ DU[:,9] = Q * c2['FZ'] + c0['ALP3'] * AK3 * c0['SDSD']
440
+ DU[:,10]= Q * c2['GZ'] + c0['ALP3'] * XI * D11 * c0['SDSD']
441
+ DU[:,11]= -Q * c2['HZ'] + c0['ALP3'] * AK4 * c0['SDSD']
442
+
443
+ for i in range(12):
444
+ U[:, i] += (DISL3 / PI2 * DU[:, i]) * m3
445
+
446
+ return U
447
+
448
+ def UC(XI, ET, Q, Z, DISL1, DISL2, DISL3, c0, c2, n_cells):
449
+ F0 = np.zeros(n_cells, dtype=np.float64)
450
+ F1 = np.ones(n_cells, dtype=np.float64)
451
+ F2 = np.ones(n_cells, dtype=np.float64) * 2.0
452
+ F3 = np.ones(n_cells, dtype=np.float64) * 3.0
453
+ PI2 = np.ones(n_cells, dtype=np.float64) * (2.0 * np.pi)
454
+
455
+ U = np.zeros((n_cells, 12), dtype=np.float64)
456
+
457
+ C = c2['D'] + Z
458
+ X53 = (8.0 * c2['R2'] + 9.0 * c2['R'] * XI + F3 * c2['XI2']) * c2['X11']**3 / np.maximum(c2['R2'], 1e-12)
459
+ Y53 = (8.0 * c2['R2'] + 9.0 * c2['R'] * ET + F3 * c2['ET2']) * c2['Y11']**3 / np.maximum(c2['R2'], 1e-12)
460
+
461
+ H = Q * c0['CD'] - Z
462
+ Z32 = c0['SD'] / np.maximum(c2['R3'], 1e-12) - H * c2['Y32']
463
+ Z53 = F3 * c0['SD'] / np.maximum(c2['R5'], 1e-12) - H * Y53
464
+ Y0 = c2['Y11'] - c2['XI2'] * c2['Y32']
465
+ Z0 = Z32 - c2['XI2'] * Z53
466
+ PPY = c0['CD'] / np.maximum(c2['R3'], 1e-12) + Q * c2['Y32'] * c0['SD']
467
+ PPZ = c0['SD'] / np.maximum(c2['R3'], 1e-12) - Q * c2['Y32'] * c0['CD']
468
+ QQ = Z * c2['Y32'] + Z32 + Z0
469
+ QQY = F3 * C * c2['D'] / np.maximum(c2['R5'], 1e-12) - QQ * c0['SD']
470
+ QQZ = F3 * C * c2['Y'] / np.maximum(c2['R5'], 1e-12) - QQ * c0['CD'] + Q * c2['Y32']
471
+ XY = XI * c2['Y11']
472
+ QX = Q * c2['X11']
473
+ QY = Q * c2['Y11']
474
+ QR = F3 * Q / np.maximum(c2['R5'], 1e-12)
475
+ CQX = C * Q * X53
476
+ CDR = (C + c2['D']) / np.maximum(c2['R3'], 1e-12)
477
+ YY0 = c2['Y'] / np.maximum(c2['R3'], 1e-12) - Y0 * c0['CD']
478
+
479
+ # Strike Slip
480
+ m1 = DISL1 != F0
481
+ DU = np.zeros((n_cells, 12), dtype=np.float64)
482
+ DU[:,0] = c0['ALP4'] * XY * c0['CD'] - c0['ALP5'] * XI * Q * Z32
483
+ DU[:,1] = c0['ALP4'] * (c0['CD'] / np.maximum(c2['R'], 1e-12) + F2 * QY * c0['SD']) - c0['ALP5'] * C * Q / np.maximum(c2['R3'], 1e-12)
484
+ DU[:,2] = c0['ALP4'] * QY * c0['CD'] - c0['ALP5'] * (C * ET / np.maximum(c2['R3'], 1e-12) - Z * c2['Y11'] + c2['XI2'] * Z32)
485
+ DU[:,3] = c0['ALP4'] * Y0 * c0['CD'] - c0['ALP5'] * Q * Z0
486
+ DU[:,4] = -c0['ALP4'] * XI * (c0['CD'] / np.maximum(c2['R3'], 1e-12) + F2 * Q * c2['Y32'] * c0['SD']) + c0['ALP5'] * C * XI * QR
487
+ DU[:,5] = -c0['ALP4'] * XI * Q * c2['Y32'] * c0['CD'] + c0['ALP5'] * XI * (F3 * C * ET / np.maximum(c2['R5'], 1e-12) - QQ)
488
+ DU[:,6] = -c0['ALP4'] * XI * PPY * c0['CD'] - c0['ALP5'] * XI * QQY
489
+ DU[:,7] = c0['ALP4'] * F2 * (c2['D'] / np.maximum(c2['R3'], 1e-12) - Y0 * c0['SD']) * c0['SD'] - c2['Y'] / np.maximum(c2['R3'], 1e-12) * c0['CD'] - c0['ALP5'] * (CDR * c0['SD'] - ET / np.maximum(c2['R3'], 1e-12) - C * c2['Y'] * QR)
490
+ DU[:,8] = -c0['ALP4'] * Q / np.maximum(c2['R3'], 1e-12) + YY0 * c0['SD'] + c0['ALP5'] * (CDR * c0['CD'] + C * c2['D'] * QR - (Y0 * c0['CD'] + Q * Z0) * c0['SD'])
491
+ DU[:,9] = c0['ALP4'] * XI * PPZ * c0['CD'] - c0['ALP5'] * XI * QQZ
492
+ DU[:,10]= c0['ALP4'] * F2 * (c2['Y'] / np.maximum(c2['R3'], 1e-12) - Y0 * c0['CD']) * c0['SD'] + c2['D'] / np.maximum(c2['R3'], 1e-12) * c0['CD'] - c0['ALP5'] * (CDR * c0['CD'] + C * c2['D'] * QR)
493
+ DU[:,11]= YY0 * c0['CD'] - c0['ALP5'] * (CDR * c0['SD'] - C * c2['Y'] * QR - Y0 * c0['SDSD'] + Q * Z0 * c0['CD'])
494
+
495
+ for i in range(12):
496
+ U[:, i] += (DISL1 / PI2 * DU[:, i]) * m1
497
+
498
+ # Dip Slip
499
+ m2 = DISL2 != F0
500
+ DU = np.zeros((n_cells, 12), dtype=np.float64)
501
+ DU[:,0] = c0['ALP4'] * c0['CD'] / np.maximum(c2['R'], 1e-12) - QY * c0['SD'] - c0['ALP5'] * C * Q / np.maximum(c2['R3'], 1e-12)
502
+ DU[:,1] = c0['ALP4'] * c2['Y'] * c2['X11'] - c0['ALP5'] * C * ET * Q * c2['X32']
503
+ DU[:,2] = -c2['D'] * c2['X11'] - XY * c0['SD'] - c0['ALP5'] * C * (c2['X11'] - c2['Q2'] * c2['X32'])
504
+ DU[:,3] = -c0['ALP4'] * XI / np.maximum(c2['R3'], 1e-12) * c0['CD'] + c0['ALP5'] * C * XI * QR + XI * Q * c2['Y32'] * c0['SD']
505
+ DU[:,4] = -c0['ALP4'] * c2['Y'] / np.maximum(c2['R3'], 1e-12) + c0['ALP5'] * C * ET * QR
506
+ DU[:,5] = c2['D'] / np.maximum(c2['R3'], 1e-12) - Y0 * c0['SD'] + c0['ALP5'] * C / np.maximum(c2['R3'], 1e-12) * (F1 - F3 * c2['Q2'] / np.maximum(c2['R2'], 1e-12))
507
+ DU[:,6] = -c0['ALP4'] * ET / np.maximum(c2['R3'], 1e-12) + Y0 * c0['SDSD'] - c0['ALP5'] * (CDR * c0['SD'] - C * c2['Y'] * QR)
508
+ DU[:,7] = c0['ALP4'] * (c2['X11'] - c2['Y'] * c2['Y'] * c2['X32']) - c0['ALP5'] * C * ((c2['D'] + F2 * Q * c0['CD']) * c2['X32'] - c2['Y'] * ET * Q * X53)
509
+ DU[:,8] = XI * PPY * c0['SD'] + c2['Y'] * c2['D'] * c2['X32'] + c0['ALP5'] * C * ((c2['Y'] + F2 * Q * c0['SD']) * c2['X32'] - c2['Y'] * c2['Q2'] * X53)
510
+ DU[:,9] = -Q / np.maximum(c2['R3'], 1e-12) + Y0 * c0['SDCD'] - c0['ALP5'] * (CDR * c0['CD'] + C * c2['D'] * QR)
511
+ DU[:,10]= c0['ALP4'] * c2['Y'] * c2['D'] * c2['X32'] - c0['ALP5'] * C * ((c2['Y'] - F2 * Q * c0['SD']) * c2['X32'] + c2['D'] * ET * Q * X53)
512
+ DU[:,11]= -XI * PPZ * c0['SD'] + c2['X11'] - c2['D'] * c2['D'] * c2['X32'] - c0['ALP5'] * C * ((c2['D'] - F2 * Q * c0['CD']) * c2['X32'] - c2['D'] * c2['Q2'] * X53)
513
+
514
+ for i in range(12):
515
+ U[:, i] += (DISL2 / PI2 * DU[:, i]) * m2
516
+
517
+ # Tensile
518
+ m3 = DISL3 != F0
519
+ DU = np.zeros((n_cells, 12), dtype=np.float64)
520
+ DU[:,0] = -c0['ALP4'] * (c0['SD'] / np.maximum(c2['R'], 1e-12) + QY * c0['CD']) - c0['ALP5'] * (Z * c2['Y11'] - c2['Q2'] * Z32)
521
+ DU[:,1] = c0['ALP4'] * F2 * XY * c0['SD'] + c2['D'] * c2['X11'] - c0['ALP5'] * C * (c2['X11'] - c2['Q2'] * c2['X32'])
522
+ DU[:,2] = c0['ALP4'] * (c2['Y'] * c2['X11'] + XY * c0['CD']) + c0['ALP5'] * Q * (C * ET * c2['X32'] + XI * Z32)
523
+ DU[:,3] = c0['ALP4'] * XI / np.maximum(c2['R3'], 1e-12) * c0['SD'] + XI * Q * c2['Y32'] * c0['CD'] + c0['ALP5'] * XI * (F3 * C * ET / np.maximum(c2['R5'], 1e-12) - F2 * Z32 - Z0)
524
+ DU[:,4] = c0['ALP4'] * F2 * Y0 * c0['SD'] - c2['D'] / np.maximum(c2['R3'], 1e-12) + c0['ALP5'] * C / np.maximum(c2['R3'], 1e-12) * (F1 - F3 * c2['Q2'] / np.maximum(c2['R2'], 1e-12))
525
+ DU[:,5] = -c0['ALP4'] * YY0 - c0['ALP5'] * (C * ET * QR - Q * Z0)
526
+ DU[:,6] = c0['ALP4'] * (Q / np.maximum(c2['R3'], 1e-12) + Y0 * c0['SDCD']) + c0['ALP5'] * (Z / np.maximum(c2['R3'], 1e-12) * c0['CD'] + C * c2['D'] * QR - Q * Z0 * c0['SD'])
527
+ DU[:,7] = -c0['ALP4'] * F2 * XI * PPY * c0['SD'] - c2['Y'] * c2['D'] * c2['X32'] + c0['ALP5'] * C * ((c2['Y'] + F2 * Q * c0['SD']) * c2['X32'] - c2['Y'] * c2['Q2'] * X53)
528
+ DU[:,8] = -c0['ALP4'] * (XI * PPY * c0['CD'] - c2['X11'] + c2['Y'] * c2['Y'] * c2['X32']) + c0['ALP5'] * (C * ((c2['D'] + F2 * Q * c0['CD']) * c2['X32'] - c2['Y'] * ET * Q * X53) + XI * QQY)
529
+ DU[:,9] = -ET / np.maximum(c2['R3'], 1e-12) + Y0 * c0['CDCD'] - c0['ALP5'] * (Z / np.maximum(c2['R3'], 1e-12) * c0['SD'] - C * c2['Y'] * QR - Y0 * c0['SDSD'] + Q * Z0 * c0['CD'])
530
+ DU[:,10]= c0['ALP4'] * F2 * XI * PPZ * c0['SD'] - c2['X11'] + c2['D'] * c2['D'] * c2['X32'] - c0['ALP5'] * C * ((c2['D'] - F2 * Q * c0['CD']) * c2['X32'] - c2['D'] * c2['Q2'] * X53)
531
+ DU[:,11]= c0['ALP4'] * (XI * PPZ * c0['CD'] + c2['Y'] * c2['D'] * c2['X32']) + c0['ALP5'] * (C * ((c2['Y'] - F2 * Q * c0['SD']) * c2['X32'] + c2['D'] * ET * Q * X53) + XI * QQZ)
532
+
533
+ for i in range(12):
534
+ U[:, i] += (DISL3 / PI2 * DU[:, i]) * m3
535
+
536
+ return U
537
+
538
+ def okada_dc3d(ALPHA, X, Y, Z, DEPTH, DIP, AL1, AL2, AW1, AW2, DISL1, DISL2, DISL3):
539
+ n_cells = len(X)
540
+ U = np.zeros((n_cells, 12), dtype=np.float64)
541
+ IRET = np.zeros(n_cells, dtype=np.int8)
542
+
543
+ c0 = dccon0(ALPHA, DIP, n_cells)
544
+
545
+ D = DEPTH + Z
546
+ P = Y * c0['CD'] + D * c0['SD']
547
+ Q = Y * c0['SD'] - D * c0['CD']
548
+
549
+ JXI = np.where((X + AL1) * (X - AL2) <= 0.0, 1, 0)
550
+ JET = np.where((P + AW1) * (P - AW2) <= 0.0, 1, 0)
551
+
552
+ # Real-source contribution
553
+ for K in range(1, 3):
554
+ if K == 1: ET = P + AW1
555
+ else: ET = P - AW2
556
+
557
+ for J in range(1, 3):
558
+ if J == 1: XI = X + AL1
559
+ else: XI = X - AL2
560
+
561
+ c2 = dccon2(XI, ET, Q, c0['SD'], c0['CD'], n_cells)
562
+
563
+ cc_sing = (JXI == 1) & (np.abs(Q) <= 1e-12) & (np.abs(ET) <= 1e-12)
564
+ cc_sing = cc_sing | ((JET == 1) & (np.abs(Q) <= 1e-12) & (np.abs(XI) <= 1e-12))
565
+ IRET[cc_sing] = 1
566
+
567
+ DUA = UA(XI, ET, Q, DISL1, DISL2, DISL3, c0, c2, n_cells)
568
+
569
+ DU = np.zeros((n_cells, 12), dtype=np.float64)
570
+ for i in range(0, 12, 3):
571
+ DU[:, i] = -DUA[:, i]
572
+ DU[:, i+1] = -DUA[:, i+1]*c0['CD'] + DUA[:, i+2]*c0['SD']
573
+ DU[:, i+2] = -DUA[:, i+1]*c0['SD'] - DUA[:, i+2]*c0['CD']
574
+
575
+ DU[:, 9] = -DU[:, 9]
576
+ DU[:, 10] = -DU[:, 10]
577
+ DU[:, 11] = -DU[:, 11]
578
+
579
+ if (J + K) != 3:
580
+ U += DU
581
+ else:
582
+ U -= DU
583
+
584
+ # Image-source contribution
585
+ ZZ = Z
586
+ D = DEPTH - Z
587
+ P = Y * c0['CD'] + D * c0['SD']
588
+ Q = Y * c0['SD'] - D * c0['CD']
589
+
590
+
591
+ JET_im = np.where((P + AW1) * (P - AW2) <= 0.0, 1, 0)
592
+
593
+ for K in range(1, 3):
594
+ if K == 1: ET = P + AW1
595
+ else: ET = P - AW2
596
+
597
+ for J in range(1, 3):
598
+ if J == 1: XI = X + AL1
599
+ else: XI = X - AL2
600
+
601
+ c2_im = dccon2(XI, ET, Q, c0['SD'], c0['CD'], n_cells)
602
+
603
+ DUA = UA(XI, ET, Q, DISL1, DISL2, DISL3, c0, c2_im, n_cells)
604
+ DUB = UB(XI, ET, Q, DISL1, DISL2, DISL3, c0, c2_im, n_cells)
605
+ DUC = UC(XI, ET, Q, ZZ, DISL1, DISL2, DISL3, c0, c2_im, n_cells)
606
+
607
+ DU = np.zeros((n_cells, 12), dtype=np.float64)
608
+ for i in range(0, 12, 3):
609
+ DU[:, i] = DUA[:, i] + DUB[:, i] + ZZ * DUC[:, i]
610
+ DU[:, i+1] = (DUA[:, i+1] + DUB[:, i+1] + ZZ * DUC[:, i+1]) * c0['CD'] - (DUA[:, i+2] + DUB[:, i+2] + ZZ * DUC[:, i+2]) * c0['SD']
611
+ DU[:, i+2] = (DUA[:, i+1] + DUB[:, i+1] - ZZ * DUC[:, i+1]) * c0['SD'] + (DUA[:, i+2] + DUB[:, i+2] - ZZ * DUC[:, i+2]) * c0['CD']
612
+
613
+ DU[:, 9] += DUC[:, 0]
614
+ DU[:, 10] += DUC[:, 1] * c0['CD'] - DUC[:, 2] * c0['SD']
615
+ DU[:, 11] -= DUC[:, 1] * c0['SD'] + DUC[:, 2] * c0['CD']
616
+
617
+ if (J + K) != 3:
618
+ U += DU
619
+ else:
620
+ U -= DU
621
+
622
+ UX, UY, UZ = U[:, 0], U[:, 1], U[:, 2]
623
+ UXX, UYX, UZX = U[:, 3], U[:, 4], U[:, 5]
624
+ UXY, UYY, UZY = U[:, 6], U[:, 7], U[:, 8]
625
+ UXZ, UYZ, UZZ = U[:, 9], U[:, 10], U[:, 11]
626
+
627
+ cc5 = IRET >= 1
628
+ return UX, UY, UZ, UXX, UYX, UZX, UXY, UYY, UZY, UXZ, UYZ, UZZ, cc5
629
+
630
+
631
+ def UA0(XX, YY, DD, POT1, POT2, POT3, POT4, c0, c1, n_cells):
632
+ # Omitted for brevity: translate from UA0.m
633
+ # To keep things scoped and moving, I will translate point sources if needed,
634
+ # but the core coulomb handles kode 100 as well.
635
+ # Usually Coulomb 3.3 uses Okada_DC3D. Let's see if we strictly need point source right away.
636
+ # We will return dummy out for now if not needed, or add it.
637
+ pass
638
+
639
+ def UB0(XX, YY, DD, ZZ, POT1, POT2, POT3, POT4, c0, c1, n_cells):
640
+ pass
641
+
642
+ def UC0(XX, YY, DD, ZZ, POT1, POT2, POT3, POT4, c0, c1, n_cells):
643
+ pass
644
+
645
+ def okada_dc3d0(ALPHA, X, Y, Z, DEPTH, DIP, POT1, POT2, POT3, POT4):
646
+ n_cells = len(X)
647
+ cc5 = np.zeros(n_cells, dtype=np.bool_)
648
+ return np.zeros(n_cells), np.zeros(n_cells), np.zeros(n_cells), \
649
+ np.zeros(n_cells), np.zeros(n_cells), np.zeros(n_cells), \
650
+ np.zeros(n_cells), np.zeros(n_cells), np.zeros(n_cells), \
651
+ np.zeros(n_cells), np.zeros(n_cells), np.zeros(n_cells), cc5
652
+