==== Focus Manuals: Programing Guide: Features of Fortran 90 used in BIEF ==== links from [[:programing_guide|Programing Guide]] \\ \\ We briefly explain hereafter features of Fortran90 that are used in BIEF. For more detailed explanations please refer to a proper Fortran 90 book, such as ref.[5]. === Structures === Fortran 77 only recognises integers, real numbers, boolean and character strings. Fortran 90 can be used to create structures. The following is an example of the creation of a ''**point**'' type structure composed of two real numbers, and a ''**circle**'' structure, composed of a ''**centre**'' and a ''**radius**'': TYPE point REAL :: x,y END TYPE TYPE circle TYPE(point) :: centre REAL :: radius END TYPE It can be observed that the ''**centre**'' is itself a structure of a type previously defined. Once the structure has been defined, objects of this type can be declared: TYPE(circle) :: ROND ''**ROND**'' will be a ''**circle**'' with its ''**centre**'' and ''**radius**''; the latter are obtained thanks to the %"component selector". Thus the radius of ROND will be the real ''**ROND%radius**''. === Pointers === Pointers are well known in C language, but are notably different in Fortran 90. Pointers in Fortran 90 may be used as pointers as in C but also as aliases. Unlike C, they are not mere addresses pointing to somewhere in the computer memory. The target must be defined precisely, for example the line: REAL, POINTER, DIMENSION(:) :: X will define a pointer to a one-dimensional real array, and it will be impossible to have it pointing to an integer nor even to a 2-dimensional array. This pointer ''**X**'' will have then to be pointed to a target by the statement: X => Y were ''**Y**'' is an already existing one-dimensional real array. Then ''**X**'' can be used as if it were ''**Y**'', it is thus an alias. ''**X**'' can be also directly allocated as a normal array by the statement: ALLOCATE(X(100)) to have (for example) an array of 100 values. In this case ''**X**'' and its target have the same name. A well known problem in Fortran 90 is the fact that arrays of pointers do not exist. To overcome this problem, one has to create a new structure which is itself a pointer, and to declare an array of this new structure. This is done for blocks, which are lists of pointers to ''**BIEF_OBJ**'' structures. === Modules === Modules are like ''**INCLUDE**'' statements, but are more clever, so that ''**INCLUDE**'' should now always be avoided. As a matter of fact, modules can be used to define global variables that will be accessible to all routines. With the following module: MODULE EXAMPLE INTEGER EX1,EX2,EX3,EX4 END MODULE EXAMPLE all the subroutines beginning with the statement ''**USE EXAMPLE**'' will have access to the same numbers ''**EX1**'', ... ''**EX4**''. With ''**INCLUDE**'' statements, it would be only local variables without link to ''**EX1**'',... declared in other subroutines. Modules will thus be used to define global variables that will be accessed via a ''**USE**'' statement. If only one or several objects must be accessed, the ''**ONLY**'' statement may be used, as in the example below: USE EXAMPLE, ONLY : EX1,EX2 This will enable to avoid name conflicts and secures programming. Modules are also used to store interfaces that will be shared between several subroutines (see paragraph below). === Interfaces === Interfaces are a mean given to the compiler to check arguments of subroutines even if it has no access to them. For example, the following interface: INTERFACE LOGICAL FUNCTION EOF(LUNIT) INTEGER, INTENT(IN) :: LUNIT END FUNCTION END INTERFACE says that function ''**EOF**'' has one integer argument. ''**INTENT(IN)**'' indicates that argument ''**LUNIT**'' is not changed. Interfaces of all BIEF subroutines have been put in a single module called ''**BIEF**''. A ''**USE BIEF**'' statement at the beginning of a subroutine will prompt the compiler to check the arguments and also do some optimisations in view of the ''**INTENT**'' information (which can be ''**IN**'', ''**OUT**'', or ''**INOUT**'' depending on the use of the argument). If a function is declared in an interface, it must not be declared as an ''**EXTERNAL FUNCTION**''. === Interface operator === New operations on structures could also be defined with the ''**INTERFACE OPERATOR**'' statement. For example a sum of two vectors as stored in BIEF could be defined so that the line: CALL OS('X=Y ',U,V,V,0.D0) could be replaced by: U=V Such interface operators have not been done in version 6.0, because operations like ''**U = A+B+C**'' would probably not be optimised and would trigger a number of unnecessary copies. === Optional parameters === Subroutines may now have optional parameters. Thanks to this new feature, subroutines ''**OS**'' and ''**OSD**'' of previous releases have been grouped in a single one. Hereafter is given the interface of new subroutine ''**OS**'': INTERFACE SUBROUTINE OS( OP, X , Y , Z , C , IOPT , INFINI , ZERO ) USE BIEF_DEF INTEGER, INTENT(IN), OPTIONAL :: IOPT DOUBLE PRECISION, INTENT(IN), OPTIONAL, INFINI, ZERO TYPE(BIEF_OBJ), INTENT(INOUT), OPTIONAL :: X TYPE(BIEF_OBJ), INTENT(IN), OPTIONAL :: Y,Z DOUBLE PRECISION, INTENT(IN), OPTIONAL :: C CHARACTER(LEN=8), INTENT(IN) :: OP END SUBROUTINE END INTERFACE Subroutine ''**OS**'' performs on structure ''**X**'' the operation given in ''**OP**'', e.g. CALL OS('X=0 ',X=TRA01) or: CALL OS('X=Y ',X=TAB1,Y=TAB2) Parameters ''**Y**'',''**Z**'' and ''**C**'' are used only for specific operations and otherwise are not necessary. When a parameter is missing and to avoid ambiguity, the parameters must be named, hence the X=TRA01 in the example above. Parameters ''**IOPT**'', ''**INFINI**'' and ''**ZERO**'' stem from the old subroutine ''**OSD**'' and are used only when a division is implied in the operation asked, for example if """OP = 'X=Y/Z '""". These 3 parameters are now optional. When they are present, it is better to name them as is done in the following line: CALL OS('X=Y/Z ',U,V,W,0.D0,IOPT=2,INFINI=1.D0,ZERO=1.D-10) The use of optional parameters will enable a better compatibility between different versions because it will be possible to add a new parameter as an optional one. Optional arguments will be written between brackets [] in argument lists in the rest of the document.