Table of Contents
Previous Chapter
Reference: Chapter 13 of Ellis, Philips, and Lahey
real :: a(100),b(100),c(100),i(25),k(10)These are all one-dimensional arrays. It is also possible to have two, three, four, etc. dimensional arrays, for example:
# of dimensions f90 qty geometrical qty
0 a point
1 a(10) line
2 a(10,10) area (rectangle)
3 a(20,10,5) volume (cube)
Two-dimensional arrays are commonly used. Three and four-dimensional arrays are also used, but only occasionally. As the number of dimensions increases, the frequency of use of that type of array decreases. Fortran 90 allows up to seven dimensions in arrays. An example with two subscripts is as follows:
reserves storage space for 50 real variables, and
reserves space for 66 variables.
Again, you should notice that the default initial subscript for arrays is 1, not 0. If you want the array's initial value to be 0, you must explicity define it as in the previous example.
An example for the structure of a two-dimensional array, of dimension (10,4) is:
col. 1 col. 2 col. 3 col.4
row 1 a(1,1) a(1,2) a(1,3) a(1,4)
row 2 a(2,1) a(2,2) a(2,3) a(2,4)
row 3 a(3,1) a(3,2) a(3,3) a(3,4)
row 4 a(4,1) a(4,2) a(4,3) a(4,4)
.
.
.
row 10 a(10,1) a(10,2) a(10,3) a(10,4)
This is an array with 40 elements. Since there are rows and columns, one subscript is no longer sufficient to specify an element; two are needed. The first number specifies the row, and the second number specifies the column.
real :: a(#row, #col)
Arrays are stored contiguously (one after the other) in memory. This makes them easy for the CPU to fetch when doing computations. We have seen arrays which are one-dimensional (like a line). Storage in computers is linear. For example, a computer with 4 Megabytes of memory has addresses in memory corresponding to:
Two-dimensional arrays in Fortran are stored columnwise (first subscript varies most rapidly), first column 1, then column 2, etc. This will be very important in subroutines and in I/O (input/output).
Arrays are initialized with assignment statements, input statements, or data statements. If the name of an array is used without a subscript in I/O or data statements, the entire array is accessed in the order it is stored in memory (column order for a two dimensional array).
Since two subscripts are needed to use a two-dimensional array, most do loops used for reading or writing of arrays are nested do loops or implied do loops.
Example:
real :: b(8,10)
.
.
.
do i = 1,8
print *, (b(i,j), j = 1,10)
end do
The above code results in the array being printed as below. Note that the printing is different from the order in which the array is stored in memory.
Order:
b(1,1) b(1,2) . . . b(1,10)
b(2,1) b(2,2) . . . b(2,10)
b(3,1) b(3,2) . . . b(3,10)
b(4,1) b(4,2) . . . b(4,10)
.
.
b(8,1) b(8,2) . . . b(8,10)
(prints upside down)
to print forward:
do i = 8, 1, -1
print *, (b(i,j), j = 1, 10)
end do
Finally, note that we sometimes include the row number in the output:
do i = 8, 1, -1
print *, 'row ', i, (b(i,j), j = 1, 10)
end do
results in:
row 8 b(8,1) b(8,2) . . . b(8,10)
row 7 b(7,1) b(7,2) . . . b(7,10)
row 6 b(6,1) b(6,2) . . . b(6,10)
.
.
.
row 1 b(1,1) b(1,2) . . . b(1,10)
A new feature found in Fortran 90 that was not available in earlier versions is that of allocatable arrays. This allows the programmer to create temporary arrays whose size can be determined during the execution of the program.
There is a three-step procedure required in order to use allocatable arrays:
real, allocatable, dimension(:,:) :: array1, array2,.... OR real, allocatable :: array1(:,:), array2(:,:,:), .....
Note: Since the size of the array is unknown at this time, the indices in the array declaration are represented by a single colon, using one colon for every dimension.
isize=20 allocate (array1(isize,isize), array2(100,5,5)) OR allocate (array1(isize,isize), array2(100,5,5), stat=allocate_status)
The advantage of allocating arrays is that the dimensions here can be variables. Thus, arrays can be made just large enough to accommodate data.
Note: The "stat=allocate_status" element of the allocatable statement enables the processor to report on the success or failure of the allocation process, in a manner similar to that in which an iostat specifier reports the success or failure of an input/output statement.
The following code fragment shows the usefulness of allocatable arrays.
subroutine space(n) implicit none integer :: n real, allocatable, dimension(:,:) :: a,b ! print *, 'enter n' read *, n allocate(a(2*n,6*n) !Allocate space for a ! Do your calculations using a . . . . deallocate(a) !Free space used by a ! allocate(b(3*n,4*n) !Allocate space for b ! Do your calculations using b . . . . deallocate(b) !Free space used by b end subroutine space
Note in this code fragment that the space used by the arrays is 12n2. Had the option to use allocatable arrays not been available, we would have had to use at least 24n2 array spaces. In truth, we would most likely have had to over-dimension arrays a and b, since the code fragment implies that the incoming integer n is a variable. This ability to allocate and deallocate memory space is very useful when doing large problems on machines with limited memory.