FORTRAN Programming: A Basic Introduction (PART II)

In college, before video games, we would amuse our- selves by posing programming exercises. One of the favorites was to write the shortest self-reproducing program. Since this is an exercise divorced from reality, the usual vehicle was FORTRAN. Actually, FORTRAN was the language of choice for the same reason that three-legged races are popular.

Ken Thompson, Communications of the ACM. 27 (8), 761–763, 1984.

This is the second part of the basic introductin to FORTRAN programming series.

Control Statements 

Relational operators

Relational operators are used for comparison between variables

< or .lt. : less than 

<= or .le. : less than or equal to 

> or .gt. : greater than 

>= or .ge. :greater than or equal to

== or .eq. : equal to  

/= or .ne. : not equal to

Logical operators

Logical operator are used to perfrom

.and. : Logical multiplication ( and) 

.or. : Logical addition (or) 

.not. : Logical negation (not)

CONDITIONAL STATEMENTS

The If construct allows the execution of a sequence of statements (block) to depend on a condition. The if construct is a compound statement.

Syntax:

If (scalar-logical-expr) then 

        block1

    else

        block2

end if

Example

A 1 D Escher world

The program allows you to move an X character in a one-dimensional world 30 characters long. The world space is on a circle so that
the endpoints of the line are stuck together. In this example, the statement GOTO is used to repeat the input of the movement.

PROGRAM EschelWorld

    !=======================================================
    !
    !    MOVING IN A ONE DIMENSIONAL CYCLIC WORLD 
    !    USING NINT FUNCTIONS
    !
    ! Roccatano (c) 2023
    !=======================================================

    CHARACTER(len=32) :: map,mapt
    REAL  :: L,pos,step,corr,zero=0

    map="|------------------------------|"
    
    L=30
    pos=L/2.0
    ip=ANINT(pos)+1
    mapt=map
    mapt(ip:ip)="x"
    print *,"You are now in the center of your world"
    write(6,'(F5.1,1x,A32,F5.1," x=",F5.1)',advance="no") zero,mapt,L,pos

    10  write(6,'("   Insert a step ->")',advance="no")
    READ(5,*) step
    pos=pos+step
    IF (pos >L) THEN
        corr=L*NINT(pos/L)
        if (corr > pos) THEN
            pos = corr-pos
        ELSE
            pos = pos - corr
        END IF
    ELSEIF (pos <= 0) THEN
        corr=L*NINT(pos/L)
        if (corr > pos) THEN
            print *,"Here"
            pos = L+pos-corr
        ELSE
            pos = L-(pos-corr)
        END IF
    END IF
    ip=ANINT(pos)+1
    mapt=map
    mapt(ip:ip)="x"
    write(6,'(F5.1,1x,A32,F5.1," x=",F5.1)',advance="no") zero,mapt,L,pos
    GOTO 10

END PROGRAM EschelWorld

EXAMPLE OF OUTPUT

 You are now in the center of your world
  0.0 |--------------x---------------| 30.0 x= 15.0   Insert a step ->4
  0.0 |------------------x-----------| 30.0 x= 19.0   Insert a step ->5
  0.0 |-----------------------x------| 30.0 x= 24.0   Insert a step ->6
  0.0 |-----------------------------x| 30.0 x= 30.0   Insert a step ->10
  0.0 |---------x--------------------| 30.0 x= 10.0   Insert a step ->20
  0.0 |-----------------------------x| 30.0 x= 30.0   Insert a step ->2
  0.0 |-x----------------------------| 30.0 x=  2.0   Insert a step ->3
  0.0 |----x-------------------------| 30.0 x=  5.0   Insert a step ->4
  0.0 |--------x---------------------| 30.0 x=  9.0   Insert a step ->5
  0.0 |-------------x----------------| 30.0 x= 14.0   Insert a step ->6
  0.0 |-------------------x----------| 30.0 x= 20.0   Insert a step ->-3
  0.0 |----------------x-------------| 30.0 x= 17.0   Insert a step ->-4
  0.0 |------------x-----------------| 30.0 x= 13.0   Insert a step ->-7
  0.0 |-----x------------------------| 30.0 x=  6.0   Insert a step ->

LOOP STATMENTS

The loop are important structure in programming as they allow to repeat a set of instructions for a given number of time. Fortran does have the DO-LOOP and the DO WHILE-LOOP staments

DO-statment

Synthax

DO variable = expr1, expr2 [,expr3] 

   <block of statements>

END DO

Example

Build up the pitagoric table of the first num (<= 20) elements.

PROGRAM PitagoricTable

INTEGER :: num
PARAMETER (num=12)
INTEGER :: tavola(num,num)

WRITE(*,50)
WRITE(*,60) (i,i=1,num)
DO i=1,num
DO j=1,num
tavola(i,j)=i*j
END DO
END DO

DO i=1,num
WRITE(*,70) i,(tavola(i,j),j=1,num)
END DO

50 FORMAT(20X,'PITAGORIC TABLE ')
60 FORMAT(5X,20I5)
70 FORMAT(i2,3X,20I5)
END PROGRAM PitagoricTable
OUTPUT 

                    PITAGORIC TABLE 
         1    2    3    4    5    6    7    8    9   10   11   12
 1       1    2    3    4    5    6    7    8    9   10   11   12
 2       2    4    6    8   10   12   14   16   18   20   22   24
 3       3    6    9   12   15   18   21   24   27   30   33   36
 4       4    8   12   16   20   24   28   32   36   40   44   48
 5       5   10   15   20   25   30   35   40   45   50   55   60
 6       6   12   18   24   30   36   42   48   54   60   66   72
 7       7   14   21   28   35   42   49   56   63   70   77   84
 8       8   16   24   32   40   48   56   64   72   80   88   96
 9       9   18   27   36   45   54   63   72   81   90   99  108
