2016-06-13 7 views
0

C++からFortranサブルーチンを呼び出しようとしています。リファレンスとして、私はFortranで同じサブルーチンを呼び出すテストプログラムを用意しています。これはプロシージャの正しい値を与えます。私はFortranの知識が非常に限られているので、なぜゴミ値を取得するのか分かりません。次のようにC++から呼び出されたFortranサブルーチンの値が正しくありません

Fortranコードは次のとおり

program test_9j 

    implicit none 

    integer :: ll1, ll2, ll3, ll4, ll5, ll6, ll7, ll8, llmin, llmax, ndim, ier, i 

    real(8) :: L1, L2, L3, L4, L5, L6, L7, L8, LMIN, LMAX 

    real(8), allocatable, dimension(:) :: ninecof 

    ll1 = 2 
    ll2 = 2 
    ll3 = 2 
    ll4 = 2 
    ll5 = 2 
    ll6 = 2 
    ll7 = 2 
    ll8 = 2 

    llmin = 0 
    llmax = 6 

    print*, llmin, llmax, llmax-llmin+1 
    print*, "" 

    L1 = real(ll1,kind=8) 
    L2 = real(ll2,kind=8) 
    L3 = real(ll3,kind=8) 
    L4 = real(ll4,kind=8) 
    L5 = real(ll5,kind=8) 
    L6 = real(ll6,kind=8) 
    L7 = real(ll7,kind=8) 
    L8 = real(ll8,kind=8) 

    LMIN = real(llmin,kind=8) 
    LMAX = real(llmax,kind=8) 

    ndim = llmax - llmin + 1 

    ALLOCATE(ninecof(ndim),stat=ier) 

! print*, ier 

    ninecof = 0.0 

    print*, "main Hi1" 

! print*, "LL", LMIN, LMAX 
    CALL w9j(ll1,ll2,ll3,ll4,ll5,ll6,ll7,ll8,llmin,llmax,ndim,ninecof) 

! print*, "main Hi2" 

    do i=1,ndim 
    print*, ninecof(i) 
    end do 

    print*, "main Hi3a" 

    !DEALLOCATE(ninecof) 

    print*, "main Hi3b" 

end program test_9j 

これはサブルーチンの正しい出力のシリーズを与えます。私はしかし、C++でこれをしようとすると、それは動作しません:(注:。。w9jサブルーチンは、私がのextern定義でそれを含める理由であるdrc6jサブルーチンを呼び出すdrc6jサブルーチンが正しい出力を与える)

using namespace std; 

extern "C" 
{ 
    double drc6j_ (double*, double*, double*, double*, double*, 
       double*, double*, double*, int*, int*); 

double w9j_ (int*, int*, int*, int*, int*, 
      int*, int*, int*, int*, int*, int*, double*); 

} 
int main() 
{ 
    int N = 1000; 
    double* coef9j; 
    int L1, L2, L3, L4, L5, L6, L7, L8, L9, Lmin=0, Lmax=6; 

    coef9j = new double [ N ]; 
    L1 = 2, L2 = 2, L3 = 2, L4 = 2, L5 = 2, L6 = 2, L7 = 2, L8 = 2; 

    w9j_ (&L2, &L3, &L4, &L5, &L6, &L7, &L8, &L9, &Lmin, &Lmax, &N, coef9j); 

    cout<<" Lmin, Lmax, ierr = "<<Lmin<<","<<Lmax<<","<<ier<<endl; 

    for (int i=0;i<Lmax-Lmin+1;i++) 
    cout<<"coeff = "<<setprecision(7)<<coef9j[i]<<endl; 

    return 0; 

} 

このプログラムは提供しますE-315などのLminとLmaxの値は、整数値を取得する必要があり、Lmaxの値があまりにもゼロでないために不可能です。以前のサブルーチン(drc6jのようなもの)では、LminとLmaxの値はサブルーチンによって決定されていました。また、入力Li値に関係なく常にcoeff =0を出力します。

drc6jサブルーチンとそれを評価するために使用するC++コードが必要な場合は、コメントに記載してください。それに応じて質問を編集します。私はC++コードを取得

出力は以下のとおりです。

