在 fortran 程序中调用 METIS API(用 C 语言编写) [英] Calling METIS API(wrtten in C language) in fortran program

查看:15
本文介绍了在 fortran 程序中调用 METIS API(用 C 语言编写)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

两周多来,我一直在努力给其中一个 METIS 从我的 fortran 代码中用 C 语言编写的库.而且,不幸的是,没有你的帮助,这似乎不是一个快乐的结局.我发现了一些关于 直接调用使用界面.我更喜欢后者,因为我可以监视变量以进行调试.我附上了三个代码.

1.我要使用的c函数
2. fortran接口模块
3. fortran程序

Over 2 weeks, I've struggled to call one of the METIS library written in C from my fortran code. And, unfortunately, It doesn't seem to be a HAPPY END without your help. I found some posts about direct calling and using interface. I prefer the latter because I could monitor the variables for debugging. There are three codes I attached.

1. c function I'd like to use
2. fortran interface module
3. fortran program

(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 是单精度或双精度.从 neoptions 是输入,最后三个参数是输出.并且 vwgtvsizetpwgtsoptions 可以接收 null 作为默认设置的输入 我编写了界面模块像这样使用 c 函数

Here, idx_t is integer and real_t is single or double precision. From ne to options are input and last three arguments are output. And vwgt, vsize, tpwgts and options can receive null as an input for default setting I wrote the interface module for using c function like this

(2) Fortran 接口模块

(2) Fortran interface module

  1. 使用常量
  2. 下插入use iso_c_bind
  3. nenn 和其他变量使用 integer(c_int) 而不是 integer.
  4. 删除未使用的模块常量
  1. Insert use iso_c_bind under use constants
  2. Use integer(c_int) instead of integer for ne, nn and other variables.
  3. Remove unused module constants

.

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

这是我调用该函数的程序代码

And here is my program code calling the function

(3) Fortran 程序

(3) Fortran program

  1. npart 的分配大小是固定的.不是 ne 而是 nn
  2. 增加了opts(7)=1来获取epart、npart的Fortran风格数组(目前无效)
  1. allocation size of npart is fixed. Not ne but nn
  2. opts(7)=1 is added to get Fortran-style array of epart, npart(no effect until now)

.

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.

But the problem is that I get an error message as below though I put null for tpwgt.

输入错误:约束 0 的 tpwgts 的 0.000000 总和不正确.

并且这条消息在下面的代码中处理.

And this message is handled in the code below.

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".
", sum, i));
      return 0;
    }
  }

无论如何,为了看看如果我为 tpwgts 放入一个数组而不是 null 会得到什么,tpwgts(:) = 1.0/nparts,这使得 tpwgts 的总和等于 1.0.但我得到了与 1.75 相同的信息.

Anyway, in order to see what I would get if I put an array for tpwgts intead of null, tpwgts(:) = 1.0/nparts, which makes sum of tpwgts equal 1.0. But I got same message with 1.75 for the sum.

这是我的问题
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的例子吗?

These are my questions
1. Did I use null() for passing arguments correctly?
2. Do I have to pass pointers for all arguments to c function? then how?
3. Is putting an integer to opts(0:39) enough for use? For example, in a post without 'interface module', simple code like options(3)=1 is used. But in the c code, options has 16 named variable like options[METIS_OPTION_NUMBERING], options[METIS_OPTION_UFACTOR]. I think some thing is necessary to set options but I have no idea. 4. Is there an example for METIS in fortran?

任何类型的提示/建议都会对我有很大帮助.谢谢你.

Any kind of hint/advice will be a great help for me. Thank you.

我遇到的问题是 c 函数无法识别 fortran 代码中的空指针.

接口模块中有一些变量的错误声明(请参阅已修复"和注释)

There were some miss declations of variables in interface module(see 'Fixed' and comments)

看起来代码工作正常.但是 fortran 样式输出的 option(7) = 1 不起作用,现在我正在研究它.

It looks like the code works properly. But option(7) = 1 for fortran style output didn't work and now I'm looking at it.

推荐答案

  1. 不,你不能传递 null(),这是一个 Fortran 指针常量.您必须从模块 ISO_C_BINDING 传递 C_NULL_PTR 并且接口必须反映这一点.虚拟参数必须是 type(c_ptr),很可能带有 VALUE 属性.由于相同的内部表示,它实际上可能会起作用,但我不会指望它.

  1. No, you cannot pass null(), that is a Fortran pointer constant. You must pass C_NULL_PTR from the module ISO_C_BINDING and the interface must reflect this. The dummy argument must be type(c_ptr), most probably with VALUE attribute. It may actually work because of the same internal representation, but I wouldn't count on it.

不,如果你传递一些普通的变量,你可以直接通过引用传递.就像通常在 Fortran 中一样.如果接口是BIND(C),编译器知道它必须发送一个指针.

No, if you pass some normal variable, you can pass it directly by reference. Just like normally in Fortran. If the interface is BIND(C), the compiler knows it must send a pointer.

有一个更新 Fortran 2008 的新 TS,您可以在其中将可互操作过程中的虚拟参数定义为 OPTIONAL.然后你可以通过省略它们来传递空指针.Gfortran 应该已经支持这个了.

There is a new TS to update Fortran 2008, where you can define dummy arguments in the interoperable procedures as OPTIONAL. Then you can pass the null pointer just by omitting them. Gfortran should already support this.

注意:在这里我可以看到你的函数的一个非常不同的 C 签名,你确定你的函数没问题吗?http://charm.cs.uiuc.edu/doxygen/charm/meshpart_8c.shtml

Note: Here I can see a much different C signature of your function, are you sure yours is OK? http://charm.cs.uiuc.edu/doxygen/charm/meshpart_8c.shtml

这篇关于在 fortran 程序中调用 METIS API(用 C 语言编写)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