From b1c78c02f00c5a6d7a62bbdcce29495ebe8f7eb6 Mon Sep 17 00:00:00 2001 From: LKedward Date: Sun, 17 May 2020 15:15:36 +0100 Subject: [PATCH 1/9] Draft navigation structure for tutorials Setup a data structure and layouts for navigating pages in the learn section. --- _data/fortran_guide.yml | 17 + _includes/learn_nav_sidebar.html | 73 ++++ _layouts/default.html | 1 + _layouts/page_learn.html | 30 ++ assets/css/main.css | 29 ++ assets/js/page_nav.js | 35 ++ learn/faq.md | 13 + learn/index.md | 602 +----------------------------- learn/quickstart.md | 604 +++++++++++++++++++++++++++++++ 9 files changed, 806 insertions(+), 598 deletions(-) create mode 100644 _data/fortran_guide.yml create mode 100644 _includes/learn_nav_sidebar.html create mode 100644 _layouts/page_learn.html create mode 100644 assets/js/page_nav.js create mode 100644 learn/faq.md create mode 100644 learn/quickstart.md diff --git a/_data/fortran_guide.yml b/_data/fortran_guide.yml new file mode 100644 index 000000000..8e3fd4602 --- /dev/null +++ b/_data/fortran_guide.yml @@ -0,0 +1,17 @@ +appendices: [~,A,B,C,D] + +chapters: + - title: Introduction + pages: + - title: Learn Fortran + url: /learn/ + + - title: Getting started + pages: + - title: Quickstart tutorial + url: /learn/quickstart + + - title: Appendices + pages: + - title: Fortran FAQ + url: /learn/faq diff --git a/_includes/learn_nav_sidebar.html b/_includes/learn_nav_sidebar.html new file mode 100644 index 000000000..638f63404 --- /dev/null +++ b/_includes/learn_nav_sidebar.html @@ -0,0 +1,73 @@ + + diff --git a/_layouts/default.html b/_layouts/default.html index ecc108e28..e4b6479d7 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -28,6 +28,7 @@ {% include google_analytics.html %} + diff --git a/_layouts/page_learn.html b/_layouts/page_learn.html new file mode 100644 index 000000000..e5bbd3d7f --- /dev/null +++ b/_layouts/page_learn.html @@ -0,0 +1,30 @@ +--- +layout: default +--- + +{% include nav.html active=page.navbar %} + +
+
+ + {% include learn_nav_sidebar.html %} + + + + + +
+
diff --git a/assets/css/main.css b/assets/css/main.css index 9a58a3ea5..36456e6fe 100644 --- a/assets/css/main.css +++ b/assets/css/main.css @@ -203,6 +203,35 @@ pre { } } +.col-right, +.col-fixed { + display: block; +} + +@media (min-width: 568px) { + .col-right { + /* display: table-cell; */ + width: 61.8%; + vertical-align: top; + margin-left: 380px; + min-height: 500px; + } + .col-fixed { + /* display: table-cell; */ + position: fixed; + width: 350px; + height: 500px; + z-index: 1; /* Stay on top */ + } + .col-fixed .content{ + overflow-y: auto; + overflow-x: hidden; + height: 90%; + width: 100%; + } +} + + .front-section { padding: 8px 0; } diff --git a/assets/js/page_nav.js b/assets/js/page_nav.js new file mode 100644 index 000000000..a49b00f16 --- /dev/null +++ b/assets/js/page_nav.js @@ -0,0 +1,35 @@ +// If the current page contains an element with id="pagenav-sidebar" +// then this script will populate it with
  • elements +// containing links to all the

    elements on the current page +if (!!document.getElementById("pagenav-sidebar")){ + + var headings = document.querySelectorAll("h2[id]"); + + for (var i = 0; i < headings.length; i++) { + document.getElementById("page-nav").innerHTML += + ''; + } + + $(document).ready(function() { + $(window).scroll(function() { + + var found = false; + var scrollPos = $(window).scrollTop(); + for (var i = 0; i < headings.length; i++) { + + if (scrollPos >= headings[i].offsetTop){ + found = true; + $("#nav-"+headings[i].id).addClass('current'); + } else { + $("#nav-"+headings[i].id).removeClass('current'); + } + + } + + }); + }); + +} \ No newline at end of file diff --git a/learn/faq.md b/learn/faq.md new file mode 100644 index 000000000..83a512f99 --- /dev/null +++ b/learn/faq.md @@ -0,0 +1,13 @@ +--- +layout: page_learn +title: Fortran FAQ +permalink: /learn/faq +navbar: Learn +--- + +## Heading 1 + + +## Heading 2 + +## Heading 3 \ No newline at end of file diff --git a/learn/index.md b/learn/index.md index 4d24fc7e2..598e49ecd 100644 --- a/learn/index.md +++ b/learn/index.md @@ -1,604 +1,10 @@ --- -layout: page -title: Quickstart Fortran +layout: page_learn +title: Learn Fortran permalink: /learn/ navbar: Learn --- -This quickstart tutorial assumes familiarity with basic programming concepts such as types, variables, arrays, control flow and functions. - - -On this page: - -- [Setting up a Fortran compiler](#compiler-setup) -- [Hello world program](#hello-world) -- [Variables, arrays & strings](#variables) -- [Operators](#operators) -- [Controlling program flow (if,loops)](#controlling-program-flow) -- [Procedures (functions,subroutines)](#procedures) -- [Modules](#modules) - -## Compiler setup - -{% include note.html content="Fortran is a compiled language which means that once written, the source code must be passed through a -compiler to produce a machine executable that can be run." %} - -In this tutorial, we'll work with the free and open source -[GNU Fortran compiler (gfortran)](https://gcc.gnu.org/fortran/), -which is part of the -[GNU Compiler Colection (GCC)](https://gcc.gnu.org/). - -To install gfortran on Linux, use your system package manager. -Otherwise, for macOS or Windows, refer to gfortran binaries from -[this page](https://gcc.gnu.org/install/binaries.html). - -To check if you have _gfortran_ setup correctly, open a terminal and run the following command : - -```shell -$> gfortran --version -``` - -this should output something like: - -``` -GNU Fortran 7.5.0 -Copyright (C) 2017 Free Software Foundation, Inc. -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -``` - -## Hello world - -Once you have setup up your compiler, open a new file in your favourite code editor and enter the following: - -```fortran -program hello - ! This is a comment line, it is ignored by the compiler - print *, 'Hello, World!' -end program hello -``` - -Having saved your program to `hello.f90`, compile at the command line with: -```shell -$> gfortran hello.f90 -o hello -``` - -{% include note.html content=".f90 is the standard file extension for modern fortran source files. -The 90 refers to the first modern fortran standard in 1990." %} - -To run your compiled program: -```shell -$> ./hello -Hello, World! -``` - -## Variables - -Fortran comes with 5 built-in data types: - -* `integer` -- for data that represent whole numbers, positive or negative -* `real` -- for floating-point data (not a whole number) -* `complex` -- pair consisting of a real part and an imaginary part -* `character` -- for text data -* `logical` -- for data that represent boolean (true or false) values - -### Declaring variables - -{% include note.html content="Fortran is a statically typed language which means the type of each -variable is fixed when the program is compiled - variable types cannot change while the program is running." %} - -__Example:__ variable declaration - -```fortran -program variables - implicit none - - integer :: amount - real :: pi - complex :: frequency - character :: initial - logical :: isOkay - -end program variables -``` - -{% include note.html content="Fortran code is __case-insensitive__; you don't have to worry about the -capitalisation of your variable names but it's good practice to keep it consistent." %} - -Note the additional statement at the beginning of the program: `implicit none`. -This statement tells the compiler that all variables will be explicitly declared; without -this statement variables will be implicitly typed according to the letter they begin with. - -{% include important.html content="Always use the `implicit none` statement at -the beginning of each program and procedure. Implicit typing is considered bad practice in -modern programming since it hides information leading to more program errors." %} - -__Example:__ variable assignment - -```fortran - amount = 10 - pi = 4.141592 - frequency = (1.0,-0.5) - initial = 'A' - isOkay = .false. -``` - -Characters are surrounded by either single (`'`) or double quotes (`"`). - -Logical or boolean values can be either `.true.` or `.false.`. - -{% include important.html title="Watch out" content="for assignment at declaration: `integer :: amount = 1`. -__This is NOT a normal initialisation;__ it implies the `save` attribute which means that the variable retains -its value between procedure calls. Good practice is to initialise your variables separately to their declaration." %} - - - -### Floating-point precision - -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 32bit and 64bit floating point types. - -__Example:__ explicit real kind -```fortran -program float - use, intrinsic :: iso_fortran_env, only: sp=>real32, dp=>real64 - implicit none - - real(sp) :: float32 - real(dp) :: float64 - - float32 = 1.0_sp ! Explicit suffix for literal constants - float64 = 1.0_dp - -end program float -``` - -{% include important.html content="Always use a `kind` suffix for floating point literal constants." %} - -__Example:__ c-interoperable kinds -```fortran -program float - use, intrinsic :: iso_c_binding, only: sp=>c_float, dp=>c_double - implicit none - - real(sp) :: float32 - real(dp) :: float64 - -end program float -``` - - -### Arrays - -{% include important.html content="Arrays in Fortran are __one-based__ by default; this means -that the first element along any dimension is at index 1." %} - -__Example:__ static array declaration -```fortran -program arrays - implicit none - - ! 1D integer array - integer, dimension(10) :: array1 - - ! An equivalent array declaration - integer :: array2(10) - - ! 2D real array - real, dimension(10,10) :: array3 - - ! Custom lower and upper index bounds - real :: array4(0:9) - real :: array5(-5:5) - -end program arrays -``` - -__Example:__ array slicing -```fortran -program array_slice - implicit none - - integer :: i - integer :: array1(10) ! 1D integer array of 10 elements - integer :: array2(10,10) ! 2D integer array of 100 elements - - array1 = [1,2,3,4,5,6,7,8,9,10] ! Array constructor - array1 = [(i,i=1,10)] ! Implied do loop constructor - array1(:) = 0 ! set all elements to zero - array1(1:5) = 1 ! set first five elements to one - array1(6:) = 1 ! set all elements after five to one - - print *,array1(1:10:2) ! print out elements at odd indices - print *,array2(:,1) ! print out the first column in a 2D array - print *,array1(10:1:-1) ! print an array in reverse - -end program array_slice -``` - -{% include note.html content="Fortran arrays are stored in __column major__ order; the first -index varies fastest." %} - -__Example:__ allocatable (dynamic) arrays -```fortran -program allocatable - implicit none - - integer, allocatable :: array1(:) - integer, allocatable :: array2(:,:) - - allocate(array1(10)) - allocate(array2(10,10)) - - ... - - deallocate(array1) - deallocate(array2) - -end program allocatable -``` - -{% include note.html content="Allocatable local arrays are deallocated automatically -when they go out of scope." %} - - -### Character strings - - -__Example:__ static character string -```fortran -program string - implicit none - - character(len=4) :: first_name - character(len=5) :: last_name - character(10) :: full_name - - first_name = 'John' - last_name = 'Smith' - - ! String concatenation - full_name = first_name//' '//last_name - - print *, full_name - -end program string -``` - -__Example:__ allocatable character string -```fortran -program allocatable_string - implicit none - - character(:), allocatable :: first_name - character(:), allocatable :: last_name - - ! Explicit allocation statement - allocate(character(4) :: first_name) - first_name = 'John' - - ! Allocation on assignment - last_name = 'Smith' - - print *, first_name//' '//last_name - -end program allocatable_string -``` - - -## Standard input / output - -We can use the `print` statement introduced earlier to print variable values to `stdout`: - -```fortran - print *, 'The value of amount (integer) is: ',amount - print *, 'The value of pi (real) is: ',pi - print *, 'The value of frequency (complex) is: ',frequency - print *, 'The value of initial (character) is: ',initial - print *, 'The value of isOkay (logical) is: ',isOkay -``` - -and the `read` statement to read values from `stdin`: - -```fortran -program read_value - implicit none - integer :: age - - print *, 'Please enter your age: ' - read(*,*) age - - print *, 'Your age is: ',age - -end program read_value -``` - -## Operators - -The usual set of arithmetic operators are available, listed in order or precedence: - -| Operator   | Description | -|:----------------:|----------------| -| `**` | Exponent | -| `*` | Multiplication | -| `/ ` | Division | -| `+` | Addition | -| `-` | Subtraction | - -
    - -{% include important.html title="Watch out" content="for accidental integer division: `1/2` is equal to `0` -because both the numerator and denominator are integers." %} - -To form a logical expression the following set of relational operators are available: - -| Operator   | Alternative   | Description | -|:----------------:|:---------------------:|-----------------------------------------------------------------| -| `==` | `.eq.` | Tests for equality of two operands | -| `/=` | `.ne.` | Test for inequality of two operands | -| `> ` | `.gt.` | Tests if left operand is strictly greater than right operand | -| `< ` | `.lt.` | Tests if left operand is strictly less than right operand | -| `>=` | `.ge.` | Tests if left operand is greater than or equal to right operand | -| `<=` | `.le.` | Tests if left operand is less than or equal to right operand | - -
    - -as well as the following logical operators: - -| Operator   | Description | -|:---------------------:|----------------------------------------------------------------| -| `.and.` | TRUE if both left and right operands are TRUE | -| `.or.` | TRUE if either left or right or both operands are TRUE | -| `.not.` | TRUE if right operand is FALSE | -| `.eqv.` | TRUE if left operand has same logical value as right operand | -| `.neqv.` | TRUE if left operand has the opposite logical value as right operand | - -
    - - - - - - - - - - -## Controlling program flow - -### Conditional construct (`if`) - -__Example:__ single branch `if` - -```fortran - if (angle < 90.0) then - print *, 'Angle is acute' - end if -``` - -__Example:__ two-branch `if-else` - -```fortran - if (angle < 90.0) then - print *, 'Angle is acute' - else - print *, 'Angle is obtuse' - end if -``` - -__Example:__ multi-branch `if-elseif-else` -```fortran - if (age < 90.0) then - print *, 'Angle is acute' - else if (angle < 180.0) then - print *, 'Angle is obtuse' - else - print *, 'Angle is reflex' - end if -``` - - -### Loop constructs (`do`) - -__Example:__ `do` loop - -```fortran - integer :: i - do i=1,10 - print *, i - end do -``` - -__Example:__ `do` loop with skip - -```fortran - integer :: i - do i=1,10,2 - print *, i ! Print odd numbers - end do -``` - - -__Example:__ `do while` loop - -```fortran - integer :: i - i = 1 - do while (i<11) - print *, i - i = i + 1 - end do -``` - - -## Procedures - -Fortran has two forms of procedure: - -- __Subroutine:__ invoked by a `call` statement -- __Function:__ invoked within an expression or assignment to which it returns a value - -Both subroutines and functions have access to variables in the parent scope by _argument association_; -unless the `VALUE` attribute is specified, this is similar to call by reference. - -### Subroutines - - -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. - -__Example:__ - -```fortran -! Print matrix A to screen -subroutine print_matrix(n,m,A) - implicit none - integer, intent(in) :: n - integer, intent(in) :: m - real, intent(in) :: A(n,m) - - integer :: i - do i=1,n - print *,A(i,1:m) - end do - -end subroutine print_matrix -``` - - -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)`) '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)`. - -{% include tip.html content="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." %} - - -We can call this subroutine from a program using a `call` statement: -```fortran -program call_sub - implicit none - - real :: mat(10,20) - - mat(:,:) = 0.0 - - call print_matrix(10,20,mat) - -end program call_sub -``` - -{% include note.html content="This example uses a so-called _explicit-shape_ array argument since we have passed additional variables to describe -the dimensions of the array `A`; this will not be necessary if we place our subroutine in a module as described later." %} - - -### Functions - -```fortran -! L2 Norm of a vector -function vector_norm(n,vec) result(norm) - implicit none - integer, intent(in) :: n - real, intent(in) :: vec(n) - real :: norm - - norm = sqrt(sum(vec**2)) - -end function vector_norm -``` - -To execute this function: - -```fortran -program run_fcn - implicit none - - real :: v(9) - real :: vector_norm - - v(:) = 9 - - print *, 'Vector norm = ',vector_norm(9,v) - -end program run_fcn -``` - -{% include tip.html content="It is good programming practice for functions not to modify their arguments - _i.e._ all function arguments should be `intent(in)` - such -functions are known as `pure` functions. Use subroutines if your procedure needs to modify its arguments." %} - - -## Modules - -Fortran modules contain definitions that are made accessible to programs, procedures and other modules through the `use` statement. -They can contain data objects, type definitions, procedures and interfaces. - -- Modules allow controlled scoping extension whereby entity access is made explicit -- Modules automatically generate explicit interfaces required for modern procedures - -{% include tip.html content="It is recommended to always place functions and subroutines -within modules." %} - -__Example:__ - -```fortran -module my_mod - implicit none - - private ! All entities are module-private by default - public public_var, print_matrix ! Explicitly export public entities - - real, parameter :: public_var = 2 - integer :: private_var - - contains - - ! Print matrix A to screen - subroutine print_matrix(A) - real, intent(in) :: A(:,:) ! An assumed-shape dummy argument - - integer :: i - do i=1,size(A,1) - print *,A(i,:) - end do - - end subroutine print_matrix - -end module my_mod -``` - -{% include note.html content="Compare this `print_matrix` subroutine with [that written outside of a module](#subroutines); -we no longer have to explicitly pass the matrix dimensions and can instead take -advantage of _assumed-shape_ arguments since the module will generate the required -explicit interface for us. This results in a much simpler subroutine interface." %} - -To `use` the module within a program: -```fortran -program use_mod - use my_mod - implicit none - - real :: mat(10,10) - - mat(:,:) = public_var - - call print_matrix(mat) - -end program use_mod -``` - -__Example:__ explicit import list - -```fortran - use my_mod, only: public_var -``` - -__Example:__ aliased import - -```fortran - use my_mod, only: printMat=>print_matrix -``` - -{% include note.html content="Each module should be written in a separate .f90 source file. Modules need to be compiled prior to any program units that `use` them." %} - - +Welcome to the Fortran guide! +Here you will find step-by-step tutorials to guide you through learning the Fortran language. diff --git a/learn/quickstart.md b/learn/quickstart.md new file mode 100644 index 000000000..7ff9a3bb6 --- /dev/null +++ b/learn/quickstart.md @@ -0,0 +1,604 @@ +--- +layout: page_learn +title: Quickstart tutorial +permalink: /learn/quickstart +navbar: Learn +--- + +This quickstart tutorial assumes familiarity with basic programming concepts such as types, variables, arrays, control flow and functions. + + +On this page: + +- [Setting up a Fortran compiler](#compiler-setup) +- [Hello world program](#hello-world) +- [Variables, arrays & strings](#variables) +- [Operators](#operators) +- [Controlling program flow (if,loops)](#controlling-program-flow) +- [Procedures (functions,subroutines)](#procedures) +- [Modules](#modules) + +## Compiler setup + +{% include note.html content="Fortran is a compiled language which means that once written, the source code must be passed through a +compiler to produce a machine executable that can be run." %} + +In this tutorial, we'll work with the free and open source +[GNU Fortran compiler (gfortran)](https://gcc.gnu.org/fortran/), +which is part of the +[GNU Compiler Colection (GCC)](https://gcc.gnu.org/). + +To install gfortran on Linux, use your system package manager. +Otherwise, for macOS or Windows, refer to gfortran binaries from +[this page](https://gcc.gnu.org/install/binaries.html). + +To check if you have _gfortran_ setup correctly, open a terminal and run the following command : + +```shell +$> gfortran --version +``` + +this should output something like: + +``` +GNU Fortran 7.5.0 +Copyright (C) 2017 Free Software Foundation, Inc. +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +``` + +## Hello world + +Once you have setup up your compiler, open a new file in your favourite code editor and enter the following: + +```fortran +program hello + ! This is a comment line, it is ignored by the compiler + print *, 'Hello, World!' +end program hello +``` + +Having saved your program to `hello.f90`, compile at the command line with: +```shell +$> gfortran hello.f90 -o hello +``` + +{% include note.html content=".f90 is the standard file extension for modern fortran source files. +The 90 refers to the first modern fortran standard in 1990." %} + +To run your compiled program: +```shell +$> ./hello +Hello, World! +``` + +## Variables + +Fortran comes with 5 built-in data types: + +* `integer` -- for data that represent whole numbers, positive or negative +* `real` -- for floating-point data (not a whole number) +* `complex` -- pair consisting of a real part and an imaginary part +* `character` -- for text data +* `logical` -- for data that represent boolean (true or false) values + +### Declaring variables + +{% include note.html content="Fortran is a statically typed language which means the type of each +variable is fixed when the program is compiled - variable types cannot change while the program is running." %} + +__Example:__ variable declaration + +```fortran +program variables + implicit none + + integer :: amount + real :: pi + complex :: frequency + character :: initial + logical :: isOkay + +end program variables +``` + +{% include note.html content="Fortran code is __case-insensitive__; you don't have to worry about the +capitalisation of your variable names but it's good practice to keep it consistent." %} + +Note the additional statement at the beginning of the program: `implicit none`. +This statement tells the compiler that all variables will be explicitly declared; without +this statement variables will be implicitly typed according to the letter they begin with. + +{% include important.html content="Always use the `implicit none` statement at +the beginning of each program and procedure. Implicit typing is considered bad practice in +modern programming since it hides information leading to more program errors." %} + +__Example:__ variable assignment + +```fortran + amount = 10 + pi = 4.141592 + frequency = (1.0,-0.5) + initial = 'A' + isOkay = .false. +``` + +Characters are surrounded by either single (`'`) or double quotes (`"`). + +Logical or boolean values can be either `.true.` or `.false.`. + +{% include important.html title="Watch out" content="for assignment at declaration: `integer :: amount = 1`. +__This is NOT a normal initialisation;__ it implies the `save` attribute which means that the variable retains +its value between procedure calls. Good practice is to initialise your variables separately to their declaration." %} + + + +### Floating-point precision + +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 32bit and 64bit floating point types. + +__Example:__ explicit real kind +```fortran +program float + use, intrinsic :: iso_fortran_env, only: sp=>real32, dp=>real64 + implicit none + + real(sp) :: float32 + real(dp) :: float64 + + float32 = 1.0_sp ! Explicit suffix for literal constants + float64 = 1.0_dp + +end program float +``` + +{% include important.html content="Always use a `kind` suffix for floating point literal constants." %} + +__Example:__ c-interoperable kinds +```fortran +program float + use, intrinsic :: iso_c_binding, only: sp=>c_float, dp=>c_double + implicit none + + real(sp) :: float32 + real(dp) :: float64 + +end program float +``` + + +### Arrays + +{% include important.html content="Arrays in Fortran are __one-based__ by default; this means +that the first element along any dimension is at index 1." %} + +__Example:__ static array declaration +```fortran +program arrays + implicit none + + ! 1D integer array + integer, dimension(10) :: array1 + + ! An equivalent array declaration + integer :: array2(10) + + ! 2D real array + real, dimension(10,10) :: array3 + + ! Custom lower and upper index bounds + real :: array4(0:9) + real :: array5(-5:5) + +end program arrays +``` + +__Example:__ array slicing +```fortran +program array_slice + implicit none + + integer :: i + integer :: array1(10) ! 1D integer array of 10 elements + integer :: array2(10,10) ! 2D integer array of 100 elements + + array1 = [1,2,3,4,5,6,7,8,9,10] ! Array constructor + array1 = [(i,i=1,10)] ! Implied do loop constructor + array1(:) = 0 ! set all elements to zero + array1(1:5) = 1 ! set first five elements to one + array1(6:) = 1 ! set all elements after five to one + + print *,array1(1:10:2) ! print out elements at odd indices + print *,array2(:,1) ! print out the first column in a 2D array + print *,array1(10:1:-1) ! print an array in reverse + +end program array_slice +``` + +{% include note.html content="Fortran arrays are stored in __column major__ order; the first +index varies fastest." %} + +__Example:__ allocatable (dynamic) arrays +```fortran +program allocatable + implicit none + + integer, allocatable :: array1(:) + integer, allocatable :: array2(:,:) + + allocate(array1(10)) + allocate(array2(10,10)) + + ... + + deallocate(array1) + deallocate(array2) + +end program allocatable +``` + +{% include note.html content="Allocatable local arrays are deallocated automatically +when they go out of scope." %} + + +### Character strings + + +__Example:__ static character string +```fortran +program string + implicit none + + character(len=4) :: first_name + character(len=5) :: last_name + character(10) :: full_name + + first_name = 'John' + last_name = 'Smith' + + ! String concatenation + full_name = first_name//' '//last_name + + print *, full_name + +end program string +``` + +__Example:__ allocatable character string +```fortran +program allocatable_string + implicit none + + character(:), allocatable :: first_name + character(:), allocatable :: last_name + + ! Explicit allocation statement + allocate(character(4) :: first_name) + first_name = 'John' + + ! Allocation on assignment + last_name = 'Smith' + + print *, first_name//' '//last_name + +end program allocatable_string +``` + + +## Standard input / output + +We can use the `print` statement introduced earlier to print variable values to `stdout`: + +```fortran + print *, 'The value of amount (integer) is: ',amount + print *, 'The value of pi (real) is: ',pi + print *, 'The value of frequency (complex) is: ',frequency + print *, 'The value of initial (character) is: ',initial + print *, 'The value of isOkay (logical) is: ',isOkay +``` + +and the `read` statement to read values from `stdin`: + +```fortran +program read_value + implicit none + integer :: age + + print *, 'Please enter your age: ' + read(*,*) age + + print *, 'Your age is: ',age + +end program read_value +``` + +## Operators + +The usual set of arithmetic operators are available, listed in order or precedence: + +| Operator   | Description | +|:----------------:|----------------| +| `**` | Exponent | +| `*` | Multiplication | +| `/ ` | Division | +| `+` | Addition | +| `-` | Subtraction | + +
    + +{% include important.html title="Watch out" content="for accidental integer division: `1/2` is equal to `0` +because both the numerator and denominator are integers." %} + +To form a logical expression the following set of relational operators are available: + +| Operator   | Alternative   | Description | +|:----------------:|:---------------------:|-----------------------------------------------------------------| +| `==` | `.eq.` | Tests for equality of two operands | +| `/=` | `.ne.` | Test for inequality of two operands | +| `> ` | `.gt.` | Tests if left operand is strictly greater than right operand | +| `< ` | `.lt.` | Tests if left operand is strictly less than right operand | +| `>=` | `.ge.` | Tests if left operand is greater than or equal to right operand | +| `<=` | `.le.` | Tests if left operand is less than or equal to right operand | + +
    + +as well as the following logical operators: + +| Operator   | Description | +|:---------------------:|----------------------------------------------------------------| +| `.and.` | TRUE if both left and right operands are TRUE | +| `.or.` | TRUE if either left or right or both operands are TRUE | +| `.not.` | TRUE if right operand is FALSE | +| `.eqv.` | TRUE if left operand has same logical value as right operand | +| `.neqv.` | TRUE if left operand has the opposite logical value as right operand | + +
    + + + + + + + + + + +## Controlling program flow + +### Conditional construct (`if`) + +__Example:__ single branch `if` + +```fortran + if (angle < 90.0) then + print *, 'Angle is acute' + end if +``` + +__Example:__ two-branch `if-else` + +```fortran + if (angle < 90.0) then + print *, 'Angle is acute' + else + print *, 'Angle is obtuse' + end if +``` + +__Example:__ multi-branch `if-elseif-else` +```fortran + if (age < 90.0) then + print *, 'Angle is acute' + else if (angle < 180.0) then + print *, 'Angle is obtuse' + else + print *, 'Angle is reflex' + end if +``` + + +### Loop constructs (`do`) + +__Example:__ `do` loop + +```fortran + integer :: i + do i=1,10 + print *, i + end do +``` + +__Example:__ `do` loop with skip + +```fortran + integer :: i + do i=1,10,2 + print *, i ! Print odd numbers + end do +``` + + +__Example:__ `do while` loop + +```fortran + integer :: i + i = 1 + do while (i<11) + print *, i + i = i + 1 + end do +``` + + +## Procedures + +Fortran has two forms of procedure: + +- __Subroutine:__ invoked by a `call` statement +- __Function:__ invoked within an expression or assignment to which it returns a value + +Both subroutines and functions have access to variables in the parent scope by _argument association_; +unless the `VALUE` attribute is specified, this is similar to call by reference. + +### Subroutines + + +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. + +__Example:__ + +```fortran +! Print matrix A to screen +subroutine print_matrix(n,m,A) + implicit none + integer, intent(in) :: n + integer, intent(in) :: m + real, intent(in) :: A(n,m) + + integer :: i + do i=1,n + print *,A(i,1:m) + end do + +end subroutine print_matrix +``` + + +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)`) '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)`. + +{% include tip.html content="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." %} + + +We can call this subroutine from a program using a `call` statement: +```fortran +program call_sub + implicit none + + real :: mat(10,20) + + mat(:,:) = 0.0 + + call print_matrix(10,20,mat) + +end program call_sub +``` + +{% include note.html content="This example uses a so-called _explicit-shape_ array argument since we have passed additional variables to describe +the dimensions of the array `A`; this will not be necessary if we place our subroutine in a module as described later." %} + + +### Functions + +```fortran +! L2 Norm of a vector +function vector_norm(n,vec) result(norm) + implicit none + integer, intent(in) :: n + real, intent(in) :: vec(n) + real :: norm + + norm = sqrt(sum(vec**2)) + +end function vector_norm +``` + +To execute this function: + +```fortran +program run_fcn + implicit none + + real :: v(9) + real :: vector_norm + + v(:) = 9 + + print *, 'Vector norm = ',vector_norm(9,v) + +end program run_fcn +``` + +{% include tip.html content="It is good programming practice for functions not to modify their arguments - _i.e._ all function arguments should be `intent(in)` - such +functions are known as `pure` functions. Use subroutines if your procedure needs to modify its arguments." %} + + +## Modules + +Fortran modules contain definitions that are made accessible to programs, procedures and other modules through the `use` statement. +They can contain data objects, type definitions, procedures and interfaces. + +- Modules allow controlled scoping extension whereby entity access is made explicit +- Modules automatically generate explicit interfaces required for modern procedures + +{% include tip.html content="It is recommended to always place functions and subroutines +within modules." %} + +__Example:__ + +```fortran +module my_mod + implicit none + + private ! All entities are module-private by default + public public_var, print_matrix ! Explicitly export public entities + + real, parameter :: public_var = 2 + integer :: private_var + + contains + + ! Print matrix A to screen + subroutine print_matrix(A) + real, intent(in) :: A(:,:) ! An assumed-shape dummy argument + + integer :: i + do i=1,size(A,1) + print *,A(i,:) + end do + + end subroutine print_matrix + +end module my_mod +``` + +{% include note.html content="Compare this `print_matrix` subroutine with [that written outside of a module](#subroutines); +we no longer have to explicitly pass the matrix dimensions and can instead take +advantage of _assumed-shape_ arguments since the module will generate the required +explicit interface for us. This results in a much simpler subroutine interface." %} + +To `use` the module within a program: +```fortran +program use_mod + use my_mod + implicit none + + real :: mat(10,10) + + mat(:,:) = public_var + + call print_matrix(mat) + +end program use_mod +``` + +__Example:__ explicit import list + +```fortran + use my_mod, only: public_var +``` + +__Example:__ aliased import + +```fortran + use my_mod, only: printMat=>print_matrix +``` + +{% include note.html content="Each module should be written in a separate .f90 source file. Modules need to be compiled prior to any program units that `use` them." %} + + + From fb961e102ddddf83b5a1aa91d3904cdb8821d5d4 Mon Sep 17 00:00:00 2001 From: LKedward Date: Sat, 30 May 2020 15:32:03 +0100 Subject: [PATCH 2/9] Restructure learn section for mini-books Restructures the previous monolithic structure into one supporting many independent mini-book tutorials. --- _data/fortran_guide.yml | 17 --- _data/learning.yml | 89 ++++++++++++++ _includes/book_navbar.html | 90 ++++++++++++++ _includes/learn_nav_sidebar.html | 73 ----------- _layouts/book.html | 56 +++++++++ _layouts/page_learn.html | 30 ----- assets/css/main.css | 45 ++++++- learn/faq.md | 13 -- learn/index.html | 123 +++++++++++++++++++ learn/index.md | 10 -- learn/{quickstart.md => quickstart/index.md} | 0 packages/index.html | 4 +- 12 files changed, 403 insertions(+), 147 deletions(-) delete mode 100644 _data/fortran_guide.yml create mode 100644 _data/learning.yml create mode 100644 _includes/book_navbar.html delete mode 100644 _includes/learn_nav_sidebar.html create mode 100644 _layouts/book.html delete mode 100644 _layouts/page_learn.html delete mode 100644 learn/faq.md create mode 100644 learn/index.html delete mode 100644 learn/index.md rename learn/{quickstart.md => quickstart/index.md} (100%) diff --git a/_data/fortran_guide.yml b/_data/fortran_guide.yml deleted file mode 100644 index 8e3fd4602..000000000 --- a/_data/fortran_guide.yml +++ /dev/null @@ -1,17 +0,0 @@ -appendices: [~,A,B,C,D] - -chapters: - - title: Introduction - pages: - - title: Learn Fortran - url: /learn/ - - - title: Getting started - pages: - - title: Quickstart tutorial - url: /learn/quickstart - - - title: Appendices - pages: - - title: Fortran FAQ - url: /learn/faq diff --git a/_data/learning.yml b/_data/learning.yml new file mode 100644 index 000000000..b61d2085e --- /dev/null +++ b/_data/learning.yml @@ -0,0 +1,89 @@ +# Categories group mini-books on the 'Learn' landing page +# +# 'fa-icon' refers to the font-awesome icon to display +# next to the category on the landing page +# +categories: + - name: Getting started + fa-icon: fas fa-cubes + # - name: Advanced programming methods + # fa-icon: fas fa-laptop-code + + + +# Mini-books are single-page or multi-page tutorials +# +# 'link' refers to the 'permalink' field of the corresponding page +# +books: + - title: Quickstart Fortran Tutorial + description: An introduction to the Fortran syntax and its capabilities + category: Getting started + link: /learn/quickstart + pages: + - link: /learn/quickstart/hello_world + - link: /learn/quickstart/variables + - link: /learn/quickstart/arrays_strings + - link: /learn/quickstart/operators_control_flow + - link: /learn/quickstart/organising_code + + + +# Web links listed at the bottom of the 'Learn' landing page +# +reference-links: + - name: Fortran wiki + url: http://fortranwiki.org/ + description: A rich collection of Fortran articles and resources in an editable wiki format + + - name: "Fortran 2018 Standard Interpretation Document" + url: https://j3-fortran.org/doc/year/18/18-007r1.pdf + description: "J3/18-007r1 F2018, specification of the base Fortran 2018 language" + + - name: "J3: US Fortran Standards Committee" + url: https://j3-fortran.org/ + description: J3 is the US National Body for the international Fortran standards committee + + - name: "WG5: International Fortran Standards Committe" + url: https://wg5-fortran.org/ + description: + + - name: "Scivision Fortran 2018 Examples" + url: https://github.com/scivision/fortran2018-examples + description: A github repository containing code samples for various Fortran 2018 features + + + + +# Print books listed at the bottom of the 'Learn' landing page +# +reference-books: + - author: Michael Metcalf, John Reid, and Malcolm Cohen + year: 2018 + title: Modern Fortran Explained + url: https://global.oup.com/academic/product/modern-fortran-explained-9780198811893 + edition: 5th ed + location: Oxford, UK + publisher: Oxford Universtiy Press + + - author: Curcic, M. + year: 2019 + title: "Modern Fortran: Building efficient parallel programs" + url: https://www.manning.com/books/modern-fortran + edition: 1st ed + publisher: Manning publications + + - author: Chivers, I. and Sleightholme, J. + year: 2018 + title: Introduction to Programming with Fortran + url: https://doi.org/10.1007/978-3-319-75502-1 + edition: 4th ed + publisher: Springer International Publishing + + - author: Chapman S. J. + year: 2018 + title: Fortran for Scientists and Engineers + url: https://www.mheducation.com/highered/product/fortran-scientists-engineers-chapman/M9780073385891.html + edition: 4th ed + location: New York + publisher: McGraw-Hill Education \ No newline at end of file diff --git a/_includes/book_navbar.html b/_includes/book_navbar.html new file mode 100644 index 000000000..186b3b3d7 --- /dev/null +++ b/_includes/book_navbar.html @@ -0,0 +1,90 @@ + + diff --git a/_includes/learn_nav_sidebar.html b/_includes/learn_nav_sidebar.html deleted file mode 100644 index 638f63404..000000000 --- a/_includes/learn_nav_sidebar.html +++ /dev/null @@ -1,73 +0,0 @@ - - diff --git a/_layouts/book.html b/_layouts/book.html new file mode 100644 index 000000000..76b2b642d --- /dev/null +++ b/_layouts/book.html @@ -0,0 +1,56 @@ +--- +layout: default +--- + +{% include nav.html active=page.navbar %} + +
    +
    + + {% include book_navbar.html %} + + + +
    +
    diff --git a/_layouts/page_learn.html b/_layouts/page_learn.html deleted file mode 100644 index e5bbd3d7f..000000000 --- a/_layouts/page_learn.html +++ /dev/null @@ -1,30 +0,0 @@ ---- -layout: default ---- - -{% include nav.html active=page.navbar %} - -
    -
    - - {% include learn_nav_sidebar.html %} - - - - - -
    -
    diff --git a/assets/css/main.css b/assets/css/main.css index 7d85962ca..5e7a317d2 100644 --- a/assets/css/main.css +++ b/assets/css/main.css @@ -25,6 +25,42 @@ a { font-weight: bold; } +.button { + background-color: #734f96; + border: none; + color: white; + padding: 10px 32px; + text-align: center; + text-decoration: none; + display: inline-block; + font-size: 20px; + border-radius: 8px; +} + +.button.center { + display: block; + margin: 0 auto; + width: fit-content; +} + +.button:hover { + background-color: #777; + color: white; + text-decoration: none; +} + +.button.blue{ + background-color: #008CBA; +} + +.button.blue:hover{ + background-color: #777; +} + +#page-nav { + padding-left: 20px; +} + h1, h2, h3 { @@ -55,11 +91,15 @@ a[target="_blank"]:after { margin: 0 3px 0 5px; } -/* " except in the navbar */ +/* " except in the navbar and buttons*/ .navbar a[target="_blank"]:after { content:''; margin: 0px; } +.button[target="_blank"]:after { + content:''; + margin: 0px; +} /* Hide text for social navbar icons if not on mobile device*/ @@ -106,7 +146,8 @@ pre { } .container-flex{ - margin: 0 15px; + margin: 0 auto; + width: 90%; display: flex; flex-wrap: wrap; } diff --git a/learn/faq.md b/learn/faq.md deleted file mode 100644 index 83a512f99..000000000 --- a/learn/faq.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -layout: page_learn -title: Fortran FAQ -permalink: /learn/faq -navbar: Learn ---- - -## Heading 1 - - -## Heading 2 - -## Heading 3 \ No newline at end of file diff --git a/learn/index.html b/learn/index.html new file mode 100644 index 000000000..71764f391 --- /dev/null +++ b/learn/index.html @@ -0,0 +1,123 @@ +--- +layout: default +title: Learn Fortran +description: Learning resources for beginners and experts alike +--- + +{% include nav.html active='Learn' %} + +
    +

    {{ page.title }}

    +

    {{ page.description }}

    +
    + +
    +
    +

    Getting Started

    + +
    +

    + New to Fortran

    +

    + Try the quickstart Fortran tutorial, to + get an overview of the language syntax and capabilities. +

    + + + Quickstart tutorial + + +
    + +
    +

    + Looking for help

    +

    + Ask a question in the Fortran-lang discourse - a forum + for friendly discussion of all things Fortran. + +

    + + + Fortran-lang Discourse + + +
    + +
    +
    +
    + +
    +
    + +

    Mini-book Tutorials

    + + {% for category in site.data.learning.categories %} + +

    + {% if category.fa-icon %} + + {% endif %} + {{ category.name }}

    + +
    + {% assign catBooks = site.data.learning.books | where_exp:"book", "book.category == category.name"%} + + {% for book in catBooks %} +
    +

    + + + {{ book.title }} +

    +

    {{ book.description }}

    +
    + {% endfor %} +
    + + {% endfor %} + +
    +
    +
    + +
    +
    + +

    Other Resources

    + +

    On the web

    +
      + + {% for refLink in site.data.learning.reference-links %} +
    • + + {{ refLink.name }} + + {{ refLink.description }} +
    • + {% endfor %} + +
    + +

    In print

    +
      + + {% for refBook in site.data.learning.reference-books %} +
    • + {{ refBook.author }}. {{ refBook.year }}. + + {{ refBook.title }} + . + {{ refBook.edition }}. + {{ refBook.location }}. + {{ refBook.publisher }} +
    • + {% endfor %} + +
    + +
    +
    + diff --git a/learn/index.md b/learn/index.md deleted file mode 100644 index 598e49ecd..000000000 --- a/learn/index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -layout: page_learn -title: Learn Fortran -permalink: /learn/ -navbar: Learn ---- - -Welcome to the Fortran guide! -Here you will find step-by-step tutorials to guide you through learning the Fortran language. - diff --git a/learn/quickstart.md b/learn/quickstart/index.md similarity index 100% rename from learn/quickstart.md rename to learn/quickstart/index.md diff --git a/packages/index.html b/packages/index.html index 479653759..cd4da0e3e 100644 --- a/packages/index.html +++ b/packages/index.html @@ -78,14 +78,14 @@

    -

    Featured open source projects

    +

    Featured open source projects

    -

    Browse by category

    +

    Browse by category

    {% for sitePage in site.pages %} From 1c132c9599085ca486284865deae496b6abf3da9 Mon Sep 17 00:00:00 2001 From: LKedward Date: Sat, 30 May 2020 15:33:16 +0100 Subject: [PATCH 3/9] Break quickstart mini-book tutorial into multiple pages This makes for easier navigation. --- learn/quickstart/arrays_strings.md | 154 ++++++ learn/quickstart/hello_world.md | 69 +++ learn/quickstart/index.md | 600 +-------------------- learn/quickstart/operators_control_flow.md | 138 +++++ learn/quickstart/organising_code.md | 178 ++++++ learn/quickstart/variables.md | 206 +++++++ 6 files changed, 751 insertions(+), 594 deletions(-) create mode 100644 learn/quickstart/arrays_strings.md create mode 100644 learn/quickstart/hello_world.md create mode 100644 learn/quickstart/operators_control_flow.md create mode 100644 learn/quickstart/organising_code.md create mode 100644 learn/quickstart/variables.md diff --git a/learn/quickstart/arrays_strings.md b/learn/quickstart/arrays_strings.md new file mode 100644 index 000000000..a13bc966c --- /dev/null +++ b/learn/quickstart/arrays_strings.md @@ -0,0 +1,154 @@ +--- +layout: book +title: Arrays and strings +permalink: /learn/quickstart/arrays_strings +navbar: Learn +--- + + + +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_. + +Arrays are _multidimensional_ variables which contain more than value +where each value is accessed using one or indices. + +{% include important.html content="Arrays in Fortran are __one-based__ by default; this means +that the first element along any dimension is at index 1." %} + + +## Array declaration + +We can declare arrays of any type. 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. + +__Example:__ static array declaration +```fortran +program arrays + implicit none + + ! 1D integer array + integer, dimension(10) :: array1 + + ! An equivalent array declaration + integer :: array2(10) + + ! 2D real array + real, dimension(10,10) :: array3 + + ! Custom lower and upper index bounds + real :: array4(0:9) + real :: array5(-5:5) + +end program arrays +``` + +## Array slicing + +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: + +__Example:__ array slicing +```fortran +program array_slice + implicit none + + integer :: i + integer :: array1(10) ! 1D integer array of 10 elements + integer :: array2(10,10) ! 2D integer array of 100 elements + + array1 = [1,2,3,4,5,6,7,8,9,10] ! Array constructor + array1 = [(i,i=1,10)] ! Implied do loop constructor + array1(:) = 0 ! set all elements to zero + array1(1:5) = 1 ! set first five elements to one + array1(6:) = 1 ! set all elements after five to one + + print *,array1(1:10:2) ! print out elements at odd indices + print *,array2(:,1) ! print out the first column in a 2D array + print *,array1(10:1:-1) ! print an array in reverse + +end program array_slice +``` + +{% include note.html content="Fortran arrays are stored in __column major__ order; the first +index varies fastest." %} + +## Allocatable (dynamic) arrays + +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. + +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. + +For this problem, we need `allocatable` arrays, these are _allocated_ +while the program is runnning once we know how big the array needs to be. + +__Example:__ allocatable arrays +```fortran +program allocatable + implicit none + + integer, allocatable :: array1(:) + integer, allocatable :: array2(:,:) + + allocate(array1(10)) + allocate(array2(10,10)) + + ... + + deallocate(array1) + deallocate(array2) + +end program allocatable +``` + +{% include note.html content="Allocatable local arrays are deallocated automatically +when they go out of scope." %} + + +## Character strings + + +__Example:__ static character string +```fortran +program string + implicit none + + character(len=4) :: first_name + character(len=5) :: last_name + character(10) :: full_name + + first_name = 'John' + last_name = 'Smith' + + ! String concatenation + full_name = first_name//' '//last_name + + print *, full_name + +end program string +``` + +__Example:__ allocatable character string +```fortran +program allocatable_string + implicit none + + character(:), allocatable :: first_name + character(:), allocatable :: last_name + + ! Explicit allocation statement + allocate(character(4) :: first_name) + first_name = 'John' + + ! Allocation on assignment + last_name = 'Smith' + + print *, first_name//' '//last_name + +end program allocatable_string +``` + diff --git a/learn/quickstart/hello_world.md b/learn/quickstart/hello_world.md new file mode 100644 index 000000000..4fb5e0388 --- /dev/null +++ b/learn/quickstart/hello_world.md @@ -0,0 +1,69 @@ +--- +layout: book +title: Hello World +permalink: /learn/quickstart/hello_world +navbar: Learn +--- + +In this part of the tutorial, we will write our first Fortran program: +the ubiquitous _Hello World_ example. + +However before we can write our program, we need to ensure that we have +a Fortran compiler set up. + +{% include note.html content="Fortran is a compiled language which means that once written, the source code must be passed through a +compiler to produce a machine executable that can be run." %} + +## Compiler setup + +In this tutorial, we'll work with the free and open source +[GNU Fortran compiler (gfortran)](https://gcc.gnu.org/fortran/), +which is part of the +[GNU Compiler Colection (GCC)](https://gcc.gnu.org/). + +To install gfortran on Linux, use your system package manager. +Otherwise, for macOS or Windows, refer to gfortran binaries from +[this page](https://gcc.gnu.org/install/binaries.html). + +To check if you have _gfortran_ setup correctly, open a terminal and run the following command : + +```shell +$> gfortran --version +``` + +this should output something like: + +``` +GNU Fortran 7.5.0 +Copyright (C) 2017 Free Software Foundation, Inc. +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +``` + +## Hello world + +Once you have setup up your compiler, open a new file in your favourite code editor and enter the following: + +```fortran +program hello + ! This is a comment line, it is ignored by the compiler + print *, 'Hello, World!' +end program hello +``` + +Having saved your program to `hello.f90`, compile at the command line with: +```shell +$> gfortran hello.f90 -o hello +``` + +{% include note.html content=".f90 is the standard file extension for modern fortran source files. +The 90 refers to the first modern fortran standard in 1990." %} + +To run your compiled program: +```shell +$> ./hello +Hello, World! +``` + +Congratulations you've written, compiled and run your first Fortran program! +In the next part of this tutorial we will introduce variables for storing data. \ No newline at end of file diff --git a/learn/quickstart/index.md b/learn/quickstart/index.md index 7ff9a3bb6..6bb573b0c 100644 --- a/learn/quickstart/index.md +++ b/learn/quickstart/index.md @@ -1,604 +1,16 @@ --- -layout: page_learn +layout: book title: Quickstart tutorial permalink: /learn/quickstart navbar: Learn --- - -This quickstart tutorial assumes familiarity with basic programming concepts such as types, variables, arrays, control flow and functions. +This quickstart tutorial gives an overview of the Fortran programming language +and its syntax for common structured programming concepts including: +types, variables, arrays, control flow and functions. -On this page: - -- [Setting up a Fortran compiler](#compiler-setup) -- [Hello world program](#hello-world) -- [Variables, arrays & strings](#variables) -- [Operators](#operators) -- [Controlling program flow (if,loops)](#controlling-program-flow) -- [Procedures (functions,subroutines)](#procedures) -- [Modules](#modules) - -## Compiler setup - -{% include note.html content="Fortran is a compiled language which means that once written, the source code must be passed through a -compiler to produce a machine executable that can be run." %} - -In this tutorial, we'll work with the free and open source -[GNU Fortran compiler (gfortran)](https://gcc.gnu.org/fortran/), -which is part of the -[GNU Compiler Colection (GCC)](https://gcc.gnu.org/). - -To install gfortran on Linux, use your system package manager. -Otherwise, for macOS or Windows, refer to gfortran binaries from -[this page](https://gcc.gnu.org/install/binaries.html). - -To check if you have _gfortran_ setup correctly, open a terminal and run the following command : - -```shell -$> gfortran --version -``` - -this should output something like: - -``` -GNU Fortran 7.5.0 -Copyright (C) 2017 Free Software Foundation, Inc. -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -``` - -## Hello world - -Once you have setup up your compiler, open a new file in your favourite code editor and enter the following: - -```fortran -program hello - ! This is a comment line, it is ignored by the compiler - print *, 'Hello, World!' -end program hello -``` - -Having saved your program to `hello.f90`, compile at the command line with: -```shell -$> gfortran hello.f90 -o hello -``` - -{% include note.html content=".f90 is the standard file extension for modern fortran source files. -The 90 refers to the first modern fortran standard in 1990." %} - -To run your compiled program: -```shell -$> ./hello -Hello, World! -``` - -## Variables - -Fortran comes with 5 built-in data types: - -* `integer` -- for data that represent whole numbers, positive or negative -* `real` -- for floating-point data (not a whole number) -* `complex` -- pair consisting of a real part and an imaginary part -* `character` -- for text data -* `logical` -- for data that represent boolean (true or false) values - -### Declaring variables - -{% include note.html content="Fortran is a statically typed language which means the type of each -variable is fixed when the program is compiled - variable types cannot change while the program is running." %} - -__Example:__ variable declaration - -```fortran -program variables - implicit none - - integer :: amount - real :: pi - complex :: frequency - character :: initial - logical :: isOkay - -end program variables -``` - -{% include note.html content="Fortran code is __case-insensitive__; you don't have to worry about the -capitalisation of your variable names but it's good practice to keep it consistent." %} - -Note the additional statement at the beginning of the program: `implicit none`. -This statement tells the compiler that all variables will be explicitly declared; without -this statement variables will be implicitly typed according to the letter they begin with. - -{% include important.html content="Always use the `implicit none` statement at -the beginning of each program and procedure. Implicit typing is considered bad practice in -modern programming since it hides information leading to more program errors." %} - -__Example:__ variable assignment - -```fortran - amount = 10 - pi = 4.141592 - frequency = (1.0,-0.5) - initial = 'A' - isOkay = .false. -``` - -Characters are surrounded by either single (`'`) or double quotes (`"`). - -Logical or boolean values can be either `.true.` or `.false.`. - -{% include important.html title="Watch out" content="for assignment at declaration: `integer :: amount = 1`. -__This is NOT a normal initialisation;__ it implies the `save` attribute which means that the variable retains -its value between procedure calls. Good practice is to initialise your variables separately to their declaration." %} - - - -### Floating-point precision - -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 32bit and 64bit floating point types. - -__Example:__ explicit real kind -```fortran -program float - use, intrinsic :: iso_fortran_env, only: sp=>real32, dp=>real64 - implicit none - - real(sp) :: float32 - real(dp) :: float64 - - float32 = 1.0_sp ! Explicit suffix for literal constants - float64 = 1.0_dp - -end program float -``` - -{% include important.html content="Always use a `kind` suffix for floating point literal constants." %} - -__Example:__ c-interoperable kinds -```fortran -program float - use, intrinsic :: iso_c_binding, only: sp=>c_float, dp=>c_double - implicit none - - real(sp) :: float32 - real(dp) :: float64 - -end program float -``` - - -### Arrays - -{% include important.html content="Arrays in Fortran are __one-based__ by default; this means -that the first element along any dimension is at index 1." %} - -__Example:__ static array declaration -```fortran -program arrays - implicit none - - ! 1D integer array - integer, dimension(10) :: array1 - - ! An equivalent array declaration - integer :: array2(10) - - ! 2D real array - real, dimension(10,10) :: array3 - - ! Custom lower and upper index bounds - real :: array4(0:9) - real :: array5(-5:5) - -end program arrays -``` - -__Example:__ array slicing -```fortran -program array_slice - implicit none - - integer :: i - integer :: array1(10) ! 1D integer array of 10 elements - integer :: array2(10,10) ! 2D integer array of 100 elements - - array1 = [1,2,3,4,5,6,7,8,9,10] ! Array constructor - array1 = [(i,i=1,10)] ! Implied do loop constructor - array1(:) = 0 ! set all elements to zero - array1(1:5) = 1 ! set first five elements to one - array1(6:) = 1 ! set all elements after five to one - - print *,array1(1:10:2) ! print out elements at odd indices - print *,array2(:,1) ! print out the first column in a 2D array - print *,array1(10:1:-1) ! print an array in reverse - -end program array_slice -``` - -{% include note.html content="Fortran arrays are stored in __column major__ order; the first -index varies fastest." %} - -__Example:__ allocatable (dynamic) arrays -```fortran -program allocatable - implicit none - - integer, allocatable :: array1(:) - integer, allocatable :: array2(:,:) - - allocate(array1(10)) - allocate(array2(10,10)) - - ... - - deallocate(array1) - deallocate(array2) - -end program allocatable -``` - -{% include note.html content="Allocatable local arrays are deallocated automatically -when they go out of scope." %} - - -### Character strings - - -__Example:__ static character string -```fortran -program string - implicit none - - character(len=4) :: first_name - character(len=5) :: last_name - character(10) :: full_name - - first_name = 'John' - last_name = 'Smith' - - ! String concatenation - full_name = first_name//' '//last_name - - print *, full_name - -end program string -``` - -__Example:__ allocatable character string -```fortran -program allocatable_string - implicit none - - character(:), allocatable :: first_name - character(:), allocatable :: last_name - - ! Explicit allocation statement - allocate(character(4) :: first_name) - first_name = 'John' - - ! Allocation on assignment - last_name = 'Smith' - - print *, first_name//' '//last_name - -end program allocatable_string -``` - - -## Standard input / output - -We can use the `print` statement introduced earlier to print variable values to `stdout`: - -```fortran - print *, 'The value of amount (integer) is: ',amount - print *, 'The value of pi (real) is: ',pi - print *, 'The value of frequency (complex) is: ',frequency - print *, 'The value of initial (character) is: ',initial - print *, 'The value of isOkay (logical) is: ',isOkay -``` - -and the `read` statement to read values from `stdin`: - -```fortran -program read_value - implicit none - integer :: age - - print *, 'Please enter your age: ' - read(*,*) age - - print *, 'Your age is: ',age - -end program read_value -``` - -## Operators - -The usual set of arithmetic operators are available, listed in order or precedence: - -| Operator   | Description | -|:----------------:|----------------| -| `**` | Exponent | -| `*` | Multiplication | -| `/ ` | Division | -| `+` | Addition | -| `-` | Subtraction | - -
    - -{% include important.html title="Watch out" content="for accidental integer division: `1/2` is equal to `0` -because both the numerator and denominator are integers." %} - -To form a logical expression the following set of relational operators are available: - -| Operator   | Alternative   | Description | -|:----------------:|:---------------------:|-----------------------------------------------------------------| -| `==` | `.eq.` | Tests for equality of two operands | -| `/=` | `.ne.` | Test for inequality of two operands | -| `> ` | `.gt.` | Tests if left operand is strictly greater than right operand | -| `< ` | `.lt.` | Tests if left operand is strictly less than right operand | -| `>=` | `.ge.` | Tests if left operand is greater than or equal to right operand | -| `<=` | `.le.` | Tests if left operand is less than or equal to right operand | - -
    - -as well as the following logical operators: - -| Operator   | Description | -|:---------------------:|----------------------------------------------------------------| -| `.and.` | TRUE if both left and right operands are TRUE | -| `.or.` | TRUE if either left or right or both operands are TRUE | -| `.not.` | TRUE if right operand is FALSE | -| `.eqv.` | TRUE if left operand has same logical value as right operand | -| `.neqv.` | TRUE if left operand has the opposite logical value as right operand | - -
    - - - - - - - - - - -## Controlling program flow - -### Conditional construct (`if`) - -__Example:__ single branch `if` - -```fortran - if (angle < 90.0) then - print *, 'Angle is acute' - end if -``` - -__Example:__ two-branch `if-else` - -```fortran - if (angle < 90.0) then - print *, 'Angle is acute' - else - print *, 'Angle is obtuse' - end if -``` - -__Example:__ multi-branch `if-elseif-else` -```fortran - if (age < 90.0) then - print *, 'Angle is acute' - else if (angle < 180.0) then - print *, 'Angle is obtuse' - else - print *, 'Angle is reflex' - end if -``` - - -### Loop constructs (`do`) - -__Example:__ `do` loop - -```fortran - integer :: i - do i=1,10 - print *, i - end do -``` - -__Example:__ `do` loop with skip - -```fortran - integer :: i - do i=1,10,2 - print *, i ! Print odd numbers - end do -``` - - -__Example:__ `do while` loop - -```fortran - integer :: i - i = 1 - do while (i<11) - print *, i - i = i + 1 - end do -``` - - -## Procedures - -Fortran has two forms of procedure: - -- __Subroutine:__ invoked by a `call` statement -- __Function:__ invoked within an expression or assignment to which it returns a value - -Both subroutines and functions have access to variables in the parent scope by _argument association_; -unless the `VALUE` attribute is specified, this is similar to call by reference. - -### Subroutines - - -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. - -__Example:__ - -```fortran -! Print matrix A to screen -subroutine print_matrix(n,m,A) - implicit none - integer, intent(in) :: n - integer, intent(in) :: m - real, intent(in) :: A(n,m) - - integer :: i - do i=1,n - print *,A(i,1:m) - end do - -end subroutine print_matrix -``` - - -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)`) '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)`. - -{% include tip.html content="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." %} - - -We can call this subroutine from a program using a `call` statement: -```fortran -program call_sub - implicit none - - real :: mat(10,20) - - mat(:,:) = 0.0 - - call print_matrix(10,20,mat) - -end program call_sub -``` - -{% include note.html content="This example uses a so-called _explicit-shape_ array argument since we have passed additional variables to describe -the dimensions of the array `A`; this will not be necessary if we place our subroutine in a module as described later." %} - - -### Functions - -```fortran -! L2 Norm of a vector -function vector_norm(n,vec) result(norm) - implicit none - integer, intent(in) :: n - real, intent(in) :: vec(n) - real :: norm - - norm = sqrt(sum(vec**2)) - -end function vector_norm -``` - -To execute this function: - -```fortran -program run_fcn - implicit none - - real :: v(9) - real :: vector_norm - - v(:) = 9 - - print *, 'Vector norm = ',vector_norm(9,v) - -end program run_fcn -``` - -{% include tip.html content="It is good programming practice for functions not to modify their arguments - _i.e._ all function arguments should be `intent(in)` - such -functions are known as `pure` functions. Use subroutines if your procedure needs to modify its arguments." %} - - -## Modules - -Fortran modules contain definitions that are made accessible to programs, procedures and other modules through the `use` statement. -They can contain data objects, type definitions, procedures and interfaces. - -- Modules allow controlled scoping extension whereby entity access is made explicit -- Modules automatically generate explicit interfaces required for modern procedures - -{% include tip.html content="It is recommended to always place functions and subroutines -within modules." %} - -__Example:__ - -```fortran -module my_mod - implicit none - - private ! All entities are module-private by default - public public_var, print_matrix ! Explicitly export public entities - - real, parameter :: public_var = 2 - integer :: private_var - - contains - - ! Print matrix A to screen - subroutine print_matrix(A) - real, intent(in) :: A(:,:) ! An assumed-shape dummy argument - - integer :: i - do i=1,size(A,1) - print *,A(i,:) - end do - - end subroutine print_matrix - -end module my_mod -``` - -{% include note.html content="Compare this `print_matrix` subroutine with [that written outside of a module](#subroutines); -we no longer have to explicitly pass the matrix dimensions and can instead take -advantage of _assumed-shape_ arguments since the module will generate the required -explicit interface for us. This results in a much simpler subroutine interface." %} - -To `use` the module within a program: -```fortran -program use_mod - use my_mod - implicit none - - real :: mat(10,10) - - mat(:,:) = public_var - - call print_matrix(mat) - -end program use_mod -``` - -__Example:__ explicit import list - -```fortran - use my_mod, only: public_var -``` - -__Example:__ aliased import - -```fortran - use my_mod, only: printMat=>print_matrix -``` - -{% include note.html content="Each module should be written in a separate .f90 source file. Modules need to be compiled prior to any program units that `use` them." %} +The contents of this tutoral are shown in the navigation bar on the left with the current page highlighted bold. +Use the _Next_ button at the bottom to start the tutorial with a _Hello World_ example. diff --git a/learn/quickstart/operators_control_flow.md b/learn/quickstart/operators_control_flow.md new file mode 100644 index 000000000..efdcb6702 --- /dev/null +++ b/learn/quickstart/operators_control_flow.md @@ -0,0 +1,138 @@ +--- +layout: book +title: Operators and Control Flow +permalink: /learn/quickstart/operators_control_flow +navbar: Learn +--- + +One of the powerful advantages of computer algorithms, compared to simple mathematical formulae, +comes in the form program _branching_ whereby the program can decide which instructions to +execute next based on a logical condition. + +There two main forms of controlling program flow: + +- _Conditional_ (if): choose program path based on a boolean (true or false) value + +- _Loop_: repeat a portion of code multiple times + + + +## Logical operators +Before we use a conditional branching operator, we need to be able to form +a logical expression. + +To form a logical expression the following set of relational operators are available: + +| Operator   | Alternative   | Description | +|:----------------:|:---------------------:|-----------------------------------------------------------------| +| `==` | `.eq.` | Tests for equality of two operands | +| `/=` | `.ne.` | Test for inequality of two operands | +| `> ` | `.gt.` | Tests if left operand is strictly greater than right operand | +| `< ` | `.lt.` | Tests if left operand is strictly less than right operand | +| `>=` | `.ge.` | Tests if left operand is greater than or equal to right operand | +| `<=` | `.le.` | Tests if left operand is less than or equal to right operand | + +
    + +as well as the following logical operators: + +| Operator   | Description | +|:---------------------:|----------------------------------------------------------------| +| `.and.` | TRUE if both left and right operands are TRUE | +| `.or.` | TRUE if either left or right or both operands are TRUE | +| `.not.` | TRUE if right operand is FALSE | +| `.eqv.` | TRUE if left operand has same logical value as right operand | +| `.neqv.` | TRUE if left operand has the opposite logical value as right operand | + +
    + + +## Conditional construct (`if`) + +In the following examples, a conditional `if` construct is used to print out a +message to describe the nature of the `angle` variable: + +__Example:__ single branch `if` + +```fortran + if (angle < 90.0) then + print *, 'Angle is acute' + end if +``` + +In this first example, the code within the `if` construct is __only executed if__ the +test expression (`angle < 90.0`) is true. + +{% include tip.html content="It is good practice to indent code within constructs such as `if` and `do` +to make code more readable." %} + +We can add alternative branch to the construct using the `else` keyword: + +__Example:__ two-branch `if-else` + +```fortran + if (angle < 90.0) then + print *, 'Angle is acute' + else + print *, 'Angle is obtuse' + end if +``` + +Now there are two _branches_ in the `if` construct, but __only one branch is executed__ depending +on the logical expression following the `if` keyword. + +We can actually add any number of branches using `else if` to specify more conditions: + +__Example:__ multi-branch `if-elseif-else` +```fortran + if (age < 90.0) then + print *, 'Angle is acute' + else if (angle < 180.0) then + print *, 'Angle is obtuse' + else + print *, 'Angle is reflex' + end if +``` + +When multiple conditional expressions are used, each conditional expression is tested only if none of the previous +expressions have evaluated to true. + +## Loop constructs (`do`) + +In the following example a `do` loop construct is used to print out the numbers in +a sequence. +The `do` loop has an integer _counter_ variable which is used to track which iteration of the loop +is currently executing, in this example we use a common name for this counter variable: `i`. + +When we define the start of the `do` loop we use our counter variable name followed by an equals (`=`) sign +to specify the start value and final value of our counting variable. + +__Example:__ `do` loop + +```fortran + integer :: i + do i=1,10 + print *, i + end do +``` + +__Example:__ `do` loop with skip + +```fortran + integer :: i + do i=1,10,2 + print *, i ! Print odd numbers + end do +``` + + +__Example:__ `do while` loop + +```fortran + integer :: i + i = 1 + do while (i<11) + print *, i + i = i + 1 + end do +``` \ No newline at end of file diff --git a/learn/quickstart/organising_code.md b/learn/quickstart/organising_code.md new file mode 100644 index 000000000..a603efb87 --- /dev/null +++ b/learn/quickstart/organising_code.md @@ -0,0 +1,178 @@ +--- +layout: book +title: Organising code structure +permalink: /learn/quickstart/organising_code +navbar: Learn +--- + +Most programming languages allow you to collect commonly-used code into +_procedures_ that can be reused by _calling_ them from other sections of code. + +Fortran has two forms of procedure: + +- __Subroutine:__ invoked by a `call` statement +- __Function:__ invoked within an expression or assignment to which it returns a value + +Both subroutines and functions have access to variables in the parent scope by _argument association_; +unless the `VALUE` attribute is specified, this is similar to call by reference. + +## Subroutines + +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. + +__Example:__ + +```fortran +! Print matrix A to screen +subroutine print_matrix(n,m,A) + implicit none + integer, intent(in) :: n + integer, intent(in) :: m + real, intent(in) :: A(n,m) + + integer :: i + do i=1,n + print *,A(i,1:m) + end do + +end subroutine print_matrix +``` + + +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)`) '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)`. + +{% include tip.html content="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." %} + + +We can call this subroutine from a program using a `call` statement: +```fortran +program call_sub + implicit none + + real :: mat(10,20) + + mat(:,:) = 0.0 + + call print_matrix(10,20,mat) + +end program call_sub +``` + +{% include note.html content="This example uses a so-called _explicit-shape_ array argument since we have passed additional variables to describe +the dimensions of the array `A`; this will not be necessary if we place our subroutine in a module as described later." %} + + +## Functions + +```fortran +! L2 Norm of a vector +function vector_norm(n,vec) result(norm) + implicit none + integer, intent(in) :: n + real, intent(in) :: vec(n) + real :: norm + + norm = sqrt(sum(vec**2)) + +end function vector_norm +``` + +To execute this function: + +```fortran +program run_fcn + implicit none + + real :: v(9) + real :: vector_norm + + v(:) = 9 + + print *, 'Vector norm = ',vector_norm(9,v) + +end program run_fcn +``` + +{% include tip.html content="It is good programming practice for functions not to modify their arguments - _i.e._ all function arguments should be `intent(in)` - such +functions are known as `pure` functions. Use subroutines if your procedure needs to modify its arguments." %} + + +## Modules + +Fortran modules contain definitions that are made accessible to programs, procedures and other modules through the `use` statement. +They can contain data objects, type definitions, procedures and interfaces. + +- Modules allow controlled scoping extension whereby entity access is made explicit +- Modules automatically generate explicit interfaces required for modern procedures + +{% include tip.html content="It is recommended to always place functions and subroutines +within modules." %} + +__Example:__ + +```fortran +module my_mod + implicit none + + private ! All entities are module-private by default + public public_var, print_matrix ! Explicitly export public entities + + real, parameter :: public_var = 2 + integer :: private_var + + contains + + ! Print matrix A to screen + subroutine print_matrix(A) + real, intent(in) :: A(:,:) ! An assumed-shape dummy argument + + integer :: i + do i=1,size(A,1) + print *,A(i,:) + end do + + end subroutine print_matrix + +end module my_mod +``` + +{% include note.html content="Compare this `print_matrix` subroutine with [that written outside of a module](#subroutines); +we no longer have to explicitly pass the matrix dimensions and can instead take +advantage of _assumed-shape_ arguments since the module will generate the required +explicit interface for us. This results in a much simpler subroutine interface." %} + +To `use` the module within a program: +```fortran +program use_mod + use my_mod + implicit none + + real :: mat(10,10) + + mat(:,:) = public_var + + call print_matrix(mat) + +end program use_mod +``` + +__Example:__ explicit import list + +```fortran + use my_mod, only: public_var +``` + +__Example:__ aliased import + +```fortran + use my_mod, only: printMat=>print_matrix +``` + +{% include note.html content="Each module should be written in a separate .f90 source file. Modules need to be compiled prior to any program units that `use` them." %} + + + diff --git a/learn/quickstart/variables.md b/learn/quickstart/variables.md new file mode 100644 index 000000000..da8305cd7 --- /dev/null +++ b/learn/quickstart/variables.md @@ -0,0 +1,206 @@ +--- +layout: book +title: Variables +permalink: /learn/quickstart/variables +navbar: Learn +--- + +Variables store information that can be manipulated by the program. +Fortran is a '_strongly typed_' language, which means that each variable +must have a type. + +There are 5 built-in data types in Fortran: + +* `integer` -- for data that represent whole numbers, positive or negative +* `real` -- for floating-point data (not a whole number) +* `complex` -- pair consisting of a real part and an imaginary part +* `character` -- for text data +* `logical` -- for data that represent boolean (true or false) values + +Before we can use a variable, we must _declare_ it; this tells the compiler +the variable type and any other variable attributes. + +{% include note.html content="Fortran is a statically typed language which means the type of each +variable is fixed when the program is compiled - variable types cannot change while the program is running." %} + +## Declaring variables + +The syntax for declaring variables is: + +```fortran + :: +``` + +where `` is one of the built-in variable types listed above and +`` is the name that you would like to call your variable. + +Variable names must start with a letter and can consist of letters, numbers and underscores. +In the following example we declare a variable for each of the built-in types. + +__Example:__ variable declaration + +```fortran +program variables + implicit none + + integer :: amount + real :: pi + complex :: frequency + character :: initial + logical :: isOkay + +end program variables +``` + +{% include note.html content="Fortran code is __case-insensitive__; you don't have to worry about the +capitalisation of your variable names but it's good practice to keep it consistent." %} + +Note the additional statement at the beginning of the program: `implicit none`. +This statement tells the compiler that all variables will be explicitly declared; without +this statement variables will be implicitly typed according to the letter they begin with. + +{% include important.html content="Always use the `implicit none` statement at +the beginning of each program and procedure. Implicit typing is considered bad practice in +modern programming since it hides information leading to more program errors." %} + + +Once we have declared a variable, we can assign and reassign values to it using the assignment operator `=`. + +__Example:__ variable assignment + +```fortran + amount = 10 + pi = 4.141592 + frequency = (1.0,-0.5) + initial = 'A' + isOkay = .false. +``` + +Characters are surrounded by either single (`'`) or double quotes (`"`). + +Logical or boolean values can be either `.true.` or `.false.`. + +{% include important.html title="Watch out" content="for assignment at declaration: `integer :: amount = 1`. +__This is NOT a normal initialisation;__ it implies the `save` attribute which means that the variable retains +its value between procedure calls. Good practice is to initialise your variables separately to their declaration." %} + + +## Standard input / output + +In our _Hello World_ example, we printed text to the command window. +This is commonly referred to as writing to `standard output` or `stdout`. + +We can use the `print` statement introduced earlier to print variable values to `stdout`: + +```fortran + print *, 'The value of amount (integer) is: ',amount + print *, 'The value of pi (real) is: ',pi + print *, 'The value of frequency (complex) is: ',frequency + print *, 'The value of initial (character) is: ',initial + print *, 'The value of isOkay (logical) is: ',isOkay +``` + +In a similar way, we can read values from the command window +using the `read` statement: + +```fortran +program read_value + implicit none + integer :: age + + print *, 'Please enter your age: ' + read(*,*) age + + print *, 'Your age is: ',age + +end program read_value +``` + +This input source is commonly referred to as `standard input` or `stdin`. + + +## Expressions +The usual set of arithmetic operators are available, listed in order or precedence: + +| Operator   | Description | +|:----------------:|----------------| +| `**` | Exponent | +| `*` | Multiplication | +| `/ ` | Division | +| `+` | Addition | +| `-` | Subtraction | + +
    + +__Example:__ + +```fortran +program arithmetic + implicit none + + real :: pi + real :: radius + real :: height + real :: area + real :: volume + + pi = 3.141592 + + print *, 'Enter cylinder base radius:' + read(*,*) radius + + print *, 'Enter cylinder height:' + read(*,*) height + + area = pi*radius**2.0 + volume = area*height + + print *, 'Cylinder radius is: ',radius + print *, 'Cylinder height is: ',height + print *, 'Cylinder base area is: ',area + print *, 'Cylinder volume is: ',volume + +end program arithmetic +``` + + + + + + +## Floating-point precision + +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 32bit and 64bit floating point types. + +__Example:__ explicit real kind +```fortran +program float + use, intrinsic :: iso_fortran_env, only: sp=>real32, dp=>real64 + implicit none + + real(sp) :: float32 + real(dp) :: float64 + + float32 = 1.0_sp ! Explicit suffix for literal constants + float64 = 1.0_dp + +end program float +``` + +{% include important.html content="Always use a `kind` suffix for floating point literal constants." %} + +__Example:__ c-interoperable kinds +```fortran +program float + use, intrinsic :: iso_c_binding, only: sp=>c_float, dp=>c_double + implicit none + + real(sp) :: float32 + real(dp) :: float64 + +end program float +``` + +In the next part we will learn how to use arrays for storing more than one +value in a variable. \ No newline at end of file From e537fd0a14d4c41b0e74df0a87c181bcc87f8d14 Mon Sep 17 00:00:00 2001 From: LKedward Date: Sat, 30 May 2020 16:32:50 +0100 Subject: [PATCH 4/9] Minor update: always highlight Learn in book layout. This simplifies the jekyll headers in the mini-books. --- _layouts/book.html | 2 +- learn/quickstart/arrays_strings.md | 1 - learn/quickstart/hello_world.md | 1 - learn/quickstart/index.md | 1 - learn/quickstart/operators_control_flow.md | 1 - learn/quickstart/organising_code.md | 1 - learn/quickstart/variables.md | 1 - 7 files changed, 1 insertion(+), 7 deletions(-) diff --git a/_layouts/book.html b/_layouts/book.html index 76b2b642d..f8c97456c 100644 --- a/_layouts/book.html +++ b/_layouts/book.html @@ -2,7 +2,7 @@ layout: default --- -{% include nav.html active=page.navbar %} +{% include nav.html active="Learn" %}
    diff --git a/learn/quickstart/arrays_strings.md b/learn/quickstart/arrays_strings.md index a13bc966c..656ac5e85 100644 --- a/learn/quickstart/arrays_strings.md +++ b/learn/quickstart/arrays_strings.md @@ -2,7 +2,6 @@ layout: book title: Arrays and strings permalink: /learn/quickstart/arrays_strings -navbar: Learn --- diff --git a/learn/quickstart/hello_world.md b/learn/quickstart/hello_world.md index 4fb5e0388..8ca5c98cd 100644 --- a/learn/quickstart/hello_world.md +++ b/learn/quickstart/hello_world.md @@ -2,7 +2,6 @@ layout: book title: Hello World permalink: /learn/quickstart/hello_world -navbar: Learn --- In this part of the tutorial, we will write our first Fortran program: diff --git a/learn/quickstart/index.md b/learn/quickstart/index.md index 6bb573b0c..44ed18143 100644 --- a/learn/quickstart/index.md +++ b/learn/quickstart/index.md @@ -2,7 +2,6 @@ layout: book title: Quickstart tutorial permalink: /learn/quickstart -navbar: Learn --- This quickstart tutorial gives an overview of the Fortran programming language diff --git a/learn/quickstart/operators_control_flow.md b/learn/quickstart/operators_control_flow.md index efdcb6702..87a9e6ada 100644 --- a/learn/quickstart/operators_control_flow.md +++ b/learn/quickstart/operators_control_flow.md @@ -2,7 +2,6 @@ layout: book title: Operators and Control Flow permalink: /learn/quickstart/operators_control_flow -navbar: Learn --- One of the powerful advantages of computer algorithms, compared to simple mathematical formulae, diff --git a/learn/quickstart/organising_code.md b/learn/quickstart/organising_code.md index a603efb87..68998bbca 100644 --- a/learn/quickstart/organising_code.md +++ b/learn/quickstart/organising_code.md @@ -2,7 +2,6 @@ layout: book title: Organising code structure permalink: /learn/quickstart/organising_code -navbar: Learn --- Most programming languages allow you to collect commonly-used code into diff --git a/learn/quickstart/variables.md b/learn/quickstart/variables.md index da8305cd7..fd4d35dc4 100644 --- a/learn/quickstart/variables.md +++ b/learn/quickstart/variables.md @@ -2,7 +2,6 @@ layout: book title: Variables permalink: /learn/quickstart/variables -navbar: Learn --- Variables store information that can be manipulated by the program. From 006e8584372e26986171ed2dbfa6d2c042484b17 Mon Sep 17 00:00:00 2001 From: LKedward Date: Sat, 30 May 2020 17:17:08 +0100 Subject: [PATCH 5/9] Add: link to J3 Fortran Proposals repo. --- _data/learning.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/_data/learning.yml b/_data/learning.yml index b61d2085e..188f14db2 100644 --- a/_data/learning.yml +++ b/_data/learning.yml @@ -40,6 +40,10 @@ reference-links: url: https://j3-fortran.org/doc/year/18/18-007r1.pdf description: "J3/18-007r1 F2018, specification of the base Fortran 2018 language" + - name: "J3 Fortran Proposals" + url: https://github.com/j3-fortran/fortran_proposals + description: a repository for community collaboration on proposals for the Fortran Standards Committee + - name: "J3: US Fortran Standards Committee" url: https://j3-fortran.org/ description: J3 is the US National Body for the international Fortran standards committee From 3441dccaf484b7de9e6e088b14e702faf4e73095 Mon Sep 17 00:00:00 2001 From: Laurence Kedward Date: Sat, 30 May 2020 20:18:33 +0100 Subject: [PATCH 6/9] Update _data/learning.yml Co-authored-by: Milan Curcic --- _data/learning.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/_data/learning.yml b/_data/learning.yml index 188f14db2..a7c423ade 100644 --- a/_data/learning.yml +++ b/_data/learning.yml @@ -71,11 +71,12 @@ reference-books: publisher: Oxford Universtiy Press - author: Curcic, M. - year: 2019 - title: "Modern Fortran: Building efficient parallel programs" + year: 2020 + title: "Modern Fortran: Building Efficient Parallel Applications" url: https://www.manning.com/books/modern-fortran edition: 1st ed - publisher: Manning publications + location: Shelter Island, NY + publisher: Manning Publications - author: Chivers, I. and Sleightholme, J. year: 2018 @@ -90,4 +91,4 @@ reference-books: url: https://www.mheducation.com/highered/product/fortran-scientists-engineers-chapman/M9780073385891.html edition: 4th ed location: New York - publisher: McGraw-Hill Education \ No newline at end of file + publisher: McGraw-Hill Education From fc92089f19c9b6feb03631fd441d99b20fa9ec9f Mon Sep 17 00:00:00 2001 From: Laurence Kedward Date: Sat, 30 May 2020 20:18:40 +0100 Subject: [PATCH 7/9] Update _data/learning.yml Co-authored-by: Milan Curcic --- _data/learning.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_data/learning.yml b/_data/learning.yml index a7c423ade..ad303b447 100644 --- a/_data/learning.yml +++ b/_data/learning.yml @@ -62,7 +62,7 @@ reference-links: # Print books listed at the bottom of the 'Learn' landing page # reference-books: - - author: Michael Metcalf, John Reid, and Malcolm Cohen + - author: Metcalf, M., Reid, J. and Cohen M. year: 2018 title: Modern Fortran Explained url: https://global.oup.com/academic/product/modern-fortran-explained-9780198811893 From 893aa9049bc709b2efc32471c432c9b8e95e1417 Mon Sep 17 00:00:00 2001 From: Laurence Kedward Date: Sat, 30 May 2020 20:18:53 +0100 Subject: [PATCH 8/9] Update _data/learning.yml Co-authored-by: Milan Curcic --- _data/learning.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/_data/learning.yml b/_data/learning.yml index ad303b447..43c2a2f50 100644 --- a/_data/learning.yml +++ b/_data/learning.yml @@ -78,6 +78,14 @@ reference-books: location: Shelter Island, NY publisher: Manning Publications + - author: Markus, A. + year: 2012 + title: "Modern Fortran in Practice" + url: https://www.cambridge.org/core/books/modern-fortran-in-practice/BC5BD23B2E478B4D457C5D6265BA9363 + edition: 1st ed + location: Cambridge, UK + publisher: Cambridge University Press + - author: Chivers, I. and Sleightholme, J. year: 2018 title: Introduction to Programming with Fortran From 28594972f958eab3edce065f3d384e3033132572 Mon Sep 17 00:00:00 2001 From: LKedward Date: Sat, 30 May 2020 20:29:00 +0100 Subject: [PATCH 9/9] Update: sort ref books by year descending. --- learn/index.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/learn/index.html b/learn/index.html index 71764f391..d0efdb61e 100644 --- a/learn/index.html +++ b/learn/index.html @@ -104,7 +104,8 @@

    On the web

    In print

      - {% for refBook in site.data.learning.reference-books %} + {% assign refBooks = site.data.learning.reference-books | sort: "year" | reverse %} + {% for refBook in refBooks %}
    • {{ refBook.author }}. {{ refBook.year }}.