Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6402f32
initial commit covering Fortran data types
theabro Oct 31, 2024
d7c4024
Merge branch 'carpentries-incubator:main' into ep2_basics
theabro Nov 15, 2024
3744b87
Update episodes/02-basics.Rmd
theabro Nov 20, 2024
900449f
Update episodes/02-basics.Rmd
theabro Nov 20, 2024
fcb2bf3
added error message when trying to alter a parameter
theabro Dec 2, 2024
e20bcb7
initial commit covering Fortran data types
theabro Oct 31, 2024
abdb0ab
Update episodes/02-basics.Rmd
theabro Nov 20, 2024
0af6e5c
Update episodes/02-basics.Rmd
theabro Nov 20, 2024
bef7877
added error message when trying to alter a parameter
theabro Dec 2, 2024
826f669
Splits off the start of the variables lesson into its own file - add …
astroDimitrios Apr 23, 2025
eabc28b
Further split up the basics section - adds in the section on Maths
astroDimitrios Apr 25, 2025
2e2cf0b
Remove whitespace
astroDimitrios Apr 25, 2025
80b7006
Line highlighting
astroDimitrios Apr 25, 2025
c2a2b9d
Ignore executables
astroDimitrios Apr 25, 2025
43efde7
Alter the exercises directory structure
astroDimitrios Apr 25, 2025
cb8301e
Tidy variables.f90 code
astroDimitrios Apr 25, 2025
67ae508
Add challenges to the exercises directory for the variables section
astroDimitrios Apr 25, 2025
e92d238
Add challenges to the README for the basic maths section - make sure …
astroDimitrios Apr 25, 2025
0539a7f
Undo line highlighting attempt
astroDimitrios Apr 25, 2025
a142006
Undo compiler flag testing with ljp code
astroDimitrios Apr 25, 2025
92d0685
Add key points to the maths section
astroDimitrios Apr 25, 2025
8940443
Add in messages for where challenges should be written and update the…
astroDimitrios Apr 25, 2025
36c7a98
Fix config
astroDimitrios Apr 25, 2025
e285d81
Clarify type/kind and add explanation of the gfortran warning (or lac…
astroDimitrios Apr 29, 2025
da2c2dd
Update AU unit
astroDimitrios Apr 29, 2025
f9385d8
Update more units AU
astroDimitrios Apr 29, 2025
604db39
Add example of scientific notation
astroDimitrios Apr 29, 2025
6e64c87
Merge remote-tracking branch 'origin/ep2_basics' into ep2_basics
theabro May 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,8 @@ renv/sandbox # OPTIONAL

# Editors
.vscode

# Executables
a.out
exercises/*/solutions/*
!exercises/*/solutions/*.*
6 changes: 4 additions & 2 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ contact: 'd.theodorakis@metoffice.gov.uk'

# Order of episodes in your lesson
episodes:
- introduction.Rmd
- 02-variables.md
- 03-maths.md
- 04-logic.md
- 05-strings.md

# Information for Learners
learners:
Expand All @@ -78,4 +81,3 @@ profiles:
sandpaper: astroDimitrios/sandpaper
pegboard: astroDimitrios/pegboard
varnish: astroDimitrios/varnish

343 changes: 343 additions & 0 deletions episodes/02-basics.Rmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,343 @@
---
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 cannot change by defining variables using `parameter`.
We are then unable to modify `parameter` variables, e.g.
```fortran
program example3
implicit none

real, parameter :: pi = 3.14159265

pi = pi + 2.0

print *, pi

end program example3
```
When compiling this program, this will give an error similar to the following from the `gfortran` compiler:
```
example3.f90:6:3:

6 | pi = pi + 2.0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Someone might think this doesn't work because of the use of itself in calculating its new value, an example like pi = 3.0 may be clearer

| 1
Error: Named constant 'pi' in variable definition context (assignment) at (1)
```

::::::::::::::::::::::::::::::::::::: 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` |
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

put commas in these lists in table

| 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.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • "to compare logical expression" - restate to be extra clear that this applies to logical and "==" should not be avoided in general.


### 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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Draft content to be moved to file 05-strings ?


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`, concatenate `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
```

:::::::::::::::::::::::::
:::::::::::::::::::::::::::::::::::::::::::::::

Loading