Introduction to Fortran90 Programming Part 3


Introduction to Fortran90 Programming Part3

9. Arrays
So far in this course, you have dealt with variables which have one value.
But this would be a difficult way to work with a vector or matrix, which could
contain many values. Instead, vectors and matrices can be stored in arrays,
which can contain many elements. Individual elements of the array are
identified by the use of subscripts. For example, the position vector of a
point in space (x,y,z) could be represented by the one-dimensional array r.
Array r would contain 3 elements, with r(1) representing the x coordinate,
r(2) the y coordinate and r(3) the z coordinate.
Fortran 90 allows arrays to have up to 7 dimensions. An array is declared in
the normal way using a declaration at the beginning of the program, but
both the type of array (real, integer, etc) and the dimensions of the array
must be declared. So, for example, the 3-element vector above might be
declared as
real,dimension(3)::r
This states that r is an array with three elements in one dimension. Since r
is declared as a real array, each element of r will contain a real value.
Similarly, a 2 by 3 integer matrix might be declared as:
integer,dimension(2,3)::mymat
and every element of mymat would be an integer. Note that the array
mymat has 2 rows and 3 columns.
Note that it would also be possible to declare mymat as:
integer::mymat(2,3)
This format is more convenient when you wish to declare arrays of different
sizes in the same declaration statement.
Fortran 90 allows you to perform calculations with an array in one of
several ways:
• apply the same operation to all elements of the array, e.g. multiplying by 2.
• apply a single operation to the whole array, e.g. calculating the sum of
the elements.
• perform a calculation on individual elements.
• perform a calculation with elements that match a certain condition, e.g.
all elements with values greater than zero.
The following subsections describe these options.
9.1 Whole array elemental operations
Fortran 90 allows you to perform calculations on all the elements of an
array at once using whole-array elemental operations. Nearly all intrinsic  functions work on arrays, so if a and b are arrays with the same shape,
then the following are all valid:
Type in the simple program below, which reads in the components of two
vectors and then calculates the sum of the vectors. Call your program
vector1.f90. Use some trial values to check that the program sums the
vectors correctly.

program vector1
! Program to add two vectors
implicit none
real, dimension(3):: vect1, vect2, vectsum
!
! Read in the elements of the two vectors
!
write(*,*)' Enter the three components of vector 1: '
read(*,*) vect1
write(*,*)' Enter the three components of vector 2: '
read(*,*) vect2
!
! Now add the vectors together by adding their components
!
vectsum = vect1 + vect2
write(*,10) vectsum
!
10 format(' The sum of the vectors is: ', 3f6.2)
stop
end program vector1

9.2 Whole array operations
Some intrinsic functions work on arrays in a different way. For example, the
sum function operates on a whole array to find the sum of all the elements.
Unlike the functions that you have used so far, this function is specific to
arrays. Some more intrinsic functions that are specific to arrays are:
Exercise 
The length of a vector r is given by 
where r1, r2 and r3 are
the components of the vector. Edit your program vector1.f90 to find the 
length rlen of the vector vectsum. Call your new program vector2.f90 and 
test it with some trial values. 
Hint: try the functions sqrt and sum. 
9.3 Working with subsections of arrays 
9.3.1 Selecting individual array elements 
If you wish to work with a single element of an array, refer to it specifically. 
For example, the three elements of vector vect1 are referred to as vect1(1), 
vect1(2) and vect1(3), so the length of vect1 could be calculated explicitly 
as: 
length = sqrt( vect1(1)**2 + vect1(2)**2 + vect1(3)**2 ) 
When you work with multi-dimensional arrays, it is important to know which 
subscript refers to which dimension, e.g. when you multiply two matrices. 
The pattern of the elements in a 2 by 3 matrix mymat can be visualised as: 
(1,1) (1,2) (1,3) 
(2,1) (2,2) (2,3) 
so the top left element would be mymat(1,1) and the bottom right one 
would be mymat(2,3). 
Note that array element numbering starts by default at element 1 (not zero). 
It is possible to assign a different range for the subscripts which identify the 
elements in the array. For example, in the above case a 2 by 3 integer 
array could also have been declared in the form: 
integer,dimension(0:1,-1:1):: mymatrix 
In this case the array is of the same 2 by 3 form but the range of the 
subscripts has been changed and the pattern of elements can now be 
visualised as: 
(0,-1) (0,0) (0,1) 
(1,-1) (1,0) (1,1) 
and the array elements must now be addressed using the modified 
subscript indices. If you choose to reference your arrays in this way, you should be aware that functions such as maxloc give the location of an 
element, not the subscript. 

Note: One of the most frequent problems with arrays is an array bound 
error. This occurs when a program attempts to read or write to an array 
element that does not exist, such as the 11th element of a 10-element array. 
Section 12 describes how to use the compiler to help avoid or correct such 
errors. 

Exercise 

