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

# `Fortran 90` Lessons for Computational Chemistry Chapter 5 - Control Structures

## 5.1 Objectives

The main aims of this session consist of:

1. presenting the different conditional control structures in `Fortran` (branching).

1. presenting the different way of building loops in `Fortran` code.

These structures allows the programmer to control the program flow, allowing the conditional execution of statements according to the user input values or the values acquired by variables during the program execution.

It is extremely important to take into account before starting to write code in any programming language that a previous step should be accomplished. In encompasses having a clear idea of the problem, the inputs and outputs, the program structure, breaking complex tasks into simpler subtasks, and the optimal algorithm. A flow diagram can be of great help at this stage.

The division of the problem into simpler and simpler tasks is called top-down design. Each subtasks should be coded and checked in an independent manner.

## 5.2 Main items.

We provide a scheme of the main control structures, strting with conditionals and later of loops.

• Conditionals.

Depend on the evaluation of boolean expressions for which the following operators are defined:

• == To be equal to.

• /= Not to be equal to.

• > Greater than.

• < Lesser than.

• >= Greater or equal than.

• <= Lesser or equal than.

There exist also logical operators to combine several logical expressions:

• .AND.

• .OR.

• .NOT.

• .EQV. (Boolean '==' operator)

• .NEQV. (Boolean '/=' operator)

The == and /= shouldn't be used to compare real type variables, due to their nonexact nature. If e.g. A and B are real variables, the following code is discouraged

```     ...
IF (A==B) same = .TRUE.
...
```

The alternative would be to define a tolerance and compare the variables as follows

```     REAL :: TOL = 0.00001
...
IF (ABS(A-B) < TOL) same = .TRUE.
...
```

The possible conditional statements are

1. IF THEN ENDIF

The syntax of this conditional statement is

```     .
. code
.
IF (Boolean Expression) THEN
.
. code_1
.
ENDIF
.
. code
.
```

Only if the Boolean Expression is true the code_1 block instructions are executed.

If there is only one statement in the code_1 block the command can be simplified to a one liner removing the THEN and ENDIF keywords as follows

```     .
. code
.
IF (Boolean Expression) statement
.
. code
.
```
1. IF THEN ELSE ENDIF

The syntax of this conditional statement is

```     .
. code
.
IF (Boolean Expression) THEN
.
. code_1
.
ELSE
.
. code_2
.
ENDIF
.
. code
.
```

If the Boolean Expression is true the code_1 block instructions are executed, if it is false then code_2 block is run.

1. IF THEN ELSE IF ENDIF

The syntax of this conditional statement is

```     .
. code
.
IF (Boolean Expression_1) THEN
.
. code_1
.
ELSE IF (Boolean Expression_2) THEN
.
. code_2
.
ENDIF
.
. code
.
```

In case that the Boolean Expression_1 is true the code_1 block instructions are executed, if it is false but Boolean Expression_2 is true then code_2 block is run.

1. IF THEN ELSE IF ELSE ENDIF

The syntax of this conditional statement is

```     .
. code
.
IF (Boolean Expression_1) THEN
.
. code_1
.
ELSE IF (Boolean Expression_2) THEN
.
. code_2
.
ELSE
.
. code_3
.
ENDIF
.
. code
.
```

In case that the Boolean Expression_1 is true the code_1 block instructions are executed, if it is false but Boolean Expression_2 is true then code_2 block is run. If both are false then the code_3 block is run.

1. SELECT CASE

The CASE statement allows to choose among different options in a clear and efficient way, though it has some limitations.

The syntax of this conditional statement is

```     SELECT CASE (selector)
CASE (label-1)
block-1
CASE (label-2)
block-2
CASE (label-3)
block-3
.............
CASE (label-n)
block-n
CASE DEFAULT
block-default
END SELECT
```

The selector is either a variable or an expression of the integer, logical, or character type. It cannot be a real or complex number.

The label-1 ... label-n labels have the following syntax

```     value
value_1 : value_2
value_1 :
: value_1
```

The first one is positive if the selector is equal to value and the second if the selector takes a value in the range value_1 to value_2. The third(fourth) is true if the selector has a value larger(less) than value_1. The valor, value_1, and value_2 should be constants or variables defined with the PARAMETER declaration.

The selector expression is evaluated first. The result is compared with the values in each one of the labels, running the block of instructions of the first successful comparison. If none of the labels is true the block-default is run if it exists.

A simple example:

```     SELECT CASE (I)
CASE (1)
PRINT*, "I = 1"
CASE (2:9)
PRINT*, "I in [2,9]"
CASE (10:)
PRINT*, "I in [10,INF]"
CASE DEFAULT
PRINT*, "I is negative"
END SELECT CASE
```

The SELECT CASE statement is more elegant than a series of IF's as only one expression controls the access to the different alternatives.

Conditional control structures can be nested in several levels. For the sake of clarity in this case the different levels should be labeled as follows

```     firstif: IF (a == 0) THEN
PRINT*,  "a is zero"
secondif: IF (c /= 0) THEN
PRINT*,  "a is zero and c is not zero"
ELSE secondif
PRINT*,  "a and c are zero"
ENDIF secondif
ELSEIF (a > 0) THEN firstif
PRINT*,  "a is positive"
ELSE firstif
PRINT*,  "a is negative"
ENDIF firstif
```

The role of the lables firstif and secondif is to clarify the source code for the reader. Once a label is included in the IF statement, then it has to be present also in the ENDIF, while it is optional in the ELSE and ELSEIF. The number of nested conditionals is unlimited.

The example code excode_5_1.f90, Section 5.3.1 contains the IF THEN ELSE IF ELSE ENDIF structure and, apparently, the same task is coped with in example excode_5_2.f90, Section 5.3.2 with the CASE structure.

• Loops

1. Basic loop: The DO statement

We have been already introduced to the basic DO loop:

```     DO Var = initial_value, final_value, increment
Block of Code
END DO
```

The variable Var changes from initial_value to final_value adding increment each iteration.

1. The DO WHILE loop

This loop has this structure:

```     DO WHILE (conditional)
Block of code
ENDDO
```

In this case the block of code is run until the conditional in the head of the block is false. E.g. see example Programa ejemplo_5_4.f90, Section 5.3.4.

1. The REPEAT UNTIL loop

This type of loop has the following structure:

```           DO
Block of code
#
IF (conditional) EXIT
END DO
```

The loop is executed until the conditional is evaluated True. This case differs from the previous two in that the code block is run at least once.

In this case we make use of the EXIT statement. When this statement is run into a loop the program leaves inmediately the loop and keeps running from the order following the corresponding ENDDO. Another interesting statement when working with loops is CYCLE. The execution of the CYCLE statement makes the program to return to the beginning of the loop, without running the statements in the loop block between the CYCLE statement and the end of the loop.

As in the conditionals case, nested loops can be labeled. This greatly clarifies the source code and, in particular, allows to indicate to which loop level refers the statements EXIT and CYCLE. By default, they address the inner loop.

There is a last statement, worth to mention, the GOTO command, though its use is highly discouraged in the moder programming standards.

## 5.3 Example codes.

### 5.3.1 excode_5_1.f90

```     PROGRAM ex_5_1
!
IMPLICIT NONE
!
CHARACTER(LEN = 2), DIMENSION(1:5) :: List_Grades=(/'D ','C ','B ','A ','A+'/)
INTEGER :: IN
PRINT *, "Student mark??"
!
IN=1
IN=2
IN=3
IN=4
IN=5
ELSE
IN=0
ENDIF
!
IF (IN==0) THEN
PRINT *, "The input : ", Grade," has a wrong value. Only [0,10]"
ELSE
ENDIF
!
END PROGRAM EX_5_1
```

### 5.3.2 excode_5_2.f90

```     PROGRAM ex_5_2
!
IMPLICIT NONE
!
CHARACTER(LEN=2), DIMENSION(1:5) ::  List_Grades=(/'D ','C ','B ','A ','A+'/)
PRINT *, "Nota del estudiante?"
!
!
CASE (0:4)
Index = 1
CASE (5,6)
Index = 2
CASE (7,8)
Index = 3
CASE (9)
Index = 4
CASE (10)
Index = 5
CASE DEFAULT
Index = 0
END SELECT
!
IF (Index==0) THEN
PRINT *, "The input grade : ", Grade," is out of bounds. Only  [0,10]."
ELSE
ENDIF
!
100 FORMAT(1X,'Student grade is ',F4.1,' (',A3,')')
!
END PROGRAM EX_5_2
```

### 5.3.3 excode_5_3.f90

```     PROGRAM ex_5_3
!
IMPLICIT NONE
!
REAL :: PIover2 = ASIN(1.0)
REAL :: ANGLE1 = 0.0, ANGLE2 = 0.0
INTEGER :: I
!
DO I = 0, 16, 2
ANGLE1 = I*PIO2/4.0
!
WRITE(*,*)
WRITE(*,*) 'Cos(',I/2,'PI/4) = ',COS(ANGLE1),'; Cos(',I/2,'PI/4) = ',COS(ANGLE2)
WRITE(*,*) 'Sin(',I/2,'PI/4) = ',SIN(ANGLE1),'; Sin(',I/2,'PI/4) = ',SIN(ANGLE2)
WRITE(*,*)
!
ANGLE2 = ANGLE2 + PIO2/2.0
!
ENDDO
END PROGRAM ex_5_3
```

### 5.3.4 Programa ejemplo_5_4.f90

```     PROGRAM excode_5_4
!
IMPLICIT NONE
!
REAL :: X_val = 0.0
REAL :: X_app = 0.0, X_sum = 0.0
INTEGER :: I_flag = 1, I_count = 0
!
! Taylor Series:  SIN(X) = X - X^3/3! + X^5/5! - X^7/7! + ...
WRITE(*,*) "Introduce the angle X (RAD) :"
!
I_count = 1
X_app = X_val
X_sum = X_val
!
PRINT*, '         Order     Approx.    SIN(X)       Approx. - SIN(X)'
!
DO WHILE (I_flag == 1)
!
PRINT*, I_count, X_app, SIN(X_val), X_app - SIN(X_val)
!
X_sum = X_sum*(-1)*X_val*X_val/((I_count*2+1)*(I_count*2))
X_app = X_app + X_sum
!
I_count = I_count + 1
!
WRITE(*,*) "STOP? (0 yes, 1 no)"
IF (I_flag /= 1 .AND. I_flag /= 0) I_flag = 1
!
ENDDO
!
END PROGRAM excode_5_4
```

[ 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`