0OpenFOAM simulation是一个包含用于配置模拟的不同子目录和文件的目录。这种OpenFOAM模拟的文件结构使得设置边界和初始条件非常简单。每个对模拟重要的物理量(压力、温度、速度场等)都有其文件,存储在0目录中:属于模拟第一个时间步的目录。本节介绍如何在这些文件中实际应用第1.3节中的边界条件和初始条件。根据场的张量秩(标量、向量、张量),使用稍微不同的语法设置它们各自的值。本次讨论仅限于案例配置;第1.3节和第10章分别讨论了边界条件的数值和设计细节。顾名思义,边界条件定义网格边界处的场值。初始条件指内部场变量的初始值。图1.12显示了内部值和边界值之间的差异示意图。

有关计算网格的更多信息,请参见第2.1章。第1章讨论了数值方法的基本原理。读者应该在一定程度上了解这两个主题。

在仔细查看如何定义边界条件文件之前,必须将用icoFoam模拟的方腔实例复制到选择的位置。要设置方腔仿真实例的基本边界条件,需要复制并重命名仿真实例目录:

?>  cp -r $FOAM_TUTORIALS/incompressible/icoFoam/cavity/cavity cavityOscillatingU
?>  cd cavityOscillatingU

列出0/目录表明定义了两个不同的物理场:p和U。这两个文件都可以直接从命令行中使用任何文本编辑器进行编辑。可以使用以下命令将压力边界条件文件的相关行打印到屏幕上:

?>  cat 0/p | tail -n 23 | head -21

dimensions [0 2 -2 0 0 0 0];
internalField uniform 0;
boundaryField
{
    movingWall
    {
        type zeroGradient;
    }
    fixedWalls
    {
        type zeroGradient;
    }
    frontAndBack
    {
        type empty;
    } 
}

内容显示边界条件文件的三个顶级对象:dimensionsinternalFieldboundaryField。第一个对象是一组标量维度(dimsionSet),用于定义物理场的量纲。每个标量对应于特殊SI单位的幂,如维度集(dimensionSet.H)的声明源文件中所定义。

// 定义维度指数名称的枚举
enum dimensionType
{
    MASS, // 质量 kg
    LENGTH, // 长度 m
    TIME, // 时间 s
    TEMPERATURE, // 温度 K
    MOLES, // 物质的量 mol
    CURRENT, // 电流 A
    LUMINOUS_INTENSITY // 光强 Cd
};

另一个对象是internalField,其定义了物理场的初始条件。请注意,这不包括由最后一个子字典:boundaryField定义的边界。在本例中,所有网格值都设置为0。还可以在每个网格格的基础上定义初始值,这反过来要求用户为每个网格组成一个包含所需值的列表。该列表中的网格数量必须与网格中的单元数量相同,其组成如[5]所述。最后,在boundaryField子目录中定义边界条件。必须为每个patch和每个物理场指定边界条件。因此,每个patch的边界条件在boundaryField字典的子字典中定义。

3.2.1 设置边界条件

OpenFOAM的官方发布已经附带了许多边界条件。在案例目录中执行foamHelp命令时,会提供所有可用边界条件的列表。 它说明了场类型,只显示了与相应场兼容的边界条件。结果列表中显示的一些边界条件非常一般,而其他边界条件则非常特定于问题。对于速度场U,可以用以下方式调用:

?>  foamHelp boundary -field U

foamHelp要求在检查可用边界条件时生成网格。作为定义边界条件的一个小例子,使用了之前复制的cavityOscillatingU案例。在本例中,将速度场U的动壁边界条件更改为确保速度随时间振荡的边界条件(图3.1)。要设置振荡速度,我们将使用codedFixedValue边界条件。这种边界条件允许其用户编写C++代码,定义边界条件如何运行。这个C++代码然后在上面的编码边界条件的C++代码片段中,我们重载了OpenFOAM场赋值操作符,以将速度向量设置为cos(πt)(1,0,0),使其每秒切换一次方向。除了上述对U场的改变外,还必须延长模拟时间,以便可以可视化几个速度振荡周期。为此,必须更改system/control Dict字典:将条目endTime从0.5修改为4.0。所有需要的调整都已完成,更改后的边界条件可以使用icoFoam解算器进行测试。在执行此操作之前,必须使用block Mesh工具生成网格:OpenFOAM编译成仿真实例中的库,存储在dynamicCode子文件夹中。该库动态链接到求解器应用程序,并在模拟中使用。由于它是实现边界条件的C++代码,边界条件的用户应该知道如何在OpenFOAM中用标量、向量或张量来执行它们各自物理场的基本操作。

本书第二部分介绍了C++编程知识。一般来说,关于边界条件、function object和其他OpenFOAM组件的使用信息可以在扩展代码指南中找到,也在第5章中介绍。或者在OpenFOAM源代码中读取边界条件的头文件通常更快。必须使用文本编辑器打开文件中codedFixedValue边界条件的声明。该文件位于:

$FOAM_SRC/finiteVolume/fields/fvPatchFields/derived/codedFixedValue/codedFixedValueFvPatchField.H

头文件顶部的注释部分的Description部分包含边界条件用法的描述,我们在这里针对movingWall边界进行修改:

movingWall
{
    type codedFixedValue;
    value uniform (0 0 0);
    name oscillatingFixedValue; // name of generated BC
    code
    #{
        operator==(Foam::cos(this-> db().time().value() * M_PI)*vector(1,0,0));
    #};
}

在上面的边界条件的C++代码片段中,我们重载了OpenFOAM场赋值操作符,以将速度向量设置为,使其每秒切换一次方向。除了上述对速度场的改变外,还必须延长模拟时间,以便可以观察几个速度振荡周期。为此,必须更改system/controlDict字典:将条目endTime从0.5修改为4.0。所有需要的调整都已完成,更改后的边界条件可以使用icoFoam解算器进行测试。在执行此操作之前,必须使用blockMesh工具生成网格:

?>  blockMesh
?>  icoFoam

可以使用paraView实现速度场的可视化。

注:要使用ParaView查看OpenFOAM的计算结果,可以创建一个扩展名为.foam的空文件,然后利用ParaView打开。

在振荡边界条件的驱动下,内部流动发生脉动。

在选择边界条件时总是需要仔细考虑,特别是在将结果与实验(验证)或精确解(验证)进行比较时。在 foam _ tutorial cases 教程中包含了使用不同边界条件的模拟示例。教程案例可以是一个使用不同的边界条件有用的信息来源。

3.2.2 设置初始条件

在这一节中,概述了如何设置模拟的初始条件。初始条件在模拟开始时定义内部物理场的值。有各种不同的工具用于用户指定初始化物理场。第八章提供有关如何开发新的前后处理应用的资料。

注:设定初始条件(IC)称为前处理。

初始条件可以是微不足道的,就像方腔案例一样:将初始内部速度和压力设置为统一的向量值0。在第一个时间步长之后,计算的流动解通常与初始设置的流动解有很大不同。对于定常的单相不可压缩流动,初始条件可以看作是加速收敛到定常的初始条件。如果这个猜测离最终结果,可能会出现计算发散。

在其他情况下,初始条件是至关重要的,因为它们决定了场如何从初始值在时间上演变。可压缩流动模拟在很大程度上依赖于初始压力、温度和/或密度来正确地计算状态方程。不可压缩的多相模拟需要非常精确的用于分离流体相的相指示器场的初始值。初始相位指示器中的较大误差会导致更大的曲率近似误差,从而导致很强的数值不稳定性和可能的灾难性失败。

如前所述,空腔示例情况对初始条件的定义相对宽容。对初始条件有特殊要求的情况是使用interFoam解算器模拟的damBreak情况。求解器interFoam是一个两相流动求解器,使用代数流体体积方法区分两个不可混溶和不可压缩的流体相。为此,引入了一个新的标量场:alpha.water。本例中的气体和液相的alpha.water值分别为0和1。对于第一个示例,将向damBreak案例添加一个水滴,如图3.2所示。

首先,创建damBreak教程案例的副本,并将案例重命名:

?>  run
?>  cp -r FOAM_TUTORIALS/multiphase/interFoam/laminar/damBreak/damBreak damBreakWithDrop

原始场值通常保存在子文件夹0中,或保存在0文件夹中的*.orig字段文件中。要重置alpha.water的初始值,请将0/alpha.water文件复制到0/alpha.water:

?>  cp 0/alpha.water 0/alpha.water

此时检查0/alpha.water字段的当前状态显示,整个内部字段的值均为0:

internalField uniform 0;

setFields实用程序可用于创建更复杂、不均匀的物理场分布。此实用程序由system/setFields字典控制。setFields应用程序的模板字典文件存储在应用程序源目录中:$FOAM_APP/utilities/pre-Processing/setFields。由于该文件相当长,因此不显示内容。然而,值得研究setFieldsDict的内容,因为它存储了setFields应用程序可用于预处理非均匀物理场的所有可用规范。

下面显示了测试用例的setFieldsDict的内容,以及用于初始化小水滴(即alpha.water值为1的圆)的添加的spherToCell子字典条目:

defaultFieldValues
(
    volScalarFieldValue alpha.water 0
);
regions
(
    boxToCell
    {
        box (0 0 -1) (0.1461 0.292 1);
        fieldValues
        (
                volScalarFieldValue alpha.water 1
        );
    }
    sphereToCell
    {
        origin (0.4 0.4 0);
        radius 0.05;
        fieldValues
            (
            volScalarFieldValue alpha.water 1
            volVectorFieldValue U (-1 0 0)
        );
    }
);

初始场如下图所示。

defaultFieldValues将内部场设置为提供的默认值0,然后继续处理regions子字典。

setFieldsDict的语法对于上面所示的简单形状体积选择基本上是不言自明的。对于选定的体积,其单元中心位于该体积内的所有单元都将相应地设置给定的字段。例如,sphereToCell源选择中心位于指定中心和半径球体内的单元,并设置物理场alpha.water=1和U=(−1, 0, 0)。

为了预处理alpha.water并运行模拟,需要在命令行中执行以下步骤:

?>  blockMesh
?>  setFields
?>  interFoam

图3.2显示了由于我们增加了setFieldDict而改变的初始条件的说明。