Aufruf der METIS-API (geschrieben in C-Sprache) in fortran

Über 2 Wochen habe ich Mühe gehabt, einen der beiden anzurufenMETIS Bibliothek geschrieben in C von meinem fortran Code. Und leider scheint es ohne Ihre Hilfe kein GLÜCKLICHES ENDE zu sein. Ich habe einige Posts über gefundendirekt anrufen undmit Schnittstelle. Ich bevorzuge letzteres, weil ich die Variablen für das Debuggen überwachen könnte. Ich habe drei Codes angehängt.

1. c-Funktion, die ich verwenden möchte
2. Fortran-Schnittstellenmodul
3. Fortran-Programm

(1) c Funktion

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)

Ich habe den C-förmigen Körper entfernt. Es ist nicht notwendig, mein Problem zu verstehen

Hier,idx_t ist Integer undreal_t ist einfache oder doppelte Präzision. Vonne zuOptionen werden eingegeben und die letzten drei Argumente werden ausgegeben. Undvwgt, vsize, tpwgts undOptionen kann null als Eingabe für die Standardeinstellung erhalten Ich habe das Schnittstellenmodul für die Verwendung der c-Funktion wie folgt geschrieben

(2) Fortran-Schnittstellenmodul

Fest!Einfügenbenutze iso_c_bind unterbenutze KonstantenBenutzenGanzzahl (c_int) anstattganze Zahl zumne, nn und andere Variablen.Unbenutztes Modul entfernenKonstanten

.

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

Und hier ist mein Programmcode, der die Funktion aufruft

(3) Fortran-Programm

Fest!Belegungsgröße vonnpart Ist repariert. Nichtne abernnopts (7) = 1 wird hinzugefügt, um ein Array von epart, npart im Fortran-Stil zu erhalten (bis jetzt kein Effekt)

.

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

Aber das Problem ist, dass ich eine Fehlermeldung wie folgt erhalte, obwohl ich null für tpwgt angegeben habe.

Eingabefehler: Falsche Summe von 0,000000 für tpwgts für Einschränkung 0.

Und diese Nachricht wird im folgenden Code behandelt.

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

Wie auch immer, um zu sehen, was ich bekommen würde, wenn ich ein Array für tpwgts anstelle von null setzen würde,tpwgts (:) = 1.0 / nparts, was die Summe von tpwgts gleich 1,0 macht. Aber ich habe die gleiche Nachricht mit1,75 für die Summe.

Das sind meine Fragen
1. Habe ich null () verwendet, um Argumente korrekt zu übergeben?
2. Muss ich Zeiger für alle Argumente an c function übergeben? wie dann?
3. Reicht es aus, eine Ganzzahl für opts (0:39) zu verwenden? Zum Beispiel in aPost Ohne 'Schnittstellenmodul' werden einfache Code-ähnliche Optionen (3) = 1 verwendet. Aber im c-Code hat options 16 benannte Variablen wie options [METIS_OPTION_NUMBERING], options [METIS_OPTION_UFACTOR]. Ich denke, etwas ist notwendig, um Optionen festzulegen, aber ich habe keine Ahnung. 4. Gibt es ein Beispiel für METIS in fortran?

Jede Art von Hinweis / Ratschlag wird mir eine große Hilfe sein. Vielen Dank.

Abschluss

Das Problem, das ich hatte, war dasc-Funktion konnte null nicht erkennen Zeiger vom fortran Code.

Es gab einige Missdeklarationen von Variablen im Schnittstellenmodul (siehe 'Behoben' und Kommentare)

Es sieht so aus, als ob der Code richtig funktioniert. AberOption (7) = 1 für fortran style hat die ausgabe nicht funktioniert und jetzt schaue ich es mir an.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage