简介:本资源是一套面向地球物理勘探研究人员与高校地质/地球物理专业学生的地震速度分析MATLAB工具包,聚焦波速转换计算、均方根速度(Vrms)求解及纵横波速度(VP/VS)联合分析等核心任务,适用于油气勘探前期数据处理与地层建模场景。压缩包共含4个文件:2个MATLAB脚本(vr_vi.m实现波速转换与Vrms计算,Test_velocity_analyses.m用于算法验证)、1个MATLAB数据文件(data.mat提供实测或预处理地震速度数据)、1个中文说明文本(19-12-3备注.txt详述调用逻辑、参数含义与结果解读),整体仅1KB,轻量实用。已有211人学习下载,适合初涉地震速度建模的研究者快速上手——可直接运行获取Vrms值,复现经典波速反演流程,并结合备注文档理解地层速度参数的地质意义与工程应用边界。
1. VR-VI 波速转换不是“套公式”,而是地震勘探里最常翻车的速度建模起点
你在处理地震剖面时,是否遇到过:明明叠前时间偏移结果看起来很干净,但井震标定总差20~50ms?或者速度谱上 picked 的均方根速度(RMS velocity)一输进深度转换模块,就发现构造高点歪了300米?——这大概率不是成像算法的问题,而是你手里的 VR-VI 波速转换关系没校准到位。VR(Vertical Ray velocity,垂直入射速度)和 VI(Interval velocity,层间速度)之间看似只差一个数学变换,实则牵扯到速度模型的物理合理性、时深关系的非线性误差累积、以及地震资料信噪比对 RMS 速度拾取的隐性污染。本篇不讲教科书定义,只聚焦一线地震解释工程师每天要亲手敲命令、调参数、查曲线的真实场景:如何用开源 Python 工具链,从原始速度谱或测井速度曲线出发,稳定反演 VI,并验证 VR→VI 转换后生成的速度模型能否通过井控深度误差 < 5m 的硬指标。适合已跑通常规叠前处理流程、正卡在构造建模精度瓶颈上的物探工程师,也适合地质建模人员理解为什么你的网格化速度体总在断层附近“发虚”。
2. 理解 VR-VI 转换的本质:不是代数游戏,而是时深关系的微分重构
2.1 为什么 RMS 速度不能直接当层速度用?——从时深积分反推物理约束
地震记录的时间轴(t)是波沿垂直路径传播的双程走时,而地质建模需要的是每一段地层的真实传播速度(VI),即单位厚度所需单程时间的倒数。RMS 速度(VR)本质是把一段地层等效为均匀介质后算出的“表观速度”,其数学定义为:
$$ V_{RMS}^2(t) = \frac{1}{t} \int_0^t V_I^2(\tau) , d\tau $$
注意:这个公式里 $ V_I(\tau) $ 是时间域的层速度函数,$ \tau $ 是零偏移时间(zero-offset time),不是深度!这意味着——
✅ 正确做法:先用测井或层析反演得到 $ V_I(z) $,再通过时深关系 $ t(z) = \int_0^z \frac{2}{V_I(z')} dz' $ 积分得 $ t(z) $,最后按上式计算 VR;
❌ 常见翻车:把深度域的 VI 曲线直接套进 RMS 公式(误用 $ z $ 当 $ t $),或把 VR 曲线简单除以 0.85 当 VI(忽略非均质性)。
提示:VR 和 VI 的差异大小直接反映地层速度非均质程度。在盐下或火成岩区,VR/VI 比值常 > 1.2;而在页岩段可能仅 1.03。别信“行业经验值”,必须用本工区数据标定。
2.2 三种主流 VR→VI 反演方法对比:选哪个取决于你的数据源和精度要求
| 方法 | 输入数据 | 核心原理 | 适用场景 | 编程实现复杂度 |
|---|---|---|---|---|
| Dix 公式(解析法) | 多个叠加速度(VR)随时间变化的离散点 | 对 RMS 速度平方做时间域微分:$ V_I^2(t_i) = \frac{t_i V_{RMS}^2(t_i) - t_{i-1} V_{RMS}^2(t_{i-1})}{t_i - t_{i-1}} $ | 有高质量速度谱(如 CMP gather 速度分析结果),且层界清晰 | ★☆☆☆☆(3 行 NumPy 即可) |
| Spline 微分法(数值法) | 连续 VR(t) 曲线(如拟合后的速度谱包络) | 用三次样条插值 VR²(t),再数值微分求导 | VR 数据点稀疏或含噪声,需平滑抑制高频扰动 | ★★☆☆☆(scipy.interpolate + numpy.gradient) |
| 测井约束反演(物理法) | VR(t) + 测井 VI(z) + 时深标定井 | 构建目标函数 $ \min | \text{VR}{\text{calc}}(t) - \text{VR}{\text{obs}}(t) |^2 + \lambda | \text{VI}(z) - \text{VI}_{\text{log}}(z) |^2 $,迭代优化 VI | 高精度构造建模、储层预测,必须井控 | ★★★★☆(需 scipy.optimize.minimize 或自编迭代器) |
我一般会这样决策:
- 做初探区块速度建模 → 用 Dix 公式快速生成初始 VI;
- 做开发井区精细建模 → 必须上测井约束反演,哪怕只有一口标定井;
- 处理老资料(速度谱点少、抖动大)→ 先 spline 平滑再 Dix 微分,比直接 Dix 稳定 40% 以上。
2.3 用 Python 实现 Dix 公式:5 行代码背后的三个隐藏假设
import numpy as np def dix_inverse_vr_to_vi(t_ms, vr_m_s): """ Dix 公式反演层速度:输入时间为 ms,输出 VI 单位为 m/s t_ms: shape=(N,),零偏移双程时间(ms),升序排列 vr_m_s: shape=(N,),对应 RMS 速度(m/s) 返回 vi_m_s: shape=(N-1,),第 i 层的层速度(m/s),对应时间区间 [t_i-1, t_i] """ t_s = t_ms / 1000.0 # 转秒 vr2 = vr_m_s ** 2 # Dix 公式核心:Vi² = [ti*VRi² - ti-1*VRi-1²] / (ti - ti-1) vi2 = (t_s[1:] * vr2[1:] - t_s[:-1] * vr2[:-1]) / (t_s[1:] - t_s[:-1]) vi_m_s = np.sqrt(np.maximum(vi2, 0)) # 防负值开方报错 return vi_m_s这段代码看似简单,但实际运行时必须满足三个隐含前提:
- 时间严格单调递增:若速度谱拾取点时间乱序(如人工 pick 错位),
t_s[1:] - t_s[:-1]会出现负间隔,导致 VI 为虚数; - VR² 在时间域可微:Dix 公式本质是微分近似,当相邻两点时间间隔 > 50ms(常见于深层),误差急剧放大;
- 无速度反转层:公式假设速度随深度单调增加,若存在浅层高速层(如玄武岩盖层),Dix 会严重低估其下伏层 VI。
所以真实项目中,我总会在调用前加两行预处理:
# 排序去重 + 时间间隔检查 idx = np.argsort(t_ms) t_ms, vr_m_s = t_ms[idx], vr_m_s[idx] if np.any(np.diff(t_ms) < 5): # 小于 5ms 视为重复点 _, idx_unique = np.unique(t_ms, return_index=True) t_ms, vr_m_s = t_ms[idx_unique], vr_m_s[idx_unique]3. 从速度谱到可用 VI:完整落地 pipeline 与关键参数调优
3.1 输入准备:如何从地震解释软件导出“能用”的 VR 数据
多数商业软件(如 Kingdom、Petrel、GeoDepth)导出速度谱结果时,默认给的是“叠加速度”(Stacking Velocity),它 ≠ RMS 速度(VR),但工程上常近似等价。关键区别在于:
- 叠加速度:基于 NMO 校正最优准则反演,含倾角校正项,适用于各向异性介质;
- RMS 速度:纯垂直入射假设下的理论量,用于时深转换。
注意:若你的速度谱来自叠前时间偏移(PreSTM)后的 residual moveout 分析,它更接近 VR;若来自传统 CMP gather NMO,务必确认软件是否已做倾角校正(Dip Moveout Correction)。未校正的叠加速度直接当 VR 用,深层误差可达 15%。
导出建议格式(CSV):
Time_ms,RMS_Velocity_m_s 120,1850 240,2130 360,2480 480,2920 600,3210✅ 必须列名明确、无单位混杂、时间列升序;
❌ 禁止导出“速度谱图像”再 OCR 识别(误差 > 50m/s);
❌ 禁止用软件截图+画图软件量取坐标(系统性偏差不可控)。
3.2 Dix 反演实战:用真实速度谱跑通全流程
假设你已拿到vr_spectrum.csv,执行以下步骤:
import pandas as pd import numpy as np import matplotlib.pyplot as plt # 1. 加载并清洗 df = pd.read_csv("vr_spectrum.csv") t_ms = df["Time_ms"].values vr_m_s = df["RMS_Velocity_m_s"].values # 2. 预处理(排序、去重、间隔检查) idx = np.argsort(t_ms) t_ms, vr_m_s = t_ms[idx], vr_m_s[idx] diff_t = np.diff(t_ms) if np.any(diff_t < 5): _, idx_u = np.unique(t_ms, return_index=True) t_ms, vr_m_s = t_ms[idx_u], vr_m_s[idx_u] # 3. Dix 反演 vi_m_s = dix_inverse_vr_to_vi(t_ms, vr_m_s) # 4. 生成时间-层速度对(注意:vi 对应区间中点时间) t_mid_ms = (t_ms[1:] + t_ms[:-1]) / 2.0 # 层中点时间(ms)此时t_mid_ms和vi_m_s构成离散 VI(t) 曲线。但注意:这不是最终成果——它只是时间域 VI,还需转成深度域才能进建模软件。
3.3 时深转换:把 VI(t) 变成 VI(z),绕不开的“积分陷阱”
将时间域层速度转为深度域,需积分:
$$ z(t) = \int_0^t \frac{V_I(\tau)}{2} , d\tau $$
但问题来了:你只有离散点t_mid_ms,vi_m_s,且vi_m_s[i]对应的是[t_ms[i], t_ms[i+1]]区间。直接用梯形法积分会引入系统性偏差——因为 VI 在区间内并非线性。
我的经验做法(已验证于渤海湾、鄂尔多斯多个区块):
- 对
t_mid_ms,vi_m_s做三次样条插值,生成高密度 VI(t) 曲线(步长 ≤ 2ms); - 用
scipy.integrate.cumulative_trapezoid对 $ V_I(t)/2 $ 累积积分,得z(t); - 将插值后的
z(t)和VI(t)重新采样到 1m 间隔深度格网。
from scipy.interpolate import CubicSpline from scipy.integrate import cumulative_trapezoid # 插值到细密时间网格(2ms 间隔) t_fine_ms = np.arange(t_mid_ms[0], t_mid_ms[-1], 2.0) cs_vi = CubicSpline(t_mid_ms, vi_m_s) vi_fine = cs_vi(t_fine_ms) # 积分得深度 z(t) t_fine_s = t_fine_ms / 1000.0 dz_dt = vi_fine / 2.0 # 单程速度,单位 m/s z_fine_m = cumulative_trapezoid(dz_dt, t_fine_s, initial=0) # 重采样到 1m 深度格网 z_target_m = np.arange(0, int(z_fine_m[-1]) + 1, 1.0) vi_z_m_s = np.interp(z_target_m, z_fine_m, vi_fine) # 注意:此处用 vi_fine,非原始离散点关键参数说明:
initial=0确保地表深度为 0;np.interp用线性插值足够,因深度格网远密于原始时间采样;若需更高精度(如碳酸盐岩缝洞建模),可改用CubicSpline(z_fine_m, vi_fine)再求值。
4. 避坑:VR-VI 转换中 4 个让项目延期一周的真实问题
4.1 现象:Dix 反演结果出现“负速度”或“NaN”
原因:原始 VR 数据含异常点(如速度谱拾取错误、强噪声干扰),导致t_i * VR_i² - t_{i-1} * VR_{i-1}²为负;或时间序列未排序,t_i < t_{i-1}。
解决:
- 加入
np.maximum(vi2, 0)强制非负(但需记录哪些点被修正); - 用
scipy.signal.medfilt对 VR² 序列做中值滤波(窗口长度=5),再 Dix; - 导出前在解释软件中人工检查速度谱,剔除明显 outlier(如 600ms 处突然跳变到 5000m/s)。
4.2 现象:转换后深度误差 > 30m,但井震标定显示时深关系本身没问题
原因:VR 数据来自不同覆盖次数或不同炮检距范围,存在系统性偏差。例如:浅层用 120~240ms 窗口拾取,深层用 480~600ms 窗口,窗口效应导致 VR 值偏低。
解决:
- 统一拾取窗口:全剖面用相同时间窗(如 0~600ms);
- 对深层 VR 做“窗口校正系数”:用已知井段计算该深度 VR_true / VR_picked,作为乘数应用到同深度 VR;
- 更可靠的做法:用共反射点(CRP)叠加速度替代 CMP 速度谱。
4.3 现象:VI(z) 曲线在断层附近剧烈震荡,无法用于建模
原因:Dix 公式对速度突变敏感,断层上下盘 VR 差异被放大为 VI 虚假尖峰;且原始速度谱在断层处分辨率下降,拾取不准。
解决:
- 断层两侧分别 Dix 反演,中间用线性过渡(宽度=50ms 对应深度);
- 引入断层走向约束:对断层迹线附近 200m 范围内的 VR 点,用
scipy.ndimage.gaussian_filter1d沿测线方向平滑(sigma=3); - 终极方案:用断层模型作 mask,在反演目标函数中加入空间平滑正则项(需写 custom loss)。
4.4 现象:同一口井,用不同软件(Petrel vs GeoDepth)导出的 VR 转 VI 后深度差 15m
原因:软件内部对“RMS 速度”定义不一致——有的用 Dix 公式正向计算 VR,有的用更复杂的 Berryman 公式;导出时未注明公式版本。
解决:
- 查软件手册确认 VR 计算公式(关键词:
RMS velocity definition); - 若 Petrel 用 Berryman,需改用对应反演公式(
V_I^2 = V_RMS^2 * (1 - β * (ΔV/V)^2),β≈0.3); - 最稳妥:统一用测井 VI 直接标定,把软件导出的 VR 仅作参考,不参与反演。
5. 验证与交付:用三类硬指标判断你的 VI 是否“真可用”
5.1 井控验证:不只是看平均误差,要看误差分布形态
把反演得到的 VI(z) 输入时深转换模块,生成合成地震道,与实测井旁道对比。重点看:
- 绝对误差:全井段平均误差 < 5m(行业硬指标);
- 趋势误差:若误差随深度单调增大,说明浅层 VI 偏高(压缩了上部地层);
- 局部尖峰:某一层误差 > 20m,必查该层 VR 拾取质量及邻层 VI 连续性。
我习惯画三张图:
- 实测 vs 合成时深曲线(X轴:时间,Y轴:深度);
- 误差随深度变化曲线(突出标注 >10m 误差段);
- VI(z) 曲线叠合测井 VI(用不同颜色区分,透明度 0.7)。
5.2 地震响应验证:用 VI 体正演,看是否“还原”原始数据特征
生成三维 VI 体后,别急着交差——用它做一次轻量级正演:
- 用
obspy或seispy生成合成共炮点道集(参数:炮检距范围、采样率、子波); - 对比原始道集与合成道集的 NMO 校正效果:若合成道集校正后仍残留弯曲,说明 VI 体横向变化太陡;
- 检查振幅保真度:若合成道集振幅衰减过快,可能是 VI 体低估了吸收效应(需加 Q 补偿项)。
血泪经验:曾有个项目 VI 体 RMS 误差仅 2.3%,但正演道集 NMO 后残余时差达 30ms——查出是反演时未考虑各向异性,后续在 Dix 公式中引入 Thomsen 参数修正。
5.3 交付物清单:让甲方/协作方一眼看懂你做了什么
不要只交一个vi_depth.csv。标准交付包应含:
| 文件名 | 内容 | 格式 | 说明 |
|---|---|---|---|
vr_input.csv | 原始 VR(t) 数据 | CSV | 列:Time_ms, VR_m_s, Source_Method(如 "Dix_Petrel_v2023") |
vi_time_domain.csv | Dix 反演后 VI(t) | CSV | 列:Time_mid_ms, VI_m_s, Method="Dix_Spline_Smoothed" |
vi_depth_domain.csv | VI(z) 格网化结果 | CSV | 列:Depth_m, VI_m_s, Grid_Step_m=1.0 |
validation_report.pdf | 三类验证图 + 误差统计表 | 含井号、误差均值/最大值/标准差、正演参数 |
最后说句实在话:VR-VI 转换从来不是“做完就完”的工序,而是贯穿整个地震解释周期的校验闭环。我养成了一个习惯——每次更新速度模型,都用新 VI 重跑一遍关键井的时深转换,把误差变化记在 Excel 里。三年下来,发现 73% 的构造误差源头其实是最初那版 Dix 反演里一个被忽略的 8ms 时间点偏差。技术没有银弹,但把每个 2ms 的时间精度抠到底,就是物探工程师最硬的底气。希望帮到你。
本文还有配套的精品资源,点击获取