Can I use a Fortran module for subroutines?

  • Context: Fortran 
  • Thread starter Thread starter sketos
  • Start date Start date
  • Tags Tags
    Fortran module
Click For Summary

Discussion Overview

The discussion revolves around the use of Fortran modules for organizing subroutines and the compilation process involved in linking these modules with main programs. Participants explore the correct methods for compiling Fortran files that include modules and subroutines, addressing errors encountered during compilation.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Mathematical reasoning

Main Points Raised

  • One participant seeks to understand if using a module is appropriate for storing subroutines in a separate file for reuse in different programs.
  • Another participant suggests compiling both the module and the main program together or separately compiling the module first and then linking it with the main program.
  • Some participants mention that the compiler needs to be explicitly told where to find the subroutines, either by listing all source files or by linking compiled object files.
  • A participant raises a question about an error related to an undefined reference to a function, speculating it could be due to a misspelling or a missing library.
  • Another participant provides insight into the linker error, explaining that it indicates the program is trying to use a function that cannot be found, possibly due to a missing library or incorrect function name.
  • One participant shares their module code and asks for help regarding an error encountered during compilation, indicating a potential issue with the function definition or linking.

Areas of Agreement / Disagreement

Participants generally agree on the need to compile and link both the module and the main program together, but there are differing opinions on the best practices for managing this process, especially regarding the use of IDEs versus command-line compilation.

Contextual Notes

Some participants note that the Fortran compiler may handle module interface files differently, and there are variations in how module information is stored across different Fortran systems. Additionally, the discussion includes unresolved aspects regarding the specific error messages related to undefined references and how to address them.

Who May Find This Useful

This discussion may be useful for Fortran programmers, particularly those working with modules and subroutines, as well as individuals encountering compilation and linking issues in their projects.

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   Reactions: 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   Reactions: 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   Reactions: 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   Reactions: 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   Reactions: 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 20 ·
Replies
20
Views
3K
  • · Replies 59 ·
2
Replies
59
Views
12K
  • · Replies 8 ·
Replies
8
Views
4K
  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 2 ·
Replies
2
Views
3K
  • · 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