Fortran Can I use a Fortran module for subroutines?

  • Thread starter Thread starter sketos
  • Start date Start date
  • Tags Tags
    Fortran module
Click For Summary
Using Fortran modules for subroutines is effective, but proper compilation is crucial. When compiling, ensure both the module and the main program are included in the command to avoid "undefined reference to main" errors. The correct compilation commands involve either compiling both files together or separately compiling the module and linking it with the main program. Errors like "undefined reference to probks_" indicate that the linker cannot find a required function, possibly due to misspelling or missing libraries. Properly managing module interfaces and ensuring all necessary components are included during compilation is essential for successful execution.
sketos
Messages
55
Reaction score
0
Hello,

I want to create one file test.f95 where i can keep all my subroutines and use them whenever i create a new program
new.f95.

Is the modules the right way to do it?? because when i create a file let's say test.f95 with the module and one other with my main program (new.f95) when i compile test.f95 i get this :

/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status


And if i try to compile my main program (new.f95) i get this:

/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status

My programs are:

test.f95 ::

module module1
integer:: n
contains

recursive subroutine sub1(x)
integer,intent(inout):: x
integer:: y
y = 0
if (x < n) then
x = x + 1
y = x**2
print *, 'x = ', x,', y = ', y
call sub1(x)
print *, 'x = ', x,', y = ', y
end if
end subroutine sub1

end module module1

new.f95 ::

program main
use module1
integer:: x = 0
print *, 'Enter number of repeats'
read (*,*) n
call sub1(x)
end program main
 
Technology news on Phys.org
What commands did you use to compile the programs?

Code:
gfortran new.f95 test.f95
works for me. Or if you want to compile the subroutines separately,
Code:
gfortran -c test.f95
gfortran new.f95 test.o
Maybe the errors are because your IDE doesn't understand what you are doing. (Personally I tend to solve that problem by not using an IDE).
 
  • Like
Likes 1 person
i compile it using : f95 test.f95 -o test --> ./test

f95 new.f95 -o new -->./newThis doesn't work?
 
It doesn't work, because you are not compiling whole project, only part of it. Compiler has no way of knowing where the missing procedures are - you have to tell it explicitly where they are. Either by giving a list of Fortran sources in the command line, or by giving list of sources to compile and objects containing already compiled sources in the "link ready" format.
 
So i have to do it the way AlephZero described?
 
Yes.

It is also possible to use the make utility, then you need to put the information about files in the makefile - but IMHO for small, two file projects it doesn't make sense.
 
  • Like
Likes 1 person
Borek said:
Compiler has no way of knowing where the missing procedures are - you have to tell it explicitly where they are. Either by giving a list of Fortran sources in the command line, or by giving list of sources to compile and objects containing already compiled sources in the "link ready" format.

One extra comment on that: when you compile test.f95, you will create a "module interface file" called module1.mod. When the compiler reads the "use module1" statement in main.f95, it will automatically read module1.mod, or produce an error message if it can't find it. But the .mod file only contains information about the argument lists of the subroutines in the module, so the compiler can check you are calling them correctly. It doesn't contain the compiled code. You also have to tell the compiler to read test.o.

Note, if you have several modules, it is simpler to have the module name the same as the source file name, so the code for "module1" is in module1.f95, and compiling it creates module1.mod and module1.o.

Also, the Fortran 95 standard doesn't say how the module interface information should be stored, and some Fortran systems do store the module interface definition and the compiled code in the same file. But gfortan doesn't do that.
 
  • Like
Likes 1 person
sketos said:
i compile it using : f95 test.f95 -o test --> ./test

This doesn't work because 'test' does not contain a main program.

f95 new.f95 -o new -->./new

This doesn't work because, although 'new' does contain a main program, it does not contain the subroutine 'sub1'.

If you use the command:

f95 new.f95 test.f95 -o new

this should compile both source files, and link (combine) the output into 'new' which should be a complete executable program that you can run via the commad './new'.

Or, if you want to do the compiling and linking separately for some reason, you can do this:

f95 new.f95 -o new.o (creates a file 'new.o' which contains the compiled main program)
f95 test.f95 -o test.o (creates a file 'test.o' which contains the compiled module with the subroutine)
f95 new.o test.o -o new (links the two '.o' files and places the result in the executable 'new')
 
  • Like
Likes 1 person
Thank you all guys.

I have one last question:

