基于MATLAB的被动源面波频散曲线反演程序全解析

发布时间:2026/10/20 16:53:23
基于MATLAB的被动源面波频散曲线反演程序全解析
简介一套基于MATLAB的被动源面波频散曲线反演程序源码主要面向地球物理学、地震勘探及地质工程领域的科研人员和高校学生解决从自然或人为产生的环境噪声中分离面波信号进而反演浅层地壳速度结构和介质参数的问题。程序利用被动源方式无需人工激发地震波具有成本低、应用灵活的特点。压缩包共包含18个文件其中17个为MATLAB脚本.m1个为Markdown说明文档.md整体大小仅24KB代码结构紧凑便于研读和修改。已有715人下载学习。程序覆盖了频散曲线提取与反演的主要流程涉及信号处理、数值计算和优化算法具体包括Haskell矩阵递推、快速Hankel变换、Muller求根法、Rayleigh波频散正演以及薄层近似方法并附有示例脚本和完整说明文档。该资源可作为地球物理反演课程的教学案例也可为相关科研工作提供可扩展的参考代码帮助读者深入理解被动源面波方法的核心原理与MATLAB实现细节。1. 拿到被动源面波反演程序包先搞清它到底要替你解决哪一步做浅层场地勘察的人把「基于MATLAB的被动源面波频散曲线反演程序.zip」下到手后最想问的往往不是“它支持什么算法”而是“我自己的数据放进去能不能出结果”。这个标题表面是一个反演程序包实际对应的是被动源面波也就是微动勘察里最关键的环节你已经通过台阵观测拿到了频散曲线需要把它换回地层的剪切波速度。程序包能替你自动完成反演搜索但替你不了另外两件事——提取出可信的频散曲线、判断反演结果是否可靠。常接触这类工具的人会有一个反直觉的体验反演程序本身跑通只要几分钟最耗时间的却是数据准备和参数边界设定。这类包适合已经能提取频散曲线、但反复被一维反演卡住的从业者也适合刚把MATLAB跑熟、想把手动试算流程改成批量处理的工程人员。下面从原理、数据约定一直拆到反演参数的落地和避坑。2. 被动源面波频散曲线反演是怎么回事程序包里到底装了什么2.1 从微动记录到剪切波速度整条链路的关键词拆解被动源面波的“被动源”对应的是主动源面波人工锤击、落重激发。被动源不自己造信号而是记录环境中海浪、风、交通等随机振动形成的背景波场。这类振动以瑞利面波为主且天然是宽频的零点几赫兹到十几赫兹都可能带能量。用规则台阵记录这些随机振动之后通过频域处理能找到“相速度随频率变化的关系”那就是频散曲线。频散曲线之所以有用是因为不同频率的波对地层深度的敏感程度不同高频波走浅层速度反映的是浅部地层低频波往深部跑速度反映深部地层。于是“相速度对频率的曲线”就成了地层速度结构在频域的投影。但这层投影没有解析的反演公式。给定一条实测频散曲线地层可能有很多种组合方式都能生产出近似相同的理论频散曲线这就是被动源面波反演经常被形容成“玄学”的原因。反演程序做的事本质是“正演搜索”先假设一个层状介质模型算出理论频散曲线跟实测曲线比对差异大就换一组地层参数再算直到差异足够小。整条链路是台阵观测记录→预处理→频散曲线提取→反演→一维剪切波速度剖面。标题里的反演程序只负责最后那段但前面环节的质量直接决定反演结果是否可信。为什么这类程序多拿MATLAB来写一是矩阵运算对频谱分析和正演计算太顺手二是优化工具箱和自写的遗传算法都能直接跑三是出图方便频散拟合图和速度剖面图几行指令就能画出来。对使用者来说这意味着改动算法、换目标函数、调层参数都相对容易这也是自己手里握一份MATLAB代码比闭源商业软件更灵活的地方。2.2 拿到.zip后的第一个小时先读文件结构和配置这类zip解压以后典型的结构通常由四块组成主脚本、函数目录、数据目录和结果输出目录。主脚本一般是“从读数据到出图”的一站式入口函数目录里至少会有正演函数、频散曲线读取函数、优化算法函数数据目录里往往带一组示例观测数据或示例频散曲线用来让用户先跑通再换自己的数据结果输出目录存放每一代最优目标函数值、最终反演模型和拟合图。我拿到任何这类包的习惯是不先碰代码先找读数据的入口和配置项。具体的动作用四步走先解压浏览根目录下的文件名确认主脚本是哪个打开主脚本或配置文件逐行看它读了哪些文件、调用了哪些函数用示例数据完整跑一遍记录运行时间量级和输出文件种类改掉一个无关紧要的配置项再跑一次确认输出确实有变化。这样做的目的是给程序包建立一个“基准行为”后续任何改动都能拿这个基准来对照。扩展地说这类包通常会把下面几项暴露在最外层频带范围、台阵孔径相关参数、层数设置、反演边界、优化代数。这些参数名义上“可调”但新手最容易改坏的是频带范围——高频设得太高而台站间距撑不住高频段分辨反演出一个虚浮的表层速度低频设得太低而记录时长不够低频能量本来就弱拾取出来的曲线不可信。所以拿到程序包先别急着动算法把配置参数里的物理含义逐一对应到自己的数据上这一步花半小时后面能省半天排错。2.3 程序包的数据约定输入文件和数据矩阵的组织频散曲线反演程序的输入可以分成三类台阵时间序列、台站坐标、拾取好的频散曲线。其中前两项是提取频散曲线用的第三项是反演直接消费的数据。大多数包会把输入数据组织成文本文件或.mat文件文本文件常见格式如下表文件内容常见组织方式需要注意的单位台阵记录每行一个台站每列一个采样时刻采样率 Hz时间序列幅值单位统一台站坐标两列X, Y按台站序号排列一律用 m不要混入经纬度频散曲线两列第1列频率 Hz第2列相速度 m/s相速度单位固定不要 km/s被这个表的单位坑过的人不少。坐标一旦度/米混填F-K 谱会直接变得不可读频散曲线速度单位从 m/s 写成 km/s反演目标函数在初期就给出巨大误差优化算法会把参数推向边界。读配置时我会格外确认三个点第一程序按行还是按列读台站数据第二坐标是否需要中心化第三频散曲线文件里有没有表头。这三个点全部对齐数据层基本稳了后面才是反演本身的调参问题。3. 把实测记录整理成频散曲线这一步决定了反演有没有意义3.1 预处理去均值、去趋势还有那个绕不开的带通滤波微动记录的预处理没有多玄学核心目标就是让后续频谱分析面对的是相对平稳的地脉动信号而不是仪器直流偏置和温漂叠加出来的“假低频”。现场记录里常见的干扰包括大电流或直流分量引起的零线偏移、长时间尺度线性漂移、局部的近源干扰附近车辆、施工振动。这些干扰对低频段影响最大而低频段恰好又是约束深部速度的关键所以预处理是频散曲线提取的前置关卡。我的习惯是先做去均值和去线性趋势再做带通滤波。频率下限参考台阵孔径和记录时长上限参考台站间距没有绝对标准但 0.2~10 Hz 是一个在浅层场地勘察里高频出现的经验范围。下面这段是常规做法% data_in : n_station x n_sample 的原始台阵记录 % fs : 采样率单位 Hz data_in data_in - mean(data_in, 2); % 去掉每个台站的直流分量 data_in detrend(data_in., linear).; % 去掉线性趋势避免低频漂移污染频散谱 data_f bandpass(data_in., [0.2 10], fs).;逻辑上去直流和去趋势解决的是“能量集中在零频附近”的问题带通滤波解决的是“频带外的强干扰把弱频散信号淹没”的问题。bandpass 函数的具体用法取决于程序包运行环境重点是参数要跟数据实际有效频带匹配不能照抄。滤波阶数太高会让时间序列边缘剧烈震荡频率越低越明显看到谱图边缘出现异常条纹时先把阶数降下来而不是急着调谱参数。3.2 用F-K变换从台阵数据中提取频散谱从台阵记录提取频散曲线主流方法是频率-波数法F-K和扩展空间自相关法ESPAC。F-K 的思路是把台阵记录变换到频率-波数域在某一频率上能量峰值对应的波数与相速度满足 v f / k把这些峰值连起来就是频散曲线。F-K 直观、分辨率好适合规则台阵ESPAC 通过台站对之间的空间自相关拟合贝塞尔函数更适合台阵不规则、信号随机性强的场景。标题里的反演程序即使只负责反演上游也需要产出可信频散曲线的过程我把常用的 F-K 骨架写在这里function [freq_list, vel_list, energy_map] fk_scan(station_data, station_xy, fs, freq_band, v_grid) % station_data : n_station x n_sample预处理后的记录 % station_xy : n_station x 2台站平面坐标单位 m % fs : 采样率单位 Hz % freq_band : 扫描频带 [fmin fmax]单位 Hz % v_grid : 相速度扫描网格单位 m/s station_xy station_xy - mean(station_xy, 1); % 中心化坐标减少大坐标导致的相位计算精度问题 freq_step 0.1; % 频率扫描步长 freq_list freq_band(1):freq_step:freq_band(2); energy_map zeros(numel(v_grid), numel(freq_list)); for i_f 1:numel(freq_list) fc freq_list(i_f); data_f bandpass(station_data., [fc-0.15 fc0.15], fs).; % 窄带滤波 for i_v 1:numel(v_grid) s 1 / v_grid(i_v); % 慢度 s 1/v phase 2 * pi * s * (station_xy(:,1)*0.6 station_xy(:,2)*0.8) * fc; energy_map(i_v, i_f) abs(sum(data_f .* exp(1i * phase), 2)); end end这里用 0.6 和 0.8 代表一个方位角的投影系数真正的 F-K 处理需要在多个方位角上重复扫描取最大值或者直接在 kx、ky 网格上做二维谱再转极坐标这段代码的核心是展示“相位校正 能量叠加”的逻辑。参数上有几个点值得注意频率步长 0.1 Hz 是平衡计算耗时和谱分辨率的常见选择窄带滤波带宽 ±0.15 Hz 对应“带宽不大于扫描步长”的经验太宽会让邻近频率的谱峰串扰v_grid 的范围应该覆盖台阵能分辨的速度极限取太窄会丢真实峰值取太宽会明显拉长计算时间。3.3 把频散谱读成一条曲线峰值拾取与质量控制得到能量谱矩阵之后最常用的操作是画等值线图找到明亮的能量脊线然后沿着脊线拾取频散曲线。自动拾取通常是对每一频率列找出最大能量对应的速度但实际数据里高频端常有多条能量脊存在这是基阶和高阶面波混叠造成的自动拾取可能跨模态拼出一条错误曲线。我一般先在彩色谱图上“人眼确认”能量脊的大致形态再自动拾取最后手工删掉低信噪比的频点。这条曲线宁可短一点只保留能量集中且形态连续的段落也不要为覆盖宽频带而把不可靠的峰值硬选进去。质量控制有一条实际经验低频端几个点决定深层速度的大致水平往往只有两三个点可信高频端能约束浅层但受台站最小间距限制间距不足时高频端曲线会假性上升或下降。把这种坏点喂给反演后面再好的优化算法也救不回来这是我在整条链路上踩得最深的一次。另外如果程序包里自带频散曲线提取模块验证它是否正常工作的办法是用示例数据跑一遍把提取出的曲线和示例自带结果对比允许少量人工拾取差异但不允许系统性偏移。系统性偏移通常意味着滤波带宽、坐标或扫描网格设置有误这类问题会在反演结果里放大成明显的速度错层。注意拾取频散曲线时宁短勿假。曲线短了只是反演深度范围小一点曲线假了反演会给你一套看似收敛、实则无意义的速度模型。4. 频散曲线反演的核心逻辑与可复用主流程4.1 正演是反演的基石层状介质理论相速度怎么算正演是根据地层参数计算理论频散曲线的过程。被动源面波反演里正演模型一般是水平层状半空间每一层有纵波速度、横波速度、密度和厚度最后加一个半空间。理论频散曲线由波动方程在层间界面上满足连续条件推导出来常见实现是传递矩阵法。这类计算在几十层以内都很快一次正演调用只有毫秒级所以全局优化里调用几千次甚至上万次完全可接受。正演函数在反演程序里的地位很容易被低估。反演要“用理论曲线去逼近实测曲线”正演一旦有边界条件错误比如层厚度为负、半空间速度小于上覆层速度、纵波速度算出来低于横波速度理论曲线就会出虚数值或阶跃跳变优化过程就表现为“无论怎么迭代目标函数都下不来”。我检查这类包时会先单独调用一次正演函数输入一个简单的两层模型观察输出是否平滑不平滑就先处理正演的数值稳定性而不是急着调反演参数。4.2 反演目标函数与模型参数化先决定反什么和不反什么参数化的含义是设定哪些参数交给算法搜索哪些参数固定不动。全参数搜索理论上可行实际中不可行——横波速度对频散曲线最敏感纵波速度和密度不敏感全搜不仅浪费算力还会引入大量等效模型让反演解在物理上不合理。常见做法是只让层横波速度 vs 和层厚度 h 参与反演纵波速度用固定的 vp/vs 比值推密度用经验公式从 vs 推算这样反演空间小结果稳定也是多数程序包的默认做法。目标函数的选择也会直接影响反演行为。绝对误差m/s会让速度值大的高频段在目标函数里占据主导相对误差百分比对所有频点更公平。工程上低频段点少但约束深层的作用大常按频率倒数加权这需要程序包支持权重配置。一条典型的目标函数长这样function misfit dispersion_misfit(params, layers, obs_freq, obs_vel) % params : 待反演参数前 layers.nlayer 个为各层 vs后面为各层厚度 % layers : 固定参数结构体层数、vp/vs 比、密度系数、半空间参数 % obs_freq : 实测频散曲线频率列单位 Hz % obs_vel : 实测频散曲线相速度列单位 m/s % 返回 misfit : 相对均方根误差单位百分比 vs params(1:layers.nlayer); h params(layers.nlayer1:end); vp vs * layers.vp_vs_ratio; % 固定 vp/vs 换算 rho 1.8 0.2 * (vs / 1000); % 经验密度公式单位 g/cm3 v_theory layered_phase_velocity(vs, h, vp, rho, layers.half_space, obs_freq); misfit sqrt(mean(((v_theory - obs_vel) ./ obs_vel).^2)) * 100; end参数说明里要注意几个量级vp_vs_ratio 一般取 1.7~2.0取 1.73 对应泊松比约 0.25取 2.0 对应泊松比接近 0.33不同地区土体差异明显rho 的经验公式是工程物探里的常见粗估频散曲线对密度不敏感不必追求精确密度。遇到场地存在明显低速层时初始模型范围要把“低速夹层”的可能性放进去否则算法很难自己长出低速层。4.3 用全局优化跑一遍反演遗传算法参数与收敛判断这类反演程序大量任务由遗传算法承担也有用粒子群、模拟退火的思路都一样在参数边界内随机生成一批候选模型按目标函数值选优、交叉、变异迭代多代。稳妥的做法是先不追求花哨算子用标准 GA 跑看收敛趋势稳定后再加约束。主循环骨架如下% 遗传算法主循环示意结构算子函数按程序包现状实现 pop_size 60; % 种群规模 max_gen 150; % 最大代数 crossover_rate 0.8; % 交叉概率 mutation_rate 0.15; % 变异概率 elite_count 2; % 精英保留个数 % lb、ub 是每个参数的上下边界向量 pop initialize_population(pop_size, lb, ub); best_cost zeros(max_gen, 1); for gen 1:max_gen for i 1:pop_size fitness(i) dispersion_misfit(pop(i,:), layers, obs_freq, obs_vel); end parents tournament_select(pop, fitness, 2); % 锦标赛选择 children crossover_and_mutate(parents, crossover_rate, mutation_rate, lb, ub); pop keep_elites(pop, children, fitness, elite_count); % 精英保留 best_cost(gen) min(fitness); end遗传算法各参数的落地建议我给一张常用表参数建议范围说明种群大小30~80待反演参数多时取大值少时取小值最大代数100~250best_cost 平台化即可提前停止交叉概率0.7~0.9太低收敛慢太高容易破坏已找到的好模型变异概率0.05~0.2变异太大会跳过窄谷结果不稳定精英个数2~4防止每一代的最优个体被下一代覆盖丢失判断收敛不要只看代数要同时看两件事best_cost 曲线在几十代内进入平台期最终模型的理论频散曲线在所有频段贴着实测点走。只做到第一点意味着算法收敛了但可能收敛到局部最优需要扩大初始模型范围或换随机种子重跑。4.4 反演出来了怎么读收敛曲线和拟合图程序包输出通常会包含三类文件目标函数迭代曲线、频散拟合对比图、一维剪切波速度剖面。读的时候按顺序来先看拟合图理论曲线和实测曲线是否在整段范围内贴合重点关注低频端是否系统性偏大或偏小再看迭代曲线确认收敛过程没有中途跳变最后才看速度剖面核对表层速度是否符合场地经验。剖面出现表层速度过低、深层速度震荡优先回查频散曲线拾取质量和边界设定而不是立刻怀疑程序。5. 反演翻车现场5个频散曲线反演常见问题与避坑从使用反馈来看真正让频散曲线反演翻车的场景里程序本身的缺陷占比不高更多是数据在输入端就已经变形或者参数边界没给对。下面五条按我遇到的出现频率排序。5.1 频点一多就发散把实测曲线每个点都喂进反演的代价现象拾取了四五十个频点全部参与反演低频段始终对不上目标函数收敛不下来换随机种子反复跑结果也不一致。 原因相邻频点反映的地下信息高度相关几十、上百个点实际上只包含几个自由度的独立信息密集的高频点还会在目标函数里占压倒性权重低频段被迫牺牲。 解决把频散曲线抽稀按每 0.5~1 Hz 取一个点或者切分频段后分别加权优先保留低频端能量清晰的点。改完之后拟合图低频段通常会有立竿见影的改善。5.2 速度总是打到边界值初始模型范围没给对现象反演出来的层速度贴着初始上界或下界走速度剖面出现明显棱角改初始值结果跟着变。 原因初始模型边界设定不符合场地实际算法碰到边界后被截住无法在边界外寻找更优解多解空间被人为切断。 解决第一轮用宽边界跑记录最优解落点第二轮把边界缩到最优解附近再跑。如果缩窄后结果仍落在边界上说明该层实际速度可能更软或更硬需要扩大边界或改变层参数化方式而不是继续加迭代。5.3 正演函数报错或理论曲线断裂厚度和半空间的隐形约束现象迭代过程中目标函数突然变成 NaN或理论频散曲线在某些频率处断裂跳变。 原因交叉变异之后层厚度变为负数或小于某个最小厚度半空间速度被算成小于上覆层速度或者 vp/vs 比让纵波速度低于横波速度正演矩阵出现奇异。 解决变异算子之后把参数夹断回合法边界厚度加最小约束浅层一般取 1~5 m半空间速度显式强制大于上覆层正演函数内部对非法输入直接返回一个大惩罚值而不是让计算崩溃。5.4 相邻测点速度剖面不衔接低频段分辨率不足的典型表现现象同一场地相邻测点单点反演拟合效果都很好但速度剖面在中深部出现单点层的突变测点之间不连续。 原因低频段有效信息本来就少低频点不足时深部层位约束不够各测点的中深部参数处于“自由落体”状态。 解决在拾取阶段低频端多保留几个有效点对深部层厚度加初始约束条件允许时做整条测线的横向平滑约束让相邻测点共享部分深部参数后再反演。5.5 谱图一团乱台阵坐标单位与中心化的坑现象计算出的 F-K 谱完全没有清晰能量脊或者反演拟合曲线很好但速度值离谱。 原因台站坐标用了不同单位、轴向定义和程序预期不一致或者没有做坐标中心化导致相位计算精度丢失。 解决统一坐标单位为 m核对程序约定的坐标轴方向坐标输入后做中心化并打印坐标范围检查拿示例数据跑通后再替换自己的数据确认问题确实出在数据侧而非程序侧的约定。6. 确认反演结果能交付的三步验证法6.1 用合成正演做自检一套永不丢的标准答案反演程序最容易让人困惑的问题是它给的结果对不对。最可靠的做法永远是合成测试构造一个已知的层状模型用正演算出理论频散曲线加 2%~3% 随机噪声后交给反演程序再把反演结果和已知模型对比。这个测试能同时验证数据读取、正演、优化、输出四个环节因为情况完全已知哪里出错都能定位。程序包每次换配置后先用同一组合成模型跑一遍相当于给程序建立了一套常驻标准答案。6.2 交付前检查拟合误差、相邻测点一致性、与既有资料对比实测数据反演结果拿到后不要急着出报告先过三道检查。第一道是拟合误差理论频散曲线和实测曲线之间的相对误差在低频段是否也控制在 3% 左右而不只是高频段好看。第二道是相邻测点一致性同一场地沿测线画一维剖面相邻点的层速度变化应当是渐变的出现单点突变先查拾取数据和边界设置。第三道是和既有资料对比有钻孔波速或主动源结果最直接完全没资料时把表层 vs 和场地地貌成因经验对照深部速度应当向区域背景值靠拢。6.3 敏感性检查哪些参数被约束住了哪些只是凑出来的最后一步是敏感性检查。把最优模型的各层速度逐一加减 10%重新正演看它引起理论频散曲线的变化幅度。变化大的层位说明当前数据对它约束得好几乎不变的层位说明数据对该层不敏感那层的结果只能作参考不能作为设计依据。这个检查放在报告里比只贴一条反演曲线有力得多。到现在我仍然保持同一个习惯任何反演程序包到手先做合成自检再做三查最后做敏感性检查。被动源面波反演程序的价值在于把人的经验压缩到参数边界和目标函数里而不是替人做地质判断——该人工复核的环节一步都不能省。希望帮到你。本文还有配套的精品资源点击获取