Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

15) Introduction to Fortran

Last time:

Today:

  1. How to compile a Fortran program

  2. The simplest Fortran program

  3. Hello, World! and Simple I/O

  4. Arithmetic in Fortran

  5. Functions
    5.1 Scope Rules

  6. Interface Blocks

  7. Subroutines

  8. Modules

1. How to compile a Fortran program

Historically, Fortran 77, is an older version of the language that still is often used. It is a little simpler in some ways than later versions such as Fortran 90 and Fortran 95. You can see the list of all versions on the Fortran wiki page.

You compile a program by typing a line similar to the following:

gfortran myprogram.f -o myprogram

It is important that you understand what is happening here:

./myprogram

2. The simplest Fortran program

The simplest Fortran program is what might be called a “do-nothing” program. It contains all of the required parts of a Fortran program. The program is as follows:

do_nothing.f
1
2
3
      PROGRAM MAIN
      STOP
      END

The program simply starts and stops. It has a beginning (the PROGRAM instruction), and then tells the system to halt execution (STOP). Notice that there is both STOP and END. The difference is that STOP tells the system to halt the execution of the program, while END identifies the end of your instructions - that is, END will always appear as the last line of a program.

Complex programs may have more than one STOP instruction; for example, execution may be halted if an error occurs or a limit is reached. A single instruction in Fortran is usually called a statement.

Although seemingly trivial, writing and executing this program illustrates some of the basic rules of writing Fortran programs:

Exercise 15.1:

Create your first “do nothing” Fortran program.

3. Hello, World! and Simple I/O

The next simplest Fortran program is something programmers call the “Hello World” program. This is the simplest program that actually produces some output. An example of the “Hello World!” program in Fortran is:

hello_world.f
1
2
3
4
      PROGRAM HelloWorld
      IMPLICIT NONE ! requires you to explicitly define the type for every variable that you use in your program, so to avoid undefined variables
      WRITE(*,*) 'Hello, world!' ! this prints out on the screen
      END PROGRAM HelloWorld

Exercise 15.2:

  1. Type the “Hello World” program yourself. Compile it and run it.

  2. Change the “Hello World” program to print out something else, such as your name.

Simple I/O

To print out on a file use the following statements in your program:

WRITE(*,*) 'Hello, world!' ! this prints out on the screen
OPEN(1,file='MyFile.dat') ! this assigns an ID number to the file
WRITE(1,99)'Hello world!' ! this prints out to the file with the format specifier 99
CLOSE(1)
CALL flush(1)
99 FORMAT(A25) ! format specifier for your data. You need the file extension .f90 for this

To read from a file:

CHARACTER(len = 25) :: x
OPEN(1,file='MyFile.dat')
READ(1,99) x ! we read the data from file and put it into x
OPEN(2,file='MyFile2.dat',STATUS='REPLACE',ACTION='WRITE') ! this assigns an ID number to the file MyFile2
WRITE(2,99)'Hello world, again!' ! this prints out to the file with the format specifier 99
CALL flush(1)
CALL flush(2)
CLOSE(1)
CLOSE(2)

99 FORMAT(A25)

4. Arithmetic in Fortran: Real and Integer Variables

Fortran has several different types of variables. The two most commonly used types for computations are integer variables and real variables.

Important! For an integer variable, the fractional part is not merely zero. The fractional part does not exist:

The type of each variable should be declared at the beginning of the program, right after the program is named.

Additionally, your variable names should adhere to the following conventions:

Following is a program that illustrates some of the differences between real and integer variables:

variables.f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
      PROGRAM MAIN
      INTEGER I, INTPI, INTE
      REAL X, REALPI, REALE
      I = 1
      X = 1
      PRINT *, 'THE VALUE OF 1 AS A REAL IS', X
      PRINT *, 'THE VALUE OF 1 AS AN INTEGER IS', I
      REALPI = 3.1416
      INTPI = REALPI
      PRINT *, 'THE VALUE OF PI AS A REAL IS', REALPI
      PRINT *, 'THE VALUE OF PI AS AN INTEGER IS', INTPI
      REALE = 2.71828
      INTE = REALE
      PRINT *, 'THE VALUE OF E AS A REAL IS', REALE
      PRINT *, 'THE VALUE OF E AS AN INTEGER IS', INTE
      STOP
      END

