Error message

Deprecated function: The each() function is deprecated. This message will be suppressed on further calls in menu_set_active_trail() (line 2405 of /home/www/rheoworks/includes/menu.inc).

OpenFOAM Basic 第1讲:方腔顶盖驱动流

提示: 方腔顶盖驱动流是流动模拟中最为经典的问题之一。方腔流可以反映出不同雷诺数条件下的流场特性, 并且流场中包含了涡旋、 二次流、 复杂三维流动、 不稳定层流、 过渡流和紊流等多种现象, 成为研究复杂紊动流场最为理想的物理模型, 也是验证数值模拟方法准确度和效率的标准。[1]

准备工作

  1. 安装好 OpenFOAM-ext
  2. 建立用户 run 目录,并将 tutorials 拷到该目录下:
mkdir $FOAM_RUN 
cd $FOAM_RUN
cp -r $FOAM_TUTORIAL ./

case 文件夹结构

进入 cavity 目录:

cd $FOAM_RUN/tutorials/incompressible/icoFoam/cavity/

小技巧: 用鼠标选中上面的一行命令,在终端窗口,单击鼠标滚轮或中键,即可将此命令复制到终端窗口。

运行 tree 命令,可以看到以下的文件夹结构:

.
|-- 0 # 初始条件和边界条件
|   |-- p                 # 压力
|   `-- U                 # 速度
|-- constant              # 参数和网格,文件夹
|   |-- polyMesh          # 网格
|   |   |-- blockMeshDict # 网格生成文件
|   |   |-- boundary      # boundary, faces, neighbour, owner, points 为网格文件
|   |   |-- faces
|   |   |-- neighbour
|   |   |-- owner
|   |   `-- points
|   `-- transportProperties # 流体属性文件
`-- system # 设置文件夹
    |-- controlDict # 控制字典
    |-- fvSchemes   # 离散格式设置
    `-- fvSolution  # 代数方程求解器设置,比如残差、循环次数等

p 文件

我们先来看看 p 文件的内容:

FoamFile // 文件头,指出文件版本、格式、变量类型、名称
{
    version     2.0;   // 版本号
    format      ascii; // 输出格式,此处指 ascii 文本格式
    class       volScalarField; // 变量类型,volScalarField 指体心标量场
    object      p;              // 变量(场)的名字
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// 变量的量纲设置,[ ] 内数字依次各量的量纲的幂,即
// [质量 长度 时间 温度 分子量 电流 光通量] 的标准单位
// [kg m s K mol A cd]
dimensions      [0 2 -2 0 0 0 0]; // p 的单位 m2s-2,不是 p 的真正单位,而是 p/rho
                                  // 因为各方程将 rho 的因数去掉了
internalField   uniform 0; // 内部场的值,uniform 代表统一的值,后面直接跟需要设定的值

boundaryField // 边界条件
{
    movingWall // 边界的名字
    {
        type            zeroGradient; // 第二类边界条件 (零梯度),即 dp/dn=0
    }

    fixedWalls
    {
        type            zeroGradient;
    }

    frontAndBack
    {
        type            empty;     // 空边界,说明是二维流动,该边界不参与方程离散
    }
}

U 文件

相应的 U 的内容:(和上面解释一样的,就不重复写出了)

FoamFile
{
    version     2.0;
    format      ascii;
    class       volVectorField; // 场的类型,volVectorField 表示体心向量场
    object      U;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

dimensions      [0 1 -1 0 0 0 0]; // 变量的单位,m/s

internalField   uniform (0 0 0);

boundaryField
{
    movingWall
    {
        type            fixedValue;      // 边界条件为定值
        value           uniform (1 0 0); // 值的大小,使用 ( ) 表示向量的大小
    }                                    // (1 0 0) 表示 x 方向的速度为 1 m/s

    fixedWalls
    {
        type            fixedValue;
        value           uniform (0 0 0);
    }

    frontAndBack
    {
        type            empty;
    }
}

controlDict 文件

接下来,我们看看 system/controlDict 的内容:

FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;  // 对象的类型
    object      controlDict; // 对象的名字
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

application icoFoam; // 此 case 使用的求解器的名字

startFrom       startTime; // 程序从 startTime (定义见下一行) 开始执行

startTime       0; // startTime 设定,此处为 0,可以设定为其他值
                   // 当设定为 latestTime 时,就从最近结束并保存的时间开始
stopAt          endTime;  // 程序什么时候结束

endTime         0.5; // 程序结束时间

deltaT          0.005; // 时间步长设定

writeControl    timeStep; // 以什么方式输出计算结果,timeStep 指按时间步数来输出,
                      // 也可以是 runTime,按时间间隔来输出
writeInterval   20; // 按 20 个时间步长的间隔来输出一次结果

purgeWrite      0; // 输出过程是否覆盖,如果 0 则不覆盖,大于 0 为覆盖。
                   // 比如:设为 2,意思是 case 文件夹中只有最新的两个输出 (时间) 文件夹。 
writeFormat     ascii; // 写的格式 ascii 或 binary

writePrecision  6; // 文件输出精度

writeCompression uncompressed; // 是否对生成数据进行压缩,uncompressed/compressed;

timeFormat      general; // 时间文件夹格式:fixed m.ddddd(d的个数取决于下面的
                         //  timePrecision),scientific :采用科学计数法,
                         // general:科学计数法指数小于-4用指数,大于-4用小数
timePrecision   6; // 时间文件夹精度

runTimeModifiable yes; // 在求解过程中是否允许修改字典文件 (如:controlDict) 里面的参数,
                                         // 修改后的参数会体现在下一个时间步

fvSolution 文件

下面,我们来看看,当方程离散以后的方程组用什么方法来求解,这些设定在文件 system/fvSolution 里面:

FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      fvSolution;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

solvers // 方程求解器设置
{
    p // 压力
    {
        solver           PCG;   // 预条件共轭梯度法(主要用于求解对称矩阵)
        preconditioner   DIC;   // 预测器,对角不完全 Cholesky 方法
        tolerance        1e-06; // 残差
        relTol           0;     // 容差
    };

    U // 速度
    {
        solver           PBiCG; // 预条件双共轭梯度法(主要用于非对称矩阵)
        preconditioner   DILU; // 预测器,对角不完全 LU
        tolerance        1e-05;
        relTol           0;
    };
}

PISO // PISO 控制参数
{
    nCorrectors     2;          // 修正次数
    nNonOrthogonalCorrectors 0; // 非正交修正次数
    pRefCell        0;          // 压力参考 cell 的 index
    pRefValue       0;          // 压力参考值
}

fvSchemes 文件

每一个变量在方程中都需要离散,因此,对于离散格式的设置,就要用到 system/fvSchemes 文件:

FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      fvSchemes;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

ddtSchemes          // 非稳态项离散的格式
{
    default         Euler; // 默认采用欧拉离散
}

gradSchemes         // 梯度项离散的格式
{
    default         Gauss linear; // 默认采用高斯方法,线性插值
    grad(p)         Gauss linear; // grad(p) 压力梯度项,采用高斯方法,线性插值
}

divSchemes         // 散度项离散的格式
{
    default         none;      // 默认无格式,即必须指定离散格式
    div(phi,U)      Gauss linear; // 对流项离散,采用高斯方法,线性插值
}

laplacianSchemes   // 拉普拉斯项离散
{
    default         none;
    laplacian(nu,U) Gauss linear corrected; // 粘性项离散,corrected 为非正交修正
    laplacian((1|A(U)),p) Gauss linear corrected; // 压力项离散
}

interpolationSchemes // 插值格式
{
    default         linear;
    interpolate(HbyA) linear;
}

snGradSchemes // 面法向梯度分量
{
    default         corrected; // 默认采用非正交修正
}

fluxRequired // 是否计算流率
{
    default         no; // 默认不计算
    p;                  // 压力需要计算,因为需要利用压力流率修正速度
}

解析了上面的这些文件,对在 OpenFOAM 里面的文件,你也大概有了一个了解。下面我们可以通过以下命令来运算一下这个 case。

blockMesh    # 根据 blockMeshDict 文件的设定划分网格
icoFoam > log & # 执行 icoFoam 进行仿真计算,> log 表示将计算记录输出
                # 到 log 文件,& 表示在后台运行

blockMeshDict 文件格式将另外解析。icoFoam 源程序 另行分析。

当计算完成,或网格生成后,可以运行 paraFoam 命令检查结果。paraFoam 是具有 foam 文件读写功能的 paraview 的外壳。 paraview 或 paraFoam 将另行解说。

参考文献

[1] 张金凤, 常璐, 马平亚.高雷诺数顶盖驱动方腔流实验 [J]. 水科学进展,2015, 26(3): 250-256