So I've been avoiding Fortran like the plague, but finally my time has come... I need to take part of someone else's Fortran code (let's call it program A) and do two things with it:
(1) Merge it with a third person's Fortran code (let's call it program B) so that B can call A
(2) Merge it with my C++ code (program C) so that C can call A
B and C are optimization algorithms, and A is a collection of benchmark functions... But before all that awesomeness can happen, I must first compile the portion of A that I need. All the subroutines of A that I need are contained in one file. I've been getting it into shape based on information I got online (eg adding "IMPLICIT NONE" to the code and making it suitable for gfortran). But I've got two stubborn bugs and a warning (I'll leave the warning for another post).
Here's how I am currently compiling it (via a Makefile):
all:
gfortran progA.FOR
g++ -c progC.cpp
g++ -o Program.out progA.o progC.o
rm *.o
But the first line fails to complete with the following errors,
FIRST ERROR:
SUBROUTINE TP1(MODE)
1
Error: Unclassifiable statement at (1)
RELEVANT CODE (starting from the top of the file):
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
I do not understand why this error appears since there are over 300 other subroutines declared exactly the same way (eg SUBROUTINE TP2(MODE), ..., SUBROUTINE TP300(MODE) ).
SECOND ERROR:
HX=TP273A(X)
1
Error: Return type mismatch of function 'tp273a' at (1) (REAL(4)/REAL(8))
RELEVANT CODE:
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
After reading Physics Forums I tried renaming the variable "TP273A" to "TP273Avar" so that it would not have the same name as the function. This did not resolve the error. Also, I replaced the "1" with "F" just below "7 GF(I) = ..." and recompiled. Nothing changed. I'm pretty sure the changes I just mentioned are necessary anyway, but there must be something else going on.
I have also read Data type mismatch in fortran and Function return type mismatch , so I naively tried adding "module mycode" to the top and "end module mycode" to the bottom of the file to no avail.
After this is all said and done, my goal is to call these subroutines from C++ using a code similar to:
#include <kitchensink>
extern"C"
{
void TP1_(int *mode);
}
int main()
{
TP1_(2);
return 0;
}
Once the Fortran Code compiles, I want to modify the subroutines so that C++ can pass std::vector X to TP#_(2,*X,*Y) and get back the computed value for Y. My std::vector X will replace COMMON/L2 X in each of the subroutines, and Y will be the value of FX computed in the subroutines. I used Mixing Fortran and C as guidance for the above C++ code.
As for the B calls A part, I hope that it will be as simple as compiling A along with B, and adding "CALL TP1(MODE)" lines wherever I need them.
Any and all guidance will be greatly appreciated!!!
You cannot have statements just in a file outside of a compilation unit. These can be subroutines, functions, modules or programs. In your case you have some statements( first of them being implicit none
) and only after them there is the beginning of the subroutine TP1.
Either organize the procedures in a module and leave the common part before the contains
section (more work with the C++ interoperability will follow if you are a Fortran newbie) or you must include the implicit none
and others in every subroutine separately. Are you sure you even need this if the code worked before?
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.