Arrays are essential in Fortran programming for storing multiple values of the same type. Often, it is necessary to process each element individually, whether to perform calculations, modify values, or extract information. The DO loop is the primary mechanism for iterating through arrays efficiently. This post provides a detailed exploration of iterating through arrays with DO loops, including examples, best practices, and practical applications.
1. Introduction to DO Loops
A DO loop in Fortran allows the repeated execution of a block of code a fixed number of times. Its general syntax is:
do variable = start, end [, step]
! code block
end do
variable– Loop control variablestart– Initial valueend– Final valuestep– Optional increment (default is 1)
DO loops are ideal for accessing each array element sequentially.
2. Iterating Through One-Dimensional Arrays
A one-dimensional (1D) array can be thought of as a list of values. To access or modify each element, a DO loop is used.
Example: Doubling Array Elements
integer :: i
real :: arr(5)
arr = (/1, 2, 3, 4, 5/)
do i = 1, 5
arr(i) = arr(i) * 2
end do
print *, "Doubled array:", arr
Explanation:
- The loop variable
igoes from 1 to 5. arr(i)accesses each element sequentially.- Each element is multiplied by 2.
- Output:
Doubled array: 2.0 4.0 6.0 8.0 10.0
3. Iterating Through Two-Dimensional Arrays
Two-dimensional arrays, or matrices, require nested DO loops for iteration.
Example: Incrementing Elements in a 3×3 Matrix
integer :: i, j
real :: matrix(3,3)
matrix = reshape((/1,2,3,4,5,6,7,8,9/), (/3,3/))
do i = 1, 3
do j = 1, 3
matrix(i,j) = matrix(i,j) + 1
end do
end do
print *, "Incremented matrix:"
do i = 1, 3
print *, matrix(i,:)
end do
Explanation:
- Nested loops iterate through rows (
i) and columns (j). - Each element is incremented by 1.
- Output:
Incremented matrix:
2.0 3.0 4.0
5.0 6.0 7.0
8.0 9.0 10.0
4. Using Step Values in DO Loops
The step value allows skipping elements or iterating in increments other than 1.
Example: Doubling Every Second Element
integer :: i
real :: arr(5)
arr = (/1, 2, 3, 4, 5/)
do i = 1, 5, 2
arr(i) = arr(i) * 2
end do
print *, "Doubled every second element:", arr
i = 1, 3, 5– Only odd indices are modified.- Output:
Doubled every second element: 2.0 2.0 6.0 4.0 10.0
5. Iterating Through Multi-Dimensional Arrays
For arrays with more than two dimensions, nested loops are required for each dimension.
Example: 3D Array Iteration
integer :: i, j, k
real :: tensor(2,2,2)
tensor = reshape((/1,2,3,4,5,6,7,8/), (/2,2,2/))
do i = 1, 2
do j = 1, 2
do k = 1, 2
tensor(i,j,k) = tensor(i,j,k) * 2
end do
end do
end do
print *, "Doubled tensor elements:"
do i = 1, 2
do j = 1, 2
print *, tensor(i,j,:)
end do
end do
Explanation:
- Nested loops iterate through all dimensions.
- Each element is multiplied by 2.
6. Combining Loops with Conditional Statements
You can use IF statements inside loops to selectively process elements.
Example: Doubling Only Positive Elements
integer :: i
real :: arr(5)
arr = (/ -1, 2, -3, 4, 5 /)
do i = 1, 5
if (arr(i) > 0) then
arr(i) = arr(i) * 2
end if
end do
print *, "Doubled positive elements:", arr
Output:
Doubled positive elements: -1.0 4.0 -3.0 8.0 10.0
7. Iterating Through Arrays with EXIT and CYCLE
DO loops can be combined with EXIT and CYCLE for precise control.
Example: Skip and Stop Iteration
integer :: i
real :: arr(5)
arr = (/1,2,3,4,5/)
do i = 1, 5
if (arr(i) == 3) cycle
if (arr(i) == 5) exit
arr(i) = arr(i) * 2
end do
print *, "Modified array:", arr
Explanation:
cycleskips iteration whenarr(i) == 3.exitstops the loop whenarr(i) == 5.- Output:
Modified array: 2.0 4.0 3.0 8.0 5.0
8. Iterating Using Array Bounds
For dynamic arrays, use lbound and ubound to determine array size:
integer :: i
real, allocatable :: arr(:)
allocate(arr(5))
arr = (/1,2,3,4,5/)
do i = lbound(arr,1), ubound(arr,1)
arr(i) = arr(i) * 2
end do
print *, "Doubled array:", arr
Explanation:
lbound(arr,1)– Lower bound of first dimensionubound(arr,1)– Upper bound of first dimension- Makes loops safe for dynamically sized arrays.
9. Iterating Through Multi-Dimensional Arrays Efficiently
Fortran stores arrays in column-major order, which means that elements in a column are contiguous in memory.
- Iterating over columns first can improve performance for large arrays.
Example: Column-major Iteration
integer :: i, j
real :: matrix(3,3)
matrix = reshape((/1,2,3,4,5,6,7,8,9/), (/3,3/))
do j = 1, 3
do i = 1, 3
matrix(i,j) = matrix(i,j) * 2
end do
end do
- Accessing elements in column-major order can improve cache efficiency.
10. Using Loops for Array Calculations
10.1 Sum of Elements
integer :: i
real :: sum, arr(5)
arr = (/1,2,3,4,5/)
sum = 0.0
do i = 1, 5
sum = sum + arr(i)
end do
print *, "Sum of array elements:", sum
- Output:
Sum of array elements: 15.0
10.2 Maximum Element
integer :: i
real :: max, arr(5)
arr = (/1, 7, 3, 4, 5/)
max = arr(1)
do i = 2, 5
if (arr(i) > max) then
max = arr(i)
end if
end do
print *, "Maximum element:", max
- Output:
Maximum element: 7.0
11. Iterating Through Arrays in Functions
Loops can be used inside functions to process arrays:
function sumArray(arr) result(total)
real, intent(in) :: arr(:)
real :: total
integer :: i
total = 0.0
do i = lbound(arr), ubound(arr)
total = total + arr(i)
end do
end function sumArray
! Main program
real :: arr(5) = (/1,2,3,4,5/)
print *, "Sum using function:", sumArray(arr)
- Functions allow reusable array processing routines.
12. Iterating with Array Slices
You can combine DO loops with array slices for partial processing:
integer :: i
real :: arr(10)
arr = (/1,2,3,4,5,6,7,8,9,10/)
do i = 3, 7
arr(i) = arr(i) * 2
end do
print *, "Modified subarray:", arr
- Only elements 3 to 7 are modified.
13. Iterating Through Logical or Character Arrays
DO loops are not limited to numeric arrays.
Example: Logical Array
integer :: i
logical :: flags(5) = (.true., .false., .true., .false., .true.)
do i = 1, 5
if (flags(i)) then
print *, "Flag", i, "is true"
end if
end do
- Output:
Flag 1 is true
Flag 3 is true
Flag 5 is true
Example: Character Array
integer :: i
character(len=5) :: names(3) = (/ "Alice", "Bob", "Eve" /)
do i = 1, 3
print *, "Name", i, ":", names(i)
end do
14. Practical Applications
- Data Processing: Scaling, filtering, or transforming datasets.
- Matrix Operations: Addition, multiplication, or transposition.
- Simulations: Iterating over grid points in 1D, 2D, or 3D simulations.
- Statistics: Calculating sum, mean, maximum, or standard deviation.
15. Best Practices
- Use
lboundanduboundfor dynamic arrays. - Prefer column-major order for large 2D arrays to optimize performance.
- Minimize nested loops where possible to reduce computational cost.
- Combine loops with conditional statements for selective processing.
- Document loop structure and array dimensions for readability.
Leave a Reply