在 MFIX-Exa 中构建嵌入边界

MFIX-Exa 允许使用 4 种方法来指定嵌入边界(EBs)。

  1. 使用原生 AMReX cpp 函数。

  2. 使用 CSG 文件格式。

  3. 使用平面壁。

  4. 使用 STL 文件格式。

还有两个影响水平集创建的参数(在 inputs 文件中指定):

参数

描述

amr.max_level

如果大于 0,MFIX-Exa 以多级模式运行。 水平集网格遵循所有其他网格。如果等于 1, 则水平集有两个级别(一个具有更高细化的 额外级别)。

mfix.levelset__refinement

如果 amr.max_level > 1 则忽略此参数。 否则它设置水平集的最大细化度。

EB 规范

原生 AMReX 函数

MFIX-Exa 使用在命名空间 amrex::EB2 中定义的 AMReX 的构造实体几何框架。有关详细信息,请参阅 AMReX EB 文档 。这些在 src/eb/mfix_eb.cpp 中定义。函数 mfix::make_eb_geometry (也在 src/eb/mfix_eb.cpp 中定义)根据 inputs 文件中的 mfix.geometry 设置的值选择以下几何之一。

描述

mfix.geometry

箱体(最多六面墙)

box

圆柱

cylinder

漏斗

hopper

通用

generic 参见下面的注释 1

  1. Generic 几何规范需要用户在 src/eb.mfix_eb_generic.cpp 中实现。此外,请参阅 AMReX 几何文档 以获取有关如何使用构造实体几何方法构建新几何的信息。

CSG 文件格式

或者,可以使用 OpenSCAD 的 CSG 文件格式创建构造实体几何,方法是安装 csg-eb 库。要使用此选项,MFIX-Exa 必须在构建时使用标志 MFIX_CSG=TRUE,并在 inputs 中设置选项 mfix.geom_type = csgmfix.geometry_filename。有关此格式的更多详细信息,请参阅 CSG-EB 仓库

平面壁

可以在 inputs 文件中指定平面边界条件。即使用户在 inputs 中未指定 mfix.geometrymfix.geometry_filename,任何无滑移或自由滑移边界条件都表示为 EB 壁。

STL 文件格式

可以使用多种 CAD 程序创建的标准三角形语言(STL)文件来指定 EB 几何。要使用此方法,必须在 inputs 中设置选项 mfix.geom_type = stlmfix.geometry_filename

MFIX-Exa 如何构建 EB 几何

一旦在 inputs 文件中指定了几何,所有几何的过程都是相同的。

  1. 构建表示几何的隐式函数。

  2. 调用 mfix::build_eb_levels(gshop) 该函数构建 EB 级别。注意,这也使颗粒 EB 级别指向流体 EB 级别。

  3. 调用 mfix.fill_eb_levelsets。此函数填充水平集 MultiFab

MFIX-Exa 的 EB 数据结构

mfix 类存储以下 EB 数据:

//! 代表流体边界条件的 EB 级别
Vector<const EB2::Level *> eb_levels;
//! 代表颗粒边界条件的 EB 级别(与 `mfix::eb_levels` 相同,但可能包括额外的墙)。
Vector<const EB2::Level *> particle_eb_levels;

//! 存在于流体网格上的 EB 工厂
Vector< std::unique_ptr<amrex::EBFArrayBoxFactory> > ebfactory;
//! 存在于颗粒网格上的 EB 工厂
Vector< std::unique_ptr<amrex::EBFArrayBoxFactory> > particle_ebfactory;

如上一小节所述,mfix::eb_levelsmfix::particle_eb_levels 之间的区别使用户能够仅为颗粒指定修改后的 EB 几何。而流体会在 mfix::eb_levels 中看到 EB 几何。如果未指定额外的颗粒 EB 几何(上一节的第 4 点),则 mfix::particle_eb_levels 指向 mfix::eb_levels

同样,mfix::ebfactory 是在流体网格上构建并使用流体 EB 级别,而 mfix::particle_ebfactory 是在颗粒网格上使用颗粒 EB 级别构建的。

关于构建 EB 级别的说明

