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ónEl 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.