Write a program mat1.f90 that requests two 2x2 integer matrices from the 
keyboard and then multiplies them. Using references to individual array 
elements, display the input matrices and the result in the order: 
(1,1) (1,2) 
(2,1) (2,2) 
Check that the ordering of elements in the matrices is as you expected and 
that the multiplication is correct for this ordering. 

9.3.2 Selecting array sections 

A subsection of an array can be selected by specifying a range of 
subscripts. For example, the selection mymat(1:2,2:3) would select these 
elements from a 4 by 4 matrix: 


If one end of the range is left out, the lower or upper bound of the array is 
used as a default. The following examples are valid subsections of arrays: 



9.3.3 Using masks 

Sometimes you may not wish to apply a function to every element in an 
array. For example, it would not be appropriate to apply the log function to 
elements with negative values. Under these circumstances, use of a mask
allows you specify which elements to include. 
To illustrate use of a mask, consider the following statement: 
                        where(a>0) b = log(a) 
The where statement is used to perform an array operation only on 
elements where a certain logical condition is true. In the example above, a
and b are arrays with the same shape. The beginning of the statement, 
where (a>0), generates a mask of locations where the elements of a have 
values greater than zero. This mask is then applied to the rest of the 
statement. So the whole statement causes the operation b=log(a) to be 
performed for all elements of a that are greater than zero. Wherever a is 
zero or less than zero, the operation is not performed and the 
corresponding element of b is unchanged. 
The condition a>0 that forms the core of this example is a logical 
expression: the value of the expression is either .true. or .false.. Part 4 of 
this course gives more details of how to construct and use logical 
expressions to control the operation of your programs, including information 
on how to construct longer where statements. 
Most array-based functions can use a mask directly. The examples in the 
table below are functions that make particular use of a mask: 
Exercise 
Imagine that your department has asked you to write a program that 
records students' exam marks. Every student who scores more than 50% 
has passed the exam. You will need to use arrays to record the students' 
names, their marks and whether they have passed. The department has 
also asked that you calculate the total number who have passed, the 
average mark, and identify the person with the top mark. Write a prototype 
program called results1.f90 which processes results for 5 students and 
produces output similar to the following:



9.4 Allocatable arrays 
All the arrays that you have seen so far have been declared with a fixed 
size. Space for fixed-size arrays is allocated when a program is compiled 
and it cannot be changed without editing the program. Sometimes this can 
be inconvenient, for example when you do not know the size of the array in 
advance, or when you would like to re-use the memory space taken up by a 
large array that is used only for a short time within a program. Under these 
circumstances it can be more useful to use allocatable arrays. 
The space for allocatable arrays is allocated in a manner similar to the way 
that files are opened and closed: you must allocate space for the array 
before you use it, and you must deallocate the space when you have 
finished with the array. 
Since the size of an allocatable array is not known at the beginning of the 
program, its declaration gives the dimension of the array but not the size. 
Colons (:) are used to indicate the number of dimensions. The following 
statement declares an allocatable, 2-dimensional array: 
             real, dimension(:,:), allocatable:: myarray 
Later on in the program, the size of the array is calculated in some way and 
space for the array is allocated. Notice that the size of each dimension 
must be an integer, e.g: 
                        read(*,*) idim1, idim2 
               allocate(myarray(idim1,idim2)) 
Now that space for it has been allocated, the array myarray can be used as 
usual. Once it is no longer needed, the memory space is freed by the 
deallocate command: 
deallocate(myarray) 
Useful functions for working with allocatable arrays include: 
Some examples of allocatable arrays are given later in this course. 


10. Parameters and initial values
If you have a program with many arrays, it can be difficult to remember why
particular arrays have particular sizes. One way round this is to use
parameters in your array declarations, as illustrated below:
 program arrays 
 integer,parameter:: imax=100, jmax=200 
 real,dimension(imax):: array1 
 real,dimension(imax,jmax+imax):: array2 
 real,dimension(3):: array3
etc....
In this program fragment, definitions of some parameters are included
among the declarations. The parameters are not variables because they
cannot be changed later in the program. Notice that the value of the
parameter is set in its declaration statement.
Once it has been declared, a parameter can be used wherever you would
use a constant, including in array declarations as shown. This can help
avoid errors if you edit your program later to accommodate different array
sizes, because you need only make the changes in one place. Notice the
position of the parameter declaration: it must come before the parameters
are used.
Values for variables can also be set in the declaration statements.
However, because the values of variables can be changed during operation
of the program, these will be initial values only. The example above could
have initialised the three arrays as follows:
 Prog1ram arrays 
 integer,parameter:: imax=100, jmax=200 
 real,parameter:: pi=3.14159 
 real,dimension(imax):: array1=pi
 real,dimension(imax,jmax+imax)::array2=0.0  
 real,dimension(3):: array3=(/1.5,2.0,2.5/) 
etc.... 
All the elements in an array can be set to the same initial value as shown
for array1 and array2, while the syntax for entering several initial values is
shown for array3. Notice that initial values can only be constant
expressions.
Exercise
Edit your program results1.f90 so that the number of students in the class
is described as a parameter.




Post a Comment

0 Comments