生成元素边数的网格化选项(tetgen-triangle)

计算科学 有限元 正则 网格生成
2021-12-06 21:23:56

我用 fortran 90 写了一个有限元代码。

这段代码真的很快,除了网格划分过程。

我分别使用三角形tetgen进行 2D 和 3D 网格划分,所以这个过程当然很快。

例如,对于 2D 中的单位正方形 [0,1]x[0,1],我有一个文件,其中包含其节点的坐标(例如,具有 5 个节点的网格):

1   0.0 0.0  # coordinates of node 1
2   1.0 0.0  # coordinates of node 2
3   1.0 1.0  # coordinates of node 3
4   0.0 1.0  # coordinates of node 4
5   0.5 0.5  # coordinates of node 5

称为coordinate.dat,它有 4 个元素(三角形),节点称为element.dat

1   1 5 4  # vertices of triangle 1
2   1 2 5  # vertices of triangle 2
3   2 3 5  # vertices of triangle 3
4   5 2 4  # vertices of triangle 4

我还有一个文件,其中每一行i是其初始的最终节点的编号,称为edge.dat

1   1 2  # initial and final node of edge 1
2   2 3  # initial and final node of edge 2
3   3 4  # initial and final node of edge 3
4   4 1  # initial and final node of edge 4
5   1 5  # initial and final node of edge 5
6   5 2  # initial and final node of edge 6
7   2 5  # initial and final node of edge 7
8   5 4  # initial and final node of edge 8

使用这些文件,我需要生成以下信息:

(1) 给定一个元素(三角形或四面体),我需要知道它的边数(分别为边和面)。例如,我需要生成以下结构或文件,称为struct1.dat

1   5 8 4  # triangle 1 has the edges number 5, 8 and 4
2   1 6 5  # triangle 2 has the edges number 1, 6 and 5
3   6 2 7  # triangle 2 has the edges number 6, 2 and 7
4   7 3 8  # triangle 4 has the edges number 7, 3 and 8

(2) 此外,给定一条边(边或面),我需要知道该边共享的 2 个元素(如果边在边界上,则只有一个)的元素编号。例如,我需要生成以下结构(或文件),称为struct2.dat

1   2 0  # edge number 1 is only on element 2
2   3 0  # edge number 2 is only on element 3
3   4 0  # edge number 3 is only on element 4
4   1 0  # edge number 4 is only on element 1
5   1 2  # edge number 5 is sharing by elements 1 and 2
6   3 2  # edge number 6 is sharing by elements 3 and 2
7   4 3  # edge number 7 is sharing by elements 4 and 3
8   1 4  # edge number 8 is sharing by elements 1 and 4

对于这两种结构struct1.datstruct2.dat,我的代码非常慢,因为我使用了带有很多循环的蛮力方法。

我正在寻找一种为此优化的算法(一篇论文,或者更好的:fortran 中的一个子程序可供下载)?我想继续使用三角形和 tetgen,但我愿意听取其他选择。

1个回答

我已经实现了一种可以很好地重建表面网格中的边缘信息(或体积网格中的面信息)的方法,但我正在使用 C++ 工作。我将尝试用可以(希望)翻译成 Fortran 的“抽象算法语言”来解释这一点:

假设我有一个由 nt 个三角形组成的三角形网格。

步骤 1:我首先构造一个由 3*nt 个“边记录”组成的数组,每个“边记录”具有以下字段:(i,j,t) 并编码从给定三角形 (t) 看到的边 (i,j) )。我还需要确保 (i < j)。

(注意:在 Fortran 中,这可以替换为三个大小为 3*nt 的数组,一个数组 I[],一个数组 J[] 和一个数组 T[],但可能 Fortran90 有“结构”/“记录”)

构建结构:

E : array of 3*nt "edge records"
e = 1
For t = 1 to nt       
  get i,j,k the vertices indices of triangle t        
  E[e].i = min(i,j); E[e].j = max(i,j); E[e].t = t; e = e + 1
  E[e].i = min(j,k); E[e].j = max(j,k); E[e].t = t; e = e + 1
  E[e].i = min(k,l); E[e].j = max(k,l); E[e].t = t; e = e + 1

步骤2:按字典顺序对记录进行排序,即给定两条记录E[e1]和E[e2],如果E[e1].i < E[e2],则E[e1]应该在E[e2]之前。 i OR (E[e1].i = E[e1].i 和 E[e1].j < E[e2].j)

(在 Fortran 中,我不确定如何实现这一点,您需要找到一个通用的排序例程,或者如果您有三个单独的 I[]、J[]、T[],则可能需要自己实现它数组。如果 Fortran90 有“结构/记录”,也许可以从 Fortran 调用 C 运行时的 sort() 函数)。在最坏的情况下,可以将数组 E 保存在一个文件中,在其上调用系统排序程序并将其读回。

第 3 步:一旦对“边记录”数组进行排序,从两个不同三角形看到的“相同边”将由两个连续的记录表示。然后,您可以通过迭代生成唯一的边缘索引,并在每次遇到不同的边缘时递增当前边缘索引。有两个与它们相关的三角形的边将由两个“边记录”(i,j,t1)、(i,j,t2) 的序列表示。然后很容易生成数组,为每个三角形提供其三个边的索引,并为每个边提供与其相邻的(最多两个)三角形的索引。它还允许检测无效网格,超过两个三角形入射到同一边缘。

还有一种替代方法,它为每个顶点提供与其相关的三角形列表。它是通过“链接”三角形的“角”来完成的(使用大小为 3*nt 的数组)。

我的“geogram”编程库中的 C++ 实现:http: //alice.loria.fr/software/geogram/doc/html/namespaceGEO.html#af10149ff831242b94b​​f3c92ac233111a

下载:https ://gforge.inria.fr/frs/?group_id=5833