# Fortran

**Fortran** (short for **For**mula **Tran**slation) is a programming language geared towards numerical computation.

## Documentation

Some documentation of the language format can be found at Intel's Developer Guide.

Fortran subroutines can also be documented using Doxygen. It is recommended that you document your code in a Doxygen format, as we're looking to move to Doxygen for PHASTA documentation.

## Miscellaneous Notes

### Associate Statement

Associate is effectively the replacement for (and better version of) the equivalence statement (which was formerly documented here, removed to reduce confusion). Effectively, it adds clarity to programming by allowing you to name "temporary variables"

The `associate`

statement allows different variable names to reference the same data storage (ie. memory allocation).
A common paradigm in PHASTA is the use of temporary arrays to store the partial result of calculations that maybe reused multiple times.
For example, the function below calculates sum over i of [ (sqrt(a) * sqrt(b))^2_i + sqrt(a * b)_i ], where a and b are vectors:

function example_func1(a, b) result(c) implicit none real, intent(in), dimension(4) :: a, b real, intent(out) :: c real, dimension(4) :: temp temp = a*b c = sqrt(temp) temp = sqrt(a)*sqrt(b) c = c + temp**2 return end function example_func1

While reusing the `temp`

array for both a*b and sqrt(a)*sqrt(b) is memory efficient (as we only need to have 2 1x4 arrays, `temp`

and `c`

) and computationally efficient (as we calculate a*b only once), it's not very easy to read as the *definition* of `temp`

changes throughout the code.

To improve the legibility, we could set a*b and sqrt(a)*sqrt(b) to be different variables instead:

function example_func2(a, b) result(c) implicit none real, intent(in), dimension(4) :: a, b real, intent(out) :: c real, dimension(4) :: ab, ab_sqrt ab = a*b c = sqrt(ab) ab_sqrt = sqrt(a)*sqrt(b) c = c + ab_sqrt**2 return end function example_func2

This is easier to read, as the contents of `ab`

and `ab_sqrt`

are far less ambiguous.
However, note that we are less memory efficient than before; we now require 3 1x4 arrays (`ab`

, `ab_sqrt`

, and `c`

) compared to the previous 2.
This may not seem like much, but memory speed is often the bottle-neck when it comes to HPC performance, so a 50% increase in required memory is significant.
This is especially true when you deal with arrays with millions of elements rather than just 4.

However, using the `associate`

statement, we can get the best of both worlds:

function example_func3(a, b) result(c) implicit none real, intent(in), dimension(4) :: a, b real, intent(out) :: c real, dimension(4) :: temp associate(ab => temp) ab = a*b c = sqrt(ab) end associate associate(ab_sqrt => temp) ab_sqrt = sqrt(a)*sqrt(b) c = c + ab_sqrt**2 end associate return end function example_func3

Here, `ab`

and `ab_sqrt`

use the *same memory*, thus we only require 2 1x4 arrays. `example_func3`

is compiled as completely identical to `example_func1`

, but it's more easily readable.
It also has the nice effect of separating the code into computation chunks; if you use temporary variables, each new associate block represents a new "task" being completed.