1. 相场法驱替模拟的核心原理
多孔介质中的两相驱替过程,本质上是一个涉及界面动力学、毛细管力和粘性力相互作用的复杂物理问题。相场方法通过引入序参数(phase-field variable)来描述两相界面,避免了传统VOF方法中显式追踪界面的困难。
在COMSOL中实现相场法模拟时,系统会求解Cahn-Hilliard方程来描述相界面的演化:
$$
\frac{\partial \phi}{\partial t} + \nabla \cdot (\mathbf{u} \phi) = \nabla \cdot (M \nabla \mu)
$$
其中$\phi$是相场变量(通常取值在-1到1之间),$M$是迁移率,化学势$\mu$由自由能泛函的变分得到:
$$
\mu = \frac{\delta F}{\delta \phi} = \gamma [-\nabla^2 \phi + \frac{\phi(\phi^2-1)}{\epsilon^2}]
$$
这里$\gamma$是界面能参数,$\epsilon$控制界面厚度。这个方程与Navier-Stokes方程耦合,共同描述了两相流体的运动。
关键提示:界面厚度$\epsilon$需要与网格尺寸匹配。经验法则是网格尺寸应小于$\epsilon/2$,否则会出现数值扩散导致界面模糊。
2. COMSOL建模关键步骤解析
2.1 几何建模与材料定义
多孔介质几何建模有两种主流方法:
- 通过图像处理导入真实岩心扫描数据
- 使用随机算法生成人造多孔结构
对于初学者,建议先用COMSOL的CAD工具创建简化模型。例如构建一个包含5-10个不规则孔隙的二维几何:
matlab复制% 示例:创建随机孔隙结构
porosity = 0.3; // 孔隙度
npores = 8; // 孔隙数量
for i=1:npores
x0 = rand()*100e-6;
y0 = rand()*100e-6;
a = 5e-6 + rand()*10e-6;
b = 5e-6 + rand()*10e-6;
model.geom.create(sprintf('pore%d',i), 'Ellipse');
model.geom.feature(sprintf('pore%d',i)).set('pos', [x0,y0]);
model.geom.feature(sprintf('pore%d',i)).set('semiaxes', [a,b]);
end
材料参数设置需特别注意:
- 两相密度比(ρ_oil/ρ_water)建议在0.8-1.2之间
- 粘度比(μ_oil/μ_water)通常在5-50范围内
- 界面张力γ一般在0.01-0.05 N/m
2.2 物理场设置与边界条件
相场模块的关键参数设置:
matlab复制phi = model.physics.create('pf', 'PhaseField', 'geom1');
phi.prop('gamma').set('1e-3[N/m]'); // 界面能
phi.prop('epsilon').set('5e-6[m]'); // 界面厚度
phi.prop('M').set('1e-11[m^2/s]'); // 迁移率
// 润湿性设置
bc = model.physics('pf').feature.create('bc1', 'PhaseFieldBC', 1);
bc.selection.named('pore_walls');
bc.prop('theta0').set('contact_angle[deg]'); // 通过参数控制
流动边界条件建议:
- 入口:速度入口(0.1-1 mm/s)
- 出口:压力出口(常压)
- 孔隙壁面:无滑移边界
3. 网格划分策略与求解器设置
3.1 自适应网格加密技术
多孔介质模拟的网格需要特殊处理:
- 在孔隙通道处添加边界层网格
- 使用尺寸函数控制局部加密
- 相界面区域设置自适应细化
matlab复制mesh = model.mesh.create('mesh1', 'geom1');
mesh.feature.create('size1', 'Size');
mesh.feature('size1').set('custom', 'on');
mesh.feature('size1').set('hmin', '0.1e-6[m]');
mesh.feature('size1').set('hmax', '5e-6[m]');
// 孔隙边缘加密
mesh.feature.create('edge1', 'Edge');
mesh.feature('edge1').selection.geom('geom1', 1);
mesh.feature('edge1').selection.named('pore_edges');
mesh.feature('edge1').set('elementSize', '0.5e-6[m]');
3.2 瞬态求解器配置
推荐使用以下求解器设置:
- 初始步长:1e-6 s
- 相对容差:0.01
- 绝对容差:0.001
- 最大迭代次数:50
对于强非线性问题,可以启用:
- 阻尼因子(0.7-0.9)
- 牛顿迭代法的线搜索
4. 后处理与结果分析
4.1 残余油饱和度计算
通过域积分计算残余油饱和度:
matlab复制% 油相体积分数积分
int1 = model.result.numerical.create('int1', 'IntVolume');
int1.selection.named('geom1_dom');
int1.set('expr', '0.5*(1-phi)'); // phi=1为水相,phi=-1为油相
% 采出程度计算
outlet_flux = model.result.numerical.create('out1', 'IntSurface');
outlet_flux.selection.named('outlet');
outlet_flux.set('expr', '0.5*(1-phi)*u*nx');
4.2 润湿性影响分析
通过参数化扫描研究接触角影响:
matlab复制study = model.study.create('param', 'Parametric');
study.feature('param').set('pname', {'contact_angle'});
study.feature('param').set('plistarr', {'30 90 120'});
study.feature('param').set('punit', {'deg'});
典型结果对比:
- 水湿条件(θ<90°):残余油呈孤立液滴状
- 中性润湿(θ≈90°):油相形成连续网络
- 油湿条件(θ>90°):油膜覆盖孔隙表面
5. 常见问题排查指南
5.1 收敛性问题解决方案
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 相场变量超出[-1,1]范围 | 迁移率M过大 | 降低M值1-2个数量级 |
| 质量不守恒 | 界面厚度ε与网格不匹配 | 确保h_max < ε/2 |
| 虚假流动 | 初始条件不协调 | 使用稳态求解初始化 |
5.2 计算效率优化技巧
- 使用分离式求解器:先解相场方程,再解流动方程
- 对线性问题使用直接求解器(MUMPS)
- 非线性较强时改用GMRES迭代法
- 合理使用"冻结"功能:先计算稳态流场,再解瞬态相场
我在实际模拟中发现,当驱替速度超过临界毛细数Ca_crit=μU/γ时(U为特征速度),采出曲线会出现明显平台期。这时继续注水的采收率提升非常有限,建议在实际油藏开发中考虑转向其他增产措施。
最后分享一个调试技巧:遇到难收敛的情况时,可以先用较大的界面厚度(如ε=1e-5 m)和较低的驱替速度进行计算,待获得稳定解后再逐步调整到实际参数。这种方法虽然增加了计算步骤,但总耗时往往比直接求解困难工况更少。