【发布时间】:2013-01-21 17:26:28
【问题描述】:
两周多来,我一直在努力从我的 fortran 代码中调用用 C 语言编写的 METIS 库之一。而且,不幸的是,没有你的帮助,这似乎不是一个快乐的结局。我发现了一些关于direct calling 和using interface 的帖子。我更喜欢后者,因为我可以监视变量以进行调试。我附上了三个代码。
1。我要使用的c函数
2. fortran接口模块
3. fortran程序
(1)c函数
int METIS_PartMeshNodal(idx_t *ne, idx_t *nn, idx_t *eptr, idx_t *eind,
idx_t *vwgt, idx_t *vsize, idx_t *nparts, real_t *tpwgts,
idx_t *options, idx_t *objval, idx_t *epart, idx_t *npart)
我删除了 c 函数体。没必要了解我的问题
这里,idx_t 是整数,real_t 是单精度或双精度。从 ne 到 options 是输入,最后三个参数是输出。并且 vwgt、vsize、tpwgts 和 options 可以接收 null 作为默认设置的输入 我编写了界面模块像这样使用 c 函数
(2) Fortran 接口模块
已修复!
- 在使用常量下插入use iso_c_bind
- ne、nn 和其他变量使用 integer(c_int) 而不是 integer。
- 删除未使用的模块常量
。
module Calling_METIS
!use constants, only : p2 !this is for double precision
use iso_c_bind !inserted later
implicit none
!integer :: ne, nn !modified
integer(c_int) :: ne, nn
!integer, dimension(:), allocatable :: eptr, eind !modified
integer(c_int), dimension(:), allocatable :: eptr, eind
!integer, dimension(:), allocatable :: vwgt, vsize !modified
type(c_ptr) :: vwgt, vsize
!integer :: nparts !modified
integer(c_int) :: nparts
!real(p2), dimension(:), allocatable :: tpwgts !modified
type(c_ptr) :: tpwgts
!integer, dimension(0:39) :: opts !modified
integer(c_int), dimension(0:39) :: opts
!integer :: objval !modified
integer(c_int) :: objval
!integer, dimension(:), allocatable :: epart, npart !modified
integer(c_int), dimension(:), allocatable :: epart, npart
interface
subroutine METIS_PartMeshNodal( ne, nn, eptr, eind, vwgt, vsize, nparts, tpwgt, &
opts, objval, epart, npart) bind(c)
use intrinsic :: iso_c_binding
!use constants, only : p2
implicit none
integer (c_int), intent(in) :: ne, nn
integer (c_int), dimension(*), intent(in) :: eptr, eind
!integer (c_int), dimension(*), intent(in) :: vwgt, vsize !modified
type(c_ptr), value :: vwgt, vsize
integer (c_int), intent(in) :: nparts
!real(c_double), dimension(*), intent(in) :: tpwgt !modified
type(c_ptr), value :: tpwgt
integer (c_int), dimension(0:39), intent(in) :: opts
integer (c_int), intent(out) :: objval
integer (c_int), dimension(*), intent(out) :: epart
integer (c_int), dimension(*), intent(out) :: npart
end subroutine METIS_PartMeshNodal
end interface
end module
这是我调用该函数的程序代码
(3) Fortran 程序
已修复!
- npart 的分配大小是固定的。不是 ne 而是 nn
- opts(7)=1 被添加以获取 epart、npart 的 Fortran 样式数组(目前无效)
.
program METIS_call_test
!some 'use' statments
use Calling_METIS
use iso_c_binging !added
implicit none
! Local variable
integer :: iC
character(80) :: grid_file !grid_file
grid_file = 'test.grid'
! (1) Read grid files
call read_grid(grid_file)
! (2) Construction Input Data for calling METIS Function
! # of cells, vertices
ne = ncells
nn = nvtxs
! eptr, eind allocation
allocate(eptr(0:ne), eind(0:3*ntria + 4*nquad - 1))
! eptr and eind building
eptr(0) = 0
do iC=1, ncells
eptr(iC) = eptr(iC-1) + cell(iC)%nvtxs
eind(eptr(iC-1):eptr(iC)-1) = cell(iC)%vtx
end do
! epart, npart building
!allocate(epart(ne), npart(ne))
allocate(epart(ne), npart(nn)) ! modified
! # of partition setting
nparts = 2
vwgt = c_null_ptr !added
vsize = c_null_ptr !added
tpwgt = c_null_ptr !added
! (3) Call METIS_PartMeshNodal
call METIS_SetDefaultOptions(opts)
opts(7) = 1 !Added. For fortran style output array epart, npart.
call METIS_PartMeshNodal(ne, nn, eptr, eind, vwgt, vsize, nparts, tpwgt, &
opts, objval, epart, npart)
!call METIS_PartMeshNodal(ne, nn, eptr, eind, null(), null(), nparts, null(), &
! opts, objval, epart, npart) !wrong...
end program
但问题是我收到如下错误消息,尽管我为 tpwgt 设置了 null。
输入错误:约束 0 的 tpwgts 的 0.000000 总和不正确。
并且这条消息在下面的代码中处理。
for (i=0; i<ctrl->ncon; i++) {
sum = rsum(ctrl->nparts, ctrl->tpwgts+i, ctrl->ncon);
if (sum < 0.99 || sum > 1.01) {
IFSET(dbglvl, METIS_DBG_INFO,
printf("Input Error: Incorrect sum of %"PRREAL" for
tpwgts for constraint %"PRIDX".\n", sum, i));
return 0;
}
}
无论如何,为了看看如果我为 tpwgts 放入一个数组而不是 null 会得到什么,tpwgts(:) = 1.0/nparts,这使得 tpwgts 的总和等于 1.0。但我得到了与 1.75 相同的信息。
这是我的问题
1. 我是否使用 null() 正确传递参数?
2. 我必须将所有参数的指针传递给 c 函数吗?那怎么办?
3. 将整数放入 opts(0:39) 是否足够使用?例如,在没有“接口模块”的post 中,使用了像 options(3)=1 这样的简单代码。但在 c 代码中,options 有 16 个命名变量,如 options[METIS_OPTION_NUMBERING]、options[METIS_OPTION_UFACTOR]。我认为设置选项是必要的,但我不知道。
4. METIS有fortran的例子吗?
任何类型的提示/建议都会对我有很大帮助。谢谢你。
结论
我遇到的问题是 c 函数无法识别 fortran 代码中的空指针。
接口模块中有一些变量的错误声明(参见“固定”和 cmets)
看起来代码工作正常。但是 fortran 样式输出的 option(7) = 1 不起作用,现在我正在研究它。
【问题讨论】:
-
乍一看,我注意到 C 函数返回一个
int,但您将METIS_PartMeshNodal作为子例程进行接口,它没有返回参数并且类似于 C @987654332 @ 功能。你的界面不应该是integer(c_int) function吗? -
另一方面,在我链接的源代码中,它确实是一个
void函数,但具有不同的签名。最好的办法是看到一些实际工作的 C 代码调用该例程。 -
到西格玛。我不确定确切的原因。但参考this,c 函数被定义为 c 绑定中的子例程。 致 Vladimir F 它看起来像旧版本。我想我必须听从你的建议。但我此时只是简单地链接了c库。我不知道如何才能看到 C 代码发生了什么,但我会找到方法的。
-
到 sigma 我把子程序改成函数并调用函数。但是结果是一样的(访问冲突)
标签: fortran fortran-iso-c-binding metis