Fortran/Fortran overview

From Wikibooks, open books for an open world
Jump to navigation Jump to search

Part of the Fortran WikiBook

This section is a quick reference on changing from other languages to Fortran.

Common Mistakes[edit | edit source]

Listed below are some common mistakes made when using Fortran by users of C or Java:

  • Perhaps the most common mistake when moving from one language to another is to try to make the new language look or act too much like the previous language in use. When switching to Fortran (for whatever reason) consider doing things the Fortran way, rather than as you would in some other language.
  • In Fortran, variables need not be declared. A new variable beginning with I through N (the "in" group) is an INTEGER. A variable beginning with some other letter is a REAL. So, the disadvantage is that a typo could result in a new variable. The advantage is that coding is fast and easy, in that for most cases, no variables need be declared. If you want Fortran to act like declaration required languages, use IMPLICIT NONE at the top of each program, function, and subroutine.
  • Arrays are indexed from 1 to N, not 0 to N−1.
  • Arguments passed to functions and subroutines are passed by reference and not by value. Additionally, languages like C typically push each of their arguments onto the stack. Many (if not most) Fortran implementations build an array of argument addresses, and push the address of that array (only) onto the stack. This uses slightly more storage, but less executed code if you average more than 1 argument. The C-user error occurs when you think you know the addresses of argument references.
  • Note that arguments may need to be declared, and might not, as per the rules above.
  • For fixed form code, the first 6 columns have special meanings, and you can only use the first 72 columns.
  • Trying to use allocation too much. When in Fortran, try to use static allocation of arrays whenever possible.
  • Thinking you know how big a variable is—Here are the rules: LOGICAL can be any number of bytes. INTEGER is at least as big as LOGICAL. REAL is at least as big as INTEGER. DOUBLE PRECISION is at least as big as REAL. And finally, COMPLEX is twice as big as REAL. Typically, the sizes are 1, 4, 4, 8, and 8 bytes, respectively, but don't rely on that if you're writing portable code. A related mistake is thinking that LOGICAL*4 or REAL*8 gives you data 4 or 8 bytes wide. The number following the * is a suggestion, not a requirement.

Variables[edit | edit source]

C / C++

int i;
double x[3];
double *y = NULL;
y = new double[3];
delete[] y;
{ 1, 2, 3}; // <- Do the semantics match exactly?

Fortran (with two examples of allocation and deallocation—don't use both at once)

INTEGER i
DOUBLE PRECISION x(3)
DOUBLE PRECISION, DIMENSION(:), ALLOCATABLE :: xx
DOUBLE PRECISION, POINTER, DIMENSION(:) :: y => null()
ALLOCATE(xx(3))
DEALLOCATE(xx)
ALLOCATE(y(3))                    ! memory allocation for pointer - similar syntax to array allocation
DEALLOCATE(y)                     ! again similar syntax as for array allocation / deallocation 
(/ 1, 2, 3 /)

Caveat: Fortran's arrays are more flexible than plain C arrays. By default they are indexed from 1 not 0.

They may be declared to be indexed by different means:

REAL, DIMENSION(-2:10) :: A

means you can use A(10) as well as A(-2).

Multidimensional arrays should be declared this way:

REAL A(5,7,10)

You will have 5*7*10 elements from A(1,1,1) to A(5,7,10). Note memory is laid out in a way unique to Fortran. The element in memory following A(1,1,1) is A(2,1,1), and not A(1,1,2).

You can use parts of array this way:

REAL A(10,10)
REAL B(3,3)
B(1:3,2:3)=A(4:6,7:8)

will act as

DO i=1,3
  DO j=2,3
    B(i,j)=A(i+3,j+5)
  END DO
END DO

Which is the same as the archaic but shorter form

DO 1 i=1,3
  DO 1 j=2,3
    1 B(i,j)=A(i+3,j+5)

Functions & Subroutines[edit | edit source]

In Fortran, FUNCTIONs return a value whereas SUBROUTINEs do not. In C/C++ this is simply the distinction between returning a value or returning void. In Fortran, the name of the function is assigned to return a value from a function. When calling, a subroutine is called with the CALL keyword whereas a function is called as in C/C++. When there are no arguments, an empty parenthesis is not needed.

C/C++:

int foo(int i, int j) {
  ...
  return 42;
}
// then later:
int x = foo(1, 2);

Fortran:

INTEGER FUNCTION foo(i, j)
...
foo = 42
END
C then later:
k = foo(1, 2)

C/C++:

void bar(double j) {
  ...
}
void baz() {
  ...
  return; // Can return in the middle.
  ...
  return; // Optional for a function returning void.
}
// then later:
bar(42.0);
baz();

Fortran:

SUBROUTINE bar(x)
...
RETURN
...
END
SUBROUTINE baz
...
END
C then later:
CALL bar(42.0)
CALL baz

Control structures[edit | edit source]

if → if, then, else, end if[edit | edit source]

C / C++

if (...) {
  ... 
} else if ( ... ) { 
  ...
} else { 
  ...
}

Fortran

if (...) then
   ...
else if (...) then
  ...
else
  ...
end if

switch → select case, case, end select[edit | edit source]

C/C++

switch (...) {
case ...:
  ...;
  break; // Without "break", control "falls through" to the next case.
default: // The "default" case is optional but advisable.
  ...;
  break; // Not necessary for the last case.
}

Fortran

select case(...)
   case (...)
      ...
   case default
      ...
end select

Iteration[edit | edit source]

for → do, end do[edit | edit source]

C/C++

for (i = 1; i <= 10; i++) { ... }

Fortran

do i=1,10
   ...
end do

External links[edit | edit source]