Fortran95

Hello World

program hello
    write(*,*) 'Hello World!'
end

Please keep in mind that the language is not case sensitive outside of character literals.

Terminology

  • Statement - An instruction which is either executabe or nonexecutable.
  • Construct - A sequence of statements ending with a construct terminal statement.
  • Function - A procedure that returns the value of a single variable.
  • Procedure - Either a function or subroutine. Intrinsic procedure, external procedure, module procedure, internal procedure, dummy procedure or statement function.
  • Subroutine - A procedure that is invoked by a CALL statement or defined assignment statement. It can return more than one argument.

Special Characters

  • (Apostrophe) Editing, declaring a string
  • (Quotation Marks) Declaring a string
  • * (Backslash and asterisk) Comment lines.
  • : (Colon) Editing.
  • :: (Double Colon) Separator.
  • ! (Exclamation) inline comment.
  • ; (Semicolon) Separates Statement on single source line. Except when it is in a character context.
  • & (Ampersand) Line continuation character.

Data types

  • integer
  • real
  • double precision
  • character
  • logical
  • complex

Type Declaration Statements

  • dimension - Specifies the dimensions (start and end index) of an array.
  • common - Common storage area for variables that are in several program units.
  • data - Puts initial values into variables.
  • non_overridable - Declares a bound procedure cannot be overridden in a subclass of this class.
  • parameter - Makes a variable into a constant with a certain value.
  • allocatable - Declares an array is allocatable.
  • dimension - Declares the rank and and shape of an array.
  • external - Declares that a name is a function external to a pro-gram unit.
  • intent - Specifies the intended use of a dummy argument.
  • intrinsic - Declares that a name is a specific intrinsic function
  • nopass - Declares a bound procedure cannot be overridden in a subclass of this class.
  • optional - Declares that a dummey argument is optional.
  • parameter - Defines named constant.
  • pointer - Declares that a variable is a pointer.
  • private - Declares that an object is private to a module.
  • protected - Declares that an object in a module is protected, meaning that it can be used but not modified outside the module in which it is defined.
  • public - Declares that an object is private to a module.
  • save - Declares that an object is private to a module.
  • target - Declares that an object is private to a module.
  • volatile - Declares that a value of a variable might be changed at any time by some source external to the program.

User Defined Types

Definition of a new data type called ‘personType’:

type :: personType
        character(len=100) :: name
        integer :: age
        real :: weight
end type personType

Declare an instance of person type:

type (personType) :: p

Access properties:

p%name = 'John Doe'
p%age = 45
p%weight = 70

Operators

  • Arithmetic Operators: | Priority | Operation | Symbol | FORTRAN Expression | | :—: | :—: | :—: | :—: | | inside to outside | Parentheses | ( ) | A(A+B) | | right to left | Exponentiation | ** | A**B | | left to right | Multiplication | * | AB | | left to right | Division | / | A/B | | left to right | Addition | + | A+B | | left to right | Subtraction | - | A-B | | left to right | Unary Minus | - | -A |

  • Character Operators:
    • Concatenation - you can do it by using the ‘//’ operator.
        write(*,*) 'Concate'//'nation'
      
    • Substring - string(startingIndex:endIndex)
        character(len=20) :: c = 'substring'
        write(*,*) c(1:3)
      
  • Logical Operators (in order of precedence):
    • .not.
    • .and.
    • .or.
  • Relational Operators

    Operator Alternative Meaning
    .eq. == equal to
    .ne. /= not equal to
    .lt. < less than
    .le. <= less than or equal
    .gt. > greater than
    .ge. >= greater than or equal
    .eqv.   equivalent to (for boolean)
    .neqv.   not equivalent to (for boolean)

Arrays

Arrays can be up to seven dimensions. They are stored in column major format. This is not the same as C which is stored in row major format. (Row-major order). By default the first index in an array is 1.

Define an array with starting index -3 and end index 3 using the dimension statement:

integer, dimension(-3:3) :: arr
data arr/1,2,3,4,5,5,5/

You can use the following syntax for repeated values count*repeatedValue:

data arr/1,2,3,4,3*5/

Access element:

write(*,*) arr(-2) ! Output: 2

Array subset:

write(*,*) arr(-2:2) ! Output: 2 3 4 5 5

Define a multidimensional array:

