├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── README.zh-CN.md ├── Readme_zh.docx ├── changelog.md ├── config ├── jilongshan.ini └── test.ini ├── fastxc ├── Makefile ├── SeisHandler │ ├── __init__.py │ ├── pattern_utils.py │ ├── seis_array.py │ ├── seisfile_filter.py │ ├── seisfile_matcher.py │ └── seisfile_organizer.py ├── __init__.py ├── bin │ ├── RotateNCF │ ├── extractSegments │ ├── sac2spec │ └── xc_new ├── cmd_StackRotate_utils.py ├── cmd_sac2spec_utils.py ├── cmd_xc_utils.py ├── config_parse.py ├── deployer_StackRotate.py ├── deployer_sac2dat.py ├── deployer_sac2spec.py ├── deployer_xc.py ├── design_filter.py ├── fastxc.py ├── gen_rotate_list_dir.py ├── gen_sac2spec_list_dir.py ├── gen_stack_list_dir.py ├── gen_xc_list_dir.py └── sac2spec_pyv │ ├── __init__.py │ ├── arguproc.py │ ├── group_files.py │ ├── main.py │ ├── process_a_group.py │ ├── run_abs_multi.py │ ├── spectrum_whiten.py │ └── write_spectrum.py ├── log └── madiliang_file.txt ├── run.py ├── src ├── extractSegments │ ├── .vscode │ │ └── settings.json │ ├── Makefile │ ├── arguproc.c │ ├── arguproc.h │ ├── do.sh │ ├── main.c │ ├── sac.h │ └── sacio.c ├── rotate │ ├── .vscode │ │ ├── c_cpp_properties.json │ │ └── settings.json │ ├── Makefile │ ├── arguproc.c │ ├── arguproc.h │ ├── hddistance.c │ ├── hddistance.h │ ├── main.c │ ├── readme.txt │ ├── rotate.c │ ├── rotate.h │ ├── sac.h │ └── sacio.c ├── sac2spec │ ├── .vscode │ │ └── settings.json │ ├── Makefile │ ├── arguproc.c │ ├── arguproc.h │ ├── cal_nseg.c │ ├── cal_nseg.h │ ├── complex.h │ ├── config.h │ ├── cuda.main.cu │ ├── cuda.misc.cu │ ├── cuda.misc.cuh │ ├── cuda.processing.cu │ ├── cuda.processing.cuh │ ├── cuda.rdcrtr.cu │ ├── cuda.rdcrtr.cuh │ ├── cuda.taper.cu │ ├── cuda.taper.cuh │ ├── cuda.util.cu │ ├── cuda.util.cuh │ ├── design_filter_response.c │ ├── design_filter_response.h │ ├── in_out_node.h │ ├── par_rw_data.c │ ├── par_rw_data.h │ ├── read_filelist.c │ ├── read_filelist.h │ ├── readme.txt │ ├── sac.h │ ├── sacio.c │ ├── segspec.h │ ├── util.c │ └── util.h ├── sac2spec_butter │ ├── .vscode │ │ └── settings.json │ ├── Makefile │ ├── arguproc.c │ ├── arguproc.h │ ├── cal_nseg.c │ ├── cal_nseg.h │ ├── complex.h │ ├── config.h │ ├── cuda.filter.cu │ ├── cuda.filter.cuh │ ├── cuda.main.cu │ ├── cuda.misc.cu │ ├── cuda.misc.cuh │ ├── cuda.processing.cu │ ├── cuda.processing.cuh │ ├── cuda.rdcrtr.cu │ ├── cuda.rdcrtr.cuh │ ├── cuda.taper.cu │ ├── cuda.taper.cuh │ ├── cuda.util.cu │ ├── cuda.util.cuh │ ├── design_filter_response.c │ ├── design_filter_response.h │ ├── in_out_node.h │ ├── par_rw_data.c │ ├── par_rw_data.h │ ├── read_filelist.c │ ├── read_filelist.h │ ├── readme.txt │ ├── sac.h │ ├── sacio.c │ ├── segspec.h │ ├── util.c │ └── util.h ├── sac2spec_cos │ ├── .vscode │ │ └── settings.json │ ├── Makefile │ ├── arguproc.c │ ├── arguproc.h │ ├── cal_nseg.c │ ├── cal_nseg.h │ ├── complex.h │ ├── config.h │ ├── cuda.main.cu │ ├── cuda.misc.cu │ ├── cuda.misc.cuh │ ├── cuda.processing.cu │ ├── cuda.processing.cuh │ ├── cuda.rdcrtr.cu │ ├── cuda.rdcrtr.cuh │ ├── cuda.taper.cu │ ├── cuda.taper.cuh │ ├── cuda.util.cu │ ├── cuda.util.cuh │ ├── design_filter_response.c │ ├── design_filter_response.h │ ├── in_out_node.h │ ├── par_rw_data.c │ ├── par_rw_data.h │ ├── read_filelist.c │ ├── read_filelist.h │ ├── readme.txt │ ├── sac.h │ ├── sacio.c │ ├── segspec.h │ ├── util.c │ └── util.h ├── sac2spec_super │ ├── .vscode │ │ └── settings.json │ ├── Makefile │ ├── arguproc.c │ ├── arguproc.h │ ├── cal_nseg.c │ ├── cal_nseg.h │ ├── complex.h │ ├── config.h │ ├── cuda.main.cu │ ├── cuda.misc.cu │ ├── cuda.misc.cuh │ ├── cuda.processing.cu │ ├── cuda.processing.cuh │ ├── cuda.rdcrtr.cu │ ├── cuda.rdcrtr.cuh │ ├── cuda.taper.cu │ ├── cuda.taper.cuh │ ├── cuda.util.cu │ ├── cuda.util.cuh │ ├── design_filter_response.c │ ├── design_filter_response.h │ ├── in_out_node.h │ ├── par_rw_data.c │ ├── par_rw_data.h │ ├── read_filelist.c │ ├── read_filelist.h │ ├── readme.txt │ ├── sac.h │ ├── sacio.c │ ├── segspec.h │ ├── util.c │ └── util.h ├── stack │ ├── .vscode │ │ └── settings.json │ ├── Makefile │ ├── Readme.txt │ ├── arguproc.c │ ├── arguproc.h │ ├── main.c │ ├── read_sac_lst.c │ ├── read_sac_lst.h │ ├── sac.h │ ├── sacio.c │ ├── util.c │ └── util.h ├── xc_dual │ ├── .vscode │ │ └── settings.json │ ├── Makefile │ ├── arguproc.c │ ├── arguproc.h │ ├── cal_dist.c │ ├── cal_dist.h │ ├── complex.h │ ├── cuda.estimate_batch.cu │ ├── cuda.estimate_batch.cuh │ ├── cuda.main.cu │ ├── cuda.pws_util.cu │ ├── cuda.pws_util.cuh │ ├── cuda.stransform.cu │ ├── cuda.stransform.cuh │ ├── cuda.util.cu │ ├── cuda.util.cuh │ ├── cuda.xc_dual.cu │ ├── cuda.xc_dual.cuh │ ├── do.sh │ ├── gen_ncf_path.c │ ├── gen_ncf_path.h │ ├── gen_pair.c │ ├── gen_pair.h │ ├── read_segspec.c │ ├── read_segspec.h │ ├── sac.h │ ├── sacio.c │ ├── segspec.h │ ├── util.c │ └── util.h └── xc_multi │ ├── .vscode │ └── settings.json │ ├── Makefile │ ├── arguproc.c │ ├── arguproc.h │ ├── cal_dist.c │ ├── cal_dist.h │ ├── complex.h │ ├── config.h │ ├── cuda.main.cu │ ├── cuda.util.cu │ ├── cuda.util.cuh │ ├── cuda.xc_dual.cu │ ├── cuda.xc_dual.cuh │ ├── do.sh │ ├── gen_ccfpath.c │ ├── gen_ccfpath.h │ ├── node_util.h │ ├── par_filter_nodes.c │ ├── par_filter_nodes.h │ ├── par_read_spec.c │ ├── par_read_spec.h │ ├── par_write_sac.c │ ├── par_write_sac.h │ ├── read_segspec.c │ ├── read_segspec.h │ ├── read_spec_lst.c │ ├── read_spec_lst.h │ ├── readme.txt │ ├── sac.h │ ├── sacio.c │ ├── segspec.h │ ├── util.c │ └── util.h ├── test_data ├── 0101 │ └── 2017 │ │ ├── 0101.2017.237.0000.E.sac │ │ ├── 0101.2017.237.0000.N.sac │ │ ├── 0101.2017.237.0000.Z.sac │ │ ├── 0101.2017.238.0000.E.sac │ │ ├── 0101.2017.238.0000.N.sac │ │ ├── 0101.2017.238.0000.Z.sac │ │ ├── 0101.2017.239.0000.E.sac │ │ ├── 0101.2017.239.0000.N.sac │ │ └── 0101.2017.239.0000.Z.sac └── 0107 │ └── 2017 │ ├── 0107.2017.237.0000.E.sac │ ├── 0107.2017.237.0000.N.sac │ ├── 0107.2017.237.0000.Z.sac │ ├── 0107.2017.238.0000.E.sac │ ├── 0107.2017.238.0000.N.sac │ ├── 0107.2017.238.0000.Z.sac │ ├── 0107.2017.239.0000.E.sac │ ├── 0107.2017.239.0000.N.sac │ └── 0107.2017.239.0000.Z.sac └── utils ├── GPU_vs_CPU.png ├── check_gpu ├── check_gpu.cu └── compile.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # ---------- Python ---------- 2 | __pycache__/ 3 | *.py[cod] 4 | *.pyo 5 | *.egg-info/ 6 | .Python 7 | 8 | # ---------- C / CUDA ---------- 9 | # 对象文件、静态/动态库、编译依赖 10 | *.o 11 | *.obj 12 | *.a 13 | *.so 14 | *.dll 15 | *.d 16 | *.dSYM/ 17 | *.exe 18 | 19 | # ---------- 可执行产物 ---------- 20 | /bin/ 21 | *.out 22 | *.run 23 | *.stackdump 24 | 25 | # ---------- 构建系统 ---------- 26 | /build/ 27 | CMakeFiles/ 28 | CMakeCache.txt 29 | Makefile 30 | cmake_install.cmake 31 | 32 | # ---------- IDE / 编辑器 ---------- 33 | .vscode/ 34 | .idea/ 35 | *.swp 36 | *~ 37 | 38 | # ---------- 日志 / 临时 ---------- 39 | *.log 40 | *.tmp 41 | *.bak 42 | # 压缩归档 43 | *.zip 44 | *.tar.gz 45 | *.tgz 46 | 47 | # ---------- Jupyter ---------- 48 | .ipynb_checkpoints/ 49 | 50 | # ---------- 依赖镜像 ---------- 51 | .env/ 52 | .venv/ 53 | .envrc 54 | 55 | 56 | # ─── Python 运行产生的缓存 ────────────────────────────────────────── 57 | __pycache__/ 58 | *.py[cod] # .pyc .pyo .pyd 59 | 60 | # ─── 临时 / 调试日志 ─────────────────────────────────────────────── 61 | *.log 62 | log_test_file.txt 63 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 wang kinghei 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------- 2 | # fastxc — 顶层 Makefile 3 | # • make → Release 并行(默认) 4 | # • make MODE=seq → Release 串行 5 | # • make debug → Debug 并行 6 | # • make debug MODE=seq → Debug 串行 7 | # ---------------------------------------------------- 8 | 9 | # ---------- 编译器 ---------- 10 | CC ?= gcc 11 | NVCC ?= /usr/local/cuda/bin/nvcc 12 | ARCH ?= sm_89 13 | 14 | # ---------- Release / Debug ---------- 15 | CFLAGS ?= -O3 -Wall 16 | NVCCFLAGS ?= -O3 --use_fast_math --generate-line-info -arch=$(ARCH) 17 | 18 | DBG_CFLAGS := -O0 -g -Wall 19 | DBG_NVCCFLAGS := -O0 -g -G -lineinfo -arch=$(ARCH) 20 | 21 | # ---------- 向子 make 继承 ---------- 22 | export CC NVCC ARCH 23 | export CFLAGS NVCCFLAGS 24 | 25 | # ---------- 并行 / 串行 开关 ---------- 26 | MODE ?= par # par (默认) | seq 27 | ifeq ($(MODE),par) 28 | PARFLAG = -j # 并行 29 | else 30 | PARFLAG = # 串行 31 | endif 32 | 33 | # ---------- GNU make ≥4 输出同步 ---------- 34 | ifeq ($(shell expr $(firstword $(subst ., ,$(MAKE_VERSION))) \>= 4),1) 35 | OSYNC ?= --output-sync=target 36 | else 37 | OSYNC := 38 | endif 39 | 40 | # ---------- 子目录 ---------- 41 | SUBDIRS := \ 42 | src/sac2spec src/sac2spec_butter \ 43 | src/sac2spec_cos src/sac2spec_super \ 44 | src/xc_multi src/xc_dual \ 45 | src/stack src/rotate \ 46 | src/extractSegments 47 | 48 | .PHONY: all debug clean veryclean recurse $(SUBDIRS) help 49 | 50 | # ---------- 递归规则 ---------- 51 | recurse: $(SUBDIRS) 52 | 53 | $(SUBDIRS): 54 | @echo "========== [ $@ ] ==========" 55 | $(MAKE) -C $@ 56 | 57 | # ---------- 默认目标:Release ---------- 58 | all: ## Build Release (MODE=par|seq) 59 | @$(info === Building in RELEASE mode, MODE=$(MODE) ===) 60 | $(MAKE) $(PARFLAG) $(OSYNC) recurse 61 | 62 | # ---------- Debug 目标 ---------- 63 | debug: export CFLAGS=$(DBG_CFLAGS) 64 | debug: export NVCCFLAGS=$(DBG_NVCCFLAGS) 65 | debug: ## Build Debug (MODE=par|seq) 66 | @$(info === Building in DEBUG mode, MODE=$(MODE) ===) 67 | $(MAKE) $(PARFLAG) $(OSYNC) recurse 68 | 69 | # ---------- 清理 ---------- 70 | clean: 71 | @for dir in $(SUBDIRS); do \ 72 | echo ">> Cleaning in $$dir"; \ 73 | $(MAKE) -C $$dir clean; \ 74 | done 75 | 76 | veryclean: 77 | @for dir in $(SUBDIRS); do \ 78 | echo ">> Very clean in $$dir"; \ 79 | $(MAKE) -C $$dir veryclean; \ 80 | done 81 | 82 | # ---------- 帮助 ---------- 83 | help: ## Show this help 84 | @awk 'BEGIN{FS=":.*##"; printf "\nUsage: make \033[36m\033[0m [MODE=par|seq]\n\nTargets:\n"} \ 85 | /^[a-zA-Z0-9_-]+:[^#]*##/{printf " \033[36m%-10s\033[0m %s\n", $$1, $$2}' \ 86 | $(MAKEFILE_LIST) 87 | 88 | -------------------------------------------------------------------------------- /Readme_zh.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/Readme_zh.docx -------------------------------------------------------------------------------- /fastxc/Makefile: -------------------------------------------------------------------------------- 1 | SUBDIRS = src/sac2spec src/xc src/rotate src/extractSegments 2 | 3 | .PHONY: $(SUBDIRS) 4 | 5 | all: $(SUBDIRS) 6 | 7 | $(SUBDIRS): 8 | @echo "Making in directory $@" 9 | $(MAKE) -C $@ 10 | 11 | clean: 12 | for dir in $(SUBDIRS); do \ 13 | echo "Cleaning in directory $$dir"; \ 14 | $(MAKE) -C $$dir clean; \ 15 | done 16 | 17 | veryclean: 18 | for dir in $(SUBDIRS); do \ 19 | echo "Performing very clean in directory $$dir"; \ 20 | $(MAKE) -C $$dir veryclean; \ 21 | done 22 | -------------------------------------------------------------------------------- /fastxc/SeisHandler/__init__.py: -------------------------------------------------------------------------------- 1 | # Author: Wang Jingxi 2 | from .seis_array import SeisArray 3 | -------------------------------------------------------------------------------- /fastxc/SeisHandler/seis_array.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List, Optional 2 | from .pattern_utils import check_pattern 3 | from .seisfile_matcher import get_files, match_files 4 | from .seisfile_filter import filter_files 5 | from .seisfile_organizer import group_by_labels, organize_by_labels 6 | 7 | 8 | class SeisArray: 9 | """ 10 | SeisArray class is designed for organizing the noise data into a virtual array. 11 | """ 12 | 13 | def __init__(self, array_dir: str, pattern: str): 14 | self.array_dir = array_dir 15 | self.pattern = check_pattern(array_dir, pattern) 16 | self.files = None 17 | self.filtered_files = None 18 | self.pattern_filter = None 19 | self.files_group = None 20 | self.virtual_array = None 21 | 22 | def match(self, threads: int = 1): 23 | """ 24 | Matching files according to the pattern 25 | """ 26 | # Get all files in the directory 27 | file_list = get_files(self.array_dir) 28 | 29 | # Match all files with the pattern 30 | self.files = match_files(file_list, self.pattern, num_threads=threads) 31 | 32 | def filter(self, criteria: Optional[Dict[str, List]] = None, threads: int = 1): 33 | """ 34 | Apply the file filter to the directory, and store the matched files. 35 | """ 36 | 37 | if self.files is None: 38 | print("[Error] Please match the files first.") 39 | return None 40 | 41 | self.filtered_files = filter_files(self.files, criteria, num_threads=threads) 42 | 43 | def group(self, labels: list, sort_labels: list = None, filtered=True): 44 | """ 45 | re-organize the array files according to the order 46 | """ 47 | if filtered: 48 | files = self.filtered_files 49 | if files is None: 50 | print("[Error] Please filter the files first.") 51 | return None 52 | else: 53 | files = self.files 54 | if files is None: 55 | print("[Error] Please match the files first.") 56 | return None 57 | files_group = group_by_labels(files, labels, sort_labels) 58 | self.files_group = files_group.to_dict(orient='index') 59 | 60 | def organize(self, label_order: list, output_type='dict', filtered=True): 61 | """ 62 | re-organize the array files according to the order 63 | """ 64 | if filtered: 65 | files = self.filtered_files 66 | if files is None: 67 | print("[Error] Please filter the files first.") 68 | return None 69 | else: 70 | files = self.files 71 | if files is None: 72 | print("[Error] Please match the files first.") 73 | return None 74 | if output_type not in ['path', 'dict']: 75 | print("[Error] flag should be 'path' or 'dict'.") 76 | output_type = 'dict' 77 | self.virtual_array = organize_by_labels(files, label_order, output_type) 78 | -------------------------------------------------------------------------------- /fastxc/SeisHandler/seisfile_organizer.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | import pandas as pd 3 | 4 | 5 | def group_by_labels(matched_files, labels, sort_labels): 6 | """ 7 | Organize the matched files into a multi-level dictionary according to the order. 8 | 9 | matched_files: a list of file paths, every file is a dictionary contains fields and path 10 | """ 11 | if not matched_files: 12 | raise ValueError("No files matched. Matching First!.") 13 | 14 | df = pd.DataFrame(matched_files) 15 | 16 | # Check if all the keys in order are in fields of file_info 17 | if not all(field in df.columns for field in labels): 18 | raise ValueError("The provided order has fields not present in the file_info") 19 | 20 | # Check if all the keys in sort_labels are in fields of file_info 21 | if sort_labels is not None: 22 | if not all(field in df.columns for field in sort_labels): 23 | raise ValueError("The provided sort_labels has fields not present in the file_info") 24 | 25 | # Check if sort_labels and labels are conflict 26 | if not set(sort_labels).isdisjoint(set(labels)): 27 | raise ValueError("The provided sort_labels and labels should not intersect") 28 | 29 | df_grouped = df.groupby(labels).agg(list) 30 | 31 | if sort_labels is not None: 32 | df_grouped = df_grouped.sort_values(by=sort_labels) 33 | 34 | return df_grouped 35 | 36 | 37 | def recursive_defaultdict(): 38 | return defaultdict(recursive_defaultdict) 39 | 40 | 41 | def add_path(multi_dict, keys, value): 42 | for key in keys[:-1]: 43 | multi_dict = multi_dict[key] 44 | # add the value into the last level of the dictionary 45 | if not multi_dict[keys[-1]]: 46 | multi_dict[keys[-1]] = [] 47 | multi_dict[keys[-1]].append(value) 48 | 49 | 50 | def organize_by_labels(matched_files, order, information_type): 51 | if not matched_files: 52 | raise ValueError("No files matched. Matching First!.") 53 | if information_type not in ['path', 'dict']: 54 | raise ValueError("The information_type should be 'path' or 'dict'") 55 | df = pd.DataFrame(matched_files) 56 | multi_dict = recursive_defaultdict() 57 | for _, row in df.iterrows(): 58 | keys = [row[field] for field in order] 59 | if information_type == 'path': 60 | add_path(multi_dict, keys, row['path']) 61 | elif information_type == 'dict': 62 | add_path(multi_dict, keys, row.to_dict()) 63 | return multi_dict 64 | -------------------------------------------------------------------------------- /fastxc/__init__.py: -------------------------------------------------------------------------------- 1 | from .fastxc import FastXC 2 | 3 | __all__ = ['FastXC'] -------------------------------------------------------------------------------- /fastxc/bin/RotateNCF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/fastxc/bin/RotateNCF -------------------------------------------------------------------------------- /fastxc/bin/extractSegments: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/fastxc/bin/extractSegments -------------------------------------------------------------------------------- /fastxc/bin/sac2spec: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/fastxc/bin/sac2spec -------------------------------------------------------------------------------- /fastxc/bin/xc_new: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/fastxc/bin/xc_new -------------------------------------------------------------------------------- /fastxc/cmd_StackRotate_utils.py: -------------------------------------------------------------------------------- 1 | from typing import List, Dict 2 | import os 3 | 4 | 5 | def gen_linear_stack_cmd(command_dict: Dict, xc_param: Dict) -> List[str]: 6 | """ 7 | Generate commands for stack 8 | """ 9 | cmd_list = [] 10 | output_dir = xc_param["output_dir"] 11 | command = command_dict["stack"] 12 | 13 | stack_list_dir = os.path.join(output_dir, "stack_list") 14 | stack_dir = os.path.join(output_dir, "stack", "linear") 15 | cmd_list_dir = os.path.join(output_dir, "cmd_list") 16 | 17 | stack_lists = [ 18 | os.path.join(stack_list_dir, fname) for fname in os.listdir(stack_list_dir) 19 | ] 20 | 21 | os.makedirs(stack_dir, exist_ok=True) 22 | 23 | for stack_list in stack_lists: 24 | stack_list_name = os.path.basename(stack_list) 25 | info = stack_list_name.split(".") 26 | output_fname = f"{info[0]}.{info[1]}.ncf.sac" 27 | output_path = os.path.join(stack_dir, info[0], output_fname) 28 | 29 | cmd = f"{command} -I {stack_list} -O {output_path} " 30 | 31 | cmd_list.append(cmd) 32 | 33 | os.makedirs(cmd_list_dir, exist_ok=True) 34 | cmd_list_path = os.path.join(cmd_list_dir, "stack_cmds.txt") 35 | with open(cmd_list_path, "w") as f: 36 | f.write("\n".join(cmd_list)) 37 | return cmd_list 38 | 39 | 40 | def gen_stack_cmd(command_dict: Dict, xc_param: Dict) -> List[str]: 41 | save_flag = xc_param["save_flag"] 42 | save_linear = bool(int(save_flag[0])) 43 | save_pws = bool(int(save_flag[1])) 44 | save_tfpws = bool(int(save_flag[2])) 45 | save_segments = bool(int(save_flag[3])) 46 | if save_linear: 47 | gen_linear_stack_cmd(command_dict, xc_param) 48 | if save_pws: 49 | pass 50 | if save_tfpws: 51 | pass 52 | if save_segments: 53 | pass 54 | 55 | 56 | # generate terminal rotate cmd 57 | def gen_rotate_cmd(command_dict: Dict, xc_param: Dict) -> List[str]: 58 | cmd_list = [] 59 | output_dir = xc_param["output_dir"] 60 | rotate_list_dir = os.path.join(output_dir, "rotate_list") 61 | cmd_list_dir = os.path.join(output_dir, "cmd_list") 62 | command = command_dict["rotate"] 63 | 64 | for rotate_list in os.listdir(rotate_list_dir): 65 | # Get first key in the enz_group dictionary 66 | target_dir = os.path.join(rotate_list_dir, rotate_list) 67 | inlist = os.path.join(target_dir, "enz_list.txt") 68 | outlist = os.path.join(target_dir, "rtz_list.txt") 69 | cmd = f"{command} -I {inlist} -O {outlist}" 70 | cmd_list.append(cmd) 71 | 72 | os.makedirs(cmd_list_dir, exist_ok=True) 73 | with open(os.path.join(cmd_list_dir, "rotate_cmds.txt"), "w") as f: 74 | f.write("\n".join(cmd_list)) 75 | 76 | return cmd_list 77 | -------------------------------------------------------------------------------- /fastxc/cmd_sac2spec_utils.py: -------------------------------------------------------------------------------- 1 | from typing import List, Dict 2 | import os 3 | import glob 4 | 5 | 6 | # find min and max value in a string like '0.1/0.5 0.5/1.0 1.0/2.0' 7 | def find_min_max_in_string(s): 8 | elements = s.split() 9 | 10 | numbers = [] 11 | for element in elements: 12 | numbers.extend(map(float, element.split("/"))) 13 | 14 | min_value = min(numbers) 15 | max_value = max(numbers) 16 | 17 | return f"{min_value}/{max_value}" 18 | 19 | 20 | # generate sac2spec terminal cmd 21 | def gen_sac2spec_cmd( 22 | SeisArrayInfo: Dict, command_dict: Dict, xc_param: Dict, gpu_info: Dict 23 | ) -> List[str]: 24 | """ 25 | Generate sac 2 spec commands for both 1 and 3 components 26 | """ 27 | win_len = xc_param["win_len"] 28 | whiten_types = {"OFF": 0, "BEFORE": 1, "AFTER": 2, "BOTH": 3} 29 | cuda_whiten = xc_param["whiten"] 30 | cuda_whiten = whiten_types.get(cuda_whiten, 2) 31 | normalize_types = {"OFF": 0, "RUN-ABS-MF": 1, "ONE-BIT": 2, "RUN-ABS": 3} 32 | cuda_normalize = xc_param["normalize"] 33 | cuda_normalize = normalize_types.get(cuda_normalize, 1) 34 | band_info = xc_param["bands"] 35 | whiten_band = find_min_max_in_string(band_info) 36 | skip_step = xc_param["skip_step"] 37 | 38 | # iterate over the gpu_dir in the work_dir 39 | output_dir = xc_param["output_dir"] 40 | sac_spec_list_dir = os.path.join(output_dir, "sac_spec_list") 41 | 42 | # the filter file is in the output_dir 43 | filter_file = os.path.join(output_dir, "butterworth_filter.txt") 44 | 45 | comopnent_num = len(SeisArrayInfo["component_list_1"]) 46 | 47 | # get the number of gpu used 48 | gpu_num = len(gpu_info["gpu_list"]) 49 | cpu_count = int(xc_param["cpu_count"] / gpu_num) 50 | 51 | param_set = [ 52 | "-L", 53 | str(win_len), 54 | "-W", 55 | str(cuda_whiten), 56 | "-N", 57 | str(cuda_normalize), 58 | "-F", 59 | whiten_band, 60 | "-Q", 61 | str(skip_step), 62 | "-B", 63 | filter_file, 64 | "-U", 65 | str(gpu_num), 66 | "-T", 67 | str(cpu_count), 68 | ] 69 | 70 | cmd_list = [] 71 | # iterate over the gpu_dir in the work_dir, each gpu_dir contains sac and spec lists 72 | sac_lists = glob.glob(os.path.join(sac_spec_list_dir, "sac_list_*.txt")) 73 | gpu_num = len(sac_lists) 74 | cpu_count = int(xc_param["cpu_count"] / gpu_num) 75 | for sac_list in sac_lists: 76 | info = os.path.basename(sac_list).split(".")[0] 77 | gpu_id = info.split("_")[-1] 78 | spec_list = os.path.join(sac_spec_list_dir, f"spec_list_{gpu_id}.txt") 79 | local_param_set = [command_dict["sac2spec"], "-I", sac_list, "-O", spec_list] 80 | local_param_set += ["-C", str(comopnent_num)] 81 | local_param_set += ["-G", str(gpu_id)] 82 | local_param_set += param_set 83 | cmd = " ".join(local_param_set) 84 | cmd_list.append(cmd) 85 | 86 | cmd_list_dir = os.path.join(output_dir, "cmd_list") 87 | os.makedirs(cmd_list_dir, exist_ok=True) 88 | cmd_file = os.path.join(cmd_list_dir, "sac2spec_cmds.txt") 89 | with open(cmd_file, "w") as f: 90 | f.write("\n".join(cmd_list)) 91 | return cmd_list 92 | -------------------------------------------------------------------------------- /fastxc/design_filter.py: -------------------------------------------------------------------------------- 1 | import os 2 | from typing import Dict 3 | from scipy.signal import butter 4 | 5 | 6 | def design_filter(xc_param: Dict): 7 | """ 8 | Design filter for fastxc, save the filter coefficients to file. 9 | 10 | Parameters 11 | ---------- 12 | xc_param : dict, including frequency bands, e.g. {'bands': '0.1/0.5 0.5/1.0 1.0/2.0'} 13 | : dict, including output_dir, e.g. {'output_dir': 'output'} 14 | 15 | Returns 16 | ------- 17 | None 18 | """ 19 | 20 | # Parsing parameters 21 | bands = xc_param['bands'] # frequency bands 22 | output_dir = xc_param['output_dir'] # output directory 23 | fs = 1.0 / xc_param['delta'] # sampling frequency 24 | f_nyq = fs / 2.0 # Nyquist frequency 25 | order = 2 # filter order 26 | 27 | # check output_dir 28 | os.makedirs(output_dir, exist_ok=True) 29 | output_file = os.path.join(output_dir, 'butterworth_filter.txt') 30 | bands_str = bands.split() 31 | 32 | all_freqs = [] 33 | for band_str in bands_str: 34 | freq_low, freq_high = map(float, band_str.split('/')) 35 | all_freqs.append((freq_low, freq_high)) 36 | 37 | # Get the overall min and max frequencies 38 | overall_min = min(freq[0] for freq in all_freqs) 39 | overall_max = max(freq[1] for freq in all_freqs) 40 | 41 | # Check if the overall band is valid 42 | if not (0 < overall_min < overall_max < f_nyq): 43 | print(f'Error: Overall frequency band {overall_min}/{overall_max} is not valid.') 44 | raise ValueError 45 | 46 | # Normalize frequencies 47 | overall_min_norm = overall_min / f_nyq 48 | overall_max_norm = overall_max / f_nyq 49 | 50 | # Design the overall bandpass filter 51 | b, a = butter(order, [overall_min_norm, overall_max_norm], btype='bandpass') 52 | 53 | # Write filters to file 54 | try: 55 | with open(output_file, 'w') as f: 56 | # Write the overall filter first 57 | f.write(f'# {overall_min}/{overall_max}\n') 58 | f.write('\t'.join(f'{b_i:.18e}' for b_i in b) + '\n') 59 | f.write('\t'.join(f'{a_i:.18e}' for a_i in a) + '\n') 60 | 61 | # Now write the individual band filters 62 | for band_str in bands_str: 63 | freq_low, freq_high = map(float, band_str.split('/')) 64 | freq_low_norm = freq_low / f_nyq 65 | freq_high_norm = freq_high / f_nyq 66 | b, a = butter(order, [freq_low_norm, freq_high_norm], btype='bandpass') 67 | 68 | line_b = '\t'.join(f'{b_i:.18e}' for b_i in b) 69 | line_a = '\t'.join(f'{a_i:.18e}' for a_i in a) 70 | 71 | f.write(f'# {band_str}\n') 72 | f.write(line_b + '\n') 73 | f.write(line_a + '\n') 74 | except IOError as e: 75 | print(f"Filter file writing error: {e}") 76 | 77 | 78 | if __name__ == "__main__": 79 | design_filter({ 80 | 'bands': '0.2/0.5 0.6/0.8', # 定义频率带 81 | 'output_dir': './', # 定义输出目录 82 | 'delta': 0.01 # 定义采样间隔 83 | }) 84 | 85 | -------------------------------------------------------------------------------- /fastxc/gen_rotate_list_dir.py: -------------------------------------------------------------------------------- 1 | from typing import Dict 2 | import os 3 | from itertools import product 4 | 5 | 6 | def gen_rotate_list_dir(SeisArrayInfo: Dict, xc_param: Dict) -> bool: 7 | 8 | flag = SeisArrayInfo["sac_dir_2"] 9 | component_list_1 = SeisArrayInfo["component_list_1"] 10 | component_list_2 = ( 11 | component_list_1 if flag == "NONE" else SeisArrayInfo["component_list_2"] 12 | ) 13 | 14 | # if len!=3 ,exit 15 | if len(component_list_1) != 3 or len(component_list_2) != 3: 16 | print("Only 3 components situation is supported in Rotate!") 17 | return False 18 | 19 | enz_dir_flag = xc_param["rotate_dir"] 20 | if enz_dir_flag == "LINEAR": 21 | stack_dir = os.path.join(xc_param["output_dir"], "stack", "linear") 22 | elif enz_dir_flag == "PWS": 23 | stack_dir = os.path.join(xc_param["output_dir"], "stack", "pws") 24 | elif enz_dir_flag == "TFPWS": 25 | stack_dir = os.path.join(xc_param["output_dir"], "stack", "tfpws") 26 | else: 27 | stack_dir = os.path.join(xc_param["output_dir"], "stack", "linear") 28 | 29 | rtz_dir = os.path.join(xc_param["output_dir"], "stack", "rtz") 30 | 31 | rotate_list_dir = os.path.join(xc_param["output_dir"], "rotate_list") 32 | 33 | mapping = {component_list_1[i]: val for i, val in enumerate(["E", "N", "Z"])} 34 | mapping.update({component_list_2[i]: val for i, val in enumerate(["E", "N", "Z"])}) 35 | 36 | component_pair_order = ["EE", "EN", "EZ", "NE", "NN", "NZ", "ZE", "ZN", "ZZ"] 37 | 38 | for sta_pair in os.listdir(stack_dir): 39 | sta_pair_path = os.path.join(stack_dir, sta_pair) 40 | enz_sac_num = len(os.listdir(sta_pair_path)) 41 | if enz_sac_num != 9: 42 | continue 43 | enz_group = {} 44 | for component_pair in product(component_list_1, component_list_2): 45 | component1, component2 = component_pair 46 | file_name = f"{sta_pair}.{component1}-{component2}.ncf.sac" 47 | file_path = os.path.join(sta_pair_path, file_name) 48 | 49 | component_pair = f"{mapping[component1]}{mapping[component2]}" 50 | enz_group.update({component_pair: file_path}) 51 | 52 | # sort the files by order of component_pair_order 53 | enz_group = {key: enz_group[key] for key in component_pair_order} 54 | 55 | rotate_dir = os.path.join(rotate_list_dir, sta_pair) 56 | os.makedirs(rotate_dir, exist_ok=True) 57 | 58 | in_list = os.path.join(rotate_dir, "enz_list.txt") 59 | out_list = os.path.join(rotate_dir, "rtz_list.txt") 60 | 61 | # Write the input stack file paths 62 | with open(in_list, "w") as f: 63 | f.write("\n".join(enz_group.values())) 64 | 65 | # Write the output RTZ file paths 66 | with open(out_list, "w") as f: 67 | for component_pair in [ 68 | "R-R", 69 | "R-T", 70 | "R-Z", 71 | "T-R", 72 | "T-T", 73 | "T-Z", 74 | "Z-R", 75 | "Z-T", 76 | "Z-Z", 77 | ]: 78 | outpath = os.path.join( 79 | rtz_dir, sta_pair, f"{sta_pair}.{component_pair}.ncf.sac" 80 | ) 81 | f.write(outpath + "\n") 82 | 83 | return True 84 | -------------------------------------------------------------------------------- /fastxc/sac2spec_pyv/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/fastxc/sac2spec_pyv/__init__.py -------------------------------------------------------------------------------- /fastxc/sac2spec_pyv/group_files.py: -------------------------------------------------------------------------------- 1 | def read_file(file_path): 2 | """读取文件内容,并将每行作为一个元素存储在列表中""" 3 | with open(file_path, "r") as file: 4 | lines = [line.strip() for line in file.readlines()] 5 | return lines 6 | 7 | 8 | def group_files(input_file, output_file, group_size): 9 | """ 10 | 根据输入和输出文件路径以及组大小,生成文件组列表。 11 | 12 | :param input_file: 输入文件路径,文件中的每一行是一个输入文件的绝对路径 13 | :param output_file: 输出文件路径,文件中的每一行是一个输出文件的绝对路径 14 | :param group_size: 每组包含的文件数 15 | :return: 文件组列表,每个文件组是一个包含输入文件列表和输出文件列表的元组 16 | """ 17 | input_files = read_file(input_file) 18 | output_files = read_file(output_file) 19 | 20 | if len(input_files) != len(output_files): 21 | raise ValueError( 22 | "The number of input files must match the number of output files." 23 | ) 24 | 25 | grouped_files = [] 26 | for i in range(0, len(input_files), group_size): 27 | input_group = input_files[i : i + group_size] 28 | output_group = output_files[i : i + group_size] 29 | grouped_files.append((input_group, output_group)) 30 | 31 | return grouped_files -------------------------------------------------------------------------------- /fastxc/sac2spec_pyv/main.py: -------------------------------------------------------------------------------- 1 | from .arguproc import parse_arguments 2 | from .group_files import group_files 3 | from .process_a_group import process_a_group 4 | from multiprocessing import Pool 5 | 6 | 7 | def process_group_wrapper(args): 8 | # 解包参数,适用于 imap_unordered 的单参数传递 9 | group_file, args_dict = args 10 | return process_a_group(group_file, args_dict) 11 | 12 | 13 | def sac2spec_pyv(command_line=None): 14 | print("\n\n[INFO]: This is a Python Version doing the Preprocessing of Data!!\n") 15 | args = parse_arguments(command_line) 16 | sac_lst = args.sac_lst 17 | spec_lst = args.spec_lst 18 | num_ch = args.num_ch 19 | thread_num = args.thread_num 20 | args_dict = vars(args) 21 | grouped_files = group_files(sac_lst, spec_lst, num_ch) 22 | # for grouped_file in grouped_files: # Sequential processing 23 | # process_a_group(grouped_file, args_dict) 24 | # 并行处理 25 | with Pool(thread_num) as pool: 26 | params = [(group_file, args_dict) for group_file in grouped_files] 27 | for param in params: 28 | pool.apply_async(process_group_wrapper, args=(param,)) 29 | 30 | pool.close() 31 | pool.join() 32 | 33 | 34 | if __name__ == "__main__": 35 | sac2spec_pyv() 36 | -------------------------------------------------------------------------------- /fastxc/sac2spec_pyv/run_abs_multi.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import scipy.signal as signal 3 | import copy 4 | import pdb 5 | 6 | 7 | def multi_freq_run_abs(streams, freq_groups): 8 | sample_rate = 1 / streams[0][0].stats.delta 9 | processed_streams = copy.deepcopy(streams) 10 | accumulated_filtered_datas = [np.zeros(len(stream[0].data)) for stream in streams] 11 | for freq in freq_groups: 12 | low_f, high_f = freq 13 | b, a = signal.butter(2, [low_f, high_f], btype="band", fs=sample_rate) 14 | 15 | filtered_datas = [] 16 | 17 | # 重置每个频段的平滑幅度数组和窗口大小 18 | smooth_amp = np.zeros(len(streams[0][0].data)) 19 | winsize = round((1 / low_f) * 2 * sample_rate) 20 | if winsize % 2 == 0: 21 | winsize += 1 22 | window = np.ones(winsize) / winsize 23 | 24 | for stream in streams: 25 | data = stream[0].data 26 | filtered_data = signal.filtfilt(b, a, data) 27 | filtered_datas.append(filtered_data) 28 | 29 | padded_data = np.pad( 30 | np.abs(filtered_data), pad_width=(winsize, winsize), mode="edge" 31 | ) 32 | 33 | filtered_smooth_amp = signal.lfilter(window, [1], padded_data) 34 | correct_length_smooth_amp = filtered_smooth_amp[winsize:-winsize] 35 | smooth_amp += correct_length_smooth_amp 36 | 37 | valid_indices = smooth_amp > 1e-10 38 | for filtered_data in filtered_datas: 39 | filtered_data[valid_indices] /= smooth_amp[valid_indices] 40 | 41 | # 累加归一化后的数据 42 | for i in range(len(accumulated_filtered_datas)): 43 | accumulated_filtered_datas[i] += filtered_datas[i] 44 | 45 | # 将累加归一化后的数据存回processed_streams中对应的stream 46 | for i, stream in enumerate(processed_streams): 47 | stream[0].data = accumulated_filtered_datas[i] 48 | 49 | return processed_streams 50 | -------------------------------------------------------------------------------- /fastxc/sac2spec_pyv/spectrum_whiten.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import scipy.signal as signal 3 | from scipy.signal import butter, filtfilt 4 | from scipy.fft import rfft, irfft 5 | import copy 6 | from scipy.signal.windows import hann 7 | import matplotlib.pyplot as plt # 导入绘图库 8 | import pdb 9 | 10 | 11 | def freq_whiten(streams, freq_low, freq_high): 12 | sampling_rate = 1 / streams[0][0].stats.delta 13 | processed_streams = copy.deepcopy(streams) 14 | fft_length = len(streams[0][0].data) 15 | delta_f = sampling_rate / fft_length 16 | 17 | freqs = np.fft.rfftfreq(len(streams[0][0].data), d=streams[0][0].stats.delta) 18 | 19 | # 计算特定白化频率的索引范围 20 | freq_low = max(freq_low, 0) 21 | freq_high = max(freq_high, 0) 22 | freq_low_limit = 0.75 * freq_low 23 | freq_high_limit = 1.5 * freq_high 24 | 25 | freq_low_limit = max(freq_low_limit, 0) 26 | freq_high_limit = min(freq_high_limit, sampling_rate / 2 - delta_f) 27 | 28 | # 拐角频率对应的指标 29 | idx_low = np.searchsorted(freqs, freq_low, side="left") 30 | idx_high = np.searchsorted(freqs, freq_high, side="right") 31 | 32 | # 截止频率对应的指标 33 | idx_low_limit = np.searchsorted(freqs, freq_low_limit, side="left") 34 | idx_high_limit = np.searchsorted(freqs, freq_high_limit, side="right") 35 | 36 | # 白化的指标范围 37 | nn = slice(idx_low_limit, idx_high_limit + 1) 38 | 39 | winsize = max(int(0.02 / delta_f), 11) 40 | if winsize % 2 == 0: 41 | winsize += 1 # 确保窗口大小为奇数 42 | 43 | window = np.ones(winsize) / winsize 44 | accumulated_smoothed_amp = np.zeros( 45 | idx_high_limit + 1 - idx_low_limit 46 | ) # Adjusted size 47 | b, a = butter( 48 | 4, [freq_low, freq_high], btype="bandpass", fs=1 / streams[0][0].stats.delta 49 | ) 50 | 51 | spectrums = [] 52 | for stream in streams: 53 | data = stream[0].data 54 | data = filtfilt(b, a, data) 55 | spectrum = rfft(data) 56 | spectrums.append(spectrum) 57 | 58 | spectrum_amp = np.abs(spectrum[nn]) 59 | padded_spectrum_amp = np.pad( 60 | spectrum_amp, pad_width=(winsize, winsize), mode="edge" 61 | ) 62 | data_f_amp_smooth = signal.lfilter(window, [1], padded_spectrum_amp) 63 | data_f_amp_smooth = data_f_amp_smooth[winsize:-winsize] 64 | accumulated_smoothed_amp += data_f_amp_smooth 65 | 66 | # 使用累加的平滑幅度进行谱白化处理 67 | for spectrum in spectrums: 68 | valid_indices_in_weight = np.where(accumulated_smoothed_amp > 1e-7)[0] 69 | valid_indices = np.where(accumulated_smoothed_amp > 1e-7)[0] + idx_low_limit 70 | spectrum[valid_indices] /= accumulated_smoothed_amp[valid_indices_in_weight] 71 | 72 | # bandpass filtering 73 | spectrum[: idx_low_limit + 1] = 0 74 | spectrum[idx_high_limit:] = 0 75 | low_transition_npts = idx_low - idx_low_limit 76 | if low_transition_npts >= 4: 77 | taperwin_low = hann(2 * low_transition_npts) 78 | spectrum[idx_low_limit:idx_low] *= taperwin_low[:low_transition_npts] 79 | 80 | high_transition_npts = idx_high_limit - idx_high + 1 81 | if high_transition_npts >= 4: 82 | taperwin_high = hann(2 * high_transition_npts) # 创建一个足够长的汉宁窗 83 | spectrum[idx_high : idx_high_limit + 1] *= taperwin_high[ 84 | high_transition_npts: 85 | ] 86 | 87 | for i, stream in enumerate(processed_streams): 88 | # 转换回时间域并存储处理后的数据 89 | stream[0].data = irfft(spectrums[i]) 90 | 91 | return processed_streams 92 | -------------------------------------------------------------------------------- /fastxc/sac2spec_pyv/write_spectrum.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | import struct 4 | 5 | 6 | def write_output_spectrum(total_output, segspec_hd, output_group): 7 | # 先初始化一个列表,用于存储每个输出文件对应的所有数据拼接结果 8 | concatenated_data = [np.array([], dtype=np.complex64) for _ in output_group] 9 | 10 | # 遍历每组时间片切割后的数据 11 | for sliced_spectrum_groups in total_output: 12 | # 遍历每个输出文件对应的数据组 13 | for idx, data in enumerate(sliced_spectrum_groups): 14 | concatenated_data[idx] = np.concatenate( 15 | [concatenated_data[idx], np.array(data, dtype=np.complex64)] 16 | ) 17 | 18 | # 开始写入到各个文件 19 | for idx, spec_data in enumerate(concatenated_data): 20 | specpath = output_group[idx] 21 | # print(f"Writing to {specpath}") 22 | parent_dir = os.path.dirname(specpath) 23 | os.makedirs(parent_dir, exist_ok=True) 24 | with open(specpath, "wb") as fid: 25 | # 创建并写入SEGSPEC头信息 26 | header_format = "ffiiff" # 对应于4个floats和2个ints的结构 27 | header_data = struct.pack( 28 | header_format, 29 | segspec_hd["stla"], 30 | segspec_hd["stlo"], 31 | segspec_hd["nstep"], 32 | segspec_hd["nspec"], 33 | segspec_hd["df"], 34 | segspec_hd["dt"], 35 | ) 36 | fid.write(header_data) 37 | fid.write(spec_data.tobytes()) # 写入二进制数据 38 | -------------------------------------------------------------------------------- /log/madiliang_file.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/log/madiliang_file.txt -------------------------------------------------------------------------------- /run.py: -------------------------------------------------------------------------------- 1 | from fastxc.fastxc import FastXC 2 | 3 | ini_file = "./config/test.ini" 4 | 5 | job = FastXC(ini_file) 6 | 7 | # generate filter 8 | job.generate_filter() 9 | 10 | # sac2spec 11 | job.generate_sac2spec_list_dir() 12 | 13 | job.generate_sac2spec_cmd() 14 | 15 | job.deploy_sac2spec_cmd() 16 | 17 | # xc 18 | job.generate_xc_list_dir() 19 | 20 | job.generate_xc_cmd() 21 | 22 | job.deploy_xc_cmd() 23 | 24 | # stack 25 | job.generate_stack_list_dir() 26 | 27 | job.generate_stack_cmd() 28 | 29 | job.deploy_stack_cmd() 30 | 31 | # rotate 32 | if job.generate_rotate_list_dir(): 33 | job.generate_rotate_cmd() 34 | job.deploy_rotate_cmd() 35 | 36 | # sac2dat 37 | job.deploy_sac2dat() 38 | -------------------------------------------------------------------------------- /src/extractSegments/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "arguproc.h": "c", 4 | "typeinfo": "c" 5 | } 6 | } -------------------------------------------------------------------------------- /src/extractSegments/Makefile: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------- 2 | # extractSegments ‒ 子目录 Makefile 3 | # · 顶层递归调用 → Release (-O3) 4 | # · 手动进目录 make → Debug (-O0 -g) 5 | # ---------------------------------------------------- 6 | 7 | # 编译器 8 | CC ?= gcc 9 | WARN ?= -Wall # 通用警告 10 | 11 | # ---------- 优化级别自动切换 ---------- 12 | ifeq ($(MAKELEVEL),0) # 手动调试 13 | CFLAGS ?= -O0 -g $(WARN) 14 | else # 顶层批量构建 15 | CFLAGS ?= -O3 $(WARN) 16 | endif 17 | # ------------------------------------- 18 | 19 | # 链接库(目前只需要 libm,如有其他库再追加) 20 | LDFLAGS ?= -lm 21 | 22 | # 源文件 / 目标文件 23 | OBJS = main.o arguproc.o sacio.o 24 | 25 | # 输出可执行文件 26 | BINDIR := ../../bin 27 | PROG := $(BINDIR)/extractSegments 28 | 29 | # 伪目标 30 | .PHONY: all clean veryclean 31 | 32 | # 默认目标 33 | all: $(BINDIR) $(PROG) 34 | 35 | # 创建输出目录 36 | $(BINDIR): 37 | @mkdir -p $@ 38 | 39 | # 链接 40 | $(PROG): $(OBJS) 41 | $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) 42 | 43 | # C 源编译 44 | %.o: %.c 45 | $(CC) $(CFLAGS) -c $< -o $@ 46 | 47 | # 清理 48 | clean: 49 | @rm -f *.o 50 | 51 | veryclean: clean 52 | @rm -f $(PROG) 53 | -------------------------------------------------------------------------------- /src/extractSegments/arguproc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "arguproc.h" 8 | 9 | int getopt(); 10 | extern char *optarg; 11 | extern int optind; 12 | 13 | void parse_arguments(int argc, char *argv[], CommandLineOptions *opts) 14 | { 15 | int lag; 16 | while ((lag = getopt(argc, argv, "I:O:")) != -1) 17 | { 18 | switch (lag) 19 | { 20 | case 'I': 21 | strcpy(opts->infn, optarg); 22 | break; 23 | case 'O': 24 | strcpy(opts->outdir, optarg); 25 | break; 26 | default: 27 | fprintf(stderr, "Unsupported option\n"); 28 | exit(1); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/extractSegments/arguproc.h: -------------------------------------------------------------------------------- 1 | #ifndef _ARGUPROC_H 2 | #define _ARGUPROC_H 3 | #include 4 | #define USAGE "[[-I:input file] [-O:output directory] [-W: the exponential term of the weight]" 5 | 6 | typedef struct CommandLineOptions 7 | { 8 | char infn[256]; // 假设输入文件名不会超过255字符 9 | char outdir[512]; // 输出目录同样限制为255字符 10 | } CommandLineOptions; 11 | 12 | void parse_arguments(int argc, char *argv[], CommandLineOptions *opts); 13 | #endif 14 | -------------------------------------------------------------------------------- /src/extractSegments/do.sh: -------------------------------------------------------------------------------- 1 | ./extractSegments -I /mnt/c/Users/admin/Desktop/FastXC_raw/output/ncf/segments/AAKH-ABNH/AAKH-ABNH.U-U.sac_segment -O ./test 2 | -------------------------------------------------------------------------------- /src/rotate/.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Linux", 5 | "includePath": [ 6 | "${workspaceFolder}/**" 7 | ], 8 | "defines": [], 9 | "compilerPath": "/usr/bin/gcc", 10 | "cStandard": "c17", 11 | "cppStandard": "gnu++17", 12 | "intelliSenseMode": "linux-gcc-x64" 13 | } 14 | ], 15 | "version": 4 16 | } -------------------------------------------------------------------------------- /src/rotate/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.c": "c", 4 | "arguproc.h": "c", 5 | "usage.h": "c" 6 | } 7 | } -------------------------------------------------------------------------------- /src/rotate/Makefile: -------------------------------------------------------------------------------- 1 | # ------------------------------------------- 2 | # RotateNCF ‒ 子目录 Makefile(纯手写依赖) 3 | # ------------------------------------------- 4 | 5 | # 编译器 6 | CC ?= gcc 7 | WARN ?= -Wall 8 | 9 | # --- 优化级别自动切换 --- 10 | ifeq ($(MAKELEVEL),0) # 手动调试 11 | OPTFLAGS := -O0 -g 12 | else # 顶层批量构建 13 | OPTFLAGS := -O3 14 | endif 15 | 16 | CFLAGS ?= $(OPTFLAGS) $(WARN) 17 | # ------------------------ 18 | 19 | # 源文件和目标文件 20 | SRCS := main.c arguproc.c sacio.c hddistance.c rotate.c 21 | OBJS := $(SRCS:.c=.o) 22 | 23 | # 输出目录 / 可执行文件 24 | BINDIR := ../../bin 25 | PROG := $(BINDIR)/RotateNCF 26 | 27 | # 伪目标 28 | .PHONY: all clean veryclean 29 | 30 | # 默认目标 31 | all: $(BINDIR) $(PROG) 32 | 33 | # 创建输出目录 34 | $(BINDIR): 35 | @mkdir -p $@ 36 | 37 | # 链接 38 | $(PROG): $(OBJS) 39 | $(CC) $(CFLAGS) -o $@ $^ -lm 40 | 41 | # 通用编译规则 42 | %.o: %.c 43 | $(CC) $(CFLAGS) -c $< -o $@ 44 | 45 | # ------------------------------------------- 46 | # 手写依赖区(按需增删,别省略) 47 | # ------------------------------------------- 48 | main.o: main.c sac.h arguproc.h 49 | arguproc.o: arguproc.c sac.h arguproc.h 50 | sacio.o: sacio.c sac.h 51 | hddistance.o: hddistance.c sac.h hddistance.h 52 | rotate.o: rotate.c sac.h arguproc.h hddistance.h 53 | # ------------------------------------------- 54 | 55 | # 清理 56 | clean: 57 | @rm -f *.o 58 | veryclean: clean 59 | @rm -f $(PROG) 60 | -------------------------------------------------------------------------------- /src/rotate/arguproc.h: -------------------------------------------------------------------------------- 1 | #ifndef _ARGUPROC_H_ 2 | #define _ARGUPROC_H_ 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | typedef struct ARGUTYPE 9 | { 10 | /* data */ 11 | char *ee_in; 12 | char *en_in; 13 | char *ez_in; 14 | char *ne_in; 15 | char *nn_in; 16 | char *nz_in; 17 | char *ze_in; 18 | char *zn_in; 19 | char *zz_in; 20 | char *rr_out; 21 | char *rt_out; 22 | char *rz_out; 23 | char *tr_out; 24 | char *tt_out; 25 | char *tz_out; 26 | char *zr_out; 27 | char *zt_out; 28 | char *zz_out; 29 | } ARGUTYPE; 30 | char* my_strdup(const char* s); 31 | void Argumentprocess(int argc, char **argv, ARGUTYPE *parg); 32 | void usage(); 33 | #endif -------------------------------------------------------------------------------- /src/rotate/hddistance.h: -------------------------------------------------------------------------------- 1 | #ifndef _HDDISTANCE_H_ 2 | #define _HDDISTANCE_H_ 3 | #ifndef M_PI 4 | #define M_PI 3.1415926535897932 5 | #endif 6 | extern void hd_distaz(float evlo, float evla, float stlo, float stla, 7 | float *gcarc, float *az, float *baz, float *distkm); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /src/rotate/rotate.c: -------------------------------------------------------------------------------- 1 | #include "rotate.h" 2 | 3 | void generate_rotate_matrix(double azi, double baz, double **matrix) 4 | { 5 | // Calculate sin and cos values to avoid repeat calculation 6 | float sin_azi = sinf(azi); 7 | float cos_azi = cosf(azi); 8 | float sin_baz = sinf(baz); 9 | float cos_baz = cosf(baz); 10 | 11 | // Initialize matrix with zeros 12 | int i, j; 13 | for (i = 0; i < 9; i++) 14 | { 15 | for (j = 0; j < 9; j++) 16 | { 17 | matrix[i][j] = 0.0; 18 | } 19 | } 20 | 21 | // Fill in the matrix 22 | matrix[0][0] = -sin_azi * sin_baz; // *EE_DATA 23 | matrix[0][1] = -sin_azi * cos_baz; // *EN_DATA 24 | matrix[0][3] = -cos_azi * sin_baz; // *NE_DATA 25 | matrix[0][4] = -cos_azi * cos_baz; // *NN_DATA 26 | 27 | matrix[1][0] = -sin_azi * cos_baz; // *EE_DATA 28 | matrix[1][1] = sin_azi * sin_baz; // *EN_DATA 29 | matrix[1][3] = -cos_azi * cos_baz; // *NE_DATA 30 | matrix[1][4] = cos_azi * sin_baz; // *NN_DATA 31 | 32 | matrix[2][2] = sin_azi; // *EZ_DATA 33 | matrix[2][5] = cos_azi; // *NZ_DATA 34 | 35 | matrix[3][0] = -cos_azi * sin_baz; // *EE_DATA 36 | matrix[3][1] = -cos_azi * cos_baz; // *EN_DATA 37 | matrix[3][3] = sin_azi * sin_baz; // *NE_DATA 38 | matrix[3][4] = sin_azi * cos_baz; // *NN_DATA 39 | 40 | matrix[4][0] = -cos_azi * cos_baz; // *EE_DATA 41 | matrix[4][1] = cos_azi * sin_baz; // *EN_DATA 42 | matrix[4][3] = sin_azi * cos_baz; // *NE_DATA 43 | matrix[4][4] = -sin_azi * sin_baz; // *NN_DATA 44 | 45 | matrix[5][2] = cos_azi; // *EZ_DATA 46 | matrix[5][5] = -sin_azi; // *NZ_DATA 47 | 48 | matrix[6][6] = -sin_baz; // *ZE_DATA 49 | matrix[6][7] = -cos_baz; // *ZN_DATA 50 | 51 | matrix[7][6] = -cos_baz; // *ZE_DATA 52 | matrix[7][7] = sin_baz; // *ZN_DATA 53 | 54 | matrix[8][8] = 1; // *ZZ_DATA 55 | } 56 | 57 | void rotate(float **rtz_data, float **enz_data, double **rotate_matrix, int npts) 58 | { 59 | int i, j, k; 60 | // Initialize rtz_data with zeros 61 | for (i = 0; i < 9; i++) 62 | { 63 | for (j = 0; j < npts; j++) 64 | { 65 | rtz_data[i][j] = 0.0; 66 | } 67 | } 68 | 69 | // Perform the rotation for each component 70 | for (k = 0; k < npts; k++) // loop for time 71 | { 72 | for (i = 0; i < 9; i++) // loop for output rtz_data 73 | { 74 | 75 | for (j = 0; j < 9; j++) // loop for input enz_data 76 | { 77 | rtz_data[i][k] += enz_data[j][k] * rotate_matrix[i][j]; 78 | } 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /src/rotate/rotate.h: -------------------------------------------------------------------------------- 1 | #ifndef _ROTATE_WRITE_H_ 2 | #define _ROTATE_WRITE_H_ 3 | 4 | #include 5 | #include 6 | #include "sac.h" 7 | 8 | void generate_rotate_matrix(double azi, double baz, double **matrix); 9 | 10 | void rotate(float **rtz_data, float **enz_data, double **rotate_matrix, int npts); 11 | 12 | #endif -------------------------------------------------------------------------------- /src/sac2spec/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.c": "c", 4 | "arguproc.h": "c", 5 | "in_out_node_c9.h": "c", 6 | "complex": "cpp" 7 | } 8 | } -------------------------------------------------------------------------------- /src/sac2spec/Makefile: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------- 2 | # sac2spec ‒ 子目录 Makefile(Release / Debug 自动切换) 3 | # ---------------------------------------------------- 4 | 5 | # 编译器 6 | CC ?= gcc 7 | NVCC ?= /usr/local/cuda/bin/nvcc 8 | ARCH ?= sm_89 9 | WARN ?= -Wall # 通用警告 10 | 11 | # -------- 优化级别自动切换 -------- 12 | ifeq ($(MAKELEVEL),0) # 手动调试 13 | CFLAGS ?= -O0 -g $(WARN) 14 | NVCCFLAGS ?= -g -G -lineinfo -arch=$(ARCH) 15 | else # 顶层批量构建 16 | CFLAGS ?= -O3 $(WARN) 17 | NVCCFLAGS ?= -O3 --generate-line-info -arch=$(ARCH) 18 | endif 19 | # --------------------------------- 20 | 21 | # 链接库 22 | LFLAG = -L/usr/local/cuda/lib64 -lcufft -lcudart -lm 23 | 24 | # 源文件 25 | CUDAOBJS = cuda.rdcrtr.o \ 26 | cuda.util.o \ 27 | cuda.misc.o \ 28 | cuda.processing.o \ 29 | cuda.taper.o \ 30 | cuda.main.o 31 | 32 | OBJS = design_filter_response.o \ 33 | arguproc.o \ 34 | cal_nseg.o \ 35 | par_rw_data.o \ 36 | read_filelist.o \ 37 | sacio.o \ 38 | util.o 39 | 40 | # 目标可执行文件 41 | BINDIR := ../../bin 42 | PROG := $(BINDIR)/sac2spec 43 | 44 | # 伪目标 45 | .PHONY: all clean veryclean 46 | 47 | # 默认目标 48 | all: $(BINDIR) $(PROG) 49 | 50 | # 创建输出目录 51 | $(BINDIR): 52 | @mkdir -p $@ 53 | 54 | # 链接 55 | $(PROG): $(OBJS) $(CUDAOBJS) 56 | $(NVCC) $(NVCCFLAGS) -o $@ $^ $(LFLAG) 57 | 58 | # C 源编译 59 | %.o: %.c 60 | $(CC) $(CFLAGS) -c $< -o $@ 61 | 62 | # CUDA 源编译 63 | %.o: %.cu 64 | $(NVCC) $(NVCCFLAGS) -c $< -o $@ 65 | 66 | # 清理 67 | clean: 68 | @rm -f *.o 69 | 70 | veryclean: clean 71 | @rm -f $(PROG) 72 | -------------------------------------------------------------------------------- /src/sac2spec/arguproc.h: -------------------------------------------------------------------------------- 1 | #ifndef _ARGU_PROC_H 2 | #define _ARGU_PROC_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "config.h" 9 | 10 | typedef struct ARGUTYPE 11 | { 12 | char *sac_lst; 13 | char *spec_lst; 14 | char *filter_file; 15 | float seglen; 16 | float freq_low; 17 | float freq_high; 18 | int num_ch; 19 | int gpu_id; 20 | int whitenType; 21 | int normalizeType; 22 | int skip_steps[MAX_SKIP_STEPS_SIZE]; 23 | int skip_step_count; 24 | int thread_num; 25 | int gpu_num; 26 | } ARGUTYPE; 27 | 28 | /* Parsing the input argument */ 29 | void ArgumentProcess(int argc, char **argv, ARGUTYPE *pargument); 30 | void usage(); 31 | #endif -------------------------------------------------------------------------------- /src/sac2spec/cal_nseg.h: -------------------------------------------------------------------------------- 1 | #ifndef _CAL_NSEG_H_ 2 | #define _CAL_NSEG_H_ 3 | #include 4 | #include 5 | 6 | // Find the number of segment using npts and seglen, delta 7 | int cal_nseg(int seglen, int npts, float delta); 8 | 9 | #endif -------------------------------------------------------------------------------- /src/sac2spec/complex.h: -------------------------------------------------------------------------------- 1 | #ifndef COMPLEX_H 2 | #define COMPLEX_H 3 | 4 | typedef struct 5 | { 6 | float x; 7 | float y; 8 | } complex; 9 | 10 | #endif -------------------------------------------------------------------------------- /src/sac2spec/config.h: -------------------------------------------------------------------------------- 1 | #ifndef _config_h 2 | #define _config_h 3 | 4 | #define MAXLINE 8192 5 | #define MAXPATH 8192 6 | #define MAXKSTNM 2048 7 | #define MAXNAME 255 8 | #define MAXBAND 100 9 | #define MAX_SKIP_STEPS_SIZE 100 10 | #define _RISTRICT_MAX_GPU_BATCH 9999999 11 | #define _RISTRICT_MAX_CPU_BATCH 9999999 12 | #define MAXVAL 20 13 | #define MINVAL 1e-30 14 | #define TAPER_RATIO 3 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/sac2spec/cuda.misc.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_MISC_CUH 2 | #define _CUDA_MISC_CUH 3 | #include "cuda.util.cuh" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | __global__ void abs2DKernel(float *d_data, size_t pitch, size_t width, 12 | size_t height); 13 | 14 | __global__ void clampmin2DKernel(float *d_data, size_t pitch, size_t width, 15 | size_t height, float minval); 16 | 17 | __global__ void onebit2DKernel(float *d_data, size_t pitch, size_t width, 18 | size_t height); 19 | 20 | __global__ void cutmax2DKernel(float *d_data, size_t pitch, size_t width, 21 | size_t height, float maxval); 22 | 23 | __global__ void isnan2DKernel(float *d_data, size_t pitch, size_t width, 24 | size_t height); 25 | 26 | __global__ void cisnan2DKernel(cuComplex *d_data, size_t pitch, size_t width, 27 | size_t height); 28 | 29 | __global__ void amp2DKernel(float *d_amp, size_t dpitch, cuComplex *d_data, 30 | size_t spitch, size_t width, size_t height); 31 | 32 | __global__ void div2DKernel(float *d_data, size_t dpitch, float *d_divisor, 33 | size_t spitch, size_t width, size_t height); 34 | 35 | __global__ void cdiv2DKernel(cuComplex *d_data, size_t dpitch, float *d_divisor, 36 | size_t spitch, size_t width, size_t height); 37 | 38 | __global__ void sum2DKernel(float *d_sum, size_t dpitch, float *d_in, 39 | size_t spitch, size_t width, size_t height); 40 | 41 | __global__ void filterKernel(cuComplex *d_spectrum, cuComplex *d_response, size_t pitch, size_t width, size_t height); 42 | 43 | __global__ void onebit2DKernel(float *d_data, size_t pitch, size_t width, size_t height); 44 | 45 | __global__ void FwdNormalize2DKernel(cuComplex *d_segspec, size_t pitch, size_t width, size_t height, float dt); 46 | 47 | __global__ void InvNormalize2DKernel(float *d_segdata, size_t pitch, size_t width, size_t height, float dt); 48 | 49 | __global__ void smooth2DKernel(float *d_out, int dpitch, float *d_tmp, int spitch, int width, int height, int winsize); 50 | 51 | #endif -------------------------------------------------------------------------------- /src/sac2spec/cuda.processing.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CU_PRE_PROCESS_H_ 2 | #define _CU_PRE_PROCESS_H_ 3 | #include "cuda.util.cuh" 4 | #include "cuda.misc.cuh" 5 | #include "cuda.rdcrtr.cuh" 6 | #include "cuda.taper.cuh" 7 | 8 | void preprocess(float *d_sacdata, double *d_sum, double *d_isum, int pitch, size_t proccnt, int taper_percentage); 9 | 10 | void runabs_mf(float *d_sacdata, cuComplex *d_spectrum, 11 | float *d_filtered_sacdata, cuComplex *d_filtered_spectrum, 12 | cuComplex *d_responses, float *d_tmp, 13 | float *d_weight, float *d_tmp_weight, 14 | cufftHandle *planinv, float *freq_lows, 15 | int filterCount, float delta, int proc_batch, int num_ch, int pitch, float maxval); 16 | 17 | void freqWhiten(cuComplex *d_spectrum, 18 | float *d_weight, float *d_tmp_weight, float *d_tmp, 19 | int num_ch, int pitch, int proc_batch, 20 | float delta, int idx1, int idx2, int idx3, int idx4); 21 | 22 | void runabs(float *d_sacdata, float *d_tmp, float *d_weight, float *d_tmp_weight, 23 | float freq_lows_limit, float delta, int proc_batch, int num_ch, int pitch, float maxval); 24 | 25 | #endif -------------------------------------------------------------------------------- /src/sac2spec/cuda.rdcrtr.cu: -------------------------------------------------------------------------------- 1 | #include "cuda.rdcrtr.cuh" 2 | 3 | __global__ void sumSingleBlock2DKernel(double *d_sum, int dpitch, 4 | const float *d_data, int spitch, 5 | int width, int height) 6 | { 7 | size_t row = blockIdx.y * blockDim.y + threadIdx.y; 8 | size_t tx = threadIdx.x; 9 | size_t ty = threadIdx.y; 10 | 11 | double sum = 0; 12 | size_t i; 13 | for (i = tx; i < width && row < height; i += blockDim.x) 14 | { 15 | sum += d_data[row * spitch + i]; 16 | } 17 | 18 | extern __shared__ double partial[]; 19 | if (row < height && tx < blockDim.x) 20 | { 21 | partial[ty * blockDim.x + tx] = sum; 22 | } 23 | __syncthreads(); 24 | 25 | for (size_t stride = blockDim.x / 2; stride >= 1; stride /= 2) 26 | { 27 | if (row < height && tx < stride) 28 | { 29 | partial[ty * blockDim.x + tx] += partial[ty * blockDim.x + tx + stride]; 30 | } 31 | __syncthreads(); 32 | } 33 | 34 | __syncthreads(); 35 | 36 | if (tx == 0 && row < height) 37 | { 38 | d_sum[row * dpitch] = partial[ty * blockDim.x]; 39 | } 40 | } 41 | 42 | __global__ void isumSingleBlock2DKernel(double *d_sum, int dpitch, 43 | const float *d_data, int spitch, 44 | int width, int height) 45 | { 46 | size_t row = blockIdx.y * blockDim.y + threadIdx.y; 47 | size_t tx = threadIdx.x; 48 | size_t ty = threadIdx.y; 49 | 50 | double sum = 0; 51 | size_t i; 52 | for (i = tx; i < width && row < height; i += blockDim.x) 53 | { 54 | sum += d_data[row * spitch + i] * i; 55 | } 56 | 57 | extern __shared__ double partial[]; 58 | if (row < height && tx < blockDim.x) 59 | { 60 | partial[ty * blockDim.x + tx] = sum; 61 | } 62 | __syncthreads(); 63 | 64 | for (size_t stride = blockDim.x / 2; stride >= 1; stride /= 2) 65 | { 66 | if (row < height && tx < stride) 67 | { 68 | partial[ty * blockDim.x + tx] += partial[ty * blockDim.x + tx + stride]; 69 | } 70 | __syncthreads(); 71 | } 72 | 73 | __syncthreads(); 74 | 75 | if (tx == 0 && row < height) 76 | { 77 | d_sum[row * dpitch] = partial[ty * blockDim.x]; 78 | } 79 | } 80 | 81 | __global__ void rdc2DKernel(float *d_data, int pitch, int width, int height, 82 | double *d_sum) 83 | { 84 | int col = blockIdx.x * blockDim.x + threadIdx.x; 85 | int row = blockIdx.y * blockDim.y + threadIdx.y; 86 | 87 | int idx = row * pitch + col; 88 | if (col < width && row < height) 89 | { 90 | d_data[idx] -= d_sum[row] / width; 91 | } 92 | } 93 | 94 | __global__ void rtr2DKernel(float *d_data, int pitch, int width, int height, 95 | double *d_sum, double *d_isum) 96 | { 97 | int col = blockIdx.x * blockDim.x + threadIdx.x; 98 | int row = blockIdx.y * blockDim.y + threadIdx.y; 99 | 100 | if (col < width && row < height) 101 | { 102 | /* SUM(i*x) */ 103 | double y1 = d_isum[row]; 104 | /* SUM(x) */ 105 | double y2 = d_sum[row]; 106 | 107 | double a, b, a11, a12, a22; 108 | a12 = 0.5 * width * (width - 1); 109 | a11 = a12 * (2 * width - 1) / 3.; 110 | a22 = width; 111 | 112 | b = a11 * a22 - a12 * a12; 113 | a = (a22 * y1 - a12 * y2) / b; 114 | b = (a11 * y2 - a12 * y1) / b; 115 | 116 | int idx = row * pitch + col; 117 | d_data[idx] -= a * col + b; 118 | } 119 | } -------------------------------------------------------------------------------- /src/sac2spec/cuda.rdcrtr.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_RDCRTR_CUH 2 | #define _CUDA_RDCRTR_CUH 3 | 4 | #include "cuda.util.cuh" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | __global__ void sumSingleBlock2DKernel(double *d_sum, int dpitch, 16 | const float *d_data, int spitch, 17 | int width, int height); 18 | 19 | __global__ void isumSingleBlock2DKernel(double *d_isum, int dpitch, 20 | const float *d_data, int spitch, 21 | int width, int height); 22 | 23 | __global__ void rdc2DKernel(float *d_data, int pitch, int width, int height, 24 | double *d_sum); 25 | 26 | __global__ void rtr2DKernel(float *d_data, int pitch, int width, int height, 27 | double *d_sum, double *d_isum); 28 | 29 | #endif -------------------------------------------------------------------------------- /src/sac2spec/cuda.taper.cu: -------------------------------------------------------------------------------- 1 | #include "cuda.taper.cuh" 2 | 3 | // The width of taper is nfft+1 4 | __global__ void specTaper2DKernel(cuComplex *d_segspec, size_t pitch, 5 | size_t width, size_t height, int np, 6 | int idx1, int idx2, int idx3, int idx4) 7 | { 8 | size_t col = blockIdx.x * blockDim.x + threadIdx.x; 9 | size_t row = blockIdx.y * blockDim.y + threadIdx.y; 10 | 11 | // Ensure that the index does not exceed th Nyquist frequency 12 | idx4 = idx4 < width ? idx4 : width; 13 | 14 | double dom, factor; 15 | int ntrans, j; 16 | 17 | if (col < width && row < height) 18 | { 19 | size_t idx = row * pitch + col; 20 | 21 | // we zero DC and nyquist freq up to f1 22 | if (col < idx1) 23 | { 24 | d_segspec[idx].x = 0.0; 25 | d_segspec[idx].y = 0.0; 26 | } 27 | // left low freq 28 | else if (col >= idx1 && col < idx2) 29 | { 30 | ntrans = idx2 - idx1; 31 | dom = M_PI / ntrans; 32 | 33 | factor = 1.0; 34 | for (j = 0; j < np; j++) 35 | { 36 | factor = factor * (1.0 - cos(dom * (col - idx1))) / 2.0; 37 | } 38 | d_segspec[idx].x = d_segspec[idx].x * factor; 39 | d_segspec[idx].y = d_segspec[idx].y * factor; 40 | } 41 | 42 | // idx2 to idx3 is flat 43 | 44 | // right high freq 45 | else if (col >= idx3 && col < idx4) 46 | { 47 | ntrans = idx4 - idx3; 48 | dom = M_PI / ntrans; 49 | 50 | factor = 1.0; 51 | for (j = 0; j < np; j++) 52 | { 53 | factor = factor * (1.0 + cos(dom * (col - idx3))) / 2.0; 54 | } 55 | d_segspec[idx].x = d_segspec[idx].x * factor; 56 | d_segspec[idx].y = d_segspec[idx].y * factor; 57 | } 58 | // higher freq are zero 59 | else if (col >= idx4 && col < width) 60 | { 61 | d_segspec[idx].x = 0.0; 62 | d_segspec[idx].y = 0.0; 63 | } 64 | } 65 | } 66 | 67 | __global__ void timetaper2DKernel(float *d_data, int pitch, int width, int height, int taper_size) 68 | { 69 | int col = blockIdx.x * blockDim.x + threadIdx.x; 70 | int row = blockIdx.y * blockDim.y + threadIdx.y; 71 | 72 | if (col < width && row < height) 73 | { 74 | size_t idx = row * pitch + col; 75 | 76 | // Apply the taper to the beginning and end of the signal. 77 | float factor = 1.0; 78 | if (col < taper_size) 79 | { 80 | factor = 0.5 * (1.0 - cos(M_PI * col / taper_size)); 81 | } 82 | else if (col >= width - taper_size) 83 | { 84 | factor = 0.5 * (1.0 - cos(M_PI * (width - col) / taper_size)); 85 | } 86 | else 87 | { 88 | factor = 1.0; 89 | } 90 | // Apply the taper to the signal. 91 | d_data[idx] *= factor; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/sac2spec/cuda.taper.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_TAPER_H 2 | #define _CUDA_TAPER_H 3 | #include 4 | #include "config.h" 5 | #include "cuda.util.cuh" 6 | 7 | __global__ void specTaper2DKernel(cuComplex *d_segspec, size_t pitch, 8 | size_t width, size_t height, int np, 9 | int idx1, int idx2, int idx3, int idx4); 10 | 11 | __global__ void timetaper2DKernel(float *d_data, int pitch, int width, int height, int taper_size); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/sac2spec/cuda.util.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_UTIL_CUH 2 | #define _CUDA_UTIL_CUH 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "config.h" 9 | #define BLOCKX 32 10 | #define BLOCKY 32 11 | #define BLOCKMAX 1024 12 | 13 | #define CUDACHECK(cmd) \ 14 | do \ 15 | { \ 16 | cudaError_t e = cmd; \ 17 | if (e != cudaSuccess) \ 18 | { \ 19 | printf("Failed: Cuda error %s:%d '%s'\n", \ 20 | __FILE__, __LINE__, cudaGetErrorString(e)); \ 21 | exit(EXIT_FAILURE); \ 22 | } \ 23 | } while (0) 24 | 25 | #define CUFFTCHECK(cmd) \ 26 | do \ 27 | { \ 28 | cufftResult_t e = cmd; \ 29 | if (e != CUFFT_SUCCESS) \ 30 | { \ 31 | printf("Failed: CuFFT error %s:%d %d\n", \ 32 | __FILE__, __LINE__, e); \ 33 | exit(EXIT_FAILURE); \ 34 | } \ 35 | } while (0) 36 | 37 | /* Compute the block and dimension for cuda kernel fucntion*/ 38 | void DimCompute(dim3 *, dim3 *, size_t, size_t); 39 | 40 | /* Free cuda pointer */ 41 | void GpuFree(void **pptr); 42 | 43 | /* Get the infomation of available GPU ram of a certain device */ 44 | size_t QueryAvailGpuRam(size_t); 45 | 46 | /* Estimate the batch of processing data */ 47 | size_t EstimateGpuBatch(size_t gpu_id, int npts, int nseg, int nstep, int num_ch, 48 | int filter_count, size_t wh_flag, size_t runabs_flag); 49 | 50 | /* Allocating Memory of Processing data */ 51 | void AllocateGpuMemory(int batch, int nseg, int num_ch, 52 | int do_runabs, int wh_flag, 53 | float **d_sacdata, cuComplex **d_spectrum, 54 | float **d_sacdata_2x, cuComplex **d_spectrum_2x, 55 | float **d_filtered_sacdata, cuComplex **d_filtered_spectrum, 56 | cuComplex **d_filter_responses, float **d_tmp, 57 | float **d_weight, float **d_tmp_weight, 58 | int filterCount, double **d_sum, double **d_isum, 59 | cufftHandle *planfwd, cufftHandle *planinv, cufftHandle *planfwd_2x); 60 | 61 | #endif -------------------------------------------------------------------------------- /src/sac2spec/design_filter_response.h: -------------------------------------------------------------------------------- 1 | #ifndef _DESIGN_RESPONSE_H_ 2 | #define _DESIGN_RESPONSE_H_ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "complex.h" 8 | 9 | typedef struct ButterworthFilter 10 | { 11 | float freq_low; 12 | float freq_high; 13 | double b[5]; /* Numerator coefficients */ 14 | double a[5]; /* Denominator coefficients */ 15 | } ButterworthFilter; 16 | 17 | typedef struct FilterResp 18 | { 19 | float freq_low; // lower frequency 20 | complex *response; // filter response 21 | } FilterResp; 22 | 23 | int parseCoefficientsLine(char *line, double *coefficients); 24 | 25 | ButterworthFilter *readButterworthFilters(const char *filepath, int *filterCount); 26 | 27 | void printButterworthFilters(const ButterworthFilter *filters, int filterCount); 28 | 29 | void calFilterResp(double *b, double *a, int nseg, complex *response); 30 | 31 | FilterResp *processButterworthFilters(ButterworthFilter *filters, int filterCount, float df_1x, int nseg); 32 | 33 | #endif -------------------------------------------------------------------------------- /src/sac2spec/in_out_node.h: -------------------------------------------------------------------------------- 1 | #ifndef _IN_OUT_NODE_H 2 | #define _IN_OUT_NODE_H 3 | #include "sac.h" 4 | #include 5 | #include "complex.h" 6 | #include "segspec.h" 7 | 8 | typedef struct InOutNode 9 | { 10 | char *sacpath; 11 | 12 | char *specpath; 13 | 14 | float *sac_data; 15 | 16 | SACHEAD *sac_hd; 17 | SEGSPEC *segspec_hd; 18 | 19 | complex *spectrum; 20 | 21 | float nstep; 22 | float nspec; 23 | float df; 24 | float dt; 25 | } InOutNode; 26 | 27 | typedef struct PathNode 28 | { 29 | char *path; 30 | struct PathNode *next; 31 | } PathNode; 32 | 33 | typedef struct FilePathArray 34 | { 35 | char **paths; 36 | int count; 37 | } FilePathArray; 38 | #endif -------------------------------------------------------------------------------- /src/sac2spec/par_rw_data.h: -------------------------------------------------------------------------------- 1 | #ifndef _PARALLEL_RW_DATA_H_ 2 | #define _PARALLEL_RW_DATA_H_ 3 | #include 4 | #include 5 | #include 6 | #include "in_out_node.h" 7 | #include "sac.h" 8 | 9 | typedef struct thread_info_read 10 | { 11 | int start; 12 | int end; 13 | InOutNode *InOutList; 14 | } thread_info_read; 15 | 16 | typedef struct ThreadPoolRead 17 | { 18 | pthread_t *threads; 19 | thread_info_read *tinfo; 20 | size_t num_threads; 21 | } ThreadPoolRead; 22 | 23 | typedef struct thread_info_write 24 | { 25 | size_t start; 26 | size_t end; 27 | InOutNode *InOutList; 28 | } thread_info_write; 29 | 30 | typedef struct ThreadPoolWrite 31 | { 32 | pthread_t *threads; 33 | thread_info_write *tinfo; 34 | size_t num_threads; 35 | } ThreadPoolWrite; 36 | 37 | ThreadPoolRead *create_threadpool_read(size_t num_threads); 38 | 39 | ThreadPoolWrite *create_threadpool_write(size_t num_threads); 40 | 41 | int parallel_read_sac(ThreadPoolRead *pool, size_t proccnt, InOutNode *pInOutList, int num_threads); 42 | 43 | int parallel_write_spec(ThreadPoolWrite *pool, size_t h_proccnt, InOutNode *pInOutList, int num_threads); 44 | 45 | void destroy_threadpool_read(ThreadPoolRead *pool); 46 | 47 | void destroy_threadpool_write(ThreadPoolWrite *pool); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/sac2spec/read_filelist.h: -------------------------------------------------------------------------------- 1 | #ifndef _PATHLIST_H_ 2 | #define _PATHLIST_H_ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "in_out_node.h" 10 | #include "config.h" 11 | #include "util.h" 12 | 13 | /* Read in a file which each line is a sac file */ 14 | PathNode *readPathList(const char *filename); 15 | 16 | /* Create directory in a recursiveS way */ 17 | void createDirectoryRecursively(char *dir); 18 | 19 | /* Create directory using a path list */ 20 | void createDirectories(PathNode *pathList); 21 | 22 | /* Convert PathList to Array */ 23 | FilePathArray PathList2Array(PathNode *head); 24 | 25 | #endif -------------------------------------------------------------------------------- /src/sac2spec/readme.txt: -------------------------------------------------------------------------------- 1 | /* ************************************************************ 2 | * Jobs of this code are 3 | * 1. read in three component SAC data 4 | * 2. split the whole data into segments 5 | * 3. do runabs time normalization and spectrum whitenning forof E,N,Z data. 6 | * 7 | * the weight used as the divisor is calculated using all three components 8 | * both in time domain normalization and frequency domain whitenning. 9 | * 10 | * 4. save spectrum of each segments and write to one file. 11 | * 12 | * The output would be segment-spectrum file which will be used later to calculate the noise 13 | * cross correlation. 14 | * 15 | * The information of segment and spectrum is saved in the header of each file which can be 16 | * found in segspec.h 17 | * 18 | * Calculated segment spectrum first would require more disk usage but may speed up the Cross 19 | * Correlation when you have huge dataset eg too many stations. 20 | * 21 | * Note: 22 | * History: 23 | * 1. init by wangwt@2015 24 | 25 | * Cuda Version Histroy 26 | * 27 | * 1. init by wangjx with the thread distrubution strategy made by wuchao 28 | * 2. use 2d cuda threads to perform batch processing of list of sac files, 29 | * X: segments of one sacfile, Y:list of sacfiles by wuchao@2021 30 | * 3. use cuda to implement rdc rtr npsmooth spectaper and etc by wuchao@2021 wangjx@2021,2022 31 | * 4. use cufft to perform FFT/IFFT transform by wuchao@2021 32 | * last updated by wangjx@20230703 33 | * *****************************************************************/ -------------------------------------------------------------------------------- /src/sac2spec/segspec.h: -------------------------------------------------------------------------------- 1 | /* Header for the segment by segment spectrum for noise cross correlation 2 | * History: 3 | * 1. init by wangwt to speed up CC on huge dataset. 4 | * 5 | * last update wangjx@20230514 6 | * */ 7 | 8 | #ifndef _SEGSPEC_H 9 | #define _SEGSPEC_H 10 | 11 | typedef struct segspec_s 12 | { 13 | float stla; 14 | float stlo; 15 | /* segment info */ 16 | int nstep; 17 | /* FFT info */ 18 | int nspec; /* use fftr() number of complex eg 2*nspec float */ 19 | float df; 20 | float dt; 21 | } SEGSPEC; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/sac2spec/util.c: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | 3 | const float RAMUPPERBOUND = 0.8; 4 | 5 | size_t QueryAvailCpuRam() 6 | { 7 | const size_t LINEMAX = 256; 8 | const size_t KILOBYTES = 1L << 10; 9 | // const size_t GIGABYTES = 1L << 30; 10 | struct sysinfo sinfo; 11 | char buffer[LINEMAX]; 12 | 13 | FILE *fid = fopen("/proc/meminfo", "r"); 14 | 15 | size_t availram = 0; 16 | 17 | while (fgets(buffer, LINEMAX, fid) != NULL) 18 | { 19 | if (strstr(buffer, "MemAvailable") != NULL) 20 | { 21 | sscanf(buffer, "MemAvailable: %lu kB", &availram); 22 | availram *= KILOBYTES; /* kB -> B */ 23 | availram *= RAMUPPERBOUND; 24 | } 25 | } 26 | fclose(fid); 27 | 28 | /* In Linux sysinfo's free ram is far smaller than available ram 29 | * Use this in condition that cannot find Memavailble in /proc/meminfo 30 | */ 31 | if (availram == 0) 32 | { 33 | int err = sysinfo(&sinfo); 34 | if (err != 0) 35 | { 36 | perror("Get sys info\n"); 37 | exit(-1); 38 | } 39 | availram = sinfo.freeram; 40 | } 41 | 42 | return availram; 43 | } 44 | 45 | size_t EstimateCpuBatch(size_t unitRam, int thread_num) 46 | { 47 | // Query available CPU RAM 48 | size_t availableRam = QueryAvailCpuRam() / thread_num; 49 | const size_t GIGABYTES = 1L << 30; 50 | printf("Avail cpu ram: %.3f GB\n", availableRam * 1.0 / GIGABYTES); 51 | // Initialize batch count and required RAM 52 | size_t batch = 0; 53 | size_t requiredRam = 0; 54 | 55 | // Keep increasing the batch count until required RAM exceeds available RAM 56 | while (requiredRam < availableRam) 57 | { 58 | // Increment the batch count 59 | batch++; 60 | 61 | // Update the required RAM based on the new batch count 62 | requiredRam = batch * unitRam; 63 | } 64 | 65 | // Decrease the batch count by 1 since the last increment caused required RAM 66 | // to exceed available RAM 67 | batch--; 68 | batch = batch > _RISTRICT_MAX_CPU_BATCH ? _RISTRICT_MAX_CPU_BATCH : batch; 69 | // Return the estimated batch count 70 | return batch; 71 | } 72 | 73 | void CpuMalloc(void **pptr, size_t sz) 74 | { 75 | if ((*pptr = malloc(sz)) == NULL) 76 | { 77 | perror("Malloc cpu memory"); 78 | exit(-1); 79 | } 80 | } 81 | 82 | void CpuFree(void **pptr) 83 | { 84 | free(*pptr); 85 | *pptr = NULL; 86 | } 87 | 88 | // in case some old compiler cannot deal with strdup 89 | char *my_strdup(const char *s) 90 | { 91 | if (s == NULL) 92 | { 93 | return NULL; 94 | } 95 | char *new_str = (char *)malloc(strlen(s) + 1); 96 | if (new_str == NULL) 97 | { 98 | return NULL; 99 | } 100 | char *p = new_str; 101 | while (*s) 102 | { 103 | *p++ = *s++; 104 | } 105 | *p = '\0'; 106 | return new_str; 107 | } 108 | -------------------------------------------------------------------------------- /src/sac2spec/util.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTIL_H 2 | #define _UTIL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "config.h" 9 | 10 | size_t QueryAvailCpuRam(); 11 | size_t EstimateCpuBatch(size_t unitRam, int thread_num); 12 | void CpuMalloc(void **, size_t); 13 | void CpuFree(void **); 14 | char* my_strdup(const char* s); 15 | #endif -------------------------------------------------------------------------------- /src/sac2spec_butter/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.cu": "cuda-cpp", 4 | "*.h": "cpp", 5 | "*.cuh": "cpp", 6 | "*.c": "c", 7 | "arguproc.h": "c", 8 | "in_out_node_c9.h": "c", 9 | "complex": "cpp", 10 | "cstddef": "cpp", 11 | "random": "cpp" 12 | } 13 | } -------------------------------------------------------------------------------- /src/sac2spec_butter/Makefile: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------- 2 | # sac2spec_butter ‒ 子目录 Makefile(Release / Debug 自动切换) 3 | # ---------------------------------------------------- 4 | 5 | # 编译器 6 | CC ?= gcc 7 | NVCC ?= /usr/local/cuda/bin/nvcc 8 | ARCH ?= sm_89 9 | WARN ?= -Wall 10 | 11 | # ---------- 优化级别自动切换 ---------- 12 | ifeq ($(MAKELEVEL),0) # 手动调试 13 | CFLAGS ?= -O0 -g $(WARN) 14 | NVCCFLAGS ?= -g -G -lineinfo -arch=$(ARCH) 15 | else # 顶层批量构建 16 | CFLAGS ?= -O3 $(WARN) 17 | NVCCFLAGS ?= -O3 --generate-line-info -arch=$(ARCH) 18 | endif 19 | # ------------------------------------- 20 | 21 | # 链接库 22 | LFLAG = -L/usr/local/cuda/lib64 -lcufft -lcudart -lm 23 | 24 | # 源文件 25 | CUDAOBJS = cuda.rdcrtr.o \ 26 | cuda.util.o \ 27 | cuda.misc.o \ 28 | cuda.filter.o \ 29 | cuda.processing.o \ 30 | cuda.taper.o \ 31 | cuda.main.o 32 | 33 | OBJS = design_filter_response.o \ 34 | arguproc.o \ 35 | cal_nseg.o \ 36 | par_rw_data.o \ 37 | read_filelist.o \ 38 | sacio.o \ 39 | util.o 40 | 41 | # 输出可执行文件 42 | BINDIR := ../../bin 43 | PROG := $(BINDIR)/sac2spec_butter 44 | 45 | # 伪目标 46 | .PHONY: all clean veryclean 47 | 48 | # 默认目标 49 | all: $(BINDIR) $(PROG) 50 | 51 | # 创建输出目录 52 | $(BINDIR): 53 | @mkdir -p $@ 54 | 55 | # 链接 56 | $(PROG): $(OBJS) $(CUDAOBJS) 57 | $(NVCC) $(NVCCFLAGS) -o $@ $^ $(LFLAG) 58 | 59 | # C 文件编译 60 | %.o: %.c 61 | $(CC) $(CFLAGS) -c $< -o $@ 62 | 63 | # CUDA 文件编译 64 | %.o: %.cu 65 | $(NVCC) $(NVCCFLAGS) -c $< -o $@ 66 | 67 | # 清理 68 | clean: 69 | @rm -f *.o 70 | 71 | veryclean: clean 72 | @rm -f $(PROG) 73 | -------------------------------------------------------------------------------- /src/sac2spec_butter/arguproc.h: -------------------------------------------------------------------------------- 1 | #ifndef _ARGU_PROC_H 2 | #define _ARGU_PROC_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "config.h" 9 | 10 | typedef struct ARGUTYPE 11 | { 12 | char *sac_lst; 13 | char *spec_lst; 14 | char *filter_file; 15 | float seglen; 16 | float freq_low; 17 | float freq_high; 18 | int num_ch; 19 | int gpu_id; 20 | int whitenType; 21 | int normalizeType; 22 | int skip_steps[MAX_SKIP_STEPS_SIZE]; 23 | int skip_step_count; 24 | int thread_num; 25 | int gpu_num; 26 | } ARGUTYPE; 27 | 28 | /* Parsing the input argument */ 29 | void ArgumentProcess(int argc, char **argv, ARGUTYPE *pargument); 30 | void usage(); 31 | #endif -------------------------------------------------------------------------------- /src/sac2spec_butter/cal_nseg.h: -------------------------------------------------------------------------------- 1 | #ifndef _CAL_NSEG_H_ 2 | #define _CAL_NSEG_H_ 3 | #include 4 | #include 5 | 6 | // Find the number of segment using npts and seglen, delta 7 | int cal_nseg(int seglen, int npts, float delta); 8 | 9 | #endif -------------------------------------------------------------------------------- /src/sac2spec_butter/complex.h: -------------------------------------------------------------------------------- 1 | #ifndef COMPLEX_H 2 | #define COMPLEX_H 3 | 4 | typedef struct 5 | { 6 | float x; 7 | float y; 8 | } complex; 9 | 10 | #endif -------------------------------------------------------------------------------- /src/sac2spec_butter/config.h: -------------------------------------------------------------------------------- 1 | #ifndef _config_h 2 | #define _config_h 3 | 4 | #define MAXLINE 8192 5 | #define MAXPATH 8192 6 | #define MAXKSTNM 2048 7 | #define MAXNAME 255 8 | #define MAXBAND 100 9 | #define MAX_SKIP_STEPS_SIZE 100 10 | #define _RISTRICT_MAX_GPU_BATCH 9999999 11 | #define _RISTRICT_MAX_CPU_BATCH 9999999 12 | #define MAXVAL 20 13 | #define MINVAL 1e-30 14 | #define TAPER_RATIO 3 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/sac2spec_butter/cuda.filter.cu: -------------------------------------------------------------------------------- 1 | #include "cuda.filter.cuh" 2 | #include 3 | 4 | __global__ void filterTKernel(float *d_sac, float *d_filtered, double *a, double *b, float *sac_hist, float *filtered_hist, size_t width, size_t height) 5 | { 6 | // int col = blockIdx.x * blockDim.x + threadIdx.x; 7 | int row = blockIdx.y * blockDim.y + threadIdx.y; 8 | int len_a = 5; 9 | int len_b = 5; 10 | int i = 0; 11 | if (row < height) 12 | { 13 | int offset_a = row * len_a; 14 | int offset_b = row * len_b; 15 | for (size_t col = 0; col < width; col++) 16 | { 17 | int idx = row * width + col; 18 | sac_hist[offset_a + 0] = d_sac[idx]; 19 | 20 | // calculate the output point 21 | d_filtered[idx] = float(b[0] * sac_hist[offset_a + 0]); 22 | for (i = 1; i < 5; i++) // 1,2,3,4 23 | { 24 | d_filtered[idx] += float(b[i] * sac_hist[offset_a + i] - a[i] * filtered_hist[offset_b + i - 1]); 25 | } 26 | // update the history 27 | for (i = 4; i > 0; i--) // 4,3,2,1 28 | { 29 | sac_hist[offset_a + i] = sac_hist[offset_a + i - 1]; 30 | } 31 | for (i = 4; i > 1; i--) // 4,3,2 32 | { 33 | filtered_hist[offset_b + i - 1] = filtered_hist[offset_b + i - 2]; 34 | } 35 | filtered_hist[offset_b + 0] = d_filtered[idx]; 36 | } 37 | } 38 | } 39 | 40 | __global__ void reverseKernel(const float *d_input, float *d_output, size_t width, size_t height) 41 | { 42 | int col = blockIdx.x * blockDim.x + threadIdx.x; 43 | int row = blockIdx.y * blockDim.y + threadIdx.y; 44 | 45 | if (col < width && row < height) 46 | { 47 | int index_in = row * width + col; 48 | int index_out = row * width + (width - 1 - col); 49 | d_output[index_out] = d_input[index_in]; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/sac2spec_butter/cuda.filter.cuh: -------------------------------------------------------------------------------- 1 | #ifndef CUDA_FILTER_CUH 2 | #include 3 | 4 | __global__ void filterTKernel(float *d_sac, float *d_filtered, double *a, double *b, float *sac_hist, float *filtered_hist, size_t width, size_t height); 5 | __global__ void reverseKernel(const float *d_input, float *d_output, size_t width, size_t height); 6 | #endif 7 | -------------------------------------------------------------------------------- /src/sac2spec_butter/cuda.misc.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_MISC_CUH 2 | #define _CUDA_MISC_CUH 3 | #include "cuda.util.cuh" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | __global__ void abs2DKernel(float *d_data, size_t pitch, size_t width, 12 | size_t height); 13 | 14 | __global__ void clampmin2DKernel(float *d_data, size_t pitch, size_t width, 15 | size_t height, float minval); 16 | 17 | __global__ void onebit2DKernel(float *d_data, size_t pitch, size_t width, 18 | size_t height); 19 | 20 | __global__ void cutmax2DKernel(float *d_data, size_t pitch, size_t width, 21 | size_t height, float maxval); 22 | 23 | __global__ void isnan2DKernel(float *d_data, size_t pitch, size_t width, 24 | size_t height); 25 | 26 | __global__ void cisnan2DKernel(cuComplex *d_data, size_t pitch, size_t width, 27 | size_t height); 28 | 29 | __global__ void amp2DKernel(float *d_amp, size_t dpitch, cuComplex *d_data, 30 | size_t spitch, size_t width, size_t height); 31 | 32 | __global__ void div2DKernel(float *d_data, size_t dpitch, float *d_divisor, 33 | size_t spitch, size_t width, size_t height); 34 | 35 | __global__ void cdiv2DKernel(cuComplex *d_data, size_t dpitch, float *d_divisor, 36 | size_t spitch, size_t width, size_t height); 37 | 38 | __global__ void sum2DKernel(float *d_sum, size_t dpitch, float *d_in, 39 | size_t spitch, size_t width, size_t height); 40 | 41 | __global__ void filterKernel(cuComplex *d_spectrum, cuComplex *d_response, size_t pitch, size_t width, size_t height); 42 | 43 | __global__ void onebit2DKernel(float *d_data, size_t pitch, size_t width, size_t height); 44 | 45 | __global__ void FwdNormalize2DKernel(cuComplex *d_segspec, size_t pitch, size_t width, size_t height, float dt); 46 | 47 | __global__ void InvNormalize2DKernel(float *d_segdata, size_t pitch, size_t width, size_t height, float dt); 48 | 49 | __global__ void smooth2DKernel(float *d_out, int dpitch, float *d_tmp, int spitch, int width, int height, int winsize); 50 | 51 | #endif -------------------------------------------------------------------------------- /src/sac2spec_butter/cuda.processing.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CU_PRE_PROCESS_H_ 2 | #define _CU_PRE_PROCESS_H_ 3 | #include "cuda.util.cuh" 4 | #include "cuda.misc.cuh" 5 | #include "cuda.rdcrtr.cuh" 6 | #include "cuda.filter.cuh" 7 | #include "cuda.taper.cuh" 8 | 9 | extern "C" 10 | { 11 | #include "design_filter_response.h" 12 | } 13 | 14 | void preprocess(float *d_sacdata, double *d_sum, double *d_isum, int pitch, size_t proccnt, int taper_percentage); 15 | 16 | void mycustom_filter(float *d_sacdata, float *d_filtered, float *d_filtered_tmp, 17 | double *d_a, double *d_b, float *d_sac_hist, float *d_filtered_hist, 18 | size_t width, size_t height); 19 | 20 | void runabs_mf(float *d_sacdata, float *d_sac_sum, 21 | float *d_filtered, float *d_filtered_tmp, 22 | double *d_a, double *d_b, float *d_sac_hist, float *d_filtered_hist, 23 | float *d_tmp, float *d_weight, float *d_tmp_weight, ButterworthFilter *filters, 24 | int filterCount, float delta, int proc_batch, int num_ch, int pitch, float maxval); 25 | 26 | void freqWhiten(cuComplex *d_spectrum, 27 | float *d_weight, float *d_tmp_weight, float *d_tmp, 28 | int num_ch, int pitch, int proc_batch, 29 | float delta, int idx1, int idx2, int idx3, int idx4); 30 | 31 | void runabs(float *d_sacdata, float *d_tmp, float *d_weight, float *d_tmp_weight, 32 | float freq_lows_limit, float delta, int proc_batch, int num_ch, int pitch, float maxval); 33 | 34 | #endif -------------------------------------------------------------------------------- /src/sac2spec_butter/cuda.rdcrtr.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_RDCRTR_CUH 2 | #define _CUDA_RDCRTR_CUH 3 | 4 | #include "cuda.util.cuh" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | __global__ void sumSingleBlock2DKernel(double *d_sum, int dpitch, 16 | const float *d_data, int spitch, 17 | int width, int height); 18 | 19 | __global__ void isumSingleBlock2DKernel(double *d_isum, int dpitch, 20 | const float *d_data, int spitch, 21 | int width, int height); 22 | 23 | __global__ void rdc2DKernel(float *d_data, int pitch, int width, int height, 24 | double *d_sum); 25 | 26 | __global__ void rtr2DKernel(float *d_data, int pitch, int width, int height, 27 | double *d_sum, double *d_isum); 28 | 29 | #endif -------------------------------------------------------------------------------- /src/sac2spec_butter/cuda.taper.cu: -------------------------------------------------------------------------------- 1 | #include "cuda.taper.cuh" 2 | 3 | // The width of taper is nfft+1 4 | __global__ void specTaper2DKernel(cuComplex *d_segspec, size_t pitch, 5 | size_t width, size_t height, int np, 6 | int idx1, int idx2, int idx3, int idx4) 7 | { 8 | size_t col = blockIdx.x * blockDim.x + threadIdx.x; 9 | size_t row = blockIdx.y * blockDim.y + threadIdx.y; 10 | 11 | // Ensure that the index does not exceed th Nyquist frequency 12 | idx4 = idx4 < width ? idx4 : width; 13 | 14 | double dom, factor; 15 | int ntrans, j; 16 | 17 | if (col < width && row < height) 18 | { 19 | size_t idx = row * pitch + col; 20 | 21 | // we zero DC and nyquist freq up to f1 22 | if (col < idx1) 23 | { 24 | d_segspec[idx].x = 0.0; 25 | d_segspec[idx].y = 0.0; 26 | } 27 | // left low freq 28 | else if (col >= idx1 && col < idx2) 29 | { 30 | ntrans = idx2 - idx1; 31 | dom = M_PI / ntrans; 32 | 33 | factor = 1.0; 34 | for (j = 0; j < np; j++) 35 | { 36 | factor = factor * (1.0 - cos(dom * (col - idx1))) / 2.0; 37 | } 38 | d_segspec[idx].x = d_segspec[idx].x * factor; 39 | d_segspec[idx].y = d_segspec[idx].y * factor; 40 | } 41 | 42 | // idx2 to idx3 is flat 43 | 44 | // right high freq 45 | else if (col >= idx3 && col < idx4) 46 | { 47 | ntrans = idx4 - idx3; 48 | dom = M_PI / ntrans; 49 | 50 | factor = 1.0; 51 | for (j = 0; j < np; j++) 52 | { 53 | factor = factor * (1.0 + cos(dom * (col - idx3))) / 2.0; 54 | } 55 | d_segspec[idx].x = d_segspec[idx].x * factor; 56 | d_segspec[idx].y = d_segspec[idx].y * factor; 57 | } 58 | // higher freq are zero 59 | else if (col >= idx4 && col < width) 60 | { 61 | d_segspec[idx].x = 0.0; 62 | d_segspec[idx].y = 0.0; 63 | } 64 | } 65 | } 66 | 67 | __global__ void timetaper2DKernel(float *d_data, int pitch, int width, int height, int taper_size) 68 | { 69 | int col = blockIdx.x * blockDim.x + threadIdx.x; 70 | int row = blockIdx.y * blockDim.y + threadIdx.y; 71 | 72 | if (col < width && row < height) 73 | { 74 | size_t idx = row * pitch + col; 75 | 76 | // Apply the taper to the beginning and end of the signal. 77 | float factor = 1.0; 78 | if (col < taper_size) 79 | { 80 | factor = 0.5 * (1.0 - cos(M_PI * col / taper_size)); 81 | } 82 | else if (col >= width - taper_size) 83 | { 84 | factor = 0.5 * (1.0 - cos(M_PI * (width - col) / taper_size)); 85 | } 86 | else 87 | { 88 | factor = 1.0; 89 | } 90 | // Apply the taper to the signal. 91 | d_data[idx] *= factor; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/sac2spec_butter/cuda.taper.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_TAPER_H 2 | #define _CUDA_TAPER_H 3 | #include 4 | #include "config.h" 5 | #include "cuda.util.cuh" 6 | 7 | __global__ void specTaper2DKernel(cuComplex *d_segspec, size_t pitch, 8 | size_t width, size_t height, int np, 9 | int idx1, int idx2, int idx3, int idx4); 10 | 11 | __global__ void timetaper2DKernel(float *d_data, int pitch, int width, int height, int taper_size); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/sac2spec_butter/cuda.util.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_UTIL_CUH 2 | #define _CUDA_UTIL_CUH 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "config.h" 9 | #define BLOCKX 32 10 | #define BLOCKY 32 11 | #define BLOCKMAX 1024 12 | 13 | #define CUDACHECK(cmd) \ 14 | do \ 15 | { \ 16 | cudaError_t e = cmd; \ 17 | if (e != cudaSuccess) \ 18 | { \ 19 | printf("Failed: Cuda error %s:%d '%s'\n", \ 20 | __FILE__, __LINE__, cudaGetErrorString(e)); \ 21 | exit(EXIT_FAILURE); \ 22 | } \ 23 | } while (0) 24 | 25 | #define CUFFTCHECK(cmd) \ 26 | do \ 27 | { \ 28 | cufftResult_t e = cmd; \ 29 | if (e != CUFFT_SUCCESS) \ 30 | { \ 31 | printf("Failed: CuFFT error %s:%d %d\n", \ 32 | __FILE__, __LINE__, e); \ 33 | exit(EXIT_FAILURE); \ 34 | } \ 35 | } while (0) 36 | 37 | /* Compute the block and dimension for cuda kernel fucntion*/ 38 | void DimCompute(dim3 *, dim3 *, size_t, size_t); 39 | 40 | /* Free cuda pointer */ 41 | void GpuFree(void **pptr); 42 | 43 | /* Get the infomation of available GPU ram of a certain device */ 44 | size_t QueryAvailGpuRam(size_t); 45 | 46 | /* Estimate the batch of processing data */ 47 | size_t EstimateGpuBatch(size_t gpu_id, int nseg, int num_ch); 48 | 49 | /* Allocating Memory of Processing data */ 50 | void AllocateGpuMemory(int batch, int nseg, int num_ch, 51 | float **d_sacdata, float **d_sac_sum, 52 | cuComplex **d_spectrum, 53 | float **d_sacdata_2x, cuComplex **d_spectrum_2x, 54 | float **d_filtered, float **d_filtered_tmp, 55 | float **sac_hist, float **filtered_hist, 56 | double **a, double **b, float **d_tmp, 57 | float **d_weight, float **d_tmp_weight, 58 | int filterCount, double **d_sum, double **d_isum, 59 | cufftHandle *planfwd, cufftHandle *planinv, cufftHandle *planfwd_2x); 60 | 61 | #endif -------------------------------------------------------------------------------- /src/sac2spec_butter/design_filter_response.h: -------------------------------------------------------------------------------- 1 | #ifndef _DESIGN_RESPONSE_H_ 2 | #define _DESIGN_RESPONSE_H_ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "complex.h" 8 | 9 | typedef struct ButterworthFilter 10 | { 11 | float freq_low; 12 | float freq_high; 13 | double b[5]; /* Numerator coefficients */ 14 | double a[5]; /* Denominator coefficients */ 15 | } ButterworthFilter; 16 | 17 | typedef struct FilterResp 18 | { 19 | float freq_low; // lower frequency 20 | complex *response; // filter response 21 | } FilterResp; 22 | 23 | int parseCoefficientsLine(char *line, double *coefficients); 24 | 25 | ButterworthFilter *readButterworthFilters(const char *filepath, int *filterCount); 26 | 27 | void printButterworthFilters(const ButterworthFilter *filters, int filterCount); 28 | 29 | void calFilterResp(double *b, double *a, int nseg, complex *response); 30 | 31 | FilterResp *processButterworthFilters(ButterworthFilter *filters, int filterCount, float df_1x, int nseg); 32 | 33 | #endif -------------------------------------------------------------------------------- /src/sac2spec_butter/in_out_node.h: -------------------------------------------------------------------------------- 1 | #ifndef _IN_OUT_NODE_H 2 | #define _IN_OUT_NODE_H 3 | #include "sac.h" 4 | #include 5 | #include "complex.h" 6 | #include "segspec.h" 7 | 8 | typedef struct InOutNode 9 | { 10 | char *sacpath; 11 | 12 | char *specpath; 13 | 14 | float *sac_data; 15 | 16 | SACHEAD *sac_hd; 17 | SEGSPEC *segspec_hd; 18 | 19 | complex *spectrum; 20 | 21 | float nstep; 22 | float nspec; 23 | float df; 24 | float dt; 25 | } InOutNode; 26 | 27 | typedef struct PathNode 28 | { 29 | char *path; 30 | struct PathNode *next; 31 | } PathNode; 32 | 33 | typedef struct FilePathArray 34 | { 35 | char **paths; 36 | int count; 37 | } FilePathArray; 38 | #endif -------------------------------------------------------------------------------- /src/sac2spec_butter/par_rw_data.h: -------------------------------------------------------------------------------- 1 | #ifndef _PARALLEL_RW_DATA_H_ 2 | #define _PARALLEL_RW_DATA_H_ 3 | #include 4 | #include 5 | #include 6 | #include "in_out_node.h" 7 | #include "sac.h" 8 | 9 | typedef struct thread_info_read 10 | { 11 | int start; 12 | int end; 13 | InOutNode *InOutList; 14 | } thread_info_read; 15 | 16 | typedef struct ThreadPoolRead 17 | { 18 | pthread_t *threads; 19 | thread_info_read *tinfo; 20 | size_t num_threads; 21 | } ThreadPoolRead; 22 | 23 | typedef struct thread_info_write 24 | { 25 | size_t start; 26 | size_t end; 27 | InOutNode *InOutList; 28 | } thread_info_write; 29 | 30 | typedef struct ThreadPoolWrite 31 | { 32 | pthread_t *threads; 33 | thread_info_write *tinfo; 34 | size_t num_threads; 35 | } ThreadPoolWrite; 36 | 37 | ThreadPoolRead *create_threadpool_read(size_t num_threads); 38 | 39 | ThreadPoolWrite *create_threadpool_write(size_t num_threads); 40 | 41 | int parallel_read_sac(ThreadPoolRead *pool, size_t proccnt, InOutNode *pInOutList, int num_threads); 42 | 43 | int parallel_write_spec(ThreadPoolWrite *pool, size_t h_proccnt, InOutNode *pInOutList, int num_threads); 44 | 45 | void destroy_threadpool_read(ThreadPoolRead *pool); 46 | 47 | void destroy_threadpool_write(ThreadPoolWrite *pool); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/sac2spec_butter/read_filelist.h: -------------------------------------------------------------------------------- 1 | #ifndef _PATHLIST_H_ 2 | #define _PATHLIST_H_ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "in_out_node.h" 10 | #include "config.h" 11 | #include "util.h" 12 | 13 | /* Read in a file which each line is a sac file */ 14 | PathNode *readPathList(const char *filename); 15 | 16 | /* Create directory in a recursiveS way */ 17 | void createDirectoryRecursively(char *dir); 18 | 19 | /* Create directory using a path list */ 20 | void createDirectories(PathNode *pathList); 21 | 22 | /* Convert PathList to Array */ 23 | FilePathArray PathList2Array(PathNode *head); 24 | 25 | #endif -------------------------------------------------------------------------------- /src/sac2spec_butter/readme.txt: -------------------------------------------------------------------------------- 1 | /* ************************************************************ 2 | * Jobs of this code are 3 | * 1. read in three component SAC data 4 | * 2. split the whole data into segments 5 | * 3. do runabs time normalization and spectrum whitenning forof E,N,Z data. 6 | * 7 | * the weight used as the divisor is calculated using all three components 8 | * both in time domain normalization and frequency domain whitenning. 9 | * 10 | * 4. save spectrum of each segments and write to one file. 11 | * 12 | * The output would be segment-spectrum file which will be used later to calculate the noise 13 | * cross correlation. 14 | * 15 | * The information of segment and spectrum is saved in the header of each file which can be 16 | * found in segspec.h 17 | * 18 | * Calculated segment spectrum first would require more disk usage but may speed up the Cross 19 | * Correlation when you have huge dataset eg too many stations. 20 | * 21 | * Note: 22 | * History: 23 | * 1. init by wangwt@2015 24 | 25 | * Cuda Version Histroy 26 | * 27 | * 1. init by wangjx with the thread distrubution strategy made by wuchao 28 | * 2. use 2d cuda threads to perform batch processing of list of sac files, 29 | * X: segments of one sacfile, Y:list of sacfiles by wuchao@2021 30 | * 3. use cuda to implement rdc rtr npsmooth spectaper and etc by wuchao@2021 wangjx@2021,2022 31 | * 4. use cufft to perform FFT/IFFT transform by wuchao@2021 32 | * last updated by wangjx@20230703 33 | * *****************************************************************/ -------------------------------------------------------------------------------- /src/sac2spec_butter/segspec.h: -------------------------------------------------------------------------------- 1 | /* Header for the segment by segment spectrum for noise cross correlation 2 | * History: 3 | * 1. init by wangwt to speed up CC on huge dataset. 4 | * 5 | * last update wangjx@20230514 6 | * */ 7 | 8 | #ifndef _SEGSPEC_H 9 | #define _SEGSPEC_H 10 | 11 | typedef struct segspec_s 12 | { 13 | float stla; 14 | float stlo; 15 | /* segment info */ 16 | int nstep; 17 | /* FFT info */ 18 | int nspec; /* use fftr() number of complex eg 2*nspec float */ 19 | float df; 20 | float dt; 21 | } SEGSPEC; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/sac2spec_butter/util.c: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | 3 | const float RAMUPPERBOUND = 0.8; 4 | 5 | size_t QueryAvailCpuRam() 6 | { 7 | const size_t LINEMAX = 256; 8 | const size_t KILOBYTES = 1L << 10; 9 | // const size_t GIGABYTES = 1L << 30; 10 | struct sysinfo sinfo; 11 | char buffer[LINEMAX]; 12 | 13 | FILE *fid = fopen("/proc/meminfo", "r"); 14 | 15 | size_t availram = 0; 16 | 17 | while (fgets(buffer, LINEMAX, fid) != NULL) 18 | { 19 | if (strstr(buffer, "MemAvailable") != NULL) 20 | { 21 | sscanf(buffer, "MemAvailable: %lu kB", &availram); 22 | availram *= KILOBYTES; /* kB -> B */ 23 | availram *= RAMUPPERBOUND; 24 | } 25 | } 26 | fclose(fid); 27 | 28 | /* In Linux sysinfo's free ram is far smaller than available ram 29 | * Use this in condition that cannot find Memavailble in /proc/meminfo 30 | */ 31 | if (availram == 0) 32 | { 33 | int err = sysinfo(&sinfo); 34 | if (err != 0) 35 | { 36 | perror("Get sys info\n"); 37 | exit(-1); 38 | } 39 | availram = sinfo.freeram; 40 | } 41 | 42 | return availram; 43 | } 44 | 45 | size_t EstimateCpuBatch(size_t unitRam, int thread_num) 46 | { 47 | // Query available CPU RAM 48 | size_t availableRam = QueryAvailCpuRam() / thread_num; 49 | const size_t GIGABYTES = 1L << 30; 50 | printf("Avail cpu ram: %.3f GB\n", availableRam * 1.0 / GIGABYTES); 51 | // Initialize batch count and required RAM 52 | size_t batch = 0; 53 | size_t requiredRam = 0; 54 | 55 | // Keep increasing the batch count until required RAM exceeds available RAM 56 | while (requiredRam < availableRam) 57 | { 58 | // Increment the batch count 59 | batch++; 60 | 61 | // Update the required RAM based on the new batch count 62 | requiredRam = batch * unitRam; 63 | } 64 | 65 | // Decrease the batch count by 1 since the last increment caused required RAM 66 | // to exceed available RAM 67 | batch--; 68 | batch = batch > _RISTRICT_MAX_CPU_BATCH ? _RISTRICT_MAX_CPU_BATCH : batch; 69 | // Return the estimated batch count 70 | return batch; 71 | } 72 | 73 | void CpuMalloc(void **pptr, size_t sz) 74 | { 75 | if ((*pptr = malloc(sz)) == NULL) 76 | { 77 | perror("Malloc cpu memory"); 78 | exit(-1); 79 | } 80 | } 81 | 82 | void CpuFree(void **pptr) 83 | { 84 | free(*pptr); 85 | *pptr = NULL; 86 | } 87 | 88 | // in case some old compiler cannot deal with strdup 89 | char *my_strdup(const char *s) 90 | { 91 | if (s == NULL) 92 | { 93 | return NULL; 94 | } 95 | char *new_str = (char *)malloc(strlen(s) + 1); 96 | if (new_str == NULL) 97 | { 98 | return NULL; 99 | } 100 | char *p = new_str; 101 | while (*s) 102 | { 103 | *p++ = *s++; 104 | } 105 | *p = '\0'; 106 | return new_str; 107 | } 108 | -------------------------------------------------------------------------------- /src/sac2spec_butter/util.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTIL_H 2 | #define _UTIL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "config.h" 9 | 10 | size_t QueryAvailCpuRam(); 11 | size_t EstimateCpuBatch(size_t unitRam, int thread_num); 12 | void CpuMalloc(void **, size_t); 13 | void CpuFree(void **); 14 | char* my_strdup(const char* s); 15 | #endif -------------------------------------------------------------------------------- /src/sac2spec_cos/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.c": "c", 4 | "arguproc.h": "c", 5 | "in_out_node_c9.h": "c", 6 | "complex": "cpp" 7 | } 8 | } -------------------------------------------------------------------------------- /src/sac2spec_cos/Makefile: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------- 2 | # sac2spec_cos ‒ 子目录 Makefile 3 | # • 顶层递归调用 → Release (-O3) 4 | # • 手动进目录 make → Debug (-O0 -g -G) 5 | # ---------------------------------------------------- 6 | 7 | # 编译器 8 | CC ?= gcc 9 | NVCC ?= /usr/local/cuda/bin/nvcc 10 | ARCH ?= sm_89 11 | WARN ?= -Wall 12 | 13 | # ---------- 优化级别自动切换 ---------- 14 | ifeq ($(MAKELEVEL),0) # 手动调试 15 | CFLAGS ?= -O0 -g $(WARN) 16 | NVCCFLAGS ?= -g -G -lineinfo -arch=$(ARCH) 17 | else # 顶层批量构建 18 | CFLAGS ?= -O3 $(WARN) 19 | NVCCFLAGS ?= -O3 --generate-line-info -arch=$(ARCH) 20 | endif 21 | # ------------------------------------- 22 | 23 | # 链接库 24 | LFLAG = -L/usr/local/cuda/lib64 -lcufft -lcudart -lm 25 | 26 | # 源文件 27 | CUDAOBJS = cuda.rdcrtr.o \ 28 | cuda.util.o \ 29 | cuda.misc.o \ 30 | cuda.processing.o \ 31 | cuda.taper.o \ 32 | cuda.main.o 33 | 34 | OBJS = design_filter_response.o \ 35 | arguproc.o \ 36 | cal_nseg.o \ 37 | par_rw_data.o \ 38 | read_filelist.o \ 39 | sacio.o \ 40 | util.o 41 | 42 | # 输出可执行文件 43 | BINDIR := ../../bin 44 | PROG := $(BINDIR)/sac2spec_cos 45 | 46 | # 伪目标 47 | .PHONY: all clean veryclean 48 | 49 | # 默认目标 50 | all: $(BINDIR) $(PROG) 51 | 52 | # 创建输出目录 53 | $(BINDIR): 54 | @mkdir -p $@ 55 | 56 | # 链接 57 | $(PROG): $(OBJS) $(CUDAOBJS) 58 | $(NVCC) $(NVCCFLAGS) -o $@ $^ $(LFLAG) 59 | 60 | # C 文件编译 61 | %.o: %.c 62 | $(CC) $(CFLAGS) -c $< -o $@ 63 | 64 | # CUDA 文件编译 65 | %.o: %.cu 66 | $(NVCC) $(NVCCFLAGS) -c $< -o $@ 67 | 68 | # 清理 69 | clean: 70 | @rm -f *.o 71 | 72 | veryclean: clean 73 | @rm -f $(PROG) 74 | -------------------------------------------------------------------------------- /src/sac2spec_cos/arguproc.h: -------------------------------------------------------------------------------- 1 | #ifndef _ARGU_PROC_H 2 | #define _ARGU_PROC_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "config.h" 9 | 10 | typedef struct ARGUTYPE 11 | { 12 | char *sac_lst; 13 | char *spec_lst; 14 | char *filter_file; 15 | float seglen; 16 | float freq_low; 17 | float freq_high; 18 | int num_ch; 19 | int gpu_id; 20 | int whitenType; 21 | int normalizeType; 22 | int skip_steps[MAX_SKIP_STEPS_SIZE]; 23 | int skip_step_count; 24 | int thread_num; 25 | int gpu_num; 26 | } ARGUTYPE; 27 | 28 | /* Parsing the input argument */ 29 | void ArgumentProcess(int argc, char **argv, ARGUTYPE *pargument); 30 | void usage(); 31 | #endif -------------------------------------------------------------------------------- /src/sac2spec_cos/cal_nseg.h: -------------------------------------------------------------------------------- 1 | #ifndef _CAL_NSEG_H_ 2 | #define _CAL_NSEG_H_ 3 | #include 4 | #include 5 | 6 | // Find the number of segment using npts and seglen, delta 7 | int cal_nseg(int seglen, int npts, float delta); 8 | 9 | #endif -------------------------------------------------------------------------------- /src/sac2spec_cos/complex.h: -------------------------------------------------------------------------------- 1 | #ifndef COMPLEX_H 2 | #define COMPLEX_H 3 | 4 | typedef struct 5 | { 6 | float x; 7 | float y; 8 | } complex; 9 | 10 | #endif -------------------------------------------------------------------------------- /src/sac2spec_cos/config.h: -------------------------------------------------------------------------------- 1 | #ifndef _config_h 2 | #define _config_h 3 | 4 | #define MAXLINE 8192 5 | #define MAXPATH 8192 6 | #define MAXKSTNM 2048 7 | #define MAXNAME 255 8 | #define MAXBAND 100 9 | #define MAX_SKIP_STEPS_SIZE 100 10 | #define _RISTRICT_MAX_GPU_BATCH 9999999 11 | #define _RISTRICT_MAX_CPU_BATCH 9999999 12 | #define MAXVAL 20 13 | #define MINVAL 1e-30 14 | #define TAPER_RATIO 3 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/sac2spec_cos/cuda.misc.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_MISC_CUH 2 | #define _CUDA_MISC_CUH 3 | #include "cuda.util.cuh" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | __global__ void abs2DKernel(float *d_data, size_t pitch, size_t width, 12 | size_t height); 13 | 14 | __global__ void clampmin2DKernel(float *d_data, size_t pitch, size_t width, 15 | size_t height, float minval); 16 | 17 | __global__ void onebit2DKernel(float *d_data, size_t pitch, size_t width, 18 | size_t height); 19 | 20 | __global__ void cutmax2DKernel(float *d_data, size_t pitch, size_t width, 21 | size_t height, float maxval); 22 | 23 | __global__ void isnan2DKernel(float *d_data, size_t pitch, size_t width, 24 | size_t height); 25 | 26 | __global__ void cisnan2DKernel(cuComplex *d_data, size_t pitch, size_t width, 27 | size_t height); 28 | 29 | __global__ void amp2DKernel(float *d_amp, size_t dpitch, cuComplex *d_data, 30 | size_t spitch, size_t width, size_t height); 31 | 32 | __global__ void div2DKernel(float *d_data, size_t dpitch, float *d_divisor, 33 | size_t spitch, size_t width, size_t height); 34 | 35 | __global__ void cdiv2DKernel(cuComplex *d_data, size_t dpitch, float *d_divisor, 36 | size_t spitch, size_t width, size_t height); 37 | 38 | __global__ void sum2DKernel(float *d_sum, size_t dpitch, float *d_in, 39 | size_t spitch, size_t width, size_t height); 40 | 41 | __global__ void filterKernel(cuComplex *d_spectrum, cuComplex *d_response, size_t pitch, size_t width, size_t height); 42 | 43 | __global__ void onebit2DKernel(float *d_data, size_t pitch, size_t width, size_t height); 44 | 45 | __global__ void FwdNormalize2DKernel(cuComplex *d_segspec, size_t pitch, size_t width, size_t height, float dt); 46 | 47 | __global__ void InvNormalize2DKernel(float *d_segdata, size_t pitch, size_t width, size_t height, float dt); 48 | 49 | __global__ void smooth2DKernel(float *d_out, int dpitch, float *d_tmp, int spitch, int width, int height, int winsize); 50 | 51 | __global__ void specTaper2DCosineKernel(cuComplex *d_segspec, size_t pitch, 52 | size_t width, size_t height, int np, 53 | int idx1, int idx2, int idx3, int idx4); 54 | 55 | #endif -------------------------------------------------------------------------------- /src/sac2spec_cos/cuda.processing.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CU_PRE_PROCESS_H_ 2 | #define _CU_PRE_PROCESS_H_ 3 | #include "cuda.util.cuh" 4 | #include "cuda.misc.cuh" 5 | #include "cuda.rdcrtr.cuh" 6 | #include "cuda.taper.cuh" 7 | 8 | void preprocess(float *d_sacdata, double *d_sum, double *d_isum, int pitch, size_t proccnt, int taper_percentage); 9 | 10 | void runabs_mf(float *d_sacdata, cuComplex *d_spectrum, 11 | float *d_filtered_sacdata, cuComplex *d_filtered_spectrum, 12 | cuComplex *d_responses, float *d_tmp, 13 | float *d_weight, float *d_tmp_weight, 14 | cufftHandle *planinv, float *freq_lows, 15 | float df, float *f1, float *f2, float *f3, float *f4, 16 | int filterCount, float delta, int proc_batch, int num_ch, int pitch, float maxval); 17 | 18 | void freqWhiten(cuComplex *d_spectrum, 19 | float *d_weight, float *d_tmp_weight, float *d_tmp, 20 | int num_ch, int pitch, int proc_batch, 21 | float delta, int idx1, int idx2, int idx3, int idx4); 22 | 23 | void runabs(float *d_sacdata, float *d_tmp, float *d_weight, float *d_tmp_weight, 24 | float freq_lows_limit, float delta, int proc_batch, int num_ch, int pitch, float maxval); 25 | 26 | #endif -------------------------------------------------------------------------------- /src/sac2spec_cos/cuda.rdcrtr.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_RDCRTR_CUH 2 | #define _CUDA_RDCRTR_CUH 3 | 4 | #include "cuda.util.cuh" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | __global__ void sumSingleBlock2DKernel(double *d_sum, int dpitch, 16 | const float *d_data, int spitch, 17 | int width, int height); 18 | 19 | __global__ void isumSingleBlock2DKernel(double *d_isum, int dpitch, 20 | const float *d_data, int spitch, 21 | int width, int height); 22 | 23 | __global__ void rdc2DKernel(float *d_data, int pitch, int width, int height, 24 | double *d_sum); 25 | 26 | __global__ void rtr2DKernel(float *d_data, int pitch, int width, int height, 27 | double *d_sum, double *d_isum); 28 | 29 | #endif -------------------------------------------------------------------------------- /src/sac2spec_cos/cuda.taper.cu: -------------------------------------------------------------------------------- 1 | #include "cuda.taper.cuh" 2 | 3 | // The width of taper is nfft+1 4 | __global__ void specTaper2DKernel(cuComplex *d_segspec, size_t pitch, 5 | size_t width, size_t height, int np, 6 | int idx1, int idx2, int idx3, int idx4) 7 | { 8 | size_t col = blockIdx.x * blockDim.x + threadIdx.x; 9 | size_t row = blockIdx.y * blockDim.y + threadIdx.y; 10 | 11 | // Ensure that the index does not exceed th Nyquist frequency 12 | idx4 = idx4 < width ? idx4 : width; 13 | 14 | double dom, factor; 15 | int ntrans, j; 16 | 17 | if (col < width && row < height) 18 | { 19 | size_t idx = row * pitch + col; 20 | 21 | // we zero DC and nyquist freq up to f1 22 | if (col < idx1) 23 | { 24 | d_segspec[idx].x = 0.0; 25 | d_segspec[idx].y = 0.0; 26 | } 27 | // left low freq 28 | else if (col >= idx1 && col < idx2) 29 | { 30 | ntrans = idx2 - idx1; 31 | dom = M_PI / ntrans; 32 | 33 | factor = 1.0; 34 | for (j = 0; j < np; j++) 35 | { 36 | factor = factor * (1.0 - cos(dom * (col - idx1))) / 2.0; 37 | } 38 | d_segspec[idx].x = d_segspec[idx].x * factor; 39 | d_segspec[idx].y = d_segspec[idx].y * factor; 40 | } 41 | 42 | // idx2 to idx3 is flat 43 | 44 | // right high freq 45 | else if (col >= idx3 && col < idx4) 46 | { 47 | ntrans = idx4 - idx3; 48 | dom = M_PI / ntrans; 49 | 50 | factor = 1.0; 51 | for (j = 0; j < np; j++) 52 | { 53 | factor = factor * (1.0 + cos(dom * (col - idx3))) / 2.0; 54 | } 55 | d_segspec[idx].x = d_segspec[idx].x * factor; 56 | d_segspec[idx].y = d_segspec[idx].y * factor; 57 | } 58 | // higher freq are zero 59 | else if (col >= idx4 && col < width) 60 | { 61 | d_segspec[idx].x = 0.0; 62 | d_segspec[idx].y = 0.0; 63 | } 64 | } 65 | } 66 | 67 | __global__ void timetaper2DKernel(float *d_data, int pitch, int width, int height, int taper_size) 68 | { 69 | int col = blockIdx.x * blockDim.x + threadIdx.x; 70 | int row = blockIdx.y * blockDim.y + threadIdx.y; 71 | 72 | if (col < width && row < height) 73 | { 74 | size_t idx = row * pitch + col; 75 | 76 | // Apply the taper to the beginning and end of the signal. 77 | float factor = 1.0; 78 | if (col < taper_size) 79 | { 80 | factor = 0.5 * (1.0 - cos(M_PI * col / taper_size)); 81 | } 82 | else if (col >= width - taper_size) 83 | { 84 | factor = 0.5 * (1.0 - cos(M_PI * (width - col) / taper_size)); 85 | } 86 | else 87 | { 88 | factor = 1.0; 89 | } 90 | // Apply the taper to the signal. 91 | d_data[idx] *= factor; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/sac2spec_cos/cuda.taper.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_TAPER_H 2 | #define _CUDA_TAPER_H 3 | #include 4 | #include "config.h" 5 | #include "cuda.util.cuh" 6 | 7 | __global__ void specTaper2DKernel(cuComplex *d_segspec, size_t pitch, 8 | size_t width, size_t height, int np, 9 | int idx1, int idx2, int idx3, int idx4); 10 | 11 | __global__ void timetaper2DKernel(float *d_data, int pitch, int width, int height, int taper_size); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/sac2spec_cos/cuda.util.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_UTIL_CUH 2 | #define _CUDA_UTIL_CUH 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "config.h" 9 | #define BLOCKX 32 10 | #define BLOCKY 32 11 | #define BLOCKMAX 1024 12 | 13 | #define CUDACHECK(cmd) \ 14 | do \ 15 | { \ 16 | cudaError_t e = cmd; \ 17 | if (e != cudaSuccess) \ 18 | { \ 19 | printf("Failed: Cuda error %s:%d '%s'\n", \ 20 | __FILE__, __LINE__, cudaGetErrorString(e)); \ 21 | exit(EXIT_FAILURE); \ 22 | } \ 23 | } while (0) 24 | 25 | #define CUFFTCHECK(cmd) \ 26 | do \ 27 | { \ 28 | cufftResult_t e = cmd; \ 29 | if (e != CUFFT_SUCCESS) \ 30 | { \ 31 | printf("Failed: CuFFT error %s:%d %d\n", \ 32 | __FILE__, __LINE__, e); \ 33 | exit(EXIT_FAILURE); \ 34 | } \ 35 | } while (0) 36 | 37 | /* Compute the block and dimension for cuda kernel fucntion*/ 38 | void DimCompute(dim3 *, dim3 *, size_t, size_t); 39 | 40 | /* Free cuda pointer */ 41 | void GpuFree(void **pptr); 42 | 43 | /* Get the infomation of available GPU ram of a certain device */ 44 | size_t QueryAvailGpuRam(size_t); 45 | 46 | /* Estimate the batch of processing data */ 47 | size_t EstimateGpuBatch(size_t gpu_id, int npts, int nseg, int nstep, int num_ch, 48 | int filter_count, size_t wh_flag, size_t runabs_flag); 49 | 50 | /* Allocating Memory of Processing data */ 51 | void AllocateGpuMemory(int batch, int nseg, int num_ch, 52 | int do_runabs, int wh_flag, 53 | float **d_sacdata, cuComplex **d_spectrum, 54 | float **d_sacdata_2x, cuComplex **d_spectrum_2x, 55 | float **d_filtered_sacdata, cuComplex **d_filtered_spectrum, 56 | cuComplex **d_filter_responses, float **d_tmp, 57 | float **d_weight, float **d_tmp_weight, 58 | int filterCount, double **d_sum, double **d_isum, 59 | cufftHandle *planfwd, cufftHandle *planinv, cufftHandle *planfwd_2x); 60 | 61 | #endif -------------------------------------------------------------------------------- /src/sac2spec_cos/design_filter_response.h: -------------------------------------------------------------------------------- 1 | #ifndef _DESIGN_RESPONSE_H_ 2 | #define _DESIGN_RESPONSE_H_ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "complex.h" 8 | 9 | typedef struct ButterworthFilter 10 | { 11 | float freq_low; 12 | float freq_high; 13 | double b[5]; /* Numerator coefficients */ 14 | double a[5]; /* Denominator coefficients */ 15 | } ButterworthFilter; 16 | 17 | typedef struct FilterResp 18 | { 19 | float freq_low; // lower frequency 20 | complex *response; // filter response 21 | } FilterResp; 22 | 23 | int parseCoefficientsLine(char *line, double *coefficients); 24 | 25 | ButterworthFilter *readButterworthFilters(const char *filepath, int *filterCount); 26 | 27 | void printButterworthFilters(const ButterworthFilter *filters, int filterCount); 28 | 29 | void calFilterResp(double *b, double *a, int nseg, complex *response); 30 | 31 | FilterResp *processButterworthFilters(ButterworthFilter *filters, int filterCount, float df_1x, int nseg); 32 | 33 | #endif -------------------------------------------------------------------------------- /src/sac2spec_cos/in_out_node.h: -------------------------------------------------------------------------------- 1 | #ifndef _IN_OUT_NODE_H 2 | #define _IN_OUT_NODE_H 3 | #include "sac.h" 4 | #include 5 | #include "complex.h" 6 | #include "segspec.h" 7 | 8 | typedef struct InOutNode 9 | { 10 | char *sacpath; 11 | 12 | char *specpath; 13 | 14 | float *sac_data; 15 | 16 | SACHEAD *sac_hd; 17 | SEGSPEC *segspec_hd; 18 | 19 | complex *spectrum; 20 | 21 | float nstep; 22 | float nspec; 23 | float df; 24 | float dt; 25 | } InOutNode; 26 | 27 | typedef struct PathNode 28 | { 29 | char *path; 30 | struct PathNode *next; 31 | } PathNode; 32 | 33 | typedef struct FilePathArray 34 | { 35 | char **paths; 36 | int count; 37 | } FilePathArray; 38 | #endif -------------------------------------------------------------------------------- /src/sac2spec_cos/par_rw_data.h: -------------------------------------------------------------------------------- 1 | #ifndef _PARALLEL_RW_DATA_H_ 2 | #define _PARALLEL_RW_DATA_H_ 3 | #include 4 | #include 5 | #include 6 | #include "in_out_node.h" 7 | #include "sac.h" 8 | 9 | typedef struct thread_info_read 10 | { 11 | int start; 12 | int end; 13 | InOutNode *InOutList; 14 | } thread_info_read; 15 | 16 | typedef struct ThreadPoolRead 17 | { 18 | pthread_t *threads; 19 | thread_info_read *tinfo; 20 | size_t num_threads; 21 | } ThreadPoolRead; 22 | 23 | typedef struct thread_info_write 24 | { 25 | size_t start; 26 | size_t end; 27 | InOutNode *InOutList; 28 | } thread_info_write; 29 | 30 | typedef struct ThreadPoolWrite 31 | { 32 | pthread_t *threads; 33 | thread_info_write *tinfo; 34 | size_t num_threads; 35 | } ThreadPoolWrite; 36 | 37 | ThreadPoolRead *create_threadpool_read(size_t num_threads); 38 | 39 | ThreadPoolWrite *create_threadpool_write(size_t num_threads); 40 | 41 | int parallel_read_sac(ThreadPoolRead *pool, size_t proccnt, InOutNode *pInOutList, int num_threads); 42 | 43 | int parallel_write_spec(ThreadPoolWrite *pool, size_t h_proccnt, InOutNode *pInOutList, int num_threads); 44 | 45 | void destroy_threadpool_read(ThreadPoolRead *pool); 46 | 47 | void destroy_threadpool_write(ThreadPoolWrite *pool); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/sac2spec_cos/read_filelist.h: -------------------------------------------------------------------------------- 1 | #ifndef _PATHLIST_H_ 2 | #define _PATHLIST_H_ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "in_out_node.h" 10 | #include "config.h" 11 | #include "util.h" 12 | 13 | /* Read in a file which each line is a sac file */ 14 | PathNode *readPathList(const char *filename); 15 | 16 | /* Create directory in a recursiveS way */ 17 | void createDirectoryRecursively(char *dir); 18 | 19 | /* Create directory using a path list */ 20 | void createDirectories(PathNode *pathList); 21 | 22 | /* Convert PathList to Array */ 23 | FilePathArray PathList2Array(PathNode *head); 24 | 25 | #endif -------------------------------------------------------------------------------- /src/sac2spec_cos/readme.txt: -------------------------------------------------------------------------------- 1 | /* ************************************************************ 2 | * Jobs of this code are 3 | * 1. read in three component SAC data 4 | * 2. split the whole data into segments 5 | * 3. do runabs time normalization and spectrum whitenning forof E,N,Z data. 6 | * 7 | * the weight used as the divisor is calculated using all three components 8 | * both in time domain normalization and frequency domain whitenning. 9 | * 10 | * 4. save spectrum of each segments and write to one file. 11 | * 12 | * The output would be segment-spectrum file which will be used later to calculate the noise 13 | * cross correlation. 14 | * 15 | * The information of segment and spectrum is saved in the header of each file which can be 16 | * found in segspec.h 17 | * 18 | * Calculated segment spectrum first would require more disk usage but may speed up the Cross 19 | * Correlation when you have huge dataset eg too many stations. 20 | * 21 | * Note: 22 | * History: 23 | * 1. init by wangwt@2015 24 | 25 | * Cuda Version Histroy 26 | * 27 | * 1. init by wangjx with the thread distrubution strategy made by wuchao 28 | * 2. use 2d cuda threads to perform batch processing of list of sac files, 29 | * X: segments of one sacfile, Y:list of sacfiles by wuchao@2021 30 | * 3. use cuda to implement rdc rtr npsmooth spectaper and etc by wuchao@2021 wangjx@2021,2022 31 | * 4. use cufft to perform FFT/IFFT transform by wuchao@2021 32 | * last updated by wangjx@20230703 33 | * *****************************************************************/ -------------------------------------------------------------------------------- /src/sac2spec_cos/segspec.h: -------------------------------------------------------------------------------- 1 | /* Header for the segment by segment spectrum for noise cross correlation 2 | * History: 3 | * 1. init by wangwt to speed up CC on huge dataset. 4 | * 5 | * last update wangjx@20230514 6 | * */ 7 | 8 | #ifndef _SEGSPEC_H 9 | #define _SEGSPEC_H 10 | 11 | typedef struct segspec_s 12 | { 13 | float stla; 14 | float stlo; 15 | /* segment info */ 16 | int nstep; 17 | /* FFT info */ 18 | int nspec; /* use fftr() number of complex eg 2*nspec float */ 19 | float df; 20 | float dt; 21 | } SEGSPEC; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/sac2spec_cos/util.c: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | 3 | const float RAMUPPERBOUND = 0.8; 4 | 5 | size_t QueryAvailCpuRam() 6 | { 7 | const size_t LINEMAX = 256; 8 | const size_t KILOBYTES = 1L << 10; 9 | // const size_t GIGABYTES = 1L << 30; 10 | struct sysinfo sinfo; 11 | char buffer[LINEMAX]; 12 | 13 | FILE *fid = fopen("/proc/meminfo", "r"); 14 | 15 | size_t availram = 0; 16 | 17 | while (fgets(buffer, LINEMAX, fid) != NULL) 18 | { 19 | if (strstr(buffer, "MemAvailable") != NULL) 20 | { 21 | sscanf(buffer, "MemAvailable: %lu kB", &availram); 22 | availram *= KILOBYTES; /* kB -> B */ 23 | availram *= RAMUPPERBOUND; 24 | } 25 | } 26 | fclose(fid); 27 | 28 | /* In Linux sysinfo's free ram is far smaller than available ram 29 | * Use this in condition that cannot find Memavailble in /proc/meminfo 30 | */ 31 | if (availram == 0) 32 | { 33 | int err = sysinfo(&sinfo); 34 | if (err != 0) 35 | { 36 | perror("Get sys info\n"); 37 | exit(-1); 38 | } 39 | availram = sinfo.freeram; 40 | } 41 | 42 | return availram; 43 | } 44 | 45 | size_t EstimateCpuBatch(size_t unitRam, int thread_num) 46 | { 47 | // Query available CPU RAM 48 | size_t availableRam = QueryAvailCpuRam() / thread_num; 49 | const size_t GIGABYTES = 1L << 30; 50 | printf("Avail cpu ram: %.3f GB\n", availableRam * 1.0 / GIGABYTES); 51 | // Initialize batch count and required RAM 52 | size_t batch = 0; 53 | size_t requiredRam = 0; 54 | 55 | // Keep increasing the batch count until required RAM exceeds available RAM 56 | while (requiredRam < availableRam) 57 | { 58 | // Increment the batch count 59 | batch++; 60 | 61 | // Update the required RAM based on the new batch count 62 | requiredRam = batch * unitRam; 63 | } 64 | 65 | // Decrease the batch count by 1 since the last increment caused required RAM 66 | // to exceed available RAM 67 | batch--; 68 | batch = batch > _RISTRICT_MAX_CPU_BATCH ? _RISTRICT_MAX_CPU_BATCH : batch; 69 | // Return the estimated batch count 70 | return batch; 71 | } 72 | 73 | void CpuMalloc(void **pptr, size_t sz) 74 | { 75 | if ((*pptr = malloc(sz)) == NULL) 76 | { 77 | perror("Malloc cpu memory"); 78 | exit(-1); 79 | } 80 | } 81 | 82 | void CpuFree(void **pptr) 83 | { 84 | free(*pptr); 85 | *pptr = NULL; 86 | } 87 | 88 | // in case some old compiler cannot deal with strdup 89 | char *my_strdup(const char *s) 90 | { 91 | if (s == NULL) 92 | { 93 | return NULL; 94 | } 95 | char *new_str = (char *)malloc(strlen(s) + 1); 96 | if (new_str == NULL) 97 | { 98 | return NULL; 99 | } 100 | char *p = new_str; 101 | while (*s) 102 | { 103 | *p++ = *s++; 104 | } 105 | *p = '\0'; 106 | return new_str; 107 | } 108 | -------------------------------------------------------------------------------- /src/sac2spec_cos/util.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTIL_H 2 | #define _UTIL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "config.h" 9 | 10 | size_t QueryAvailCpuRam(); 11 | size_t EstimateCpuBatch(size_t unitRam, int thread_num); 12 | void CpuMalloc(void **, size_t); 13 | void CpuFree(void **); 14 | char* my_strdup(const char* s); 15 | #endif -------------------------------------------------------------------------------- /src/sac2spec_super/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.c": "c", 4 | "arguproc.h": "c", 5 | "in_out_node_c9.h": "c", 6 | "complex": "cpp" 7 | } 8 | } -------------------------------------------------------------------------------- /src/sac2spec_super/Makefile: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------- 2 | # sac2spec_super ‒ 子目录 Makefile 3 | # • 顶层递归调用 → Release (-O3, --generate-line-info) 4 | # • 手动进入目录 make → Debug (-O0 -g -G -lineinfo) 5 | # ---------------------------------------------------- 6 | 7 | # 编译器 8 | CC ?= gcc 9 | NVCC ?= /usr/local/cuda/bin/nvcc 10 | ARCH ?= sm_89 11 | WARN ?= -Wall 12 | 13 | # ---------- 优化级别自动切换 ---------- 14 | ifeq ($(MAKELEVEL),0) # 手动调试 15 | CFLAGS ?= -O0 -g $(WARN) 16 | NVCCFLAGS ?= -g -G -lineinfo -arch=$(ARCH) 17 | else # 顶层批量构建 18 | CFLAGS ?= -O3 $(WARN) 19 | NVCCFLAGS ?= -O3 --generate-line-info -arch=$(ARCH) 20 | endif 21 | # ------------------------------------- 22 | 23 | # 链接库 24 | LFLAG = -L/usr/local/cuda/lib64 -lcufft -lcudart -lm 25 | 26 | # 源文件 27 | CUDAOBJS = cuda.rdcrtr.o \ 28 | cuda.util.o \ 29 | cuda.misc.o \ 30 | cuda.processing.o \ 31 | cuda.taper.o \ 32 | cuda.main.o 33 | 34 | OBJS = design_filter_response.o \ 35 | arguproc.o \ 36 | cal_nseg.o \ 37 | par_rw_data.o \ 38 | read_filelist.o \ 39 | sacio.o \ 40 | util.o 41 | 42 | # 输出可执行文件 43 | BINDIR := ../../bin 44 | PROG := $(BINDIR)/sac2spec_super 45 | 46 | # 伪目标 47 | .PHONY: all clean veryclean 48 | 49 | # 默认目标 50 | all: $(BINDIR) $(PROG) 51 | 52 | # 创建输出目录 53 | $(BINDIR): 54 | @mkdir -p $@ 55 | 56 | # 链接 57 | $(PROG): $(OBJS) $(CUDAOBJS) 58 | $(NVCC) $(NVCCFLAGS) -o $@ $^ $(LFLAG) 59 | 60 | # C 文件编译 61 | %.o: %.c 62 | $(CC) $(CFLAGS) -c $< -o $@ 63 | 64 | # CUDA 文件编译 65 | %.o: %.cu 66 | $(NVCC) $(NVCCFLAGS) -c $< -o $@ 67 | 68 | # 清理 69 | clean: 70 | @rm -f *.o 71 | 72 | veryclean: clean 73 | @rm -f $(PROG) 74 | -------------------------------------------------------------------------------- /src/sac2spec_super/arguproc.h: -------------------------------------------------------------------------------- 1 | #ifndef _ARGU_PROC_H 2 | #define _ARGU_PROC_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "config.h" 9 | 10 | typedef struct ARGUTYPE 11 | { 12 | char *sac_lst; 13 | char *spec_lst; 14 | char *filter_file; 15 | float seglen; 16 | float freq_low; 17 | float freq_high; 18 | int num_ch; 19 | int gpu_id; 20 | int whitenType; 21 | int normalizeType; 22 | int skip_steps[MAX_SKIP_STEPS_SIZE]; 23 | int skip_step_count; 24 | int thread_num; 25 | int gpu_num; 26 | } ARGUTYPE; 27 | 28 | /* Parsing the input argument */ 29 | void ArgumentProcess(int argc, char **argv, ARGUTYPE *pargument); 30 | void usage(); 31 | #endif -------------------------------------------------------------------------------- /src/sac2spec_super/cal_nseg.h: -------------------------------------------------------------------------------- 1 | #ifndef _CAL_NSEG_H_ 2 | #define _CAL_NSEG_H_ 3 | #include 4 | #include 5 | 6 | // Find the number of segment using npts and seglen, delta 7 | int cal_nseg(int seglen, int npts, float delta); 8 | 9 | #endif -------------------------------------------------------------------------------- /src/sac2spec_super/complex.h: -------------------------------------------------------------------------------- 1 | #ifndef COMPLEX_H 2 | #define COMPLEX_H 3 | 4 | typedef struct 5 | { 6 | float x; 7 | float y; 8 | } complex; 9 | 10 | #endif -------------------------------------------------------------------------------- /src/sac2spec_super/config.h: -------------------------------------------------------------------------------- 1 | #ifndef _config_h 2 | #define _config_h 3 | 4 | #define MAXLINE 8192 5 | #define MAXPATH 8192 6 | #define MAXKSTNM 2048 7 | #define MAXNAME 255 8 | #define MAXBAND 100 9 | #define MAX_SKIP_STEPS_SIZE 100 10 | #define _RISTRICT_MAX_GPU_BATCH 9999999 11 | #define _RISTRICT_MAX_CPU_BATCH 9999999 12 | #define MAXVAL 20 13 | #define MINVAL 1e-30 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/sac2spec_super/cuda.misc.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_MISC_CUH 2 | #define _CUDA_MISC_CUH 3 | #include "cuda.util.cuh" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | __global__ void abs2DKernel(float *d_data, size_t pitch, size_t width, 12 | size_t height); 13 | 14 | __global__ void clampmin2DKernel(float *d_data, size_t pitch, size_t width, 15 | size_t height, float minval); 16 | 17 | __global__ void onebit2DKernel(float *d_data, size_t pitch, size_t width, 18 | size_t height); 19 | 20 | __global__ void cutmax2DKernel(float *d_data, size_t pitch, size_t width, 21 | size_t height, float maxval); 22 | 23 | __global__ void isnan2DKernel(float *d_data, size_t pitch, size_t width, 24 | size_t height); 25 | 26 | __global__ void cisnan2DKernel(cuComplex *d_data, size_t pitch, size_t width, 27 | size_t height); 28 | 29 | __global__ void amp2DKernel(float *d_amp, size_t dpitch, cuComplex *d_data, 30 | size_t spitch, size_t width, size_t height); 31 | 32 | __global__ void div2DKernel(float *d_data, size_t dpitch, float *d_divisor, 33 | size_t spitch, size_t width, size_t height); 34 | 35 | __global__ void cdiv2DKernel(cuComplex *d_data, size_t dpitch, float *d_divisor, 36 | size_t spitch, size_t width, size_t height); 37 | 38 | __global__ void sum2DKernel(float *d_sum, size_t dpitch, float *d_in, 39 | size_t spitch, size_t width, size_t height); 40 | 41 | __global__ void filterKernel(cuComplex *d_spectrum, cuComplex *d_response, size_t pitch, size_t width, size_t height); 42 | 43 | __global__ void onebit2DKernel(float *d_data, size_t pitch, size_t width, size_t height); 44 | 45 | __global__ void FwdNormalize2DKernel(cuComplex *d_segspec, size_t pitch, size_t width, size_t height, float dt); 46 | 47 | __global__ void InvNormalize2DKernel(float *d_segdata, size_t pitch, size_t width, size_t height, float dt); 48 | 49 | __global__ void smooth2DKernel(float *d_out, int dpitch, float *d_tmp, int spitch, int width, int height, int winsize); 50 | 51 | #endif -------------------------------------------------------------------------------- /src/sac2spec_super/cuda.processing.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CU_PRE_PROCESS_H_ 2 | #define _CU_PRE_PROCESS_H_ 3 | #include "cuda.util.cuh" 4 | #include "cuda.misc.cuh" 5 | #include "cuda.rdcrtr.cuh" 6 | #include "cuda.taper.cuh" 7 | 8 | void preprocess(float *d_sacdata, double *d_sum, double *d_isum, int pitch, size_t proccnt, float freq_low, float delta); 9 | 10 | void runabs_mf(float *d_sacdata, float *d_filtered_sacdata, float *d_total_sacdata, 11 | float *d_sacdata_2x, cuComplex *d_spectrum_2x, 12 | cuComplex *d_responses, float *d_tmp, 13 | float *d_weight, float *d_tmp_weight, 14 | cufftHandle *planinv, float *freq_lows, 15 | int filterCount, float delta, int proc_batch, int num_ch, float maxval, 16 | int nseg_1x, int nseg_2x, cufftHandle *planinv_2x, cufftHandle *planfwd_2x); 17 | 18 | void freqWhiten(cuComplex *d_spectrum, 19 | float *d_weight, float *d_tmp_weight, float *d_tmp, 20 | int num_ch, int pitch, int proc_batch, 21 | float delta, int idx1, int idx2, int idx3, int idx4); 22 | 23 | void runabs(float *d_sacdata, float *d_tmp, float *d_weight, float *d_tmp_weight, 24 | float freq_lows_limit, float delta, int proc_batch, int num_ch, int pitch, float maxval); 25 | 26 | #endif -------------------------------------------------------------------------------- /src/sac2spec_super/cuda.rdcrtr.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_RDCRTR_CUH 2 | #define _CUDA_RDCRTR_CUH 3 | 4 | #include "cuda.util.cuh" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | __global__ void sumSingleBlock2DKernel(double *d_sum, int dpitch, 16 | const float *d_data, int spitch, 17 | int width, int height); 18 | 19 | __global__ void isumSingleBlock2DKernel(double *d_isum, int dpitch, 20 | const float *d_data, int spitch, 21 | int width, int height); 22 | 23 | __global__ void rdc2DKernel(float *d_data, int pitch, int width, int height, 24 | double *d_sum); 25 | 26 | __global__ void rtr2DKernel(float *d_data, int pitch, int width, int height, 27 | double *d_sum, double *d_isum); 28 | 29 | #endif -------------------------------------------------------------------------------- /src/sac2spec_super/cuda.taper.cu: -------------------------------------------------------------------------------- 1 | #include "cuda.taper.cuh" 2 | 3 | // The width of taper is nfft+1 4 | __global__ void specTaper2DKernel(cuComplex *d_segspec, size_t pitch, 5 | size_t width, size_t height, int np, 6 | int idx1, int idx2, int idx3, int idx4) 7 | { 8 | size_t col = blockIdx.x * blockDim.x + threadIdx.x; 9 | size_t row = blockIdx.y * blockDim.y + threadIdx.y; 10 | 11 | // Ensure that the index does not exceed th Nyquist frequency 12 | idx4 = idx4 < width ? idx4 : width; 13 | 14 | double dom, factor; 15 | int ntrans, j; 16 | 17 | if (col < width && row < height) 18 | { 19 | size_t idx = row * pitch + col; 20 | 21 | // we zero DC and nyquist freq up to f1 22 | if (col < idx1) 23 | { 24 | d_segspec[idx].x = 0.0; 25 | d_segspec[idx].y = 0.0; 26 | } 27 | // left low freq 28 | else if (col >= idx1 && col < idx2) 29 | { 30 | ntrans = idx2 - idx1; 31 | dom = M_PI / ntrans; 32 | 33 | factor = 1.0; 34 | for (j = 0; j < np; j++) 35 | { 36 | factor = factor * (1.0 - cos(dom * (col - idx1))) / 2.0; 37 | } 38 | d_segspec[idx].x = d_segspec[idx].x * factor; 39 | d_segspec[idx].y = d_segspec[idx].y * factor; 40 | } 41 | 42 | // idx2 to idx3 is flat 43 | 44 | // right high freq 45 | else if (col >= idx3 && col < idx4) 46 | { 47 | ntrans = idx4 - idx3; 48 | dom = M_PI / ntrans; 49 | 50 | factor = 1.0; 51 | for (j = 0; j < np; j++) 52 | { 53 | factor = factor * (1.0 + cos(dom * (col - idx3))) / 2.0; 54 | } 55 | d_segspec[idx].x = d_segspec[idx].x * factor; 56 | d_segspec[idx].y = d_segspec[idx].y * factor; 57 | } 58 | // higher freq are zero 59 | else if (col >= idx4 && col < width) 60 | { 61 | d_segspec[idx].x = 0.0; 62 | d_segspec[idx].y = 0.0; 63 | } 64 | } 65 | } 66 | 67 | __global__ void timetaper2DKernel(float *d_data, int pitch, int width, int height, int taper_size) 68 | { 69 | int col = blockIdx.x * blockDim.x + threadIdx.x; 70 | int row = blockIdx.y * blockDim.y + threadIdx.y; 71 | 72 | if (col < width && row < height) 73 | { 74 | size_t idx = row * pitch + col; 75 | 76 | // Apply the taper to the beginning and end of the signal. 77 | float factor = 1.0; 78 | if (col < taper_size) 79 | { 80 | factor = 0.5 * (1.0 - cos(M_PI * col / taper_size)); 81 | } 82 | else if (col >= width - taper_size) 83 | { 84 | factor = 0.5 * (1.0 - cos(M_PI * (width - col) / taper_size)); 85 | } 86 | else 87 | { 88 | factor = 1.0; 89 | } 90 | // Apply the taper to the signal. 91 | d_data[idx] *= factor; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/sac2spec_super/cuda.taper.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_TAPER_H 2 | #define _CUDA_TAPER_H 3 | #include 4 | #include "config.h" 5 | #include "cuda.util.cuh" 6 | 7 | __global__ void specTaper2DKernel(cuComplex *d_segspec, size_t pitch, 8 | size_t width, size_t height, int np, 9 | int idx1, int idx2, int idx3, int idx4); 10 | 11 | __global__ void timetaper2DKernel(float *d_data, int pitch, int width, int height, int taper_size); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/sac2spec_super/cuda.util.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_UTIL_CUH 2 | #define _CUDA_UTIL_CUH 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "config.h" 9 | #define BLOCKX 32 10 | #define BLOCKY 32 11 | #define BLOCKMAX 1024 12 | 13 | #define CUDACHECK(cmd) \ 14 | do \ 15 | { \ 16 | cudaError_t e = cmd; \ 17 | if (e != cudaSuccess) \ 18 | { \ 19 | printf("Failed: Cuda error %s:%d '%s'\n", \ 20 | __FILE__, __LINE__, cudaGetErrorString(e)); \ 21 | exit(EXIT_FAILURE); \ 22 | } \ 23 | } while (0) 24 | 25 | #define CUFFTCHECK(cmd) \ 26 | do \ 27 | { \ 28 | cufftResult_t e = cmd; \ 29 | if (e != CUFFT_SUCCESS) \ 30 | { \ 31 | printf("Failed: CuFFT error %s:%d %d\n", \ 32 | __FILE__, __LINE__, e); \ 33 | exit(EXIT_FAILURE); \ 34 | } \ 35 | } while (0) 36 | 37 | /* Compute the block and dimension for cuda kernel fucntion*/ 38 | void DimCompute(dim3 *, dim3 *, size_t, size_t); 39 | 40 | /* Free cuda pointer */ 41 | void GpuFree(void **pptr); 42 | 43 | /* Get the infomation of available GPU ram of a certain device */ 44 | size_t QueryAvailGpuRam(size_t); 45 | 46 | /* Estimate the batch of processing data */ 47 | size_t EstimateGpuBatch(size_t gpu_id, int npts, int nseg, int nstep, int num_ch, 48 | int filter_count, size_t wh_flag, size_t runabs_flag); 49 | 50 | /* Allocating Memory of Processing data */ 51 | void AllocateGpuMemory(int batch, int nseg, int num_ch, 52 | int do_runabs, int wh_flag, 53 | float **d_sacdata, cuComplex **d_spectrum, 54 | float **d_sacdata_2x, cuComplex **d_spectrum_2x, 55 | float **d_filtered_sacdata, 56 | float **d_total_sacdata, 57 | cuComplex **d_filter_responses, float **d_tmp, 58 | float **d_weight, float **d_tmp_weight, 59 | int filterCount, double **d_sum, double **d_isum, 60 | cufftHandle *planfwd, cufftHandle *planinv, 61 | cufftHandle *planfwd_2x, cufftHandle *planinv_2x); 62 | 63 | #endif -------------------------------------------------------------------------------- /src/sac2spec_super/design_filter_response.h: -------------------------------------------------------------------------------- 1 | #ifndef _DESIGN_RESPONSE_H_ 2 | #define _DESIGN_RESPONSE_H_ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "complex.h" 8 | 9 | typedef struct ButterworthFilter 10 | { 11 | float freq_low; 12 | float freq_high; 13 | double b[5]; /* Numerator coefficients */ 14 | double a[5]; /* Denominator coefficients */ 15 | } ButterworthFilter; 16 | 17 | typedef struct FilterResp 18 | { 19 | float freq_low; // lower frequency 20 | complex *response; // filter response 21 | } FilterResp; 22 | 23 | int parseCoefficientsLine(char *line, double *coefficients); 24 | 25 | ButterworthFilter *readButterworthFilters(const char *filepath, int *filterCount); 26 | 27 | void printButterworthFilters(const ButterworthFilter *filters, int filterCount); 28 | 29 | void calFilterResp(double *b, double *a, int nseg, complex *response); 30 | 31 | FilterResp *processButterworthFilters(ButterworthFilter *filters, int filterCount, float df_2x, int nseg_2x); 32 | 33 | #endif -------------------------------------------------------------------------------- /src/sac2spec_super/in_out_node.h: -------------------------------------------------------------------------------- 1 | #ifndef _IN_OUT_NODE_H 2 | #define _IN_OUT_NODE_H 3 | #include "sac.h" 4 | #include 5 | #include "complex.h" 6 | #include "segspec.h" 7 | 8 | typedef struct InOutNode 9 | { 10 | char *sacpath; 11 | 12 | char *specpath; 13 | 14 | float *sac_data; 15 | 16 | SACHEAD *sac_hd; 17 | SEGSPEC *segspec_hd; 18 | 19 | complex *spectrum; 20 | 21 | float nstep; 22 | float nspec; 23 | float df; 24 | float dt; 25 | } InOutNode; 26 | 27 | typedef struct PathNode 28 | { 29 | char *path; 30 | struct PathNode *next; 31 | } PathNode; 32 | 33 | typedef struct FilePathArray 34 | { 35 | char **paths; 36 | int count; 37 | } FilePathArray; 38 | #endif -------------------------------------------------------------------------------- /src/sac2spec_super/par_rw_data.h: -------------------------------------------------------------------------------- 1 | #ifndef _PARALLEL_RW_DATA_H_ 2 | #define _PARALLEL_RW_DATA_H_ 3 | #include 4 | #include 5 | #include 6 | #include "in_out_node.h" 7 | #include "sac.h" 8 | 9 | typedef struct thread_info_read 10 | { 11 | int start; 12 | int end; 13 | InOutNode *InOutList; 14 | } thread_info_read; 15 | 16 | typedef struct ThreadPoolRead 17 | { 18 | pthread_t *threads; 19 | thread_info_read *tinfo; 20 | size_t num_threads; 21 | } ThreadPoolRead; 22 | 23 | typedef struct thread_info_write 24 | { 25 | size_t start; 26 | size_t end; 27 | InOutNode *InOutList; 28 | } thread_info_write; 29 | 30 | typedef struct ThreadPoolWrite 31 | { 32 | pthread_t *threads; 33 | thread_info_write *tinfo; 34 | size_t num_threads; 35 | } ThreadPoolWrite; 36 | 37 | ThreadPoolRead *create_threadpool_read(size_t num_threads); 38 | 39 | ThreadPoolWrite *create_threadpool_write(size_t num_threads); 40 | 41 | int parallel_read_sac(ThreadPoolRead *pool, size_t proccnt, InOutNode *pInOutList, int num_threads); 42 | 43 | int parallel_write_spec(ThreadPoolWrite *pool, size_t h_proccnt, InOutNode *pInOutList, int num_threads); 44 | 45 | void destroy_threadpool_read(ThreadPoolRead *pool); 46 | 47 | void destroy_threadpool_write(ThreadPoolWrite *pool); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/sac2spec_super/read_filelist.h: -------------------------------------------------------------------------------- 1 | #ifndef _PATHLIST_H_ 2 | #define _PATHLIST_H_ 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "in_out_node.h" 10 | #include "config.h" 11 | #include "util.h" 12 | 13 | /* Read in a file which each line is a sac file */ 14 | PathNode *readPathList(const char *filename); 15 | 16 | /* Create directory in a recursiveS way */ 17 | void createDirectoryRecursively(char *dir); 18 | 19 | /* Create directory using a path list */ 20 | void createDirectories(PathNode *pathList); 21 | 22 | /* Convert PathList to Array */ 23 | FilePathArray PathList2Array(PathNode *head); 24 | 25 | #endif -------------------------------------------------------------------------------- /src/sac2spec_super/readme.txt: -------------------------------------------------------------------------------- 1 | /* ************************************************************ 2 | * Jobs of this code are 3 | * 1. read in three component SAC data 4 | * 2. split the whole data into segments 5 | * 3. do runabs time normalization and spectrum whitenning forof E,N,Z data. 6 | * 7 | * the weight used as the divisor is calculated using all three components 8 | * both in time domain normalization and frequency domain whitenning. 9 | * 10 | * 4. save spectrum of each segments and write to one file. 11 | * 12 | * The output would be segment-spectrum file which will be used later to calculate the noise 13 | * cross correlation. 14 | * 15 | * The information of segment and spectrum is saved in the header of each file which can be 16 | * found in segspec.h 17 | * 18 | * Calculated segment spectrum first would require more disk usage but may speed up the Cross 19 | * Correlation when you have huge dataset eg too many stations. 20 | * 21 | * Note: 22 | * History: 23 | * 1. init by wangwt@2015 24 | 25 | * Cuda Version Histroy 26 | * 27 | * 1. init by wangjx with the thread distrubution strategy made by wuchao 28 | * 2. use 2d cuda threads to perform batch processing of list of sac files, 29 | * X: segments of one sacfile, Y:list of sacfiles by wuchao@2021 30 | * 3. use cuda to implement rdc rtr npsmooth spectaper and etc by wuchao@2021 wangjx@2021,2022 31 | * 4. use cufft to perform FFT/IFFT transform by wuchao@2021 32 | * last updated by wangjx@20230703 33 | * *****************************************************************/ -------------------------------------------------------------------------------- /src/sac2spec_super/segspec.h: -------------------------------------------------------------------------------- 1 | /* Header for the segment by segment spectrum for noise cross correlation 2 | * History: 3 | * 1. init by wangwt to speed up CC on huge dataset. 4 | * 5 | * last update wangjx@20230514 6 | * */ 7 | 8 | #ifndef _SEGSPEC_H 9 | #define _SEGSPEC_H 10 | 11 | typedef struct segspec_s 12 | { 13 | float stla; 14 | float stlo; 15 | /* segment info */ 16 | int nstep; 17 | /* FFT info */ 18 | int nspec; /* use fftr() number of complex eg 2*nspec float */ 19 | float df; 20 | float dt; 21 | } SEGSPEC; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/sac2spec_super/util.c: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | 3 | const float RAMUPPERBOUND = 0.8; 4 | 5 | size_t QueryAvailCpuRam() 6 | { 7 | const size_t LINEMAX = 256; 8 | const size_t KILOBYTES = 1L << 10; 9 | // const size_t GIGABYTES = 1L << 30; 10 | struct sysinfo sinfo; 11 | char buffer[LINEMAX]; 12 | 13 | FILE *fid = fopen("/proc/meminfo", "r"); 14 | 15 | size_t availram = 0; 16 | 17 | while (fgets(buffer, LINEMAX, fid) != NULL) 18 | { 19 | if (strstr(buffer, "MemAvailable") != NULL) 20 | { 21 | sscanf(buffer, "MemAvailable: %lu kB", &availram); 22 | availram *= KILOBYTES; /* kB -> B */ 23 | availram *= RAMUPPERBOUND; 24 | } 25 | } 26 | fclose(fid); 27 | 28 | /* In Linux sysinfo's free ram is far smaller than available ram 29 | * Use this in condition that cannot find Memavailble in /proc/meminfo 30 | */ 31 | if (availram == 0) 32 | { 33 | int err = sysinfo(&sinfo); 34 | if (err != 0) 35 | { 36 | perror("Get sys info\n"); 37 | exit(-1); 38 | } 39 | availram = sinfo.freeram; 40 | } 41 | 42 | return availram; 43 | } 44 | 45 | size_t EstimateCpuBatch(size_t unitRam, int thread_num) 46 | { 47 | // Query available CPU RAM 48 | size_t availableRam = QueryAvailCpuRam() / thread_num; 49 | const size_t GIGABYTES = 1L << 30; 50 | printf("Avail cpu ram: %.3f GB\n", availableRam * 1.0 / GIGABYTES); 51 | // Initialize batch count and required RAM 52 | size_t batch = 0; 53 | size_t requiredRam = 0; 54 | 55 | // Keep increasing the batch count until required RAM exceeds available RAM 56 | while (requiredRam < availableRam) 57 | { 58 | // Increment the batch count 59 | batch++; 60 | 61 | // Update the required RAM based on the new batch count 62 | requiredRam = batch * unitRam; 63 | } 64 | 65 | // Decrease the batch count by 1 since the last increment caused required RAM 66 | // to exceed available RAM 67 | batch--; 68 | batch = batch > _RISTRICT_MAX_CPU_BATCH ? _RISTRICT_MAX_CPU_BATCH : batch; 69 | // Return the estimated batch count 70 | return batch; 71 | } 72 | 73 | void CpuMalloc(void **pptr, size_t sz) 74 | { 75 | if ((*pptr = malloc(sz)) == NULL) 76 | { 77 | perror("Malloc cpu memory"); 78 | exit(-1); 79 | } 80 | } 81 | 82 | void CpuFree(void **pptr) 83 | { 84 | free(*pptr); 85 | *pptr = NULL; 86 | } 87 | 88 | // in case some old compiler cannot deal with strdup 89 | char *my_strdup(const char *s) 90 | { 91 | if (s == NULL) 92 | { 93 | return NULL; 94 | } 95 | char *new_str = (char *)malloc(strlen(s) + 1); 96 | if (new_str == NULL) 97 | { 98 | return NULL; 99 | } 100 | char *p = new_str; 101 | while (*s) 102 | { 103 | *p++ = *s++; 104 | } 105 | *p = '\0'; 106 | return new_str; 107 | } 108 | -------------------------------------------------------------------------------- /src/sac2spec_super/util.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTIL_H 2 | #define _UTIL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "config.h" 9 | 10 | size_t QueryAvailCpuRam(); 11 | size_t EstimateCpuBatch(size_t unitRam, int thread_num); 12 | void CpuMalloc(void **, size_t); 13 | void CpuFree(void **); 14 | char* my_strdup(const char* s); 15 | #endif -------------------------------------------------------------------------------- /src/stack/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.c": "c", 4 | "limits.h": "c", 5 | "stdlib.h": "c", 6 | "usage.h": "c", 7 | "libgen.h": "c", 8 | "algorithm": "c", 9 | "sac.h": "c" 10 | } 11 | } -------------------------------------------------------------------------------- /src/stack/Makefile: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------- 2 | # ncfstack ‒ 子目录 Makefile(纯手写依赖) 3 | # • 顶层 make 递归调用 → Release (-O3) (MAKELEVEL=1) 4 | # • 手动进入目录 make → Debug (-O0 -g) (MAKELEVEL=0) 5 | # ---------------------------------------------------- 6 | 7 | # 编译器 8 | CC ?= gcc 9 | WARN ?= -Wall 10 | 11 | # --- 优化级别自动切换 --- 12 | ifeq ($(MAKELEVEL),0) # 手动调试 13 | OPTFLAGS := -O0 -g 14 | else # 顶层批量构建 15 | OPTFLAGS := -O3 16 | endif 17 | 18 | CFLAGS ?= $(OPTFLAGS) $(WARN) 19 | # ------------------------ 20 | 21 | # 源文件 / 目标文件 22 | SRCS := main.c arguproc.c sacio.c read_sac_lst.c util.c 23 | OBJS := $(SRCS:.c=.o) 24 | 25 | # 输出目录 / 可执行文件 26 | BINDIR := ../../bin 27 | PROG := $(BINDIR)/ncfstack 28 | 29 | # 伪目标 30 | .PHONY: all clean veryclean 31 | 32 | # 默认目标 33 | all: $(BINDIR) $(PROG) 34 | 35 | # 创建输出目录(若已存在则静默) 36 | $(BINDIR): 37 | @mkdir -p $@ 38 | 39 | # 链接 40 | $(PROG): $(OBJS) 41 | $(CC) $(CFLAGS) -o $@ $^ -lm 42 | 43 | # 通用编译规则 44 | %.o: %.c 45 | $(CC) $(CFLAGS) -c $< -o $@ 46 | 47 | # ---------------------------------------------------- 48 | # 手写依赖区——按实际头文件增删 49 | # ---------------------------------------------------- 50 | main.o: main.c sac.h arguproc.h read_sac_lst.h util.h 51 | arguproc.o: arguproc.c sac.h arguproc.h 52 | sacio.o: sacio.c sac.h 53 | read_sac_lst.o: read_sac_lst.c sac.h read_sac_lst.h 54 | util.o: util.c util.h sac.h 55 | # ---------------------------------------------------- 56 | 57 | # 清理 58 | clean: 59 | @rm -f *.o 60 | veryclean: clean 61 | @rm -f $(PROG) 62 | -------------------------------------------------------------------------------- /src/stack/Readme.txt: -------------------------------------------------------------------------------- 1 | /******************************************************************** 2 | * Stack the daily cross correlation NCF sac file by directory. 3 | * 4 | * This code will read in a directory path and iterate through all .sac files 5 | * under the directory. 6 | * You can choose to normalize them by divide N or just leave it un-normed. 7 | * 8 | * Since we create cross correlation file by outselves, their length and other 9 | * headers are always same for the same chn and same station. so we do not 10 | * add heavy check on the header info. 11 | * 12 | * Note: 13 | * 1.change all reference time to 2010/08/02/00:00:00:000 for pretty look 14 | * 2.number of stacked files are save in sachd.unused27 15 | * 3.changed from reading in list file to reading in directory path 16 | * 17 | * 18 | * History: 19 | * 1. many revision by wangwt@2009-2015 20 | * 2. Use linked list to store the file list so we now have no limit on the 21 | * number of files listed. wangwt@20160411 22 | * 3. add -W options for special check wangwt@20160723 23 | * 4. revise the rdlist2link so the main code is shorter and we can now 24 | * stack -O outputsac file1 file2 file3... 25 | * 26 | * last update wangwt@20190510 27 | * 28 | * OpenMP Version History: 29 | * 1. init by wuchao@202108 30 | * 2. use OpenMP multithread to perform parallel stackings 31 | * 3. get performance improvement on SSD, nearly no improvement on HDD 32 | * last update by wuchao@20211010 33 | *************************************************/ -------------------------------------------------------------------------------- /src/stack/arguproc.c: -------------------------------------------------------------------------------- 1 | #include "arguproc.h" 2 | #include "read_sac_lst.h" // for my_strdup 3 | void ArgumentProcess(int argc, char **argv, ARGUTYPE *pargument) 4 | { 5 | int opt; 6 | 7 | pargument->sac_lst = NULL; 8 | pargument->out_sac = NULL; 9 | pargument->normalize = 1; 10 | if (argc <= 1) 11 | { 12 | usage(); 13 | exit(-1); 14 | } 15 | struct option long_options[] = { 16 | {"I", required_argument, NULL, 'I'}, 17 | {"O", required_argument, NULL, 'O'}, 18 | {"A", no_argument, &(pargument->normalize), 0}, 19 | {0, 0, 0, 0}}; 20 | 21 | while ((opt = getopt_long(argc, argv, "I:O:A", long_options, NULL)) != -1) 22 | { 23 | switch (opt) 24 | { 25 | case 'I': 26 | pargument->sac_lst = my_strdup(optarg); 27 | break; 28 | case 'O': 29 | pargument->out_sac = optarg; 30 | break; 31 | case 'A': 32 | pargument->normalize = 0; 33 | break; 34 | default: // 处理其他任何错误的默认情况 35 | usage(); 36 | exit(EXIT_FAILURE); 37 | } 38 | } 39 | } 40 | 41 | void usage() 42 | { 43 | fprintf(stderr, "Usage:\n"); 44 | fprintf(stderr, "ncfstack -I ncf_list -O outpath [-A] \n"); 45 | fprintf(stderr, " -I ncf_dir.\n"); 46 | fprintf(stderr, " if -A is set, do NOT normalize output NCF,in accumulate mode.\n"); 47 | fprintf(stderr, " Else normalize the output NCF by devide N effect day as default.\n"); 48 | fprintf(stderr, "Note:\n"); 49 | fprintf(stderr, " 1. The input file should have same delta and npts.\n"); 50 | fprintf(stderr, " Since we create the NCFs list by ourselves, we do not make too much check\n"); 51 | fprintf(stderr, " 2. Header of the stacked ncfile will be taken from the first file in list\n"); 52 | fprintf(stderr, " 3. We forcely set the KZTIME and KZDATE to one special day to be convenience.\n"); 53 | fprintf(stderr, " 4. By default,we will always normlized the stacked NCF by divide N.\n"); 54 | fprintf(stderr, " The effective stacked N is save into hd.unused27.\n"); 55 | fprintf(stderr, " 5. We have not limitation on number of files in the listfile.\n"); 56 | fprintf(stderr, "Version: updated wangwt@20190510\n"); 57 | fprintf(stderr, "Version: last updated wangjx@20231105\n"); 58 | fprintf(stderr, "OpenMP version abandoned by wangjx@20230717, since we will do multiprocessing in higher level python script\n"); 59 | } 60 | -------------------------------------------------------------------------------- /src/stack/arguproc.h: -------------------------------------------------------------------------------- 1 | #ifndef _ARGUPROC_H_ 2 | #define _ARGUPROC_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | typedef struct ARGUTYPE 9 | { 10 | /* used by -L */ 11 | char *sac_lst; 12 | char *out_sac; 13 | /* used by -A */ 14 | /* take the normlized version as default. by wangwt@20130927 */ 15 | int normalize; 16 | } ARGUTYPE; 17 | 18 | void ArgumentProcess(int argc, char **argv, ARGUTYPE *pargument); 19 | void usage(); 20 | #endif -------------------------------------------------------------------------------- /src/stack/read_sac_lst.h: -------------------------------------------------------------------------------- 1 | #ifndef _FILE2LST_H 2 | #define _FILE2LST_H 3 | #include "sac.h" 4 | #include "util.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #define MAXLINE 8192 18 | #define MAXPATH 8192 19 | #define MAXNAME 255 20 | 21 | /* calculate dist gcarc az baz */ 22 | typedef struct FilePaths 23 | { 24 | char **paths; 25 | int count; 26 | } FilePaths; 27 | 28 | char* my_strdup(const char* s); 29 | 30 | FilePaths *read_sac_lst(char *dir); 31 | 32 | FilePaths *filter_by_npts(FilePaths *input); 33 | 34 | void freeFilePaths(FilePaths *fp); 35 | 36 | #endif -------------------------------------------------------------------------------- /src/stack/util.c: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include 3 | #include 4 | #include 5 | 6 | const float SHRINKRATIO = 2; 7 | const float RAMUPPERBOUND = 0.8; 8 | 9 | size_t QueryAvailCpuRam() 10 | { 11 | const size_t LINEMAX = 256; 12 | const size_t KILOBYTES = 1L<<10; 13 | const size_t GIGABYTES = 1L<<30; 14 | 15 | struct sysinfo sinfo; 16 | char buffer[LINEMAX]; 17 | 18 | FILE *fid = fopen("/proc/meminfo", "r"); 19 | 20 | size_t availram = 0; 21 | 22 | while (fgets(buffer, LINEMAX, fid) != NULL) 23 | { 24 | if (strstr(buffer, "MemAvailable") != NULL) 25 | { 26 | sscanf(buffer, "MemAvailable: %lu kB", &availram); 27 | availram *= KILOBYTES; /* kB -> B */ 28 | availram *= RAMUPPERBOUND; 29 | } 30 | } 31 | fclose(fid); 32 | 33 | /* In Linux sysinfo's free ram is far smaller than available ram 34 | * Use this in condition that cannot find Memavailble in /proc/meminfo 35 | */ 36 | if (availram == 0) 37 | { 38 | int err = sysinfo(&sinfo); 39 | if (err != 0) 40 | { 41 | perror("Get sys info\n"); 42 | exit(-1); 43 | } 44 | availram = sinfo.freeram; 45 | } 46 | 47 | printf("Avail cpu ram: %.3f GB\n", availram*1.0/GIGABYTES); 48 | 49 | return availram; 50 | } 51 | 52 | void CpuMalloc(void **pptr, size_t sz) 53 | { 54 | if ((*pptr = malloc(sz)) == NULL) 55 | { 56 | perror("Malloc cpu memory"); 57 | exit(-1); 58 | } 59 | } 60 | 61 | void CpuCalloc(void **pptr, size_t sz) 62 | { 63 | if ((*pptr = malloc(sz)) == NULL) 64 | { 65 | perror("Calloc cpu memory\n"); 66 | exit(-1); 67 | } 68 | memset(*pptr, 0, sz); 69 | } 70 | 71 | void CpuFree(void **pptr) 72 | { 73 | free(*pptr); 74 | *pptr = NULL; 75 | } 76 | 77 | size_t EstimateCpuBatch(size_t batch, size_t unitram) 78 | { 79 | size_t availram = QueryAvailCpuRam(); 80 | 81 | size_t reqram = batch * unitram; 82 | while (reqram >= availram) 83 | { 84 | batch = (batch + SHRINKRATIO - 1) / SHRINKRATIO; 85 | reqram = batch * unitram; 86 | } 87 | 88 | return batch; 89 | } 90 | -------------------------------------------------------------------------------- /src/stack/util.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTIL_H 2 | #define _UTIL_H 3 | 4 | #include 5 | 6 | size_t QueryAvailCpuRam(); 7 | size_t EstimateCpuBatch(size_t batch, size_t unitram); 8 | void CpuMalloc(void **pptr, size_t sz); 9 | void CpuCalloc(void **pptr, size_t sz); 10 | void CpuFree(void **pptr); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /src/xc_dual/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "chrono": "c", 4 | "*.cu": "cuda-cpp" 5 | } 6 | 7 | } 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/xc_dual/Makefile: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------- 2 | # xc_dual_channel ‒ 子目录 Makefile 3 | # • 顶层递归调用 → Release (-O3, --generate-line-info) 4 | # • 手动进入目录 → Debug (-O0 -g -G -lineinfo) 5 | # ---------------------------------------------------- 6 | 7 | # 编译器 8 | CC ?= gcc 9 | NVCC ?= /usr/local/cuda/bin/nvcc 10 | ARCH ?= sm_89 11 | WARN ?= -Wall 12 | 13 | # ---------- 优化级别自动切换 ---------- 14 | ifeq ($(MAKELEVEL),0) # 手动调试 15 | CFLAGS ?= -O0 -g $(WARN) 16 | NVCCFLAGS ?= -g -G -lineinfo -arch=$(ARCH) 17 | else # 顶层批量构建 18 | CFLAGS ?= -O3 $(WARN) 19 | NVCCFLAGS ?= -O3 --generate-line-info -arch=$(ARCH) 20 | endif 21 | # ------------------------------------- 22 | 23 | # 链接库 24 | LDFLAGS = -L/usr/local/cuda/lib64 -lcufft -lcudart -lm \ 25 | -L/usr/lib/x86_64-linux-gnu 26 | 27 | # 源文件 28 | CUDAOBJS = cuda.stransform.o \ 29 | cuda.pws_util.o \ 30 | cuda.estimate_batch.o\ 31 | cuda.xc_dual.o \ 32 | cuda.util.o \ 33 | cuda.main.o 34 | 35 | OBJS = arguproc.o \ 36 | sacio.o \ 37 | gen_ncf_path.o \ 38 | gen_pair.o \ 39 | read_segspec.o \ 40 | util.o \ 41 | cal_dist.o 42 | 43 | # 输出可执行文件 44 | BINDIR := ../../bin 45 | PROG := $(BINDIR)/xc_dual_channel 46 | 47 | # 伪目标 48 | .PHONY: all clean veryclean 49 | 50 | # 默认目标 51 | all: $(BINDIR) $(PROG) 52 | 53 | # 创建输出目录 54 | $(BINDIR): 55 | @mkdir -p $@ 56 | 57 | # 链接 58 | $(PROG): $(OBJS) $(CUDAOBJS) 59 | $(NVCC) $(NVCCFLAGS) -o $@ $^ $(LDFLAGS) 60 | 61 | # C 文件编译 62 | %.o: %.c 63 | $(CC) $(CFLAGS) -c $< -o $@ 64 | 65 | # CUDA 文件编译 66 | %.o: %.cu 67 | $(NVCC) $(NVCCFLAGS) -c $< -o $@ 68 | 69 | # 清理 70 | clean: 71 | @rm -f *.o 72 | 73 | veryclean: clean 74 | @rm -f $(PROG) 75 | -------------------------------------------------------------------------------- /src/xc_dual/arguproc.c: -------------------------------------------------------------------------------- 1 | #include "arguproc.h" 2 | 3 | /* parse command line arguments */ 4 | void ArgumentProcess(int argc, char **argv, ARGUTYPE *parg) 5 | { 6 | int c; 7 | 8 | parg->src_files_list = NULL; 9 | parg->sta_files_list = NULL; 10 | parg->ncf_dir = NULL; 11 | parg->cc_len = 0; 12 | parg->gpu_id = 0; 13 | parg->save_linear = 1; 14 | parg->save_pws = 0; 15 | parg->save_tfpws = 0; 16 | parg->save_segment = 0; 17 | parg->cpu_count = 1; 18 | parg->gpu_num = 1; 19 | parg->threshold_distance = 40000; 20 | 21 | /* check argument */ 22 | if (argc <= 1) 23 | { 24 | // usage(); 25 | exit(-1); 26 | } 27 | 28 | /* new stype parsing command line options */ 29 | while ((c = getopt(argc, argv, "A:B:O:C:G:S:T:D:")) != -1) 30 | { 31 | switch (c) 32 | { 33 | case 'A': 34 | parg->src_files_list = optarg; 35 | break; 36 | case 'B': 37 | parg->sta_files_list = optarg; 38 | break; 39 | case 'O': 40 | parg->ncf_dir = optarg; 41 | break; 42 | case 'C': 43 | parg->cc_len = atof(optarg); 44 | break; 45 | case 'G': 46 | parg->gpu_id = atoi(optarg); 47 | break; 48 | case 'T': 49 | parg->cpu_count = atoi(optarg); 50 | break; 51 | case 'S': 52 | if (strlen(optarg) != 4 || strspn(optarg, "01") != 4) 53 | { 54 | fprintf(stderr, "Error: Option -S requires a four-digit binary number consisting of 0s and 1s.\n"); 55 | exit(-1); 56 | } 57 | parg->save_linear = (optarg[0] == '1') ? 1 : 0; // 解析第一位 58 | parg->save_pws = (optarg[1] == '1') ? 1 : 0; // 解析第二位 59 | parg->save_tfpws = (optarg[2] == '1') ? 1 : 0; // 解析第三位 60 | parg->save_segment = (optarg[3] == '1') ? 1 : 0; // 解析第四位 61 | break; 62 | case 'D': 63 | parg->threshold_distance = atof(optarg); 64 | break; 65 | case '?': 66 | default: 67 | fprintf(stderr, "Unknown option %c\n", optopt); 68 | exit(-1); 69 | } 70 | } 71 | 72 | /* end of parsing command line arguments */ 73 | } 74 | 75 | void usage() 76 | { 77 | fprintf( 78 | stderr, 79 | "\nUsage:\n" 80 | "specxc_mg -A virt_src_lst -B virt_sta_dir -C halfCCLength -O " 81 | "outputdir -G gpu num\n" 82 | "Options:\n" 83 | " -A Specify the list file of input files for the 1st station, eg virtual " 84 | "source\n" 85 | " -B Specify the list file of input files for the 2nd station, eg virtual " 86 | "station\n" 87 | " -O Specify the output directory for NCF files as sac format\n" 88 | " -C Half of cclenth (in seconds).\n" 89 | " -D max ncf distances (in km).\n" 90 | " -G ID of Gpu device to be launched \n" 91 | " -U number of tasks deploy on a single GPU\n" 92 | " -T number of CPUs will be used in this threads\n" 93 | " -S Save options: 4 digits binary number, 1 for save, 0 for not save for [linear,pws,tfpws,segments]\n" 94 | "Version:\n" 95 | " last update by wangjx@20241127\n" 96 | " cuda version\n"); 97 | } -------------------------------------------------------------------------------- /src/xc_dual/arguproc.h: -------------------------------------------------------------------------------- 1 | #ifndef __CU_ARG_PROC_H 2 | #define __CU_ARG_PROC_H 3 | 4 | #define MAX_GPU_COUNT 100 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | typedef struct ARGUTYPE 14 | { 15 | 16 | char *src_files_list; // input list file of -A and -B 17 | char *sta_files_list; 18 | char *ncf_dir; // output dir for CC vector 19 | float cc_len; // half length of output NCF 20 | int gpu_id; // GPU ID 21 | int save_linear; // 是否线性叠加结果 22 | int save_pws; // 保留相位加权叠加结果 23 | int save_tfpws; // 保留时频域相位加权叠加结果 24 | int save_segment; // 是否保存每一段NCF(叠前) 25 | int cpu_count; // cpu并行数 26 | int gpu_num; // 同时开启的gpu数量 27 | float threshold_distance; // 阈值距离 28 | } ARGUTYPE; 29 | 30 | void usage(); 31 | void ArgumentProcess(int argc, char **argv, ARGUTYPE *parg); 32 | #endif -------------------------------------------------------------------------------- /src/xc_dual/cal_dist.h: -------------------------------------------------------------------------------- 1 | #ifndef _CAL_DIST_H_ 2 | #define _CAL_DIST_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #ifndef M_PI 8 | #define M_PI 3.1415926535897 9 | #endif 10 | 11 | void distkm_az_baz_Rudoe(double evlo,double evla,double stlo,double stla,double *gcarc,double *az,double* baz,double *distkm); 12 | 13 | 14 | 15 | 16 | #endif -------------------------------------------------------------------------------- /src/xc_dual/complex.h: -------------------------------------------------------------------------------- 1 | #ifndef _COMPLEX_H 2 | #define _COMPLEX_H 3 | 4 | // complex number 5 | typedef struct 6 | { 7 | float x; 8 | float y; 9 | } complex; 10 | 11 | #endif -------------------------------------------------------------------------------- /src/xc_dual/cuda.estimate_batch.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_ESTEIMATE_BATCH_CUH 2 | #define _CUDA_ESTEIMATE_BATCH_CUH 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "cuda.util.cuh" 8 | #include 9 | 10 | size_t EstimateFreqBatchSize( 11 | int gpu_id, 12 | size_t num_trace, 13 | size_t npts_ncf, 14 | size_t nfreq, 15 | size_t gpu_task_num, 16 | float safety_factor); 17 | 18 | #endif -------------------------------------------------------------------------------- /src/xc_dual/cuda.pws_util.cu: -------------------------------------------------------------------------------- 1 | #include "cuda.pws_util.cuh" 2 | #include 3 | 4 | __global__ void cudaMean(cufftComplex *hilbert_complex, cufftComplex *mean, size_t num_trace, size_t nfft) 5 | { 6 | size_t col = blockIdx.x * blockDim.x + threadIdx.x; 7 | 8 | if (col < nfft) 9 | { 10 | float sum_real = 0.0f, sum_img = 0.0f; 11 | // 计算当前时间点上所有信号的实部总和 12 | for (size_t j = 0; j < num_trace; ++j) 13 | { 14 | sum_real += hilbert_complex[j * nfft + col].x; 15 | sum_img += hilbert_complex[j * nfft + col].y; 16 | } 17 | // // 计算平均值 18 | mean[col].x = sum_real / num_trace; 19 | mean[col].y = sum_img / num_trace; 20 | } 21 | } 22 | 23 | __global__ void cudaNormalizeComplex(cufftComplex *hilbert_complex, size_t data_num, size_t nfft) 24 | { 25 | size_t idx = blockIdx.x * blockDim.x + threadIdx.x; // 一维索引 26 | if (idx < data_num) 27 | { 28 | float real = hilbert_complex[idx].x / nfft; 29 | float imag = hilbert_complex[idx].y / nfft; 30 | 31 | float modulus = sqrtf(real * real + imag * imag); 32 | modulus = (modulus > 1e-7f) ? modulus : 1e-7f; 33 | hilbert_complex[idx].x = real / modulus; 34 | hilbert_complex[idx].y = imag / modulus; 35 | } 36 | } 37 | 38 | __global__ void cudaMultiply(float *linear_stack, cuComplex *weight, float *pws_stack, size_t nfft) 39 | { 40 | size_t idx = blockIdx.x * blockDim.x + threadIdx.x; 41 | 42 | if (idx < nfft) 43 | { 44 | float weight_value = sqrtf(weight[idx].x * weight[idx].x + weight[idx].y * weight[idx].y); 45 | pws_stack[idx] = linear_stack[idx] * weight_value; 46 | } 47 | } -------------------------------------------------------------------------------- /src/xc_dual/cuda.pws_util.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CU_PWS_UTIL_H_ 2 | #define _CU_PWS_UTIL_H_ 3 | #include 4 | #include 5 | #include 6 | 7 | __global__ void cudaMean(cufftComplex *hilbert_complex, cufftComplex *mean, size_t num_trace, size_t nfft); 8 | 9 | __global__ void cudaNormalizeComplex(cufftComplex *hilbert_complex, size_t data_num, size_t nfft); 10 | 11 | __global__ void cudaMultiply(float *linear_stack, cuComplex *weight, float *pws_stack, size_t nfft); 12 | 13 | #endif -------------------------------------------------------------------------------- /src/xc_dual/cuda.util.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_UTIL_CUH 2 | #define _CUDA_UTIL_CUH 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | // 3060 gpu do not have enough resources, so I try modify the block size to 16 15 | #define BLOCKX1D 256 16 | #define BLOCKX2D 16 17 | #define BLOCKY2D 16 18 | #define BLOCKX3D 8 19 | #define BLOCKY3D 8 20 | #define BLOCKZ3D 8 21 | #define BLOCKMAX 1024 22 | #define BLOCKX 16 23 | #define BLOCKY 16 24 | 25 | #define CUDACHECK(cmd) \ 26 | do \ 27 | { \ 28 | cudaError_t e = cmd; \ 29 | if (e != cudaSuccess) \ 30 | { \ 31 | printf("Failed: Cuda error %s:%d '%s'\n", __FILE__, __LINE__, \ 32 | cudaGetErrorString(e)); \ 33 | exit(EXIT_FAILURE); \ 34 | } \ 35 | } while (0) 36 | 37 | #define CUFFTCHECK(cmd) \ 38 | do \ 39 | { \ 40 | cufftResult_t e = cmd; \ 41 | if (e != CUFFT_SUCCESS) \ 42 | { \ 43 | printf("Failed: CuFFT error %s:%d %d\n", __FILE__, __LINE__, e); \ 44 | exit(EXIT_FAILURE); \ 45 | } \ 46 | } while (0) 47 | 48 | size_t QueryAvailGpuRam(size_t gpu_id); 49 | 50 | size_t EstimateGpuBatch_CC(size_t gpu_id, size_t fiexed_ram, size_t unitram, 51 | int numType, int rank, int *n, int *inembed, 52 | int istride, int idist, int *onembed, int ostride, 53 | int odist, cufftType *typeArr); 54 | 55 | size_t EstimateGpuBatch_TFPWS(size_t gpu_id, int nfft, int nfreq); 56 | 57 | void DimCompute(dim3 *, dim3 *, size_t, size_t); 58 | 59 | /* Compute the block and dimension for cuda kernel fucntion*/ 60 | void DimCompute1D(dim3 *pdimgrd, dim3 *pdimblk, size_t width); 61 | void DimCompute2D(dim3 *, dim3 *, size_t, size_t); 62 | void DimCompute3D(dim3 *pdimgrd, dim3 *pdimblk, size_t width, size_t height, size_t depth); 63 | 64 | void CufftPlanAlloc(cufftHandle *, int, int *, int *, int, int, int *, int, int, 65 | cufftType, int); 66 | void GpuMalloc(void **, size_t); 67 | void GpuCalloc(void **, size_t); 68 | void GpuFree(void **); 69 | 70 | #endif -------------------------------------------------------------------------------- /src/xc_dual/cuda.xc_dual.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_XC_DUAL_CUH 2 | #define _CUDA_XC_DUAL_CUH 3 | 4 | #include "cuda.util.cuh" 5 | #include 6 | #include 7 | 8 | __global__ void complexMul2DKernel(cuComplex *src_vec, cuComplex *sta_vec, size_t spitch, 9 | cuComplex *ncf_vec, size_t dpitch, 10 | size_t width, size_t height); 11 | 12 | __global__ void generateSignVector(int *sgn_vec, size_t width); 13 | 14 | __global__ void applyPhaseShiftKernel(cuComplex *result_vec, int *sign_vec, size_t spitch, size_t width, size_t height); 15 | 16 | __global__ void sum2DKernel(float *d_finalccvec, int dpitch, float *d_segncfvec, 17 | int spitch, size_t width, size_t height, int nstep); 18 | 19 | __global__ void csum2DKernel(cuComplex *d_total_spectrum, int dpitch, 20 | cuComplex *d_segment_spectrum, int spitch, 21 | size_t width, size_t height, int step_idx, int nstep); 22 | 23 | __global__ void InvNormalize2DKernel(float *d_segdata, size_t pitch, 24 | size_t width, size_t height, float dt); 25 | 26 | #endif -------------------------------------------------------------------------------- /src/xc_dual/do.sh: -------------------------------------------------------------------------------- 1 | /mnt/c/Users/admin/Desktop/FastXC_raw/xc-new/bin/xc_new -A /mnt/c/Users/admin/Desktop/FastXC_raw/output/xc_list/array1/AAKH.U.speclist -B /mnt/c/Users/admin/Desktop/FastXC_raw/output/xc_list/array1/ABNH.U.speclist -O ./ -C 500 -S 1110 -D 400000 -T 40 2 | -------------------------------------------------------------------------------- /src/xc_dual/gen_ncf_path.h: -------------------------------------------------------------------------------- 1 | #ifndef _GEN_NCF_PATH_H 2 | #define _GEN_NCF_PATH_H 3 | #define MAXLINE 8192 4 | #define MAXPATH 8192 5 | #define MAXNAME 255 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "sac.h" 14 | #include "segspec.h" 15 | #include "cal_dist.h" 16 | 17 | char *my_strdup(const char *s); 18 | 19 | char *my_strtok(char *str, const char *delim, char **saveptr); 20 | 21 | void CreateDir(char *sPathName); 22 | 23 | void SplitFileName(const char *fname, const char *delimiter, char *stastr, 24 | char *yearstr, char *jdaystr, char *hmstr, char *chnstr); 25 | 26 | void SacheadProcess(SACHEAD *ncfhd, SEGSPEC *srchd, SEGSPEC *stahd, float cclength); 27 | 28 | void GenCCFPath(char *ccf_path, char *src_path, char *sta_path, char *output_dir); 29 | 30 | char *GetNcfPath(char *src_path, char *sta_path, char *output_dir); 31 | 32 | char *GetEachNcfPath(char *src_path, char *sta_path, char *output_dir); 33 | 34 | #endif -------------------------------------------------------------------------------- /src/xc_dual/gen_pair.h: -------------------------------------------------------------------------------- 1 | #ifndef _GEN_PAIR_H 2 | #define _GEN_PAIR_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #define MAX_LINE_LENGTH 1024 8 | 9 | typedef struct TimeInfo 10 | { 11 | int year; 12 | int jday; 13 | int hourminute; 14 | } TimeInfo; 15 | 16 | typedef struct 17 | { 18 | char filename[MAX_LINE_LENGTH]; 19 | TimeInfo time; 20 | } FileEntry; 21 | 22 | typedef struct 23 | { 24 | char source_path[MAX_LINE_LENGTH]; 25 | char station_path[MAX_LINE_LENGTH]; 26 | TimeInfo time; 27 | int index; // 添加以存储对的索引 28 | } FilePair; 29 | 30 | void find_matching_files(const char *filelist1, const char *filelist2, FilePair **matches, size_t *match_count); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/xc_dual/read_segspec.h: -------------------------------------------------------------------------------- 1 | #ifndef _READ_SEGSPEC_H 2 | #define _READ_SEGSPEC_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "complex.h" 12 | #include "segspec.h" 13 | #include "gen_pair.h" 14 | 15 | typedef struct thread_info_read 16 | { 17 | int start; 18 | int end; 19 | FilePair *filepairs; 20 | complex *src_buffer; 21 | complex *sta_buffer; 22 | size_t vec_size; 23 | } thread_info_read; 24 | 25 | typedef struct ThreadPoolRead 26 | { 27 | pthread_t *threads; 28 | thread_info_read *tinfo; 29 | size_t num_threads; 30 | } ThreadPoolRead; 31 | 32 | // 创建读取进程池 33 | ThreadPoolRead *create_threadpool_read(size_t num_threads); 34 | 35 | // 销毁读取进程池 36 | void destroy_threadpool_read(ThreadPoolRead *pool); 37 | 38 | // 并行读取segspec文件 39 | int parallel_read_segspec(ThreadPoolRead *pool, size_t proccnt, FilePair *pairs, 40 | complex *src_buffer, complex *sta_buffer, size_t block_size, 41 | int num_threads); 42 | 43 | // 读取segspec文件的头 44 | int read_spechead(char *file_path, SEGSPEC *hd); 45 | #endif -------------------------------------------------------------------------------- /src/xc_dual/segspec.h: -------------------------------------------------------------------------------- 1 | /* Header for the segment by segment spectrum for noise cross correlation 2 | * History: 3 | * 1. init by wangwt to speed up CC on huge dataset. 4 | * 5 | * last update wangjx@20230504 6 | * */ 7 | 8 | #ifndef _SEGSPEC_H 9 | #define _SEGSPEC_H 10 | 11 | // struct segspec 12 | typedef struct segspec_s 13 | { 14 | float stla; 15 | float stlo; 16 | /* segment info */ 17 | int nstep; // nstep is the number of segments, example divide 24h into 12 segments 18 | 19 | /* FFT info */ 20 | int nspec; /* use fftr() number of complex eg 2*nspec float */ 21 | float df; 22 | float dt; 23 | 24 | } SEGSPEC; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/xc_dual/util.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTIL_H 2 | #define _UTIL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "sac.h" 8 | 9 | // sharedItem 10 | typedef struct 11 | { 12 | pthread_mutex_t mtx; 13 | int valid; /* -1: default; 1: ready to file; 2: finish to file */ 14 | char fname[PATH_MAX]; 15 | SACHEAD *phead; 16 | float *pdata; 17 | } SHAREDITEM; 18 | 19 | size_t QueryAvailCpuRam(); 20 | size_t EstimateCpuBatch(size_t fixedRam, size_t unitRam); 21 | void CpuMalloc(void **pptr, size_t sz); 22 | void CpuCalloc(void **pptr, size_t sz); 23 | void CpuFree(void **pptr); 24 | 25 | double getElapsedTime(struct timespec start, struct timespec end); 26 | int write_multiple_sac(const char *filename, SHAREDITEM *pItem, int paircnt); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/xc_multi/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.c": "c", 4 | "node_util.h": "c", 5 | "string.h": "c", 6 | "read_segspec.h": "c", 7 | "complex.h": "c", 8 | "stdlib.h": "c", 9 | "par_write_sac.h": "c", 10 | "array": "c", 11 | "string": "c", 12 | "string_view": "c", 13 | "complex": "c", 14 | "pthread.h": "c", 15 | "algorithm": "cpp", 16 | "limits.h": "c", 17 | "par_filter_nodelist.h": "c", 18 | "gen_ccfpath.h": "c" 19 | } 20 | } -------------------------------------------------------------------------------- /src/xc_multi/Makefile: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------- 2 | # xc_multi_channel ‒ 子目录 Makefile 3 | # · 顶层递归调用 → Release (-O3, --generate-line-info) 4 | # · 手动进目录 make → Debug (-O0 -g -G -lineinfo) 5 | # ---------------------------------------------------- 6 | 7 | # 编译器 8 | CC ?= gcc 9 | NVCC ?= /usr/local/cuda/bin/nvcc 10 | ARCH ?= sm_89 11 | WARN ?= -Wall 12 | 13 | # ---------- 优化级别自动切换 ---------- 14 | ifeq ($(MAKELEVEL),0) # 手动调试 15 | CFLAGS ?= -O0 -g $(WARN) 16 | NVCCFLAGS ?= -g -G -lineinfo -arch=$(ARCH) 17 | else # 顶层批量构建 18 | CFLAGS ?= -O3 $(WARN) 19 | NVCCFLAGS ?= -O3 --generate-line-info -arch=$(ARCH) 20 | endif 21 | # ------------------------------------- 22 | 23 | # 链接库 24 | LFLAG = -L/usr/local/cuda/lib64 -lcufft -lcudart -lm 25 | 26 | # 源文件 27 | CUDAOBJS = cuda.main.o \ 28 | cuda.xc_dual.o \ 29 | cuda.util.o 30 | 31 | OBJS = arguproc.o \ 32 | sacio.o \ 33 | cal_dist.o \ 34 | gen_ccfpath.o \ 35 | par_read_spec.o \ 36 | par_write_sac.o \ 37 | par_filter_nodes.o \ 38 | read_segspec.o \ 39 | read_spec_lst.o \ 40 | util.o 41 | 42 | # 输出可执行文件 43 | BINDIR := ../../bin 44 | PROG := $(BINDIR)/xc_multi_channel 45 | 46 | # 伪目标 47 | .PHONY: all clean veryclean 48 | 49 | # 默认目标 50 | all: $(BINDIR) $(PROG) 51 | 52 | # 创建输出目录 53 | $(BINDIR): 54 | @mkdir -p $@ 55 | 56 | # 链接 57 | $(PROG): $(OBJS) $(CUDAOBJS) 58 | $(NVCC) $(NVCCFLAGS) -o $@ $^ $(LFLAG) 59 | 60 | # C 源编译 61 | %.o: %.c 62 | $(CC) $(CFLAGS) -c $< -o $@ 63 | 64 | # CUDA 源编译 65 | %.o: %.cu 66 | $(NVCC) $(NVCCFLAGS) -c $< -o $@ 67 | 68 | # 清理 69 | clean: 70 | @rm -f *.o 71 | 72 | veryclean: clean 73 | @rm -f $(PROG) 74 | -------------------------------------------------------------------------------- /src/xc_multi/arguproc.c: -------------------------------------------------------------------------------- 1 | #include "arguproc.h" 2 | 3 | /* parse command line arguments */ 4 | void ArgumentProcess(int argc, char **argv, ARGUTYPE *parg) 5 | { 6 | int c; 7 | 8 | parg->src_lst_path = NULL; 9 | parg->sta_lst_path = NULL; 10 | parg->ncf_dir = NULL; 11 | parg->cclength = 0; 12 | parg->gpu_id = 0; 13 | parg->cpu_count = 1; 14 | parg->gpu_task_num = 1; 15 | parg->max_distance = 400000; 16 | 17 | /* check argument */ 18 | if (argc <= 1) 19 | { 20 | usage(); 21 | exit(-1); 22 | } 23 | 24 | /* new stype parsing command line options */ 25 | while ((c = getopt(argc, argv, "A:B:O:C:G:U:T:D:")) != -1) 26 | { 27 | switch (c) 28 | { 29 | case 'A': 30 | parg->src_lst_path = optarg; 31 | break; 32 | case 'B': 33 | parg->sta_lst_path = optarg; 34 | break; 35 | case 'O': 36 | parg->ncf_dir = optarg; 37 | break; 38 | case 'C': 39 | parg->cclength = atof(optarg); 40 | break; 41 | case 'G': 42 | parg->gpu_id = atof(optarg); 43 | break; 44 | case 'T': 45 | parg->cpu_count = atof(optarg); 46 | break; 47 | case 'U': 48 | parg->gpu_task_num = atof(optarg); 49 | break; 50 | case 'D': 51 | parg->max_distance = atof(optarg); 52 | break; 53 | case '?': 54 | default: 55 | fprintf(stderr, "Unknown option %c\n", optopt); 56 | exit(-1); 57 | } 58 | } 59 | /* end of parsing command line arguments */ 60 | } 61 | 62 | void usage() 63 | { 64 | fprintf( 65 | stderr, 66 | "\nUsage:\n" 67 | "specxc_mg -A virt_src_lst -B virt_sta_dir -C halfCCLength -O " 68 | "outputdir -G gpu num\n" 69 | "Options:\n" 70 | " -A Specify the list file of input files for the 1st station, eg virtual " 71 | "source\n" 72 | " -B Specify the list file of input files for the 2nd station, eg virtual " 73 | "station\n" 74 | " -O Specify the output directory for NCF files as sac format\n" 75 | " -C Half of cclenth (in seconds).\n" 76 | " -D max ncf distances (in km).\n" 77 | " -G ID of Gpu device to be launched \n" 78 | " -U number of tasks deploy on a single GPU\n" 79 | " -T number of CPUs will be used in this threads\n" 80 | "Version:\n" 81 | " last update by wangjx@20240515\n" 82 | " cuda version\n"); 83 | } -------------------------------------------------------------------------------- /src/xc_multi/arguproc.h: -------------------------------------------------------------------------------- 1 | #ifndef __CU_ARG_PROC_H 2 | #define __CU_ARG_PROC_H 3 | 4 | #define MAX_GPU_COUNT 100 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | typedef struct ARGUTYPE 13 | { 14 | 15 | char *src_lst_path; /* input list file of -A */ 16 | char *sta_lst_path; /* input list file of -B */ 17 | char *ncf_dir; /* output dir for CC vector */ 18 | float cclength; /* half length of output NCF */ 19 | float max_distance; /* higher distance threshold for calaulating CCF*/ 20 | size_t gpu_id; /* GPU ID */ 21 | size_t gpu_task_num; /*number of tasks deploy on a single GPU*/ 22 | size_t cpu_count; /*number of CPUs will be used in this threads*/ 23 | } ARGUTYPE; 24 | 25 | void usage(); 26 | void ArgumentProcess(int argc, char **argv, ARGUTYPE *pargument); 27 | 28 | #endif -------------------------------------------------------------------------------- /src/xc_multi/cal_dist.h: -------------------------------------------------------------------------------- 1 | #ifndef _CAL_DIST_H_ 2 | #define _CAL_DIST_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #ifndef M_PI 8 | #define M_PI 3.1415926535897 9 | #endif 10 | 11 | void distkm_az_baz_Rudoe(double evlo,double evla,double stlo,double stla,double *gcarc,double *az,double* baz,double *distkm); 12 | 13 | 14 | 15 | 16 | #endif -------------------------------------------------------------------------------- /src/xc_multi/complex.h: -------------------------------------------------------------------------------- 1 | #ifndef _COMPLEX_H 2 | #define _COMPLEX_H 3 | 4 | typedef struct 5 | { 6 | float x; 7 | float y; 8 | } complex; 9 | 10 | #endif -------------------------------------------------------------------------------- /src/xc_multi/config.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_H 2 | #define CONFIG_H 3 | 4 | #define MAXLINE 8192 5 | #define MAXPATH 8192 6 | #define MAXNAME 255 7 | 8 | #endif -------------------------------------------------------------------------------- /src/xc_multi/cuda.util.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_UTIL_CUH 2 | #define _CUDA_UTIL_CUH 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define BLOCKX 32 15 | #define BLOCKY 32 16 | #define BLOCKX1D 256 17 | 18 | #define CUDACHECK(cmd) \ 19 | do \ 20 | { \ 21 | cudaError_t e = cmd; \ 22 | if (e != cudaSuccess) \ 23 | { \ 24 | printf("Failed: Cuda error %s:%d '%s'\n", __FILE__, __LINE__, \ 25 | cudaGetErrorString(e)); \ 26 | exit(EXIT_FAILURE); \ 27 | } \ 28 | } while (0) 29 | 30 | #define CUFFTCHECK(cmd) \ 31 | do \ 32 | { \ 33 | cufftResult_t e = cmd; \ 34 | if (e != CUFFT_SUCCESS) \ 35 | { \ 36 | printf("Failed: CuFFT error %s:%d %d\n", __FILE__, __LINE__, e); \ 37 | exit(EXIT_FAILURE); \ 38 | } \ 39 | } while (0) 40 | 41 | size_t QueryAvailGpuRam(size_t gpu_id); 42 | 43 | void DimCompute1D(dim3 *pdimgrd, dim3 *pdimblk, size_t width); 44 | void DimCompute(dim3 *, dim3 *, size_t, size_t); 45 | 46 | int EstimateGpuBatch(size_t gpu_id, int nspec, int nstep, int gpu_task_num); 47 | 48 | void CufftPlanAlloc(cufftHandle *, int, int *, int *, int, int, int *, int, int, 49 | cufftType, int); 50 | void GpuMalloc(void **, size_t); 51 | void GpuCalloc(void **, size_t); 52 | void GpuFree(void **); 53 | 54 | #endif -------------------------------------------------------------------------------- /src/xc_multi/cuda.xc_dual.cuh: -------------------------------------------------------------------------------- 1 | #ifndef _CUDA_XC_DUAL_CUH 2 | #define _CUDA_XC_DUAL_CUH 3 | 4 | #include "cuda.util.cuh" 5 | #include "node_util.h" 6 | #include 7 | #include 8 | 9 | __global__ void generateSignVector(int *sgn_vec, size_t width); 10 | 11 | __global__ void cmultiply2DKernel(cuComplex *d_src_buffer, size_t *src_idx_list, 12 | cuComplex *d_sta_buffer, size_t *sta_idx_list, 13 | cuComplex *d_ncf_buffer, size_t height, size_t width); 14 | 15 | __global__ void csum2DKernel(cuComplex *d_total_spectrum, int dpitch, 16 | cuComplex *d_segment_spectrum, int spitch, 17 | size_t width, size_t height, int step_idx, int nstep); 18 | 19 | __global__ void applyPhaseShiftKernel(cuComplex *ncf_vec, int *sgn_vec, 20 | size_t spitch, size_t width, size_t height); 21 | 22 | __global__ void sum2DKernel(float *d_finalccvec, int dpitch, float *d_segncfvec, 23 | int spitch, size_t width, size_t height, int nstep); 24 | 25 | __global__ void csum2DKernel(cuComplex *d_total_spectrum, int dpitch, 26 | cuComplex *d_segment_spectrum, int spitch, 27 | size_t width, size_t height, int nstep); 28 | 29 | __global__ void InvNormalize2DKernel(float *d_segdata, size_t pitch, 30 | size_t width, size_t height, float dt); 31 | 32 | #endif -------------------------------------------------------------------------------- /src/xc_multi/do.sh: -------------------------------------------------------------------------------- 1 | /mnt/c/Users/admin/Desktop/FastXC_daily/bin/xc -A /mnt/c/Users/admin/Desktop/FastXC_daily/output/xc_list/array1/2017.244.0000.speclist -B /mnt/c/Users/admin/Desktop/FastXC_daily/output/xc_list/array1/2017.244.0000.speclist -O /mnt/c/Users/admin/Desktop/FastXC_daily/output/ncf -C 100 -D 400000 -T 40 -G 0 -U 1 2 | -------------------------------------------------------------------------------- /src/xc_multi/gen_ccfpath.h: -------------------------------------------------------------------------------- 1 | #ifndef _GEN_CCF_PATH_H 2 | #define _GEN_CCF_PATH_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "config.h" 9 | #include "sac.h" 10 | #include "segspec.h" 11 | #include "util.h" 12 | #include "cal_dist.h" 13 | 14 | void CreateDir(char *sPathName); 15 | 16 | void SplitFileName(const char *fname, const char *delimiter, char *stastr, 17 | char *yearstr, char *jdaystr, char *hmstr, char *chnstr); 18 | 19 | void SacheadProcess(SACHEAD *ncfhd, 20 | float stla, float stlo, float evla, float evlo, 21 | float Gcarc, float Az, float Baz, float Dist, 22 | float delta, int ncc, float cclength); 23 | 24 | void GenCCFPath(char *ccf_path, char *src_path, char *sta_path, char *output_dir); 25 | 26 | #endif -------------------------------------------------------------------------------- /src/xc_multi/node_util.h: -------------------------------------------------------------------------------- 1 | #ifndef NODE_UTIL_H 2 | #define NODE_UTIL_H 3 | 4 | #include "config.h" 5 | #include "segspec.h" 6 | #include "sac.h" 7 | #include "complex.h" 8 | #include 9 | 10 | typedef struct FilePaths 11 | { 12 | char **paths; 13 | int count; 14 | } FilePaths; 15 | 16 | // typedef struct SPECNODE 17 | // { 18 | // int valid; 19 | // char filepath[MAXLINE]; 20 | // SEGSPEC head; 21 | // complex *pdata; 22 | // } SPECNODE; 23 | 24 | // typedef struct PAIRNODE 25 | // { 26 | // size_t srcidx; 27 | // size_t staidx; 28 | // } PAIRNODE; 29 | 30 | typedef struct PAIRLIST_MANAGER 31 | { 32 | size_t *src_idx_list; // 存储每一源台对的源在输入列表的索引 33 | size_t *sta_idx_list; // 存储每一源台对的源在输入列表的索引 34 | float *stla_list; // 存储每个节点虚拟台的纬度 35 | float *stlo_list; // 存储每个节点虚拟台的经度 36 | float *evla_list; // 存储每个节点虚拟源的纬度 37 | float *evlo_list; // 存储每个节点虚拟源的经度 38 | float *Gcarc_list; // 存储每个节点源-台大圆路径长度 39 | float *Az_list; // 方位角 40 | float *Baz_list; // 反方位角 41 | float *Dist_list; // 存储每个源-台节点的间距 42 | int *ok_flag_list; // 每个节点是否可用的标识符 43 | size_t node_count; // 这组表里由多少个节点(多少对台站对) 44 | int single_array_flag; // 是否单一阵列(源台一致) 45 | size_t src_start_idx; // 源文件在[本批]输入列表中的[相对]起始索引 46 | size_t src_end_idx; // 源文件在[本批]输入列表中的[相对]截止索引+1(满足左闭右开原则) 47 | size_t sta_start_idx; // 台文件在[本批]输入列表中的[相对]起始索引 48 | size_t sta_end_idx; // 台文件在[本批]输入列表中的[相对]截止索引+1(满足左闭右开原则) 49 | } PAIRLIST_MANAGER; 50 | 51 | #endif -------------------------------------------------------------------------------- /src/xc_multi/par_filter_nodes.h: -------------------------------------------------------------------------------- 1 | #ifndef _PAR_FILTER_NODELIST 2 | #define _PAR_FILTER_NODELIST 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "node_util.h" 9 | #include "read_segspec.h" 10 | #include "segspec.h" 11 | #include "util.h" 12 | #include "cal_dist.h" 13 | 14 | // 定义一个结构体来存储线程需要的数据 15 | typedef struct 16 | { 17 | FilePaths *srcFileList; // 指向文件路径列表的指针 18 | FilePaths *staFileList; // 指向文件路径列表的指针 19 | PAIRLIST_MANAGER *manager; // 输入整一个待处理的列表 20 | size_t start; // 开始处理的台站对节点索引 21 | size_t end; // 结束处理的台站对索引索引 22 | float max_distance; 23 | } thread_info_filter; 24 | 25 | // 线程池结构体定义 26 | typedef struct 27 | { 28 | pthread_t *threads; 29 | thread_info_filter *tinfo; 30 | size_t num_threads; 31 | } ThreadPoolFilter; 32 | 33 | ThreadPoolFilter *create_threadpool_filter_nodes(size_t num_threads); 34 | 35 | void destroy_threadpool_filter_nodes(ThreadPoolFilter *pool); 36 | 37 | int FilterNodeParallel(PAIRLIST_MANAGER *manager, FilePaths *src_paths, FilePaths *sta_paths, 38 | ThreadPoolFilter *pool, float max_distance); 39 | 40 | void CompressManager(PAIRLIST_MANAGER *manager); 41 | #endif -------------------------------------------------------------------------------- /src/xc_multi/par_read_spec.c: -------------------------------------------------------------------------------- 1 | #include "par_read_spec.h" 2 | #include "util.h" 3 | 4 | // 创建线程池的函数 5 | ThreadPoolRead *create_threadpool_read(size_t num_threads) 6 | { 7 | ThreadPoolRead *pool = malloc(sizeof(ThreadPoolRead)); 8 | pool->threads = malloc(num_threads * sizeof(pthread_t)); 9 | pool->tinfo = malloc(num_threads * sizeof(thread_info_read)); 10 | pool->num_threads = num_threads; 11 | return pool; 12 | } 13 | 14 | // 销毁线程池的函数 15 | void destroy_threadpool_read(ThreadPoolRead *pool) 16 | { 17 | free(pool->threads); 18 | free(pool->tinfo); 19 | free(pool); 20 | } 21 | 22 | // 线程函数,用于处理文件 23 | void *read_files(void *arg) 24 | { 25 | thread_info_read *tinfo = (thread_info_read *)arg; 26 | SEGSPEC *tmp_hd = NULL; 27 | CpuMalloc((void **)&tmp_hd, sizeof(SEGSPEC)); 28 | 29 | // 为每个线程处理文件 30 | for (size_t i = tinfo->start; i < tinfo->end; i++) 31 | { 32 | size_t file_idx = tinfo->file_start + i; 33 | size_t offset = tinfo->vec_count * i; 34 | if (read_spec_buffer(tinfo->pFileList->paths[file_idx], tmp_hd, tinfo->data_buffer + offset) == NULL) 35 | { 36 | continue; 37 | } 38 | } 39 | 40 | CpuFree((void **)&tmp_hd); 41 | return NULL; 42 | } 43 | 44 | // 并行生成SPECNODE数组的函数 45 | int ReadSpecArrayParallel(FilePaths *pFileList, complex *data_buffer, size_t file_start, size_t file_end, 46 | size_t vec_count, ThreadPoolRead *pool) 47 | { 48 | size_t total_files = file_end - file_start; 49 | size_t files_per_thread = total_files / pool->num_threads; 50 | size_t remainder = total_files % pool->num_threads; 51 | 52 | size_t current_file_start = file_start; 53 | size_t start = 0; 54 | for (int i = 0; i < pool->num_threads; i++) 55 | { 56 | pool->tinfo[i].start = start; 57 | pool->tinfo[i].end = start + files_per_thread + (i < remainder ? 1 : 0); 58 | start = pool->tinfo[i].end; 59 | pool->tinfo[i].pFileList = pFileList; 60 | pool->tinfo[i].data_buffer = data_buffer; 61 | pool->tinfo[i].file_start = current_file_start; 62 | pool->tinfo[i].vec_count = vec_count; 63 | 64 | if (pthread_create(&pool->threads[i], NULL, read_files, &pool->tinfo[i])) 65 | { 66 | fprintf(stderr, "Error creating thread\n"); 67 | return -1; 68 | } 69 | } 70 | for (int i = 0; i < pool->num_threads; i++) 71 | { 72 | if (pthread_join(pool->threads[i], NULL)) 73 | { 74 | fprintf(stderr, "Error joining thread\n"); 75 | return -1; 76 | } 77 | } 78 | 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /src/xc_multi/par_read_spec.h: -------------------------------------------------------------------------------- 1 | #ifndef _PAR_READ_SPEC_H 2 | #define _PAR_READ_SPEC_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "read_segspec.h" 9 | #include "node_util.h" 10 | #include "complex.h" 11 | #include "sac.h" 12 | #include "segspec.h" 13 | 14 | // 定义一个结构体来存储线程需要的数据 15 | typedef struct 16 | { 17 | FilePaths *pFileList; // 指向文件路径列表的指针 18 | complex *data_buffer; // 指向数据缓冲区的指针 19 | size_t start; 20 | size_t end; 21 | size_t file_start; // 开始处理的文件索引 22 | size_t file_end; // 结束处理的文件索引 23 | size_t vec_count; // 每一道数据的大小 24 | } thread_info_read; 25 | 26 | // 线程池结构体定义 27 | typedef struct 28 | { 29 | pthread_t *threads; 30 | thread_info_read *tinfo; 31 | size_t num_threads; 32 | } ThreadPoolRead; 33 | 34 | ThreadPoolRead *create_threadpool_read(size_t num_threads); 35 | int ReadSpecArrayParallel(FilePaths *pFileList, complex *data_buffer, size_t start, size_t end, 36 | size_t vec_count, ThreadPoolRead *pool); 37 | void destroy_threadpool_read(ThreadPoolRead *pool); 38 | #endif -------------------------------------------------------------------------------- /src/xc_multi/par_write_sac.h: -------------------------------------------------------------------------------- 1 | #ifndef _PAR_WRITE_H 2 | #define _PAR_WRITE_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "node_util.h" 8 | #include "gen_ccfpath.h" 9 | 10 | typedef struct 11 | { 12 | PAIRLIST_MANAGER *manager; // 包含了源台索引 13 | FilePaths *src_path_list; // 虚拟源文件路径列表 14 | FilePaths *sta_path_list; // 虚拟台文件路径列表 15 | size_t start; // 处理的起始索引 16 | size_t end; // 处理的结束索引 17 | float *ncf_buffer; // 用于存储交叉相关函数结果的缓冲区 18 | float delta; // 互相关采样间隔 19 | int ncc; // 交叉相关数据点的数量 20 | float cc_length; // lapse time 半个互相关长度 21 | char *output_dir; // 输出文件路径 22 | } thread_info_write; 23 | 24 | typedef struct 25 | { 26 | pthread_t *threads; 27 | thread_info_write *tinfo; 28 | size_t num_threads; 29 | } ThreadWritePool; 30 | 31 | ThreadWritePool *create_threadwrite_pool(size_t num_threads); 32 | 33 | void destroy_threadwrite_pool(ThreadWritePool *pool); 34 | 35 | int write_pairs_parallel(PAIRLIST_MANAGER *manager, FilePaths *src_path_list, FilePaths *sta_path_list, 36 | float *ncf_buffer, float delta, int ncc, float cc_length, 37 | char *output_dir, ThreadWritePool *pool); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/xc_multi/read_segspec.c: -------------------------------------------------------------------------------- 1 | #include "read_segspec.h" 2 | 3 | /* read the segment spectrum and return whole spec array 4 | * and header using preallocated buffer 5 | * 6 | * wuchao@20211004 7 | * */ 8 | complex *read_spec_buffer(char *name, SEGSPEC *hd, complex *buffer) 9 | { 10 | FILE *strm = NULL; 11 | int size; 12 | 13 | if ((strm = fopen(name, "rb")) == NULL) 14 | { 15 | fprintf(stderr, "Unable to open %s\n", name); 16 | return NULL; 17 | } 18 | 19 | if (fread(hd, sizeof(SEGSPEC), 1, strm) != 1) 20 | { 21 | fprintf(stderr, "Error in reading SEGSPEC header %s\n", name); 22 | return NULL; 23 | } 24 | 25 | /* read whole segment spectrum in 26 | * Total size is nseg*nspec*sizeof(our_float_complex) */ 27 | size = sizeof(complex) * hd->nspec * hd->nstep; 28 | 29 | if (fread((char *)buffer, size, 1, strm) != 1) 30 | { 31 | fprintf(stderr, "Error in reading SEGSPEC data %s\n", name); 32 | return NULL; 33 | } 34 | 35 | fclose(strm); 36 | 37 | return buffer; 38 | } 39 | 40 | /* read the segment spectrum header 41 | * 42 | * wuchao@20211004 43 | * */ 44 | 45 | int read_spechead(const char *name, SEGSPEC *hd) 46 | { 47 | FILE *strm; 48 | if ((strm = fopen(name, "rb")) == NULL) 49 | { 50 | fprintf(stderr, "Unable to open %s\n", name); 51 | return -1; 52 | } 53 | 54 | if (fread(hd, sizeof(SEGSPEC), 1, strm) != 1) 55 | { 56 | fprintf(stderr, "Error in reading SAC header %s\n", name); 57 | fclose(strm); 58 | return -1; 59 | } 60 | 61 | fclose(strm); 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /src/xc_multi/read_segspec.h: -------------------------------------------------------------------------------- 1 | #ifndef _RDSPEC_H 2 | #define _RDSPEC_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "complex.h" 8 | #include "segspec.h" 9 | 10 | // Read in a spec file and store in buffer 11 | complex *read_spec_buffer(char *name, SEGSPEC *hd, complex *buffer); 12 | 13 | // Read in a spec file header 14 | int read_spechead(const char *name, SEGSPEC *hd); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/xc_multi/read_spec_lst.c: -------------------------------------------------------------------------------- 1 | #include "read_spec_lst.h" 2 | 3 | #include 4 | 5 | FilePaths *read_spec_lst(char *spec_lst_file) 6 | { 7 | FILE *fp; 8 | char line[MAXLINE]; 9 | int count = 0; 10 | FilePaths *data = (FilePaths *)malloc(sizeof(FilePaths)); 11 | data->paths = NULL; 12 | 13 | if (!(fp = fopen(spec_lst_file, "r"))) 14 | return NULL; 15 | 16 | while (fgets(line, sizeof(line), fp)) 17 | { 18 | // remove newline character from line, if present 19 | char *pos; 20 | if ((pos = strchr(line, '\n')) != NULL) 21 | *pos = '\0'; 22 | 23 | // Skip empty lines 24 | if (line[0] == '\0') 25 | continue; 26 | 27 | // realloc memory to fit the new path 28 | data->paths = (char **)realloc(data->paths, (count + 1) * sizeof(char *)); 29 | data->paths[count] = my_strdup(line); // copy the string 30 | count++; 31 | } 32 | 33 | fclose(fp); 34 | data->count = count; 35 | return data; 36 | } 37 | 38 | void freeFilePaths(FilePaths *fp) 39 | { 40 | int i; 41 | if (fp == NULL) 42 | { 43 | return; 44 | } 45 | 46 | if (fp->paths != NULL) 47 | { 48 | for (i = 0; i < fp->count; i++) 49 | { 50 | free(fp->paths[i]); 51 | } 52 | free(fp->paths); 53 | } 54 | 55 | free(fp); 56 | } 57 | -------------------------------------------------------------------------------- /src/xc_multi/read_spec_lst.h: -------------------------------------------------------------------------------- 1 | #ifndef _READ_SPEC_LST_H 2 | #define _READ_SPEC_LST_H 3 | 4 | #include "config.h" 5 | #include "node_util.h" 6 | #include "segspec.h" 7 | #include "read_segspec.h" 8 | #include "util.h" 9 | #include 10 | #include 11 | #include 12 | 13 | FilePaths *read_spec_lst(char *spec_lst_file); 14 | 15 | void freeFilePaths(FilePaths *fp); 16 | 17 | #endif -------------------------------------------------------------------------------- /src/xc_multi/readme.txt: -------------------------------------------------------------------------------- 1 | ************************************************************************** 2 | * This code is for Green's function extraction using long time ambient noise 3 | * cross correlation for single component,usually ZZ 4 | * 5 | * Input files are previously created segment-spectrums. This vector version 6 | * requires you specify two input from the same component at one time. 7 | * 8 | * 1.Those file by -A is take as virtual source 9 | * while file by -B is taken as virtual station 10 | * 11 | * the NCF.evlo and NCF.evla are set to be position of source 12 | * and NCF.stlo and NCF.stla are set to be position of station. 13 | * also we save the knetwk and kstnm of station as NCF's netwk and stnm 14 | * and we save the knetwk and kstnm of source as NCF's kevnm. 15 | * Since kevnm is 16 characters(include terminate \0), we set evnm to 16 | * kevnm=A.knetwk space A.kstnm, this is consistent by taking A as source. 17 | * 18 | * Azimuth is the angle clockwise between vector north and vector 19 | * Source->Station and back-azimuth is the angle clockwise between vector 20 | * north and vector Station->Source so you can check the source direction 21 | * using all NCF ends with B according the baz. wangwt@20101028 22 | * 23 | * Also we set the cmpaz and cmpinc for 1st and 2nd station in NCF sacheader 24 | * 25 | * 2.kcomp will be created using the last character in chnnm of two input if 26 | * it is not esplicitly set by -N 27 | * 28 | * 3.For 2nd station, the cmpaz and cmpinc are stored in sac.cmpaz and sac.cmpinc 29 | * For 1st station, the original sac header do not have coresponding key, so 30 | * I change sachd.unused11 to sachd.scmpaz to store cmpaz for 1st station 31 | *while change sachd.unused12 to sachd.scmpinc to store cmpinc for 1st station 32 | * You can use unuser11 or 12 to access those value and they should be used 33 | * mainly in tensor NCF rotation. wangwt@20160701 34 | * 35 | * 36 | * History: 37 | * 1. init by wangwt@2015 38 | * 2. add scmpaz and scmpinc by wangwt@20160701 39 | * 3. set khole and kinst so we have complete info of Net.Sta.Loc 40 | * for both virt source and virt station. wangwt@20160711 41 | * 4. add -D option, very simple but could output NCFs of each small segment@2018 42 | * 5. add -S option, change the target directory style of output ncfs, by 43 | *stations wangjx@2022 44 | * 45 | * last update wangwt@20181125 46 | * 47 | * Cuda Version History: 48 | * 1. init by wuchao@202105 49 | * 2. use 2d cuda threads to perform batch processing of list of pairs of spec 50 | *files, X: segments of spec pair, Y: list of pairs of spec files 51 | * 3. use cuda to implement speccc and etc 52 | * 4. use cufft to perform FFT/IFFT transform 53 | * 5. add -RD option to avoid calculating duplicate NCFs. Like A2B and B2A 54 | *wangjx@2022 55 | * 56 | * last update by wuchao@20211008 57 | * last updated by wangjx@20230716 58 | * **************************************************************************/ -------------------------------------------------------------------------------- /src/xc_multi/segspec.h: -------------------------------------------------------------------------------- 1 | /* Header for the segment by segment spectrum for noise cross correlation 2 | * History: 3 | * 1. init by wangwt to speed up CC on huge dataset. 4 | * 5 | * last update wangjx@20230504 6 | * */ 7 | 8 | #ifndef _SEGSPEC_H 9 | #define _SEGSPEC_H 10 | 11 | typedef struct segspec_s 12 | { 13 | float stla; 14 | float stlo; 15 | /* segment info */ 16 | int nstep; 17 | 18 | /* FFT info */ 19 | int nspec; /* use fftr() number of complex eg 2*nspec float */ 20 | float df; 21 | float dt; 22 | 23 | } SEGSPEC; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/xc_multi/util.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTIL_H 2 | #define _UTIL_H 3 | 4 | #include 5 | #include 6 | 7 | size_t QueryAvailCpuRam(); 8 | size_t EstimateCpuBatch(size_t fixedRam, size_t unitRam); 9 | void CpuMalloc(void **pptr, size_t sz); 10 | void CpuCalloc(void **pptr, size_t sz); 11 | void CpuFree(void **pptr); 12 | char* my_strdup(const char* s); 13 | #endif 14 | -------------------------------------------------------------------------------- /test_data/0101/2017/0101.2017.237.0000.E.sac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/test_data/0101/2017/0101.2017.237.0000.E.sac -------------------------------------------------------------------------------- /test_data/0101/2017/0101.2017.237.0000.N.sac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/test_data/0101/2017/0101.2017.237.0000.N.sac -------------------------------------------------------------------------------- /test_data/0101/2017/0101.2017.237.0000.Z.sac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/test_data/0101/2017/0101.2017.237.0000.Z.sac -------------------------------------------------------------------------------- /test_data/0101/2017/0101.2017.238.0000.E.sac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/test_data/0101/2017/0101.2017.238.0000.E.sac -------------------------------------------------------------------------------- /test_data/0101/2017/0101.2017.238.0000.N.sac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/test_data/0101/2017/0101.2017.238.0000.N.sac -------------------------------------------------------------------------------- /test_data/0101/2017/0101.2017.238.0000.Z.sac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/test_data/0101/2017/0101.2017.238.0000.Z.sac -------------------------------------------------------------------------------- /test_data/0101/2017/0101.2017.239.0000.E.sac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/test_data/0101/2017/0101.2017.239.0000.E.sac -------------------------------------------------------------------------------- /test_data/0101/2017/0101.2017.239.0000.N.sac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/test_data/0101/2017/0101.2017.239.0000.N.sac -------------------------------------------------------------------------------- /test_data/0101/2017/0101.2017.239.0000.Z.sac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/test_data/0101/2017/0101.2017.239.0000.Z.sac -------------------------------------------------------------------------------- /test_data/0107/2017/0107.2017.237.0000.E.sac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/test_data/0107/2017/0107.2017.237.0000.E.sac -------------------------------------------------------------------------------- /test_data/0107/2017/0107.2017.237.0000.N.sac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/test_data/0107/2017/0107.2017.237.0000.N.sac -------------------------------------------------------------------------------- /test_data/0107/2017/0107.2017.237.0000.Z.sac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/test_data/0107/2017/0107.2017.237.0000.Z.sac -------------------------------------------------------------------------------- /test_data/0107/2017/0107.2017.238.0000.E.sac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/test_data/0107/2017/0107.2017.238.0000.E.sac -------------------------------------------------------------------------------- /test_data/0107/2017/0107.2017.238.0000.N.sac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/test_data/0107/2017/0107.2017.238.0000.N.sac -------------------------------------------------------------------------------- /test_data/0107/2017/0107.2017.238.0000.Z.sac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/test_data/0107/2017/0107.2017.238.0000.Z.sac -------------------------------------------------------------------------------- /test_data/0107/2017/0107.2017.239.0000.E.sac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/test_data/0107/2017/0107.2017.239.0000.E.sac -------------------------------------------------------------------------------- /test_data/0107/2017/0107.2017.239.0000.N.sac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/test_data/0107/2017/0107.2017.239.0000.N.sac -------------------------------------------------------------------------------- /test_data/0107/2017/0107.2017.239.0000.Z.sac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/test_data/0107/2017/0107.2017.239.0000.Z.sac -------------------------------------------------------------------------------- /utils/GPU_vs_CPU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/utils/GPU_vs_CPU.png -------------------------------------------------------------------------------- /utils/check_gpu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangkingh/FastXC/3915345053414e6f92611327941ebc189d3b15be/utils/check_gpu -------------------------------------------------------------------------------- /utils/check_gpu.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(){ 5 | int nDevices; 6 | cudaGetDeviceCount(&nDevices); 7 | for (int n=0;n