2

だから私は疫病のように Fortran を避けてきましたが、ついに私の時が来ました... 私は他の誰かの Fortran コード (プログラム A と呼びましょう) の一部を取り、それで 2 つのことを行う必要があります:

(1) 第三者の Fortran コード (プログラム B としましょう) とマージして、B が A を呼び出せるようにします。

(2)CがAを呼び出すことができるように、それを私のC++コード(プログラムC)とマージします

B と C は最適化アルゴリズムであり、A はベンチマーク関数の集合です... しかし、すべての素晴らしい機能が実現する前に、まず A の必要な部分をコンパイルする必要があります。必要な A のサブルーチンはすべて 1 つのファイルに含まれています。オンラインで入手した情報に基づいて形を整えてきました(たとえば、コードに「IMPLICIT NONE」を追加して、gfortranに適したものにします)。しかし、2 つの頑固なバグと 1 つの警告があります (警告は別の記事に譲ります)。

私が現在コンパイルしている方法は次のとおりです(Makefileを介して):

all:
    gfortran progA.FOR
    g++ -c progC.cpp
    g++ -o Program.out progA.o progC.o
    rm *.o

しかし、最初の行は次のエラーで完了できません。

最初のエラー:

SUBROUTINE TP1(MODE)
1
Error: Unclassifiable statement at (1)

関連コード (ファイルの先頭から):

      IMPLICIT NONE  
      INTEGER    NMAX,MMAX,LMAX,MNNMAX,LWA,LIWA,LACTIV,N,NILI,NINL,
     /           NELI,NENL,NEX, MODE              
      PARAMETER (NMAX   = 101, 
     /           MMAX   = 50, 
     /           LMAX   = 50, 
     /           MNNMAX = NMAX + NMAX + MMAX + 2,
     /           LWA    = 2*NMAX*NMAX + 33*NMAX + 10*MMAX + 200,
     /           LIWA   = MMAX + NMAX + 150,
     /           LACTIV = 2*MMAX + 15)  
      LOGICAL    INDEX1,INDEX2

      SUBROUTINE TP1(MODE)      
      COMMON/L1/N,NILI,NINL,NELI,NENL   
      COMMON/L2/X(2)   
      COMMON/L4/GF(2)   
      COMMON/L6/FX      
      COMMON/L9/INDEX1  
      COMMON/L10/INDEX2 
      COMMON/L11/LXL    
      COMMON/L12/LXU    
      COMMON/L13/XL(2)  
      COMMON/L20/LEX,NEX,FEX,XEX(2)     
      REAL*8 X,G,GF,GG,FX,XL,XU,FEX,XEX 
      LOGICAL LXL(2),LXU(2),LEX 
      GOTO (1,2,3,4,4),MODE     
1     N=2       
      NILI=0    
      NINL=0    
      NELI=0    
      NENL=0    
      X(1)=-2.D0
      X(2)=1.D0 
      LXL(1)=.FALSE.    
      LXL(2)=.TRUE.     
      LXU(1)=.FALSE.    
      LXU(2)=.FALSE.    
      XL(2)=-1.5D0      
      LEX=.TRUE.
      NEX=1     
      XEX(1)=1.D0       
      XEX(2)=1.D0       
      FEX=0.D0  
      RETURN    
2     FX=100.D0*(X(2)-X(1)**2)**2+(1.D0-X(1))**2
      RETURN    
3     GF(2)=200.D0*(X(2)-X(1)**2)       
      GF(1)=-2.D0*(X(1)*(GF(2)-1.D0)+1.D0)      
4     RETURN    
      END       

まったく同じ方法で宣言された 300 以上の他のサブルーチンがあるため、このエラーが表示される理由がわかりません (例: SUBROUTINE TP2(MODE), ..., SUBROUTINE TP300(MODE) )。

2 番目のエラー:

