Difference between revisions of "Coding Conventions"
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