首页/文章/ 详情

OpenFOAM 中的 topoSet 及其应用

10月前浏览2018

OpenFOAM 中的 topoSet 及其应用

CFD 模拟需要的前处理和后处理,通过需要涉及到对某些指定区域进行操作。比如,在指定区域设置初始浓度,在指定区域加入一个源项,给指定区域加上一个旋转速度,计算指定区域内的统计值,计算某个截面上的通量,甚至对某些特定的网格使用特殊的离散格式等等。

OpenFOAM 中有一个专门的工具来帮助用户管理 “指定区域”,叫 topoSettopoSet 含义是 topology set(集 合),该工具作用是将一些点、面、或者体网格提取出来存放在指定名字的 set 里,用以辅助前后处理。topoSet 可以生成的“集 合”包括 pointSet,faceSet,cellSet,pointZone,faceZone,cellZone。set 和 zone 在概念上基本上是一致的,都是包含一系列点(或者面,或者体)的集 合,只是由于历史原因,目前 set 和 zone 并存于 OpenFOAM 中,有的前后处理工具可能同时支持使用 set 或 zone,但也有的只支持其中一种。下面来看看 topoSet 工具的使用方法,以及一些应用的例子。

topoSet使用

topoSet 的基本使用分两步,第一步是编写一个 topoSetDict 放在算例的 system 目录下,其中包含需要提取的 set 的信息,然后运行 topoSet 命令,正常的话,将在 constant/polyMesh 目录下生成需要的 set 或者 zone 文件。下面是一个 topoSetDict 的示例:

actions
(
    {
        name    porousCells; // 需要生成的集 合的名字
type    cellSet;   // 集 合类型,pointSet, pointZoneSet,faceSet, faceZoneSet, pointSet, pointZoneSet, cellSet, cellZoneSet,
        action  new;      // 操作类型,new, add, delete, subset(交集) 
        source  boxToCell; // 操作对象,boxToCell 含义是将某个box内的所有cell作为本次 action 的操作对象
        sourceInfo  // 操作对象的信息,这个取决于上一条的设置
        {
            box (2.050.4-1) (2.10.851); // 一个 box 的左下和右上角点的坐标
        }
    }
    {
        name    porousZone;  // 需要生成的集 合的名字
type    cellZoneSet; // 表示需要生成一个cellZone
        action  new;  // 新建
        source  setToCellZone; // 表示是要将某个 cellSet 中的所有网格作为操作对象
        sourceInfo
        {
            set porousCells; // 指定这个将集 合作的 cellSet 的名字
        }
    }
);

所有的操作,都囊括在 actions (  ); 这一层括号里,里面的每一个被 { } 包围起来的便是一个 action。每个 action 需要包含的基本元素的含义见上述注释。运行 topoSet 命令时,actions 里面的每一个 action 将按顺序执行。注释中已将 type 和 action 的种类都列出来了,source 的种类比较多,这里不便一一列出,OpenFOAM 提供了一个示例 topoSetDict,位于 applications/utilities/mesh/manipulation/topoSet/topoSetDict,里面列出了所有支持的 source 类型,供用户参考。此外,还有一种方式可以获取到所有支持的 source 类型:在编写 topoSetDict 时,source 字段后面随便填写一串字符(比如 banana),然后运行 topoSet 命令,这时候,命令会报错,因为随便填入的字符串不是合法的 source,但同时,topoSet 命令也会将所有支持的 source 类型输出到屏幕上,示例如下:

