simpop

普通会员

原创 OpenFOAM 中的 topoSet 及其应用


多相流在线 本期的 OpenFOAM 系列专题文章是「OpenFOAM 中的 topoSet 及其应用」。如您对 OpenFOAM 有更进一步的学习要求,欢迎您参加由我们举办的 “ OpenFOAM 多相流基础课程 ” !开课在即,名额有限,报名请从速,请扫描本文末二维码报名参加。



OpenFOAM 多相流基础培训课程  敬请期待

6月21-23日 上海锦江汤臣洲际酒店 培训会议厅 



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.05 0.4 -1) (2.1 0.85 1); // 一个 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 (
        12750 12751 12752 12753 12754 12755 12756 12757 12758 12759
        );
}
)


同时,在 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 -2 0 0 0 0 0] (5e7 -1000 -1000);
            f   f [0 -1 0 0 0 0 0] (0 0 0);
            coordinateSystem
            {
                type            cartesian;
                origin          (0 0 0);
                coordinateRotation
                {
                    type            axesRotation;
                    e1              (1 0 0);
                    e2              (0 1 0);
                }
            }
        }
    }
}


  • 3.后处理


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


    weightdSum1
    {
        type            surfaceFieldValue;
        libs            ("libfieldFunctionObjects.so");
        log             true;
        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");
        log             true;
        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,这个工具值得大家花点时间去掌握。


-End-



多相流在线 OpenFOAM专题 往期文章:


多相流在线 — 专注于多相流解决方案的技术平台

公众号名称:  多相流在线

微信号: duoxlzx


第2楼 回复于: 9个月前

你好,我想问一下,如果用ICEM画网格,导入OpenFOAM之后,也是用toposet来划分区域?还说可以在ICEM里画好之后再导入?