Search code examples
functionmodulefortranfortran90subroutine

Correct use of modules, subroutines and functions in Fortran


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?


Solution

  • 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.