integer, dimension(1:3, 1:3) :: arr2
data arr2/1,2,3,4,5,6,7,8,9/

write(*,*) arr2(1,1:3) ! Output: 1 4 7   
write(*,*) arr2(1:3,1) ! Output: 1 2 3
write(*,*) arr2(1:3,1:3) ! Output:  1 2 3 4 5 6 7 8 9

Array Operations

If we want to add two arrays a and b and put the result in c. We may have something like the following piece of code:

do i=1,n
  do j=1,n
    c(j,i) = a(j,i) + b(j,i)
  enddo
enddo

However in Fortran we can also do the following:

c = a + b

Most of the intrinsic functions operate component-wise on arrays. m = sin(k) is equivalent to:

do i=1,n
  m(i) = sin(k(i))
enddo

Note: c = a*b multplies corresponding elements in A and B. It does NOT do matrix multiplication. There are some intrinic functions for matrix multiplication (matmul) and dot products (dot_product).

Another example operations on a vector and a scalar:

real, dimension(3) :: m
data m/1.0, 2.0, 3.0/

write(*,*) m + 1   ! Output: 2.0 3.0 4.0    
write(*,*) m * 2   ! Output: 2.0 4.0 6.0    
write(*,*) m/2     ! Output: 0.5 1.0 1.5   
write(*,*) sqrt(m) ! Output: 1.00 1.41 1.73

Implicit variable declaration

Back in the 1950s, when Fortran was first developed, memory was very expensive, and because of this, a typical computer might have only a few KB of main memory. So, programmers wanted their Fortran programs to be as short as possible. Because of this they made variable declaration implicit. A consequence of this is type inference, this refers to the compiler’s ability to deduce the type of the used variable if it has not been declared beforehand.

This means that when you mistype a character of a variable name the compiler will declare a new variable instead of an error!

For example:

real :: variable = 0
vaIRable = 3 + 5 ! wrong name
write(*,*) variable ! output is 0

You can force explicit variable declaration by either using the “implicit none” statement or by passing a specific parameter to the compiler.

If you put the “implicit none” statement at the top of this piece of code:

implicit none
real :: variable = 0
vaIRable = 3 + 5 !! 
write(*,*) variable

You will get a compile time error similar to this:

    vaIRable = 3 + 5 ! wrong name
            1
Error: Symbol 'vairable' at (1) has no IMPLICIT type

According to the Fortran language standard unless specified otherwise, all variables starting with letters I, J, K, L, M and N are of type integer. All other are by default of type real. Other data types must be explicitly declared. Those defaults can be overridden by ‘implicit TypeName (CharacterRange)’ statements. However it is considered a good practice to always use the ‘implicit none’ statement and explicitly declare all variables!

Goto Statements

Goto statements performs a one-way transfer of control to another line of code. A function call normally returns control. Goto statements should be avoided as they can lead to spaghetti code.

Simple example:

n = 2
if(n.eq.2) then
	goto 100
endif

write(*,*) 'This line will not be printed!'

100 write(*,*) 'Hi!'

Goto statements can have multiple parameters.

goto (s[, s])e

Where ‘s’ is label of an executable statement and ‘e’ is an expression of type integer which points which label should be used by index.

Example:

n = 3
goto (10, 20, 30, 40), n
 
10 write(*,*) 10
20 write(*,*) 20
30 write(*,*) 30
40 write(*,*) 40

Output:

30
40

Loops

A loop can be defined using the following syntax:

do  variable = startValue, StopValue [, StepValue]       
	one or more statments
end do

StepValue is optional. Default value is 1.

Example, where an iteration is skipped:

do i = 1, 10, 2
	if (i.eq.5) then
    	cycle ! Skip iteration
    endif

	write(*,*) "i = ", i
end do

Output:

 i = 1
 i = 3
 i = 7
 i = 9

Example of a do while loop:

integer:: i = 1, n = 3 
       
do while (i <= n)
  write(*,*) "i = ", i                
  i = i + 1
enddo

Output:

 i = 1
 i = 2
 i = 3

Implied DO loops are DO loops in the sense that they control the execution of some iterative procedure, but are different than DO loops because they do not use the do statement to control the execution. Basically, these loops are a shorthand that was introduced in FORTRAN to provide a method for array initialization and to cut back on the number of lines of code that where required in the program. Example:

write (*,*) (i, i=1, 5) ! Output:  1 2 3 4 5

Control flow

If/else statement:

if(n.eq.2) then
	write(*,*) 'N is equal to 2'
else
	write(*,*) 'N is not equal to 2'
endif

Switch case statement:

character(len=1) :: c
c = 'C'

select case (c)
   case ('A')
      write(*,*) 'A'
   case ('B')
      write(*,*) 'B'
   case ('C')
      write(*,*) 'C'
   case ('D')
      write(*,*) 'D'
   case default
      write(*,*) 'Other'
end select

Functions

Defining and calling a function:

program functions
  implicit none

  real :: k = 4.5, z = 1.5

  write (*,*) sumNumbers(k,z)
  
  contains
      function sumNumbers(a, b)
          real :: sumNumbers  ! The variable with the same name as the function is the returned value
          real, intent(in) :: a,b ! a and b cannot be modified
          
          sumNumbers = a + b                
      end function sumNumbers
      
end program functions

Subroutines

Subroutines in Fortran do not return a value. Instead they can modify some of their arguments. They must be invoked with the ‘call’ keyword. The ‘intent’ statement defines the type of the argument. Input arguments cannot be changed inside the subroutine.

real :: k
call sumNumbers(k, 1.0, 3.0)
write (*,*) k ! Output is 4.0

contains
    subroutine sumNumbers(k, z, y)
        real, intent(out) :: k ! Output variable
        real, intent(in) :: z,y ! Input variable
        
        k = z + y
    end subroutine sumNumbers

Modules

Define a module:

module vector
    implicit none
    private ! private statement causes all data and subprograms to be hidden
    
    type, public :: vectorType
        integer :: n = 3
        real :: a(3) ! vector component, array
        real :: magnitude
    end type vectorType
    
    interface assignment(=)
        module procedure assignVector
    end interface
    
    public :: magnitude
    
    contains
        subroutine assignVector (left, right)
            type(vectorType), intent(in) :: right
            type(vectorType), intent(inout) :: left
            
            integer :: i
            
            left%n = right%n
            left%magnitude = right%magnitude
            
            do i = 1, right%n
                left%a(i) = right%a(i) 
            enddo
            
        end subroutine assignVector
    
        subroutine magnitude (x)
            type(vectorType), intent(inout) :: x
            integer :: i
            
            x%magnitude = 0.0
            do i= 1, x%n ! increment is omitted
                x%magnitude = x%magnitude + x%a(i) * x%a(i)
            enddo 
            
            x%magnitude = sqrt(x%magnitude)
            
        end subroutine magnitude 
    
end module vector

Use the module:

program modules
    use vector
    implicit none           
    type(vectorType) :: v1,v2
        
    write(*,*) 'Program using modules'
    v1%a(1) = 1.0
    v1%a(2) = 1.0
    v1%a(3) = 0.0
   
    write (*,*) 'Vector magnitude', v1%magnitude

    v2 = v1
    write(*,*) 'Second vector', v2%a
end program modules

File I/O

Write Pi to a file and open the file to check if the content is written as expected:

program fileIO
implicit none

    integer :: istat
    real :: a,b
    a = 3.142

    ! open a file
    open(101, file = "out.txt", status = "unknown", action="write", form="formatted", IOSTAT=istat)

    ! check the file
    if( istat /= 0) then
        write (*,*) 'Error opening file'
        return
    endif

    write(101, '(f0.3)') a

    close(101)

    ! open for reading
    open(102, file = "out.txt", status = "old", action="read", form="formatted", IOSTAT=istat)

    ! check the file
    if( istat /= 0) then
        write (*,*) 'Error opening file'
        return
    endif

    read(102, '(f5.3)') b
    write(*, '(f5.3)') b

    close(102)

    write(*,*) 'A is equal to B: ', a.eq.b

end program fileIO

Command line arguments

A simple program to read the passed arguments and print them:

program argumentsTest  
     integer :: num_args, ix
     character(len=12), dimension(:), allocatable :: args

     num_args = command_argument_count()
     allocate(args(num_args)) 
     
     if(.not.allocated(args)) then
        return
     endif

     do ix = 1, num_args
         call get_command_argument(ix,args(ix))
         ! now parse the argument as you wish
     end do
   
     print*, args
end program argumentsTest

Source

See Also

Learn X in Y minutes

Back to top ↑

Updated: