-
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0350db9
commit 907e99f
Showing
4 changed files
with
757 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,330 @@ | ||
--- | ||
title: 'Basics' | ||
teaching: 35 | ||
exercises: 15 | ||
--- | ||
|
||
::::::::::::::::::::::::::::::::::::: questions | ||
|
||
- How do we represent and manipulate data in Fortran? | ||
|
||
:::::::::::::::::::::::::::::::::::::::::::::::: | ||
|
||
::::::::::::::::::::::::::::::::::::: objectives | ||
|
||
- Understand the different intrinsic data types | ||
- Understand the different intrinsic operators and functions available | ||
|
||
:::::::::::::::::::::::::::::::::::::::::::::::: | ||
|
||
## Fortran data types | ||
|
||
Fortran provides the following intrinsic data types: | ||
|
||
* numeric types | ||
* `integer` | ||
* `real` | ||
* `complex` | ||
* non-numeric types | ||
* `logical` | ||
* `character` | ||
|
||
### Defining numeric variables | ||
|
||
The following program declares a variable with each of the three intrinsic | ||
numeric types, and provides an initial value in each case. | ||
```fortran | ||
program example1 | ||
integer :: i = 1 ! An integer | ||
real :: a = 2.0 ! A floating point number | ||
complex :: z = (0.0, 1.0) ! A complex number as (real-part, imag-part) | ||
end program example1 | ||
``` | ||
Initial values are optional, and these values may be changed later within the code. | ||
If a declaration does not specify an initial value, the variable is said to be _undefined_. | ||
|
||
### Variable names | ||
|
||
The valid Fortran character set for names is `a-z`, `A-Z`, `0-9` and the | ||
underscore `_`. Valid names must begin with a character. The maximum | ||
length of a name is 63 characters (introduced in the F2003 standard) with | ||
no spaces allowed. This includes names for programs, modules, subroutines, | ||
and functions, as well as names for variables. | ||
|
||
### The `implicit` statement | ||
|
||
By default, variables in fortran do not need to be declared a specific type, they | ||
can just be used within the code. Variables with names beginning with letters `i-n` are implicitly | ||
of type `integer`, while anything else is of type `real` (unless explicitly declared otherwise). | ||
|
||
**This is very bad practice and modern Fortran should not be used in this way.** | ||
|
||
The solution to prevent errors involving undeclared variables (usually arising from | ||
typos) is to declare that no names have implicit type via the use of the | ||
```fortran | ||
implicit none | ||
``` | ||
statment at the very top of the code. | ||
|
||
With this statement inserted, all variable names must be declared explicitly before they | ||
are referenced. It is still common to see variables beginning with `i-n` as integers. | ||
|
||
::::::::::::::::::::::::::::::::::::: challenge | ||
|
||
## Use `implicit none` | ||
|
||
Edit the above example to include an `implicit none` statment, and print out the three variables | ||
|
||
:::::::::::::::: solution | ||
|
||
```fortran | ||
program solution1 | ||
implicit none | ||
integer :: i = 1 ! An integer | ||
real :: a = 2.0 ! A floating point number | ||
complex :: z = (0.0, 1.0) ! A complex number as (real-part, imag-part) | ||
print *, i, a, z | ||
end program solution1 | ||
``` | ||
Compiling and running this code will give the following output | ||
``` | ||
$ ./a.out | ||
1 2.00000000 (0.00000000,1.00000000) | ||
``` | ||
|
||
::::::::::::::::::::::::: | ||
::::::::::::::::::::::::::::::::::::::::::::::: | ||
|
||
### Parameters | ||
|
||
In the above example, it is possible to change the values of initialised variables, e.g. | ||
```fortran | ||
program example2 | ||
implicit none | ||
real :: a = 2.0 | ||
print *, a | ||
a = a + 5.0 | ||
print *, a | ||
end program example2 | ||
``` | ||
This will then give the output: | ||
``` | ||
$ ./a.out | ||
2.00000000 | ||
7.00000000 | ||
``` | ||
However, you can also define constant values that do not change by defining variables using `parameter`, e.g. | ||
```fortran | ||
program example3 | ||
implicit none | ||
real, parameter :: pi = 3.14159265 | ||
end program example3 | ||
``` | ||
|
||
::::::::::::::::::::::::::::::::::::: challenge | ||
|
||
## Write a Fortran program to calculate the circumference of a circle | ||
|
||
Using the `parameter` statement, write a Fortran program to calculate the circumference of a circle of | ||
radius 3.0. | ||
|
||
::::::::::::::::: hint | ||
|
||
The cicumference $c$ of a circle can be calculated from the radius $r$ and constant $\pi$ by | ||
|
||
$c = 2 \pi r$ | ||
|
||
:::::::::::::::::::::: | ||
|
||
:::::::::::::::: solution | ||
|
||
```fortran | ||
program solution2 | ||
implicit none | ||
real, parameter :: pi = 3.14159265 | ||
real :: r=3.0 ! radius of the circle | ||
real :: c ! circumference of the circle | ||
c = 2.0 * pi * r | ||
print *, c | ||
end program solution2 | ||
``` | ||
Compiling and running this code will give the following output | ||
``` | ||
$ ./a.out | ||
18.8495560 | ||
``` | ||
|
||
::::::::::::::::::::::::: | ||
::::::::::::::::::::::::::::::::::::::::::::::: | ||
|
||
## Logical variables | ||
|
||
Fortran has a `logical` type that has two literal values, True and False, defined by | ||
```fortran | ||
logical :: switch0 = .false. | ||
logical :: switch1 = .true. | ||
``` | ||
|
||
### Logical operators and expressions | ||
|
||
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., | ||
```fortran | ||
q = i .or. j .and. .not. k ! evaluated as i .or. (j .and. (.not. k)) | ||
``` | ||
where q, i, j, and k are all logical variables. | ||
|
||
The use of parentheses is highly recommended to avoid ambiguity and/or to add clarity. | ||
|
||
### 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 | ||
``` | ||
|
||
## Character variables | ||
|
||
Character variables are strings that hold zero or more characters. Some examples are: | ||
```fortran | ||
program example5 | ||
implicit none | ||
character (len = *), parameter :: string1 = "don't" ! assumed length of 5 characters | ||
character (len = 5) :: string2 = "Don""t" ! 5 characters | ||
character (len = 6) :: string3 = ' don''t' ! blank + 5 characters | ||
end program example5 | ||
``` | ||
There should be a `len` specifier. Specifying `len = *` means that the length will be assumed | ||
from the length of the string. A space is a valid character in a string. | ||
|
||
Strings must be defined within quotation marks, either single, `'`, or double, `"`, beginning | ||
and ending with the same type of mark. To define a quotation mark within a string, either | ||
use one of the alternative type, e.g. `"'"`, or use two of the same type, e.g. `''''`, which | ||
will be intepreted as a single mark within the string. | ||
|
||
Strings may be concatenated with the string concatenation operator `//`. For example `string2` | ||
and `string3` could be concatenated into a new variable `string4` by | ||
```fortran | ||
string4 = string2//string3 | ||
``` | ||
A single character, or a subset of characters, can be extracted via | ||
use of an array-index like notation by defining the start and end characters | ||
to extract, e.g. `string1(1:1)` would extract only the first character from the string | ||
variable `string1`. | ||
|
||
::::::::::::::::::::::::::::::::::::: challenge | ||
|
||
## Working with strings | ||
|
||
Using the above `example5`, concatinate `string2` and `string3` into a new variable `string4`, | ||
and print out the values of all strings. Also, print the third character of `string4`. | ||
|
||
:::::::::::::::: solution | ||
|
||
```fortran | ||
program solution3 | ||
implicit none | ||
character (len = *), parameter :: string1 = "don't" ! 5 characters | ||
character (len = 5) :: string2 = "Don""t" ! 5 characters | ||
character (len = 6) :: string3 = ' don''t' ! blank + 5 characters | ||
character (len = 11) :: string4 ! length of string2+string3 | ||
string4 = string2//string3 | ||
print *, string1 | ||
print *, string2 | ||
print *, string3 | ||
print *, string4 | ||
print *, string4(3:3) | ||
end program solution3 | ||
``` | ||
Compiling and running this code will give the following output | ||
``` | ||
$ ./a.out | ||
don't | ||
Don"t | ||
don't | ||
Don"t don't | ||
n | ||
``` | ||
|
||
::::::::::::::::::::::::: | ||
::::::::::::::::::::::::::::::::::::::::::::::: | ||
|
Oops, something went wrong.