2

我正在尝试使用METIS库进行网格划分,作为我为有限元计算编写的 Fortran 程序的一部分。METIS 是用 C 语言编写的,但它应该可以在 Fortran 90 上正常工作。但我不断遇到段错误。

一个潜在的问题是我给出了一些空指针的参数。其他一些人在从 fortran 调用 C 函数以识别空指针对象时遇到了麻烦。这是在这里解决的,我认为这不是我遇到的问题。

我认为问题在于让 METIS 更改起始数组索引;在 C 中它是 0,在 Fortran 中它是 1。有一个数组传递给每个函数,如果你想要 Fortran 约定options,它应该有一个METIS_OPTION_NUMBERING你可以更改的字段。1不这样做会导致 C 程序尝试访问索引 0,从而给您 seg 错误。

edunlop1在这里的帖子建议我只是创建一个数组options,并且与 METIS 达成的一些约定确定该数组的哪个元素应该设置为 1,以便对所有内容重新编号。但这取决于您使用的例程,数组长度也会发生变化。

无论如何,这是我的代码:

integer :: ndomains,ncommon,objval
integer :: options(0:40)
integer, dimension(:), allocatable :: eptr,eind
integer, pointer :: vwgt(:)=>null(), vsize(:)=>null(), opts(:)=>null()
real(kind=8), pointer :: tpwgts(:)=>null()

! Read in the mesh data
call getarg(1,meshname)
call readmesh(meshname)
allocate(color(ne),domain(nn))
allocate(eind(3*ne),eptr(ne+1))
do n=1,ne
    eptr(n) = 1+3*(n-1)
    do i=1,3
        eind( eptr(n)+i-1 ) = elem(i,n)
    enddo
enddo

! Try and call METIS
ncommon = 2
ndomains = 2
options = 0
options(0) = 1
options(8) = 1
call METIS_PartMeshDual(ne,nn,eptr,eind,vwgt,vsize, &
    & ncommon,ndomains,tpwgts,options,objval,color,domain)

METIS 中用于更改编号的相关代码位于文件 libmetis/meshpart.c 中:

/* renumber the mesh */
if (options && options[METIS_OPTION_NUMBERING] == 1) {
  ChangeMesh2CNumbering(*ne, eptr, eind);
  renumber = 1;
}

有什么想法吗?如果有帮助,我可以发布 Valgrind 输出。

4

3 回答 3

3

这可能没有什么,但也许问题第二段中的链接帖子仍然是相关的。

Fortran 中的 POINTER 和 C 中的指针不是完全相同的概念,尤其是当 Fortran 指针指向数组时。在 Fortran 中实现指向数组的指针需要存储超出 C 指针(只是数据的地址)中存储的附加信息(数组边界或等效信息)。

(从技术上讲,除非 METIS_PartMeshDual 的相关虚拟参数定义具有可选或指针属性(如果它是被调用的 C 函数并且语言标准为 <= F2008,则不可能),那么在 Fortran 调用中对分离指针的引用是非法。再次 - 实现取决于会发生什么 - 我可以想象它会在哪里工作和在哪里不会工作的实施选项。)

请注意,在您链接到空指针声明的帖子中,作为解决方案的一部分从数组更改为标量(列表中的第一个回复 - 检查帖子的时间)。在作为问题的一部分发布的示例代码中,“null”事物的声明仍然显示数组。我怀疑声明中的更改会更改调用 C api 的“设置”和/或解离指针对于您的编译器的外观。

这些天来,当从 Fortran 调用 C API 时,我更喜欢(在可能的情况下)使用 Fortran 2003 的 C 互操作性特性(BIND(C) 和朋友)为 C API 编写接口块。这更加健壮,并且避免了这种依赖于平台的问题。它确实需要一次性的前期工作以及支持 F2003 的这一方面的 Fortran 编译器。为他们的 Fortran 用户提供这样的接口块而麻烦的库供应商从我那里得到了一个很大的选择和很多好意的想法。

于 2012-12-31T02:14:05.403 回答
2

Fortran 数组大小比 C 更灵活。您可以将 Fortran 数组设为 0 索引,或任何您想要的起始索引。

real, dimension (0:N-1) :: array
real, dimension (:), allocatable :: group
allocate (group (0:N-1))

如果对起始索引的某种分歧是问题所在,那么这可能会有所帮助。

于 2012-12-29T07:58:30.240 回答
2

采用:

vwgt=>null() 

代替

vwgt(:)=>null()

对于所有空值(即,vwgt、vsize、opts、tpwgts 等)。问题是 vwgt(:) 并没有真正定义,而不仅仅是 vwgt 或 vwgt(1)。如果仍然有问题,请使用调试器检查所有值。

我是第 2 段中提到的线程中的 OP。不幸的是,最终解决方案位于回复的顶部(请参阅时间戳)。希望有帮助。

于 2013-01-02T03:25:32.223 回答