HX=TP273A(X)
1
Error: Return type mismatch of function 'tp273a' at (1) (REAL(4)/REAL(8))

関連コード:

      SUBROUTINE TP273(MODE) 
      COMMON/L1/N,NILI,NIML,NELI,NENL 
      COMMON/L2/X 
      COMMON/L4/GF 
      COMMON/L6/FX 
      COMMON/L11/LXL 
      COMMON/L12/LXU 
      COMMON/L20/LEX,NEX,FEX,XEX 
      LOGICAL LEX,LXL(6),LXU(6) 
      REAL*8 X(6),FX,GF(6),FEX,XEX(6),HX,DFLOAT
      GOTO (1,2,3,4,4)MODE 
 1    N=6 
      NILI=0 
      NINL=0 
      NELI=0 
      NENL=0 
      DO 6 I=1,6 
      X(I)=0.D+0 
      XEX(I)=0.1D+1 
      LXL(I)=.FALSE. 
6     LXU(I)=.FALSE. 
      LEX=.TRUE. 
      NEX=1 
      FEX=0.D+0 
      RETURN 
 2    HX=TP273A(X) 
      FX=0.1D+2*HX*(0.1D+1+HX) 
      RETURN 
 3    HX=TP273A(X) 
      DO 7 I=1,6 
 7    GF(I)=0.2D+2*(0.16D+2-DFLOAT(I))*(X(I)-0.1D+1) 
     1       *(0.1D+1+0.2D+1*HX) 
 4    RETURN 
      END       

      REAL*8 FUNCTION TP273A (X) 
      REAL*8 X(6),DFLOAT
      TP273A=0 
      DO 10 I=1,6 
10    TP273A=TP273A+(0.16D+2-DFLOAT(I))*(X(I)-0.1D+1)**2 
      RETURN
      END

Physics Forumsを読んだ後、変数「TP273A」の名前を「TP273Avar」に変更して、関数と同じ名前にならないようにしました。これはエラーを解決しませんでした。また、「7 GF(I) = ...」のすぐ下の「1」を「F」に置き換えて再コンパイルしました。何も変わっていません。いずれにせよ、今述べた変更が必要であると確信していますが、何か他のことが起こっているに違いありません.

Fortran の Data type mismatchFunction return type mismatchも読んだので、ファイルの一番上に「module mycode」を、一番下に「end module mycode」を単純に追加しようとしましたが、役に立ちませんでした。

これがすべて完了したら、私の目標は、次のようなコードを使用して C++ からこれらのサブルーチンを呼び出すことです。

#include <kitchensink>

extern"C"
{
void TP1_(int *mode);
}

int main()
{
    TP1_(2);
    return 0;
}

Fortran コードがコンパイルされたら、サブルーチンを変更して、C++ が std::vector X を TP#_(2,*X,*Y) に渡し、Y の計算値を取得できるようにします。私の std::vector X各サブルーチンで COMMON/L2 X を置き換え、Y はサブルーチンで計算された FX の値になります。上記の C++ コードのガイダンスとして、Fortran と C の混合を使用しました。

B が A を呼び出す部分については、A を B と一緒にコンパイルし、必要な場所に「CALL TP1(MODE)」行を追加するだけで済むことを願っています。

すべてのガイダンスは大歓迎です!!!

4

1 に答える 1

6

コンパイル単位外のファイルにステートメントを含めることはできません。これらは、サブルーチン、関数、モジュール、またはプログラムです。あなたの場合、いくつかのステートメントがあり(最初はimplicit none)、それらの後にのみサブルーチンTP1の始まりがあります。

手順をモジュールに編成し、containsセクションの前に共通部分を残すか (Fortran 初心者の場合は、C++ 相互運用性に関する作業が続きます) implicit none、すべてのサブルーチンに とその他を個別に含める必要があります。コードが以前に機能していた場合でも、これが必要ですか?

于 2013-08-19T18:40:12.677 に答える