Wywołanie METIS API (napisany w języku C) w programie fortran

W ciągu 2 tygodni walczyłem z jednym z nichMETYS biblioteka napisana w C z mojego kodu fortran. I niestety nie wydaje się być SZCZĘŚLIWYM KONIECEM bez twojej pomocy. Znalazłem kilka postówbezpośrednie połączenie iza pomocą interfejsu. Wolę ten drugi, ponieważ mogę monitorować zmienne do debugowania. Załączam trzy kody.

1. Funkcja c Chciałbym użyć
2. Moduł interfejsu fortran
3. program fortran

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

Usunąłem ciało funkcji c. Nie trzeba rozumieć mojego problemu

Tutaj,idx_t jest liczbą całkowitą ireal_t jest pojedyncza lub podwójna precyzja. Zne doopcje są wejściowe i wyprowadzane są trzy ostatnie argumenty. Ivwgt, vsize, tpwgts iopcje może otrzymać wartość NULL jako dane wejściowe dla ustawień domyślnych Napisałem moduł interfejsu do używania funkcji c w ten sposób

(2) Moduł interfejsu Fortran

Naprawiony!Wstawićużyj iso_c_bind podużyj stałychPosługiwać sięliczba całkowita (c_int) zamiastliczba całkowita dlane, nn i inne zmienne.Usuń nieużywany modułstałe

.

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

A oto mój kod programu wywołujący tę funkcję

(3) Program Fortran

Naprawiony!wielkość alokacjinpart jest naprawiony. Niene alenndodano opts (7) = 1, aby uzyskać tablicę epart w stylu Fortrana, npart (brak efektu do teraz)

.

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

Ale problem polega na tym, że otrzymuję komunikat o błędzie, jak poniżej, chociaż wprowadziłem wartość null dla tpwgt.

Błąd wejścia: niepoprawna suma 0,000000 dla tpwgts dla ograniczenia 0.

Ta wiadomość jest obsługiwana w poniższym kodzie.

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

W każdym razie, aby zobaczyć, co bym dostał, gdybym wstawił tablicę dla tpwgts intead o wartości null,tpwgts (:) = 1.0 / nparts, co powoduje, że suma tpwgts równa się 1,0. Ale mam tę samą wiadomość1,75 za sumę.

To są moje pytania
1. Czy użyłem null () do poprawnego przekazywania argumentów?
2. Czy muszę przekazywać wskaźniki dla wszystkich argumentów funkcji c? więc jak?
3. Czy wprowadzenie liczby całkowitej do opcji (0:39) jest wystarczające do użycia? Na przykład w asłupek bez „modułu interfejsu” używany jest prosty kod, taki jak opcje (3) = 1. Ale w kodzie c opcje mają 16 nazwanych zmiennych, takich jak opcje [METIS_OPTION_NUMBERING], opcje [METIS_OPTION_UFACTOR]. Myślę, że konieczne jest ustawienie pewnych opcji, ale nie mam pojęcia. 4. Czy jest przykład METIS w fortran?

Wszelkie wskazówki / porady będą dla mnie wielką pomocą. Dziękuję Ci.

Zanieczyszczenie

Problem, który miałem, był takiFunkcja c nie mogła rozpoznać wartości zerowej wskaźnik z kodu fortran.

W module interfejsu były pewne deklinacje zmiennych (patrz „Naprawiono” i komentarze)

Wygląda na to, że kod działa poprawnie. Aleopcja (7) = 1 dla stylu fortran wynik nie działał i teraz na niego patrzę.

questionAnswers(2)

yourAnswerToTheQuestion