Llamando a METIS API (escrito en lenguaje C) en el programa fortran

Durante 2 semanas, he luchado para llamar a uno de losMETIS Biblioteca escrita en C a partir de mi código fortran. Y, desafortunadamente, no parece ser un FINAL FELIZ sin su ayuda. He encontrado algunos mensajes sobrellamada directa yusando interfaz. Prefiero este último porque podría monitorear las variables para la depuración. Hay tres códigos que adjunto.

1. c función que me gustaría usar
2. módulo de interfaz fortran
3. programa fortran

(1) función 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)

Quité el cuerpo de la función c. No es necesario entender mi problema.

Aquí,idx_t es entero yreal_t Es simple o doble precisión. DesdeNebraska aopciones son de entrada y los últimos tres argumentos son de salida. Yvwgt, vsize, tpwgts yopciones puedo recibir nulo como entrada para la configuración predeterminada. Escribí el módulo de interfaz para usar la función c como esta

(2) módulo de interfaz Fortran

¡Fijo!Insertarusa iso_c_bind debajousar constantesUtilizarentero (c_int) en lugar deentero paraNebraska, nn y otras variables.Eliminar módulo no 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

Y aquí está mi código de programa llamando a la función

(3) programa Fortran

¡Fijo!tamaño de asignación denpart está arreglado. NoNebraska peronnopts (7) = 1 se agrega para obtener una matriz de estilo de Fortran de epart, npart (sin efecto hasta ahora)

.

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

Pero el problema es que recibo un mensaje de error como el siguiente, aunque puse nulo para tpwgt.

Error de entrada: suma incorrecta de 0.000000 para tpwgts para la restricción 0.

Y este mensaje se maneja en el siguiente código.

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 todos modos, para ver lo que obtendría si pusiera una matriz para tpwgts en lugar de nulo,tpwgts (:) = 1.0 / nparts, lo que hace que la suma de tpwgts sea igual a 1.0. Pero tengo el mismo mensaje con1.75 por la suma

Estas son mis preguntas
1. ¿Usé null () para pasar argumentos correctamente?
2. ¿Tengo que pasar punteros para todos los argumentos a la función c? ¿entonces como?
3. ¿Es suficiente para usar un entero a las opciones (0:39)? Por ejemplo, en unaenviar sin 'módulo de interfaz', se usa el código simple como opciones (3) = 1. Pero en el código c, opciones tiene 16 variables nombradas como opciones [METIS_OPTION_NUMBERING], opciones [METIS_OPTION_UFACTOR]. Creo que algo es necesario para establecer opciones pero no tengo idea. 4. ¿Hay un ejemplo para METIS en Fortran?

Cualquier tipo de sugerencia / consejo será de gran ayuda para mí. Gracias.

Conclusión

El problema que tuve fue queLa función c no pudo reconocer nula Puntero del codigo fortran.

Hubo algunas fallas en las desconexiones de las variables en el módulo de interfaz (consulte 'Corregido' y comentarios)

Parece que el código funciona correctamente. Peroopción (7) = 1 Para el estilo Fortran, la salida no funcionó y ahora lo estoy viendo.

Respuestas a la pregunta(2)

Su respuesta a la pregunta