==== 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.