Correct use of modules, subroutines and functions in Fortran

Seconding and extending what has already been said. It is better to put your procedures (subroutines and functions) into modules and "use" them because them you get automatic consistency checking of the interfaces with little effort. The other ways have drawbacks. If you define the interface with an interface block, then you have three things to maintain instead of two: the interface, the procedure itself and the call. If you make a change, then all three have to be modified to be consistent. If you use a module, only two have to be changed. A reason to use an interface block is if you don't have access to the source code (e.g., pre-compiled library) or the source code is in another language (e.g., you are using C code via the ISO C Binding).

The drawback to the "contains" approach is that contained procedures inherit all of the local variables of the parent program ... which is not very modular and can be very confusing if you forget this "feature".


Modules are always the right thing to use ;-)

If you have a very simple F90 program you can include functions and subroutines in the 'contains' block:

 program simple
   implicit none
   integer :: x, y
   x = ...
   y = myfunc(x)
 contains
   function myfunc(x) result(y)
     implicit none
     integer, intent(in)  :: x
     integer              :: y
     ...
   end function myfunc
 end program

Then the interface of the functions/subroutines will be known in the program and don't need to be defined in an interface block.

For more complex programs you should keep all functions/subroutines in modules and load them when required. So you don't need to define interfaces, either:

 module mymod
   implicit none
   private
   public :: myfunc
 contains
   function myfunc(x) result(y)
     implicit none
     integer, intent(in)  :: x
     integer              :: y
     ...
   end function myfunc
 end module mymod

 program advanced
   use mymod, only: myfunc
   implicit none
   integer :: x, y
   x = ...
   y = myfunc(x)
 end program advanced

The module and the program can (actually should) be in separate files, but the module has to be compiled before the actual program.