Difference between revisions of "Modern Fortran"

From oldwiki.scinet.utoronto.ca
Jump to navigation Jump to search
m
Line 1: Line 1:
=Modern Fortran for FORTRAN77 users=
+
'''Modern Fortran for FORTRAN77 users'''
Jonathan Dursi
 
  
 +
''Jonathan Dursi''
  
==Course Overview==
+
This is the Wiki-fied version of the [[Media:ModernFortran.pdf | slides]] used for the Modern Fortran course at SciNet.  To follow along, with both the examples and the hands on, you will want to download the [[Media:ModernFortran.tgz | source code]] and make sure you have a working Fortran 2003 compiler.
 +
 
 +
__NOTOC__
 +
 
 +
=Course Overview=
  
 
{|
 
{|
 
|
 
|
* Intro, History (10 min)
+
* [[#A Brief History of Fortran|Intro, History]] (10 min)
 
* New syntax (30 min), Hands on #1(60 min)
 
* New syntax (30 min), Hands on #1(60 min)
 
* Functions, Modules (45 min), Hands on #2 (30 min)
 
* Functions, Modules (45 min), Hands on #2 (30 min)
Line 18: Line 22:
 
|}
 
|}
  
__NOTOC__
+
=A Brief History of Fortran=
 
 
==A Brief History of Fortran==
 
 
{|
 
{|
 
|
 
|
Line 37: Line 39:
 
|}
 
|}
  
===FORTRAN (1957)===
+
==FORTRAN (1957)==
 
{|
 
{|
 
|
 
|
Line 56: Line 58:
  
  
===Incremental changes===
+
==Incremental changes==
 
{|
 
{|
 
|
 
|
Line 66: Line 68:
  
  
===FORTRAN66===
+
==FORTRAN66==
 
{|
 
{|
 
|
 
|
Line 75: Line 77:
 
|}
 
|}
  
===FORTRAN77===
+
==FORTRAN77==
 
{|
 
{|
 
* The most common to see “in the wild” of old code today
 
* The most common to see “in the wild” of old code today
Line 83: Line 85:
 
|}
 
|}
  
===The interregnum===
+
==The interregnum==
 
{|
 
{|
 
* Programming languages and techniques were moving quite quickly
 
* Programming languages and techniques were moving quite quickly
Line 91: Line 93:
 
|}
 
|}
  
===Fortran90===
+
==Fortran90==
 
{|
 
{|
 
* Enormous changes; the basis of modern Fortran (not FORTRAN!)
 
* Enormous changes; the basis of modern Fortran (not FORTRAN!)
Line 99: Line 101:
 
|}
 
|}
  
===And since...===
+
==And since...==
 
{|
 
{|
 
* Fortran95 - modest changes to Fortran90, killed off some deprecated F77 constructs.
 
* Fortran95 - modest changes to Fortran90, killed off some deprecated F77 constructs.
Line 106: Line 108:
 
|}
 
|}
  
===F90, F95, F2003, F2008..===
+
==F90, F95, F2003, F2008..==
 
{|
 
{|
 
* We won’t distinguish between versions; we’ll just show you a lot of useful features of modern fortran.
 
* We won’t distinguish between versions; we’ll just show you a lot of useful features of modern fortran.
Line 112: Line 114:
 
|}
 
|}
  
==New Format, New Syntax==
+
=New Format, New Syntax=
 
{|
 
{|
 
|}
 
|}
  
===Free Format: some highlights===
+
==Free Format: some highlights==
 
{|
 
{|
 
|
 
|
Line 127: Line 129:
 
* <, > vs .lt., .gt.
 
* <, > vs .lt., .gt.
 
* <=, >=  vs .le., .ge.
 
* <=, >=  vs .le., .ge.
* ===, /= vs .eq., .neq.
+
* ==, /= vs .eq., .neq.
 
* Program, procedure can contain other procedures
 
* Program, procedure can contain other procedures
 
* “program x” or “function y” ended by “end program x” or “end function y”
 
* “program x” or “function y” ended by “end program x” or “end function y”
Line 140: Line 142:
 
|}
 
|}
  
===Variable Declarations===
+
==Variable Declarations==
 
{|
 
{|
 
* Implicit none turns off all implicit typing.
 
* Implicit none turns off all implicit typing.
Line 150: Line 152:
 
|}
 
|}
  
===Variable Declarations===
+
==Variable Declarations==
 
{|
 
{|
 
* The “::” separating type and name is new
 
* The “::” separating type and name is new
Line 158: Line 160:
 
|}
 
|}
  
===Variable Declarations===
+
==Variable Declarations==
 
{|
 
{|
 
* Parameter attribute for values which will be constants.
 
* Parameter attribute for values which will be constants.
Line 168: Line 170:
 
|}
 
|}
  
===Variable Declarations===
+
==Variable Declarations==
 
* Initialization of variables at declaration time
 
* Initialization of variables at declaration time
 
* Required for parameters (because can’t change them later), can be done for other variables.
 
* Required for parameters (because can’t change them later), can be done for other variables.
 
* Can do anything that compiler can figure out at compile time, including math with other parameters.
 
* Can do anything that compiler can figure out at compile time, including math with other parameters.
  
===Variable Declarations===
+
==Variable Declarations==
 
* Initializing variables this way gives unexpected behaviour in functions/subroutines “for historical reasons”.
 
* Initializing variables this way gives unexpected behaviour in functions/subroutines “for historical reasons”.
 
* Initialized variables given the “save” attribute
 
* Initialized variables given the “save” attribute
Line 183: Line 185:
 
samples/variables/initialization/initialization.f90
 
samples/variables/initialization/initialization.f90
  
===Real Kinds===
+
==Real Kinds==
 
* Reals, Double precisions, really different “kinds” of same “type” - floating pt real #s.
 
* Reals, Double precisions, really different “kinds” of same “type” - floating pt real #s.
 
* Kinds introduced to give enhanced version of functionality of non-standard but ubiquitous constructs like REAL*8
 
* Kinds introduced to give enhanced version of functionality of non-standard but ubiquitous constructs like REAL*8
Line 197: Line 199:
 
samples/variables/kinds/realkinds.f90
 
samples/variables/kinds/realkinds.f90
  
===Integer Kinds===
+
==Integer Kinds==
 
* Similar constructs for integers
 
* Similar constructs for integers
 
* selected int kind(N): kind can represent all N-digit decimal numbers.
 
* selected int kind(N): kind can represent all N-digit decimal numbers.
 
* huge(N): largest positive number of that type samples/variables/kinds/intkinds.f90
 
* huge(N): largest positive number of that type samples/variables/kinds/intkinds.f90
  
===Strings===
+
==Strings==
  
 
* Character types are usually used for strings
 
* Character types are usually used for strings
Line 208: Line 210:
 
* Padded by blanks
 
* Padded by blanks
 
* Intrinsic trim() gets rid of blanks at end
 
* Intrinsic trim() gets rid of blanks at end
* Can compare strings with <,>,===, etc.
+
* Can compare strings with <,>,==, etc.
 
* Concatenate with //
 
* Concatenate with //
 
* Characters have kinds too
 
* Characters have kinds too
 
* gfortran has partial support for selected_char_kind(“ISO_10646”) for unicode strings.
 
* gfortran has partial support for selected_char_kind(“ISO_10646”) for unicode strings.
  
===Array declarations===
+
==Array declarations==
 
* Array declarations have changed, too:
 
* Array declarations have changed, too:
 
* dimension is now an attribute
 
* dimension is now an attribute
 
* Can easily declare several arrays with same dimension
 
* Can easily declare several arrays with same dimension
  
===Do loops===
+
==Do loops==
 
* Do loops syntax has had some changes
 
* Do loops syntax has had some changes
 
* do/enddo - was a common extension, now standard.
 
* do/enddo - was a common extension, now standard.
Line 224: Line 226:
 
samples/variables/doloops/doi.f90
 
samples/variables/doloops/doi.f90
  
===Do loops===
+
==Do loops==
 
* All constructs now have end constructname to end.
 
* All constructs now have end constructname to end.
 
* Named constructs (program, subroutine) require, eg, end program doi.
 
* Named constructs (program, subroutine) require, eg, end program doi.
 
* Helps catch various simple errors (mismatched ends, etc.)
 
* Helps catch various simple errors (mismatched ends, etc.)
  
===Do loops===
+
==Do loops==
  
 
* Can name control structures like do, if statements now, too.
 
* Can name control structures like do, if statements now, too.
Line 238: Line 240:
 
samples/variables/doloops/nameddo.f90
 
samples/variables/doloops/nameddo.f90
  
===Do loops===
+
==Do loops==
 
{|
 
{|
 
|
 
|
Line 251: Line 253:
 
|}
 
|}
  
===Cycle/exit===
+
==Cycle/exit==
  
 
samples/variables/doloops/cycleexit.f90
 
samples/variables/doloops/cycleexit.f90
  
===Do while===
+
==Do while==
 
* do while - repeats as
 
* do while - repeats as
 
long as precondition is
 
long as precondition is
Line 267: Line 269:
 
samples/variables/doloops/dowhile.f90
 
samples/variables/doloops/dowhile.f90
  
===Hands on #1===
+
==Hands on #1==
 
* In workedexample/f77 is a simplified, F77ized version of a fluid-dynamics code from UeLi Pen, CITA, U of Toronto (http://
 
* In workedexample/f77 is a simplified, F77ized version of a fluid-dynamics code from UeLi Pen, CITA, U of Toronto (http://
 
www.cita.utoronto.ca/~pen/MHD/)
 
www.cita.utoronto.ca/~pen/MHD/)
Line 275: Line 277:
 
then compile (using make) and run (./hydro)
 
then compile (using make) and run (./hydro)
  
===Hands on #1===
+
==Hands on #1==
 
* Outputs a .pbm file;
 
* Outputs a .pbm file;
 
use “display
 
use “display
Line 284: Line 286:
 
medium.
 
medium.
  
===Hands on #1===
+
==Hands on #1==
 
* In workedexamples/freeform, have partly
 
* In workedexamples/freeform, have partly
 
converted the program to new freeform
 
converted the program to new freeform
Line 297: Line 299:
 
working)
 
working)
  
===Procedures and===
+
==Procedures and==
 
modules
 
modules
 
* Several enhancements to how procedures
 
* Several enhancements to how procedures
Line 305: Line 307:
 
maintenance, clarity
 
maintenance, clarity
  
===Modules===
+
==Modules==
  
 
* Easiest to show by
 
* Easiest to show by
Line 321: Line 323:
 
samples/procedures/simplemod/simplemod.f90
 
samples/procedures/simplemod/simplemod.f90
  
===Compiling & Running===
+
==Compiling & Running==
 
* When compiling the code
 
* When compiling the code
 
a gravity.mod file is
 
a gravity.mod file is
Line 333: Line 335:
 
versions.
 
versions.
  
===Modules===
+
==Modules==
 
* function gravforce can
 
* function gravforce can
 
“see” the modulewide parameter
 
“see” the modulewide parameter
Line 343: Line 345:
 
samples/procedures/simplemod/simplemod.f90
 
samples/procedures/simplemod/simplemod.f90
  
===use module, only :===
+
==use module, only :==
 
* Best practice is to only
 
* Best practice is to only
 
pull in from the
 
pull in from the
Line 356: Line 358:
 
samples/procedures/simplemod/simplemod2.f90
 
samples/procedures/simplemod/simplemod2.f90
  
===Modules usually get their own files===
+
==Modules usually get their own files==
 
* For encapsulation
 
* For encapsulation
 
* For ease of re-use
 
* For ease of re-use
Line 368: Line 370:
 
samples/procedures/multifilemod/gravity.f90
 
samples/procedures/multifilemod/gravity.f90
  
===Modules usually get their own files===
+
==Modules usually get their own files==
 
* Compiling gravity.f90
 
* Compiling gravity.f90
 
now gives both an .o
 
now gives both an .o
Line 381: Line 383:
 
samples/procedures/multifilemod/Makefile
 
samples/procedures/multifilemod/Makefile
  
===.mod needed for compilation===
+
==.mod needed for compilation==
 
* ...because needs the
 
* ...because needs the
 
type information of
 
type information of
Line 394: Line 396:
 
samples/procedures/multifilemod/multifilemod.f90
 
samples/procedures/multifilemod/multifilemod.f90
  
===.o needed for linking===
+
==.o needed for linking==
 
* Linking, however,
 
* Linking, however,
 
doesn’t require
 
doesn’t require
Line 407: Line 409:
 
samples/procedures/multifilemod/Makefile
 
samples/procedures/multifilemod/Makefile
  
===Compiling and running===
+
==Compiling and running==
  
 
* So compile files with modules first, so
 
* So compile files with modules first, so
Line 413: Line 415:
 
* Link the .o files
 
* Link the .o files
  
===Private and public===
+
==Private and public==
 
* Not all of a module’s
 
* Not all of a module’s
 
content need be public
 
content need be public
Line 426: Line 428:
 
samples/procedures/multifilemod/gravity.f90
 
samples/procedures/multifilemod/gravity.f90
  
===Procedures===
+
==Procedures==
 
* We’ve already seen
 
* We’ve already seen
 
procedures defined in
 
procedures defined in
Line 438: Line 440:
 
samples/procedures/funcsub/procedures.f90
 
samples/procedures/funcsub/procedures.f90
  
===Procedures===
+
==Procedures==
 
* Again, make expectations
 
* Again, make expectations
 
more explicit, compiler can
 
more explicit, compiler can
Line 453: Line 455:
 
samples/procedures/funcsub/procedures.f90
 
samples/procedures/funcsub/procedures.f90
  
===Functions===
+
==Functions==
 
* Can be typed a couple of ways.
 
* Can be typed a couple of ways.
 
* Old-style still works (real
 
* Old-style still works (real
Line 469: Line 471:
 
samples/procedures/funcsub/procedures.f90
 
samples/procedures/funcsub/procedures.f90
  
===Procedure interfaces===
+
==Procedure interfaces==
 
* The interface to a procedure
 
* The interface to a procedure
 
consists of
 
consists of
Line 485: Line 487:
 
procedures.
 
procedures.
  
===Procedure interfaces===
+
==Procedure interfaces==
 
* To see where interfaces
 
* To see where interfaces
 
become necessary, consider
 
become necessary, consider
Line 501: Line 503:
 
File:Trapezoidal_rule_illustration_small.svg
 
File:Trapezoidal_rule_illustration_small.svg
  
===Procedure interfaces===
+
==Procedure interfaces==
 
* Define f as a parameter, give its
 
* Define f as a parameter, give its
 
type via an interface.
 
type via an interface.
Line 511: Line 513:
 
integrate.f90
 
integrate.f90
  
===Recursive procedures===
+
==Recursive procedures==
 
* By default, Fortran procedures
 
* By default, Fortran procedures
 
cannot call themselves
 
cannot call themselves
Line 525: Line 527:
 
samples/procedures/recursive/integrate.f90
 
samples/procedures/recursive/integrate.f90
  
===Pure procedures===
+
==Pure procedures==
 
* Procedures are pure or
 
* Procedures are pure or
 
impure depending on
 
impure depending on
Line 538: Line 540:
 
samples/procedures/purity/purity.f90
 
samples/procedures/purity/purity.f90
  
===Pure procedures===
+
==Pure procedures==
 
* Optimizations can be made
 
* Optimizations can be made
 
for pure routines which
 
for pure routines which
Line 548: Line 550:
 
samples/procedures/purity/purity.f90
 
samples/procedures/purity/purity.f90
  
===Optional Arguments===
+
==Optional Arguments==
 
* Can make
 
* Can make
 
arguments optional
 
arguments optional
Line 559: Line 561:
 
samples/procedures/optional/integrate.f90
 
samples/procedures/optional/integrate.f90
  
===Optional Arguments===
+
==Optional Arguments==
 
* When calling the
 
* When calling the
 
procedure, can use
 
procedure, can use
Line 572: Line 574:
 
samples/procedures/optional/optional.f90
 
samples/procedures/optional/optional.f90
  
===Keyword Arguments===
+
==Keyword Arguments==
 
* To avoid ambiguity with
 
* To avoid ambiguity with
 
omitted arguments - or
 
omitted arguments - or
Line 587: Line 589:
 
samples/procedures/optional/optional.f90
 
samples/procedures/optional/optional.f90
  
===Procedures & Modules===
+
==Procedures & Modules==
 
Summary
 
Summary
 
* Modules let you bundle procedures, constants
 
* Modules let you bundle procedures, constants
Line 598: Line 600:
 
program).
 
program).
  
===Procedures & Modules===
+
==Procedures & Modules==
 
Summary
 
Summary
 
* New syntax for functions/subroutines: intent
 
* New syntax for functions/subroutines: intent
Line 609: Line 611:
 
* Pure/recursive procedures
 
* Pure/recursive procedures
  
===Hands on #2===
+
==Hands on #2==
 
* In workedexamples/modules, have have
 
* In workedexamples/modules, have have
 
pulled the PBM stuff out into a module.
 
pulled the PBM stuff out into a module.
Line 618: Line 620:
 
* ~30 min
 
* ~30 min
  
===Fortran arrays===
+
==Fortran arrays==
 
* Fortran made for dealing with scientific data
 
* Fortran made for dealing with scientific data
 
* Arrays built into language
 
* Arrays built into language
Line 627: Line 629:
 
programmer-friendly features.
 
programmer-friendly features.
  
===Fortran arrays===
+
==Fortran arrays==
 
* Can be manipulated
 
* Can be manipulated
 
like simple scalar
 
like simple scalar
Line 636: Line 638:
 
samples/arrays/basic.f90
 
samples/arrays/basic.f90
  
===Array constructors===
+
==Array constructors==
 
* Can have array
 
* Can have array
 
constants like
 
constants like
Line 653: Line 655:
 
[ ((i*j,j=1,3),i=1,5)]
 
[ ((i*j,j=1,3),i=1,5)]
  
===Elementwise operations===
+
==Elementwise operations==
 
* Elementwise operations
 
* Elementwise operations
 
can be */+-, or
 
can be */+-, or
Line 669: Line 671:
 
samples/arrays/elementwise.f90
 
samples/arrays/elementwise.f90
  
===Elemental Functions===
+
==Elemental Functions==
 
* User can create their
 
* User can create their
 
own elemental functions
 
own elemental functions
Line 684: Line 686:
 
samples/arrays/elemental.f90
 
samples/arrays/elemental.f90
  
===Array comparisons===
+
==Array comparisons==
 
* Array comparisons
 
* Array comparisons
 
return an array of
 
return an array of
Line 694: Line 696:
 
samples/arrays/compare.f90
 
samples/arrays/compare.f90
  
===Array masks===
+
==Array masks==
 
* These logical arrays can
 
* These logical arrays can
 
be used to mask several
 
be used to mask several
Line 707: Line 709:
 
samples/arrays/mask.f90
 
samples/arrays/mask.f90
  
===Where construct===
+
==Where construct==
 
* The where construct
 
* The where construct
 
can be used to easily
 
can be used to easily
Line 722: Line 724:
 
samples/arrays/where.f90
 
samples/arrays/where.f90
  
===Forall construct===
+
==Forall construct==
 
* Forall is an array
 
* Forall is an array
 
assignment statement
 
assignment statement
Line 739: Line 741:
 
samples/arrays/forall.f90
 
samples/arrays/forall.f90
  
===Array Sections===
+
==Array Sections==
 
* Generalization of array
 
* Generalization of array
 
indexing
 
indexing
Line 755: Line 757:
 
a([start]:[end][:step])
 
a([start]:[end][:step])
 
a = [1,2,3,4,5,6,7,8,9,10]
 
a = [1,2,3,4,5,6,7,8,9,10]
a(7:) === [7,8,9,10]
+
a(7:) == [7,8,9,10]
a(:3) === [1,2,3]
+
a(:3) == [1,2,3]
a(2:4) === [2,3,4]
+
a(2:4) == [2,3,4]
a(::3) === [1,4,7,10]
+
a(::3) == [1,4,7,10]
a(2:4:2) === [2,4]
+
a(2:4:2) == [2,4]
a(2) === 2
+
a(2) == 2
a(:) === [1,2,3,4,5,6,7,8,9,10]
+
a(:) == [1,2,3,4,5,6,7,8,9,10]
  
===Array Sections===
+
==Array Sections==
 
* This sort of thing is very
 
* This sort of thing is very
 
handy in numerical
 
handy in numerical
Line 776: Line 778:
 
samples/arrays/derivative.f90
 
samples/arrays/derivative.f90
  
===Array Sections===
+
==Array Sections==
 
* The previous sorts of array
 
* The previous sorts of array
 
sections - shifting things leftward
 
sections - shifting things leftward
Line 792: Line 794:
  
 
a = [1,2,3,4,5]
 
a = [1,2,3,4,5]
cshift(a,1) === [2,3,4,5,1]
+
cshift(a,1) == [2,3,4,5,1]
cshift(a,-1) === [5,1,2,3,4]
+
cshift(a,-1) == [5,1,2,3,4]
eoshift(a,1) ===[2,3,4,5,0]
+
eoshift(a,1) ==[2,3,4,5,0]
eoshift(a,-1)===[0,1,2,3,4]
+
eoshift(a,-1)==[0,1,2,3,4]
  
===Other important array===
+
==Other important array==
 
intrinsics
 
intrinsics
 
* minval/maxval - finds min, max element in an array.
 
* minval/maxval - finds min, max element in an array.
Line 804: Line 806:
 
* reshape - Adjusts shape of array data. Eg:
 
* reshape - Adjusts shape of array data. Eg:
 
1,4
 
1,4
reshape([1,2,3,4,5,6],[3,2]) === 2,5
+
reshape([1,2,3,4,5,6],[3,2]) == 2,5
 
3,6
 
3,6
  
===Linear algebra in Fortran===
+
==Linear algebra in Fortran==
 
* Comes built in with transpose, matmul,
 
* Comes built in with transpose, matmul,
 
dot_product for dealing with arrays.
 
dot_product for dealing with arrays.
Line 814: Line 816:
 
libraries - never, ever write yourself.
 
libraries - never, ever write yourself.
  
===Matmul times===
+
==Matmul times==
 
$ ./matmul 2500
 
$ ./matmul 2500
 
Experiment with matrix size
 
Experiment with matrix size
Line 830: Line 832:
 
samples/arrays/matmul.f90
 
samples/arrays/matmul.f90
  
===Linear algebra in Fortran===
+
==Linear algebra in Fortran==
  
 
samples/arrays/matrix.f90
 
samples/arrays/matrix.f90
  
===Array sizes and Assumed Shape===
+
==Array sizes and Assumed Shape==
 
* Printmat routine here is
 
* Printmat routine here is
 
interesting - don’t pass
 
interesting - don’t pass
Line 848: Line 850:
 
samples/arrays/matrix.f90
 
samples/arrays/matrix.f90
  
===Array sizes and Assumed Shape===
+
==Array sizes and Assumed Shape==
 
* Assumed shape arrays (eg,
 
* Assumed shape arrays (eg,
 
dimension(:,:)) much better
 
dimension(:,:)) much better
Line 865: Line 867:
 
samples/arrays/matrix.f90
 
samples/arrays/matrix.f90
  
===Allocatable Arrays===
+
==Allocatable Arrays==
 
* So far, all our programs have had fixed-size
 
* So far, all our programs have had fixed-size
 
arrays, set at compile time.
 
arrays, set at compile time.
Line 877: Line 879:
 
important addition to Fortran.
 
important addition to Fortran.
  
===Allocate(), Deallocate()===
+
==Allocate(), Deallocate()==
 
* Give array a deferred size (eg,
 
* Give array a deferred size (eg,
 
dimension(:)) and the attribute
 
dimension(:)) and the attribute
Line 888: Line 890:
 
as any other array.
 
as any other array.
  
===Allocate(), Deallocate()===
+
==Allocate(), Deallocate()==
 
* If allocation fails (not enough memory available for
 
* If allocation fails (not enough memory available for
 
request), program will exit.
 
request), program will exit.
Line 899: Line 901:
 
the problem, or you don’t.
 
the problem, or you don’t.
  
===get_command_argument()===
+
==get_command_argument()==
 
* Previous version still
 
* Previous version still
 
depended on a compiled-in
 
depended on a compiled-in
Line 913: Line 915:
 
samples/arrays/allocatable2.f90
 
samples/arrays/allocatable2.f90
  
===get_command_argument()===
+
==get_command_argument()==
  
 
samples/arrays/allocatable2.f90
 
samples/arrays/allocatable2.f90
  
===Hands on #3===
+
==Hands on #3==
 
* Use array functionality to simplify hydro code
 
* Use array functionality to simplify hydro code
 
-- don't need to pass, array size, and can
 
-- don't need to pass, array size, and can
Line 927: Line 929:
 
* ~30 min
 
* ~30 min
  
===Fortran Pointers===
+
==Fortran Pointers==
 
* Pointers, or references,
 
* Pointers, or references,
 
refer to another
 
refer to another
Line 948: Line 950:
 
3.2
 
3.2
  
===Fortran Pointers===
+
==Fortran Pointers==
  
 
samples/pointers/ptr1.f90
 
samples/pointers/ptr1.f90
  
===Fortran Pointers===
+
==Fortran Pointers==
 
* Pointers are either
 
* Pointers are either
 
associated, null, or
 
associated, null, or
Line 971: Line 973:
 
x
 
x
  
===Fortran Pointers===
+
==Fortran Pointers==
 
real, target :: x = 3.2
 
real, target :: x = 3.2
 
real, pointer:: p
 
real, pointer:: p
Line 984: Line 986:
 
x
 
x
  
===Fortran Pointers===
+
==Fortran Pointers==
 
* Fortran pointers can’t
 
* Fortran pointers can’t
 
point just anywhere.
 
point just anywhere.
Line 1,000: Line 1,002:
 
3.2
 
3.2
  
===Fortran Pointers===
+
==Fortran Pointers==
 
real, target :: x = 3.2
 
real, target :: x = 3.2
 
real, pointer:: p1, p2
 
real, pointer:: p1, p2
Line 1,017: Line 1,019:
 
3.2
 
3.2
  
===Allocating a pointer===
+
==Allocating a pointer==
 
* Pointer doesn’t
 
* Pointer doesn’t
 
necessarily have to have
 
necessarily have to have
Line 1,035: Line 1,037:
 
7.9
 
7.9
  
===Allocating a Pointer===
+
==Allocating a Pointer==
  
 
samples/pointers/ptr2.f90
 
samples/pointers/ptr2.f90
  
===What are they good===
+
==What are they good==
 
for? (1)
 
for? (1)
 
* Pointers are essential for
 
* Pointers are essential for
Line 1,056: Line 1,058:
 
http://en.wikipedia.org/wiki/File:Max-Heap.svg
 
http://en.wikipedia.org/wiki/File:Max-Heap.svg
  
===What are they good===
+
==What are they good==
 
for? (2)
 
for? (2)
 
* A pointer can be of
 
* A pointer can be of
Line 1,086: Line 1,088:
 
7
 
7
  
===Array Views===
+
==Array Views==
  
 
samples/pointers/views.f90
 
samples/pointers/views.f90
  
===Hands on #4===
+
==Hands on #4==
 
* Use pointers to provide views into subsets of
 
* Use pointers to provide views into subsets of
 
the arrays in solver.f90 to clarify the functions.
 
the arrays in solver.f90 to clarify the functions.
Line 1,098: Line 1,100:
 
* ~30 min
 
* ~30 min
  
===Derived Types and Objects===
+
==Derived Types and Objects==
 
* Often, groups of
 
* Often, groups of
 
variables naturally go
 
variables naturally go
Line 1,120: Line 1,122:
 
g % xmax = +1
 
g % xmax = +1
  
===Derived Types and Objects===
+
==Derived Types and Objects==
 
* Consider interval
 
* Consider interval
 
arithmetic (good for
 
arithmetic (good for
Line 1,132: Line 1,134:
 
samples/derivedtypes/simple/intervalmath.f90
 
samples/derivedtypes/simple/intervalmath.f90
  
===Derived Types and Objects===
+
==Derived Types and Objects==
 
* Note can access the
 
* Note can access the
 
fields in the type with
 
fields in the type with
Line 1,145: Line 1,147:
 
samples/derivedtypes/simple/intervalmath.f90
 
samples/derivedtypes/simple/intervalmath.f90
  
===Procedures using types===
+
==Procedures using types==
 
* Can start creating
 
* Can start creating
 
library of routines that
 
library of routines that
Line 1,157: Line 1,159:
 
samples/derivedtypes/intervalfunctions/intervalmath.f90
 
samples/derivedtypes/intervalfunctions/intervalmath.f90
  
===Procedures using types===
+
==Procedures using types==
 
* Can start creating
 
* Can start creating
 
library of routines that
 
library of routines that
Line 1,170: Line 1,172:
 
samples/derivedtypes/intervalfunctions/interval1.f90
 
samples/derivedtypes/intervalfunctions/interval1.f90
  
===Procedures using types===
+
==Procedures using types==
 
* Would prefer not to
 
* Would prefer not to
 
have to treat integer
 
have to treat integer
Line 1,181: Line 1,183:
 
samples/derivedtypes/intervalfunctions/intervalmath.f90
 
samples/derivedtypes/intervalfunctions/intervalmath.f90
  
===Procedures using types===
+
==Procedures using types==
 
{|
 
{|
 
|
 
|
Line 1,190: Line 1,192:
 
|}
 
|}
  
===Generic Interfaces===
+
==Generic Interfaces==
 
{|
 
{|
 
* Generic Interfaces
 
* Generic Interfaces
Line 1,200: Line 1,202:
 
|}
 
|}
  
===Generic Interfaces===
+
==Generic Interfaces==
 
* Note that everything is
 
* Note that everything is
 
private except what is
 
private except what is
Line 1,214: Line 1,216:
 
samples/derivedtypes/genericintervals/intervalmath.f90
 
samples/derivedtypes/genericintervals/intervalmath.f90
  
===Generic interfaces===
+
==Generic interfaces==
 
* Call to addintervals or
 
* Call to addintervals or
 
subtract intervals goes
 
subtract intervals goes
Line 1,225: Line 1,227:
 
samples/derivedtypes/genericintervals/interval2.f90
 
samples/derivedtypes/genericintervals/interval2.f90
  
===Operator overloading===
+
==Operator overloading==
 
* An infix operator is
 
* An infix operator is
 
really just “syntactic
 
really just “syntactic
Line 1,238: Line 1,240:
 
returns a
 
returns a
  
===Operator overloading===
+
==Operator overloading==
 
* An assignment
 
* An assignment
 
operator is really just
 
operator is really just
Line 1,251: Line 1,253:
 
subroutine assign(a,b)
 
subroutine assign(a,b)
  
===Operator overloading===
+
==Operator overloading==
 
* Here, we’ve defined
 
* Here, we’ve defined
 
two subroutines which
 
two subroutines which
Line 1,261: Line 1,263:
 
samples/derivedtypes/intervaloperators/intervalmath.f90
 
samples/derivedtypes/intervaloperators/intervalmath.f90
  
===Generic interfaces===
+
==Generic interfaces==
 
* Once this is done, can
 
* Once this is done, can
 
use assignment
 
use assignment
Line 1,274: Line 1,276:
 
samples/derivedtypes/intervaloperators/interval3.f90
 
samples/derivedtypes/intervaloperators/interval3.f90
  
===Type bound procedures===
+
==Type bound procedures==
 
* Types can have not only
 
* Types can have not only
 
variables, but
 
variables, but
Line 1,285: Line 1,287:
 
intervalmath.f90
 
intervalmath.f90
  
===Type bound procedures===
+
==Type bound procedures==
 
* Called like one accesses
 
* Called like one accesses
 
a field - %
 
a field - %
Line 1,294: Line 1,296:
 
samples/derivedtypes/intervaltypebound/interval3.f90
 
samples/derivedtypes/intervaltypebound/interval3.f90
  
===Type bound procedures===
+
==Type bound procedures==
 
* It is implicitly passed as
 
* It is implicitly passed as
 
it’s first parameter the
 
it’s first parameter the
Line 1,304: Line 1,306:
 
intervalmath.f90
 
intervalmath.f90
  
===Object oriented===
+
==Object oriented==
 
programming
 
programming
 
* F2003 onwards can do full object oriented
 
* F2003 onwards can do full object oriented
Line 1,314: Line 1,316:
 
starting-off point.
 
starting-off point.
  
===Interoperability with===
+
==Interoperability with==
 
other languages
 
other languages
 
* Large scientific software now frequently uses
 
* Large scientific software now frequently uses
Line 1,326: Line 1,328:
 
python.
 
python.
  
===C-interoperability===
+
==C-interoperability==
 
* iso_c_binding module contains definitions for
 
* iso_c_binding module contains definitions for
 
interacting with C
 
interacting with C
Line 1,333: Line 1,335:
 
routines in a way that they can be called by C.
 
routines in a way that they can be called by C.
  
===Calling a C routine===
+
==Calling a C routine==
 
from Fortran
 
from Fortran
 
* As with the case of
 
* As with the case of
Line 1,344: Line 1,346:
 
samples/C-interop/call-c-fn/main.f90
 
samples/C-interop/call-c-fn/main.f90
  
===Calling a C routine===
+
==Calling a C routine==
 
from Fortran
 
from Fortran
 
* BIND(C) - tells compiler/
 
* BIND(C) - tells compiler/
Line 1,358: Line 1,360:
 
function.
 
function.
  
===Calling a C routine===
+
==Calling a C routine==
 
from Fortran
 
from Fortran
 
* The value the function
 
* The value the function
Line 1,368: Line 1,370:
 
c_long, etc.
 
c_long, etc.
  
===Calling a C routine===
+
==Calling a C routine==
 
from Fortran
 
from Fortran
 
* C function arguments by
 
* C function arguments by
Line 1,381: Line 1,383:
 
arguments.
 
arguments.
  
===Calling a C routine===
+
==Calling a C routine==
 
from Fortran C math
 
from Fortran C math
 
lib.
 
lib.
Line 1,403: Line 1,405:
 
1.4142135623730951
 
1.4142135623730951
  
===C strings===
+
==C strings==
 
* When using C
 
* When using C
 
strings, you have to
 
strings, you have to
Line 1,425: Line 1,427:
 
samples/C-interop/c-strings/main.f90
 
samples/C-interop/c-strings/main.f90
  
===Calling Fortran from C===
+
==Calling Fortran from C==
 
* To write Fortran
 
* To write Fortran
 
routines callable from
 
routines callable from
Line 1,438: Line 1,440:
 
samples/C-interop/c-call-fortran/froutine.f90
 
samples/C-interop/c-call-fortran/froutine.f90
  
===Calling Fortran from C===
+
==Calling Fortran from C==
 
* Here, we’ll do
 
* Here, we’ll do
 
something a little
 
something a little
Line 1,446: Line 1,448:
 
samples/C-interop/c-call-fortran/froutine.f90
 
samples/C-interop/c-call-fortran/froutine.f90
  
===Calling Fortran from C===
+
==Calling Fortran from C==
 
* In Fortran, we accept
 
* In Fortran, we accept
 
the arguments as C
 
the arguments as C
Line 1,461: Line 1,463:
 
samples/C-interop/c-call-fortran/froutine.f90
 
samples/C-interop/c-call-fortran/froutine.f90
  
===Calling Fortran from C===
+
==Calling Fortran from C==
 
* The single scalar
 
* The single scalar
 
argument passed back
 
argument passed back
Line 1,469: Line 1,471:
 
samples/C-interop/c-call-fortran/froutine.f90
 
samples/C-interop/c-call-fortran/froutine.f90
  
===More advanced===
+
==More advanced==
 
* Handling arbitrary C code is possible
 
* Handling arbitrary C code is possible
 
* Passing C structs -- create a Fortran derived
 
* Passing C structs -- create a Fortran derived
Line 1,481: Line 1,483:
 
functionptr)
 
functionptr)
  
===Example of===
+
==Example of==
 
Fortran calling
 
Fortran calling
 
C, which calls
 
C, which calls
Line 1,488: Line 1,490:
 
samples/C-interop/valueref/driver.f90
 
samples/C-interop/valueref/driver.f90
  
===samples/C-interop/valueref/croutine.c===
+
==samples/C-interop/valueref/croutine.c==
  
===samples/C-interop/valueref/froutine.f90===
+
==samples/C-interop/valueref/froutine.f90==
  
===$ ./main===
+
==$ ./main==
 
(1) In the FORTRAN routine before call to C
 
(1) In the FORTRAN routine before call to C
 
(1) i =
 
(1) i =
Line 1,509: Line 1,511:
 
30.000000000000000
 
30.000000000000000
  
===samples/C-interop/valueref/Makefile===
+
==samples/C-interop/valueref/Makefile==
  
===F2py===
+
==F2py==
 
* Comes with scipy,
 
* Comes with scipy,
 
a widely-installed
 
a widely-installed
Line 1,524: Line 1,526:
 
http://www.scipy.org/F2py
 
http://www.scipy.org/F2py
  
===* Will only use solver module.===
+
==* Will only use solver module.==
 
* Unfortunately, f2py isn’t quite smart enough to understand
 
* Unfortunately, f2py isn’t quite smart enough to understand
 
using parameters to size arrays, so global replace ‘nvars’=4
 
using parameters to size arrays, so global replace ‘nvars’=4
Line 1,530: Line 1,532:
 
* “f2py -m hydro_solver -h hydro_solver.pyf solver.f90”
 
* “f2py -m hydro_solver -h hydro_solver.pyf solver.f90”
  
===* generates the following header file (hydro_solver.pyf)===
+
==* generates the following header file (hydro_solver.pyf)==
  
 
* Comment out stuff we don’t need (lower-level routines)
 
* Comment out stuff we don’t need (lower-level routines)
 
* f2py -c --fcompiler=gfortran hydro_solver.pyf solver.f90
 
* f2py -c --fcompiler=gfortran hydro_solver.pyf solver.f90
  
===$ ipython===
+
==$ ipython==
 
In [1]: import hydro_solver
 
In [1]: import hydro_solver
 
In [2]: hydro_solver.solver.
 
In [2]: hydro_solver.solver.
Line 1,562: Line 1,564:
 
In [8]: pylab.imshow(u[1,:,:])
 
In [8]: pylab.imshow(u[1,:,:])
  
===Coarrays===
+
==Coarrays==
 
* In F2008, objects
 
* In F2008, objects
 
can also have a
 
can also have a
Line 1,574: Line 1,576:
 
samples/coarrays/simple.f90
 
samples/coarrays/simple.f90
  
===Coarrays===
+
==Coarrays==
 
1
 
1
  
Line 1,596: Line 1,598:
 
processes
 
processes
  
===Coarrays===
+
==Coarrays==
 
1
 
1
  
Line 1,624: Line 1,626:
 
“see” each other’s data as easily as an array index.
 
“see” each other’s data as easily as an array index.
  
===Sychronization===
+
==Sychronization==
 
* When accessing other
 
* When accessing other
 
processor’s data, must
 
processor’s data, must
Line 1,635: Line 1,637:
 
samples/coarrays/broadcast.f90
 
samples/coarrays/broadcast.f90
  
===Sychronization===
+
==Sychronization==
 
* Other synchronization
 
* Other synchronization
 
tools:
 
tools:
Line 1,650: Line 1,652:
 
samples/coarrays/broadcast.f90
 
samples/coarrays/broadcast.f90
  
===1d Diffusion Eqn===
+
==1d Diffusion Eqn==
 
* Calculate heat
 
* Calculate heat
 
diffusion along a bar
 
diffusion along a bar
Line 1,663: Line 1,665:
 
1 -2 1
 
1 -2 1
  
===1d Diffusion Eqn===
+
==1d Diffusion Eqn==
 
* Initial conditions:
 
* Initial conditions:
 
* Use pointers to
 
* Use pointers to
Line 1,677: Line 1,679:
 
samples/coarrays/diffusion/diffusion.f90
 
samples/coarrays/diffusion/diffusion.f90
  
===1d Diffusion Eqn===
+
==1d Diffusion Eqn==
 
* Evolution:
 
* Evolution:
 
* Apply BCs
 
* Apply BCs
Line 1,685: Line 1,687:
 
samples/coarrays/diffusion/diffusion.f90
 
samples/coarrays/diffusion/diffusion.f90
  
===1d Diffusion Eqn===
+
==1d Diffusion Eqn==
 
* Output calculated
 
* Output calculated
 
values and theory to
 
values and theory to
Line 1,696: Line 1,698:
 
samples/coarrays/diffusion/diffusion.f90
 
samples/coarrays/diffusion/diffusion.f90
  
===$ ./diffusion===
+
==$ ./diffusion==
 
[..]
 
[..]
 
$ gnuplot
 
$ gnuplot
Line 1,703: Line 1,705:
 
'output.txt' using 1:3 with lines title 'Theory'
 
'output.txt' using 1:3 with lines title 'Theory'
  
===Coarray Diffusion===
+
==Coarray Diffusion==
 
* Now we’ll try this in
 
* Now we’ll try this in
 
parallel
 
parallel
Line 1,716: Line 1,718:
 
neighbouring image.
 
neighbouring image.
  
===Coarray Diffusion===
+
==Coarray Diffusion==
 
* Everything’s the same
 
* Everything’s the same
 
except we are only
 
except we are only
Line 1,731: Line 1,733:
 
samples/coarrays/diffusion/diffusion-coarray.f90
 
samples/coarrays/diffusion/diffusion-coarray.f90
  
===Coarray Diffusion===
+
==Coarray Diffusion==
 
* Boundary exchange; if we
 
* Boundary exchange; if we
 
have interior neighbours,
 
have interior neighbours,
Line 1,746: Line 1,748:
 
samples/coarrays/diffusion/diffusion-coarray.f90
 
samples/coarrays/diffusion/diffusion-coarray.f90
  
===Coarray Diffusion===
+
==Coarray Diffusion==
  
 
temperature()[leftneigh]
 
temperature()[leftneigh]
Line 1,757: Line 1,759:
 
lnpts+2
 
lnpts+2
  
===Coarray Diffusion===
+
==Coarray Diffusion==
 
* Everything else exactly
 
* Everything else exactly
 
the same.
 
the same.
Line 1,767: Line 1,769:
 
samples/coarrays/diffusion/diffusion-coarray.f90
 
samples/coarrays/diffusion/diffusion-coarray.f90
  
===$ export FOR_COARRAY_NUM_IMAGES=3===
+
==$ export FOR_COARRAY_NUM_IMAGES=3==
 
# 3 images
 
# 3 images
 
$ ./diffusion-coarray
 
$ ./diffusion-coarray
Line 1,776: Line 1,778:
 
using 1:2
 
using 1:2
  
===gnuplot> plot '1-output.txt' using 1:2, '2-output.txt' using 1:2, '3output.txt' using 1:2, '1-output.txt' using 1:3 with lines title 'Theory',===
+
==gnuplot> plot '1-output.txt' using 1:2, '2-output.txt' using 1:2, '3output.txt' using 1:2, '1-output.txt' using 1:3 with lines title 'Theory',==
 
'2-output.txt' using 1:3 with lines title 'Theory', '3-output.txt' using 1:3
 
'2-output.txt' using 1:3 with lines title 'Theory', '3-output.txt' using 1:3
 
with lines title 'Theory'
 
with lines title 'Theory'
  
===Parallel Matrix Multiplication===
+
==Parallel Matrix Multiplication==
 
* Consider matrix
 
* Consider matrix
 
operations, where
 
operations, where
Line 1,798: Line 1,800:
 
=
 
=
  
===Parallel Matrix Multiplication===
+
==Parallel Matrix Multiplication==
 
* Block matrix multiply exactly like matrix multiply, except each operation is a submatrix operation
 
* Block matrix multiply exactly like matrix multiply, except each operation is a submatrix operation
 
* matmul instead of “*”.
 
* matmul instead of “*”.
Line 1,810: Line 1,812:
 
=
 
=
  
===Parallel Matrix Multiplication===
+
==Parallel Matrix Multiplication==
 
* Each image gets its own block of a, b, c.
 
* Each image gets its own block of a, b, c.
 
* Note [nrows,*].  Coarrays can have any corank(eg, number of codimensions)
 
* Note [nrows,*].  Coarrays can have any corank(eg, number of codimensions)
Line 1,818: Line 1,820:
 
samples/coarrays/blockmatrix.f90
 
samples/coarrays/blockmatrix.f90
  
===Parallel Matrix Multiplication===
+
==Parallel Matrix Multiplication==
 
* Allocation, deallocation of coarrays is like a sync all
 
* Allocation, deallocation of coarrays is like a sync all
 
* Forces synchronization across all images
 
* Forces synchronization across all images
Line 1,825: Line 1,827:
 
samples/coarrays/blockmatrix.f90
 
samples/coarrays/blockmatrix.f90
  
===Parallel Matrix Multiplication===
+
==Parallel Matrix Multiplication==
 
* This is the entire parallel multiplication operation.
 
* This is the entire parallel multiplication operation.
 
* a[myrow,k] gets the entire a block from image at myrow,k.
 
* a[myrow,k] gets the entire a block from image at myrow,k.
Line 1,832: Line 1,834:
 
samples/coarrays/blockmatrix.f90
 
samples/coarrays/blockmatrix.f90
  
===Coarray Summary===
+
==Coarray Summary==
 
* Coarrays are powerful, simple-to-use addition to parallel programming models available
 
* Coarrays are powerful, simple-to-use addition to parallel programming models available
 
* Will be widely available soon
 
* Will be widely available soon
Line 1,839: Line 1,841:
 
* Other languages have similar extensions (UPC based on C, Titanium based on Java) but are not part of languages’ standard.
 
* Other languages have similar extensions (UPC based on C, Titanium based on Java) but are not part of languages’ standard.
  
===Closing Hints===
+
==Closing Hints==
 
* Always give the compiler info it needs to help you by being as explicit as possible
 
* Always give the compiler info it needs to help you by being as explicit as possible
 
* implicit none, end [construct] [name], parameters for constants, intent in/out, use only, etc.
 
* implicit none, end [construct] [name], parameters for constants, intent in/out, use only, etc.
 
* Always get as much info from compiler as possible - always use -Wall (gfortran) or -warn all (ifort).
 
* Always get as much info from compiler as possible - always use -Wall (gfortran) or -warn all (ifort).
  
===Useful Resources===
+
==Useful Resources==
 
* http://fortranwiki.org/
 
* http://fortranwiki.org/
 
* Reference source; has all standards; Fortran2003/2008 status of major compilers
 
* Reference source; has all standards; Fortran2003/2008 status of major compilers

Revision as of 17:46, 13 August 2012

Modern Fortran for FORTRAN77 users

Jonathan Dursi

This is the Wiki-fied version of the slides used for the Modern Fortran course at SciNet. To follow along, with both the examples and the hands on, you will want to download the source code and make sure you have a working Fortran 2003 compiler.


Course Overview

  • Intro, History (10 min)
  • New syntax (30 min), Hands on #1(60 min)
  • Functions, Modules (45 min), Hands on #2 (30 min)
  • Lunch (1 hr)
  • New Array Features (15 min), Hands on #3 (30 min)
  • Pointers & Interfaces (30 min), Hands on #4 (30 min)
  • Derived Data Types and Objects (30 min)
  • Interoperability with C,Python (30 min)
  • Coarrays (30 min)

A Brief History of Fortran

  • Only major compiled programming language designed specifically for scientific programming.
  • Powerful array operations; many mathematical functions (Bessel functions!) built in; designed to enable compiler optimizations for fast code
  • Oldest (54-57 yrs) still-used programming language.
  • Most people come to Fortran via being given old code by someone.
  • Can’t understand the old code, or quirks of modern language, without understanding it’s history
  • 1957 - J.W. Backus et al. In Proceedings Western Joint Computer Conference, Los Angeles, California, February 1957.
  • IBM 704
  • (Arguably) first modern compiled programming language.
  • Idea of compilers at all was controversial at time.

http://www.softwarepreservation.org/projects/FORTRAN/ http://en.wikipedia.org/wiki/File:Fortran_acs_cover.jpeg

FORTRAN (1957)

  • Fixed-column format to simplify punched cards
  • C in column 1 - comment
  • Line labels in cols 2-5
  • Continuation character in col 6
  • Code in cols 7-72.
  • Continued until Fortran90!
  • Variables did not need declaration
  • Any variables used starting with i,j,k,l,m,n were assumed integer, all others real.
  • Saved punched cards.
  • Idea is with us today terrible idea.
  • Already had multidimensional arrays!

http://en.wikipedia.org/wiki/File:FortranCardPROJ039.agr.jpg


Incremental changes

  • FORTRAN II (1958) - subroutines and functions (good!) common blocks (terrible, terrible).
  • Still machine dependent (READ INPUT TAPE)
  • FORTRAN III - inline assembly - never released
  • FORTRAN IV (1961) - removed machine dependancies


FORTRAN66

  • With implementation of standard, loss of machine dependency, started gaining wide use on many computers
  • Many implementations
  • double precision, complex, logical types
  • intrinsic and external routines

FORTRAN77

  • The most common to see “in the wild” of old code today
  • if/else/endif, better do loops, control of implicit typing
  • Character strings, saved variables, IO improvements
  • Approved in 1978, beginning long tradition of “optimistic” naming of standards by year.

The interregnum

  • Programming languages and techniques were moving quite quickly
  • Several attempts were made to make new version, but standardization process very slow, failed repeatedly.
  • Absent new real standard, implementations began to grow in many different directions
  • Some extensions became quasi-standard, many were peculiar to individual compilers.

Fortran90

  • Enormous changes; the basis of modern Fortran (not FORTRAN!)
  • Free form, array slices, modules, dynamic memory allocation, derived types...
  • Changes so major that took several years for compilers to catch up.
  • Modern fortran

And since...

  • Fortran95 - modest changes to Fortran90, killed off some deprecated F77 constructs.
  • Fortran 2003 - bigger change; object-oriented, C interoperability. Most compilers have pretty good F2003 support.
  • Fortran 2008 - mostly minor changes, with one big addition (coarray), other parallel stuff. Compiler-writers getting there.

F90, F95, F2003, F2008..

  • We won’t distinguish between versions; we’ll just show you a lot of useful features of modern fortran.
  • Will only show widely-implemented features from 2003 and 8, with exception of coarrays; these are being implemented and are very important.

New Format, New Syntax

Free Format: some highlights

  • Columns no longer significant; can start at left margin
  • Implicit none. Always, always use.
  • Variable declaration syntax changed (more later)
  • Lines can be up to 132 char long; to continue, put & at end of line.
  • ! for comments; comments out rest of line.
  • Numeric line labels are strongly discouraged, but control structures can be named (more later)
  • <, > vs .lt., .gt.
  • <=, >= vs .le., .ge.
  • ==, /= vs .eq., .neq.
  • Program, procedure can contain other procedures
  • “program x” or “function y” ended by “end program x” or “end function y”
  • Case doesn’t matter (except strings)
  • Lines can start anywhere, can be 132 cols long
  • Continue with an & at end of line
  • Can continue a single line 255 times
  • Comments - !, can start anywhere, comments out rest of line
  • Compilers can usually handle both old fixed format and modern free format, but not within the same file.

(from samples/freeform/freeform.f90)

Variable Declarations

  • Implicit none turns off all implicit typing.
  • Was a common F77 extension, but not part of a standard.
  • DO THIS. Without, (eg) variable typos don’t get caught.
  • This is going to be a recurring theme for several features.
  • You do a little more typing and make things explicit to compiler.
  • Then compiler can catch errors, optimize, better.

Variable Declarations

  • The “::” separating type and name is new
  • Type declarations can now have a lot more information
  • Many attributes of variables set on declaration line
  • :: makes it easier for you, compiler, to see where attributes stop and variable names begin

Variable Declarations

  • Parameter attribute for values which will be constants.
  • Compiler error if try to change them.
  • Useful for things which shouldn’t change.
  • F77 equivalent:
integer i parameter (i=5)

Variable Declarations

  • Initialization of variables at declaration time
  • Required for parameters (because can’t change them later), can be done for other variables.
  • Can do anything that compiler can figure out at compile time, including math with other parameters.

Variable Declarations

  • Initializing variables this way gives unexpected behaviour in functions/subroutines “for historical reasons”.
  • Initialized variables given the “save” attribute
  • eg, integer, save, i=5
  • Value saved between calls. Can be handy - but not threadsafe.
  • Initialization done only first time through.
  • Not a problem for main program, parameters.

samples/variables/initialization/initialization.f90

Real Kinds

  • Reals, Double precisions, really different “kinds” of same “type” - floating pt real #s.
  • Kinds introduced to give enhanced version of functionality of non-standard but ubiquitous constructs like REAL*8
  • real32, real64 defined in iso_fortran_env in newest compilers (gfortran 4.6, ifort 12)
  • selected_real_kind(N): returns kind parameter for reals with N decimal digits of precision
  • Default real is generally 4-byte (32bit) real, has 6 digits of precision and a range of 37 in the exponent.
  • Many built-in (‘intrinsic’) functions which give info about properties of a variable’s numerical type.
  • precision - #digits of precision in decimal * range - of exponent
  • tiny, huge - smallest, largest positive represented number
  • epsilon - machine epsilon
  • several others

samples/variables/kinds/realkinds.f90

Integer Kinds

  • Similar constructs for integers
  • selected int kind(N): kind can represent all N-digit decimal numbers.
  • huge(N): largest positive number of that type samples/variables/kinds/intkinds.f90

Strings

  • Character types are usually used for strings
  • Specify length
  • Padded by blanks
  • Intrinsic trim() gets rid of blanks at end
  • Can compare strings with <,>,==, etc.
  • Concatenate with //
  • Characters have kinds too
  • gfortran has partial support for selected_char_kind(“ISO_10646”) for unicode strings.

Array declarations

  • Array declarations have changed, too:
  • dimension is now an attribute
  • Can easily declare several arrays with same dimension

Do loops

  • Do loops syntax has had some changes
  • do/enddo - was a common extension, now standard.

samples/variables/doloops/doi.f90

Do loops

  • All constructs now have end constructname to end.
  • Named constructs (program, subroutine) require, eg, end program doi.
  • Helps catch various simple errors (mismatched ends, etc.)

Do loops

  • Can name control structures like do, if statements now, too.
  • Handy for documentation, or to distinguish deeply-nested loops.
  • Again, can help catch mismatched loops.
  • enddo or end do; fortran isn’t picky about spaces.

samples/variables/doloops/nameddo.f90

Do loops

  • Do loops don’t even need a i=1,n
  • do/enddo
  • Will loop forever
  • Can control looping with cycle, exit
  • exit - exits loop. (exit loopname can exit out of nested loops)
  • cycle - jumps back to do
samples/variables/doloops/cycleexit.f90

Cycle/exit

samples/variables/doloops/cycleexit.f90

Do while

  • do while - repeats as

long as precondition is true.

  • Seems like it should be

useful, but in practice, just do/enddo with exit condition is usually cleaner.

samples/variables/doloops/dowhile.f90

Hands on #1

  • In workedexample/f77 is a simplified, F77ized version of a fluid-dynamics code from UeLi Pen, CITA, U of Toronto (http://

www.cita.utoronto.ca/~pen/MHD/)

  • Today we’ll be translating it to a very modern

Fortran

  • ssh -Y in to login nodes, then to devel nodes,

then compile (using make) and run (./hydro)

Hands on #1

  • Outputs a .pbm file;

use “display dens.pbm” to see the result of dense blob of fluid moving through a light medium.

Hands on #1

  • In workedexamples/freeform, have partly

converted the program to new freeform format, with enddos, ending procedures, implicit nones, and new variable declaration syntax.

  • Finish doing so - just need to do program

hydro, subroutine color, subroutine outputpbm, function cfl. Fix indenting (Don't need to start at col 7 anymore).

  • ~1 hr (for getting logged in and everything

working)

Procedures and

modules

  • Several enhancements to how procedures

(functions, subroutines) are defined

  • Modules are ways of organizing procedures,

definitions, into sensible units for ease of code maintenance, clarity

Modules

  • Easiest to show by

example

  • Here, the gravity

module defines a constant, and contains a function

  • Main program “use”s

the module, has access to both.

  • “Use” goes before

“implicit none”

samples/procedures/simplemod/simplemod.f90

Compiling & Running

  • When compiling the code

a gravity.mod file is created

  • Machine-generated and readable “header” file

containing detailed type, other information about contents of module

  • Not compatible between

different compilers, versions.

Modules

  • function gravforce can

“see” the modulewide parameter defined above.

  • So can main program,

through use statement.

samples/procedures/simplemod/simplemod.f90

use module, only :

  • Best practice is to only

pull in from the module what you need

  • Otherwise, everything.
  • Adds some clarity and

documentation, good for maintainability

  • (Note syntax for

continuation of a string...) samples/procedures/simplemod/simplemod2.f90

Modules usually get their own files

  • For encapsulation
  • For ease of re-use
  • Here’s a slightly

expanded module;

  • Let’s see how to

compile it.

  • (Main program hasn’t

changed much).

samples/procedures/multifilemod/gravity.f90

Modules usually get their own files

  • Compiling gravity.f90

now gives both an .o file (containing the code) and the .mod file as before.

  • Compiling the main

program (multifilemod.f90) requires the .mod file.

samples/procedures/multifilemod/Makefile

.mod needed for compilation

  • ...because needs the

type information of the constants,

  • and type

information, number and type of parameters, for the function call.

  • Can’t compile

without these samples/procedures/multifilemod/multifilemod.f90

.o needed for linking

  • Linking, however,

doesn’t require the .mod file

  • Only requires the .o

file from the module code.

  • .mod file analogous

(but better than) .h files for C code.

samples/procedures/multifilemod/Makefile

Compiling and running

  • So compile files with modules first, so

those that need them have the .mod files

  • Link the .o files

Private and public

  • Not all of a module’s

content need be public

  • Can give individual

items public or private attribute

  • “private” makes

everything private by default

  • Allows hiding

implementationspecific routines samples/procedures/multifilemod/gravity.f90

Procedures

  • We’ve already seen

procedures defined in new style; let’s look more closely.

  • Biggest change: intent

attribute to “dummy variables” (eg, parameters passed in/ out). samples/procedures/funcsub/procedures.f90

Procedures

  • Again, make expectations

more explicit, compiler can catch errors, optimize.

  • Intent(in) - read only. Error

to change.

  • Intent(out) - write only.

Value undefined before set.

  • Intent(inout) - read/write.

(eg, modify region of an array)

  • Also documentation of a

sort. samples/procedures/funcsub/procedures.f90

Functions

  • Can be typed a couple of ways.
  • Old-style still works (real

function square..)

  • Give a result variable different

from function name; set that, type that result (xsquared) real :: xsquared

  • Explicitly type the function

name, set that as return value real :: cube

  • Function values don’t take

intent samples/procedures/funcsub/procedures.f90

Procedure interfaces

  • The interface to a procedure

consists of

  • A procedure’s name
  • The arguments, their names,

types and all attributes

  • For functions, the return value

name and type

  • Eg, the procedure, with all the

real code stripped out.

  • Like a C prototype, but more

detailed info

  • .mod files contain explicit

interfaces to all public module procedures.

Procedure interfaces

  • To see where interfaces

become necessary, consider this sketch of a routine to do trapezoid-rule integration

  • We want to use a passed-in

function f, but we don’t know anything about it - type, # of arguments, etc.

  • Need to “type” f the same way

you do with xlo, xhi, n.

  • You do that for procedures

with interfaces http://en.wikipedia.org/wiki/ File:Trapezoidal_rule_illustration_small.svg

Procedure interfaces

  • Define f as a parameter, give its

type via an interface.

  • Can then use it, and at compile

time compiler ensures function passed in matches this interface.

  • samples/procedures/interface/

integrate.f90

Recursive procedures

  • By default, Fortran procedures

cannot call themselves (recursion)

  • Can be enabled by giving the

procedure the recursive attribute

  • Subroutines, functions
  • Recursive functions must use

“result” keyword to return value.

samples/procedures/recursive/integrate.f90

Pure procedures

  • Procedures are pure or

impure depending on whether or not they have “side effects”:

  • Changing things other

than their dummy arguments

  • Modifying save variables
  • Modifying module data
  • Printing, etc.

samples/procedures/purity/purity.f90

Pure procedures

  • Optimizations can be made

for pure routines which can’t for impure

  • Label known-pure routines

with the pure attribute.

  • Almost all the procedures

we’ve seen so far are pure. samples/procedures/purity/purity.f90

Optional Arguments

  • Can make

arguments optional by using the optional attribute.

  • Use present to test.
  • Can’t use tol if not

present; have to use another variable. samples/procedures/optional/integrate.f90

Optional Arguments

  • When calling the

procedure, can use the optional argument or not.

  • Makes sense to leave

optional arguments at end - easier to figure out what’s what when it’s omitted.

samples/procedures/optional/optional.f90

Keyword Arguments

  • To avoid ambiguity with

omitted arguments - or really whenever you want - you can specify which value is which explicitly.

  • Don’t have to be in

order.

  • Can clarify calls of

routines with many arguments.

samples/procedures/optional/optional.f90

Procedures & Modules

Summary

  • Modules let you bundle procedures, constants

in useful packages.

  • Can have public, private components
  • Compiling them generates a .mod file

(needed for compiling anything that does a “use modulename”) and an .o file (where the code goes, needed to link together the program).

Procedures & Modules

Summary

  • New syntax for functions/subroutines: intent

(IN/OUT/INOUT)

  • New syntax for function return values; result

or explicit typing of function in argument list.

  • Procedures have interfaces, which are needed

for (eg) passing functions

  • Optional/keyword arguments
  • Pure/recursive procedures

Hands on #2

  • In workedexamples/modules, have have

pulled the PBM stuff out into a module.

  • Do the same with the hydro routines. What

needs to be private? Public?

  • The common block (thankfully) only contains

constants, can make those module parameters

  • ~30 min

Fortran arrays

  • Fortran made for dealing with scientific data
  • Arrays built into language
  • The type information associated with an

array includes rank (# of dimension), size, element type, stride..

  • Enables powerful optimizations,

programmer-friendly features.

Fortran arrays

  • Can be manipulated

like simple scalar variables

  • Elementwise

addition, multiplication.. samples/arrays/basic.f90

Array constructors

  • Can have array

constants like numerical constants

  • use [] or (/ /), then

comma-separated list of values.

  • Implied do loops

can be used in constructors

  • (Variables have to

be defined)

[1,2,3,4,5] or (/1,2,3,4,5/) [ (i,i=1,5)] [ ((i*j,j=1,3),i=1,5)]

Elementwise operations

  • Elementwise operations

can be */+-, or application of an elemental function.

  • Math intrinsics are all

elemental - applied to array, applies to every element.

  • Order of execution

undefined - allows vectorization, parallelization.

samples/arrays/elementwise.f90

Elemental Functions

  • User can create their

own elemental functions

  • Label any scalar function

with “elemental” should (until recently, must) be pure, so can be applied everywhere at same time.

  • Faster than in loop.
  • Can also take multiple

arguments: eg z = addsquare(x,y)

samples/arrays/elemental.f90

Array comparisons

  • Array comparisons

return an array of logicals of the same size of the arrays.

  • Can use any and all to

see if any or all of those logicals are true. samples/arrays/compare.f90

Array masks

  • These logical arrays can

be used to mask several operations

  • Only do sums, mins, etc

where the mask is true

  • Eg, only pick out positive

values.

  • Many array intrinsics

have this mask option

samples/arrays/mask.f90

Where construct

  • The where construct

can be used to easily manipulate sections of array based on arbitrary comparisons.

  • Where construct => for

whatever indices the comparison is true, set values as follow; otherwise, set other values.

samples/arrays/where.f90

Forall construct

  • Forall is an array

assignment statement

  • Each line in forall has to be

independent. All done “at once” - no guarantees as to order

  • If (say) 2 lines in the forall,

all of the first line is done, then all of the second.

  • Any functions called must

be pure

  • Can be vectorized or

parallelized by compiler

samples/arrays/forall.f90

Array Sections

  • Generalization of array

indexing

  • Familiar to users of

Matlab, IDL, Python..

  • Can use “slices” of an

array using “index triplet”

  • [start]:[end][:step]
  • Default start=1, default

end=size, default step=1.

  • Can be used for each

index of multid array

a([start]:[end][:step]) a = [1,2,3,4,5,6,7,8,9,10] a(7:) == [7,8,9,10] a(:3) == [1,2,3] a(2:4) == [2,3,4] a(::3) == [1,4,7,10] a(2:4:2) == [2,4] a(2) == 2 a(:) == [1,2,3,4,5,6,7,8,9,10]

Array Sections

  • This sort of thing is very

handy in numerical computation

  • Replace do-loops with

clearer, shorter, possibly vectorized array operations

  • Bigger advantage for

multidimensional arrays

samples/arrays/derivative.f90

Array Sections

  • The previous sorts of array

sections - shifting things leftward and rightward - are so common there are intrinsics for them

  • +ve shift shifts elements

leftwards (or array bounds rightwards).

  • cshift does circular shift - shifting

off the end of the array “wraps around”.

  • eoshift fills with zeros, or

optional filling.

  • Can work on given dimension

a = [1,2,3,4,5] cshift(a,1) == [2,3,4,5,1] cshift(a,-1) == [5,1,2,3,4] eoshift(a,1) ==[2,3,4,5,0] eoshift(a,-1)==[0,1,2,3,4]

Other important array

intrinsics

  • minval/maxval - finds min, max element in an array.
  • minloc/maxloc - finds location of min/max element
  • product/sum - returns product/sum of array elements
  • reshape - Adjusts shape of array data. Eg:

1,4 reshape([1,2,3,4,5,6],[3,2]) == 2,5 3,6

Linear algebra in Fortran

  • Comes built in with transpose, matmul,

dot_product for dealing with arrays.

  • matmul also does matrix-vector multiplication
  • Either use these or system-provided BLAS

libraries - never, ever write yourself.

Matmul times

$ ./matmul 2500 Experiment with matrix size 2500 Triple-loop time: 149.63400 matmul intrinsic time: 10.370000 SGEMM lapack call time: 1.4809999

(gfortran 4.6, compiled -O3 -march=native using Intel MKL 10.3 for sgemm)

samples/arrays/matmul.f90

Linear algebra in Fortran

samples/arrays/matrix.f90

Array sizes and Assumed Shape

  • Printmat routine here is

interesting - don’t pass (a,rows,cols), just a.

  • Can assume a rank-2 array,

and get size at runtime.

  • Simplifies call, and eliminates

possible inconsistency: what if rows, cols is wrong?

  • size(array,dim) gets the size of

array in the dim dimension.

samples/arrays/matrix.f90

Array sizes and Assumed Shape

  • Assumed shape arrays (eg,

dimension(:,:)) much better than older ways of passing arrays: integer nx, ny integer a(nx,ny) or worse, integer a(*,ny)

  • Information is thrown away,

possibility of inconsistency.

  • Here, (:,:) means we know the

rank, but don’t know the size yet.

samples/arrays/matrix.f90

Allocatable Arrays

  • So far, all our programs have had fixed-size

arrays, set at compile time.

  • To change problem size, have to edit code,

recompile.

  • Has some advantages (optimization,

determinism) but very inflexible.

  • Would like to be able to request memory

at run time, make array of desired size.

  • Allocatable arrays are arguably most

important addition to Fortran.

Allocate(), Deallocate()

  • Give array a deferred size (eg,

dimension(:)) and the attribute allocatable.

  • When time to allocate it, use

allocate(a(n)).

  • Deallocate with deallocate(a).

samples/arrays/allocatable.f90

  • In between, arrays can be used

as any other array.

Allocate(), Deallocate()

  • If allocation fails (not enough memory available for

request), program will exit.

  • Can control this by checking for an optional error code,

allocate(a(n),stat=ierr)

  • Can then test if ierr>0 (failure condition) and handle

gracefully.

  • In scientific programming, the default behaviour is often

fine, if abrupt - you either have enough memory to run the problem, or you don’t.

get_command_argument()

  • Previous version still

depended on a compiled-in number.

  • Can read from file or from

console, but Fortran now has standard way to get command-line arguments

  • Get the count of arguments,

and if there’s at least one argument there, get it, read it as integer, and allocate array. samples/arrays/allocatable2.f90

get_command_argument()

samples/arrays/allocatable2.f90

Hands on #3

  • Use array functionality to simplify hydro code

-- don't need to pass, array size, and can simplify mathematics using array operations.

  • In workedexamples/arrays, have modified

hydro to allocate u, and pbm to just take array.

  • Do the same with the fluid dynamic routines in

solver.f90

  • ~30 min

Fortran Pointers

  • Pointers, or references,

refer to another variable.

  • Eg, p does not contain a

real value, but a reference to another real variable.

  • Once associated with

another variable, can read/write to it as if it were stored “in” p.

real, target :: x = 3.2 real, pointer:: p p => x p

x 3.2

Fortran Pointers

samples/pointers/ptr1.f90

Fortran Pointers

  • Pointers are either

associated, null, or undefined; start out life undefined.

  • Can associate them to

a variable with => , or mark them as not associated with any valid variable by pointing it to null().

real, target :: x = 3.2 real, pointer:: p p => null() p

x

Fortran Pointers

real, target :: x = 3.2 real, pointer:: p

  • Reading value from or

writing value to a null pointer will cause errors, probably crash.

p => null() p

x

Fortran Pointers

  • Fortran pointers can’t

point just anywhere.

  • Must reference a

variable with the same type, that has the target attribute.

real, target :: x = 3.2 real, pointer:: p p => x p

x 3.2

Fortran Pointers

real, target :: x = 3.2 real, pointer:: p1, p2

  • Pointers can reference

other pointers.

  • Actually references

what they’re pointing to.

p1 => x p2 => p1 p1 p2

x 3.2

Allocating a pointer

  • Pointer doesn’t

necessarily have to have another variable to target

  • Can allocate memory

for p to point to that does not belong to any other pointer.

  • Must deallocate it when

done

real, pointer:: p allocate(p) p = 7.9 p 7.9

Allocating a Pointer

samples/pointers/ptr2.f90

What are they good

for? (1)

  • Pointers are essential for

creating, maintaining dynamic data structures

  • Linked lists, trees, heaps..
  • Some of these can be

sort-of implemented in arrays, but very awkward

  • Adaptive meshes, treebased particle solvers

need these structures.

http://en.wikipedia.org/wiki/File:Singly-linked-list.svg

http://en.wikipedia.org/wiki/File:Max-Heap.svg

What are they good

for? (2)

  • A pointer can be of

array type, not just scalar

  • Fortran pointers +

fortran arrays are quite interesting; can create “views” of subarrays

real, target, dimension(7) :: x real, pointer:: p(:) p => x(2:6)

p x 1

2

3

4

5

6

7

Array Views

samples/pointers/views.f90

Hands on #4

  • Use pointers to provide views into subsets of

the arrays in solver.f90 to clarify the functions.

  • In workedexamples/pointers, have started

the process with cfl, hydroflux; try tackling tvd1d, others.

  • ~30 min

Derived Types and Objects

  • Often, groups of

variables naturally go together to represent a larger structure

  • Whenever you find

yourself passing the same group of variables to several routines, a good candidate for a derived type.

type griddomain real :: xmin, xmax real :: ymin, ymax real :: nx, ny real, dimension(:,:) :: u endtype griddomain type(griddomain) :: g g % xmin = -1 g % xmax = +1

Derived Types and Objects

  • Consider interval

arithmetic (good for quantification of uncertainties, etc).

  • An interval inherently

has two values associated with it - the end points.

  • Can make this a type.

samples/derivedtypes/simple/intervalmath.f90

Derived Types and Objects

  • Note can access the

fields in the type with “%”

  • typename

(field1val,field2val..) initializes a value of that type.

  • Can pass values of this

type to functions, etc., just like a built-in type. samples/derivedtypes/simple/intervalmath.f90

Procedures using types

  • Can start creating

library of routines that operate on these new interval types.

  • Procedures can take

the new type as arguments, functions can return the new type. samples/derivedtypes/intervalfunctions/intervalmath.f90

Procedures using types

  • Can start creating

library of routines that operate on these new interval types.

  • Procedures can take

the new type as arguments, functions can return the new type.

samples/derivedtypes/intervalfunctions/interval1.f90

Procedures using types

  • Would prefer not to

have to treat integer and real intervals so differently in main program

  • Different types, but

adding should be similar. samples/derivedtypes/intervalfunctions/intervalmath.f90

Procedures using types

  • Would like to be able to call “addintervals” and have language call the right subroutine, do the right thing.
  • Similar to how intrinsics work - sin() works on any kind of real, matmult() works on integer, real, or complex matricies.

samples/derivedtypes/genericintervals/interval2.f90

Generic Interfaces

  • Generic Interfaces
  • addintintervals and addrealintervals share the same interface, (two input parameters, one function return), but different types.
  • Put them behind the same interface.
  • Now, a call to addintervals is resolved at compile time to one or the other.

samples/derivedtypes/genericintervals/intervalmath.f90

Generic Interfaces

  • Note that everything is

private except what is explicitly made public.

  • Types are public.
  • Generic interfaces are

public.

  • Type specific routines

are not.

  • Program using interval

math sees only the generic interfaces. samples/derivedtypes/genericintervals/intervalmath.f90

Generic interfaces

  • Call to addintervals or

subtract intervals goes to the correct typespecific routine.

  • As does print interval.
  • Could create routines

to add real to int interval, etc and add to the same interface. samples/derivedtypes/genericintervals/interval2.f90

Operator overloading

  • An infix operator is

really just “syntactic sugar” for a function which takes two operands and returns a third.

a = b (op) c => function op(b,c) returns a

Operator overloading

  • An assignment

operator is really just “syntactic sugar” for a subroutine which takes two operands and sets the first from the second.

a=b => subroutine assign(a,b)

Operator overloading

  • Here, we’ve defined

two subroutines which set intervals based on an array - 2 ints for an integer interval, or 2 reals for a real interval

samples/derivedtypes/intervaloperators/intervalmath.f90

Generic interfaces

  • Once this is done, can

use assignment operator,

  • Or add, subtract

multiply intervals.

  • Can even compose

them in complex expressions! Functions automatically composed. samples/derivedtypes/intervaloperators/interval3.f90

Type bound procedures

  • Types can have not only

variables, but procedures.

  • Takes us from a type to

what is usually called a class.

samples/derivedtypes/intervaltypebound/ intervalmath.f90

Type bound procedures

  • Called like one accesses

a field - %

  • Operates on data of

the particular variable it is invoked from

samples/derivedtypes/intervaltypebound/interval3.f90

Type bound procedures

  • It is implicitly passed as

it’s first parameter the variable itself.

  • Can take other

arguments as well.

samples/derivedtypes/intervaltypebound/ intervalmath.f90

Object oriented

programming

  • F2003 onwards can do full object oriented

programing.

  • Types can be derived from other types, inheriting

their fields and type-bound procedures, and extending them.

  • Goes beyond scope of today, but this is the

starting-off point.

Interoperability with

other languages

  • Large scientific software now frequently uses

multiple languages, either within a single code or between codes.

  • Right tool for the job!
  • Need to know how to make software

interact.

  • Here we’ll look at C/Fortran code calling

each other, and calling Fortran code from python.

C-interoperability

  • iso_c_binding module contains definitions for

interacting with C

  • Types, ways to bind procedures to C, etc.
  • Allows you to call C routines, or bind Fortran

routines in a way that they can be called by C.

Calling a C routine

from Fortran

  • As with the case of

calling a passed-in function, need an explicit prototype.

  • Tells compiler what

to do with “sqrtc” function when called. samples/C-interop/call-c-fn/main.f90

Calling a C routine

from Fortran

  • BIND(C) - tells compiler/

linker will have a C-style, rather than fortran-style name in object file.

  • Can optionally supply

another name; otherwise, will default to procedure name.

  • Here we’re calling it sqrtc

to avoid Fortran sqrt() function.

Calling a C routine

from Fortran

  • The value the function

takes and returns are C doubles; that is, reals of kind(c_double).

  • Also defined: c_float,

integers of kind c_int, c_long, etc.

Calling a C routine

from Fortran

  • C function arguments by

default are passed by value; Fortran by default are passed by reference.

  • Passed by value - values

copied into function

  • Passed by reference pointers to values copied

in.

  • value attribute for C-style

arguments.

Calling a C routine

from Fortran C math lib.

  • Compiling - just make

sure to link in C library you’re calling

  • And that’s it.

$ make gfortran -c main.f90 gfortran -o main main.o -lm

$ ./main x = 2.0000000000000000 C sqrt(x) = 1.4142135623730951 Fortran sqrt(x) = 1.4142135623730951

C strings

  • When using C

strings, you have to remember that C terminates strings with a special character

  • C_NULL_CHAR
  • Dealing with functions

that return strings is hairier, as they return a pointer, not an array.

$ make gfortran-mp-4.4 -c main.f90 gfortran-mp-4.4 -o main main.o -lc $ ./main 1234 = 1234

samples/C-interop/c-strings/main.f90

Calling Fortran from C

  • To write Fortran

routines callable from C, bind the subroutine to a C name

  • Can optionally give it a

different name, as above

  • And make sure

arguments are of C types.

samples/C-interop/c-call-fortran/froutine.f90

Calling Fortran from C

  • Here, we’ll do

something a little trickier and pass C dynamic arrays

samples/C-interop/c-call-fortran/froutine.f90

Calling Fortran from C

  • In Fortran, we accept

the arguments as C pointers

  • We then associate

them with fortran pointers to arrays of shape [nx] (1d arrays here)

  • Then we can do the

usual Fortran array operations with them.

samples/C-interop/c-call-fortran/froutine.f90

Calling Fortran from C

  • The single scalar

argument passed back we just treat as an intent(out) variable

  • Of type c_float.

samples/C-interop/c-call-fortran/froutine.f90

More advanced

  • Handling arbitrary C code is possible
  • Passing C structs -- create a Fortran derived

type with the same fields, use BIND(C) in defining the type.

  • C “multidimensional arrays” - have to be

careful, they may not be contiguous! Follow pointers.

  • Even taking passed function pointers to C

functions is possible (samples/C-interop/ functionptr)

Example of

Fortran calling C, which calls Fortran

samples/C-interop/valueref/driver.f90

samples/C-interop/valueref/croutine.c

samples/C-interop/valueref/froutine.f90

$ ./main

(1) In the FORTRAN routine before call to C (1) i = 15 x = 2.0000000000000000 (2) In the C routine, got i=15, *x=2.000000 (2) Changed x (3) In the FORTRAN routine called by C (3) Got product p = 30.000000000000000 (1) In the FORTRAN routine after call to C (1) i = 15 x = 3.0000000000000000 prod = 30.000000000000000

samples/C-interop/valueref/Makefile

F2py

  • Comes with scipy,

a widely-installed (by scientists) python package.

  • Wraps fortran in

python, allows you to easily interface.

  • fwrap is another

option

http://www.scipy.org/F2py

* Will only use solver module.

  • Unfortunately, f2py isn’t quite smart enough to understand

using parameters to size arrays, so global replace ‘nvars’=4

  • module load use.experimental gcc python/2.7.1 intel/12
  • “f2py -m hydro_solver -h hydro_solver.pyf solver.f90”

* generates the following header file (hydro_solver.pyf)

  • Comment out stuff we don’t need (lower-level routines)
  • f2py -c --fcompiler=gfortran hydro_solver.pyf solver.f90

$ ipython

In [1]: import hydro_solver In [2]: hydro_solver.solver. hydro_solver.solver.cfl hydro_solver.solver.gamma hydro_solver.solver.hydroflux hydro_solver.solver.idens hydro_solver.solver.iener hydro_solver.solver.imomx

hydro_solver.solver.imomy hydro_solver.solver.initialconditions hydro_solver.solver.timestep hydro_solver.solver.tvd1d hydro_solver.solver.xsweep hydro_solver.solver.xytranspose

In [2]: hydro_solver.solver.idens Out[2]: array(1, dtype=int32) In [3]: import numpy In [4]: u = hydro_solver.solver.initialconditions(100,100) In [5]: import pylab In [6]: pylab.imshow(u[1,:,:]) In [7]: for i in range(100) ...dt = hydro_solver.solver.timestep(u) In [8]: pylab.imshow(u[1,:,:])

Coarrays

  • In F2008, objects

can also have a “codimension”.

  • An object with a

codimension can be “seen” across processes

  • Right now, only intel

v 12 supports this samples/coarrays/simple.f90

Coarrays

1

A B

2

A B

N

...

A B

num_images independant processes

Coarrays

1

A B

2

A B

N

...

A B

num_images independant processes

A[1] B[N]

Independent, parallel tasks can “see” each other’s data as easily as an array index.

Sychronization

  • When accessing other

processor’s data, must ensure that tasks are synchronized

  • Don’t want to read

task 1’s data before read is complete!

  • sync all

samples/coarrays/broadcast.f90

Sychronization

  • Other synchronization

tools:

  • sync images([..]) syncs

only images in the list provided

  • critical - only one

image can enter block at a time

  • lock - finer-grained

control than critical.

  • atomic operations.

samples/coarrays/broadcast.f90

1d Diffusion Eqn

  • Calculate heat

diffusion along a bar

  • Finite difference;

calculate second derivative using neighbours

  • Get new

temperature from old temperatures

1 -2 1

1d Diffusion Eqn

  • Initial conditions:
  • Use pointers to

point to new, old temperatures

  • 1..totpoints+2 (pts 1,

totpoints+1 “ghost cells)

  • Setup x, orig

temperature, expected values

samples/coarrays/diffusion/diffusion.f90

1d Diffusion Eqn

  • Evolution:
  • Apply BCs
  • Apply finite

difference stencil to all real data points samples/coarrays/diffusion/diffusion.f90

1d Diffusion Eqn

  • Output calculated

values and theory to file output.txt

  • Note: Fortran2008,

can use “newunit” to find, use an unused IO unit

samples/coarrays/diffusion/diffusion.f90

$ ./diffusion

[..] $ gnuplot [..] gnuplot> plot 'output.txt' using 1:2 with points title 'Simulated', 'output.txt' using 1:3 with lines title 'Theory'

Coarray Diffusion

  • Now we’ll try this in

parallel

  • Each image runs it’s part

of the problem (totpoints/num_images())

  • Communications is like

boundary condition handling - except boundary data must be obtained from neighbouring image.

Coarray Diffusion

  • Everything’s the same

except we are only responsible for locpoints points, starting at start.

  • Once calculated, we

never need totpoints again. All arrays are of size (locpoints), etc.

  • For simplicity, we

assume here everything divides evenly.

samples/coarrays/diffusion/diffusion-coarray.f90

Coarray Diffusion

  • Boundary exchange; if we

have interior neighbours, get updated data from them so we can calculate our new data

  • Note: can’t use pointers

here, coarrays can’t be targets.

  • Sync all around boundary

exchange a little heavy handed; could just sync neighbours. samples/coarrays/diffusion/diffusion-coarray.f90

Coarray Diffusion

temperature()[leftneigh]

temperature() temperature()[rightneigh]

1 2 3 ...

lnpts+2

Coarray Diffusion

  • Everything else exactly

the same.

  • For I/O, we each output

our own file, prefixed by our image number

  • (eg, 1-output.txt, 2output.txt...)

samples/coarrays/diffusion/diffusion-coarray.f90

$ export FOR_COARRAY_NUM_IMAGES=3

  1. 3 images

$ ./diffusion-coarray [..] $ gnuplot [..] gnuplot> plot '1-ics.txt' using 1:2, '2-ics.txt' using 1:2, '3-ics.txt' using 1:2

gnuplot> plot '1-output.txt' using 1:2, '2-output.txt' using 1:2, '3output.txt' using 1:2, '1-output.txt' using 1:3 with lines title 'Theory',

'2-output.txt' using 1:3 with lines title 'Theory', '3-output.txt' using 1:3 with lines title 'Theory'

Parallel Matrix Multiplication

  • Consider matrix

operations, where matrix is decomposed onto images in blocks

  • A given image has

corresponding blocks in A, B, responsible for that block in C.

A

B X C =

Parallel Matrix Multiplication

  • Block matrix multiply exactly like matrix multiply, except each operation is a submatrix operation
  • matmul instead of “*”.
  • For simplicity, we’ll assume square decomposition.

A

B X C =

Parallel Matrix Multiplication

  • Each image gets its own block of a, b, c.
  • Note [nrows,*]. Coarrays can have any corank(eg, number of codimensions)
  • Here, we make decomposition nrows x ncols.
  • Can set decomposition array-by-array.

samples/coarrays/blockmatrix.f90

Parallel Matrix Multiplication

  • Allocation, deallocation of coarrays is like a sync all
  • Forces synchronization across all images
  • Any particular coarray must have same size, co-size across all images

samples/coarrays/blockmatrix.f90

Parallel Matrix Multiplication

  • This is the entire parallel multiplication operation.
  • a[myrow,k] gets the entire a block from image at myrow,k.
  • matmul works with those blocks, updates c with new term.

samples/coarrays/blockmatrix.f90

Coarray Summary

  • Coarrays are powerful, simple-to-use addition to parallel programming models available
  • Will be widely available soon
  • Basic model implemented in Cray fortran for ~10 yrs; well tested and understood.
  • Typically implemented with MPI under the hood; can give performance similar to MPI with fewer lines of code.
  • Other languages have similar extensions (UPC based on C, Titanium based on Java) but are not part of languages’ standard.

Closing Hints

  • Always give the compiler info it needs to help you by being as explicit as possible
  • implicit none, end [construct] [name], parameters for constants, intent in/out, use only, etc.
  • Always get as much info from compiler as possible - always use -Wall (gfortran) or -warn all (ifort).

Useful Resources