
简介本资源面向地球物理、地质勘探方向的研究者与工程师聚焦海洋大地电磁二维数值模拟与MT-Occam反演重点涉及additional KsZ优化算法适合具备一定Matlab基础、希望上手反演实践的中高级学习者。压缩包共15个文件约32KB以8个m脚本为主体涵盖Occam反演主流程、剖面提取、迭代误差与响应曲线绘制、二维模型可视化等模块另含readme说明及少量系统辅助文件便于快速理解代码组织与调用关系。已有155人学习下载。通过研读与运行这些脚本读者可掌握有限单元法离散复杂海底地形、基于最小描述长度原则的平滑反演实现以及KsZ迭代求解器加速模型收敛的思路为海洋大地电磁数据处理、地下电阻率结构恢复与反演效率优化提供可直接复用的代码参考。1. Occam2DMT 到底解决什么问题从一条视电阻率曲线说起如果你手上有一条大地电磁MT测深曲线TE 和 TM 两支在低频段劈叉相位还往下掉你大概会怀疑地下有二维结构。这时候一维反演已经不够用了你需要二维反演。Occam2DMT 就是干这个的——它把 Occam 反演思想搬到二维 MT 场景用 Matlab 实现核心思路是在拟合误差满足要求的前提下找最平滑的模型。换句话说它不追求“最像”的模型而是追求“够用且不瞎折腾”的模型。这个标题里的additionalksz是 Occam2DMT 里一个容易被忽略但很关键的参数——它控制模型网格在垂向上的额外细分层数。很多人跑完反演发现深部电阻率被“抹平”了或者浅部细节糊成一团八成是网格参数没调对。这篇笔记面向两类人一是刚拿到 MT 数据、想用 Occam2DMT 跑出第一张二维电阻率剖面的新手二是已经跑过几轮、但结果总差点意思、想搞清楚参数边界的老手。Matlab 只是工具真正要理解的是 Occam 反演在二维 MT 里的落地逻辑。2. Occam 反演在二维 MT 里的数学骨架与网格设计2.1 为什么是“最平滑模型”而不是“最优拟合”MT 反演是不适定问题数据有噪声、解不唯一。如果只追拟合差模型会变得极其粗糙出现大量虚假异常体。Occam 反演的做法是反过来先定一个可接受的拟合差阈值然后在这个约束下最小化模型粗糙度。数学上就是拉格朗日乘子法minimize: ||∂m||² μ⁻¹(||Wd - WF(m)||² - χ²)其中∂是粗糙度算子μ是拉格朗日乘子W是数据权重χ²是目标拟合差。Occam2DMT 用迭代方式调整μ每次线性化正演算子解一个大型稀疏线性系统。Matlab 在这里的优势是稀疏矩阵工具箱成熟backslash直接能解。关键点μ太大模型过于平滑数据拟合不够μ太小模型粗糙可能过拟合。Occam2DMT 内部有自动搜索μ的机制但初始值和搜索范围需要你根据数据质量给。2.2 网格设计additionalksz 到底加在哪Occam2DMT 的模型网格分两部分核心网格和扩展网格。核心网格覆盖测点下方扩展网格往外扩用来吸收边界效应。垂向上第一层厚度通常取最小趋肤深度的几分之一然后按比例递增。additionalksz的作用是在每个核心网格的垂向层之间插入额外层。比如你原本设了 30 层additionalksz 2实际参与反演的垂向层数会变成 30 2×(30-1) 88 层。这样做的好处是正演计算时垂向离散更细对高频段和薄层响应更准坏处是模型参数变多反演更慢且如果数据本身分辨不了那么细多出来的层只会增加不确定性。我一般会这样定先看数据最高频率对应的趋肤深度确保第一层厚度小于它的 1/3然后看最低频率的趋肤深度确保总深度覆盖到它。additionalksz从 1 开始试如果浅部低阻层厚度反演出来明显偏大就加到 2 或 3。2.3 正演与雅可比矩阵的计算代价二维 MT 正演常用有限差分或有限元。Occam2DMT 用的是有限差分把 Helmholtz 方程离散成稀疏线性系统。每个频率要解一次每个测点也要参与。雅可比矩阵是正演对模型参数的偏导直接算代价很大Occam2DMT 用伴随方程法adjoint来算把代价降到和正演同量级。在 Matlab 里这一步是性能瓶颈。如果你有 20 个频率、30 个测点、88 层垂向网格雅可比矩阵的规模是 (2×20×30) × (88×水平网格数)。水平网格数如果 50那就是 1200 × 4400稀疏度还行但迭代次数一多时间就上去了。我的经验是先用粗网格跑几轮看拟合差下降趋势再决定要不要加密。3. 用 Occam2DMT 跑通第一张二维反演剖面的完整步骤3.1 数据准备从 EDI 到 Matlab 结构体Occam2DMT 通常读 EDI 格式但如果你只有文本数据需要自己整理成结构体。常见做法是每个测点一个结构体字段包括freq频率、rho_te、phase_te、rho_tm、phase_tm、err_rho、err_phase。注意相位单位是度还是弧度Occam2DMT 内部一般用弧度读入时要转。% 读取一个测点的 MT 数据并整理成 Occam2DMT 需要的结构 % 假设数据文件是四列频率(Hz), 视电阻率(Ohm-m), 相位(度), 误差 data load(site01.txt); freq data(:,1); rho data(:,2); phase_deg data(:,3); err data(:,4); % 转弧度 phase_rad phase_deg * pi / 180; % 构造结构体 site struct(); site.freq freq; site.rho_te rho; % 这里假设是 TE 模式TM 类似 site.phase_te phase_rad; site.err_rho err; site.err_phase err * pi / 180; % 相位误差也转弧度 % 多个测点组成 cell 数组 sites {site};逻辑说明Occam2DMT 对数据格式敏感频率必须从高频到低频排列否则正演会出错。误差如果给得太小反演会强行拟合噪声给得太大拟合差下不去。我一般把视电阻率误差设为 5% 的绝对值加 0.01相位误差设为 1 度对应的弧度值。3.2 参数文件与 additionalksz 的设置Occam2DMT 通常用一个参数文件控制反演里面包括网格参数、频率列表、迭代次数、目标拟合差等。additionalksz就在网格参数段。下面是一个典型的参数片段# 网格参数 nx 50 # 水平网格数 nz 30 # 垂向核心层数 additionalksz 2 # 垂向额外细分层数 dz1 10 # 第一层厚度(m) dz_ratio 1.1 # 层厚递增比例additionalksz设 2 意味着垂向实际层数变成 30 2×29 88。如果你发现反演结果在浅部比如 100 m 以内有低阻层但厚度明显比地质资料厚可以试着把additionalksz加到 3同时把dz1减小到 5。代价是反演时间大概增加 30%50%。3.3 启动反演与监控拟合差启动命令通常是一个主脚本比如occam2dmt_run.m里面读参数文件、读数据、调反演函数。运行后Matlab 命令窗口会打印每次迭代的拟合差和μ值。你要盯的是拟合差是否稳定下降以及μ是否在合理范围。% 运行 Occam2DMT 反演的主脚本示例 % 假设参数文件是 params.txt数据在 sites 变量里 addpath(occam2dmt); % 添加工具箱路径 % 读参数 params read_params(params.txt); % 运行反演 [model, misfit] occam2dmt_inv(sites, params); % 保存结果 save(inversion_result.mat, model, misfit); % 画拟合差曲线 figure; semilogy(misfit, o-); xlabel(Iteration); ylabel(RMS Misfit); title(Occam2DMT 拟合差下降曲线); grid on;逻辑说明occam2dmt_inv是主反演函数返回模型和每次迭代的拟合差。如果拟合差在 5 次迭代后还在 10 以上说明要么数据误差给太小要么网格太粗。如果拟合差降到 1 以下可能过拟合了要检查误差是否合理。3.4 结果可视化从模型向量到电阻率剖面反演出来的model是一个向量需要重组成二维矩阵才能画图。Occam2DMT 通常提供plot_model.m或类似函数。如果没有自己写一个也不难。% 把模型向量重组成二维电阻率剖面并画图 % model 是 log10(电阻率) 的向量长度 nx * nz_actual nx params.nx; nz_actual params.nz params.additionalksz * (params.nz - 1); % 重组 rho_model reshape(model, nz_actual, nx); rho_model 10.^rho_model; % 转回线性 % 画图 figure; imagesc(1:nx, 1:nz_actual, log10(rho_model)); colormap(jet); colorbar; xlabel(Horizontal Grid); ylabel(Vertical Grid); title(Occam2DMT 二维电阻率剖面);逻辑说明reshape的顺序要和反演内部一致通常是先垂向后水平。如果画出来上下颠倒用flipud翻一下。颜色用log10是为了突出低阻异常。4. 避坑与排查Occam2DMT 跑不出合理剖面的 5 个常见原因4.1 拟合差降不下去一直卡在 10 以上现象迭代 10 次RMS 拟合差从 20 降到 12 就不动了。 原因数据误差给得太小反演认为数据必须精确拟合但实际噪声大或者网格太粗正演响应根本对不上。 解决把视电阻率误差从 2% 提到 5%10%相位误差从 0.5 度提到 12 度。如果还不行把nx和nz各加 10additionalksz加到 2。4.2 深部出现虚假高阻或低阻体现象反演剖面在最低频率对应的深度附近出现一个明显异常但地质上不可能。 原因扩展网格不够大边界反射被当成真实信号或者最低频率的数据质量差被强行拟合。 解决把扩展网格往外扩通常要求扩展网格宽度大于最低频率趋肤深度的 3 倍。另外把最低频的误差放大或者直接剔除。4.3 additionalksz 设太大导致反演极慢现象additionalksz 5反演跑了 8 小时还没完。 原因垂向层数变成 30 5×29 175雅可比矩阵规模翻了几倍每次迭代解方程时间指数上升。 解决先用additionalksz 1跑通看结果是否合理。如果浅部细节确实需要更细网格再逐步加到 2 或 3不要一上来就 5。4.4 TE 和 TM 模式反演结果差异巨大现象TE 数据反演出来是层状TM 数据反演出来一堆横向异常。 原因二维结构中 TE 和 TM 对异常体的敏感度不同TM 对横向边界更敏感。如果数据本身三维性很强二维反演就会劈叉。 解决先做二维性分析比如用阻抗张量旋转不变量。如果三维性明显Occam2DMT 不适合要考虑三维反演。如果只是轻微差异可以联合反演 TETM权重各 0.5。4.5 Matlab 内存不足或报稀疏矩阵错误现象运行到雅可比矩阵组装时Matlab 报Out of memory。 原因网格太密频率太多测点太多稀疏矩阵非零元爆炸。 解决减少频率数只保留关键频点或者把测点分组先反演一个子集。Matlab 的sparse函数要确保用对不要用full转来转去。5. 进阶技巧用 additionalksz 做垂向分辨率测试与模型评估additionalksz不只是个网格参数它还能帮你判断数据到底能分辨多细的垂向结构。做法很简单固定其他参数把additionalksz从 1 逐步加到 4每次跑完反演比较同一位置的垂向电阻率曲线。如果additionalksz从 1 加到 2曲线明显变化说明数据有更细的分辨能力如果从 2 加到 4曲线基本不变说明数据分辨不了那么细再加层只是浪费计算。我一般会做一个表格来记录additionalksz垂向层数反演时间(min)RMS浅部低阻层厚度(m)130121.8120288251.5803146481.4754204851.474从这个假想表可以看出additionalksz 2时 RMS 和浅部厚度都有明显改善到 3 以后收益递减。所以 2 是性价比最高的选择。另一个技巧用additionalksz做“棋盘”测试。人为在模型里放一个薄层正演合成数据加噪声然后用不同additionalksz反演看哪个能恢复出薄层。这能直接告诉你你的数据采集和处理流程下垂向分辨率极限在哪。最后说个血泪经验Occam2DMT 的additionalksz和dz1要配合调。dz1太大additionalksz再大也救不了浅部分辨率dz1太小第一层可能只有几米正演高频段需要更密的频率采样否则会产生数值噪声。我一般让dz1等于最高频率趋肤深度的 1/5 到 1/3然后additionalksz从 1 开始试。希望帮到你。本文还有配套的精品资源点击获取