AA   2   2   2   2   2   2   2   256   0   6  1000 
L9min, L9max, ierr = 0,6,0 
coeff = 0 
coeff = 0 
coeff = 0 
coeff = 0 
coeff = 0 
coeff = 0 

とFortranコードについて:

  0   6   7 

main Hi1 
    -8.5714285714285719E-003 
    1.7347234759768071E-018 
    1.6734693877551020E-002 
    1.7347234759768071E-018 
    1.3877551020408163E-002 
    0.0000000000000000  
    0.0000000000000000  
main Hi3a 
main Hi3b 

これはサブルーチンw9jコードです:

subroutine w9j(l1,l2,l3,l4,l5,l6,l7,l8,lmin,lmax,ndim,cof9j) 

    implicit none 

    !--- in/out variables 

    integer, intent(in) :: l1, l2, l3, l4, l5, l6, l7, l8, lmin, lmax, ndim 
    real(8), dimension(ndim), intent(out) :: cof9j 

    !--- program variables 

    integer :: l1min, l1max, l2min, l2max, l3min, l3max 
    integer :: i, j, k, jmin, jmax, ier, dim1, dim2, dim3 

    real(8) :: y 
    real(8), allocatable, dimension(:) :: sixj1, sixj2, sixj3 
    real(8) :: rl1, rl2, rl3, rl4, rl5, rl6, rl7, rl8, ri 
    real(8) :: rl1min, rl1max, rl2min, rl2max, rl3min, rl3max 

    !--- --- --- 

    print*, 'AA', l1,l2,l3,l4,l5,l6,l7,l8,lmin,lmax,ndim 

    cof9j = 0.0 

    do k=1,ndim 
    i=k+lmin-1 

! print*, 'i', i 
! print*, "" 

    if((l2+i-l1 < 0) .or. (l2-i+l1 < 0) .or. (-l2+i+l1 < 0) .or. & 
    & (l2+l5-l8 < 0) .or. (l2-l5+l8 < 0) .or. (-l2+l5+l8 < 0) .or. & 
    & (l4+l3-l5 < 0) .or. (l4-l3+l5 < 0) .or. (-l4+l3+l5 < 0) .or. & 
    & (l4+l1-l7 < 0) .or. (l4-l1+l7 < 0) .or. (-l4+l1+l7 < 0) .or. & 
    & (l6+i-l3 < 0) .or. (l6-i+l3 < 0) .or. (-l6+i+l3 < 0) .or. & 
    & (l6+l7-l8 < 0) .or. (l6-l7+l8 < 0) .or. (-l6+l7+l8 < 0)) then 
!  print*, "violation of triangularity" 
     cof9j(k) = 0.0 
     cycle 
    end if 

    l1min=max(abs(i-l8),abs(l5-l1)) 
    l1max=min(i+l8,l5+l1) 
    dim1 = l1max -l1min + 1 
! print*, 'l1', l1min,l1max,dim1 
! print*, "" 

    l2min=max(abs(l3-l7),abs(l1-l5)) 
    l2max=min(l3+l7,l1+l5) 
    dim2 = l2max -l2min + 1 
! print*, 'l2', l2min,l2max,dim2 
! print*, "" 

    l3min=max(abs(i-l8),abs(l7-l3)) 
    l3max=min(i+l8,l7+l3) 
    dim3 = l3max -l3min + 1 
! print*, 'l3', l3min,l3max,dim3 
! print*, "" 

    if (l1max < l1min .or. l2max < l2min .or. l3max < l3min) then 
     cof9j(k) = 0.0 
     cycle 
    end if 

    allocate(sixj1(dim1)) 
    allocate(sixj2(dim2)) 
    allocate(sixj3(dim3)) 

    sixj1 = 0.0 
    sixj2 = 0.0 
    sixj3 = 0.0 

    ri = real(i) ! L1 
    rl1 = real(l1) ! L2 
    rl2 = real(l2) ! L3 
    rl3 = real(l3) ! L4 
    rl4 = real(l4) ! L5 
    rl5 = real(l5) ! L6 
    rl6 = real(l6) ! L7 
    rl7 = real(l7) ! L8 
    rl8 = real(l8) ! L9 
    rl1min = 0.0 
    rl1max = 0.0 
    rl2min = 0.0 
    rl2max = 0.0 
    rl2min = 0.0 
    rl3max = 0.0 

