Answers:
您显示的结构是常见选择,等效于以CSR矩阵格式存储单元格面邻接关系,并将边界重影单元格放在特殊位置。但是,请注意,FV方法也可以公式化为全部或几乎全部遍历整个面孔,其中每个面孔仅被访问一次(从两侧重建为面孔质心/正交点,解决黎曼问题,将通量重新分配回单元格上的残差中) )。您可以通过使用基于单元格的遍历并跳过稀疏矩阵中“对角线”下方的任何两个单元格来“伪造”它,但是一种流行的替代方法是存储(leftCell, rightCell) = support(face)
,在这种情况下,面孔将成为一流的实体。这很有用,因为您通常需要一个位置来存储面部正交点(质心),面部法线。您还可以将重建部分(如最小二乘)放入基于面部的数据结构中。人脸遍历似乎是矢量化友好的,因为所有大小都是规则的,但是另一方面,输出重叠,因此您需要组织遍历以避免将其放入内部循环。使用这种更加面向面部的数据结构,自然可以对面部编号进行排序,以便可以使用连续的面部遍历来应用每种边界条件类型(也对矢量化友好)。
如果选择此数据结构,请记住对面进行排序,以便遍历尽可能重用高速缓存中的单元格数据。请参阅任何PETSc-FUN3D论文,以进行人脸排序和相关优化的性能分析。
我知道这个问题已经回答了,但这是在OpenFOAM C ++库中实现的类似的基于单面的循环存储:
每个单元在cellList中都有一个索引(ID)。为所有面孔定义了两个列表:“面孔内部所有者”和“面孔邻居”。两个面列表的长度对应于网格中内部面的数量。面部所有者将是cellList中ID较低的单元格(与面部邻居相反)。边界面是最后写入的,它们具有面向外的法线(来自求解域),当然只有一个所有者单元格。脸部区域法线的方向使其从所有者单元格向外看向相邻单元格。
这对于例如磁通计算非常有效。每个通量对通量进行一次评估,并将其添加到所有者单元格的总面部总数中,并从相邻单元格中扣除(相加/扣除额基于面部区域法线的方向确定)。边界面被排序并存储在脸部列表的底部,从而允许将边界条件定义为脸部列表的切片(边界标签的开始标签,结束标签),从而简化了边界条件的实现因为它依赖于内表面操作提供的解决方案,因此可以提高边界条件更新过程的效率。
由于边界面被聚集为补丁,因此为耦合(处理器)补丁定义了进程间通信并进行了预定义。这意味着,一旦边界网格上出现循环,顶层访问功能就会调用包装的MPI调用,从而使此类代码“自动”并行化(如果它依赖于上述基于面部的连接性)。