10      10   20   30   40   50   60   70   80   90  100  110  120
11      11   22   33   44   55   66   77   88   99  110  121  132
12      12   24   36   48   60   72   84   96  108  120  132  144

Fortran 90/95 use a DO construct to have the computer execute the same statements more than once. A do construct can be exited by using the EXIT or CYCLE statement. 

Example

Search of the Prime numbers using the Sieve of Eratosthenes

PROGRAM PrimeSieve
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! The Sieve of Eratosthenes
!
! 1994 (c) Roccatano
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

INTEGER MAXNUM
PARAMETER( MAXNUM= 1000)

LOGICAL:: flag(MAXNUM)

INTEGER :: primo,conto,SQMAX

DO  i=2,MAXNUM
    flag(i)=.TRUE.
END DO

SQMAX=INT(SQRT(float(MAXNUM)))

DO  i=2,SQMAX
    IF (flag(i)) THEN
        DO k=2*i,MAXNUM,i
            flag(k)=.FALSE.
        END DO
    END IF
END DO

DO  i=2,MAXNUM
    IF (flag(i)) WRITE(6,100,advance="no") i
END DO

100   FORMAT(1X,I6)

END PROGRAM PrimeSieve
OUTPUT 
 
2      3      5      7     11     13     17     19     23     29     31     37     41     43     47     53     59     61     67     71     73     79     83     89     97    101    103    107    109    113    127    131    137    139    149    151    157    163    167    173    179    181    191    193    197    199    211    223    227    229    233    239    241    251    257    263    269    271    277    281    283    293    307    311    313    317    331    337    347    349    353    359    367    373    379    383    389    397    401    409    419    421    431    433    439    443    449    457    461    463    467    479    487    491    499    503    509    521    523    541    547    557    563    569    571    577    587    593    599    601    607    613    617    619    631    641    643    647    653    659    661    673    677    683    691    701    709    719    727    733    739    743    751    757    761    769    773    787    797    809    811    821    823    827    829    839    853    857    859    863    877    881    883    887    907    911    919    929    937    941    947    953    967    971    977    983    991    997

I/O STATEMENTS

A Fortran program can input and output data from the keyboard or a file to the screen, printer or file. Access to multiple files, or in general multiple input/output devices, is controlled by assigning a device number that uniquely identifies the device. For example, the keyboard and screen are standard input and output devices, and they are identified with the numbers 5 and 6, respectively. The input/output to files requires assigning the device number to a specific file, which is done with the command open. The syntax of the command is the following:

open(unit=infile, file=’indata.dat’, access=’sequential’, action=’read’) ! read a file  

open(unit=outfile, file=’outdata.dat’, access=’sequential’, action=’write’)! Write a file

Standard input-output channels do not require the open statement. It is possible to input-output data from /to a file using the standard devices 5 and 6, respectively. For this purpose, you need to use the redirection command of the Unix OS as follows:

./program.exe < input.dat > output.log

In this case, the program Integral reads parameters in the input file input.dat and output.log. The access to the file is terminated, and the device number is released by the statement close(devnum) where devnum is the device number used in the open statement.

Reading lines from an open file is performed using the statement READ(devnum,format). The asterisks (*,*) following READ represent the default format for output, i.e., the outcome is, e.g. written out on the screen. 

The writing of data to a device is performed by using the statement PRINT devnum, format or WRITE(devnum,format). 

The asterisks (*,*) following WRITE represent the default format for output, i.e., the output is, e.g. written out on the screen. 

The format is defined between apostrophes in the read/write command or a numbered label line. In this case, the line contains a FORMAT statement.  

10 FORMAT (E15.8,E15.8,E15.8, 5X,'ERROR=',E15.8)

Each format code defines how the data should be read and written. The following table reports the meanings of the one-letter format command.

FORMAT SPECIFICATIONS

I/O program example

An example of a reading and writing file is given in the following example.

Program IOofAllocatedarr

!
! Example of I/O Staments and automatic memory allocations
! of arrays
!
!

    Implicit none

    real(8), allocable :: data (:,:)

    real(8), allocable :: rowsum (:)

    integer :: rows, i, j

     ! File unit numbers

    integer, parameter :: infile=15

    integer, parameter :: outile=16

    ! Allocate matrices

    rows=5

    allocate (infield(3,rows))

    allocate(rowsum(rows))

    ! Open the file 'indata.dat' for reading

    open(unit=infile, file=’indata.dat’, access=’sequential’, action=’read’)

    ! open the file 'outdta.dat' for writing

    open(unit=outfile, file=’outdata.dat’, access=’sequential’, action=’write’)

    ! Read input from file

    do i=1, rews

             read(infile, *) (data(j,i),j=1,3)

             rowsum(i)= data(1,i)+data(2,i)+data(3,i)

             write(outfile,*) rowsum(i)

    end do

    ! Close files

    close(infile)

    close(outfile)

    deallocate (data)

    deallocate (rowsum)

    stop

end program IOofAllocatedarr

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.