Chamando a API METIS (escrita em linguagem C) no programa fortran

Mais de 2 semanas, tenho lutado para chamar um dosMETIS biblioteca escrita em C do meu código fortran. E, infelizmente, não parece ser um HAPPY END sem a sua ajuda. Eu encontrei alguns posts sobrechamadas diretas eusando interface. Eu prefiro o último porque eu poderia monitorar as variáveis ​​para depuração. Existem três códigos que eu anexei.

1. c função eu gostaria de usar
2. módulo de interface fortran
3. programa fortran

(1) função 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)

Eu removi o corpo c funciton. Não é necessário entender meu problema

Aqui,idx_t é inteiro ereal_t é de precisão simples ou dupla. Dene paraopções são entradas e os últimos três argumentos são enviados. Evwgt, vsize, tpwgts eopções pode receber null como uma entrada para a configuração padrão Eu escrevi o módulo de interface para usar a função c como este

(2) módulo de interface Fortran

Fixo!Inseriruse iso_c_bind debaixousar constantesUsarinteiro (c_int) ao invés deinteiro parane, nn e outras variáveis.Remover módulo não utilizadoconstantes

.

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

E aqui está o meu código de programa chamando a função

(3) programa Fortran

Fixo!tamanho de alocação denpart está consertado. Nãone masnnopts (7) = 1 é adicionado para obter a matriz de estilo de Fortran de epart, npart (sem efeito até agora)

.

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

Mas o problema é que recebo uma mensagem de erro como abaixo, embora eu tenha colocado null para o tpwgt.

Erro de entrada: soma incorreta de 0,000000 para tpwgts para restrição 0.

E esta mensagem é tratada no código abaixo.

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;
    }
  }

De qualquer forma, a fim de ver o que eu iria conseguir se eu colocar uma matriz para tpwgts intead de nulo,tpwgts (:) = 1,0 / nparts, o que torna a soma de tpwgts igual a 1.0. Mas eu recebi a mesma mensagem com1,75 para a soma.

Estas são minhas perguntas
1. Eu usei null () para passar argumentos corretamente?
2. Tenho que passar ponteiros para todos os argumentos para a função c? então como?
3. Está colocando um inteiro para opts (0:39) o suficiente para usar? Por exemplo, em umpostar sem 'módulo de interface', código simples como opções (3) = 1 é usado. Mas no código c, as opções têm 16 variáveis ​​nomeadas como opções [METIS_OPTION_NUMBERING], opções [METIS_OPTION_UFACTOR]. Eu acho que algo é necessário para definir opções, mas não tenho ideia. 4. Existe um exemplo para o METIS no fortran?

Qualquer tipo de sugestão / conselho será uma grande ajuda para mim. Obrigado.

Conclusão

O problema que tive foi quefunção c não pôde reconhecer nulo ponteiro do código fortran.

Houve algumas descrições erradas de variáveis ​​no módulo de interface (veja 'Fixo' e comentários)

Parece que o código funciona corretamente. Masopção (7) = 1 para saída de estilo fortran não funcionou e agora estou olhando para ele.

questionAnswers(2)

yourAnswerToTheQuestion