求解器应用程序(求解器)在结构上与任何其他 OpenFOAM 应用程序没有区别:它使用在不同 OpenFOAM 库中实现的算法。求解器不是对物理场进行算术处理或以某种方式操纵网格,而是近似于对物理过程建模的偏微分方程 (PDE) 求解解。第 1 章简要概述了 OpenFOAM 中用于 PDE 离散化的 FVM。OpenFOAM 求解器根据求解器模拟的物理过程分为不同的类别。它们可以通过使用预定义的别名命令位于 OpenFOAM 安装中:

sol

切换到 OpenFOAM 中所有可用求解器的父目录,或者手动更改为 FOAM_SOLVERS


作为示例求解器,我们为两相流的 DNS 选择了 interFoam 求解器。 interFoam 求解器实现了一个数学模型,该模型将两种分离的不混溶流体(相)的流动描述为单一流体(连续体)的流动。通过使用额外的标量场 - 体积分数场 (α) 来完成相分离。该方法称为VOF方法,α表示主相的填充水平,并采用区间[0,1]中的值。有关VoF方法的更多信息,请参见[8]。

interFoam 的源代码文件位于 $FOAM_SOLVERS/multiphase/interFoam。列出 interFoam 目录的内容,结果如下:

```bash
ls <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">FO</span><span class="mord mathnormal">A</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mord mathnormal">L</span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="mord mathnormal" style="margin-right:0.05764em;">ERS</span><span class="mord">/</span><span class="mord mathnormal">m</span><span class="mord mathnormal">u</span><span class="mord mathnormal">lt</span><span class="mord mathnormal">i</span><span class="mord mathnormal">p</span><span class="mord mathnormal">ha</span><span class="mord mathnormal">se</span><span class="mord">/</span><span class="mord mathnormal">in</span><span class="mord mathnormal">t</span><span class="mord mathnormal" style="margin-right:0.02778em;">er</span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord mathnormal">o</span><span class="mord mathnormal">ama</span><span class="mord mathnormal">lp</span><span class="mord mathnormal">ha</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">u</span><span class="mord mathnormal">Sp</span><span class="mord">.</span><span class="mord mathnormal">Hcorrec</span><span class="mord mathnormal" style="margin-right:0.13889em;">tP</span><span class="mord mathnormal">hi</span><span class="mord">.</span><span class="mord mathnormal">Hcre</span><span class="mord mathnormal">a</span><span class="mord mathnormal">t</span><span class="mord mathnormal">e</span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord mathnormal">i</span><span class="mord mathnormal">e</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">d</span><span class="mord mathnormal">s</span><span class="mord">.</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mord mathnormal">ini</span><span class="mord mathnormal" style="margin-right:0.07153em;">tC</span><span class="mord mathnormal">orrec</span><span class="mord mathnormal" style="margin-right:0.13889em;">tP</span><span class="mord mathnormal">hi</span><span class="mord">.</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mord mathnormal">in</span><span class="mord mathnormal">t</span><span class="mord mathnormal" style="margin-right:0.02778em;">er</span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord mathnormal">o</span><span class="mord mathnormal">am</span><span class="mord">.</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord mathnormal">in</span><span class="mord mathnormal">t</span><span class="mord mathnormal" style="margin-right:0.02778em;">er</span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord mathnormal">i</span><span class="mord mathnormal">x</span><span class="mord mathnormal">in</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord mathnormal">o</span><span class="mord mathnormal">am</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord mathnormal" style="margin-right:0.03148em;">ak</span><span class="mord mathnormal">e</span><span class="mord">/</span><span class="mord mathnormal">o</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mord mathnormal" style="margin-right:0.02778em;">er</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord mathnormal">n</span><span class="mord mathnormal">t</span><span class="mord mathnormal" style="margin-right:0.03588em;">erDy</span><span class="mord mathnormal" style="margin-right:0.13889em;">MF</span><span class="mord mathnormal">o</span><span class="mord mathnormal">am</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.03588em;">pEq</span><span class="mord mathnormal">n</span><span class="mord">.</span><span class="mord mathnormal" style="margin-right:0.02778em;">Hr</span><span class="mord mathnormal">h</span><span class="mord mathnormal">o</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">s</span><span class="mord">.</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mord mathnormal" style="margin-right:0.10903em;">U</span><span class="mord mathnormal" style="margin-right:0.03588em;">Eq</span><span class="mord mathnormal">n</span><span class="mord">.</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mord">‘‘‘</span><span class="mord cjk_fallback">每个求解器目录都包含许多不同的文件,这些文件伴随着主求解器实现文件,在本例中为</span><span class="mord mathnormal">in</span><span class="mord mathnormal">t</span><span class="mord mathnormal" style="margin-right:0.02778em;">er</span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord mathnormal">o</span><span class="mord mathnormal">am</span><span class="mord">.</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord cjk_fallback">。当求解器实现一个由不同项耦合在一起的</span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mord cjk_fallback">系统时,有必要获得一个不仅满足单个</span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mord cjk_fallback">,而且满足所有</span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mord cjk_fallback">的解决方案。附加文件实现了所谓的求解算法的一部分:确定如何在</span><span class="mord mathnormal">Op</span><span class="mord mathnormal">e</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.02778em;">FO</span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord cjk_fallback">中求解耦合偏微分方程的算法。在单独的文件中实现方程并将它们包含在主求解器应用程序中显着增加了求解器应用程序实现的求解算法的可读性。除了更好地了解求解器应用程序之外,将算法分成不同的文件使它们可以轻松地为其他求解器重用,同时避免复制源代码。包含对</span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="mord mathnormal" style="margin-right:0.13889em;">OF</span><span class="mord cjk_fallback">求解器系列重要的实现的支持文件可以通过下面的命令找到:</span><span class="mord">‘‘‘</span><span class="mord mathnormal">ba</span><span class="mord mathnormal">s</span><span class="mord mathnormal">h</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">s</span></span></span></span>FOAM_SOLVERS/multiphase/VoF/
aCourantNo.H alphaEqn.H alphaEqnSubCycle.H
teAlphaFluxes.H setDeltaT.H setRDeltaT.H

共享文件可以很容易地被放置在求解器目录中的同名文件替换:wmake 构建系统首先在求解器目录中搜索要包含的文件。包含“Eqn”后缀的文件包含定义求解器正在实施的数学模型方程的源代码。这个实现是在非常高的抽象层次上完成的,使其更具人类可读性。显然,interFoam 使用了动量方程(UEqn.H)、压力方程(pEqn.H)、体积分数方程(alphaEqn.H)以及求解算法的其他支持部分。 alphaEqn.H 由不同版本的 interFoam 共享,因此存储在 $FOAM_SOLVERS/multiphase/VoF 中。

提示:每当遇到带有 Eqn 后缀的源文件时,意味着该文件包含数学模型方程的实现。

对全局字段变量进行操作且未以函数或类的形式实现的源代码分布在求解器应用程序包含的文件中。在求解器代码中包含文件 CourantNo.H,包括求解器应用程序中当前 Courant 数的计算,该计算基于全局范围内可用的场变量。为了防止代码重复,在构建系统的帮助下,共享公共源代码片段的此类文件的数量减少到最低限度。所有共享的包含文件都存储在特定文件夹中,例如:

ls <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">FO</span><span class="mord mathnormal">A</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.07153em;">RC</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">ini</span><span class="mord mathnormal">t</span><span class="mord mathnormal">e</span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="mord mathnormal">o</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">u</span><span class="mord mathnormal">m</span><span class="mord mathnormal">e</span><span class="mord">/</span><span class="mord mathnormal">c</span><span class="mord mathnormal">fd</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal">oo</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">s</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">e</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.02778em;">er</span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord">/</span><span class="mord mathnormal">in</span><span class="mord mathnormal">c</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">u</span><span class="mord mathnormal">d</span><span class="mord mathnormal">ec</span><span class="mord mathnormal">h</span><span class="mord mathnormal">ec</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mord mathnormal">a</span><span class="mord mathnormal">t</span><span class="mord mathnormal">c</span><span class="mord mathnormal">h</span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord mathnormal">i</span><span class="mord mathnormal">e</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">d</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mord mathnormal">p</span><span class="mord mathnormal">es</span><span class="mord">.</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mord mathnormal" style="margin-right:0.13889em;">CF</span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mord">.</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mord mathnormal">ini</span><span class="mord mathnormal" style="margin-right:0.07153em;">tC</span><span class="mord mathnormal">o</span><span class="mord mathnormal">n</span><span class="mord mathnormal">t</span><span class="mord mathnormal">in</span><span class="mord mathnormal">u</span><span class="mord mathnormal">i</span><span class="mord mathnormal">t</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mord mathnormal">rrs</span><span class="mord">.</span><span class="mord mathnormal">Hre</span><span class="mord mathnormal">a</span><span class="mord mathnormal">d</span><span class="mord mathnormal">G</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mord mathnormal">i</span><span class="mord mathnormal">t</span><span class="mord mathnormal">a</span><span class="mord mathnormal">t</span><span class="mord mathnormal">i</span><span class="mord mathnormal">o</span><span class="mord mathnormal">na</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">A</span><span class="mord mathnormal">cce</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal" style="margin-right:0.02778em;">er</span><span class="mord mathnormal">a</span><span class="mord mathnormal">t</span><span class="mord mathnormal">i</span><span class="mord mathnormal">o</span><span class="mord mathnormal">n</span><span class="mord">.</span><span class="mord mathnormal">Hre</span><span class="mord mathnormal">a</span><span class="mord mathnormal">d</span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord mathnormal" style="margin-right:0.07153em;">SOC</span><span class="mord mathnormal">o</span><span class="mord mathnormal">n</span><span class="mord mathnormal">t</span><span class="mord mathnormal">ro</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">s</span><span class="mord">.</span><span class="mord mathnormal">Hre</span><span class="mord mathnormal">a</span><span class="mord mathnormal">d</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal">im</span><span class="mord mathnormal">e</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord mathnormal">o</span><span class="mord mathnormal">n</span><span class="mord mathnormal">t</span><span class="mord mathnormal">ro</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">s</span><span class="mord">.</span><span class="mord mathnormal">Hse</span><span class="mord mathnormal">t</span><span class="mord mathnormal">De</span><span class="mord mathnormal">lt</span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">.</span><span class="mord mathnormal">Hse</span><span class="mord mathnormal">t</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord mathnormal">ni</span><span class="mord mathnormal">t</span><span class="mord mathnormal">ia</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">De</span><span class="mord mathnormal">lt</span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">.</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mord mathnormal">o</span><span class="mord mathnormal" style="margin-right:0.07153em;">lC</span><span class="mord mathnormal">o</span><span class="mord mathnormal">n</span><span class="mord mathnormal">t</span><span class="mord mathnormal">in</span><span class="mord mathnormal">u</span><span class="mord mathnormal">i</span><span class="mord mathnormal">t</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mord">.</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mord">‘‘‘</span><span class="mord cjk_fallback">并在</span></span></span></span>FOAM_SRC/finiteVolume/lnInclude 文件夹中创建指向这些文件的链接,因此该文件夹可用于 Make/options 以启用在求解器应用程序中包含共享文件。默认情况下,所有 OpenFOAM 应用程序都包含finiteVolume/lnInclude 作为编译器的搜索目录:

```bash
EXE_INC = \
        -I$(LIB_SRC)/finiteVolume/lnInclude \

