Calling METIS API(wrtten in C language) in fortran program

吃可爱长大的小学妹 提交于 2019-11-28 14:14:52
  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.

  2. 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.

    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.

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

I think your opts(7) does not work because you also need an interface for the METIS function METIS_SetDefaultOptions. Based on the answer from http://glaros.dtc.umn.edu/gkhome/node/877, I created a wrapper module (metisInterface.F90) with the interfaces I needed:

module metisInterface
! module to allows us to call METIS C functions from the main Fortran code

   use,intrinsic :: ISO_C_BINDING

   integer :: ia,ic
   integer(C_INT) :: metis_ne,metis_nn
   integer(C_INT) :: ncommon,objval
   integer(C_INT) :: nparts
   integer(C_INT),allocatable,dimension(:) :: eptr,eind,perm,iperm
   integer(C_INT),allocatable,dimension(:) :: epart,npart
   type(C_PTR) :: vwgt,vsize,twgts,tpwgts
   integer(C_INT) :: opts(0:40)


   interface
      integer(C_INT) function METIS_SetDefaultOptions(opts) bind(C,name="METIS_SetDefaultOptions")
         use,intrinsic :: ISO_C_BINDING
         implicit none
         integer(C_INT) :: opts(0:40)
      end function METIS_SetDefaultOptions
   end interface 

   interface
      integer(C_INT) function METIS_PartMeshDual(ne,nn,eptr,eind,vwgt,vsize,ncommon,nparts,tpwgts, &
                              opts,objval,epart,npart) bind(C,name="METIS_PartMeshDual")
         use,intrinsic :: ISO_C_BINDING
         implicit none
         integer(C_INT):: ne, nn
         integer(C_INT):: ncommon, objval
         integer(C_INT):: nparts
         integer(C_INT),dimension(*) :: eptr, eind
         integer(C_INT),dimension(*) :: epart, npart
         type(C_PTR),value :: vwgt, vsize, tpwgts
         integer(C_INT) :: opts(0:40)
      end function METIS_PartMeshDual
   end interface    

end module metisInterface

Then, in the main program (or wherever you make the call to the METIS functions) you need to have (for completeness, I also added the call to METIS_PartMeshDual):

use metisInterface

integer :: metis_call_status
.
.
.
metis_call_status = METIS_SetDefaultOptions(opts)

! METIS_OPTION_NUMBERING for Fortran
opts(17) = 1

metis_call_status = METIS_PartMeshDual(metis_ne,metis_nn,eptr,eind, &
                    vwgt,vsize,ncommon,nparts,tpwgts,opts,objval,epart,npart)

Note that epart and npart will have Fortran numbering as you want (starting at 1). However, the processors will also start numbering at 1. For example, if you are running in 4 processors, root processor is 1 and you may have epart(n)=4, and you will not have any epart(n)=0.

Finally, a file metis.c is also needed with a single line:

#include "metis.h"

Compiling instructions

  1. Compile metis.c with a C compiler
  2. Compile metisInterface.F90 with a Fortran compiler linking with the compiled C object
  3. Compile main program with a Fortran compiler linking with metisInterface.o
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!