2

有限要素計算用に作成した Fortran プログラムの一部として、メッシュ分割にMETISライブラリを使用しようとしています。METIS は C で書かれていますが、Fortran 90 で問題なく動作するはずです。

潜在的な問題の 1 つは、null ポインターを与えるいくつかの引数があることです。Fortran から C 関数を呼び出してヌル ポインター オブジェクトを認識するのに苦労した人もいます。それはここで対処されており、それが私が抱えている問題ではないと思います。

問題は、METIS が配列の開始インデックスを変更することだと思います。C では 0、Fortran では 1 です。すべての関数に渡される配列があり、Fortran 規則が必要な場合に変更するoptionsフィールドがあるはずです。そうしないと、C プログラムがインデックス 0 にアクセスしようとし、セグ フォールトが発生します。METIS_OPTION_NUMBERING1

ここでの edunlop1 による投稿は、配列を作成するだけoptionsで、METIS と合意した規則によって、その配列のどの要素を 1 に設定してすべての番号を付け直すかを決定することを示唆しています。ただし、配列の長さと同様に、使用しているルーチンによって異なります。

とにかく、ここに私のコードがあります:

integer :: ndomains,ncommon,objval
integer :: options(0:40)
integer, dimension(:), allocatable :: eptr,eind
integer, pointer :: vwgt(:)=>null(), vsize(:)=>null(), opts(:)=>null()
real(kind=8), pointer :: tpwgts(:)=>null()

! Read in the mesh data
call getarg(1,meshname)
call readmesh(meshname)
allocate(color(ne),domain(nn))
allocate(eind(3*ne),eptr(ne+1))
do n=1,ne
    eptr(n) = 1+3*(n-1)
    do i=1,3
        eind( eptr(n)+i-1 ) = elem(i,n)
    enddo
enddo

! Try and call METIS
ncommon = 2
ndomains = 2
options = 0
options(0) = 1
options(8) = 1
call METIS_PartMeshDual(ne,nn,eptr,eind,vwgt,vsize, &
    & ncommon,ndomains,tpwgts,options,objval,color,domain)

番号付けを変更するための METIS の関連コードは、ファイル libmetis/meshpart.c にあります。

/* renumber the mesh */
if (options && options[METIS_OPTION_NUMBERING] == 1) {
  ChangeMesh2CNumbering(*ne, eptr, eind);
  renumber = 1;
}

何かご意見は?役立つ場合は、Valgrind の出力を投稿できます。

4

3 に答える 3

3

これには何もないかもしれませんが、おそらく質問の2番目の段落にあるリンクされた投稿はまだ適切です.

Fortran の POINTER と C のポインターは、特に Fortran ポインターが配列を指す場合、まったく同じ概念ではありません。Fortran での配列へのポインターの実装では、C ポインター (単なるデータのアドレス) に格納される情報以外の追加情報 (配列境界または同等のもの) を格納する必要があります。

(技術的には、METIS_PartMeshDual の関連する仮引数定義にオプションまたはポインター属性がない限り (呼び出される C 関数であり、言語標準が <= F2008 の場合は不可能です)、Fortran での呼び出しで分離されたポインターへの参照は次のようになります。繰り返しになりますが、何が起こるかは実装に依存します - 機能する場所と機能しない場所の実装オプションを想像できます。)

null ポインターの宣言にリンクした投稿では、ソリューションの一部として配列からスカラーに変更されていることに注意してください (リストの最初の返信 - 投稿のタイミングを確認してください)。質問の一部として投稿されたコード例では、「null」の宣言はまだ配列を示しています。宣言の変更により、C api への呼び出しの「セットアップ」や、コンパイラにとって分離されたポインターがどのように見えるかが変更されると思われます。

最近では、Fortran から C API を呼び出すとき、(可能な場合) Fortran 2003 の C 相互運用機能 (BIND(C) など) を使用して C API のインターフェイス ブロックを作成することを好みます。これははるかに堅牢で、この種のプラットフォーム依存の問題を回避します。F2003 のこの側面をサポートする Fortran コンパイラも必要です。Fortran ユーザーにそのようなインターフェイス ブロックを提供するのに苦労しているライブラリ ベンダーは、私から大きな関心と多くの親切な考えを得ることができます。

于 2012-12-31T02:14:05.403 に答える
2

Fortran 配列のサイズは、C よりも柔軟です。Fortran 配列を 0 から始まるインデックスにすることも、任意の開始インデックスにすることもできます。

real, dimension (0:N-1) :: array
real, dimension (:), allocatable :: group
allocate (group (0:N-1))

開始インデックスに関する何らかの不一致が問題である場合、おそらくこれが役立ちます。

于 2012-12-29T07:58:30.240 に答える
2

使用する:

vwgt=>null() 

それ以外の

vwgt(:)=>null()

すべてのヌル (つまり、vwgt、vsize、opts、tpwgts など)。問題は、vwgt または vwgt(1) だけではなく、vwgt(:) が実際には定義されていないことです。それでも問題が解決しない場合は、デバッガーを使用してすべての値を確認してください。

2段落目に挙げたスレッドのOPでした。残念ながら、最終的な解決策は返信の一番上にあります (タイムスタンプを参照してください)。それが役立つことを願っています。

于 2013-01-02T03:25:32.223 に答える