Content from A Trivial Program
Last updated on 2025-05-01 | Edit this page
Estimated time: NA minutes
Overview
Questions
- How do you write programs in Fortran?
- How do you compile the Fortran code to make an executable?
- How do we run that executable and see any output?
Objectives
Be able to
- write
- compile
- run
a basic Fortran program.
During the setup you compiled a simple hello world
program. Let’s look at that program in more detail:
The first statement program hello_world
starts the
program. It also defines the program name, hello_world
. It
is matched by the end
statement
(end program hello_world
). The end
statement
is always the last statement in a program.
program
on its own marks the start of a program and
end
on its own will end the program. Words that follow
program
or end
are labels which improve
readability. Some legacy codes may not have labels.
Implicit None
Some variables in Fortran have a default type. Variables with names
beginning with letters i-n
are implicitly of type
integer
Anything else is of type real
.
This is very bad practice and modern Fortran should not be used in this way.
To prevent implicit typing we add the:
statement to all programs
(and modules
,
functions
, and subroutines
that you will
encounter in later episodes).
Now all variable names must be declared explicitly before they are referenced.
The only executable line in this program is the print
statement. We will cover IO in a later episode. For now, know that
print *,
will print what follows to standard output when
the program runs. In this case, it will print the string
Hello world!
to our terminal.
Comments
Comments start with an exclamation mark !
. Comments can
appear on their own line, or after any other Fortran statement.
Add comments to hello_world.f90
Add two comments to your file:
- The first should explain what the program does
- The second should explain the purpose of
implicit none
Think about where the best place for these comments are.
FORTRAN
program hello_world
!! A simple hello world program
implicit none ! prevent implicit typing (to integers) of variables
! whose name starts with the letters i-n
print *, 'Hello world!'
end program hello_world
- We have placed a comment describing the program under the
program
statement. You might also see program descriptions before theprogram
statement. Note the double!
at the start of the comment. This allows the automatic documentation generator FORD to extract documentation from the comment. - The second comment could have been placed before or after the
implicit none
statement. We have shown an inline comment. Note the two spaces between the Fortran and the start of the comment, and the comment spans multiple lines with each!
aligned vertically.
You may have noticed comments at the top of the Fortran files you downloaded during the setup. Those comments provide licensing and authorship information.
Compiling
Fortran is a compiled language (like C++). A compiler turns human-readable source code into machine code. This machine code can then be executed by the computer. Languages like Python are interpreted. This means Python source code is executed directly without being compiled into machine code first. The program is parsed, interpreted, and executed each time it is run. Compiled programs are usually more efficient than interpreted programs. This is a major reason that compiled languages like Fortran remain popular. The draw back is that there is an extra step in building Fortran programs.
There are several steps1 that occur during compilation. Your compiler takes care of each step for you. To test your compiler in the setup episode you ran:
This created a file named a.out
. This is the default
executable name if no name is specified. To tell the compiler the name
of the executable use the -o
flag:
Now run ls
to see the new executable:
OUTPUT
hello_world hello_world.f90
We now have an executable called hello_world
. Sometimes
code can compile but fail when executed2. Let’s run this
executable to check it works:
OUTPUT
Hello world!
Compiler Documentation and Flags
Take a moment to find and bookmark the documentation for your compiler. Find the correct flags to:
- Turn on debugging
- Specify the default optimisation level
Filenames
Fortran files normally end in .f90
, although they can
have different file
extensions. The .f90
extension is the most widely
recognised across compilers. You may see Fortran files with an
upper-case extension .F90
. This tells the compiler to pre-process
the file before compiling.
In the next episode we will introduce variable declaration, and you will write your first Fortran program from scratch.
Key Points
- Fortran programs start with the
program <label>
statement. - Fortran programs end with the
end program <label>
statement. - Always use
implicit none
to prevent implicit typing for variables. - Fortran comments start with
!
. - The
-o
flag specifies the name of the compiled executable:<compiler_command> -o <executable_name> <source_file.f90>
.
Compilation steps for a C program: https://www.geeksforgeeks.org/compiling-a-c-program-behind-the-scenes/, the steps are the same for Fortran!↩︎
If a program fails to compile that’s a compiler error. If a program compiles but fails to run that’s a runtime error.↩︎
Content from Variables
Last updated on 2025-05-01 | Edit this page
Estimated time: 30 minutes
Overview
Questions
- How do we declare and assign values to variables?
Objectives
- Understand the different intrinsic data types.
- Declare and assign variables and parameters.
Variables store information we can use in our programs. Fortran is a strongly typed language. Each variable must be declared with a type.1 Fortran provides the following intrinsic (built-in) data types for variables:
-
integer
: A whole number which is positive, negative or zero. -
real
: A real number includes the fractional part, even if the fractional part is 0. -
complex
: A number made up of a real and an imaginary part. -
logical
: A boolean value which can be .true. or .false.. -
character
: A single ASCII character. Strings are made from sequences of characters.
Variable names must be 63 characters or less (F2003 standard). No
spaces are allowed. Names can contain the characters a-z
,
A-Z
, 0-9
and the underscore _
. No
spaces are allowed. Names must begin with a letter. This also applies to
names for programs, modules, subroutines, and functions, which you will
learn about later in the course.
Do not use Fortran keywords as variable names. Fortran will let you overwrite these keywords if you’re not careful. The Fortran wiki keywords page contains a list of all Fortran keywords.
Declaring Variables
Fortran variables are declared with this syntax:
So to declare an integer:
For this episode complete challenges in:
Create a variables
program
- Create a new Fortran program named
variables.f90
. - Declare 5 variables. One of each of the 5 intrinsic data types.
- Print your variables.
- Compile and run your program.
What do you notice about the output?
FORTRAN
program variables
implicit none
integer :: number_of_pelicans
real :: pelican_weight
complex :: pelican_population_dynamics
logical :: is_young_pelican
character :: pelican_tag
print *, number_of_pelicans
print *, pelican_weight
print *, pelican_population_dynamics
print *, is_young_pelican
print *, pelican_tag
end program variables
The output below is from the GNU gfortran compiled executable:
OUTPUT
-922534656
0.00000000
(2.063298560E+11,0.00000000)
T
Where did those values come from? If you forget to assign a value to a variable the output will depend on your compiler. Here the program accessed the memory allocated for each variable and printed what was leftover in the memory from other processes.
Most compilers have a flag which warns you if there are uninitialised variables in your code. Have a look and see if there is a flag like this for your compiler.
- Fortran is case-insensitive. This course prefers the use of lowercase.
- Fortran file names must match the name of the program or module
contained in the file. ie.
variables.f90
contains the programvariables
.matrix_mod.f90
contains the modulematrix_mod
. -
::
markers should be aligned to improve readability.
Variable Assignment
Variables are assigned using the assignment operator
=
:
For example:
FORTRAN
number_of_pelicans = 5
pelican_weight = 2.5 ! kg
pelican_population_dynamics = (-1.2e3, 0.9e2) ! Scientific notation, -1,200 etc
is_young_pelican = .false.
pelican_tag = 'Jeff'
Logicals can be .true.
or .false.
.
Characters (strings) such as pelican_tag
can be surrounded
by single or double quotes.
Modify your variables
program
- Assign values to the variables in your program.
- Compile and run your program.
FORTRAN
program variables
implicit none
integer :: number_of_pelicans
real :: pelican_weight
complex :: pelican_population_dynamics
logical :: is_young_pelican
character :: pelican_tag
number_of_pelicans = 5
pelican_weight = 2.5 ! kg
pelican_population_dynamics = (-1.2e3, 0.9e2)
is_young_pelican = .false.
pelican_tag = 'J'
print *, number_of_pelicans
print *, pelican_weight
print *, pelican_population_dynamics
print *, is_young_pelican
print *, pelican_tag
end program variables
Example output:
OUTPUT
5
2.50000000
(-1.20000005,0.899999976)
F
J
- The assignment operator
=
should be aligned to improve readability. - Variable names are written in snake case and are verbose.
- Variables with units must have a comment (Ford or vanilla Fortran style) with the unit.
Assignment on declaration
Fortran lets you assign a value to a variable when you declare it.
This gives the variable the save
attribute. With
save
the variable will keep its value between procedure
(function) calls. This is not good practice. Never assign a value to a
variable on declaration unless it’s a parameter.
Parameters
In your program, it is possible to change the values of initialised variables, e.g.
FORTRAN
program variables
implicit none
integer :: number_of_pelicans
real :: pelican_weight
complex :: pelican_population_dynamics
logical :: is_young_pelican
character :: pelican_tag
number_of_pelicans = 5
pelican_weight = 2.5 ! kg
pelican_population_dynamics = (-1.2e3, 0.9e2)
is_young_pelican = .false.
pelican_tag = 'J'
! print *, number_of_pelicans
! print *, pelican_weight
! print *, pelican_population_dynamics
! print *, is_young_pelican
print *, pelican_tag
! Changing the value of the tag
pelican_tag = 'F'
print *, pelican_tag
end program variables
This will now give the output:
OUTPUT
J
F
However, you can also define constant values that cannot change. You
do this by defining variables using parameter
. We are then
unable to modify parameter
variables, e.g.
Add a parameter to your variables
program
- Modify a variable in your code to be a parameter.
- Try modifying the parameter in your code. What output do you get when compiling?
FORTRAN
program variables
implicit none
integer :: number_of_pelicans
real :: pelican_weight
complex :: pelican_population_dynamics
logical :: is_young_pelican
character, parameter :: pelican_tag = 'J'
number_of_pelicans = 5
pelican_weight = 2.5 ! kg
pelican_population_dynamics = (-1.2e3, 0.9e2)
is_young_pelican = .false.
! pelican_tag = 'J'
print *, number_of_pelicans
print *, pelican_weight
print *, pelican_population_dynamics
print *, is_young_pelican
print *, pelican_tag
pelican_tag = 'F'
end program variables
Here we have modified pelican_tag
to be the parameter.
Then at the end of the program we attempt to change its value.
Example GFortran output:
OUTPUT
variables.f90:23:4:
23 | pelican_tag = 'F'
| 1
Error: Named constant ‘pelican_tag’ in variable definition context (assignment) at (1)
The compiler has given us an error. This is because we are trying to
edit the value, variable definition context (assignment)
,
of a parameter, Named constant
. The error is in the
variables.f90
file, on line 23
, starting at
character 4
. This location has been marked as
1
in the compiler output.
Different compilers will show different error messages. Some have clearer messages for certain errors than others. We recommend testing code with at least two compilers. This will aid your debugging and help make your code more portable.
Tidy up your program
- Make sure your code conforms to the style followed by this course.
- Add Ford comments to document the program and each variable.
FORTRAN
program variables
!! A test program to lean how to declare and assign variables.
implicit none
integer :: number_of_pelicans
!! The number of pelicans in the pod
real :: pelican_weight
!! The average weight of a pelican in the pod / kg
complex :: pelican_population_dynamics
!! The birth and death rate as a complex number
!! Units are the number of pelicans per year
logical :: is_young_pelican
!! Test to see if the current pelican is young
character, parameter :: pelican_tag = 'J'
!! Pelican pod tracking tag
number_of_pelicans = 5
pelican_weight = 2.5 ! kg
pelican_population_dynamics = (-1.2e3, 0.9e2) ! births, deaths per year
is_young_pelican = .false.
print *, number_of_pelicans
print *, pelican_weight
print *, pelican_population_dynamics
print *, is_young_pelican
print *, pelican_tag
end program variables
Notice we have left an extra blank line in-between the parameter
declaration and the other variable declarations. This is so we didn’t
have to align all the ::
markers far to the right. If you
are declaring lots of variables, break up the declarations into sections
for readability.
Key Points
- There are 5 intrinsic data types for Fortran variables:
integer
,real
,complex
,logical
, andcharacter
. - Fortran variables are declared with the syntax:
<variable_type> :: <variable_name>
- Assign a value to a variable with the syntax:
<variable> = <value>
- Never assign a value on the same line as a variable is declared.
This gives the variable the
save
attribute. - Parameters are variables whose value can’t be changed:
<variable_type>, parameter :: <variable_name> = <variable_value>
.
Fortran is also statically typed. You can not change a variables type after the variable declaration.↩︎
Content from Maths
Last updated on 2025-04-29 | Edit this page
Estimated time: 30 minutes
Overview
Questions
- How do we perform calculations in Fortran?
Objectives
- Use the built in operators and intrinsic functions.
- Specify the precision of our numeric variables.
In this episode we will look at arithmetic with Fortran. Arithmetic operations are where Fortran shines. Fortran is much faster than Python, Matlab and other interpreted languages. Good Fortran code will be comparable in speed, perhaps faster, than equivalent C/C++ code depending on your compiler and optimisations. To provide a good starting point for this episode complete the challenge below.
For this episode complete challenges in:
Create a maths
Fortran
program
- Create a new Fortran program
maths.f90
. - Define a real parameter
pi
. - Print the value of
pi
. - Check your program compiles and runs.
FORTRAN
program maths
!! Test program to demonstrate Fortran arithmetic
implicit none
real, parameter :: pi = 3.141592654
!! Value of pi
print *, 'Pi = ', pi
end program maths
Notice the print statement outputs the string 'Pi = '
before printing the value of pi
on the same line.
Example output:
OUTPUT
3.14159274
This is slightly different to the value we coded. We will discuss why
in the kinds
section of this episode.
Operators & Intrinsics
The usual operators are available in Fortran:
Operator | Description |
---|---|
** |
Exponent |
* |
Multiplication |
/ |
Division |
+ |
Addition |
- |
Subtraction |
They are listed in order of precedence. Fortran also has a number of intrinsic maths functions.
Calculate the area of a circle with radius 5 cm
- Add two new real variables for the
radius
andarea
to your program. - Print the value of
radius
andarea
. - Calculate the area of the circle using \(\pi r^2\).
- Check your program compiles and runs.
FORTRAN
program maths
!! Test program to demonstrate Fortran arithmetic
implicit none
real, parameter :: pi = 3.141592654
!! Value of pi
real :: radius
!! Radius of the circle in cm
real :: area
!! Area of the circle in cm
radius = 5.0 ! cm
area = pi * radius**2
print *, 'Pi = ', pi
print *, 'Radius = ', radius, ' cm'
print *, 'Area = ', area, ' cm^2'
end program maths
Example output:
OUTPUT
Pi = 3.14159274
Radius = 5.00000000 cm
Area = 78.5398178 cm^2
Kinds
Numeric types such as integer
, real
, and
complex
can have different floating-point precisions. This
is commonly 32 or 64-bit precision. We can specify the precision using
kind parameters. There are two common ways to specify
kind parameters:
Fortran defaults to single precision
Fortran differs from other languages. The default precision for reals is single.
FORTRAN
use, intrinsic :: iso_fortran_env, only: r_64 => real64
real(kind=r_64) :: current_distance_from_sun ! AU
current_distance_from_sun = 1.3 ! no kind suffix - this is single precision
current_distance_from_sun = 1.3_r_64 ! double precision
Always use a kind suffix for real and integer types.
You might see variables declared as:
The d
here specifies the reals as double precision.
You might also see variables with kinds which are plain integers:
Some information on this older style is available in the gfortran docs.
Specify the precision in your program
Update your maths.f90
program to specify the real kind
as real64
. Note the output before and
after you modify the precision. How has the output
changed?
FORTRAN
program maths
!! Test program to demonstrate Fortran arithmetic
use, intrinsic :: iso_fortran_env, only: r_64 => real64
implicit none
real(kind=r_64), parameter :: pi = 3.141592654_r_64
!! Value of pi
real(kind=r_64) :: radius
!! Radius of the circle in cm
real(kind=r_64) :: area
!! Area of the circle in cm
! this float must be written as 5.0 (sometimes seen as 5.)
! not 5 on its own without the decimal point
radius = 5.0_r_64 ! cm
area = pi * radius**2
print *, 'Pi = ', pi
print *, 'Radius = ', radius, ' cm'
print *, 'Area = ', area, ' cm^2'
end program maths
Example output before (32 bit single precision):
OUTPUT
Pi = 3.14159274
Radius = 5.00000000 cm
Area = 78.5398178 cm^2
Example output after (64 bit double precision):
OUTPUT
Pi = 3.1415926540000001
Radius = 5.0000000000000000 cm
Area = 78.539816349999995 cm^2
The value of pi now accurately reflects the value you coded in the program. The value of the area is also now more accurate.
Lennard-Jones Potential
Create a new program to calculate the Lennard-Jones Potential for two Xenon atoms. They are separated by 4.0 Angstroms. Approximate the potential using:
\[V(r)=4\epsilon\left[\left(\frac{\sigma}{r}\right)^{12}-\left(\frac{\sigma}{r}\right)^{6}\right]\]
where:
- \(\epsilon=0.997\ kJ/mol\)
- \(\sigma=3.40\ Angstroms\)
- \(r=4.0\ Angstroms\)
Print the value at the end of your program.
In the file lennard_jones_potential.f90
:
FORTRAN
program lennard_jones_potential
!! Calculates the Lennard-Jones Potential for 2 Xenon atoms
use, intrinsic :: iso_fortran_env, only: i_64 => int64, r_64 => real64
implicit none
real(kind=r_64), parameter :: epsilon = 0.997_r_64 ! kJ/mol
!! well depth kJ/mol
real(kind=r_64), parameter :: sigma = 3.40_r_64 ! Angstroms
!! van der Waals radius Angstroms
integer(kind=i_64), parameter :: lj_potential_const = 4_i_64
!! unit-less Lennard-Jones Potential constant
real(kind=r_64) :: separation_distance
!! separation distance r in Angstroms
real(kind=r_64) :: lj_potential
!! Lennard-Jones Potential kJ/mol
separation_distance = 4.0_r_64 ! Angstroms
! Calculate the Lennard-Jones Potential using:
! V(r) = 4*epsilon*[(sigma/r)**12 - (sigma/r)**6]
lj_potential = lj_potential_const * epsilon * &
((sigma/separation_distance)**12 &
- (sigma/separation_distance)**6)
print *, 'V(4.0 Angstrom) = ', lj_potential, ' kJ/mol'
end program lennard_jones_potential
Note:
- We couldn’t name the
lj_potential
variablelennard_jones_potential
since that’s the program name. Try changing it to be the same as the program name. What compiler error do you get? - We’ve used verbose names for all variables. This is good practice
since using single character maths related variable names makes code
harder to read. This does mean that the formula on one line would break
the 80 character line limit in our style guide. To get around this the
formula has been split over multiple lines using the continuation marker
&
. - The constant
lj_potential_const
has been defined as a variable. This avoids magic numbers in our code.
Type Casting & Mixed Precision
Take a look at the calculation of lj_potential
(from the
challenge above). What kinds are each of the variables in the
equation?
FORTRAN
lj_potential = lj_potential_const * epsilon * &
((sigma/separation_distance)**12 &
- (sigma/separation_distance)**6)
The value we are calculating is a 64 bit real
(lj_potential
). The first variable in the equation is a 64
bit integer (lj_potential_const
). The compiler will
cast the integer to a 64 bit real before using
it in the multiplication.
In this program the casting only occurs once. Doing this casting many times can slow a program down. To remove this implicit casting we can:
-
cast
lj_potential_const
to a real explicitly before the calculation.We would also have to define the new real variable
lj_potential_const_real
. -
declare the constant as a real to start with. This is the simplest solution which avoids casting.
This program uses mixed type in its arithmetic (reals and integers). Some programs have mixed precision (kinds) as well. i.e. 32 bit integers in an equation with 64 bit integers. In this case the 32 bit integers are promoted to 64 bit by the compiler before use. It is best to avoid implicit conversions like this by being consistent with your precision.
Remove Casting
- Find your compiler documentation. Is there a flag that warns you about implicit conversions / kind casting? If there is, compile your program with the flag. What warning do you get?
- Modify your solution to the last challenge to remove any type/kind casting.
-
For gfortran there are two flags we can use. These are taken from the gfortran options documentation:
$ gfortran -o ljp lennard_jones_potential.f90 -Wconversion -Wconversion-extra
Note that in the solution code to the last challenge gfortran will still not provide a warning. The parameter was declared as an integer and used in arithmetic with reals (mixed type). So why is there no warning about conversion?
Because the variable is a parameter the compiler is performing optimisations under the hood that remove the type casting. Remove the parameter keyword and the following warning appears:
OUTPUT
lennard_jones_potential.f90:24:35: 24 | lj_potential = lj_potential_const * epsilon * & | 1 Warning: Conversion from INTEGER(8) to REAL(8) at (1) [-Wconversion-extra]
So turning on compiler warnings can be useful but are no substitute for thorough code and science review. A later episode goes deeper into compiler usage and debugging.
Example modified code with no type/kind casting:
FORTRAN
program lennard_jones_potential
!! Calculates the Lennard-Jones Potential for 2 Xenon atoms
use, intrinsic :: iso_fortran_env, only: r_64 => real64
implicit none
real(kind=r_64), parameter :: epsilon = 0.997_r_64 ! kJ/mol
!! well depth kJ/mol
real(kind=r_64), parameter :: sigma = 3.40_r_64 ! Angstroms
!! van der Waals radius Angstroms
real(kind=r_64), parameter :: lj_potential_const = 4_r_64
!! unit-less Lennard-Jones Potential constant
real(kind=r_64) :: separation_distance
!! separation distance r in Angstroms
real(kind=r_64) :: lj_potential
!! Lennard-Jones Potential kJ/mol
separation_distance = 4.0_r_64 ! Angstroms
! Calculate the Lennard-Jones Potential using:
! V(r) = 4*epsilon*[(sigma/r)**12 - (sigma/r)**6]
lj_potential = lj_potential_const * epsilon * &
((sigma/separation_distance)**12 &
- (sigma/separation_distance)**6)
print *, 'V(4.0 Angstrom) = ', lj_potential, ' kJ/mol'
end program lennard_jones_potential
The exponents in the equation 12
and 6
have
been left as integers. They have no kind suffix. This means they are the
compilers default integer kind. Using an integer exponent where possible
is faster than using a real exponent.
Key Points
- Operators in order of precedance:
**
,*
,/
,+
, and-
. - List of intrinsic maths functions.
- A numeric variables kind specifies its floating-point precision. 32-bit, 64-bit etc.
- Always specify a kind when defining and assigning values to variables. Otherwise Fortran will default to the compilers single precision.
- Avoid mixing precision and kinds (e.g. integers with reals, or 32-bit with 64-bit). The compiler will implicitly convert the lower precision value to a higher precision value. This can slow down your programs.
Content from Logic
Last updated on 2025-04-29 | Edit this page
Estimated time: 30 minutes
Overview
Questions
- How do we declare and assign values to variables?
Objectives
- Understand the different intrinsic data types.
- Declare and assign variables and parameters.
Fortran’s logical
type has two values:
Logical operators
Values can be tested logical operators .or.
,
.and.
and .not.
are available, and these can
be used to set the value of logical variables.
The precedence is illustrated by, e.g.,
where q, i, j, and k are all logical variables.
Use brackets to avoid confusion over operator precedence.
Relational operators
To form logical expressions from numeric or other expressions, we require relational operators. The are two forms in Fortran, illustrated in the table below. It is recommended that you avoid the older form.
Relation | Operator | Older form | For |
---|---|---|---|
Less than | < |
.lt. |
integer real
|
Less than or equal to | <= |
.le. |
integer real
|
Greater than | > |
.gt. |
integer real
|
Greater than or equal to | >= |
.ge. |
integer real
|
Equal to | == |
.eq. |
integer real complex
|
Not equal to | /= |
.neq. |
integer real complex
|
Logical equivalence
Equivalence between two logical expressions or variables is
established via the logical operators .eqv.
and
.neqv.
.
While some some compilers may allow the use of ==
, this
should be avoided.
Using logical operators
These operators can be used to check and set the values of logical variables, dependent on other variables, e.g.
FORTRAN
program example4
implicit none
real, parameter :: pi = 3.14159265
logical, parameter :: switch1 = .true.
real :: a=3.0
logical :: test1, test2, test3
test1 = a >= pi ! True if a is greater than or equal to pi
test2 = (.not. test1) ! True if test1 is False, False if test1 is True
test3 = (test2 .eqv. switch1) ! True if test2 is True, False if test2 is False
print *, test1
print *, test2
print *, test3
end program example4
Compiling and running this code will give the following output
$ ./a.out
F
T
T
Key Points
- Th
Content from Strings
Last updated on 2025-04-25 | Edit this page
Estimated time: 30 minutes
Overview
Questions
- How do we declare and assign values to variables?
Objectives
- Understand the different intrinsic data types.
- Declare and assign variables and parameters.
Variables store information we can use in our
Key Points
- Th