Difference between revisions of "Coding Conventions"

From LIBISIS
Jump to navigation Jump to search
 
Line 1: Line 1:
 +
A good place to start is [http://www.meto.gov.uk/research/nwp/numerical/fortran90/f90_standards.html]
 +
 +
==Object Oriented Design==
 +
We will be making use of object oriented concepts to assist with code structure. In this methodology an object and functions which operate on it are bound together in a unit and a select known number of them exposed. In general the object data is not exposed outside of the object itself and must be accessed via functions – this “encapsulation” allows for the internals of the object to be modified later and only a known set of access functions need to be maintained.
 +
 +
With this in mind we will use the FORTRAN90 module as our basic class/object unit. A single module will implement methods for a single data type – in our naming convention type IXTsomething will be defined, along with its methods, in the module IXMsomething contained in file IXMsomething.f90 Though the IXTdata type itself will be public, its internal members should be declared private and thus accessible only via module functions in the IXMsomething module. These modules should be “binding neutral” i.e. they should not refer to MATLAB – separate IXB binding functions will be declared outside of each module to retrieve data to/from the appropriate source. Function that interface between Matlab and FOTRAN will end in the “_m” suffix; other suffices will be defined later as appropriate
 +
==Preprocessing==
 +
Often you end up writing essentially the same function several times, but changing only one small part (e.g. real for integer or :,: for : ) - one way to get round this is by using a pre-processor. Essentially a pre-processor is “language neutral” and defines a set of text substitutions that should be performed prior to compiling. We are using the C pre-processor as it is called automatically by all the FORTRAN compilers. Substitutions are declared by using a #define command and files for substitutioninserted using #include e.g.
 +
<pre>
 +
#define IXD_NAME testclass
 +
#include “some_file.f90”
 +
</pre>
 +
will insert the file “some_file.f90” at the current place in the program, but replacing all instances of IXD_NAME within it with the word “testclass”. We will always prefix variables to be substituted with IXD_ so they are easy to spot. In general we will use
 +
* IXD_NAME for a derived data type (class) name with the IXT prefix removed
 +
* IXD_TYPE for a fortran basic data type (real, integer etc)
 +
* IXD_DIMS for a fortran array dimension specifier (e.g. : or :,: )
 +
Whitespace can get added or removed in funny ways around pre-processor constants – as the Intel compiler does not support concatenation of these tokens, you will see use of the FORTRAN & line continuation character in the included files e.g.
 +
<pre>
 +
call IXFfunc_&
 +
IXD_NAME
 +
</pre>
 +
Will  produce, after pre-processing, the line
 +
<pre>
 +
Call IXFfunc_&
 +
                                    Testclass
 +
</pre>
 +
Which is treated by the compiler as
 +
<pre>
 +
Call IXFfunc_testclass
 +
</pre>
 +
 
==Subroutines Arguments==
 
==Subroutines Arguments==
  

Revision as of 09:09, 23 January 2007

A good place to start is [1]

Object Oriented Design

We will be making use of object oriented concepts to assist with code structure. In this methodology an object and functions which operate on it are bound together in a unit and a select known number of them exposed. In general the object data is not exposed outside of the object itself and must be accessed via functions – this “encapsulation” allows for the internals of the object to be modified later and only a known set of access functions need to be maintained.

With this in mind we will use the FORTRAN90 module as our basic class/object unit. A single module will implement methods for a single data type – in our naming convention type IXTsomething will be defined, along with its methods, in the module IXMsomething contained in file IXMsomething.f90 Though the IXTdata type itself will be public, its internal members should be declared private and thus accessible only via module functions in the IXMsomething module. These modules should be “binding neutral” i.e. they should not refer to MATLAB – separate IXB binding functions will be declared outside of each module to retrieve data to/from the appropriate source. Function that interface between Matlab and FOTRAN will end in the “_m” suffix; other suffices will be defined later as appropriate

Preprocessing

Often you end up writing essentially the same function several times, but changing only one small part (e.g. real for integer or :,: for : ) - one way to get round this is by using a pre-processor. Essentially a pre-processor is “language neutral” and defines a set of text substitutions that should be performed prior to compiling. We are using the C pre-processor as it is called automatically by all the FORTRAN compilers. Substitutions are declared by using a #define command and files for substitutioninserted using #include e.g.

	#define IXD_NAME	testclass
	#include “some_file.f90”

will insert the file “some_file.f90” at the current place in the program, but replacing all instances of IXD_NAME within it with the word “testclass”. We will always prefix variables to be substituted with IXD_ so they are easy to spot. In general we will use

  • IXD_NAME for a derived data type (class) name with the IXT prefix removed
  • IXD_TYPE for a fortran basic data type (real, integer etc)
  • IXD_DIMS for a fortran array dimension specifier (e.g. : or :,: )

Whitespace can get added or removed in funny ways around pre-processor constants – as the Intel compiler does not support concatenation of these tokens, you will see use of the FORTRAN & line continuation character in the included files e.g.

	call IXFfunc_&
 			 IXD_NAME

Will produce, after pre-processing, the line

	Call IXFfunc_&
                                     Testclass

Which is treated by the compiler as

	Call IXFfunc_testclass

Subroutines Arguments

Subroutines arguments should be arranged in the order:

mandatory [in] (input only) arguments, followed by
mandatory [inout] (input and output) arguments, followed by
mandatory [out] (output) arguments, followed by
optional  [in] (input only) arguments, followed by
optional  [inout] (input and output) arguments, followed by
optional  [out] (output) arguments

These should them be declared in separate blocks and commented as follows

subroutine test(arg1, arg2, arg3, arg4, arg5, arg6)
implicit none
! Mandatory input arguments
integer(i4b) , intent(in) :: arg1 !! description of arg1
! Mandatory input/output arguments
integer(i4b) , intent(inout) :: arg2 !! description of arg2
! Mandatory output arguments
integer(i4b) , intent(out) :: arg3 !! description of arg3
! Optional input arguments
integer(i4b) , intent(in) :: arg4 !! description of arg4
! Optional input/output arguments
integer(i4b) , intent(inout) :: arg5 !! description of arg5
! Optional output arguments
integer(i4b) , intent(out) :: arg6 !! description of arg6

Nore that we use !! on the variable description so that is it picked up by F90DOC