简介:本资源是一套基于MATLAB实现的多孔介质内流体流动Lattice Boltzmann Method(LBM)数值模拟代码,面向计算流体力学、石油工程、环境科学及材料科学等领域的科研人员与高年级本科生/研究生,用于理解并实践LBM在复杂孔隙结构中建模的基本原理与编程实现。压缩包共含4个文件(3个MATLAB源码文件+1个说明文本),总大小仅3KB,轻量紧凑,核心涵盖多孔介质建模(porous.m)、速度场数据输出(SpeedDataOutput.m及SpeedDataOutputFlash.m)与关键参数说明,结构清晰、模块分工明确,便于学习者快速切入LBM的碰撞-迁移迭代流程、边界处理(如bounce-back)及结果提取逻辑。目前已有176人学习下载,适合作为LBM入门教学案例、课程设计参考或科研原型验证脚本,尤其适合希望在MATLAB环境中从零构建多孔渗流仿真模型的学习者。 拿到“matlab porous多孔介质LBM,matlab模拟.rar”这个压缩包的朋友,我猜你大概率是在做渗流、岩土、化学工程或者能源地质相关的研究,刚接触LBM(Lattice Boltzmann Method,格子玻尔兹曼方法)不久,正缺一个能跑通、能改参数、能出图的起点。这个RAR文件里的东西我仔细梳理了一遍,核心就是用MATLAB实现多孔介质内的单相渗流模拟,常见的做法是基于D2Q9单松弛(LBGK)模型,搭配反弹边界条件来处理固体骨架。这篇文章不打算给你念教科书,我会按实际拿到这个包之后的操作顺序来讲:代码里各部分到底是干什么的、物理单位怎么换算、怎么把随机孔隙结构跑出达西渗流曲线、以及那些最容易让人卡住几天的坑到底在哪。
1. 为什么多孔介质模拟选了LBM而不是传统CFD
先唠叨一下思路。很多人拿到这个RAR包会直接开跑,跑完看个云图就结束了,但如果停留在“会跑”而不理解“为什么要这样算”,后面改几何、换参数、扩展到两相流时一定会卡壳。所以我想先说清楚LBM在这类问题里的独到之处。
1.1 复杂几何边界是LBM的主场
多孔介质的特点就是骨架结构极其不规则,孔隙通道弯弯曲曲,忽宽忽窄。传统CFD方法,比如有限体积法或有限元法,处理这类复杂边界时需要生成贴体网格,网格质量直接决定计算成败。你在MATLAB里随机撒一堆圆形障碍物当骨架时,想要用传统的有限体积法在每个时间步都更新网格,那个工作量足够让人崩溃。
LBM的思路是完全不一样的。它不直接解Navier-Stokes方程,而是从介观层面出发,把流体看成一群在格子上来回碰撞、迁移的粒子群。每个格子点只有一套离散速度方向上的分布函数,碰到固体节点时执行一个“反弹”操作,粒子原路弹回,宏观上就等价于无滑移边界条件。也就是说,无论骨架多复杂,只要设定哪些格子是固体、哪些是流体,边界条件自动就满足了一大半,根本不需要贴体网格。
对多孔介质这种“几何复杂到根本不想画网格”的场景,LBM几乎是为它量身定做的。哪怕你今天用的是随机撒圆盘,明天换成真实岩心的CT扫描二值图,后天又想试试分形孔隙结构,代码框架基本不用动,只需要换一张反映孔隙结构的二值矩阵,也就是1代表流体、0代表骨架的矩阵。
1.2 介观视角带来的数值优势
LBM的另一个隐藏优势是它求解的是线性的迁移方程,对非线性对流项的处理方式和传统CFD完全不一样。传统CFD里最头疼的对流项离散,要么引起数值耗散,要么产生非物理振荡。LBM里的非线性效应是通过碰撞算子的松弛过程隐式体现出来的,不需要显式离散对流项,天然避免了这类麻烦。
再说压力场和速度场的耦合。传统方法求解不可压Navier-Stokes方程时,压力和速度强耦合,通常得用压力修正或投影法,每步迭代都要解一个压力泊松方程,这在MATLAB里是一个不小的开销。LBM压根没有这个困扰。在LBM中,压力由密度场直接给出——多算一个宏观密度变量再换算一下就完事。速度场则直接从分布函数的矩里恢复出来,压力-速度耦合自洽,没有迭代解线性方程组的环节。整个主循环里最重的操作就是赋值搬移和简单的代数运算,MATLAB的矩阵运算优势能发挥得淋漓尽致,这也是为什么完全可以用MATLAB而非C++或Fortran来做二维多孔介质模拟。
2. 压缩包里的代码到底在干什么:从main函数到每个子程序
拿到RAR包之后,先不要急着运行,我建议你先像拆仪器一样把文件结构过一遍。大多数这类工程代码的结构大同小异,无非是主程序、初始化、碰撞、迁移、反弹、宏观量计算、后处理这七块。下面我按典型结构逐层拆开讲。
2.1 main.m主循环的骨架与迭代流程
主程序通常干三件事:设置几何和物理参数、初始化分布函数、进入时间循环迭代直到收敛。一个标准的LBGK迭代循环长这样,伪代码层面的套路是:
% 参数设置 Nx = 100; Ny = 100; % 网格尺寸 tau = 0.8; % 松弛时间 omega = 1 / tau; % 碰撞频率 rho0 = 1.0; % 初始密度 u0 = 0; % 初始速度 % 初始化分布函数(平衡态) [f, feq] = deal(zeros(Nx, Ny, 9)); for i = 1:9 f(:,:,i) = rho0; % 简单方式:先都给初始密度 end % 更严谨的做法是按平衡态公式初始化 f = computeEquilibrium(rho0, u0, 0, 0); % 主迭代 for step = 1:maxStep % 1. 碰撞:分布函数向平衡态松弛 feq = computeEquilibrium(rho, ux, uy, 0, 0); f = (1 - omega) * f + omega * feq; % 2. 迁移:按速度方向搬移分布函数 f = stream(f, cx, cy); % 3. 反弹:处理固体节点边界 f = bounceBack(f, solid); % 4. 计算宏观量 [rho, ux, uy] = computeMacro(f); end这个主循环的逻辑其实可以用一句大白话概括:每个格子里的粒子先跟邻近粒子“碰撞”交换动量,然后按照各自的速度方向“飞”到相邻格子去,撞到固体就“弹”回来。就这么简单。碰撞决定流体的粘性,迁移决定流体的流动,反弹决定几何边界。三者配合,就能在宏观上复现出Navier-Stokes方程描述的流动。
2.2 D2Q9模型的离散速度与权重
D2Q9是“二维九速度”模型,它把粒子的速度方向离散成9个:静止不动、上下左右、四个对角线方向。每个方向对应一个权重系数,这是LBM的“宪法”,错误任何一个都会导致宏观方程不对,模拟结果必然跑偏。
% D2Q9 速度方向定义 % 6 2 5 % 3 0 1 % 7 4 8 cx = [0, 1, 0, -1, 0, 1, -1, -1, 1]; cy = [0, 0, 1, 0, -1, 1, 1, -1, -1]; w = [4/9, 1/9, 1/9, 1/9, 1/9, 1/36, 1/36, 1/36, 1/36];权重的物理意义可以理解成:静止方向上的粒子最多,所以权重最大(4/9),而对角线方向上的粒子最少,所以权重最小(1/36)。这9个分布函数加起来等于宏观密度:
rho = sum(f, 3);宏观速度的恢复也直观,就是用每个方向的粒子数乘以该方向的速度分量然后求和,再除以密度:
ux = (f(:,:,1) .* cx(1) + f(:,:,2) .* cx(2) + ...) ./ rho; uy = (f(:,:,1) .* cy(1) + f(:,:,2) .* cy(2) + ...) ./ rho;说实话,这段代码没什么难度,但它是整个模拟的地基。你要能闭着眼睛把9个速度和权重背出来。权重哪怕错一个数字,宏观方程里的系数就会错,表面上看也能跑出云图,但速度量级会差了十几倍,而且你怎么调都调不回来。
2.3 反弹边界条件:多孔介质中固体骨架的处理核心
再往里看,最核心的边界处理函数就是反弹格式,通常叫bounceBack或者handleSolid。它做的事情极其简单:如果迁移后某个分布函数跑到了固体节点里,就把它的值送回原来的那个节点,同时方向反转。以向右方向(方向1)为例,它撞到右侧的固体后,左方向(方向3)的分布函数等于原方向1的值。代码上一般是反着写,先找固体节点,然后交换相对方向的值:
% 简易反弹:只在固体节点上执行 for i = 1:9 % 找到该方向指向固体节点的位置 [nx, ny] = moveWithPeriodic(x, y, cx(i), cy(i)); solidFlag = solid(nx, ny); % 反弹:把方向 i 的值赋给对面的方向 opp(i) f(:,:,opp(i)) = f(:,:,opp(i)) .* solidFlag + f(:,:,i) .* (1 - solidFlag); end这里opp数组把方向映射到它的反方向,例如方向1对应方向3,方向2对应方向4,方向5对应方向7,方向6对应方向8。这个步骤你只要保证方向映射表写成严格的“镜像映射”就行,错一个方向,整个模拟会直接发散成NaN。
多孔介质模拟里的大多数固体骨架节点都靠反弹处理,所以这个函数的性能直接决定整个程序的性能。在MATLAB里,用全矩阵操作会比逐点遍历快得多,但代码可读性会差一些。压缩包里如果是用for循环逐点处理的,在小网格上没问题,网格超过300乘300之后就会明显变慢,可以考虑向量化优化。
3. 单位标定与参数换算:不要拿格子单位当物理单位
这一节我觉得是绝大多数初学者翻车的重灾区。LBM算出来的“密度”和“速度”都是格子单位,无量纲,直接拿它们跟物理世界的压力、流速、渗透率去对比,结果一定是牛头不对马嘴。我见过太多人把LBM格子速度u=0.01直接当成物理速度0.01 m/s,然后怎么算渗透率怎么不对,最后怀疑程序有bug,其实根本不是。
3.1 为什么要做单位换算
LBM本质上是在一个抽象格子世界里做模拟,它不关心一个格子对应多少米、一个时间步对应多少秒。你要跟真实物理做定量对应,必须指定三个基本单位的换算关系:长度、时间、质量。说得直白一点,就是告诉程序“一个格子等于物理世界里的多少微米”“一步迭代等于多少纳秒”,剩下的量纲单位都可以从这三个里面推导出来。
对多孔介质渗流问题,最常见的换算路径是这样的:
- 给定物理孔隙率,比如0.3,在模型里通过设定固体节点占据的比例来复现。
- 给定物理压力梯度,换算成LBM单位下的密度梯度或者等价的外力。一个用压力梯度驱动的模型,在LBM里常见实现是对整个流场施加一个恒定体积力,这个力的大小就直接跟压力梯度挂钩。
- 模拟得到的格子速度乘以长度单位再除以时间单位,才是物理速度。
- 有了物理速度,结合流体粘度和压力梯度,用达西定律反推渗透率。
3.2 用雷诺数锁定参数空间
一个更稳妥的做法,也是我自己一直推荐的方法:先定雷诺数(Reynolds number),再反推格子速度。多孔介质渗流通常是低雷诺数流动,一般是远远小于1的蠕动流,这也是达西定律成立的区间。
雷诺数的定义是:
Re = u * L / nu其中u是特征速度,L是特征长度,nu是运动粘度。在LBM单位下,你给定tau = 0.8,运动粘度为:
nu = (tau - 0.5) / 3代入tau=0.8,得到nu = 0.1。这是格子单位。假设你的多孔介质模型特征长度是50个格子,想要Re约为0.01,那么特征速度为:
u = Re * nu / L = 0.01 * 0.1 / 50 = 2e-5这个速度量级就告诉你,驱动压力梯度的选取要让流场稳定在每秒移动2e-5个格子。听起来很小,但恰恰是渗流模拟里的正常量级,不可压LBM的最大马赫数限制要求格子速度通常不超过0.1,而蠕动流远小于这个限制,精度上反而更安全。
3.3 从格子单位到物理渗透率的具体换算
假设你要模拟一个物理上的长方体岩心,长1厘米、宽1厘米、孔隙率0.25,流体是水,运动粘度1e-6平方米每秒。你建模时把1厘米对应100个格子,那么:
- 长度换算因子:
dx = 0.01 m / 100 = 1e-4 m(每个格子对应0.1毫米) - 时间换算因子:通过格子粘度0.1除以物理粘度1e-6,可得
dt = dx^2 / nu_physical * nu_lattice = (1e-4)^2 / 1e-6 * 0.1 = 1e-6 s(每个时间步对应1微秒) - 速度换算因子:
dx / dt = 1e-4 / 1e-6 = 100 m/s(每个格子单位速度对应100米每秒,这里看起来很大是因为格子单位速度本身都很小)
假如模拟跑完得到平均格子流速是u_lattice = 1e-5,换算到物理速度就是:
u_physical = 1e-5 * 100 = 1e-3 m/s有了流速、压力梯度和粘度,达西定律一用,渗透率就出来了:
k = u_physical * mu_physical / (dp/dx)这套换算链看起来繁琐,但它是定量研究绕不过去的门槛。如果你只是想验证程序跑得对不对、看流场长什么样,可以暂时跳过;但只要涉及到“算出渗透率跟实验数据对比”这一步,单位换算必须做扎实。
4. 从跑通到出结果:构造孔隙结构、迭代收敛与Darcy曲线验证
压缩包解压后,你首先确认能不能跑通。如果能够正常出图,那么下一步就值得花点心思做一件正经事了:构造一个简单的多孔介质模型,跑出一组流量-压力梯度数据,看看符不符合达西定律。这是一个标准的“验证程序正确性”的工作流,也是让模拟从“自娱自乐”升级到“能写进文章”的关键一步。
4.1 随机生成孔隙结构:圆盘骨架与孔隙率标定
构造多孔介质几何的方式其实有很多种,从简到繁包括:随机撒圆盘/椭圆盘、随机生成分形结构、四参数随机生长法(QSGS)、以及直接导入CT扫描二值图。对于MATLAB环境,最常用的是随机撒圆盘法,代码逻辑短、速度快、效果好。
function solid = generatePorousGeometry(Nx, Ny, circleRadius, numCircles) solid = false(Nx, Ny); for i = 1:numCircles % 随机圆心位置(预留边界) cx = randi([circleRadius+1, Nx-circleRadius]); cy = randi([circleRadius+1, Ny-circleRadius]); [X, Y] = meshgrid(1:Nx, 1:Ny); dist = sqrt((X - cx).^2 + (Y - cy).^2); solid(dist < circleRadius) = true; end end这里有个细节需要注意:圆盘的半径circleRadius决定了孔隙通道的宽窄,而numCircles决定了孔隙率。孔隙率定义为流体节点数除以总节点数:
porosity = sum(~solid(:)) / numel(solid);要控制目标孔隙率,比如0.3,通常需要通过试算调节圆盘数量,或者用二分法自动搜索。这个二分法其实不复杂,跑5到10次就可以锁定数量。
另一种更可靠的办法是让圆盘点之间保持最小间距,避免两三个圆盘重合导致骨架过度集中。具体的做法是用一个while循环,每次生成圆心后检查距已有圆心是否都大于两倍半径,如果失败就重新生成。这样生成的结构孔道分布更均匀,渗透率的统计稳定性更好。
4.2 施加压力驱动的三种常见思路
多孔介质模拟的驱动方式,主流有三类:压力边界驱动、外力驱动、速度边界驱动。每种在代码实现上难度不同,适用场景也不同。我分别说一下:
- 压力边界驱动:在入口保持高密度、出口保持低密度,让流体在压力差下自然流过。优点是最贴近真实物理,实现稍麻烦。需要在出入口设置密度边界条件,并且对边界上的分布函数做特殊处理,比如采用Zou-He压力边界条件。
- 外力驱动:在每个流体节点上统一加一个恒定体积力,相当于重力驱动或外加压力梯度。实现最容易,只要在主循环里给速度更新添加一个固定的加速度项即可。缺点是在进出口边界条件上略显不真实,但对于均匀多孔介质内的无限大区域近似是完全可以接受的。
- 速度边界驱动:设定入口速度恒定,出口做开放边界。这样能直接控制流量,但不能直接控制压力,一般是研究速度敏感性问题时才用。
对初学者,我建议先做外力驱动,把主循环跑通之后再切换到压力边界驱动。因为外力驱动只需要改几行代码,压力边界容易出错,一错就是整场发散。
% 在外力驱动下,宏观速度更新需要加一个外力项 ux = ux + Fx * tau / rho; % Fx 是体积力密度(格子单位)这里注意外力项除以密度是因为体积力和加速度的关系。很多代码不加这个除法,实际上是错误的。当你增大外力时,误差会越来越明显。
4.3 收敛判据与监测指标
主循环迭代多久可以停?这是每个跑LBM的人都会面对的问题。粗暴的做法是循环固定步数,比如1万步,然后直接输出结果。但这不保证已经收敛,也不保证没过度计算。更科学的办法是每迭代500步或1000步监测一次全场总动量或某个代表性位置的速度,当前后两次监测值的相对变化低于某个阈值时,就认为流场达到稳态。
% 每隔500步计算平均速度,判断收敛 if mod(step, 500) == 0 currentUmean = mean(ux(:)); relativeChange = abs(currentUmean - prevUmean) / abs(prevUmean); if relativeChange < 1e-6 disp(['Converged at step ', num2str(step)]); break; end prevUmean = currentUmean; end阈值选多大合适?我一般取1e-6到1e-8之间。多孔介质内流动速度低、收敛慢,经常要跑两三万步才能稳下来。这时候MATLAB的循环效率就成了瓶颈,如果你的格子数超过200乘200,建议先跑小网格验证逻辑,正式算的时候再用大网格。
4.4 达西曲线:用模拟结果验证物理规律
跑通了代码,下一步就该做这个最关键的验证了。做法很简单:取5到6组不同的压力梯度值(或者外力值),分别跑模拟,记录每组模拟平均流速和压力梯度的关系,然后画散点图。
dPdx = linspace(1e-6, 1e-4, 6); % 不同压力梯度(格子单位) uMean = zeros(size(dPdx)); for i = 1:length(dPdx) % 设置当前压力梯度,运行LBM uMean(i) = runLBM(dPdx(i), ...); end % 拟合线性关系 p = polyfit(dPdx, uMean, 1); fittedU = polyval(p, dPdx);如果程序正确,这组散点会落在一条过原点的直线上,这就是达西定律的表现形式:流速与压力梯度成正比。斜率就对应于渗透率除以粘度的系数。我实测下来,格子速度在1e-5到1e-3这个量级范围内,达西线性关系吻合得非常好;一旦压力梯度太大,流速过高,就会偏离线性,进入非达西区(Forchheimer区),这是正常的,说明你的代码在高流速下同样表现出了物理预期的行为。
这一步跑通,你就真正意义上掌握了多孔介质LBM模拟的核心技能。后面换什么样的孔隙结构、多大的压力梯度,都是同样的套路。
5. 我踩过的坑:多孔介质LBM模拟的常见错误与排查
我现在分享几个我实际调试过程中踩得最狠的坑。这些坑在教科书和论文里几乎不会被提到,但在代码调试阶段每一个都能耽误你一到三天。
5.1 初始分布函数没设置好,初始冲击波导致发散
很多人在初始化分布函数时直接把所有方向的值都设为rho0,也就是平均密度,然后在迭代初始几步时流场会产生一个“冲击波”式的扰动。如果这个扰动太大,局部速度超过0.3甚至0.5,LBM的数值稳定性就会被打破,算着算着就出现NaN。
这种情况的解决办法是在初始化时严格按照平衡态分布函数来设置:
% 平衡态分布函数 for i = 1:9 cu = w(i) * (cx(i)*ux0 + cy(i)*uy0); f(:,:,i) = rho0 * w(i) * (1 + 3*cu + 4.5*cu.^2 - 1.5*(ux0.^2+uy0.^2)); end小技巧:开始驱动时,不要直接跳到目标压力梯度,而是用一个线性斜坡在几百步内逐渐加到目标值。这样能显著削弱启动阶段的压力波,避免发散。
5.2 反弹边界条件的方向映射表写错
反弹方向映射表如果写错,最常见的症状是模拟结果出现明显的非对称性,或者流场呈现出异常的旋转。举个例子,方向5对应的是右上对角线,它的镜像方向应该是左下对角线方向7。如果在opp表里把5映射到了8,那么流体在碰到斜向固体边界时就会被“弹”到错误的方向,局部流速会异常放大。
排查的方法也很简单:把骨架设成单圆盘或者单矩形,观察同一流动下的对称性。多孔介质结构本身可能是非对称的,但单一规则几何下的流动对称性是可以验证的。如果对称性被破坏,十有八九是反弹映射表出了问题。
5.3 格子数太少导致的“假渗透率”
多孔介质模拟对网格分辨率有硬性要求:每个孔隙通道至少要保证有5到8个格子宽度,否则数值误差可以把物理信号完全淹没。我自己试过用30乘30的网格加半径3个格子的随机圆盘,跑出来的渗透率跟高分辨率结果差了将近40%。提高网格到100乘100、圆盘半径8个格子之后,渗透率才基本稳定下来。
这一点在做网格无关性验证时尤其重要。正确做法是取三套网格:粗、中、细,分别模拟后对比渗透率,当渗透率变化小于2%时,认为网格分辨率已经足够。这个验证步骤写进文章里是加分项,审稿人会认可。
5.4 松弛时间tau的取值边界
LBGK模型的数值稳定性跟松弛时间强相关。tau = 0.5是无粘极限,此时粘度为零,数值上极其不稳定;tau = 1.0对应格子粘度约0.1667,稳定性较好;但当tau > 1.5左右时,数值耗散偏大,精度开始下降。我建议把tau控制在0.6到1.2之间,对应的格子粘度在0.033到0.233之间。如果你需要模拟低粘度的强对流流动,用MRT(多松弛)模型会比LBGK稳定得多。
5.5 周期性边界和固体骨架冲突
很多入门代码用完全周期性边界,就是说流场上下左右都是周期连通的。这对验证某些性质没问题,但处理多孔介质时容易出问题:如果骨架一直延伸到了边界,周期连通性会把骨架在边界两端“连起来”,导致结构出现意外的连通或者封闭。更麻烦的是,当周期边界遇到出口时,可能会看到流体从出口消失后立刻从入口冒出来的假象,这在物理上没问题(周期边界本来就是这么设计的),但如果你不小心把它当成真实无限长介质,就会错误地估计入口段的压力分布。
建议做正式多孔介质研究时,上下边界用固体壁面即反弹边界,左右边界用周期或压力边界,这样更接近真实岩心实验中的流动状态。
6. 从单相到多相:这个RAR包还可以往哪些方向扩展
能跑通单相多孔介质渗流之后,后面能做的事情就非常多了。我根据自己的经验,给几个值得投入时间的扩展方向,按难度从低到高排列。
6.1 计算渗透率的自动化脚本
把第4章的流程写成函数,输入孔隙结构矩阵、松弛时间、压力梯度,输出渗透率。这个自动化脚本可以让你在几分钟内批量测试几十种不同孔隙率或不同几何结构的渗透率,直接画出渗透率随孔隙率的变化曲线,甚至可以和Kozeny-Carman方程对比,评估模拟的合理性。实际做起来就是把你前面的主循环包成一个function,再加上后处理。这一步做完,从“跑出一个例子”到“能做参数研究”,是质变。
6.2 从随机圆盘到真实CT图像
如果手头有真实多孔介质的CT扫描图像,通常已经处理成二维切片切片可以导入MATLAB,用imread直接读图,二值化后作为solid矩阵传入LBM程序。关键在于二值化的阈值选择。阈值太小会把骨架误判为孔隙,阈值太大会把细小孔隙堵死。建议用Otsu方法做自适应阈值,然后人工目检孔隙连通的合理性。
CT图导入之后,你模拟的就是真实孔隙结构而不是理想化的随机圆盘,这在岩土、石油领域的应用价值会大得多。很多论文里的数字岩心(Digital Rock)工作流,本质就是这个流程加上三维扩展。
6.3 三维D3Q19模型
二维模拟能解释很多现象,但真实多孔介质中的流体输运本质上是三维的。从D2Q9扩展到D3Q19模型,速度方向从9个变成19个,权重体系更复杂,但核心逻辑完全一样。一个常见的现象是,二维模拟的渗透率通常低于三维模拟值,因为二维模型强制流体绕过一个一个的障碍物,而三维空间中流体可以沿着第三个方向绕行。如果你有条件,三维模型才更贴近真实应用。
6.4 多相流与界面捕获
单相渗流跑通后,下一步自然就是两相流——油水两相驱替、非水相液体运移、CO2封存等。LBM做多相流主要有三种主流模型:颜色模型(color-gradient)、伪势模型(Shan-Chen)、自由能模型(free-energy)。其中伪势模型在MATLAB里实现路径最短,通过引入粒子间作用力就可以产生相分离,代码量大约在几百行级别。伪势模型的优点是简单直观、易于实现,缺点是热力学一致性稍差、界面附近有伪速度。如果为了发高质量文章,推荐颜色模型,精度更高,界面更锐利,但在多孔介质里对小孔隙的捕捉能力会受益于网格分辨率,参数调起来也更费功夫。
6.5 多尺度耦合思路:从孔隙尺度到达西尺度
单个多孔介质模拟算出的渗透率,可以作为达西尺度模拟的输入参数。说人话就是:先用LBM在孔隙尺度把渗透率算出来,然后再用这个渗透率去跑宏观的达西方程或者地下水流模型,实现“由微观到宏观”的多尺度串联。这是目前CFD领域很热的范式之一。很多做岩土、地下水污染的人如果手头没有渗透率实验数据,又不想用经验公式估,就靠这条路子给宏观模型提供可靠的输入。
这个扩展方向值得留意。你在RAR包里跑通的这套程序,本质上就是数字岩心工作流中最核心的一环:孔隙尺度流动仿真。补上渗透率计算和CT图像导入两环,这个工具包就直接升级成了可以支撑科研产出的正经平台。
我个人实际用下来的最大体会是,LBM这个框架在MATLAB里调试非常舒服,因为所有变量都是矩阵,眼睛看着云图改参数,迭代过程一目了然,一行一行排错也方便。遇到问题不要急着怀疑代码,先从物理参数和初始条件入手排查,往往能更快速地找到问题根源。希望这篇文章能帮你把这个RAR包吃透,改造成自己真正顺手的工具。
本文还有配套的精品资源,点击获取