Difference between revisions of "Fortran"

From PHASTA Wiki
Jump to: navigation, search
Line 4: Line 4:
 
Some documentation of the language format can be found at [https://software.intel.com/content/www/us/en/develop/documentation/fortran-compiler-developer-guide-and-reference/top/language-reference.html Intel's Developer Guide]].  
 
Some documentation of the language format can be found at [https://software.intel.com/content/www/us/en/develop/documentation/fortran-compiler-developer-guide-and-reference/top/language-reference.html Intel's Developer Guide]].  
  
Fortran subroutines can also be documented using [[Doxygen]]. It'd recommended that you document your code in a Doxygen format, as we're looking to move to Doxygen for [[PHASTA]] documentation, plus Doxygen.
+
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 ==
 
== Miscellaneous Notes ==

Revision as of 17:22, 16 December 2020

Fortran (short for Formula Translation) 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

Equivalence Statement

Caution: The equivalence statement has been labeled obsolete in modern Fortran standards (see Intel compiler documentation).

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

real function fun_prod1(a, b)
    implicit none
    real, intent(in), dimension(4) :: a, b
    real, dimension(4) :: temp, sqrtab
    integer :: i

    temp = a*b
    sqrtab = sqrt(temp)
    temp = temp * 2.
    fun_prod1 = sum(temp + sqrtab)

    return
end function fun_prod1

While reusing the temp array for both a*b and 2*a*b is memory efficient (as we only need to have 2 1x4 arrays) 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 2*a*b to be different variables instead:

real function fun_prod2(a, b)
    implicit none
    real, intent(in), dimension(4) :: a, b
    real, dimension(4) :: ab, ab2, sqrtab
    integer :: i
    
    ab = a*b
    sqrtab = sqrt(ab)
    ab2 = ab * 2.
    fun_prod2 = sum(ab2 + sqrtab)

    return
end function fun_prod2

This is easier to read, as the contents of ab and ab2 are far less ambiguous. However, note that we are less memory efficient than before; we now require 3 1x4 arrays 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.

However, using the equivalence statement, we can get the best of both worlds:

real function fun_prod3(a, b)
    implicit none
    real, intent(in), dimension(4) :: a, b
    real, dimension(4) :: equiv__ab, equiv_2ab, sqrtab
    equivalence (equiv_ab, equiv_2ab)
    integer :: i
    
    equiv_ab = a*b
    sqrtab = sqrt(equiv_ab)
    equiv_2ab = equiv_ab * 2.
    fun_prod3 = sum(equiv_2ab + sqrtab)

    return
end function fun_prod3


Here, eqab</code and <code>eq2ab use the same memory, thus we only require 2 1x4 arrays. fun_prod3 is compiled as completely identical to fun_prod1, but it's more easily readable.

Note: equivalence can unexpected results if the programmer is not aware that two variables are made equivalent. That is why the variables ab and ab2 in fun_prod2 were changed to equiv_ab</code and <code>equiv_2ab. This serves as a reminder that variables with the prefix equiv_ belong to the same memory space, and thus cannot be treated as different.