You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: Backend/tutorial.yml
+162
Original file line number
Diff line number
Diff line change
@@ -15,4 +15,166 @@
15
15
- title: Standard input
16
16
content: In a similar way, we can read values from the command window using the read statement. Enter values in the box below.
17
17
code: "program read_value\r\n implicit none\r\n integer :: age\r\n\r\n print *, 'Please enter your age: '\r\n read(*,*) age\r\n\r\n print *, 'Your age is: ', age\r\n\r\nend program read_value"
18
+
- title: Expressions
19
+
content: |
20
+
The usual set of arithmetic operators are available, listed in order or precedence -
21
+
** - Exponent
22
+
* - Multiplication
23
+
/ - Division
24
+
+ - Addition
25
+
- - Subtraction
26
+
27
+
code: "program arithmetic\r\n implicit none\r\n\r\n real :: pi\r\n real :: radius\r\n real :: height\r\n real :: area\r\n real :: volume\r\n\r\n pi = 3.1415927\r\n\r\n print *, 'Enter cylinder base radius:'\r\n read(*,*) radius\r\n\r\n print *, 'Enter cylinder height:'\r\n read(*,*) height\r\n\r\n area = pi * radius**2.0\r\n volume = area * height\r\n\r\n print *, 'Cylinder radius is: ', radius\r\n print *, 'Cylinder height is: ', height\r\n print *, 'Cylinder base area is: ', area\r\n print *, 'Cylinder volume is: ', volume\r\n\r\nend program arithmetic"
18
28
29
+
- title: Floating-point precision
30
+
content: The desired floating-point precision can be explicitly declared using a kind parameter. The iso_fortran_env intrinsic module provides kind parameters for the common 32-bit and 64-bit floating-point types.
More often than not, we need to store and operate on long lists of numbers as opposed to just the single scalar variables that we have been using so far; in computer programming such lists are called arrays.
36
+
Arrays are multidimensional variables that contain more than one value where each value is accessed using one or more indices.
37
+
There are two common notations for declaring array variables using the dimension attribute or by appending the array dimensions in parentheses to the variable name.
38
+
39
+
code: "program arrays\r\n implicit none\r\n\r\n ! 1D integer array\r\n integer, dimension(10) :: array1\r\n\r\n ! An equivalent array declaration\r\n integer :: array2(10)\r\n\r\n ! 2D real array\r\n real, dimension(10, 10) :: array3\r\n\r\n ! Custom lower and upper index bounds\r\n real :: array4(0:9)\r\n real :: array5(-5:5)\r\n\r\nend program arrays\r\n"
40
+
41
+
- title: Array slicing
42
+
content: A powerful feature of the Fortran language is its built-in support for array operations; we can perform operations on all or part of an array using array slicing notation
43
+
code: "program array_slice\r\n implicit none\r\n\r\n integer :: i\r\n integer :: array1(10) ! 1D integer array of 10 elements\r\n integer :: array2(10, 10) ! 2D integer array of 100 elements\r\n\r\n array1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] ! Array constructor\r\n array1 = [(i, i = 1, 10)] ! Implied do loop constructor\r\n array1(:) = 0 ! Set all elements to zero\r\n array1(1:5) = 1 ! Set first five elements to one\r\n array1(6:) = 1 ! Set all elements after five to one\r\n\r\n print *, array1(1:10:2) ! Print out elements at odd indices\r\n print *, array2(:,1) ! Print out the first column in a 2D array\r\n print *, array1(10:1:-1) ! Print an array in reverse\r\n\r\nend program array_slice\r\n"
44
+
45
+
- title: Allocatable (dynamic) arrays
46
+
content: |
47
+
So far we have specified the size of our array in our program code—this type of array is known as a static array since its size is fixed when we compile our program.
48
+
Quite often, we do not know how big our array needs to be until we run our program, for example, if we are reading data from a file of unknown size.
49
+
For this problem, we need allocatable arrays. These are allocated while the program is running once we know how big the array needs to be.
content: An array of strings can be expressed in Fortran as an array of character variables. All elements in a character array have equal length. However, strings of varying lengths can be provided as input to the array constructor, as shown in the example below. They will be truncated or right-padded with spaces if they are longer or shorter, respectively, than the declared length of the character array. Finally, we use the intrinsic function trim to remove any excess spaces when printing the values to the standard output.
One of the powerful advantages of computer algorithms, compared to simple mathematical formulae, comes in the form of program branching whereby the program can decide which instructions to execute next based on a logical condition.
67
+
There are two main forms of controlling program flow:
68
+
Conditional (if): choose program path based on a boolean (true or false) value
69
+
Loop: repeat a portion of code multiple times
70
+
code : ""
71
+
72
+
- title: Relational operators
73
+
content: |
74
+
Before we use a conditional branching operator, we need to be able to form a logical expression.
75
+
To form a logical expression, the following set of relational operators are available:
76
+
Operator - Alternative - Description
77
+
== - .eq. - Tests for equality of two operands
78
+
/= .ne. Test for inequality of two operands
79
+
> .gt. Tests if left operand is strictly greater than right operand
80
+
< .lt. Tests if left operand is strictly less than right operand
81
+
>= .ge. Tests if left operand is greater than or equal to right operand
82
+
<= .le. Tests if left operand is less than or equal to right operand
83
+
code: ""
84
+
85
+
- title: Logical Operators
86
+
content: |
87
+
There’s the following logical operators:
88
+
.and. TRUE if both left and right operands are TRUE
89
+
.or. TRUE if either left or right or both operands are TRUE
90
+
.not. TRUE if right operand is FALSE
91
+
.eqv. TRUE if left operand has same logical value as right operand
92
+
.neqv. TRUE if left operand has the opposite logical value as right operand
93
+
code: ""
94
+
95
+
- title: Conditional construct (if)
96
+
content: In the following examples, a conditional if construct is used to print out a message to describe the nature of the angle variable,
97
+
In this first example, the code within the if construct is only executed if the test expression (angle < 90.0) is true.
98
+
Tip - It is good practice to indent code within constructs such as if and do to make code more readable.
99
+
100
+
code: "program conditional\r\n\r\n real :: angle\r\n angle = 60\r\n\r\n if (angle < 90.0) then\r\n print *, 'Angle is acute'\r\n end if\r\n\r\nend program conditional\r\n\r\n"
101
+
102
+
- title: Conditional construct (if-else)
103
+
content: We can add an alternative branch to the construct using the else keyword
104
+
code: "program conditional\r\n\r\n real :: angle\r\n angle = 120\r\n\r\n if (angle < 90.0) then\r\n print *, 'Angle is acute'\r\n else\r\n print *, 'Angle is obtuse'\r\n end if\r\n\r\nend program conditional\r\n\r\n"
105
+
106
+
- title: Conditional construct (if)
107
+
content: Now there are two branches in the if construct, but only one branch is executed depending on the logical expression following the if keyword.
108
+
We can actually add any number of branches using else if to specify more conditions
109
+
When multiple conditional expressions are used, each conditional expression is tested only if none of the previous expressions have evaluated to true.
110
+
code: "program conditional\r\n\r\n real :: angle\r\n angle = 200\r\n\r\n if (angle < 90.0) then\r\n print *, 'Angle is acute'\r\n else if (angle < 180.0) then\r\n print *, 'Angle is obtuse'\r\n else\r\n print *, 'Angle is reflex'\r\n end if\r\n\r\nend program conditional\r\n\r\n"
111
+
112
+
- title: Loop constructs (do)
113
+
content: |
114
+
In this example, a do loop construct is used to print out the numbers in a sequence.
115
+
The do loop has an integer counter variable which is used to track which iteration
116
+
of the loop is currently executing.
117
+
In this example we use a common name for this counter variable i.
118
+
When we define the start of the do loop, we use our counter variable name followed by an equals (=) sign
119
+
to specify the start value and final value of our counting variable.
120
+
code: "program conditional\r\n\r\n integer :: i\r\n\r\n do i = 1, 10\r\n print *, i\r\n end do\r\n\r\nend program conditional\r\n\r\n"
121
+
122
+
- title: Loop constructs (do)
123
+
content: Here's how to perform a do loop with skip
124
+
code: "program conditional\r\n\r\n integer :: i\r\n\r\n do i = 1, 10, 2\r\n print *, i ! Print odd numbers\r\n end do\r\n\r\nend program conditional\r\n\r\n"
125
+
126
+
- title: Conditional loop (do while)
127
+
content: A condition may be added to a do loop with the while keyword. The loop will be executed while the condition given in while() evaluates to .true..
128
+
code: "program loop\r\n\r\n integer :: i\r\n\r\n i = 1\r\n do while (i < 11)\r\n print *, i\r\n i = i + 1\r\n end do\r\n ! Here i = 11\r\n\r\n\r\nend program loop"
129
+
130
+
- title: Loop control statements (cycle)
131
+
content: Most often than not, loops need to be stopped if a condition is met. Fortran provides two executable statements to deal with such cases.
132
+
exit is used to quit the loop prematurely. It is usually enclosed inside an if.
133
+
code: "program loop\r\n\r\n integer :: i\r\n\r\n do i = 1, 100\r\n if (i > 10) then\r\n exit ! Stop printing numbers\r\n end if\r\n print *, i\r\n end do\r\n ! Here i = 11\r\n\r\nend program loop"
134
+
135
+
- title: Loop control statements (cycle)
136
+
content: On the other hand, cycle skips whatever is left of the loop and goes into the next cycle.
137
+
Note - When used within nested loops, the cycle and exit statements operate on the innermost loop.
138
+
code: "program loop\r\n\r\n integer :: i\r\n\r\n do i = 1, 10\r\n if (mod(i, 2) == 0) then\r\n cycle ! Don't print even numbers\r\n end if\r\n print *, i\r\n end do\r\n\r\nend program loop"
139
+
140
+
- title: Nested loop control - tags
141
+
content: |
142
+
A recurring case in any programming language is the use of nested loops. Nested loops refer to loops that exist within another loop. Fortran allows the programmer to tag or name each loop. If loops are tagged, there are two potential benefits:
143
+
1. The readability of the code may be improved (when the naming is meaningful).
144
+
2. exit and cycle may be used with tags, which allows for very fine-grained control of the loops.
145
+
code: "program nested\r\n\r\n integer :: i, j\r\n\r\n outer_loop: do i = 1, 10\r\n inner_loop: do j = 1, 10\r\n if ((j + i) > 10) then ! Print only pairs of i and j that add up to 10\r\n cycle outer_loop ! Go to the next iteration of the outer loop\r\n end if\r\n print *, 'I=', i, ' J=', j, ' Sum=', j + i\r\n end do inner_loop\r\n end do outer_loop\r\n\r\n do i = 1, 10\r\n if (mod(i, 2) == 0) then\r\n cycle ! Don't print even numbers\r\n end if\r\n print *, i\r\n end do\r\n\r\nend program nested"
146
+
147
+
- title: Parallelizable loop (do concurrent)
148
+
content: The do concurrent loop is used to explicitly specify that the inside of the loop has no interdependencies; this informs the compiler that it may use parallelization/SIMD to speed up execution of the loop and conveys programmer intention more clearly. More specifically, this means that any given loop iteration does not depend on the prior execution of other loop iterations. It is also necessary that any state changes that may occur must only happen within each do concurrent loop. These requirements place restrictions on what can be placed within the loop body.
149
+
code: "program nested\r\n\r\n real, parameter :: pi = 3.14159265\r\n integer, parameter :: n = 10\r\n real :: result_sin(n)\r\n integer :: i\r\n\r\n do concurrent (i = 1:n) ! Careful, the syntax is slightly different\r\n result_sin(i) = sin(i * pi/4.)\r\n end do\r\n\r\n print *, result_sin\r\n\r\nend program nested"
150
+
151
+
- title: Parallelizable loop (do concurrent)
152
+
content: Important - Simply replacing a do loop with a do concurrent does not guarantee parallel execution. The explanation given above does not detail all the requirements that need to be met in order to write a correct do concurrent loop. Compilers are also free to do as they see fit, meaning they may not optimize the loop (e.g., a small number of iterations doing a simple calculation, like the below example). In general, compiler flags are required to activate possible parallelization for do concurrent loops.
153
+
code: "program nested\r\n\r\n real, parameter :: pi = 3.14159265\r\n integer, parameter :: n = 10\r\n real :: result_sin(n)\r\n integer :: i\r\n\r\n do concurrent (i = 1:n) ! Careful, the syntax is slightly different\r\n result_sin(i) = sin(i * pi/4.)\r\n end do\r\n\r\n print *, result_sin\r\n\r\nend program nested"
154
+
155
+
- title: Organising code structure
156
+
content: |
157
+
Fortran has two forms of procedure:
158
+
1. Subroutine: invoked by a call statement
159
+
2. Function: invoked within an expression or assignment to which it returns a value
160
+
code: ""
161
+
162
+
- title: Subroutines
163
+
content: The subroutine input arguments, known as dummy arguments, are specified in parentheses after the subroutine name; the dummy argument types and attributes are declared within the body of the subroutine just like local variables.
164
+
code: "subroutine print_matrix(n,m,A)\r\n implicit none\r\n integer, intent(in) :: n\r\n integer, intent(in) :: m\r\n real, intent(in) :: A(n, m)\r\n\r\n integer :: i\r\n\r\n do i = 1, n\r\n print *, A(i, 1:m)\r\n end do\r\n\r\nend subroutine print_matrix\r\n\r\nprogram call_sub\r\n implicit none\r\n\r\n real :: mat(10, 20)\r\n\r\n mat(:,:) = 0.0\r\n\r\n call print_matrix(10, 20, mat)\r\n\r\nend program call_sub\r\n"
165
+
166
+
- title: Subroutines
167
+
content: |
168
+
Note the additional intent attribute when declaring the dummy arguments; this optional attribute signifies to the compiler whether the argument is read-only (intent(in)) or write-only (intent(out)) or read-write(intent(inout)) within the procedure. In this example, the subroutine does not modify its arguments, hence all arguments are intent(in).
169
+
Tip: It is good practice to always specify the intent attribute for dummy arguments; this allows the compiler to check for unintentional errors and provides self-documentation.
170
+
We can call this subroutine from a program using a call statement.
171
+
code: "subroutine print_matrix(n,m,A)\r\n implicit none\r\n integer, intent(in) :: n\r\n integer, intent(in) :: m\r\n real, intent(in) :: A(n, m)\r\n\r\n integer :: i\r\n\r\n do i = 1, n\r\n print *, A(i, 1:m)\r\n end do\r\n\r\nend subroutine print_matrix\r\n\r\nprogram call_sub\r\n implicit none\r\n\r\n real :: mat(10, 20)\r\n\r\n mat(:,:) = 0.0\r\n\r\n call print_matrix(10, 20, mat)\r\n\r\nend program call_sub\r\n"
172
+
173
+
- title: Functions
174
+
content: |
175
+
Tip: In production code, the intrinsic function norm2 should be used.
176
+
Tip: It is good programming practice for functions not to modify their arguments that is, all function arguments should be intent(in). Such functions are known as pure functions. Use subroutines if your procedure needs to modify its arguments.
177
+
code: "function vector_norm(n,vec) result(norm)\r\n implicit none\r\n integer, intent(in) :: n\r\n real, intent(in) :: vec(n)\r\n real :: norm\r\n\r\n norm = sqrt(sum(vec**2))\r\n\r\nend function vector_norm\r\n\r\nprogram run_fcn\r\n implicit none\r\n\r\n real :: v(9)\r\n real :: vector_norm\r\n\r\n v(:) = 9\r\n\r\n print *, 'Vector norm = ', vector_norm(9,v)\r\n\r\nend program run_fcn\r\n"
0 commit comments