[ previous ] [ Contents ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ] [ 11 ] [ 12 ] [ 13 ] [ next ]
Fortran 90
Lessons for Computational Chemistry
The main aims of this session consist of:
presenting the different conditional control structures in Fortran
(branching).
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.
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
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 .
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.
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.
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.
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
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.
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.
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.
PROGRAM ex_5_1 ! IMPLICIT NONE ! REAL :: Grade CHARACTER(LEN = 2), DIMENSION(1:5) :: List_Grades=(/'D ','C ','B ','A ','A+'/) INTEGER :: IN ! READ NOTE PRINT *, "Student mark??" READ *, Grade ! IF (Grade>=0.0.AND.Grade<5.0) THEN IN=1 ELSE IF (Grade>=5.0.AND.Grade<7.0) THEN IN=2 ELSE IF (Grade>=7.0.AND.Grade<9.0) THEN IN=3 ELSE IF (Grade>=9.0.AND.Grade<10.0) THEN IN=4 ELSE IF (Grade==10.0) THEN IN=5 ELSE IN=0 ENDIF ! IF (IN==0) THEN PRINT *, "The input : ", Grade," has a wrong value. Only [0,10]" ELSE PRINT *, "The student grade is ", List_Grades(IN) ENDIF ! END PROGRAM EX_5_1
PROGRAM ex_5_2 ! IMPLICIT NONE ! REAL :: Grade INTEGER :: Index, Integer_Grade CHARACTER(LEN=2), DIMENSION(1:5) :: List_Grades=(/'D ','C ','B ','A ','A+'/) ! READ Grade PRINT *, "Nota del estudiante?" READ *, Grade ! Integer_Grade = NINT(Grade) ! SELECT CASE (Integer_Grade) 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 PRINT 100, Grade, List_Grades(Index) ENDIF ! 100 FORMAT(1X,'Student grade is ',F4.1,' (',A3,')') ! END PROGRAM EX_5_2
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
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) :" READ(*,*) X_val ! 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)" READ(*,*) I_flag 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
mailto:francisco.perez@dfaie.uhu.es