[ previous ] [ Contents ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ] [ 11 ] [ 12 ] [ 13 ] [ next ]

# `Fortran 90` Lessons for Computational Chemistry Chapter 8 - Subprograms (I): FUNCTIONS

## 8.1 Objectives

The main aims of this lesson are the following:

1. presenting the advantages of using functions, subroutines and modules.

1. presenting the function concept in `Fortran`.

1. showing the different types of functions: intrinsic, generic, elemental, transformational, and internal.

1. making possible the definition of new functions by the user.

1. evinving the difference beyween external and internal functions.

The use of subporgrams allows a more structured and efficient programming owing to

• the possibility of developing and testing different subtasks in an independent manner.

• it makes possible to recycle subprograms in different programs, diminishing the necessary time for coding.

• the isolation in different subtasks of possible errors and the minimization of unexpected side effects, due to variable encapsulation.

## 8.2 Main items.

We first focus in functions and will follow with subroutines and modules.

• General characteristics of functions.

The main characteristics of a function are:

• May require the input of one or several arguments.

• Arguments can take the form of an expression.

• In general, a function produces a single output, which is a function of the arguments, and this output is of scalar type though in some cases it also can be of an array type.

• The arguments can be of different types.

There are more than one hundred predefined functions in `Fortran`, highly tested, and of easy usage. E.g. we need trigonometric functions we can make use of the following:

• Y = SIN(X)

• Y = COS(X)

• Y = TAN(X)

where X and Y are real variables[10]

This predefined functions are called intrinsic functions. In this link `URL` you can find a complet list of the intrinsic functions at your disposal with the `gfortran` compiler.

In general intrinsic functions are also generic, which means that they can admit different argument types, with the exception of the functions LGE, LGT, LLE, and LLT.

• Elemental functions may have as an argument both scalars or vectors. The example source codes excode_8_1.f90, Section 8.3.1 and excode_8_2.f90, Section 8.3.2 show the elemental and generic character of some intrinsic functions. When an elemental function is applied to an array the fucntions is applied to each array element.

• Other type of functions are of inquiry type, giving information about the characterictics of an array, e.g. the SIZE and ALLOCATED functions. Examples of the latter are found in excode_6_7.f90, Section 6.3.7 and excode_9_3.f90, Section 9.3.3.

Transformational functions transform between different data types, e.g. REAL and TRANSPOSE, or functions that work with time data variables as SYSTEM_CLOCK and DATE_AND_TIME.

• Conversion between data types:

• REAL(i): integer i is converted to a float. The argument i can be an integer, a double precision real or a complex number.

• INT(x): transforms the real variable x to an integer, truncating the decimal part. No rounding is performed. The x variable can be a real, double precision real, or a complex variable.

• The functions that follow allow to transform from real to integer values with an adequate control:

• CEILING(x): real value x to the minimum integer value larger than or equal than x.

• FLOOR(x): real value x to the maximum integer value less than or equal than x.

• NINT(x): round the real value x to the nearest integer.

• DBLE(a): transforms a to double precision. The argument can be integer, real, or complex.

• CMPLX(x) or CMPLX(x,y): transform to complex values, where the second argument is the imaginary part.

• Apart from the intrinsic functions, user defined functions can also be added. The definition of a function requires, apart from the function definition, the way the function is invoked from a program.

A user defined function is created according to the following scheme.

```     FUNCTION fun_name(argument_list)
IMPLICIT NONE
Declaration section (including arguments and fun_name)
....
Local variables declaration
....
fun_name = expr
RETURN ! Optional
END FUNCTION fun_name
```

The example Programa ejemplo_8_3.f90, Section 8.3.3 shows how to define and invoke a function computing the greatest common divisor of two integers. The following considerations should be taken into account:

• This example is built with two blocks, the main program and the function definition. bloque con el programa principal y un segundo bloque donde se define la función. The function definition can be carried out in a separate file. In such case both filenames should be provided to the compiler.

• The variables defined in a function are local with respect to the main program variables.

• The MCD function is of INTEGER type. Therefore, in principle, the function output should be of integer type.

• The INTENT(IN) attribute characterizing the A and B variables:

```     INTEGER , INTENT(IN) :: A,B
```

marks these two as input variables, whose values cannot be modified in the body of the function.

Every function argument needs to be difined with the INTENT(IN) attribute to avoid the modification of their values with unforeseen consequences.

## 8.3 Example Codes

### 8.3.1 excode_8_1.f90

```     PROGRAM ex_8_1
IMPLICIT NONE
! Variable Definition
INTEGER, PARAMETER :: Long=SELECTED_REAL_KIND(18,310)
!
REAL (KIND=Long), PARAMETER :: DPI = ACOS(-1.0_Long) ! Pi number double precision
!
REAL, PARAMETER :: PI = ACOS(-1.0) ! Pi number single precision
!
PRINT*, 'ANGLE INPUT (Degrees)'
PRINT*
!
PRINT*
PRINT*
!
PRINT*
!
20 FORMAT (1X, 'An angle of ',F14.8,' degrees = ', F14.8, ' rad. (dp)')
21 FORMAT (1X, 'An angle of ',F14.8,' degrees = ', F14.8, ' rad. (sp)')
22 FORMAT (1X, 'ANGLE ',F14.8,', SIN = ', F13.9, ', COS =',F13.9,/'SIN**2+COS**2 = ', F18.14, ', 1 - SIN**2+COS**2 = ', F18.14)
END PROGRAM EX_8_1
```

### 8.3.2 excode_8_2.f90

```     PROGRAM ex_8_2
IMPLICIT NONE
! VARIABLE DEFINITION
INTEGER , PARAMETER :: NEL=5
REAL, PARAMETER :: PI = ACOS(-1.0) ! Pi number
REAL, DIMENSION(1:NEL)   :: XR = (/ 0.0, PI/2.0, PI, 3.0*PI/2.0, 2.0*PI/)
INTEGER , DIMENSION(1:NEL):: XI = (/ 0, 1, 2, 3, 4/)
!
PRINT*, 'Sin  ', XR, ' = ', SIN(XR)
PRINT*, 'LOG10  ', XR, ' = ', LOG10(XR)
PRINT*, 'REAL ', XI, ' = ', REAL(XI)
END PROGRAM ex_8_2
```

### 8.3.3 Programa ejemplo_8_3.f90

```     PROGRAM ex_8_3
IMPLICIT NONE
INTEGER :: I,J,Result
INTEGER :: MCD
EXTERNAL MCD
PRINT *,' INTRODUCE TWO INTEGERS:'
RESULT = MCD(I,J)
PRINT *,' THE GREATEST COMMON DIVISOR OF ',I,' AND ',J,' IS ',RESULT
END PROGRAM ex_8_3
!
INTEGER FUNCTION MCD(A,B)
IMPLICIT NONE
INTEGER , INTENT(IN) :: A,B
INTEGER :: Temp
IF (A < B) THEN
Temp=A
ELSE
Temp=B
ENDIF
DO WHILE ((MOD(A,Temp) /= 0) .OR. (MOD(B,Temp) /=0))
Temp=Temp-1
END DO
MCD=Temp
END FUNCTION MCD
```

### 8.3.4 Programa ejemplo_8_4.f90

```     PROGRAM ex_8_4
IMPLICIT NONE
! Internal function example:
! E(v) = we (v+1/2) - wexe (v+1/2)**2.
INTEGER :: V, VMAX
REAL :: we, wexe, Energy
PRINT *,' Vmax?:'
PRINT *,' we and wexe?'
DO V = 0, VMAX
Energy = FEN(V)
PRINT 100, V, Energy
ENDDO
100 FORMAT(1X,'E(',I3,') = ',F14.6)
CONTAINS
!
REAL FUNCTION FEN(V)
IMPLICIT NONE
INTEGER , INTENT(IN) :: V
FEN = we*(V+0.5)-wexe*(V+0.5)**2
END FUNCTION FEN
!
END PROGRAM EX_8_4
```

### 8.3.5 excode_8_5.f90