Exercise 15.3:

  1. Type the program as listed above, compile it and run it.

  2. What happens to the value of pi when it gets converted to an integer?

  3. What happens to the value of e when it gets converted to an integer? Look closely: Is the result rounded to the nearest integer?

  4. Change the values of pi and e to negative numbers (that is, -3.1416 and -2.71828), then re-compile and re-run the program. What happens when the negative values are converted to integers?

Other variable types

Examples:

      CHARACTER(len=*), PARAMETER :: Name = 'YourName' ! defines a constant string of characters of unknown length
      INTEGER, PARAMETER :: n = 10
      REAL, PARAMETER :: Dx = 1.0d0
      REAL :: x(n) ! declares an array of n real values called x

Restrictions

5. Functions

User-defined functions are functions defined by programmers to meet a specific need not addressed by the standard intrinsic functions.

General form of user-defined functions:

    RETURN_TYPE  FUNCTION function_name(argument list)
	  !! DECLARACTIONS

	  !! EXECUTABLES

	  function_name = expression

      RETURN	! ONLY NEEDED IF WE PLAN TO REACH END FUNCTION ALL OF THE TIME
    END FUNCTION function_name
      function_name = expression
      INTENT(IN)

Example:

larger_root_function.f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
      REAL FUNCTION LargerRoot(a,b,c)

        IMPLICIT NONE ! Remember that this tells the compiler that we will define all variables we will use

        REAL, INTENT(IN) :: a
        REAL, INTENT(IN) :: b
        REAL, INTENT(IN) :: c

        REAL             :: d, r1,r2 ! Some temporary auxiliary variables needed that will live only inside this function

        d = SQRT(b*b - 4.0*a*c)

        r1 = (-b+d) / (2.0*a)

        r2 = (-b-d) / (2.0*a)

        IF(r1 >= r2) THEN
          LargerRoot = r1
        ELSE
          LargerRoot = r2
        END IF

      END FUNCTION LargerRoot

Common mistakes

  1. Forgetting the function type (i.e., the type of the return argument).

Example:

      FUNCTION DoSomething(a,b)
        IMPLICIT NONE

        INTEGER, INTENT (IN) :: a, b

        DoSomething = SQRT(a*a+b*b)
      END FUNCTION DoSomething

If there is no type, you will not be able to determine the returned value type.

  1. Forgetting INTENT(IN) for input variables.

Example:

      REAL FUNCTION DoSomething(a,b)

        IMPLICIT NONE
        INTEGER :: a,b

        DoSomething = SQRT(a*a + b*b)
      END FUNCTION DoSomething

Actually, this is not an error. But, without INTENT (IN), the compiler will not be able to check many potential errors.

  1. Changing value of formal argument declared with INTENT(IN).

Example:

      REAL FUNCTION DoSomething(a,b)

        IMPLICIT NONE
        INTEGER, INTENT (IN) :: a,b

        IF(a>b) THEN
            a = a - b
        ELSE
            a = a + b
        END IF

        DoSomething = SQRT(a*a+b*b)
      END FUNCTION DoSomething

Since a was declared with INTENT(IN), its value cannot be changed.

  1. Forgetting to store value to function name.

Example:

      REAL FUNCTION DoSomething(a,b)

        IMPLICIT NONE

        INTEGER, INTENT(IN) :: a,b
        INTEGER :: c
        c = SQRT(a*a + b*b)
      END FUNCTION DoSomething

Since there is no value ever stored in DoSomething, the returned value could be anything (garbage).

  1. Function name used in right hand side of expression.

Example:

      REAL FUNCTION DoSomething (a,b)

        IMPLICIT NONE
        INTEGER, INTENT(IN) :: a,b

        DoSomething = a*a+b*b
        DoSomething = SQRT(DoSomething)
      END FUNCTION DoSomething

Only a special type of functions, recursive functions, could have their names on the right-hand side of expressions (we don’t cover recursion in this lecture, because as we’ve seen before it is pretty impractical).

  1. The most recent value stored in function name is returned.

Example:

      REAL FUNCTION DoSomething(a,b)

        IMPLICIT NONE
        INTEGER, INTENT(IN) :: a,b
        DoSomething = a*a+b*b
        DoSomething = SQRT(a*a-b*b)
      END FUNCTION DoSomething

