In Fortran, subroutines are a fundamental way to modularize code. They allow programmers to encapsulate specific tasks into reusable blocks, improving readability, maintainability, and scalability of programs. Unlike functions, subroutines perform tasks but do not return values directly; instead, they may modify their arguments or produce output via other means.
This post provides a complete guide to declaring, using, and managing subroutines, including examples, passing arguments, intent specification, modular programming, and best practices.
1. Introduction to Subroutines
A subroutine is a named block of code designed to perform a specific task. Subroutines:
- Improve code reusability
- Enhance readability by reducing repeated code
- Can modify arguments or perform output operations
- Are invoked using the
callstatement
Basic Syntax
subroutine subroutine_name(arguments)
! Declaration of arguments
! Body of subroutine
end subroutine subroutine_name
Invoking a Subroutine
call subroutine_name(arguments)
2. Simple Example: Greeting Subroutine
Example 1: Subroutine with Character Input
program main
call greet("Fortran")
end program main
subroutine greet(name)
character(len=*), intent(in) :: name
print *, "Hello,", name
end subroutine greet
Explanation:
greetis a subroutine that prints a greetingintent(in)specifies that the argument is input onlycall greet("Fortran")invokes the subroutine from the main program
3. Passing Arguments
Subroutines can take multiple arguments, including integers, real numbers, logicals, and arrays.
Example 2: Sum of Two Numbers
program main
integer :: a, b, result
a = 5
b = 7
call add_numbers(a, b, result)
print *, "Sum:", result
end program main
subroutine add_numbers(x, y, sum)
integer, intent(in) :: x, y
integer, intent(out) :: sum
sum = x + y
end subroutine add_numbers
Explanation:
xandyare input argumentssumis an output argument- The subroutine calculates the sum and returns it via
sum
4. Using Intent Attributes
The intent attribute clarifies how arguments are used:
intent(in)– Read-only inputintent(out)– Output from subroutineintent(inout)– Both input and output
Example 3: Incrementing a Number
program main
integer :: value
value = 10
call increment(value)
print *, "Incremented value:", value
end program main
subroutine increment(number)
integer, intent(inout) :: number
number = number + 1
end subroutine increment
Explanation:
intent(inout)allows modification of the argument- The main program sees the updated value after the subroutine call
5. Subroutines with Arrays
Subroutines can process arrays to perform element-wise operations or aggregation.
Example 4: Doubling Array Elements
program main
integer :: arr(5)
integer :: i
arr = (/1,2,3,4,5/)
call double_array(arr)
print *, "Doubled array:"
do i = 1, 5
print *, arr(i)
end do
end program main
subroutine double_array(array)
integer, intent(inout) :: array(:)
integer :: i
do i = 1, size(array)
array(i) = array(i) * 2
end do
end subroutine double_array
Explanation:
array(:)indicates a one-dimensional array of arbitrary size- Each element is doubled using a loop
- Shows array processing inside subroutines
6. Modular Programming with Subroutines
Subroutines can be grouped into modules, which enhances organization and allows reuse across multiple programs.
Example 5: Using a Module
module math_utils
contains
subroutine square(x, result)
real, intent(in) :: x
real, intent(out) :: result
result = x**2
end subroutine square
end module math_utils
program main
use math_utils
real :: num, sq
num = 3.0
call square(num, sq)
print *, "Square of", num, "is", sq
end program main
Explanation:
math_utilsmodule contains reusable subroutinesquare- Main program uses
use math_utilsto access the subroutine - Modular design improves maintainability
7. Subroutines with Optional Arguments
Fortran allows optional arguments in subroutines, which can be omitted when calling.
Example 6: Optional Greeting
program main
call greet("Fortran")
call greet("World", "Good morning")
end program main
subroutine greet(name, salutation)
character(len=*), intent(in) :: name
character(len=*), intent(in), optional :: salutation
if (present(salutation)) then
print *, salutation, ",", name
else
print *, "Hello,", name
end if
end subroutine greet
Explanation:
optionalallows subroutine flexibilitypresentchecks if the argument was provided
8. Keyword Arguments in Subroutines
Subroutines support keyword arguments, improving readability and allowing arguments in any order.
Example 7: Keyword Arguments
program main
call display_values(b=20, a=10)
end program main
subroutine display_values(a, b)
integer, intent(in) :: a, b
print *, "a =", a, ", b =", b
end subroutine display_values
Explanation:
- Call uses keywords to specify arguments
- Enhances clarity and reduces errors in long argument lists
9. Subroutines Calling Other Subroutines
Subroutines can call other subroutines to create structured and hierarchical code.
Example 8: Nested Subroutine Calls
program main
call main_task()
end program main
subroutine main_task()
print *, "Starting main task..."
call subtask()
end subroutine main_task
subroutine subtask()
print *, "Executing subtask..."
end subroutine subtask
Explanation:
main_taskcallssubtask- Demonstrates modular, hierarchical design
10. Best Practices for Subroutines
- Use meaningful names – Describe the task clearly
- Specify intent – Avoid accidental modification of inputs
- Keep subroutines focused – Each subroutine should perform one task
- Use modules for reusability – Organize subroutines for multiple programs
- Document inputs and outputs – Clarifies usage for others
- Use optional and keyword arguments – Increases flexibility
- Avoid global variables – Pass data via arguments instead
11. Practical Applications
Subroutines are essential for:
- Mathematical computations – Sum, product, matrix operations
- Data processing – Array transformations, filtering
- Simulation control – Modular tasks for physics or engineering simulations
- User interface tasks – Printing messages or formatted outputs
- Modular programming – Grouping related routines into modules
12. Advanced Example: Temperature Conversion
program temperature_conversion
real :: celsius, fahrenheit
celsius = 25.0
call convert_to_fahrenheit(celsius, fahrenheit)
print *, celsius, "Celsius is", fahrenheit, "Fahrenheit"
end program temperature_conversion
subroutine convert_to_fahrenheit(c, f)
real, intent(in) :: c
real, intent(out) :: f
f = c * 9.0 / 5.0 + 32.0
end subroutine convert_to_fahrenheit
Explanation:
- Subroutine performs temperature conversion
- Main program receives converted value through output argument
13. Subroutines with Multiple Arrays
Subroutines can manipulate multiple arrays for matrix or vector operations.
Example 9: Element-wise Array Sum
program main
integer :: A(5), B(5), C(5)
integer :: i
A = (/1,2,3,4,5/)
B = (/5,4,3,2,1/)
call sum_arrays(A, B, C)
print *, "Sum of arrays:"
do i = 1, 5
print *, C(i)
end do
end program main
subroutine sum_arrays(arr1, arr2, result)
integer, intent(in) :: arr1(:), arr2(:)
integer, intent(out) :: result(size(arr1))
integer :: i
do i = 1, size(arr1)
result(i) = arr1(i) + arr2(i)
end do
end subroutine sum_arrays
Explanation:
- Demonstrates array manipulation in subroutines
- Subroutine handles element-wise computation for input arrays
Leave a Reply