Вызов 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 вывод в стиле фортран не сработал, и теперь я смотрю на него.