The second assignment overwrites the previous value.

Some important rules for Fortran function arguments:

5.1 Scope rules

Example:

scope.f90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    PROGRAM Scope
        IMPLICIT NONE
        INTEGER :: a = 1, b = 2, c = 3 ! a,b,c are global

        WRITE (*,*) Add(a) ! a = 4
        c = 4
        WRITE (*,*) Add(a) ! a = 5
        WRITE (*,*) Mul (b,c)

    CONTAINS
        INTEGER FUNCTION Add(q)
            IMPLICIT NONE
            INTEGER , INTENT (IN) :: q

            Add = q + c ! c is used here, from global scope
        END FUNCTION Add

        INTEGER FUNCTION Mul(x,y)
            IMPLICIT NONE

            INTEGER, INTENT (IN) :: x,y

            Mul = x * y
        END FUNCTION Mul
    END PROGRAM Scope

6. Interface blocks

Example:

area_circle_function_interface.f90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
      PROGRAM Area
        IMPLICIT NONE

        INTERFACE
            REAL FUNCTION Area_Circle(r)

              REAL, INTENT(IN) :: r

            END FUNCTION Area_Circle
        END INTERFACE

        REAL :: radius

        write(*, '(A)', ADVANCE = "NO") "Enter radius of circle: "
        read(*,*) radius

        ! Write out area of circle using function call
        write(*, 100) "Area of circle with radius", radius, " is", Area_Circle(radius)
100 FORMAT(A, 2x, F6.2, A, 2x, F11.2) ! Need Fortran90 specification, i.e., name your file with the .f90 extension
      END PROGRAM Area

      REAL FUNCTION Area_Circle(r)

        IMPLICIT NONE
        REAL, INTENT (IN) :: r

        REAL, PARAMETER :: Pi = 3.1415927

        Area_Circle = Pi*r*r

      END FUNCTION Area_Circle

7. Subroutines

Example:

area_circle_subroutine_interface.f90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
PROGRAM Area
    IMPLICIT NONE

    INTERFACE
        SUBROUTINE Compute_Area(r, Area)

            REAL, INTENT(IN) :: r
            REAL, INTENT(OUT) :: Area

        END SUBROUTINE Compute_Area
    END INTERFACE

    REAL :: radius, Area_Circle

    write(*, '(A)', ADVANCE = "NO") "Enter radius of circle: "
    read(*,*) radius

    CALL Compute_Area(radius, Area_Circle)

    ! Write out area of circle using function call
    write(*, 100) "Area of circle with radius", radius, " is", Area_Circle
100 FORMAT(A, 2x, F6.2, A, 2x, F11.2) ! Need Fortran90 specification, i.e., name your file with the .f90 extension
  END PROGRAM Area

  SUBROUTINE Compute_Area(r, Area)

    IMPLICIT NONE
    REAL, INTENT(IN) :: r
    REAL, INTENT(OUT) :: Area
    REAL, PARAMETER :: Pi = 3.1415927

    Area = Pi*r*r

  END SUBROUTINE Compute_Area

8. Modules

Syntax:

      MODULE module_name
      ! some specifications
      END MODULE module_name

Example:

using_modules.f
1
2
3
4
5
6
7
8
9
10
11
12
      PROGRAM program_using_module
      USE math_consts_module

      real :: x
      x = cos(pi)

      write(*,*) "The cosine of pi is ", x
      x = log(e)

      write(*,*) "The natural log of e is ", x

      END PROGRAM program_using_module
gfortran -c math_consts_module.f

which will produce math_consts_module.o and math_consts_module.mod files

gfortran -Wall using_modules.f math_consts_module.o -o using_modules

This will both compile your main program using_modules.f and link your compiled module.

Alternatively, you could have compiled the module and main program together, as in:

gfortran -ffree-form -c math_consts_module.f using_modules.f

And then you could have done the linking of the object files:

gfortran math_consts_module.o using_modules.o -o using_modules

Review of Fortran modules:

General form:

      MODULE module_name
      ! [ statement declarations ]
      ! [ contains subroutine and function definitions]
      END MODULE module_name

Using a module:

      USE module_name

Note: