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.
AbschlussDas 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.