用 C++ 编程有限元方法

计算科学 有限元 C++ 软件 数据结构
2021-11-28 09:29:04

我正在尝试为 C++ 中的有限元方法开发一个库,为此我正在研究网格的数据结构。根据我对 fenics 和 deal.ii 的阅读,一般的理解似乎是一个基本的网格类应该具有以下成员:

  1. 单元格、面、顶点。
  2. 连通性关系(给定单元的邻居是什么,单元之间的共同面,给定单元的顶点,单元的边界指示符,面和顶点)
  3. 单元迭代器

这些是我的问题:

  1. 存储网格单元的最佳方法是什么。我认为一个 STL 向量就足够了。这是流行的选择吗?我还读过链接列表已用于单元格,但在这种情况下我看不到链接列表相对于向量的优势。
  2. 同样,对于连接关系,STL 映射对我来说似乎是最好的方法。对此有何评论?
  3. 相同的数据结构是否适用于三角形和四边形网格。我认为应该,但我不确定我是否在这里遗漏了任何基本的东西?
  4. 是否还有更多的连接关系需要牢记?
  5. 对有限元库进行编程有什么好的参考吗?

谢谢你。

2个回答

fenics 的作者之一,A. Logg,写了一篇关于存储网格的数据结构的非常好的论文。该论文是 A. Logg (2009)。计算网格的有效表示 http://arxiv.org/abs/1205.3081

事实上,它总是在存储所有拓扑信息(节点周围的节点、节点周围的面等)或必须在使用它们之前重新计算它们之间进行权衡。如果您存储它们,那么您最终可能会存储大量数据,如果您使用迭代器重新计算它们将花费一些(太多)时间。根据算法(通常对于 FEM,对于线性元素,您只需要多面体节点来组装局部刚度矩阵),您可能需要使用一些特定的遍历,然后您可以动态生成所需的内容。

无论如何,在 fenics 中提出的解决方案基于许多整数句柄数组,并且可能是最接近最有效的方法(在内存和访问方面)。

在 deal.II 中,我们基本上只使用向量。映射太慢并且数据分散在内存中,所以如果键是整数并且在给定范围内,我们通常不使用它们。例如,对于单元格之间的连通性,您可以使用数组(STL 向量)在其中存储相邻索引,以便相邻索引4i4i+3对应单元格i(在 2d 中,因为每个单元有 4 个邻居)。这样您就可以直接进行数组查找,而不是在 STL 映射中遍历树。

您可能已经意识到这一点,但是我们已经对我们在这个库中使用的数据结构进行了大量研究,并且我们使用的方案导致缓存未命中的数量非常少。如果您想提高效率,您将花费大量时间提出我们使用的相同类型的解决方案。