Difference between revisions of "Fortran"
Conrad54418 (talk | contribs) |
|||
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 | + | 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.