0 Some basic properties

  • Fortran code is case insensitive
  • Fortran code must be written in a program, similar to the main() function in C

Example 1 Hello World

1
2
3
program hello_world
 print *,'Hello World'   
end program hello_world

1 Variables

1.1 Built-in datatypes

There are five built-in datatypes:

  1. integer
  2. real
  3. complex
  4. character
  5. logical

declaring a variable:

1
<variable type> :: <variable name>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
program variable
   implicit none
   
   integer :: int
   real :: re
   complex :: com
   character :: char
   logical :: boolean

   int = 10
   re = 10.0
   com = (10,1)
   char = "character"
   logical = .false.
end program variable

implicit none should be followed by every program/function/subroutine, in modern fortran the type of variable should be declared explicitly

boolen types are .false. and .true

integer,parameter :: i = 10

means a immutable variable, the variable can’t change its value in the function

Expressions for numbers are

  • +
  • -
  • *
  • /
  • **

Floating point precision

1.2 array and strings

Decalre an array

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
program arrays
  implicit none

  ! 1D integer array
  integer, dimension(10) :: array1

  ! An equivalent array declaration
  integer :: array2(10)

  ! 2D real array
  real, dimension(10, 10) :: array3

  ! Custom lower and upper index bounds
  real :: array4(0:9)
  real :: array5(-5:5)

end program arrays

Array index can be set manully

Array Slicing

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
program array_slice
  implicit none

  integer :: i
  integer :: array1(10)  ! 1D integer array of 10 elements
  integer :: array2(10, 10)  ! 2D integer array of 100 elements

  array1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]  ! Array constructor
  array1 = [(i, i = 1, 10)]  ! Implied do loop constructor
  array1(:) = 0  ! Set all elements to zero
  array1(1:5) = 1  ! Set first five elements to one
  array1(6:) = 1  ! Set all elements after five to one

  print *, array1(1:10:2)  ! Print out elements at odd indices
  print *, array2(:,1)  ! Print out the first column in a 2D array
  print *, array1(10:1:-1)  ! Print an array in reverse

end program array_slice

Allocatable arrays

If the length of the array is unkown

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
program allocatable
  implicit none

  integer, allocatable :: array1(:)
  integer, allocatable :: array2(:,:)

  allocate(array1(10))
  allocate(array2(10,10))

  ! ...

  deallocate(array1)
  deallocate(array2)

end program allocatable

Array of strings

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
program string
  implicit none

  character(len=4) :: first_name
  character(len=5) :: last_name
  character(10) :: full_name

  first_name = 'John'
  last_name = 'Smith'

  ! String concatenation
  full_name = first_name//' '//last_name

  print *, full_name

end program string

Allocatable array of strings

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
program allocatable_string
  implicit none

  character(:), allocatable :: first_name
  character(:), allocatable :: last_name

  ! Explicit allocation statement
  allocate(character(4) :: first_name)
  first_name = 'John'

  ! Allocation on assignment
  last_name = 'Smith'

  print *, first_name//' '//last_name

end program allocatable_string

Array of strings

Logical operators and flow controls

logical operators

== .eq. (equal) /= .ne. (not equal) > .gt. (greater than) < .lt. (less than) >= .ge (greater equal) <= .le. (less equal)

.and. .or. .not. .eqv. .neqv.

Conditional

1
2
3
if (condition) then
! some code
end if
1
2
3
4
5
6
7
if (condition1) then
! some code
else if (condition2) then
! some code
else
! some code
end if

if is always followed by then, but else does not need then

1
2
3
4
5
6
7
if (angle < 90.0) then
  print *, 'Angle is acute'
else if (angle < 180.0) then
  print *, 'Angle is obtuse'
else
  print *, 'Angle is reflex'
end if

Loop

Do loop with counter

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
program sum
implicit none
integer :: i
integer :: sum

sum = 0
do i = 1, 10
sum = sum + i
end do

print *, sum
end program sum

Conditional loop

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
program sum
implicit none
integer :: i, sum

i = 1
sum = 0
do while(i<11)
sum = sum + i
i = i + 1
end do

print *, sum
end program sum

Loop control statements

exit and cycle, similar to break and continue in C

1
2
3
4
5
6
7
8
9
integer :: i

do i = 1, 100
  if (i > 10) then
    exit  ! Stop printing numbers
  end if
  print *, i
end do
! Here i = 11
1
2
3
4
5
6
7
8
integer :: i

do i = 1, 10
  if (mod(i, 2) == 0) then
      cycle  ! Don't print even numbers
  end if
  print *, i
end do

Tag nested loops

To avoid ambiguity of which loop to break, it’a a good habit to name the loop and designate which loop to break

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
integer :: i, j

outer_loop: do i = 1, 10
  inner_loop: do j = 1, 10
    if ((j + i) > 10) then  ! Print only pairs of i and j that add up to 10
      cycle outer_loop  ! Go to the next iteration of the outer loop
    end if
    print *, 'I=', i, ' J=', j, ' Sum=', j + i
  end do inner_loop
end do outer_loop

Do concurent

If the loops have no interdependence, it could be computed parallel

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
real, parameter :: pi = 3.14159265
integer, parameter :: n = 10
real :: result_sin(n)
integer :: i

do concurrent (i = 1:n)  ! Careful, the syntax is slightly different
  result_sin(i) = sin(i * pi/4.)
end do

print *, result_sin

Subroutine, function and module

Subroutine: invoke by a call statement
Function: invoke by its expression