Introduction to Arrays

Arrays are one of the most important types in Fortran. It can represent many mathematical entities such as grids, matrices, vectors, and so forth. The members of an array are frequently called elements. From the computational point of view, an array is a data structure that contains data of the same type with each scalar element addressed by indexing into the array. Indices must be integers. An array has one or more dimensions . The bounds are the lowest and highest indexes. The rank is the number of dimensions. The size of an array is the number of elements. The shape is a tuple giving the size in each individual dimension.

Fortran Arrays

Arrays must be declared by type and either by size or by some indication of the number of dimensions. The simplest case is static arrays, which are declared to be of a fixed size and shape.

REAL, DIMENSION(100)            :: A
INTEGER, DIMENSION(50,50)       :: INDS
CHARACTER(LEN=3), DIMENSION(12) :: MONTHS

By default the index starts at 1. However, it can start at any integer less than the upper bound:

REAL, DIMENSION(-1:101,0:3) :: A0

Arrays may have zero size. The maximum (standard) dimensions up to the F2003 standard is 7. This increases to 15 in F2008. Fortran arrays carry metadata (shape, size, bounds, some other data) about themselves and these data can be extracted by intrinsic functions.

Each element can be addressed by its index or indices, which must be enclosed in parentheses.

A(3)
X(i,j)

Remember that the bounds start at 1 by default.

Compiler Bounds Checking

One of the most common errors in programming, in all languages that support an array or something like it, is attempting to access an element with values for the indices that are outside the declared bounds. This frequently happens with loops such as

! Average nearest neighbors
do j=1,m
   do i=1,n
      A(i,j)=0.25*(B(i+1,j)+B(i,j+1)+B(i-1,j)+B(i,j-1))  !OOPS
   enddo
enddo

Most usually this results in an error such as “Segmentation fault.” In Fortran, compilers know the size and shape of each array, once allocated, so they are able to check each operation to make sure it is within the bounds. However, since this can greatly slow down your executable, it must be invoked at compile time. The name of the option may vary from one compiler to another.
For gfortran and Intel they are:

gfortran -g -fbounds-check mycode.f90
ifort -g -CB mycode.f90
ifort -g -check bounds mycode.f90 

Be sure to remove the options -g -<array check> and replace with -O once your program is debugged.

Array Operations

Fortran supports array operations in which an action is applied across an entire array, elementwise. All arithmetic operators and most of the mathematical functions are overloaded to accept array arguments, for arrays of numerical type.

T=3.0
A=3.14159*I
B=sin(A)
C=A/B !Watch out for elements that are zero

Array Orientation

Array elements are adjacent in memory and are arranged linearly no matter how many dimensions you declare. If you declare a 3x2 array the order in memory is

(1,1), (2,1), (3,1), (1,2), (2,2), (3,2)

“Orientation” refers to how the array is stored in memory , not to any mathematical properties. Fortran is column-major oriented. Most other languages are row-major oriented. Loop indices should reflect this whenever possible (when you need loops). Fortran: outermost first. Go right to left.

    do k=1,nz-1
       do j=1,ny-1
          do i=1,nx
              A(i,j,k) = C(i,j,k) !loop order is do k/do j/do i
          enddo
       enddo
    enddo

Array operations can be used to avoid loops in many cases, and the compiler will be able to optimize them automatically.

A=C

Obtaining Size and Shape Information

The SIZE(ARRAY [,DIM]) function returns the number of elements in the array if DIM is absent. If it is present, it returns the number of elements in that dimension, e.g. number of rows or columns.

The SHAPE(ARRAY) function returns a one-dimensional array whose elements are the dimensions of the array.

The RANK(ARRAY) function returns the rank (number of dimensions).

Where

where functions like a “vectorized” loop+conditional. The clauses must be array assignments.

where ( A>=0.0 )
   B=sqrt(A)
elsewhere
   B=0.
end where

Exercises

  • Open a new file (you can call it arrays.f90) and type
program arrays
! Array demo
```fortran
implicit none
   real, dimension(10)    :: A
   integer                :: i, j
      A=[(0.2*real(i),i=1,10)]
end program
  • In arrays.f90 1 Print the size and shape of the array A 2 Declare a new real array W of shape 10x10. Set all values to 1.0 using an array operation. 3 Declare another 10x10 array Z. Use a nested loop to set each element of W(i,j) to the sum of its row and column indices. Remember that Fortran loops should run over indices from right to left, e.g.
do j=1,N
   do i=1,M
      A(i,j)=something
   enddo
enddo

4 Change the fourth column of the second row of Z to 1.1

  • In arrays.f90
    • Add a WHERE to set elements to W equal to the corresponding elements of Z if the element of Z is less than 7. Print W(2,4).
Example solution

program arrays
implicit none
real, dimension(10,10) :: A
integer                :: i, j
real, dimension(10,10) :: W, Z

   do j=1,10
      do i=1,10
         A(i,j)=0.1*i+0.2*j
      enddo
   enddo
   print *, size(A)
   print *, shape(A)

   W=1.0
   do j=1,10
      do i=1,10
         Z(i,j)=i+j
      enddo
   enddo
   Z(2,4)=1.1

   where (Z<7)
      W=Z
   endwhere
   print *,W(2,4)

end program


Previous
Next