!  SUBROUTINE DRC6J (L2, L3, L4, L5, L6, L1MIN, L1MAX, SIXCOF, NDIM, IER) 
!   L1MAX=MIN(L2+L3,L5+L6) and L1MIN=MAX(ABS(L2-L3),ABS(L5-L6)). 

! print*, "Hi1" 

! print*, 'BB',ri,rl1,rl2,rl3,rl4,rl5,rl6,rl7,rl8,dim1,dim2,dim3 

!    L2 L3 L4 L5 L6 
    call DRC6J(ri,rl8,rl2,rl5,rl1,rl1min,rl1max,sixj1,dim1,ier) 
! print*, "6j - 1" 
!    L2 L3 L4 L5 L6 
    call DRC6J(rl3,rl7,rl4,rl1,rl5,rl2min,rl2max,sixj2,dim2,ier) 
! print*, "6j - 2" 
!    L2 L3 L4 L5 L6 
    call DRC6J(ri,rl8,rl6,rl7,rl3,rl3min,rl3max,sixj3,dim3,ier) 
! print*, "6j - 3" 

! print*, "Hi2" 

    if (l1min /= int(rl1min) .or. l1max /= int(rl1max) .or. & 
    & l2min /= int(rl2min) .or. l2max /= int(rl2max) .or. & 
    & l3min /= int(rl3min) .or. l3max /= int(rl3max)) then 
     print*, "Declared dimensions of 'sixj' arrays are wrong" 
    end if 

    jmin = max(l1min,l2min,l3min) 
    jmax = min(l1max,l2max,l3max) 
    print*, 'Jmin Jmax', jmin, jmax 


    y = 0.0 

    if(jmin <= jmax) then 

     do j=jmin,jmax 
     y = y + (2.0*j+1.0)*sixj1(j-l1min+1)*sixj2(j-l2min+1)*sixj3(j-l3min+1) 
     end do 

    end if 

    cof9j(k) = y 

    deallocate(sixj1,sixj2,sixj3) 

    end do 
    print*, 'end values', l1,l2,l3,l4,l5,l6,l7,l8,lmin,lmax,ndim 


    return 

end subroutine w9j 

サブルーチンdrc6j.fと依存関係については、netlib.orgにあります。

+0

cppはCプリプロセッサであり、C++ではありません –

+0

サブルーチンのコードはどこにありますか?あなたが得る正確な出力を表示できますか? –

+1

これが重要なのかどうかはわかりませんが、FORTRANプログラムでLL1 LL2 ...が整数として宣言されているようですが、C++ではすべてのパラメータをdoubleとして宣言しています。これは、スタックのいくつかの問題を引き起こし、変数の値を乱す可能性があります。 –

答えて

2

w9jの時点でlminlmaxを設定していますが、C++コードではこれらの変数を設定しないので、C++コードで印刷すると、これらの場所にある値をメモリに記録しているだけです変数 - つまり、未定義です。あなたの元のFortranコードでは、これらの変数をw9jに渡す前にこれらの変数を設定します。これがうまくいくようです。

注あなたはw9jintent(in)として​​とLmaxをマークしたが、その後、あなたは彼らがw9jの出力であるかのように、C++のコードでそれらをプリントアウトしようとしています。 intent(in)としてマークされた引数は、そのルーチン内で変更しないでください。コメント

最終修正はw9jにC++の呼び出しがl1に合格しないことに注意することだったが、あなたは、未定義の使用につながる、何に設定されていないl9を渡すかを、次の

更新メインw9jルーチンの値。

+0

後でコードを修正し、それぞれLmin Lmaxを0,6に設定しました。まだcoeffは0です。 – pyroscepter

+0

あなたが提案した内容を組み込むようにコードを修正すると、答えは常に0になりません。値が配列coeffにコピーされないのはなぜですか、私はまだ考えていません。 – pyroscepter

+0

@pyroscepterコメントにいくつかの変更が提案されているので、実際に使用しているコードを示すために質問を更新できますか? 'lmin'などを設定したとしたら、' w9j'呼び出しの後にC++コードで印刷しても異常な数字が出るのですか? –

関連する問題