Correct use of modules, subroutines and functions in Fortran

Pureferret picture Pureferret · Dec 7, 2011 · Viewed 40.5k times · Source

I've recently learnt about interface blocks when adding a function to my Fortran program. Everything works nice and neatly, but now I want to add a second function into the interface block.

Here is my interface block:

interface
    function correctNeighLabel (A,i,j,k)
    integer :: correctNeighLabel
    integer, intent(in) :: i,j,k
    integer,dimension(:,:,:),intent(inout) :: A
    end function

    function correctNeighArray (B,d,e,f)
        character :: correctNeighArray
    integer, intent(in) :: d,e,f
    character, dimension(:,:,:),intent(inout) :: B
    end function
end interface

It appears to me that this may not be the best option.

I've looked into subroutines, but I'm not very confident that it's the right solution. What I'm doing is relatively simple, and I need to pass arguments to the subroutine, but all the subroutines I've seen are a) complicated (i.e. too complicated for a function), and b) don't take arguments. They behave as though they manipulate variables without them being passed to them.

I've not really looked into modules properly, but from what I've seen it's not the right thing to use.

Which should I use when, and how do I go about it best?

Answer

alexurba picture alexurba · Dec 7, 2011

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.