```     PROGRAM ex_8_5
!
! Simple program to compute the prime divisors of a given integer number.
!
IMPLICIT NONE
INTEGER :: NUMVAL
INTEGER :: NUM
!
!
DO
NUM = QUOT(NUMVAL)
IF (NUM == NUMVAL) THEN
PRINT*, NUM
EXIT
ELSE
PRINT*, NUMVAL/NUM, NUM
NUMVAL = NUM
ENDIF
ENDDO
!
CONTAINS
!
INTEGER FUNCTION QUOT(NUM1)
!
INTEGER, INTENT(IN) :: NUM1
INTEGER :: I
!
QUOT = NUM1
!
DO I = 2, NUM1-1
IF (MOD(NUM1,I) == 0) THEN
QUOT = NUM1/I
EXIT
ENDIF
ENDDO
!
END FUNCTION QUOT
!
END PROGRAM ex_8_5
```

### 8.3.6 excode_8_6.f90

```     PROGRAM ex_8_6
!
! Program to evaluate a 1D potential function on grid points
!
IMPLICIT NONE
!
REAL, DIMENSION(:), ALLOCATABLE :: X_grid, Pot_grid
!
REAL :: X_min, X_max, Delta_X
REAL :: V_0 = 10.0, a_val = 1.0
INTEGER :: Index, X_dim
INTEGER :: Ierr
!
!
INTERFACE Potf
ELEMENTAL FUNCTION Potf(Depth, Inv_length, X)
!
IMPLICIT NONE
!
REAL, INTENT(IN) :: Depth, Inv_length, X
REAL :: Potf
!
END FUNCTION Potf
END INTERFACE Potf
!
!
READ(*,*), X_min, X_max, X_dim ! input minimum and maximum values of X and number of points
!
ALLOCATE(X_grid(1:X_dim), STAT = Ierr)
IF (Ierr /= 0) THEN
STOP 'X_grid allocation failed'
ENDIF
!
ALLOCATE(Pot_grid(1:X_dim), STAT = Ierr)
IF (Ierr /= 0) THEN
STOP 'Pot_grid allocation failed'
ENDIF
!
!
Delta_X = (X_max - X_min)/REAL(X_dim - 1)
!
X_grid = (/ (Index, Index = 0 , X_dim - 1 ) /)
X_grid = X_min + Delta_X*X_grid
!
Pot_grid = Potf(V_0, a_val, X_grid)
!
DO Index = 1, X_dim
PRINT*, X_grid, Pot_grid
ENDDO
!
DEALLOCATE(X_grid, STAT = Ierr)
IF (Ierr /= 0) THEN
STOP 'X_grid deallocation failed'
ENDIF
!
DEALLOCATE(Pot_grid, STAT = Ierr)
IF (Ierr /= 0) THEN
STOP 'Pot_grid deallocation failed'
ENDIF
!
!
END PROGRAM ex_8_6
!
ELEMENTAL FUNCTION Potf(Depth, Inv_length, X)
!
IMPLICIT NONE
!
REAL, INTENT(IN) :: Depth, Inv_length, X
!
REAL :: Potf
!
Potf = -Depth/(COSH(Inv_length*X)**2)
!
END FUNCTION Potf
```

### 8.3.7 excode_8_7.f90

```     PROGRAM ex_8_7
!
! Program to characterize an array making use of inquiry functions
!
IMPLICIT NONE
!
REAL, DIMENSION(:,:), ALLOCATABLE :: X_grid
INTEGER :: Ierr
!
!
ALLOCATE(X_grid(-20:20,0:50), STAT = Ierr)
IF (Ierr /= 0) THEN
STOP 'X_grid allocation failed'
ENDIF
!
WRITE(*, 100) SHAPE(X_grid)
100 FORMAT(1X, "Shape :        ", 7I7)
!
WRITE(*, 110) SIZE(X_grid)
110 FORMAT(1X, "Size :         ", I7)
!
WRITE(*, 120) LBOUND(X_grid)
120 FORMAT(1X, "Lower bounds : ", 7I6)
!
WRITE(*, 130) UBOUND(X_grid)
130 FORMAT(1X, "Upper bounds : ", 7I6)
!
DEALLOCATE(X_grid, STAT = Ierr)
IF (Ierr /= 0) THEN
STOP 'X_grid deallocation failed'
ENDIF
!
END PROGRAM ex_8_7
```

[ previous ] [ Contents ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ] [ 11 ] [ 12 ] [ 13 ] [ next ]

`Fortran 90` Lessons for Computational Chemistry

0.0

Curro Pérez-Bernal `mailto:francisco.perez@dfaie.uhu.es`