这篇博文总结之前几篇博文,讲一下我对OpenFOAM-v2006版本挖洞机制的理解,下面是我归纳的结构图(如有错误请不吝赐教):
从结构来看,在solver运行mesh.update()之后,重叠网格的update()就会被调用。它会先读取用户的设置,然后提取当前网格,包括背景网格和上层网格,以及它们各自的边界条件信息。程序会先运行markBoundaries()函数,把每层网格的每个边界元(faceCells)的边界条件进行识别。这里会分3种情况:patch、wall等一般的边界条件会被识别为PATCH;empty、cyclic等比较特殊的约束性条件会被识别为OTHER,这部分一般不参与重叠网格的计算;overset的边界条件(用户在设置算例时设置好的)会别识别为OVERSET。其他内部面的体元会被标识为OTHER。定义好后的patchType会被用于markPatchesAsHole中。
在markPatchesAsHole()里,会对每一对网格进行洞单元的识别。为什么说每一对呢?当重叠网格只有上下两层时,就只需要对这一对进行识别就行了。但如果运动部件不只一个(如三段翼、多体运动),那就会有不只两层的网格,这时候需要一一进行洞单元的识别。如上图所示,这里有两层for循环,就是遍历每一对的匹配,且不会重复。假如背景网格为target(tgt),且以圆柱那一层网格为source(src),那么在markPatchesAsHole()中,每一个背景网格中的单元都会和圆柱层网格进行比较,然后确定是否为HOLE单元。
在这里,cBb即为需要确定的单元,它对应celli这个元,这个元的检索范围(maxId和minId)会传递到overlaps()里,唤起圆柱层对应范围的单元,如果有其中一个单元是被标记为PATCH的话,那么这个celli对应的体单元就会被标记为HOLE。
如上左图所示,背景网格单元a唤起的圆柱层网格有1,2,4,5,6…,而其中1和6都是PATCH的体元,那么这个单元a就会别识别为HOLE(红色),而体元b因为其唤起的圆柱层网格不包含有PATCH的体元,所以这个单元b就不会被标记为HOLE了。
在程序上是如何实现“唤起”的功能呢?难道要对每一个圆柱层的体元都要作一次坐标的判定吗?那就会涉及到很多的问题了,最严重的莫过于判断繁琐,增加处理时间,以及多判漏判等。代码是通过把这一部分圆柱层网格(一般并行后会像上图那样分成几个扇形)先分一个boundBox(上图蓝色方框),这个boundBox从三个方向被分成nDivs份,并为每一个圆柱层网格的体元分配了对应的三维的位置。这个三维位置与mesh的数组下标是不一样的,由特别定义的index、index3函数来索引。在唤起时,程序会先计算背景网格的一个体元(target框)在这个大框(source框)下的相对位置(maxId,minId),然后调取这个范围里面的圆柱层单元(label i1 = index(nDivs, labelVector(i, j, k));)然后分别判断是否有某一个圆柱层单元是PATCH的边界单元(if (vals[i1] == patchCellType::PATCH))。这样,以boundBox为中介,来判定背景网格的单元是否与壁面相接触,首先根据该单元的范围来调取对应的圆柱层单元,节省了很多比较坐标位置的处理的时间。试想,如果每一个背景网格的单元都和圆柱层的每一个单元进行坐标的判断,那么可想而知会浪费多少时间。
这样,OpenFOAM-v2006版的重叠网格挖洞的机制就算是弄清楚了。它和extend4.0版本是完全不一样的,也许是因为贡献者不同吧?相比较之下,v2006版本更加干净整洁,但相应的,功能可调性没有extend的那么多。接下来尝试修改一下v2006版的挖洞机制,希望其能挖洞挖到剩下边缘几层。