blockMesh 是 OpenFOAM 最基础的网格划分工具,适合处理简单的体型。但是 blockMeshDict 文件往往被点坐标占据大量篇幅,这些数字毫无逻辑。如果点坐标很多的话,很难将坐标值和点序号对应起来,这样后面 blocks、edges 和 faces 的定义根本看不明白。相信很多初学者都像我一样有类似的体验。
这个文件读起来困难,写起来就更困难了。需要输入大量坐标值不说,定义 blocks 的时候还容易看错点序号。如果要修改体型,一个数字一个数字改起来更是痛苦。
笔者曾考虑用脚本语言生成 blockMeshDict,又觉得这种实现方法不够优雅,所以先试着搜索了一下,发现了一个优雅的做法,Writing a blockMeshDict file with variables。我总结一下。
先看一个参数化的例子,这个 blockMeshDict 文件定义了一个横截面为扇形的柱体。
gedit $FOAM_TUTORIALS/incompressible/simpleFoam/pipeCyclic/system/blockMeshDict
Code language: PHP (php)
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
convertToMeters 1;
//- Half angle of wedge in degrees
halfAngle 45.0;
//- Radius of pipe [m]
radius 0.5;
radHalfAngle #calc "degToRad($halfAngle)";
y #calc "$radius*sin($radHalfAngle)";
minY #calc "-1.0*$y";
z #calc "$radius*cos($radHalfAngle)";
minZ #calc "-1.0*$z";
vertices
(
(0.0 0.0 0) //0
(10 0.0 0)
(10 0.0 0) //2
(0.0 0.0 0)
(0.0 $minY $z) //4
(10 $minY $z)
(10 $y $z) //6
(0.0 $y $z)
);
Code language: PHP (php)
可以看到定义点坐标时,使用了 minY、y、z 等变量,这些变量是用半径 radius 和半顶角 radHalfAngle 计算出来的。这个例子中,柱体的长度是10,这个数字没有用参数替代,如果把坐标里的数字都用变量名替代,代码的可读性还可以进一步提高。
上例中用到的 #calc 指令支持 C++ 标准函数。如果计算很复杂,还可以使用 #codeStream 指令,详见OpenFOAM User Guide: 4.2 Basic input/output file format。
最后请教读者们一个问题,类似 #calc 这种用法是 C++ 的什么特性,和 #include 一样是预处理指令吗?如果想了解更多相关内容,应该用什么关键词搜索呢?