此目录包含指向finiteVolume 目录及其子目录中所有头文件的符号链接。因此,来自 cfdTools 的不同应用程序之间共享的包含头文件默认可供任何 OpenFOAM 应用程序使用。

上面列出了根据头文件实现的其他全局可用功能,它们包括以下内容:

  • 基于 CFL 条件的时间步调整
  • 体积守恒校正
  • 连续性误差的确定
  • 读取重力加速度矢量…

有人可能会争辩说,根据包含在应用程序(求解器)代码中的文件实现的计算并不是一种纯粹的面向对象的软件设计方法。这是真的,然而,CFD 模拟的本质是程序性的:处理模拟输入以计算近似解并存储输出。因此,一些变量已成为全局变量,因此求解过程始终可以访问,例如场和网格。在这种情况下,将包含文件中定义的操作封装到类中并对其施加层次结构仍然是可能的。例如,没有什么能阻止用户实现类的层次结构,这些类实现不同的策略来修改基于 Courant 数的时间步长。实际上,使用全局字段变量作为参数执行的计算可以很好地封装到函数对象中,如第 12 章所述。然而,这种封装并非总是必要的,在这些情况下,使用包含的源文件。

fvVectorMatrix UEqn
(
    fvm::ddt(rho, U)
    + fvm::div(rhoPhi, U)
    + turbulence-> divDevRhoReff(rho, U)
);

