Вызов METIS API (написанный на языке C) в программе на фортране

За 2 недели я изо всех сил пытался позвонить одному изMETIS библиотека написана на C из моего кода на Фортране. И, к сожалению, это не кажется счастливым концом без вашей помощи. Я нашел несколько постов опрямой вызов а такжеиспользуя интерфейс, Я предпочитаю последнее, потому что я мог контролировать переменные для отладки. Я прикрепил три кода.

1. С функцией, которую я хотел бы использовать
2. интерфейсный модуль Fortran
3. фортран программа

(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)

Я удалил тело cc funciton. Нет необходимости понимать мою проблему

Вот,idx_t целое число иreal_t одинарной или двойной точности. ИзНебраска впараметры входные и последние три аргумента выводятся. А такжеvwgt, VSIZE, tpwgts а такжепараметры может получить нулевое значение в качестве входных данных для настройки по умолчанию. Я написал интерфейсный модуль для использования функции c, как это

(2) интерфейсный модуль Fortran

Исправлена!Вставитьиспользовать iso_c_bind подиспользовать константыиспользованиецелое число (c_int) вместоцелое число заНебраска, пп и другие переменные.Удалить неиспользуемый модульконстанты

.

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) программа Фортран

Исправлена!размер распределенияNpart фиксированный. НеНебраска ноппopts (7) = 1 добавлен, чтобы получить массив epart, npart в стиле Фортрана (до сих пор не работал)

.

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.

Ошибка ввода: неверная сумма 0,000000 для tpwgts для ограничения 0.

И это сообщение обрабатывается в коде ниже.

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 intead из NULL,tpwgts (:) = 1.0 / nparts, что делает сумму tpwgts равной 1,0. Но я получил то же сообщение с1,75 на сумму.

Это мои вопросы
1. Я правильно использовал null () для передачи аргументов?
2. Должен ли я передавать указатели для всех аргументов в функцию c? тогда как?
3. Достаточно ли для использования ввода целого числа в opts (0:39)? Например, вПочта без «интерфейсного модуля» используется простой код, подобный options (3) = 1. Но в коде c параметры имеют 16 именованных переменных, таких как options [METIS_OPTION_NUMBERING], options [METIS_OPTION_UFACTOR]. Я думаю, что некоторые вещи необходимы для установки параметров, но я понятия не имею. 4. Есть ли пример для METIS в фортране?

Любой намек / совет будет большой помощью для меня. Спасибо.

Conclution

У меня была проблемафункция c не может распознать ноль указатель из кода Фортрана.

Были некоторые пропущенные переменные в модуле интерфейса (см. «Исправлено» и комментарии)

Похоже, код работает правильно. Ноопция (7) = 1 вывод в стиле фортран не сработал, и теперь я смотрю на него.

Ответы на вопрос(2)

Ваш ответ на вопрос