MFIX-Exa 在 mfix::build_eb_levels 中构建 EB 级别(通过 LSCore<F>::BuildEBLevel

EB2::Build(gshop, geom[lev], required_crse_lev, max_crse_level);
const EB2::IndexSpace & ebis = EB2::IndexSpace::top();

在构建 EB 级别时,需要指定最大粗化级别 (int max_crse_level) 和所需粗化级别 (int required_crse_lev)。这样做的原因是我们需要指定 EB 仍然定义在哪个粗化级别。这可能不是立即显而易见的,但泊松求解器(用于流体求解)也间接依赖于这些参数。因此,在创建 EB 级别时更改这些参数可能会限制 MLMG 求解器可以使用的级别数量,从而在流体求解中给出略有不同的答案。

在壁面处的局部网格细化

MFIX-Exa 具有在 EBs 附近局部细化计算网格的能力。这是通过标记(在 mfix::ErrorEst 中)体积分数介于 0 和 1 之间的任何单元来完成的。要启用局部网格细化,请将 amr.max_level 设置为大于 1 的值。请注意,参数 mfix.levelset__refinement 在所有情况下都被忽略,除非 amr.max_level = 1

MFIX-Exa 初始化过程

由于 MFIX-Exa 在构建网格时需要体积分数(因为这是 mfix::ErrorEst 所需的),因此在调用 mfix::Init 之前需要构建 EB 几何。因此,推荐的过程是

// 默认构造函数(geom[lev] 在此处定义)
mfix my_mfix;

// 从 ParamParse 数据库初始化内部参数
my_mfix.InitParams(solve_fluid, solve_dem, call_udf);

// 初始化数据数组内部的内存
my_mfix.ResizeArrays();

// 构建 EB(必须在 mfix::Init 之前完成)
my_mfix.make_eb_geometry();

// 初始化派生的内部参数。在此处创建网格。
my_mfix.Init(dt, time);

// 在新网格上创建 EB 工厂
my_mfix.make_eb_factories();

if (solve_dem)
{
    // 在每个级别上填充水平集(必须在 mfix::Init 之后完成)
    my_mfix.fill_eb_levelsets();
}

// 完成构建级别
my_mfix.InitLevelData(dt, time);

// 重网格(确保所有 MultiFabs 都在其正确的网格上)
my_mfix.Regrid();

还请注意,mfix 也在 Fortran 中定义了边界条件(通过 mfix.dat)。由于这些可能需要用于构建 EB 墙,mfix::make_eb_geometry 也会调用 mfix_set_bc_type

每个级别的网格是在 mfix::Init 中通过调用从 amrex::AmrCore 继承的初始化函数构建的。

// 这告诉 AmrMesh 类在创建初始网格层次结构时不进行迭代
SetIterateToFalse();

// 这告诉 Cluster 例程使用新的分割例程,如果它们不能提高效率,则拒绝分割
SetUseNewChop();

// 这构建了新的网格
InitFromScratch(0.);

水平集函数

MFIX-Exa 使用水平集函数来解决颗粒-壁面碰撞。有关详细信息,请参阅 AMReX 水平集文档。水平集函数存储在节点 Vector<std::unique_ptr<MultiFab>> mfix::level_sets 上。水平集数据始终存储在颗粒网格上。根据输入 amr.max_level 水平集可以处于两种模式之一:

  1. MFIX-Exa 以单级模式运行 (nlev == 1)。然后 mfix::level_sets[0] 将与流体的分辨率相同(除了它存储在颗粒网格上)。即使 nlev == 1,也有第二个级别,level_sets[1]。该级别与 level_sets[0] 相同,但经过 mfix::levelset__refinement 的细化。这样,即使流体定义在相当粗的网格上,水平集也始终具有适当的分辨率来解析 EB 中的结构。

  2. MFIX-Exa 以多级模式运行 (nlev > 1)。参数 mfix::levelset__refinement 被忽略。mfix::level_sets 然后遵循 MFIX-Exa 的其余部分,即它在所有级别的颗粒网格上定义。

水平集在两个地方使用:

  1. 函数 MFIXParticleContainer::EvolveParticles 将水平集插值到每个颗粒的位置,以解决与 EBs 的碰撞。如果 nlev == 1,则使用 level_sets[1] 来演化颗粒位置。否则,每个级别使用 level_sets[lev]

  2. 流体-颗粒耦合有时会依赖于邻居模板,其中一个或多个单元被 EB 覆盖。为了避免不符合边界条件的值,流体速度在这些单元中被重建。该算法依赖于水平集,并在每个级别上使用 level_sets[lev]

涉及水平集的特殊情况

水平集函数由 mfix::fill_eb_levelsets() 函数填充。涉及水平集的两种特殊情况:

  1. 质量流入边界条件没有给出 EB 墙。然而,我们也不希望颗粒从 MI 中掉落,因此在 mfix::fill_eb_levelsets() 函数的最后,我们调用 mfix::intersect_ls_walls()。这会在每个 MI 处执行与表示墙的水平集的交集操作。

  2. 箱体几何和常规几何完全由平面表面组成。因此,水平集不是由 EB 工厂构建的(如所有其他几何的情况)。而是与所有平面表面的交集。这具有正确描述角落的优点。