OOD 用于封装离散算子所需的插值等内容,并使它们的交互对 OpenFOAM 的用户不可见,除非作为配置文件中的命名条目。正如前面章节中已经指出的,fvSolution 和 fvSchemes 字典负责控制数值方案和求解器。数学模型的方程调用诸如速度、压力、动量等领域的离散算子。这就是为什么不同的求解器在 fvSolution 和 fvSchemes 字典中需要不同的条目的原因,如果默认条目设置为none的话。因此,求解器的用户和开发人员都不必关心任何方案是如何实现的,OpenFOAM 会根据配置文件中的规范自动选择所选方案。由于为格式启用了 RTS,因此如果离散化发生更改,则不得重新编译求解器。

提示:OpenFOAM 使用通用编程来实现离散微分算子。算子将离散化和插值操作分别分配给离散化和插值方案的通用层次结构。插值/离散化类模板已实例化,并已在运行时可选。结果,选择不同的格式时,不需要更改求解器代码。

9.1.1 Fields

如第 1 章所述,非结构化 FVM 需要将流域离散细分为有限体积的网格,物理场(例如压力、速度、温度)映射到该网格上。物理场、网格和解控制(由 Time 类实现)在模拟开始但时间循环开始之前由解算器初始化。可以在主求解器应用程序文件 interFoam.C 中检查求解器代码的初始化部分,如清单 32 所示。上面列出的大多数包含(头)文件都可以全局使用。一些头文件是求解器特定的,在这种情况下,它们对任何应用程序都不可用,但存储在求解器源目录中。求解器特定文件的示例是 createFields.H 和 readTimeControls.H,它们读取求解器特定字段和求解器相关控制结构。当调用求解器时,求解器期望在 createFields.H 中初始化的任何字段都存在于模拟案例的初始 (0) 目录中。

