pygrt-kit 0.2.0__py3-none-win_amd64.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.
Files changed (64) hide show
  1. pygrt/C_extension/Makefile +137 -0
  2. pygrt/C_extension/bin/grt.exe +0 -0
  3. pygrt/C_extension/bin/grt.syn +0 -0
  4. pygrt/C_extension/bin/grt.travt +0 -0
  5. pygrt/C_extension/include/attenuation.h +24 -0
  6. pygrt/C_extension/include/bessel.h +22 -0
  7. pygrt/C_extension/include/colorstr.h +19 -0
  8. pygrt/C_extension/include/const.h +115 -0
  9. pygrt/C_extension/include/dwm.h +44 -0
  10. pygrt/C_extension/include/fim.h +78 -0
  11. pygrt/C_extension/include/grt.h +128 -0
  12. pygrt/C_extension/include/iostats.h +72 -0
  13. pygrt/C_extension/include/layer.h +123 -0
  14. pygrt/C_extension/include/logo.h +57 -0
  15. pygrt/C_extension/include/matrix.h +205 -0
  16. pygrt/C_extension/include/model.h +165 -0
  17. pygrt/C_extension/include/progressbar.h +22 -0
  18. pygrt/C_extension/include/propagate.h +379 -0
  19. pygrt/C_extension/include/prtdbg.h +13 -0
  20. pygrt/C_extension/include/ptam.h +90 -0
  21. pygrt/C_extension/include/quadratic.h +55 -0
  22. pygrt/C_extension/include/sacio.h +382 -0
  23. pygrt/C_extension/include/search.h +69 -0
  24. pygrt/C_extension/include/signals.h +170 -0
  25. pygrt/C_extension/include/source.h +38 -0
  26. pygrt/C_extension/include/travt.h +28 -0
  27. pygrt/C_extension/include/version.h +14 -0
  28. pygrt/C_extension/lib/libgrt.a +0 -0
  29. pygrt/C_extension/lib/libgrt.so +0 -0
  30. pygrt/C_extension/src/attenuation.c +18 -0
  31. pygrt/C_extension/src/bessel.c +18 -0
  32. pygrt/C_extension/src/dwm.c +135 -0
  33. pygrt/C_extension/src/fim.c +254 -0
  34. pygrt/C_extension/src/grt.c +484 -0
  35. pygrt/C_extension/src/grt_main.c +1215 -0
  36. pygrt/C_extension/src/grt_syn.c +716 -0
  37. pygrt/C_extension/src/grt_travt.c +227 -0
  38. pygrt/C_extension/src/iostats.c +94 -0
  39. pygrt/C_extension/src/layer.c +254 -0
  40. pygrt/C_extension/src/model.c +377 -0
  41. pygrt/C_extension/src/progressbar.c +30 -0
  42. pygrt/C_extension/src/propagate.c +773 -0
  43. pygrt/C_extension/src/ptam.c +347 -0
  44. pygrt/C_extension/src/quadratic.c +59 -0
  45. pygrt/C_extension/src/sacio.c +712 -0
  46. pygrt/C_extension/src/search.c +66 -0
  47. pygrt/C_extension/src/signals.c +350 -0
  48. pygrt/C_extension/src/source.c +88 -0
  49. pygrt/C_extension/src/travt.c +356 -0
  50. pygrt/C_extension/version +1 -0
  51. pygrt/__init__.py +19 -0
  52. pygrt/_version.py +1 -0
  53. pygrt/c_interfaces.py +68 -0
  54. pygrt/c_structures.py +86 -0
  55. pygrt/print.py +17 -0
  56. pygrt/pygrn.py +188 -0
  57. pygrt/pymod.py +442 -0
  58. pygrt/signals.py +196 -0
  59. pygrt/utils.py +685 -0
  60. pygrt_kit-0.2.0.dist-info/LICENSE +674 -0
  61. pygrt_kit-0.2.0.dist-info/METADATA +154 -0
  62. pygrt_kit-0.2.0.dist-info/RECORD +64 -0
  63. pygrt_kit-0.2.0.dist-info/WHEEL +5 -0
  64. pygrt_kit-0.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1215 @@
