だから私は疫病のように 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 mismatchとFunction 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)」行を追加するだけで済むことを願っています。
すべてのガイダンスは大歓迎です!!!