#include "setRootCase.H"
#include "createTime.H"
#include "createMesh.H"
pimpleControl pimple(mesh);
#include "initContinuityErrs.H"
#include "createFields.H"
#include "readTimeControls.H"
#include "correctPhi.H"
#include "CourantNo.H"
#include "setInitialDeltaT.H"

9.1.2 求解算法

动量守恒方程包含右侧的项,用于模拟作用在流体上的压力的体积力密度。压力场在模拟开始时是未知的。作用在流体上的压力会强制改变动量,但质量守恒(连续性)方程需要始终满足。对于不可压缩的流动,这种情况会导致连续性方程和动量方程之间的紧密耦合。这种方程耦合通常被称为压力-速度耦合,在 CFD 中开发了许多算法,其唯一目的是在处理方程耦合的同时保持求解过程稳定。

耦合可以通过使用块耦合求解器的代数方程组的联立求解来解决。研究非结构化网格的块耦合求解算法的起点通常是 [2] 的工作。专门针对 OpenFOAM 的开发是 [1] 和 [5] 等。尽管对方程耦合的强性质很直观,但由于在 CFD 中遇到压力-速度耦合问题时计算机的内存限制过高,这种方法在历史上并未被使用。因此,已经开发了将原始方程组修改为允许每个方程单独求解的分离算法。

有关压力-速度耦合的 CFD 求解算法的详细信息,请参见 [3] 和 [6] 所著的 CFD 教科书。 OpenFOAM 实现了两种主要的压力-速度耦合算法:最初由 [4] 开发的带有算子分裂的压力隐式 (PISO) 算法和最初由 [7] 开发的压力关联方程的半隐式方法 (SIMPLE) 算法。