Should I use a Fortran module?

In summary, you want to create one file, test.f95, where you can keep all your subroutines and use them whenever you create a new program. However, when you compile test.f95, you get this error: undefined reference to 'main'.
  • #1
sketos
56
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
  • #2
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
  • #3
i compile it using : f95 test.f95 -o test --> ./test

f95 new.f95 -o new -->./newThis doesn't work?
 
  • #4
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.
 
  • #5
So i have to do it the way AlephZero described?
 
  • #6
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
  • #7
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
  • #8
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
  • #9
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 !
 

1. Should I use a Fortran module for my project?

It depends on the specific needs and requirements of your project. Fortran modules can be useful for organizing and reusing code, but they may not be necessary for all projects. Consider the size and complexity of your code, as well as the potential benefits and drawbacks of using a module.

2. What are the advantages of using a Fortran module?

Fortran modules can help with code organization and reuse, making it easier to maintain and update your code. They also allow for better encapsulation and data hiding, which can improve code reliability and protect against unintentional changes.

3. Are there any disadvantages to using a Fortran module?

One potential disadvantage is that modules can add complexity to your code, especially if you are not familiar with their use. Additionally, modules may not be necessary for smaller or simpler projects, and their use may not be worth the added effort and time.

4. Can a Fortran module improve the performance of my code?

In some cases, using a Fortran module can improve the performance of your code. By organizing and reusing code, you may be able to reduce the overall execution time of your program. However, the impact on performance will depend on the specific implementation and use of the module.

5. Are there any alternatives to using a Fortran module?

Yes, there are alternative approaches to organizing and reusing code in Fortran, such as subroutines and functions. These may be simpler to implement and may be more appropriate for smaller projects. Ultimately, the best approach will depend on the specific needs and goals of your project.

Similar threads

  • Programming and Computer Science
Replies
1
Views
1K
  • Programming and Computer Science
Replies
20
Views
1K
  • Programming and Computer Science
2
Replies
59
Views
9K
  • Programming and Computer Science
Replies
8
Views
3K
  • Engineering and Comp Sci Homework Help
Replies
2
Views
2K
Replies
2
Views
2K
  • Engineering and Comp Sci Homework Help
Replies
5
Views
1K
  • Programming and Computer Science
Replies
22
Views
4K
  • Programming and Computer Science
Replies
1
Views
2K
  • Programming and Computer Science
Replies
4
Views
6K
Back
Top