☰
基于CT扫描的岩心孔隙建模与两相流模拟技术
2026/11/4 3:03:45 网站建设 项目流程

1. 项目背景与核心挑战

实验室的白炽灯管嗡嗡作响,老张盯着CT扫描生成的岩心灰度图像,屏幕上那些扭曲的黑色纹路就像被揉皱的报纸——这是某油田实际取芯样本的微观孔隙结构。墙角两个标着"实验专用"的油罐已经见底,第三次驱替实验的数据曲线依然不符合预期。

问题的核心在于:传统手工建模的规则孔隙网络根本无法还原真实岩心的复杂结构。那些像毛细血管般交错连接的孔喉通道,其直径分布从纳米级到微米级不等,形状更是千奇百怪。我们尝试用AutoCAD重建时,要么丢失了关键的喉道连接,要么把表面粗糙度简化成了光滑曲面——这直接导致两相驱替模拟结果与物理实验出现高达40%的偏差。

2. 真实孔隙建模关键技术

2.1 CT扫描数据的预处理

从医院借来的医用CT扫描仪分辨率达到2μm,但原始DICOM格式的断层图像需要经过一系列预处理:

  1. 灰度阈值分割:使用ImageJ的Otsu算法自动区分固体骨架(亮色)和孔隙空间(暗色)
  2. 噪声消除:采用非局部均值滤波(Non-local Means Denoising)保留孔隙边缘细节
  3. 三维重建:通过Avizo软件的Marching Cubes算法生成STL格式的表面网格

关键提示:扫描时务必保持样本绝对静止,我们曾因样本轻微晃动导致连续三组数据出现"重影"伪影

2.2 COMSOL几何导入与修复

将STL文件导入COMSOL时,常见的几何问题包括:

  • 微小孔隙被识别为噪点(<5体素)
  • 相邻孔隙间的薄壁(<1μm)出现破损
  • 曲面存在非流形边缘

修复代码示例:

model = ModelUtil.create('Model'); model.geom.create('geom1', 3); model.geom('geom1').feature.create('imp1', 'Import'); model.geom('geom1').feature('imp1').set('filename', 'core_sample.stl'); model.geom('geom1').feature('imp1').set('repair', 'on'); // 自动修复开关 model.geom('geom1').run; // 执行导入 model.geom('geom1').scale(1e-6); // 单位转换为米

常见修复策略对比表:

问题类型手动修复方法自动修复效果
孤立噪点逐个删除效果较好
孔喉断裂桥接操作成功率约60%
曲面破损重新三角化可能改变拓扑结构

3. 两相流物理场设置

3.1 材料参数定义

根据实验室实测数据定义两种原油属性:

// 重质原油(原始油藏) rho1 = 892 [kg/m^3]; mu1 = 0.032 [Pa·s]; // 轻质原油(驱替液) rho2 = 856 [kg/m^3]; mu2 = 0.028 [Pa·s]; // 界面张力 sigma = 0.025 [N/m];

3.2 Level Set方法实现

采用相场法追踪两相界面时,控制方程包括:

  1. Navier-Stokes方程: $$\rho(\frac{\partial \mathbf{u}}{\partial t} + \mathbf{u} \cdot \nabla \mathbf{u}) = -\nabla p + \mu \nabla^2 \mathbf{u} + \mathbf{F}_{st}$$

  2. Level Set输运方程: $$\frac{\partial \phi}{\partial t} + \mathbf{u} \cdot \nabla \phi = \gamma \nabla \cdot (\epsilon \nabla \phi - \phi(1-\phi)\frac{\nabla \phi}{|\nabla \phi|})$$

COMSOL中的关键设置:

Physics.create("pf", "PhaseField"); Physics.feature("pfinit").set("c0", "0.5*(1-tanh((x-1e-4)/2e-5))"); // 初始界面 Physics.feature("pfeq1").set("Gamma", 0.032*[1,0.8]); // 各向异性参数

4. 网格划分策略

4.1 边界层网格配置

在孔隙壁面处设置5层边界层网格:

  • 第一层厚度:0.1μm
  • 增长因子:1.5
  • 总厚度:约1μm

实测表明:边界层少于3层时,毛细管力计算误差可达15%

4.2 主体区域离散化

采用自由四面体网格:

  • 最大单元尺寸:孔隙平均直径的1/5
  • 最小单元尺寸:喉道最窄处的1/10
  • 曲率因子:0.3
  • 狭窄区域细化等级:2

网格质量对比实验:

网格类型计算时间界面稳定性内存占用
纯四面体2.5h差(易发散)12GB
边界层+四面体3.8h优18GB
六面体主导6.2h良25GB

5. 求解器配置技巧

5.1 瞬态求解参数

Study.create("std1", "Transient"); Study.feature("time").set("tlist", "range(0,5,100)"); // 0-5秒,100步 Study.feature("solver").set("stol", "1e-4"); // 相对容差

5.2 稳定性控制

  1. Peclet数监控: $$Pe = \frac{|\mathbf{u}|h}{2\epsilon}$$ 当局部Pe>2时切换为全耦合求解器

  2. 自动时间步进:

    • 初始步长:1e-6s
    • 最大步长:0.1s
    • 步长增长因子:1.2

6. 后处理与结果分析

6.1 滞油区识别

使用流线积分器追踪粒子轨迹:

Results.create("pt", "ParticleTracing"); Results.feature("pt").set("solnum", "auto"); Results.feature("pt").set("tlist", "range(0,5,50)");

6.2 驱替效率计算

定义采收率公式: $$\eta = \frac{V_{produced}}{V_{initial}} \times 100%$$

参数化扫描结果显示:

  • 注采压差0.5MPa时:η=73%
  • 注采压差1.0MPa时:η=85%
  • 注采压差1.5MPa时:η=89%

7. 实战经验总结

  1. 几何修复陷阱:某次自动修复将相邻孔隙合并,导致模拟的驱替速度比实验快22%。后来我们开发了孔隙连通性检查脚本:

    import networkx as nx def check_connectivity(stl_file): # 构建孔隙网络图 G = nx.Graph() # ...拓扑分析代码... return G.is_connected()
  2. 服务器崩溃预防:长时间计算时务必设置自动保存:

    Study.feature("time").set("savetime", "0.1"); // 每0.1秒保存 ModelUtil.saveState('autosave.mph');
  3. 毛细管数临界值:当无量纲毛细管数$Ca=\frac{\mu u}{\sigma}>10^{-3}$时,滞油现象显著改善。我们最终采用的注采压差1.2MPa正好对应Ca=1.2×10⁻³。

实验室的空调突然发出嗡鸣,屏幕上的两相界面正以完美的指进形态向前推进。老张盯着后处理模块显示的89%采收率曲线,终于露出了三个月来的第一个笑容。我默默把冰棍棍扔进垃圾桶——这次模拟消耗了38小时CPU时间,但相比浪费的三罐原油,这代价简直微不足道。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询