--> FOAM FATAL ERROR: 
Unknown topoSetSource type banana
Valid topoSetSource types : 
43
(
boundaryToFace
boxToCell
boxToFace
boxToPoint
cellToCell
cellToFace
cellToPoint
cylinderAnnulusToCell
cylinderToCell
faceToCell
faceToFace
faceToPoint
......

这种小技巧在 OpenFOAM 中几乎所有的 dict 中都可以使用,以下简称为 “banana 方法”。

对于上述示例中的 topoSetDict , topoSet 命令运行结束后,将在 constant/polyMesh 目录下生成一个 cellZones 文件,里面存放的是 cellZone 信息,

1// 表示 cellZone 的数量
(
porousZone // 这是上述 topoSetDict 中指定的 cellZone 的名字 
{
    type cellZone; 
    cellLabels      List<label>  
// 下面的是网格信息,10表示当前 cellZone 包含的网格数目,括号里的10个整数是网格编号(是的,假如你知道你需要提取的网格编号,你也可以手动填入这些数字)
10 (
12750127511275212753127541275512756127571275812759
        );
}
)

同时,在 constant/polyMesh 会生成一个目录 sets ,里面存放的是 set 的信息,对于上述示例,sets 目录项将会有一个 porousCells 文件,里面存放的是名字为 porousCells 这个 cellSet 的信息(格式相信一目了然,不需要额外解释)

FoamFile
{
    version     2.0;
    format      ascii;
    class       cellSet;
    location    "constant/polyMesh/sets";
    object      porousCells;
}
// * ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** * * //
10
(
12750 
12751 
12752 
12753 
12754 
12755 
12756 
12757 
12758 
12759 
)

接下来举一些使用 set 或者 zone 的前后处理示例。

应用举例

  • 1.setFields
    setFields 的作用是设置非均匀初始场,可以在一个指定区域内对某个场设置指定的初始值。典型的 setFieldsDict 如下:

defaultFieldValues
(
    volScalarFieldValue alpha.water 0.0
);
regions
(
    boxToCell
    {
        box (0 0 -1) (0.1461 0.292 1);
        fieldValues
        (
            volScalarFieldValue alpha.water 1.0
        );
    }
);

需要注意的是,这里的 boxToCell 不是唯一选项,用户可以使用“banana 方法”来获取所有可选项。其中就包含 cellToCell,这个选项的作用是让 setFields 将某个 cellSet 中的所有网格的初始值设置为指定值,假设事先用 topoSet 将需要的网格提取到了 waterCells 这个 cellSet中,那么 regions 可以按如下方式写:

regions
(
    cellToCell
    {
set  waterCells;
        fieldValues
        (
            volScalarFieldValue alpha.water $speValue
        );
    }
);
  • 2.源项
    OpenFOAM 中设置源项需要使用 fvOptions,其中指定区域的方式也通常是 cellSet 或者 cellZone,下面以设置多孔介质区域的源相为例:

porosity1
{
type            explicitPorositySource;
    active          true;
    explicitPorositySourceCoeffs
    {
type            DarcyForchheimer;
        selectionMode   cellZone; // 选择 cellZone 作为多孔介质区域
        cellZone        porousZone; // cellZone 的名字
        DarcyForchheimerCoeffs
        {
            d   d [0-200000] (5e7-1000-1000);
            f   f [0-100000] (000);
            coordinateSystem
            {
type            cartesian;
                origin          (000);
                coordinateRotation
                {
type            axesRotation;
                    e1              (100);
                    e2              (010);
                }
            }
        }
    }
}
  • 3.后处理

    OpenFOAM 中后处理建议的方式是在设置算例时就考虑好需要做哪些后处理,然后,在 controlDict 的 functions 部分加上需要的 functionObject 来实现一边计算一边后处理。这样可以减少需要保存的计算数据,这在算例很大(比如数千万网格)时很有意义(不仅是节省硬盘空间,也节省时间,因为往硬盘上频繁写入大量数据是非常耗时的)。这里介绍 surfaceFieldValue和 volFieldValue 两个 functionObject,主要关注其如何使用 set 或者 zone 来实现后处理。
    比如,需要统计某些面上的某个场相对某相体积分率的加权和,那么可以用如下方式编写一段添加到 controlDict中的 functions 部分:

    weightdSum1
    {
        type            surfaceFieldValue;
        libs            ("libfieldFunctionObjects.so");
logtrue;
        writeControl    writeTime;
        writeFields     true;
        surfaceFormat   none;
        regionType      faceZone; // 选择一个 faceZone 中的所有面网格作为操作对象
        name            f0;  // faceZone 的名字
        operation       sum;
        weightField     alpha.gas;
        fields
        (
            phi
            U
        );
    }

volFieldValue 也是类似,只不过它处理的是体网格相关的,例如

    volWeightedAverage1
    {
        type            volFieldValue;
        libs            ("libfieldFunctionObjects.so");
logtrue;
        writeControl    writeTime;
        writeFields     true;
        regionType      cellZone; // 选择一个 cellZone 中的所有体网格作为操作对象
        name            c0;  // cellZone 的名字
        operation       volAverage;
        weightField     alpha.gas;
        fields
        (
            U
        );
    }

高级应用

如果 OpenFOAM 中提供的工具还满足不了需求,你需要在程序中来读取某些 set 或者 zone 进来,然后对其中的面或者网格进行特殊操作,这也是可以做到的,这里提供读取 cellZone 和 cellSet 的示例代码如下:

  • 读取 cellZone

    word zoneName = "zone1"// 需要读取的 cellZone 的名字
    label zoneID = mesh.cellZones().findZoneID(zoneName);
if (zoneID == -1)
    {
        FatalErrorIn("cellZones") << "Cannot find cellZone " << zoneName << exit(FatalError);
    }
    labelList cells = mesh.cellZones()[zoneID]; // 获取到 zone1 中包含的所有的网格 id 列表

获取到网格 id 列表,接下来怎么玩就随你了。读取 faceZone 或者 pointZone,方法也是类似的。

  • 读取 cellSet 和 faceSet
    读取 set 的方法略微麻烦一些

#include"faceSet.H"
#include"cellSet.H"
// 读取 faceSet 
word faceSetName_("faceSet1");
faceSet face1
(
        mesh_,
        faceSetName_,
        IOobject::READ_IF_PRESENT,
        IOobject::NO_WRITE
    )
;
    forAllConstIter(faceSet ,meshQualityFaces, faceI) // 遍历 faceSet
    {
        Info << faceI.key() << endl// faceI.key() 返回的就是 face 的编号
    }
// 读取 cellSet 
    word cellSetName_ = "cellSet1";
cellSet cellset1
(
        mesh,
        cellSetName_,
        IOobject::READ_IF_PRESENT,
        IOobject::NO_WRITE
    )
;
    forAllConstIter(cellSet ,cellset1, cellI) // 遍历 cellSet 
    {
        Info << cellI.key() << endl;  // cellI.key() 返回的就是 cell 的编号
    }

最后想说的是,当你的需求中涉及对一些指定的区域进行操作时,几乎肯定会用到 topoSet,这个工具值得大家花点时间去掌握。

来源:多相流在线
SystemOpenFOAM多相流多孔介质湍流控制
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2023-06-22
最近编辑:10月前
积鼎科技
联系我们13162025768
获赞 97粉丝 81文章 246课程 0
点赞
收藏
未登录
还没有评论

课程
培训
服务
行家

VIP会员 学习 福利任务 兑换礼品
下载APP
联系我们
帮助与反馈