I've recently learnt about tinterface 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, 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?
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:
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:
The module and the program can (actually should) be in separate files, but the module has to be compiled before the actual program.
alexurba's and MSB's answers are correct and useful as usual; let me just flesh out a little more detail on one point - if modules are the way to go (and they are), what are interfaces for at all?
For functions and subroutines in modules, anything that
use
s that module can automatically see those interfaces; the interfaces are generated when the module is compiled (that information, amongst other things, goes into the .mod file that's generated when you compile a module). So you don't need to write it yourself. Similarly, when you use aCONTAIN
ed subprogram (which, agreeing with MSB, I find more confusing then helpful - they're much better thought of as closures or nested subroutines than external subroutines), the main program can already 'see' the interface explicitly and it doesn't need you to write it out for it.Interface blocks are for when you can't do this - when the compiler isn't able to generate the explicit interface for you, or when you want something different than what is given. One example is when using C-Fortran interoperability in Fortran 2003. In that case, the Fortran code is linking against some C library (say) and has no way of generating a correct fortran interface to the C routine for you -- you have to do it yourself, by writing your own interface block.
Another example is when you do already know the interfaces to subroutines, but when you want to create a new interface to "hide" the subroutines behind - for instance, when you have one routine that operates on (say) integers, and one on reals, and you want to be able to call the same routine name on either and let the compiler sort it out based on the arguments. Such constructs are called generic routines and have been around since Fortran 90. In that case, you create an interface explicitly to this new generic routine, and list the interfaces to the "real" routines within that interface block.
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".