• HOME
  • PUBLICATIONS
  • RESEARCH INTERESTS
  • CONTACTS
  • Teaching
  • RANDOM WORDS
  • FORTRAN .... OF COURSE!
  • Contents (Fortran)

Basic Usage of external procedures in Fortran: functions & subroutines

28/7/2017

0 Comments

 
(Please, check the content section if interested in Fortran-related topics and maybe subscribe to the newsletter ;-) )
A Fortran main program is contained in between the instructions "program ... end program", according the general scheme:
program ProgramName
implicit none
[variable declaration]
[main body]
end program ProgramName
In principle, we do not need to introduce external procedures called by the main program in order to write a working Fortran code. However, external procedures become highly useful when the main body of the program is made up of different huge subsections. Thus, the idea is to construct a tool, say external_procedure(variable1, variable2,...,variableN), able to recall in the main program a series of complicated instructions written elsewhere. Such technique brings with it many pros:
  • all the instructions contained in external_procedure(variable1, variable2,...,variableN) appear, in the main program, as a single line, thus improving the readability of the main program ;
  • any error in external_procedure(variable1, variable2,...,variableN) can be fixed by working on that procedure only, rather than referring to the whole program, thus improving the debugging ;
  • using external procedures promotes the collaboration between different developers, each one working on a single external procedure. 
From the other hand, when a main program calls an external procedure is typically a bit slower (in terms of the execution time) than the same program where all the procedures are directly written in the main body. However, the gain in using external procedures, justifies their use.

​ In Fortran there are three types of external procedures
  • functions
  • subroutines
  • modules
Functions and subroutines are pretty much the same, in the sense that you might use both of them to code the same subsection of the main program. The difference, typically, is only stylistic and definitively depends on the developer and her/his personal feelings with such external procedures. Personally, I use functions when I am interested in coding functions in the mathematical sense. Thus, for example, if in the main program I need to make a complicated operation on the variable x, which returns me a value f(x), such as, for example
Picture
I code f(x) using a Fortran function. When I need to code entire subprograms, in that cases, I personally use subroutines. The correct way to define functions and subroutines can be found here, where some fully coded examples are discussed. You will also find an example on how to use modules, which, in any case, will be discussed soon on my blog as well ( stay tuned :-) ).

Where should I put external procedures and How do I call them?

Typically external procedures are written before the instruction program ProgramName or after the instruction end program ProgramName. They might be eventually called by the main program or any other external procedure. For example, let us suppose that we are writing the external procedures after the instruction end program ProgramName and we have an external function FuncExtProcedure(Var1,Var2,Var3) and an external subroutine SubExtProcedure(Var1,Var2,Var3) . Our code will look like the following one 
​program ProgramName
implicit none
real*8 
FuncExtProcedure  ! <-- LOOK: HERE I'M DECLARING THE FUNCTION NAME. NO NEED TO
                                               ! DECLARE THE SUBROUTINE. IF YOU ARE NOT CALLING THE                                                                 ! FUNCTION IN THE MAIN PROGRAM, NO NEED TO DECLARE IT

real*8 Var1, Var2, Var3,y
[declaration of other variables]

y = FuncExtProcedure(Var1,Var2,Var3) !function call
call SubExtProcedure(Var1,Var2,Var3) !subroutine call
[main body]
end program ProgramName

function FuncExtProcedure(Var1, Var2, Var3)
implicit none
real*8 
FuncExtProcedure ! <-- LOOK: HERE I'M DECLARING THE FUNCTION NAME.
real*8 Var1, Var2, Var3
[declaration of other (DUMMY) variables]
[function body]
!I MIGHT WANT TO CALL THE SUBROUTINE SubExtProcedure IN THIS FUNCTION, IN SUCH !CASE I JUST CALL IT EXACTLY LIKE IN THE MAIN PROGRAM, I.E.
call SubExtProcedure(Var1,Var2,Var3) !subroutine call
FuncExtProcedure = [SPECIFY THE FINAL VAULE OF YOUR FUNCTION]
return
end function FuncExtProcedure

subroutine SubExtProcedure(Var1, Var2, Var3)
implicit none
real*8
, intent(in):: Var1
real*8, intent(inout):: Var2
real*8, intent(out):: Var3
real*8 FuncExtProcedure ! <-- LOOK: IF I NEED TO CALL THE ABOVE FUNCTION  IN THIS 
                                              !SUBROUTINE, I MUST DECLARE IT.

[declaration of other (DUMMY) variables]
[subroutine body]
return
end subroutine SubExtProcedure
The instruction intent(in):: Var1  tells to the compiler that Var1 is a variable passed by the main program (or any oder external procedure) to the subroutine. The value of VAR1 cannot be changed by the subroutine. If you attempt to change such value in the main body of the subroutine, you'll get an error message from the compiler!!!!!
The instruction intent(inout):: Var2  tells to the compiler that Var2 is a variable which can be either passed by the main program (or any oder external procedure)  or returned by the subroutine as an output of the operations in the main body of the subroutine. The difference with Var1 is that if you pass the initial value of Var2 to the subroutine, that value could be eventually overwritten by the subroutine, if in the main body of the subroutine there's an instruction like Var2 = functionof(Var2), without getting any error from the compiler when you compile. Finally, the instruction intent(out):: Var3 tells to the compiler that Var3 is a variable whose value (the value of the variable and not the variable itself) is not passed by the main program  (or any oder external procedure) to the subroutine, however, it is returned by the subroutine to the main program (or any oder external procedure). This means that Var3 will be evaluated by the subroutine main body using the input variable(s) Var1 or (eventually) the input/output variable(s) Var2. Here we go. Now let's call the above code as Myfile.f and let's compile it with the instruction
gfortran -O3 Myfile.f -o out.x
once the output out.x is ready, we can run it using the instruction ./out.x and that's it: have fun!!! 
0 Comments

Your comment will be posted after it is approved.


Leave a Reply.

    Author

    Personal blog: http://www.giuseppeforte.me/

    Archives

    July 2017

  • HOME
  • PUBLICATIONS
  • RESEARCH INTERESTS
  • CONTACTS
  • Teaching
  • RANDOM WORDS
  • FORTRAN .... OF COURSE!
  • Contents (Fortran)