When i compile my main program with the module (which contains one function and 2 subroutines) i get the following error:

/tmp/ccToz1RS.o: In function `__statistictests_MOD_kstwo':
StatiTests.f95:(.text+0x208): undefined reference to `probks_'
collect2: ld returned 1 exit status

are you guys familiar with what that means?? (my function name in probks and the module name is statistictests)
 
  • #10
Without seeing the code, and exactly what you did to compile it, we are just guessing.
 
  • #11
sketos said:
StatiTests.f95:(.text+0x208): undefined reference to `probks_'
collect2: ld returned 1 exit status

'ld' is the "linker" utility that f95 (and most other compilers on Unix-like systems) uses to link compiled modules together into an executable program. The error message means that your program wants to use something named 'probks_', and 'ld' can't find it. It's probably a subroutine or function named 'probks' (with the compiler adding the '_' internally).

I can offer two guesses: (1) You've simply misspelled the name of one of your own subroutines when you call it. (2) Your program uses a subroutine or function named 'probks' from a third-party library, and you didn't specify the library when you tried to compile the program.

If it's (2), how you specify the library in the compilation command depends on how and where it's installed on your system.
 
  • #12
MY FILE ( StatiTests.f95) WHICH CONTAINS THE MODULE:

module StatisticTests

implicit none
contains

SUBROUTINE kstwo(data1,n1,data2,n2,d,prob)
INTEGER n1,n2
REAL d,prob,data1(n1),data2(n2)
!CU USES probks,sort
INTEGER j1,j2
REAL d1,d2,dt,en1,en2,en,fn1,fn2,probks
call sort(n1,data1)
call sort(n2,data2)
en1=n1
en2=n2
j1=1
j2=1
fn1=0.
fn2=0.
d=0.
1 if(j1.le.n1.and.j2.le.n2)then
d1=data1(j1)
d2=data2(j2)
if(d1.le.d2)then
fn1=j1/en1
j1=j1+1
endif
if(d2.le.d1)then
fn2=j2/en2
j2=j2+1
endif
dt=abs(fn2-fn1)
if(dt.gt.d)d=dt
goto 1
endif
en=sqrt(en1*en2/(en1+en2))
prob=probks((en+0.12+0.11/en)*d)
return
END

FUNCTION probks(alam)
REAL probks,alam,EPS1,EPS2
PARAMETER (EPS1=0.001, EPS2=1.e-8)
INTEGER j
REAL a2,fac,term,termbf
a2=-2.*alam**2
fac=2.
probks=0.
termbf=0.
do 11 j=1,100
term=fac*exp(a2*j**2)
probks=probks+term
if(abs(term).le.EPS1*termbf.or.abs(term).le.EPS2*probks)return
fac=-fac
termbf=abs(term)
11 continue
probks=1.
return
END SUBROUTINE sort(n,arr)
INTEGER n,M,NSTACK
REAL arr(n)
PARAMETER (M=7,NSTACK=50)
INTEGER i,ir,j,jstack,k,l,istack(NSTACK)
REAL a,temp
jstack=0
l=1
ir=n
1 if(ir-l.lt.M)then
do 12 j=l+1,ir
a=arr(j)
do 11 i=j-1,1,-1
if(arr(i).le.a)goto 2
arr(i+1)=arr(i)
11 continue
i=0
2 arr(i+1)=a
12 continue
if(jstack.eq.0)return
ir=istack(jstack)
l=istack(jstack-1)
jstack=jstack-2
else
k=(l+ir)/2
temp=arr(k)
arr(k)=arr(l+1)
arr(l+1)=temp
if(arr(l+1).gt.arr(ir))then
temp=arr(l+1)
arr(l+1)=arr(ir)
arr(ir)=temp
endif
if(arr(l).gt.arr(ir))then
temp=arr(l)
arr(l)=arr(ir)
arr(ir)=temp
endif
if(arr(l+1).gt.arr(l))then
temp=arr(l+1)
arr(l+1)=arr(l)
arr(l)=temp
endif
i=l+1
j=ir
a=arr(l)
3 continue
i=i+1
if(arr(i).lt.a)goto 3
4 continue
j=j-1
if(arr(j).gt.a)goto 4
if(j.lt.i)goto 5
temp=arr(i)
arr(i)=arr(j)
arr(j)=temp
goto 3
5 arr(l)=arr(j)
arr(j)=a
jstack=jstack+2
if(jstack.gt.NSTACK)pause
if(ir-i+1.ge.j-l)then
istack(jstack)=ir
istack(jstack-1)=i
ir=j-1
else
istack(jstack)=j-1
istack(jstack-1)=l
l=i
endif
endif
goto 1
ENDend module StatisticTests

AND MY MAIN PROGRAM:

program main

use StatisticTests

implicit none

integer i,n1,n2,n3
real pi,HI,Mfof,RA,DE,Vcdm,CDz
parameter(pi=3.1415,n1=3071,n2=1032,n3=2005)
real Z_obs1(n1),Z_obs2(n2),Z_obs3(n3)
real d12,d23,d31,prob12,prob23,prob31
open(unit=1,file="halo_cone_mock_lcdmw5_c2592_n1024.dat",status="old")
open(unit=2,file="halo_cone_mock_rpcdmw5_c2592_n1024.dat",status="old")
!n1=3071 !# of data-points for the ΛCDM
!n2=1032 !# of data-points for the RPCDMdo i=1,n1
read(1,*) HI,Mfof,Z_obs1(i),RA,DE,Vcdm,CDz !Read data of ΛCDM
end do

do i=1,n2
read(2,*) HI,Mfof,Z_obs2(i),RA,DE,Vcdm,CDz !Read data of RPCDM
end do

call kstwo(Z_obs1,n1,Z_obs2,n2,d12,prob12)

print*,"The KS two-sample test fot the LCDM-RPCDM"
print*,
print*,d12,prob12

end program

FOR THE COMPLILE : f95 main.f95 StatiTests.f95 -o new

sorry for the long post :)
 
  • #13
Suggestion for the OP: When posting source code, please use the
Code:
 tags around the source statements.  The [CODE] tags help preserve the formatting of the source file, which is lost if it is inserted directly into the Reply Box.
 
  • #14
I don't understand this yet.

If you remove the use of modules, the error message goes away.

But this minimal example compiles and runs OK:

Code:
program test

use mymod

call sub(x)
print *,x
end

Code:
module mymod

contains

subroutine sub(y)
x = 10
y = func(x)
end

function func(x)
func = 42 + x
end

end module mymod

One way to solve the mystery would be to add one thing at a time to the working example until it stop working, and then figure out why.
 
  • Like
Likes 1 person
  • #15
I've never used modules, but can you use 'implicit none' at the beginning of a module? I've always used it at the beginning of each subroutine or function.
 
  • #16
I never used IMPLICIT NONE that way either, but that's not the problem.

It seems like the compiler thinks you have declared probks twice: once by writing the actual function, and again in subroutine kstwo when you say

Code:
REAL d1,d2,dt,en1,en2,en,fn1,fn2,probks
If you change that line to
Code:
REAL d1,d2,dt,en1,en2,en,fn1,fn2
it compiles and links OK.

You can make my trivial example fail the same way, without IMPLICIT NONE. This fails:
Code:
module mymod

contains

subroutine sub(y)
real x, y, func
x = 10
y = func(x)
end

function func(x)
real func, x
func = 42 + x
end

end module mymod
but this works:
Code:
...
subroutine sub(y)
real x, y
...
I don't understand this. IMO either this is a very obscure feature of Fortran 95, or else it's a compiler bug. But at least we now know what to do about it!

Note, in F95 you can write "overloaded functions" similar to C++, where you have several functions with the same name and the compiler calls the correct one based on the type of the parameters passed to it. Maybe the "failed" version is somehow declaring two different functions with the sane name, but of course the link editor can only find one so it gives an error about the other one. But the "proper" way to use overloaded functions is write your own "interface" block between the "module" and "contains" statements, not let it happen by default. :confused:
 
Last edited:
  • #17
I am truly thankful to you man !
 

Similar threads

  • · Replies 59 ·
2
Replies
59
Views
11K
  • · Replies 20 ·
Replies
20
Views
3K
  • · Replies 8 ·
Replies
8
Views
4K
  • · Replies 2 ·
Replies
2
Views
2K
  • · Replies 1 ·
Replies
1
Views
1K
  • · Replies 5 ·
Replies
5
Views
4K
Replies
3
Views
3K
  • · Replies 22 ·
Replies
22
Views
5K
  • · Replies 3 ·
Replies
3
Views
22K
  • · Replies 1 ·
Replies
1
Views
2K