1
+ /**
2
+ * @file grt_main.c
3
+ * @author Zhu Dengda (zhudengda@mail.iggcas.ac.cn)
4
+ * @date 2024-11-28
5
+ *
6
+ * 定义main函数,形成命令行式的用法(不使用python的entry_points,会牺牲性能)
7
+ * 计算不同震源的格林函数
8
+ *
9
+ */
10
+
11
+ #include <stdio.h>
12
+ #include <unistd.h>
13
+ #include <complex.h>
14
+ #include <fftw3.h>
15
+ #include <string.h>
16
+ #include <stdlib.h>
17
+ #include <sys/stat.h>
18
+ #include <errno.h>
19
+ #include <omp.h>
20
+
21
+ #include "const.h"
22
+ #include "model.h"
23
+ #include "grt.h"
24
+ #include "search.h"
25
+ #include "sacio.h"
26
+ #include "travt.h"
27
+ #include "logo.h"
28
+ #include "signals.h"
29
+ #include "colorstr.h"
30
+
31
+ #ifdef GRT_USE_FLOAT
32
+ #define _FFTW_COMPLEX fftwf_complex
33
+ #define _FFTW_PLAN fftwf_plan
34
+ #define _FFTW_EXECUTE fftwf_execute
35
+ #define _FFTW_MALLOC fftwf_malloc
36
+ #define _FFTW_FREE fftwf_free
37
+ #define _FFTW_DESTROY_PLAN fftwf_destroy_plan
38
+ #define _FFTW_PLAN_DFT_C2R_1D fftwf_plan_dft_c2r_1d
39
+ #else
40
+ #define _FFTW_COMPLEX fftw_complex
41
+ #define _FFTW_PLAN fftw_plan
42
+ #define _FFTW_EXECUTE fftw_execute
43
+ #define _FFTW_MALLOC fftw_malloc
44
+ #define _FFTW_FREE fftw_free
45
+ #define _FFTW_DESTROY_PLAN fftw_destroy_plan
46
+ #define _FFTW_PLAN_DFT_C2R_1D fftw_plan_dft_c2r_1d
47
+ #endif
48
+
49
+
50
+ extern char *optarg;
51
+ extern int optind;
52
+ extern int optopt;
53
+
54
+ //****************** 在该文件以内的全局变量 ***********************//
55
+ // 命令名称
56
+ static char *command = NULL;
57
+ // 线程数
58
+ static int nthreads=-1;
59
+ // 模型路径,模型PYMODEL1D指针,全局最大最小速度
60
+ static char *s_modelpath = NULL;
61
+ static char *s_modelname = NULL;
62
+ static PYMODEL1D *pymod;
63
+ static double vmax, vmin;
64
+ // 震源和场点深度
65
+ static double depsrc, deprcv;
66
+ static char *s_depsrc = NULL, *s_deprcv = NULL;
67
+ // 点数、采样间隔、时窗长度、频率点数、频率间隔
68
+ static int nt;
69
+ static double dt;
70
+ static double winT;
71
+ static int nf1, nf2, nf;
72
+ static double df, dw;
73
+ static MYREAL *freqs = NULL;
74
+ // 输出目录
75
+ static char *s_output_dir = NULL;
76
+ // 计算频率范围
77
+ static double freq1=-1.0, freq2=-1.0;
78
+ // 虚频率系数和虚频率
79
+ static double zeta=0.8, wI=0.0;
80
+ // 波数积分间隔
81
+ static double Length=0.0;
82
+ // 波数积分相关变量
83
+ static double keps=-1.0, ampk=1.15, k0=5.0;
84
+ bool iwk0=false;
85
+ // 参考最小速度,小于0表示使用峰谷平均法;
86
+ static double vmin_ref=0.0;
87
+ static const double min_vmin_ref=0.1;
88
+ // 自动使用峰谷平均法的最小厚度差 1km
89
+ static const double hs_ptam = 0.5;
90
+ // 时间延迟量,延迟参考速度。总延迟=T0 + dist/V0;
91
+ static double delayT=0.0, delayT0=0.0, delayV0=0.0;
92
+ static double tmax; // 时窗最大截止时刻
93
+ // 震中距数组以及保存对应初至波走时的数组
94
+ static char **s_rs = NULL;
95
+ static MYREAL *rs = NULL;
96
+ static int nr=0;
97
+ // 是否silence整个输出
98
+ static bool silenceInput=false;
99
+ // 输出单个频率下的波数积分过程文件 -S
100
+ static char *s_statsdir = NULL; // 保存目录,和SAC文件目录同级
101
+ static char **s_statsidxs = NULL;
102
+ static MYINT nstatsidxs=0;
103
+ static MYINT *statsidxs = NULL;
104
+ // 计算哪些格林函数,确定震源类型, 默认计算全部
105
+ static bool doEXP=true, doVF=true, doHF=true, doDC=true;
106
+
107
+ // 各选项的标志变量,初始化为0,定义了则为1
108
+ static int M_flag=0, D_flag=0, N_flag=0,
109
+ O_flag=0, H_flag=0,
110
+ L_flag=0, V_flag=0, E_flag=0,
111
+ K_flag=0, s_flag=0,
112
+ S_flag=0, R_flag=0, P_flag=0,
113
+ G_flag=0;
114
+
115
+ // 三分量代号
116
+ const char chs[3] = {'Z', 'R', 'T'};
117
+
118
+
119
+ /**
120
+ * 打印使用说明
121
+ */
122
+ static void print_help(){
123
+ print_logo();
124
+ printf("\n"
125
+ "+ To get more precise results when source and receiver are \n"
126
+ " at a close or same depth, Peak-Trough Average Method(PTAM)\n"
127
+ " (Zhang et al., 2003) will be applied automatically.\n"
128
+ "\n"
129
+ "+ To use large dk to increase computing speed at a large\n"
130
+ " epicentral distance, Filon's Integration Method(FIM) with \n"
131
+ " 2-point linear interpolation(Ji and Yao, 1995) can be applied.\n"
132
+ "\n\n"
133
+ "The units of output Green's Functions for different sources are: \n"
134
+ " + Explosion: 1e-20 cm/(dyne-cm)\n"
135
+ " + Single Force: 1e-15 cm/(dyne)\n"
136
+ " + Double Couple: 1e-20 cm/(dyne-cm)\n"
137
+ " + Moment Tensor: 1e-20 cm/(dyne-cm)\n"
138
+ "\n\n"
139
+ "The components of Green's Functions are :\n"
140
+ " +------+-----------------------------------------------+\n"
141
+ " | Name | Description (Source, Component) |\n"
142
+ " +------+-----------------------------------------------+\n"
143
+ " | EXZ | Explosion, Vertical Upward |\n"
144
+ " | EXR | Explosion, Radial Outward |\n"
145
+ " | VFZ | Vertical Downward Force, Vertical Upward |\n"
146
+ " | VFR | Vertical Downward Force, Radial Outward |\n"
147
+ " | HFZ | Horizontal Force, Vertical Upward |\n"
148
+ " | HFR | Horizontal Force, Radial Outward |\n"
149
+ " | HFT | Horizontal Force, Transverse Clockwise |\n"
150
+ " | DDZ | 45° dip slip, Vertical Upward |\n"
151
+ " | DDR | 45° dip slip, Radial Outward |\n"
152
+ " | DSZ | 90° dip slip, Vertical Upward |\n"
153
+ " | DSR | 90° dip slip, Radial Outward |\n"
154
+ " | DST | 90° dip slip, Transverse Clockwise |\n"
155
+ " | SSZ | Vertical strike slip, Vertical Upward |\n"
156
+ " | SSR | Vertical strike slip, Radial Outward |\n"
157
+ " | SST | Vertical strike slip, Transverse Clockwise |\n"
158
+ " +------+-----------------------------------------------+\n"
159
+ "\n"
160
+ "\n\n"
161
+ "Usage:\n"
162
+ "----------------------------------------------------------------\n"
163
+ " grt -M<model> -D<depsrc>/<deprcv> -N<nt>/<dt>[/<zeta>] \n"
164
+ " -R<r1>,<r2>[,...] [-O<outdir>] [-H<f1>/<f2>] \n"
165
+ " [-L<length>] [-V<vmin_ref>] [-E<t0>[/<v0>]] \n"
166
+ " [-K<k0>[/<iwk0>/<ampk>/<keps>]] [-P<nthreads>]\n"
167
+ " [-G<b1>[/<b2>/<b3>/<b4>]] [-S<i1>,<i2>[,...]] [-s]\n"
168
+ "\n\n"
169
+ "Options:\n"
170
+ "----------------------------------------------------------------\n"
171
+ " -M<model> Filepath to 1D horizontally layered halfspace \n"
172
+ " model. The model file has 6 columns: \n"
173
+ "\n"
174
+ " +-------+----------+----------+-------------+----+----+\n"
175
+ " | H(km) | Vp(km/s) | Vs(km/s) | Rho(g/cm^3) | Qp | Qa |\n"
176
+ " +-------+----------+----------+-------------+----+----+\n"
177
+ "\n"
178
+ " and the number of layers are unlimited.\n"
179
+ "\n"
180
+ " -D<depsrc>/<deprcv>\n"
181
+ " <depsrc>: source depth (km).\n"
182
+ " <deprcv>: receiver depth (km).\n"
183
+ "\n"
184
+ " -N<nt>/<dt>[/<zeta>]\n"
185
+ " <nt>: number of points. (NOT requires 2^n).\n"
186
+ " <dt>: time interval (secs). \n"
187
+ " <zeta>: define the coefficient of imaginary \n"
188
+ " frequency wI=zeta*PI/T, where T=nt*dt.\n"
189
+ " Default zeta=%.1f.\n", zeta); printf(
190
+ "\n"
191
+ " -R<r1>,<r2>[,...]\n"
192
+ " Multiple epicentral distance (km), \n"
193
+ " seperated by comma.\n"
194
+ "\n"
195
+ " -O<outdir> Directorypath of output for saving. Default is\n"
196
+ " current directory.\n"
197
+ "\n"
198
+ " -H<f1>/<f2> Apply bandpass filer with rectangle window, \n"
199
+ " default no filter.\n"
200
+ " <f1>: lower frequency (Hz), %.1f means low pass.\n", freq1); printf(
201
+ " <f2>: upper frequency (Hz), %.1f means high pass.\n", freq2); printf(
202
+ "\n"
203
+ " -L<length> Define the wavenumber integration interval\n"
204
+ " dk=(2*PI)/(<length>*rmax). rmax is the maximum \n"
205
+ " epicentral distance. \n"
206
+ " There are 3 cases:\n"
207
+ " + (default) not set or set %.1f.\n", Length); printf(
208
+ " <length> will be determined automatically\n"
209
+ " in program with the criterion (Bouchon, 1980).\n"
210
+ " + manually set POSITIVE value.\n"
211
+ " + manually set NEGATIVE value, \n"
212
+ " and FIM will be used.\n"
213
+ "\n"
214
+ " -V<vmin_ref> \n"
215
+ " Minimum velocity (km/s) for reference. This\n"
216
+ " is designed to define the upper bound \n"
217
+ " of wavenumber integration, see the\n"
218
+ " description of -K for the specific formula.\n"
219
+ " There are 3 cases:\n"
220
+ " + (default) not set or set %.1f.\n", vmin_ref); printf(
221
+ " <vmin_ref> will be the minimum velocity\n"
222
+ " of model, but limited to %.1f. and if the \n", min_vmin_ref); printf(
223
+ " depth gap between source and receiver is \n"
224
+ " thinner than %.1f km, PTAM will be appled\n", hs_ptam); printf(
225
+ " automatically.\n"
226
+ " + manually set POSITIVE value. \n"
227
+ " + manually set NEGATIVE value, \n"
228
+ " and PTAM will be appled.\n"
229
+ "\n"
230
+ " -E<t0>[/<v0>]\n"
231
+ " Introduce the time delay in results. The total \n"
232
+ " delay = <t0> + dist/<v0>, dist is the\n"
233
+ " straight-line distance between source and \n"
234
+ " receiver.\n"
235
+ " <t0>: reference delay (s), default t0=%.1f\n", delayT0); printf(
236
+ " <v0>: reference velocity (km/s), \n"
237
+ " default %.1f not use.\n", delayV0); printf(
238
+ "\n"
239
+ " -K<k0>[/<iwk0>/<ampk>/<keps>]\n"
240
+ " Several parameters designed to define the\n"
241
+ " behavior in wavenumber integration. The upper\n"
242
+ " bound is \n"
243
+ " sqrt( (<k0>*mult)^2 + (<ampk>*w/<vmin_ref>)^2 ),\n"
244
+ " default mult=1.0.\n"
245
+ " <k0>: designed to give residual k at\n"
246
+ " 0 frequency, default is %.1f, and \n", k0); printf(
247
+ " multiply PI/hs in program, \n"
248
+ " where hs = max(fabs(depsrc-deprcv), %.1f).\n", MIN_DEPTH_GAP_SRC_RCV); printf(
249
+ " <iwk0>: 0 or 1, designed to give a k0 \n"
250
+ " varies linearly with frequeny, \n"
251
+ " default %d not use. If set, mult will be \n", (int)iwk0); printf(
252
+ " mult=f/fmax, fmax is the maximum\n"
253
+ " frequency.\n"
254
+ " <ampk>: amplification factor, default is %.2f.\n", ampk); printf(
255
+ " <keps>: a threshold for break wavenumber \n"
256
+ " integration in advance. See \n"
257
+ " (Yao and Harkrider, 1983) for details.\n"
258
+ " Default %.1f not use.\n", keps); printf(
259
+ "\n"
260
+ " -P<n> Number of threads. Default use all cores.\n"
261
+ "\n"
262
+ " -G<b1>[/<b2>/<b3>/<b4>]\n"
263
+ " Designed to choose which kind of source's Green's \n"
264
+ " functions will be computed, default is all (%d/%d/%d/%d). \n", (int)doEXP, (int)doVF, (int)doHF, (int)doDC); printf(
265
+ " Four bool type (0 or 1) options are\n"
266
+ " <b1>: Explosion (EXP)\n"
267
+ " <b2>: Vertical Force (VF)\n"
268
+ " <b3>: Horizontal Force (HF)\n"
269
+ " <b4>: Double Couple (DC)\n"
270
+ "\n"
271
+ " -S<i1>,<i2>[,...]\n"
272
+ " Frequency (index) of statsfile in wavenumber\n"
273
+ " integration to be output, require 0 <= i <= nf-1,\n"
274
+ " where nf=nt/2+1. These option is designed to check\n"
275
+ " the trend of kernel and integrand with wavenumber.\n"
276
+ " \n"
277
+ " -s Silence all outputs.\n"
278
+ "\n"
279
+ " -h Display this help message.\n"
280
+ "\n\n"
281
+ "Examples:\n"
282
+ "----------------------------------------------------------------\n"
283
+ " grt -Mmilrow -N1000/0.01 -D2/0 -Ores -R2,4,6,8,10\n"
284
+ "\n\n\n"
285
+ );
286
+
287
+ }
288
+
289
+
290
+ /**
291
+ * 从路径字符串中找到用/或\\分隔的最后一项
292
+ *
293
+ * @param path 路径字符串指针
294
+ *
295
+ * @return 指向最后一项字符串的指针
296
+ */
297
+ static char* get_basename(char* path) {
298
+ // 找到最后一个 '/'
299
+ char* last_slash = strrchr(path, '/');
300
+
301
+ #ifdef _WIN32
302
+ char* last_backslash = strrchr(path, '\\');
303
+ if (last_backslash && (!last_slash || last_backslash > last_slash)) {
304
+ last_slash = last_backslash;
305
+ }
306
+ #endif
307
+ if (last_slash) {
308
+ // 返回最后一个 '/' 之后的部分
309
+ return last_slash + 1;
310
+ }
311
+ // 如果没有 '/',整个路径就是最后一项
312
+ return path;
313
+ }
314
+
315
+ /**
316
+ * 从命令行中读取选项,处理后记录到全局变量中
317
+ *
318
+ * @param argc 命令行的参数个数
319
+ * @param argv 多个参数字符串指针
320
+ */
321
+ static void getopt_from_command(int argc, char **argv){
322
+ int opt;
323
+ while ((opt = getopt(argc, argv, ":M:D:N:O:H:L:V:E:K:shR:S:P:G:")) != -1) {
324
+ switch (opt) {
325
+ // 模型路径,其中每行分别为
326
+ // 厚度(km) Vp(km/s) Vs(km/s) Rho(g/cm^3) Qp Qs
327
+ // 互相用空格隔开即可
328
+ case 'M':
329
+ M_flag = 1;
330
+ s_modelpath = (char*)malloc(sizeof(char)*(strlen(optarg)+1));
331
+ strcpy(s_modelpath, optarg);
332
+ if(access(s_modelpath, F_OK) == -1){
333
+ fprintf(stderr, "[%s] " BOLD_RED "Error! File \"%s\" set by -M not exists.\n" DEFAULT_RESTORE, command, s_modelpath);
334
+ exit(EXIT_FAILURE);
335
+ }
336
+
337
+ s_modelname = get_basename(s_modelpath);
338
+ break;
339
+
340
+ // 震源和场点深度, -Ddepsrc/deprcv
341
+ case 'D':
342
+ D_flag = 1;
343
+ s_depsrc = (char*)malloc(sizeof(char)*(strlen(optarg)+1));
344
+ s_deprcv = (char*)malloc(sizeof(char)*(strlen(optarg)+1));
345
+ if(2 != sscanf(optarg, "%[^/]/%s", s_depsrc, s_deprcv)){
346
+ fprintf(stderr, "[%s] " BOLD_RED "Error in -D.\n" DEFAULT_RESTORE, command);
347
+ exit(EXIT_FAILURE);
348
+ };
349
+ if(1 != sscanf(s_depsrc, "%lf", &depsrc)){
350
+ fprintf(stderr, "[%s] " BOLD_RED "Error in -D.\n" DEFAULT_RESTORE, command);
351
+ exit(EXIT_FAILURE);
352
+ }
353
+ if(1 != sscanf(s_deprcv, "%lf", &deprcv)){
354
+ fprintf(stderr, "[%s] " BOLD_RED "Error in -D.\n" DEFAULT_RESTORE, command);
355
+ exit(EXIT_FAILURE);
356
+ }
357
+ if(depsrc < 0.0 || deprcv < 0.0){
358
+ fprintf(stderr, "[%s] " BOLD_RED "Error! Negative value in -D is not supported.\n" DEFAULT_RESTORE, command);
359
+ exit(EXIT_FAILURE);
360
+ }
361
+ break;
362
+
363
+ // 点数,采样间隔,虚频率 -Nnt/dt/[zeta]
364
+ case 'N':
365
+ N_flag = 1;
366
+ if(2 > sscanf(optarg, "%d/%lf/%lf", &nt, &dt, &zeta)){
367
+ fprintf(stderr, "[%s] " BOLD_RED "Error in -N.\n" DEFAULT_RESTORE, command);
368
+ exit(EXIT_FAILURE);
369
+ };
370
+ if(nt <= 0 || dt <= 0.0 || zeta <= 0.0){
371
+ fprintf(stderr, "[%s] " BOLD_RED "Error! Nonpositive value in -N is not supported.\n" DEFAULT_RESTORE, command);
372
+ exit(EXIT_FAILURE);
373
+ }
374
+ break;
375
+
376
+ // 输出路径 -Ooutput_dir
377
+ case 'O':
378
+ O_flag = 1;
379
+ s_output_dir = (char*)malloc(sizeof(char)*(strlen(optarg)+1));
380
+ strcpy(s_output_dir, optarg);
381
+ break;
382
+
383
+ // 频带 -H f1/f2
384
+ case 'H':
385
+ H_flag = 1;
386
+ if(2 != sscanf(optarg, "%lf/%lf", &freq1, &freq2)){
387
+ fprintf(stderr, "[%s] " BOLD_RED "Error in -H.\n" DEFAULT_RESTORE, command);
388
+ exit(EXIT_FAILURE);
389
+ };
390
+ if(freq1>0.0 && freq2>0.0 && freq1 > freq2){
391
+ fprintf(stderr, "[%s] " BOLD_RED "Error! In -H, positive freq1 should be less than positive freq2.\n" DEFAULT_RESTORE, command);
392
+ exit(EXIT_FAILURE);
393
+ }
394
+ break;
395
+
396
+ // 波数积分间隔 -LLength
397
+ case 'L':
398
+ L_flag = 1;
399
+ if(0 == sscanf(optarg, "%lf", &Length)){
400
+ fprintf(stderr, "[%s] " BOLD_RED "Error in -L.\n" DEFAULT_RESTORE, command);
401
+ exit(EXIT_FAILURE);
402
+ };
403
+ break;
404
+
405
+ // 参考最小速度 -Vvmin_ref
406
+ case 'V':
407
+ V_flag = 1;
408
+ if(0 == sscanf(optarg, "%lf", &vmin_ref)){
409
+ fprintf(stderr, "[%s] " BOLD_RED "Error in -V.\n" DEFAULT_RESTORE, command);
410
+ exit(EXIT_FAILURE);
411
+ };
412
+ break;
413
+
414
+ // 时间延迟 -ET0/V0
415
+ case 'E':
416
+ E_flag = 1;
417
+ if(0 == sscanf(optarg, "%lf/%lf", &delayT0, &delayV0)){
418
+ fprintf(stderr, "[%s] " BOLD_RED "Error in -E.\n" DEFAULT_RESTORE, command);
419
+ exit(EXIT_FAILURE);
420
+ };
421
+ if(delayV0 < 0.0){
422
+ fprintf(stderr, "[%s] " BOLD_RED "Error! Can't set negative v0(%f) in -E.\n" DEFAULT_RESTORE, command, delayV0);
423
+ exit(EXIT_FAILURE);
424
+ }
425
+ break;
426
+
427
+ // 波数积分相关变量 -Kk0/iwk0/ampk/keps
428
+ case 'K':
429
+ K_flag = 1;
430
+ {
431
+ int i=0;
432
+ if(0 == sscanf(optarg, "%lf/%d/%lf/%lf", &k0, &i, &ampk, &keps)){
433
+ fprintf(stderr, "[%s] " BOLD_RED "Error in -K.\n" DEFAULT_RESTORE, command);
434
+ exit(EXIT_FAILURE);
435
+ };
436
+ iwk0 = (i!=0);
437
+ }
438
+
439
+ if(k0 < 0.0){
440
+ fprintf(stderr, "[%s] " BOLD_RED "Error! Can't set negative k0(%f) in -K.\n" DEFAULT_RESTORE, command, k0);
441
+ exit(EXIT_FAILURE);
442
+ }
443
+ if(ampk < 0.0){
444
+ fprintf(stderr, "[%s] " BOLD_RED "Error! Can't set negative ampk(%f) in -K.\n" DEFAULT_RESTORE, command, ampk);
445
+ exit(EXIT_FAILURE);
446
+ }
447
+ break;
448
+
449
+ // 不打印在终端
450
+ case 's':
451
+ s_flag = 1;
452
+ silenceInput = true;
453
+ break;
454
+
455
+ // 震中距数组,-Rr1,r2,r3,r4 ...
456
+ case 'R':
457
+ R_flag = 1;
458
+ {
459
+ char *token;
460
+ char *str_copy = strdup(optarg); // 创建字符串副本,以免修改原始字符串
461
+ token = strtok(str_copy, ",");
462
+
463
+ while(token != NULL){
464
+ s_rs = (char**)realloc(s_rs, sizeof(char*)*(nr+1));
465
+ s_rs[nr] = NULL;
466
+ s_rs[nr] = (char*)realloc(s_rs[nr], sizeof(char)*(strlen(token)+1));
467
+ rs = (MYREAL*)realloc(rs, sizeof(MYREAL)*(nr+1));
468
+ strcpy(s_rs[nr], token);
469
+ rs[nr] = atof(token);
470
+ if(rs[nr] == 0.0){
471
+ fprintf(stderr, "[%s] " BOLD_RED "Warning! Add 1e-5 to Zero epicentral distance in -R.\n" DEFAULT_RESTORE, command);
472
+ rs[nr] += 1e-5;
473
+ }
474
+ if(rs[nr] < 0.0){
475
+ fprintf(stderr, "[%s] " BOLD_RED "Error! Can't set negative epicentral distance(%f) in -R.\n" DEFAULT_RESTORE, command, rs[nr]);
476
+ exit(EXIT_FAILURE);
477
+ }
478
+
479
+
480
+ token = strtok(NULL, ",");
481
+ nr++;
482
+ }
483
+ free(str_copy);
484
+ }
485
+ break;
486
+
487
+ // 多线程数 -Pnthreads
488
+ case 'P':
489
+ P_flag = 1;
490
+ if(1 != sscanf(optarg, "%d", &nthreads)){
491
+ fprintf(stderr, "[%s] " BOLD_RED "Error in -P.\n" DEFAULT_RESTORE, command);
492
+ exit(EXIT_FAILURE);
493
+ };
494
+ if(nthreads <= 0){
495
+ fprintf(stderr, "[%s] " BOLD_RED "Error! Nonpositive value in -P is not supported.\n" DEFAULT_RESTORE, command);
496
+ exit(EXIT_FAILURE);
497
+ }
498
+ set_num_threads(nthreads);
499
+ break;
500
+
501
+ // 选择要计算的格林函数 -G1/1/1/1
502
+ case 'G':
503
+ G_flag = 1;
504
+ doEXP = doVF = doHF = doDC = false;
505
+ {
506
+ int i1, i2, i3, i4;
507
+ i1 = i2 = i3 = i4 = 0;
508
+ if(0 == sscanf(optarg, "%d/%d/%d/%d", &i1, &i2, &i3, &i4)){
509
+ fprintf(stderr, "[%s] " BOLD_RED "Error in -G.\n" DEFAULT_RESTORE, command);
510
+ exit(EXIT_FAILURE);
511
+ };
512
+ doEXP = (i1!=0);
513
+ doVF = (i2!=0);
514
+ doHF = (i3!=0);
515
+ doDC = (i4!=0);
516
+ }
517
+
518
+ // 至少要有一个真
519
+ if(!(doEXP || doVF || doHF || doDC)){
520
+ fprintf(stderr, "[%s] " BOLD_RED "Error! At least set one true value in -G.\n" DEFAULT_RESTORE, command);
521
+ exit(EXIT_FAILURE);
522
+ }
523
+
524
+ break;
525
+
526
+ // 输出波数积分中间文件, -Sidx1,idx2,idx3,...
527
+ case 'S':
528
+ S_flag = 1;
529
+ {
530
+ char *token;
531
+ char *str_copy = strdup(optarg); // 创建字符串副本,以免修改原始字符串
532
+ token = strtok(str_copy, ",");
533
+
534
+ while(token != NULL){
535
+ s_statsidxs = (char**)realloc(s_statsidxs, sizeof(char*)*(nstatsidxs+1));
536
+ s_statsidxs[nstatsidxs] = NULL;
537
+ s_statsidxs[nstatsidxs] = (char*)realloc(s_statsidxs[nstatsidxs], sizeof(char)*(strlen(token)+1));
538
+ strcpy(s_statsidxs[nstatsidxs], token);
539
+ statsidxs = (MYINT*)realloc(statsidxs, sizeof(MYINT)*(nstatsidxs+1));
540
+ statsidxs[nstatsidxs] = atoi(token);
541
+ if(statsidxs[nstatsidxs] < 0){
542
+ fprintf(stderr, "[%s] " BOLD_RED "Error! Can't set negative index(%d) in -S.\n" DEFAULT_RESTORE, command, statsidxs[nstatsidxs]);
543
+ exit(EXIT_FAILURE);
544
+ }
545
+
546
+ token = strtok(NULL, ",");
547
+ nstatsidxs++;
548
+ }
549
+ free(str_copy);
550
+ }
551
+ break;
552
+
553
+ // 帮助
554
+ case 'h':
555
+ print_help();
556
+ exit(EXIT_SUCCESS);
557
+ break;
558
+
559
+ // 参数缺失
560
+ case ':':
561
+ fprintf(stderr, "[%s] " BOLD_RED "Error! Option '-%c' requires an argument. Use '-h' for help.\n" DEFAULT_RESTORE, command, optopt);
562
+ exit(EXIT_FAILURE);
563
+ break;
564
+
565
+ // 非法选项
566
+ case '?':
567
+ default:
568
+ fprintf(stderr, "[%s] " BOLD_RED "Error! Option '-%c' is invalid. Use '-h' for help.\n" DEFAULT_RESTORE, command, optopt);
569
+ exit(EXIT_FAILURE);
570
+ break;
571
+ }
572
+ } // END get options
573
+
574
+ // 检查必须设置的参数是否有设置
575
+ if(argc == 1){
576
+ fprintf(stderr, "[%s] " BOLD_RED "Error! Need set options. Use '-h' for help.\n" DEFAULT_RESTORE, command);
577
+ exit(EXIT_FAILURE);
578
+ }
579
+ if(M_flag == 0){
580
+ fprintf(stderr, "[%s] " BOLD_RED "Error! Need set -M. Use '-h' for help.\n" DEFAULT_RESTORE, command);
581
+ exit(EXIT_FAILURE);
582
+ }
583
+ if(D_flag == 0){
584
+ fprintf(stderr, "[%s] " BOLD_RED "Error! Need set -D. Use '-h' for help.\n" DEFAULT_RESTORE, command);
585
+ exit(EXIT_FAILURE);
586
+ }
587
+ if(N_flag == 0){
588
+ fprintf(stderr, "[%s] " BOLD_RED "Error! Need set -N. Use '-h' for help.\n" DEFAULT_RESTORE, command);
589
+ exit(EXIT_FAILURE);
590
+ }
591
+ if(R_flag == 0){
592
+ fprintf(stderr, "[%s] " BOLD_RED "Error! Need set -R. Use '-h' for help.\n" DEFAULT_RESTORE, command);
593
+ exit(EXIT_FAILURE);
594
+ }
595
+
596
+
597
+ if(O_flag == 1){
598
+ // 建立保存目录
599
+ if(mkdir(s_output_dir, 0777) != 0){
600
+ if(errno != EEXIST){
601
+ fprintf(stderr, "[%s] " BOLD_RED "Error! Unable to create folder %s. Error code: %d\n" DEFAULT_RESTORE, command, s_output_dir, errno);
602
+ exit(EXIT_FAILURE);
603
+ }
604
+ }
605
+ } else {
606
+ // 使用当前目录
607
+ s_output_dir = (char*)malloc(sizeof(char)*100);
608
+ strcpy(s_output_dir, ".");
609
+ }
610
+
611
+
612
+ // 在目录中保留命令
613
+ char *dummy = (char*)malloc(sizeof(char)*(strlen(s_output_dir)+100));
614
+ sprintf(dummy, "%s/command", s_output_dir);
615
+ FILE *fp = fopen(dummy, "a");
616
+ for(int i=0; i<argc; ++i){
617
+ fprintf(fp, "%s ", argv[i]);
618
+ }
619
+ fprintf(fp, "\n");
620
+ fclose(fp);
621
+ free(dummy);
622
+ }
623
+
624
+ /**
625
+ * 将长数组以换行的方式打印
626
+ *
627
+ * @param nlen1 第一列字符宽度
628
+ * @param nlen2 第二列字符宽度
629
+ * @param rowname 行名
630
+ * @param s_arr 字符串数组
631
+ * @param arrsize 数组长度
632
+ */
633
+ static void print_long_array_in_tabel(
634
+ const int nlen1, const int nlen2, const char *rowname,
635
+ const char **s_arr, const int arrsize)
636
+ {
637
+ char tmp[nlen2-2];
638
+ printf("| %-*s | ", nlen1-3, rowname);
639
+ {
640
+ tmp[0] = '\0';
641
+ int len = 0;
642
+ for(int m=0; m<arrsize; ++m){
643
+ len = strlen(tmp);
644
+ char s2[strlen(s_arr[m])+2]; // 加上'\0'和逗号的长度
645
+ snprintf(s2, sizeof(s2), "%s,", s_arr[m]);
646
+
647
+ snprintf(tmp+len, sizeof(tmp)-len, "%s", s2);
648
+ while(sizeof(tmp) - strlen(tmp) == 1){ // 允许换行
649
+ printf("%-*s |\n", nlen2-3, tmp);
650
+ snprintf(tmp, sizeof(tmp), "%s", s2+(strlen(tmp)-len));
651
+ if(strcmp(tmp, ",") == 0 && m==arrsize-1) break;
652
+ printf("| %-*s | ", nlen1-3, "");
653
+ len -= strlen(tmp);
654
+ }
655
+ if(strcmp(tmp, ",") == 0 && m==arrsize-1) break;
656
+ }
657
+
658
+ if(strlen(tmp) > 0 && strcmp(tmp, ",") != 0){
659
+ printf("%-*s |\n", nlen2-3, tmp);
660
+ }
661
+ }
662
+ }
663
+
664
+
665
+ /**
666
+ * 将某一道做ifft,做时间域处理,保存到sac文件
667
+ *
668
+ * @param delay 时间延迟
669
+ * @param mult 幅值放大系数
670
+ * @param grn 某一道格林函数频谱,GRN结构体指针
671
+ * @param fftw_grn 将GRN结构体的频谱写到FFTW_COMPLEX类型中
672
+ * @param out ifft后的时域数据
673
+ * @param float_arr 将时域数据写到float类型的数组中
674
+ * @param plan FFTW_PLAN
675
+ * @param hd SAC头段变量结构体
676
+ * @param outpath sac文件保存路径
677
+ */
678
+ static void ifft_one_trace(
679
+ MYREAL delay, MYREAL mult,
680
+ MYCOMPLEX *grncplx, _FFTW_COMPLEX *fftw_grn, MYREAL *out, float *float_arr,
681
+ _FFTW_PLAN plan, SACHEAD hd, const char *outpath)
682
+ {
683
+ // 赋值复数,包括时移
684
+ MYCOMPLEX cfac, ccoef;
685
+ cfac = CEXP(I*dw*delay);
686
+ ccoef = mult;
687
+ for(int i=0; i<nf; ++i){
688
+ fftw_grn[i] = grncplx[i] * ccoef;
689
+ ccoef *= cfac;
690
+ }
691
+
692
+ // 发起fft任务
693
+ _FFTW_EXECUTE(plan);
694
+
695
+ // 归一化,并处理虚频
696
+ double fac, coef;
697
+ coef = df * EXP(delay*wI);
698
+ fac = EXP(wI*dt);
699
+ for(int i=0; i<nt; ++i){
700
+ out[i] *= coef;
701
+ coef *= fac;
702
+ }
703
+
704
+ // 以sac文件保存到本地
705
+ for(int i=0; i<nt; ++i){
706
+ float_arr[i] = out[i];
707
+ }
708
+
709
+ // 写入虚频率
710
+ hd.user0 = wI;
711
+
712
+ write_sac(outpath, hd, float_arr);
713
+ // FILE *fp = fopen(outpath, "wb");
714
+ // fwrite(out, sizeof(float), nt, fp);
715
+ // fclose(fp);
716
+ }
717
+
718
+
719
+ /**
720
+ * 以表格形式打印使用的参数
721
+ */
722
+ static void print_parameters(){
723
+ // 模拟打两列表格,第一列参数名,第二列参数值
724
+ print_pymod(pymod);
725
+ const int nlen1=20, nlen2=30; // 两列字符宽度
726
+ // 制作每行分割线
727
+ char splitline[nlen1+nlen2+2];
728
+ splitline[0] = '+';
729
+ for(int i=1; i<nlen1; splitline[i]='-', ++i);
730
+ splitline[nlen1] = '+';
731
+ for(int i=nlen1+1; i<nlen1+nlen2; splitline[i]='-', ++i);
732
+ splitline[nlen1+nlen2] = '+';
733
+ splitline[nlen1+nlen2+1] = '\0';
734
+ // 用于输出值的特殊处理
735
+ char tmp[nlen2-2];
736
+
737
+ printf("%s\n", splitline);
738
+ printf("| %-*s | %-*s |\n", nlen1-3, "Parameter", nlen2-3, "Value");
739
+ printf("%s\n", splitline);
740
+ printf("| %-*s | %-*s |\n", nlen1-3, "model_path", nlen2-3, s_modelpath);
741
+ printf("| %-*s | %-*f |\n", nlen1-3, "vmin", nlen2-3, vmin);
742
+ printf("| %-*s | %-*f |\n", nlen1-3, "vmax", nlen2-3, vmax);
743
+ // 特殊处理vmin_ref的输出
744
+ snprintf(tmp, sizeof(tmp), "%f", fabs(vmin_ref));
745
+ if(vmin_ref < 0.0) strncat(tmp, ", using PTAM.", sizeof(tmp)-strlen(tmp)-1);
746
+ printf("| %-*s | %-*s |\n", nlen1-3, "vmin_ref", nlen2-3, tmp);
747
+ // 特殊处理length的输出
748
+ snprintf(tmp, sizeof(tmp), "%f", fabs(Length));
749
+ if(Length < 0.0) strncat(tmp, ", using FIM.", sizeof(tmp)-strlen(tmp)-1);
750
+ printf("| %-*s | %-*s |\n", nlen1-3, "length", nlen2-3, tmp);
751
+ //
752
+ printf("| %-*s | %-*d |\n", nlen1-3, "nt", nlen2-3, nt);
753
+ printf("| %-*s | %-*f |\n", nlen1-3, "dt", nlen2-3, dt);
754
+ printf("| %-*s | %-*f |\n", nlen1-3, "winT", nlen2-3, winT);
755
+ printf("| %-*s | %-*f |\n", nlen1-3, "zeta", nlen2-3, zeta);
756
+ printf("| %-*s | %-*f |\n", nlen1-3, "delayT0", nlen2-3, delayT0);
757
+ printf("| %-*s | %-*f |\n", nlen1-3, "delayV0", nlen2-3, delayV0);
758
+ printf("| %-*s | %-*f |\n", nlen1-3, "tmax", nlen2-3, tmax);
759
+ printf("| %-*s | %-*f |\n", nlen1-3, "k0", nlen2-3, k0);
760
+ printf("| %-*s | %-*f |\n", nlen1-3, "ampk", nlen2-3, ampk);
761
+ printf("| %-*s | %-*s |\n", nlen1-3, "iwk0", nlen2-3, (iwk0 ? "true" : "false"));
762
+ printf("| %-*s | %-*f |\n", nlen1-3, "keps", nlen2-3, keps);
763
+ printf("| %-*s | %-*f |\n", nlen1-3, "maxfreq(Hz)", nlen2-3, freqs[nf-1]);
764
+ printf("| %-*s | %-*f |\n", nlen1-3, "f1(Hz)", nlen2-3, freqs[nf1]);
765
+ printf("| %-*s | %-*f |\n", nlen1-3, "f2(Hz)", nlen2-3, freqs[nf2]);
766
+ // 特殊处理震中距的输出
767
+ print_long_array_in_tabel(nlen1, nlen2, "distances(km)", (const char **)s_rs, nr);
768
+
769
+ // 特殊处理statsfile index的输出
770
+ if(nstatsidxs > 0){
771
+ print_long_array_in_tabel(nlen1, nlen2, "statsfile_index", (const char **)s_statsidxs, nstatsidxs);
772
+ }
773
+
774
+ printf("| %-*s | ", nlen1-3, "sources");
775
+ tmp[0] = '\0';
776
+ if(doEXP) snprintf(tmp+strlen(tmp), sizeof(tmp)-strlen(tmp), "EX,");
777
+ if(doVF) snprintf(tmp+strlen(tmp), sizeof(tmp)-strlen(tmp), "VF,");
778
+ if(doHF) snprintf(tmp+strlen(tmp), sizeof(tmp)-strlen(tmp), "HF,");
779
+ if(doDC) snprintf(tmp+strlen(tmp), sizeof(tmp)-strlen(tmp), "DC,");
780
+ printf("%-*s |\n", nlen2-3, tmp);
781
+
782
+ // 特殊处理输出路径
783
+ printf("| %-*s | ", nlen1-3, "output_path");
784
+ {
785
+ int len=0;
786
+ tmp[0] = '\0';
787
+ snprintf(tmp+strlen(tmp), sizeof(tmp)-strlen(tmp), "%s", s_output_dir);
788
+ len = strlen(tmp);
789
+ while(sizeof(tmp) - strlen(tmp) == 1){ // 允许换行
790
+ printf("%-*s |\n", nlen2-3, tmp);
791
+ snprintf(tmp, sizeof(tmp), "%s", s_output_dir+(strlen(tmp)-len));
792
+ printf("| %-*s | ", nlen1-3, "");
793
+ len -= strlen(tmp);
794
+ }
795
+ if(strlen(tmp) > 0){
796
+ printf("%-*s |\n", nlen2-3, tmp);
797
+ }
798
+ }
799
+ printf("%s\n", splitline);
800
+ printf("\n");
801
+
802
+ }
803
+
804
+
805
+ /**
806
+ * 以表格形式打印输出的文件夹和走时
807
+ *
808
+ * @param s_output_subdir 输出文件夹
809
+ * @param s_R 字符串形式的震中距
810
+ * @param Tp P波初至走时
811
+ * @param Ts S波初至走时
812
+ */
813
+ static void print_outdir_travt(const char *s_output_subdir, const char *s_R, double Tp, double Ts){
814
+ // 进入该函数的次数
815
+ static int numin = 0;
816
+
817
+ static const int ncols = 4;
818
+ static const int nlens[] = {28, 17, 13, 13};
819
+ int Nlen=0;
820
+ for(int ic=0; ic<ncols; ++ic){
821
+ Nlen += nlens[ic];
822
+ }
823
+ // 定义分割线
824
+ char splitline[Nlen+2];
825
+ {
826
+ int n=0;
827
+ for(int ic=0; ic<ncols; ++ic){
828
+ splitline[n] = '+';
829
+ for(int i=1; i<nlens[ic]; ++i){
830
+ splitline[n + i] = '-';
831
+ }
832
+ n += nlens[ic];
833
+ }
834
+ splitline[Nlen] = '+';
835
+ splitline[Nlen+1] = '\0';
836
+ }
837
+
838
+ // 第一次执行该函数,打印题头
839
+ if(numin == 0){
840
+ printf("\n");
841
+ printf("%s\n", splitline);
842
+ printf("| %-*s ", nlens[0]-3, "Output Directory");
843
+ printf("| %-*s ", nlens[1]-3, "Distance(km)");
844
+ printf("| %-*s ", nlens[2]-3, "Tp(secs)");
845
+ printf("| %-*s ", nlens[2]-3, "Ts(secs)");
846
+ printf("|\n");
847
+ printf("%s\n", splitline);
848
+ }
849
+
850
+
851
+ // 打印目录、震中距、走时P、走时S
852
+ // 目录和震中距的字符串可能分行,且行数不一
853
+ // 这里不断分行打印,直到打印完
854
+ char dirtmp[nlens[0]-2];
855
+ char Rtmp[nlens[1]-2];
856
+ int lendir=0, lenR=0;
857
+ int LENdir=strlen(s_output_subdir);
858
+ int LENR=strlen(s_R);
859
+ dirtmp[0] = '\0';
860
+ Rtmp[0] = '\0';
861
+ int iline=0;
862
+ int idir=0, iR=0;
863
+
864
+ snprintf(dirtmp, sizeof(dirtmp), "%s", s_output_subdir);
865
+ snprintf(Rtmp, sizeof(Rtmp), "%s", s_R);
866
+ lendir = strlen(dirtmp);
867
+ lenR = strlen(Rtmp);
868
+ do{
869
+ printf("| %-*s ", nlens[0]-3, dirtmp);
870
+ idir += strlen(dirtmp);
871
+ if(sizeof(dirtmp) - strlen(dirtmp) == 1 && lendir < LENdir){
872
+ snprintf(dirtmp, sizeof(dirtmp), "%s", s_output_subdir+lendir);
873
+ lendir += strlen(dirtmp);
874
+ } else {
875
+ dirtmp[0] = '\0';
876
+ }
877
+
878
+ printf("| %-*s ", nlens[1]-3, Rtmp);
879
+ iR += strlen(Rtmp);
880
+ if(sizeof(Rtmp) - strlen(Rtmp) == 1 && lenR < LENR){
881
+ snprintf(Rtmp, sizeof(Rtmp), "%s", s_R+lenR);
882
+ lenR += strlen(Rtmp);
883
+ } else {
884
+ Rtmp[0] = '\0';
885
+ }
886
+
887
+ if(iline == 0){
888
+ printf("| %-*.3f ", nlens[2]-3, Tp);
889
+ printf("| %-*.3f ", nlens[3]-3, Ts);
890
+ } else {
891
+ printf("| %-*s ", nlens[2]-3, " ");
892
+ printf("| %-*s ", nlens[3]-3, " ");
893
+ }
894
+ printf("|\n");
895
+
896
+ iline++;
897
+
898
+ // printf("iR=%d, idir=%d, LENDIR=%d\n", iR, idir, LENdir);
899
+
900
+ }while(iR < LENR || idir < LENdir);
901
+
902
+ if(numin == nr-1){
903
+ printf("%s\n", splitline);
904
+ printf("\n");
905
+ }
906
+
907
+
908
+ numin++;
909
+ }
910
+
911
+
912
+
913
+ //====================================================================================
914
+ //====================================================================================
915
+ //====================================================================================
916
+ int main(int argc, char **argv) {
917
+ command = argv[0];
918
+
919
+ // 传入参数
920
+ getopt_from_command(argc, argv);
921
+
922
+ // 读入模型文件
923
+ if((pymod = read_pymod_from_file(command, s_modelpath, depsrc, deprcv)) ==NULL){
924
+ exit(EXIT_FAILURE);
925
+ }
926
+
927
+ // 最大最小速度
928
+ vmax = pymod->Va[findMinMax_MYREAL(pymod->Va, pymod->n, true)];
929
+ vmin = pymod->Vb[findMinMax_MYREAL(pymod->Vb, pymod->n, false)];
930
+ if(vmin > vmax) {
931
+ double tmp;
932
+ tmp = vmin; vmin = vmax; vmax = tmp;
933
+ }
934
+
935
+ // 参考最小速度
936
+ if(vmin_ref == 0.0){
937
+ vmin_ref = vmin;
938
+ if(vmin_ref < min_vmin_ref) vmin_ref = min_vmin_ref;
939
+ }
940
+
941
+ // 如果没有主动设置vmin_ref,则判断是否要自动使用PTAM
942
+ if(V_flag == 0 && fabs(deprcv - depsrc) <= hs_ptam) {
943
+ vmin_ref = - fabs(vmin_ref);
944
+ }
945
+
946
+ // 时窗长度
947
+ winT = nt*dt;
948
+
949
+ // 最大震中距
950
+ MYREAL rmax=rs[findMinMax_MYREAL(rs, nr, true)];
951
+
952
+ // 时窗最大截止时刻
953
+ tmax = delayT0 + winT;
954
+ if(delayV0 > 0.0) tmax += rmax/delayV0;
955
+
956
+ // 自动选择积分间隔,默认使用传统离散波数积分
957
+ // 自动选择会给出很保守的值(较大的Length)
958
+ if(Length == 0.0){
959
+ Length = 15.0;
960
+ double jus = (vmax*tmax)*(vmax*tmax) - (deprcv-depsrc)*(deprcv-depsrc);
961
+ if(jus >= 0.0){
962
+ Length = 1.0 + sqrt(jus)/rmax + 0.5; // +0.5为保守值
963
+ if(Length < 15.0) Length = 15.0;
964
+ }
965
+ }
966
+
967
+ // 虚频率
968
+ wI = zeta*PI/winT;
969
+
970
+ // 定义要计算的频率、时窗等
971
+ nf = nt/2 + 1;
972
+ df = 1.0/winT;
973
+ dw = 2.0*PI*df;
974
+ freqs = (MYREAL*)malloc(nf*sizeof(MYREAL));
975
+ for(int i=0; i<nf; ++i){
976
+ freqs[i] = i*df;
977
+ }
978
+
979
+ nf1 = 0; nf2 = nf-1;
980
+ if(freq1 > 0.0){
981
+ nf1 = (int)(freq1/df) + 1;
982
+ if(nf1 >= nf-1) nf1 = nf-1;
983
+ }
984
+ if(freq2 > 0.0){
985
+ nf2 = (int)(freq2/df) + 1;
986
+ if(nf2 >= nf-1) nf2 = nf-1;
987
+ }
988
+
989
+ // 波数积分中间文件输出目录
990
+ if(nstatsidxs > 0){
991
+ s_statsdir = (char*)malloc(sizeof(char)*(strlen(s_modelpath)+strlen(s_output_dir)+100));
992
+ sprintf(s_statsdir, "%s_grtstats", s_output_dir);
993
+ // 建立保存目录
994
+ if(mkdir(s_statsdir, 0777) != 0){
995
+ if(errno != EEXIST){
996
+ fprintf(stderr, "[%s] " BOLD_RED "Error! Unable to create folder %s. Error code: %d\n" DEFAULT_RESTORE, command, s_statsdir, errno);
997
+ exit(EXIT_FAILURE);
998
+ }
999
+ }
1000
+ sprintf(s_statsdir, "%s/%s_stats", s_statsdir, s_modelname);
1001
+ }
1002
+
1003
+
1004
+ // 建立格林函数的complex数组
1005
+ MYCOMPLEX *(*EXPcplx)[2] = (doEXP) ? (MYCOMPLEX*(*)[2])calloc(nr, sizeof(*EXPcplx)) : NULL;
1006
+ MYCOMPLEX *(*VFcplx)[2] = (doVF) ? (MYCOMPLEX*(*)[2])calloc(nr, sizeof(*VFcplx)) : NULL;
1007
+ MYCOMPLEX *(*HFcplx)[3] = (doHF) ? (MYCOMPLEX*(*)[3])calloc(nr, sizeof(*HFcplx)) : NULL;
1008
+ MYCOMPLEX *(*DDcplx)[2] = (doDC) ? (MYCOMPLEX*(*)[2])calloc(nr, sizeof(*DDcplx)) : NULL;
1009
+ MYCOMPLEX *(*DScplx)[3] = (doDC) ? (MYCOMPLEX*(*)[3])calloc(nr, sizeof(*DScplx)) : NULL;
1010
+ MYCOMPLEX *(*SScplx)[3] = (doDC) ? (MYCOMPLEX*(*)[3])calloc(nr, sizeof(*SScplx)) : NULL;
1011
+
1012
+ for(int ir=0; ir<nr; ++ir){
1013
+ for(int i=0; i<3; ++i){
1014
+ if(i<2){
1015
+ if(EXPcplx) EXPcplx[ir][i] = (MYCOMPLEX*)calloc(nf, sizeof(MYCOMPLEX));
1016
+ if(VFcplx) VFcplx[ir][i] = (MYCOMPLEX*)calloc(nf, sizeof(MYCOMPLEX));
1017
+ if(DDcplx) DDcplx[ir][i] = (MYCOMPLEX*)calloc(nf, sizeof(MYCOMPLEX));
1018
+ }
1019
+ if(HFcplx) HFcplx[ir][i] = (MYCOMPLEX*)calloc(nf, sizeof(MYCOMPLEX));
1020
+ if(DScplx) DScplx[ir][i] = (MYCOMPLEX*)calloc(nf, sizeof(MYCOMPLEX));
1021
+ if(SScplx) SScplx[ir][i] = (MYCOMPLEX*)calloc(nf, sizeof(MYCOMPLEX));
1022
+ }
1023
+ }
1024
+
1025
+
1026
+
1027
+ // 在计算前打印所有参数
1028
+ if(! silenceInput){
1029
+ print_parameters();
1030
+ }
1031
+
1032
+
1033
+ //==============================================================================
1034
+ // 计算格林函数
1035
+ integ_grn_spec_in_C(
1036
+ pymod, nf1, nf2, nf, freqs, nr, rs, wI,
1037
+ vmin_ref, keps, ampk, iwk0, k0, Length, !silenceInput,
1038
+ EXPcplx, VFcplx, HFcplx, DDcplx, DScplx, SScplx,
1039
+ s_statsdir, nstatsidxs, statsidxs
1040
+ );
1041
+ //==============================================================================
1042
+
1043
+
1044
+ // 使用fftw3做反傅里叶变换
1045
+ // 分配fftw_complex内存
1046
+ _FFTW_COMPLEX *fftw_grn = (_FFTW_COMPLEX*)_FFTW_MALLOC(sizeof(_FFTW_COMPLEX)*nf);
1047
+ MYREAL *out = (MYREAL*)malloc(sizeof(MYREAL)*nt);
1048
+ float *float_arr = (float*)malloc(sizeof(float)*nt);
1049
+
1050
+ // fftw计划
1051
+ _FFTW_PLAN plan = _FFTW_PLAN_DFT_C2R_1D(nt, fftw_grn, out, FFTW_ESTIMATE);
1052
+
1053
+ // 建立SAC头文件,包含必要的头变量
1054
+ SACHEAD hd = new_sac_head(dt, nt, delayT0);
1055
+ char kcmpnm[9];
1056
+ // 发震时刻作为参考时刻
1057
+ hd.o = 0.0;
1058
+ hd.iztype = IO;
1059
+ // 记录震源和台站深度
1060
+ hd.evdp = depsrc; // km
1061
+ hd.stel = (-1.0)*deprcv*1e3; // m
1062
+
1063
+
1064
+ // 做反傅里叶变换,保存SAC文件
1065
+ for(int ir=0; ir<nr; ++ir){
1066
+ hd.dist = rs[ir];
1067
+
1068
+ // 文件保存子目录
1069
+ char *s_output_subdir = (char*)malloc(sizeof(char)*(
1070
+ strlen(s_output_dir)+strlen(s_modelpath)+
1071
+ strlen(s_depsrc)+strlen(s_deprcv)+strlen(s_rs[ir])+100));
1072
+
1073
+ sprintf(s_output_subdir, "%s/%s_%s_%s_%s", s_output_dir, s_modelname, s_depsrc, s_deprcv, s_rs[ir]);
1074
+ if(mkdir(s_output_subdir, 0777) != 0){
1075
+ if(errno != EEXIST){
1076
+ fprintf(stderr, "[%s] " BOLD_RED "Error! Unable to create folder %s. Error code: %d\n" DEFAULT_RESTORE, command, s_output_subdir, errno);
1077
+ exit(EXIT_FAILURE);
1078
+ }
1079
+ }
1080
+ // 时间延迟
1081
+ delayT = delayT0;
1082
+ if(delayV0 > 0.0) delayT += sqrt(rs[ir]*rs[ir] + (deprcv-depsrc)*(deprcv-depsrc))/delayV0;
1083
+ // 修改SAC头段时间变量
1084
+ hd.b = delayT;
1085
+
1086
+ // 计算理论走时
1087
+ hd.t0 = compute_travt1d(pymod->Thk, pymod->Va, pymod->n, pymod->isrc, pymod->ircv, rs[ir]);
1088
+ strcpy(hd.kt0, "P");
1089
+ hd.t1 = compute_travt1d(pymod->Thk, pymod->Vb, pymod->n, pymod->isrc, pymod->ircv, rs[ir]);
1090
+ strcpy(hd.kt1, "S");
1091
+
1092
+ // 用于反转Z分量
1093
+ int sgn=1;
1094
+ for(int i=0; i<3; ++i){
1095
+ // 文件保存总路径
1096
+ // char *s_outpath = (char*)malloc(sizeof(char)*(strlen(s_output_dir)+100));
1097
+ char *s_outpath = (char*)malloc(sizeof(char)*(strlen(s_output_subdir)+100));
1098
+ // char *s_suffix = (char*)malloc(sizeof(char)*(strlen(s_depsrc)+strlen(s_deprcv)+strlen(s_rs[ir])+100));
1099
+ // sprintf(s_suffix, "%s_%s_%s", s_depsrc, s_deprcv, s_rs[ir]);
1100
+ char s_suffix[] = "";
1101
+
1102
+ // Z分量反转
1103
+ sgn = (i==0) ? -1 : 1;
1104
+ if(i<2){
1105
+ if(doEXP){
1106
+ sprintf(kcmpnm, "EX%c", chs[i]);
1107
+ strcpy(hd.kcmpnm, kcmpnm);
1108
+ sprintf(s_outpath, "%s/%s%c%s.sac", s_output_subdir, "EX", chs[i], s_suffix);
1109
+ ifft_one_trace(delayT, sgn, EXPcplx[ir][i], fftw_grn, out, float_arr, plan, hd, s_outpath);
1110
+ }
1111
+ if(doVF){
1112
+ sprintf(kcmpnm, "VF%c", chs[i]);
1113
+ strcpy(hd.kcmpnm, kcmpnm);
1114
+ sprintf(s_outpath, "%s/%s%c%s.sac", s_output_subdir, "VF", chs[i], s_suffix);
1115
+ ifft_one_trace(delayT, sgn, VFcplx[ir][i], fftw_grn, out, float_arr, plan, hd, s_outpath);
1116
+ }
1117
+ if(doDC){
1118
+ sprintf(kcmpnm, "DD%c", chs[i]);
1119
+ strcpy(hd.kcmpnm, kcmpnm);
1120
+ sprintf(s_outpath, "%s/%s%c%s.sac", s_output_subdir, "DD", chs[i], s_suffix);
1121
+ ifft_one_trace(delayT, sgn, DDcplx[ir][i], fftw_grn, out, float_arr, plan, hd, s_outpath);
1122
+ }
1123
+ }
1124
+
1125
+ if(doHF){
1126
+ sprintf(kcmpnm, "HF%c", chs[i]);
1127
+ strcpy(hd.kcmpnm, kcmpnm);
1128
+ sprintf(s_outpath, "%s/%s%c%s.sac", s_output_subdir, "HF", chs[i], s_suffix);
1129
+ ifft_one_trace(delayT, sgn, HFcplx[ir][i], fftw_grn, out, float_arr, plan, hd, s_outpath);
1130
+ }
1131
+
1132
+ if(doDC){
1133
+ sprintf(kcmpnm, "DS%c", chs[i]);
1134
+ strcpy(hd.kcmpnm, kcmpnm);
1135
+ sprintf(s_outpath, "%s/%s%c%s.sac", s_output_subdir, "DS", chs[i], s_suffix);
1136
+ ifft_one_trace(delayT, sgn, DScplx[ir][i], fftw_grn, out, float_arr, plan, hd, s_outpath);
1137
+ sprintf(kcmpnm, "SS%c", chs[i]);
1138
+ strcpy(hd.kcmpnm, kcmpnm);
1139
+ sprintf(s_outpath, "%s/%s%c%s.sac", s_output_subdir, "SS", chs[i], s_suffix);
1140
+ ifft_one_trace(delayT, sgn, SScplx[ir][i], fftw_grn, out, float_arr, plan, hd, s_outpath);
1141
+ }
1142
+
1143
+ free(s_outpath);
1144
+ // free(s_suffix);
1145
+ }
1146
+
1147
+
1148
+ if(!silenceInput){
1149
+ print_outdir_travt(s_output_subdir, s_rs[ir], hd.t0, hd.t1);
1150
+ }
1151
+
1152
+
1153
+ free(s_output_subdir);
1154
+ }
1155
+
1156
+
1157
+ // 释放内存
1158
+ free(s_modelpath);
1159
+ free(s_depsrc);
1160
+ free(s_deprcv);
1161
+ free(s_output_dir);
1162
+
1163
+ for(int ir=0; ir<nr; ++ir){
1164
+ free(s_rs[ir]);
1165
+ for(int i=0; i<3; ++i){
1166
+ if(i<2){
1167
+ if(doEXP){
1168
+ free(EXPcplx[ir][i]);
1169
+ }
1170
+ if(doVF){
1171
+ free(VFcplx[ir][i]);
1172
+ }
1173
+ if(doDC){
1174
+ free(DDcplx[ir][i]);
1175
+ }
1176
+ }
1177
+ if(doHF){
1178
+ free(HFcplx[ir][i]);
1179
+ }
1180
+ if(doDC){
1181
+ free(DScplx[ir][i]);
1182
+ free(SScplx[ir][i]);
1183
+ }
1184
+ }
1185
+ }
1186
+ if(EXPcplx) free(EXPcplx);
1187
+ if(VFcplx) free(VFcplx);
1188
+ if(HFcplx) free(HFcplx);
1189
+ if(DDcplx) free(DDcplx);
1190
+ if(DScplx) free(DScplx);
1191
+ if(SScplx) free(SScplx);
1192
+
1193
+ free(s_rs);
1194
+ free(rs);
1195
+ free(s_statsdir);
1196
+ free(statsidxs);
1197
+ for(int i=0; i<nstatsidxs; ++i){
1198
+ free(s_statsidxs[i]);
1199
+ }
1200
+ free(s_statsidxs);
1201
+ free(freqs);
1202
+ _FFTW_FREE(fftw_grn);
1203
+ free(out);
1204
+ free(float_arr);
1205
+ _FFTW_DESTROY_PLAN(plan);
1206
+
1207
+ free_pymod(pymod);
1208
+
1209
+
1210
+
1211
+
1212
+ return 0;
1213
+ }
1214
+
1215
+