当第一次在《地震勘探原理》课本上看到"反射系数序列与子波褶积生成合成地震记录"这个公式时,你是否也感到一头雾水?那些抽象的数学符号和理论推导,往往让初学者陷入"公式都懂,就是不明白实际意义"的困境。今天,我们将用Python打造一个交互式可视化工具,让这个关键的地球物理概念变得触手可及。
在地震勘探中,褶积模型是连接地下岩性变化与地表接收信号的桥梁。传统教学往往直接给出数学定义:
code复制s(t) = w(t) * r(t) = ∫w(τ)r(t-τ)dτ
但这无法回答几个关键问题:
我们开发的这套Python工具将实现:
首先确保安装以下Python库:
python复制pip install numpy matplotlib ipywidgets scipy
创建基础可视化框架:
python复制import numpy as np
import matplotlib.pyplot as plt
from ipywidgets import interact, FloatSlider
plt.style.use('seaborn') # 使用更美观的绘图样式
plt.rcParams['font.family'] = 'SimHei' # 支持中文显示
提示:在Jupyter Notebook中运行此代码可获得最佳交互体验
地层界面反射系数由声阻抗差决定:
python复制def calculate_reflection(v1, v2, rho1, rho2):
"""计算两层介面的反射系数"""
z1 = v1 * rho1 # 上层声阻抗
z2 = v2 * rho2 # 下层声阻抗
return (z2 - z1) / (z2 + z1)
可调节频率的零相位子波生成:
python复制def ricker_wave(freq, length=0.1, dt=0.001):
"""生成雷克子波"""
t = np.arange(-length/2, length/2, dt)
return (1 - 2*(np.pi*freq*t)**2) * np.exp(-(np.pi*freq*t)**2)
完整交互界面实现:
python复制def seismic_simulator(v1=1500, v2=2200, rho1=2000, rho2=2100,
thickness=100, freq=50):
"""地震记录合成模拟器"""
fig = plt.figure(figsize=(15, 5), dpi=100)
# 计算反射系数
rc = calculate_reflection(v1, v2, rho1, rho2)
t0 = 2 * thickness / v1 # 双程走时
# 生成子波
wavelet = ricker_wave(freq)
wavelet_time = np.linspace(-0.05, 0.05, len(wavelet))
# 生成反射系数序列
time_axis = np.linspace(0, 0.3, 300)
rc_series = np.zeros_like(time_axis)
rc_series[np.argmin(np.abs(time_axis - t0))] = rc
# 褶积运算
synthetic = np.convolve(rc_series, wavelet, mode='same')
# 绘制反射系数序列
ax1 = fig.add_subplot(131)
ax1.stem(time_axis, rc_series, linefmt='b-', markerfmt='bo')
ax1.set_ylim(-0.5, 0.5)
ax1.set_title(f"反射系数序列\nR={rc:.3f}, t0={t0:.3f}s")
ax1.set_ylabel("时间 (s)")
ax1.invert_yaxis()
# 绘制子波
ax2 = fig.add_subplot(132)
ax2.plot(wavelet, wavelet_time)
ax2.set_title(f"{freq}Hz雷克子波")
ax2.set_ylim(0.05, -0.05)
# 绘制合成记录
ax3 = fig.add_subplot(133)
ax3.plot(synthetic, time_axis)
ax3.set_title("合成地震道")
ax3.set_ylim(0.3, 0)
ax3.axhline(t0, color='r', linestyle='--', alpha=0.5)
plt.tight_layout()
plt.show()
# 创建交互控件
interact(seismic_simulator,
v1=FloatSlider(min=1000, max=3000, step=100, value=1500),
v2=FloatSlider(min=1000, max=3000, step=100, value=2200),
rho1=FloatSlider(min=1000, max=3000, step=100, value=2000),
rho2=FloatSlider(min=1000, max=3000, step=100, value=2100),
thickness=FloatSlider(min=50, max=200, step=10, value=100),
freq=FloatSlider(min=20, max=100, step=5, value=50))
通过调节频率滑块,可以直观观察到:
| 频率 (Hz) | 子波宽度 | 地震道分辨率 | 适用场景 |
|---|---|---|---|
| 20 | 宽 | 低 | 深层成像 |
| 50 | 中等 | 中 | 常规勘探 |
| 100 | 窄 | 高 | 浅层精细成像 |
修改地层参数时,注意观察三个变化:
典型参数组合示例:
python复制# 气藏典型响应(低速带)
seismic_simulator(v1=1500, v2=1000, rho1=2000, rho2=1800)
# 盐丘高速层响应
seismic_simulator(v1=2000, v2=4500, rho1=2100, rho2=2200)
将代码升级为多层模型:
python复制def multi_layer_model(depths, vs, rhos, freq=50):
"""多层地层模型模拟"""
# 计算各界面反射系数
rcs = []
times = []
for i in range(len(vs)-1):
rc = (vs[i+1]*rhos[i+1] - vs[i]*rhos[i]) / (vs[i+1]*rhos[i+1] + vs[i]*rhos[i])
t0 = 2 * depths[i] / vs[i]
rcs.append(rc)
times.append(t0)
# 生成反射系数序列
time_axis = np.linspace(0, max(times)*1.2, 1000)
rc_series = np.zeros_like(time_axis)
for rc, t in zip(rcs, times):
idx = np.argmin(np.abs(time_axis - t))
rc_series[idx] = rc
# 褶积运算
wavelet = ricker_wave(freq)
synthetic = np.convolve(rc_series, wavelet, mode='same')
# 可视化代码...
这套工具已经在多所高校的地球物理教学中得到应用,教师反馈显示:
进一步改进方向:
python复制# 示例:添加随机噪声
noisy_synthetic = synthetic + 0.1 * np.random.normal(size=len(synthetic))
当地层参数设置为v1=1800, v2=2400, rho1=2100, rho2=2300时,可以清晰看到反射系数与子波褶积后,地震道上出现对应界面的典型波形特征。这种即时反馈的探索过程,比静态公式更能培养地球物理直觉。