fortran basics
TRANSCRIPT
Fortran 95: Building blocksfor object-based programming
©2006-8 LRZ 2
Fortran Type System: Intrinsic types (1)
Which ones are available?1. integer2. real3. complex4. logical5. character
Declaration:
works OK, but not recommended
implementation dependency
Use KIND instead
(minimum range)compiler barfs if KIND number unavailable
but beware constants
change only one line to convert all objects
encapsulation for re-use also possible
integer myintdouble precision y
integer, parameter :: ik = & selected_int_kind(6)integer(ik) :: myint:myint = 42_ik
−106myint106
©2006-8 LRZ 3
Fortran Type System: Intrinsic types (2)
KINDS of reals
first argument „p“: decimal precisionsecond argument „r“: decimal exponent rangeone of two arguments can be omittedreal KIND numbers also apply to each component of type complex
KINDS of logical, characternot definedUNICODE support however in
integer, parameter :: rk = selected_real_kind(12,100)real(rk) :: y:y = 3.14_rk
©2006-8 LRZ 4
Fortran Type System:Arrays
Arrays of intrinsic typestatic
elements 12, 15, 18, ..., 96 are assigned an array expression
dynamic
Performance featureimplement as reference to contiguous chunk of memoryknowledge of layout
optimize accesses
usually in (nested loop) access patterns
loop unrolling, blocking, ... by compiler
Multi-dimensional arraysup to 7 dimensionsinnermost index contiguous
integer, parameter :: dim = 100real(rk), dimension(dim) :: y_a:y_a(12:98:3) = (/ ... /)
real(rk), allocatable, & dimension(:) :: y_a:allocate(y_a(dim), stat=...): ! check status and use y_a(:)deallocate(y_a)
C++ STL functionality
©2006-8 LRZ 5
Fortran Type System:Handling Strings
While it is possible to define an array of characters
for handling of strings length parametrization is more appropriate:
disadvantage: no dynamic adjustment possible. Hence,
will print 'give me a very long ', and
will print 'a short line' (trim will remove trailing white spaces)
Reference a substring:
character, dimension(20) :: line
character(len=20) :: line ! this is a scalar
line = 'give me a very long line' ; write(6, *) line
line(:) = 'a short line' ; write(6, *) trim(line)
line(i:j), line(:), line(i:), ...
©2006-8 LRZ 6
Fortran Type SystemDerived types (1)
Type definition:
improved abstractiongroup data belonging to a concept together
aggregation allowed:intrinsic typespreviously defined derived types
Structure declaration„instantiation“ uses „real“ memory
earth: static scalar
planets: dynamic array
Note:type must be defined before instantiation must be in scope of type definition
scope ~ „region of validity“
type :: body real :: mass character(len=5) :: units real, dimension(3) :: pos real, dimension(3) :: velend type
type(body) :: earthtype(body), allocatable :: &
planets(:)
©2006-8 LRZ 7
Fortran Type SystemDerived types (2)
Default initializationwithin type definitionimproved version -
recommended practice
Accessing componentswrite access:
earth%mass = 5.5e18 earth%units = 'mks '
read access analogous:
real(rk) :: em : em = earth%mass
type :: body real(rk) :: mass = 0._rk character(5) :: & units = 'mks ' real(rk), dimension(3) :: & pos = (/ 3 * 0._rk /) real(rk), dimension(3) :: & vel = (/ 3 * 0._rk /)end type
componentselector
©2006-8 LRZ 8
Fortran Type SystemDerived types (3)
Assignmentdefault is to copy all components -
type (body) :: earth type (body), allocatable :: planets(:) : earth%mass = ... : ! initialize all components allocate(planets(8))
planets(3) = earthnested derived types are treated recursively
see later slide
types with dynamic components need special attentiontreated in a separate section of this talk
©2006-8 LRZ 9
Fortran Type SystemDerived types (4)
Structure constructor:earth = body(5.5e18_rk, & 'mks',1.5e11_rk, ...)
again: beware dynamic components
Nested type definition:type charged_body type (body) :: m real(rk) :: chargeend type
„has a“ relationship: charged_body has a body
also known as „object composition“
Accessing type components:
type (charged_body) :: x:x%m%mass = 1.2x%m%units = 'cgs'x%charge = 1.4e-6
tiresome for many levels of nesting
©2006-8 LRZ 10
Arrays of derived types
Looking at planets(:) array
Extract scalar subobjects
substring refs allowedExtract array subobjects
However, two subpart references are not allowed
need to use loop:
note storage layout
Also works forderived type componentsdynamical components
character(len=5) :: txtreal :: pmass:txt = planets(3)%unitspmass = planets(4)%mass
real :: pvel(3)real :: xvel(4):pvel(:) = planets(5)%vel(:)xvel(:) = & planets(1:8:2)%vel(1)
real :: all_pvel(3,8):do i = 1, 8 pvel(:,i) = & planets(i)%vel(:)end do! ... = planets(:)%vel(:)! is illegal
©2006-8 LRZ 11
Manipulating array sections:Vector subscripts and the cshift() intrinsic
Extract (unordered) subset
Can be injectivemany-one (as above)
Restrictions:many-one not on left hand side of an assignmentactual subroutine argument: dummy may not be intent(out|inout)
consistency of type and shape required
can also specify an array of integers as second argument
type(body) :: p_subset(4)
p_subset(:) = & planets( (/4,3,9,3/) )
real :: v(20), vs(20)real :: w(10,20), ws(10, 20):vs = cshift(v, 3)ws = cshift(w, 3, 2)
...
...
v
vs
©2006-8 LRZ 12
What can we do with all this?
First, some caveatstype definition only usable within scope of defining program unit
cannot re-declare same type
what about re-use?
special role of type definition with sequence attribute
determine storage layout
can be re-defined elsewhere
loss of type safety
general recommendation: do not use
Additional wishes: (especially if you know C++)
manipulate type components through API calls („methods“)make type components inaccessible otherwise („encapsulation“)
An additional kind of program unit is required
known kinds: program, procedure
©2006-8 LRZ 13
Fortran Module concept:Definition
A module may contain:type definitionsdeclarations of objectsdeclarations of interfacesdata encapsulation attributes and statements (private, public)
these constrain accessibility to module-defined entities from outside the module
subroutines and functions („module procedures“)namelist groups
Graphical representation:„OMT extended for modules“
note rounded corners of box
ocean
ocean_init_t()ocean_set_t()...
module name
public objectsand
type definitions
public procedures
©2006-8 LRZ 14
Fortran Module concept:Example: Storage Pool (1)
Realization of diagram from previous slide
module ocean implicit none real, private, save, allocatable :: ocean_t(:,:,:) contains subroutine ocean_init_t(n) integer, intent(in) :: n(3) allocate(ocean_t(n(1),n(2),n(3))) ! check status etc.omitted end subroutine ocean_init_t subroutine ocean_set_t(i,j,k,val) integer, intent(in) :: i,j,k real, intent(in) :: val ocean_t(i,j,k) = val end subroutine ocean_set_t! analogous: ocean_get_t() and further callsend module ocean
temperature
©2006-8 LRZ 15
Fortran Module conceptStorage pool (2): Explanations
properties of storage area:private attribute encapsulates
save attribute guarantees survival of ocean_t even if scope is left
default attribute is publicall subroutines
optimization aspect:assume evaluation of each matrix element expensive compared to storing/reading
contained module procedures:
access possible to all objects and data types
→„host association“
automatically define an „explicit interface“
©2006-8 LRZ 16
Fortran Module concept:Using the module (1)
program myprog
use ocean implicit none real :: x : call ocean_init_t((/34,34,22/)) ocean_t(3,6,2) = 1.4 ! will fail to compile call ocean_set_t(3,6,2,1.4) ! this is OK call ocean_set_t(3,6,2.0,1.4) ! will fail to compile call ocean_get_t(3,6,2,x) write(6, *) x ! will write 1.4 to unit 6 :end program
ocean
ocean_init_t()ocean_set_t()...
myprog
u„use inheritance“
©2006-8 LRZ 17
Fortran Module concept:Using the module (2)
other program units:may access all publically available entities
→ „use association“
as if redeclaredonly way to re-use type definitions
use statement requirespre-compiled module information for argument module(s)
compiler checksreferenced entities
consistent use of explicit interfaces
1. programs2. subroutines
can be module procedures in other module
3. other modulesno (indirect) circular module referencesthis is enforced by separate compilation
→ form directed acyclical graph
©2006-8 LRZ 18
Fortran Module concept: A technical aspect
Handling the compilation:generic f90 command assumed
1. compile ocean: f90 c o ocean.o ocean.f90
2. compile myprog: f90 c myprog.f90
3. link to an executable program f90 o myprog.exe myprog.o ocean.o
compiling ocean.f90 generates a module information file
typically called ocean.mod
needed to compile myprog.f90 (access entities, check against explicit interface)
module information file iscompiler specific, hopefully designed for lookup efficiency
usually in proprietary format (name mangling)
no binary compatibility between compilers and platformsnot a library file (instead, think „precompiled header“)
©2006-8 LRZ 19
Fortran Module concept:Module procedures as methods (1)
Add procedures to a type definition
module mod_foo implicit none private public :: foo_create, & foo_destroy, & foo_xxx type, public :: foo private integer :: len real, ... :: stuff end typecontains! continued to the right
function foo_create(this,...) type(foo), ... :: this :end function foo_create subroutine foo_destroy(...) :end subroutinefunction foo_xxx(x) result(y) type(foo), ... :: x logical :: y : end function foo_xxxend module foo
©2006-8 LRZ 20
Fortran Module concept:Module procedures as methods (2)
encapsulation: no access to type components outside module host scopeenforce use of (accessor) methodsobject-based program
function return value:specify via resultis not a dummy argument
contrast to C++encapsulation on level of module, not „class“no default methods (e.g., constructor)
C++ class definitioninclude file
#include <iostream>#include <iomanip>#include <string>
class Foo { public: Foo() : len_(0),stuff_(NULL) {}; Foo(int, float *); ~Foo(); virtual void print(); protected: int len_; private: float *stuff_;};
©2006-8 LRZ 21
Fortran Module concept:diagrammatic representation
Fortran 95 C++ (inheritance)
other virtual methods inherited
mod_foo
foo
lenstuff(:)
foo_create():
foo2
name
foo2_create():
type, public :: foo2 private! aggregation of foo type(foo) :: foo character(len=10) :: nameend type
Foo
len_* stuff_
Foo():
Foo2
name_
Foo2():
class Foo2 : public Foo { private: string name_; public: Foo2() : name_(NULL) {}; Foo2(int, float *, string &); virtual void print();};
©2006-8 LRZ 22
Specifying intent:Letting the compiler help you
function foo_create(this,y) type(foo), & intent(inout) :: this real, intent(in) :: y(n) integer :: foo_create :end function foo_create
intent(in):no changes allowed to value
intent(out):do not dereference before writinghad better write before exiting procedure because ...
argument becomes undefined on entry
beware unwritten components
beware memory leaks in objects with pointer components
intent(inout):similar to out, except:
may dereference before writing
unwritten components keep value from entry
pointer argumentno intent allowed inrefers to pointer association status in
©2006-8 LRZ 23
Interfaces (1)
establish definition of communication mechanism available to client codecategories of interface
explicitimplicit (Fortran 77 style)
→ do not use implicit interfaces, compiler cannot check
generation of explicit interfaces:
automatic for contained module proceduresuse interface block in module definition section
interfaces for externally defined routines
some compilers allow to auto-generate these from Fortran 77 source
ifort switch: geninterfaces
interface subroutine stuff_1(x,...) type(...), ... :: x : end subroutine stuff_1 end interface
©2006-8 LRZ 24
Interfaces (2): Overloading and generics
Situation:have (set of) various types
may be intrinsic or derived
have a well-defined set of operations
working in the same manner for each member of the set
uniform usability desireddefine a generic interface
overloads specific namesallows to use a single method name for each member of the set
e.g., static polymorphism (only object argument varies)
module mod_foo
private
public :: create
: ! define public types foo, foo2
interface create
module procedure &
foo_create, foo2_create
end interface
contains
function foo_create(x, ...)
type(foo) :: x
:
end function
function foo2_create(x, ...)
type(foo2) :: x
:
end function
end module mod_foo
©2006-8 LRZ 25
Interfaces (3): Using generic calls
program myprog use mod_foo use mod_3 ! def. type foo3 type(foo) :: x type(foo2) :: y type(foo3) :: z : call create(x,...) call create(y,...) call create(z,...) :end program
specifics must be all sub-routines or all functions
generic interface also required across modules to prevent name collisionone specific per module may have same name as genericargument list:
must differ sufficiently to ensure unambiguous invocation: „TKR“
in particular, pointer or allocatable attributes do not differentiate!
role of optional arguments
1. data type2. kind type parameter3. rank
©2006-8 LRZ 26
Diagrammatic representationfor generic calls
mod_foo
create()
foo
lenstuff(:)
create():
foo2name
create():
mod_3
create()
foo3
?
create():
Italics to indicate generic-nessreplicate for each type which has specific implementation
©2006-8 LRZ 27
Interfaces (4): Operator overloading
assignmentinterface assignment(=) module procedure e1, e2 end interface
module procedures must be
subroutines with two arguments
first with intent(out) or intent(inout), second with intent(in)
extend existing operatorinterface operator(+) module procedure p1, p2end interface
function with one or two intent(in) arguments
consistency with intrinsic
self defined operatorinterface operator(.myop.)
module procedure m1, m2
end interface
function with one or two intent(in) arguments
up to 31 letter characters between dotsusage in expressions
unary .unary_op. y
binary x .myop. y
All these are genericRecommendation:
do not overload assignmentoverload intrinsic (+, -, ...) only if necessary
and follow semantics!
©2006-8 LRZ 28
Interfaces (5): Optional arguments
Want to be able to omit arguments if not always needed
module mod_foo : ! omitted definitionscontains subroutine foo_calc(this, func, param) type(foo), intent(inout) :: this interface real function func(t, param) type(foo), intent(in) :: t type(par_type), intent(in) :: param end function end interface optional :: func type(par_type), intent(in), optional :: param : ! see next slide end subroutineend module
©2006-8 LRZ 29
Interfaces (6): Optional arguments cont'd
present() intrinsiclogical function
function parametersmay not reference at all if not present
undefined
can hand on non-presentneed for check only postponed
Client use:require keyword call starting with first optional
also for non-optionals coming after first optional
suggests programming style: all optionals to the end of the argument list
type(par_type) :: param_def: param_def = ... ! set defaultif (present(param)) then param_def = param! may need overloaded! assignmentend if
! possible calls are:call foo_calc(this)call foo_calc(this, func=f, param=p)call foo_calc(this, param=p, func=f)call foo_calc(this, param=p)call foo_calc(this, func=f)
©2006-8 LRZ 30
Concluding remarks on explicit interfaces
usage of module procedures:only those which have been made public
for generics, typically only the generic name should be made public
compiler checks correct use of interface TKR of actual parameters
other characteristics: pointer, allocatable, intent
against definition
mandatory for most „advanced“ Fortran functionalityfunctions with array result
allocatable dummy arguments (see later)
pointer/target dummy arguments (see later)
intent
generic interfaces
optional arguments
use as extensively as possible!
©2006-8 LRZ 31
Programming Style Hints
Recommendations for software engineering
when using modules
defining a naming schemedefault attributes to choosehandling global variables
elimination of COMMON and EQUIVALENCEfunction / subroutine arguments
©2006-8 LRZ 32
Recommendations:Use a naming scheme (1)
Module:defines internal name space for compiler
typical mangling: foo_MP_foo_create for method foo_create
name space separation mostly unavailable to clientsame (global) name (type definition, object, module procedure) may occur multiple times, but not be referenced via use association (only clauses and/or renaming can help – see following slides)
compiler will refuse compilation or linking if this occurs
exceptions: generic interfaces / operator overloading
→ define consistent naming scheme for public symbols
need not be the same for each module
Example (module defining some type):module name mod_foo
type name foo
method names foo_create
©2006-8 LRZ 33
Recommendations:Use a naming scheme (2):
Handling of name clashes:renaming of module entities possible
tt defined by module mod2_tt a different derived type with (possibly) different internal structure
use mod_tt, t1 => ttuse mod2_tt type(t1) :: o_t1type(tt) :: o_tt
alternative: one of the clashing symbols not needed
use only clause use mod_tt, only : foo
also contributes to taking pressure off namespace
self-defined operatorscannot be renamed in
this has been enabled for use mod, operator(.locop.) & =>
operator(.myop.)
©2006-8 LRZ 34
Recommendations:What to put into every module
module xyz use .. ! whatever needed implicit none save private ...end module xyz
remove implicit typingcompiler enforces strong typing
blanket privatesets default accessibilityall exported entities need explicit public attribute
blanket save statementmay use in module declaration section
values of uninitialized globals otherwise not guaranteed to be preserved if module not used by main program
better alternative: use xyz, only :
in main program, or
save attribute on objects, or
initialize objects
but not in subroutinesuse save attribute ...and use with carebeware side effects e.g., in recursive subroutines!
©2006-8 LRZ 35
Global objects (1)Example: counting objects
add global variable count C++: static member variable
module mod_foo : public :: ..., get_count integer, private, save :: & count = 0 :contains function foo_create(this,...) : count = count + 1 end function foo_create! destructor must decrement integer function get_count() get_count = count end function : end module
class Foo { public: Foo() : ...; Foo(int, float *); : protected: static int count; int len_; private: float *stuff_; };
#include “Foo.h“int Foo::count = 0;
Foo::Foo() { count += 1;} // same with all other constr.
©2006-8 LRZ 36
Global variables (2)Threading issues
Example:use OpenMP directives
beware definition statusupdates on count are not thread-safe
inconsistencies/wrong valuues
Fix: named criticalnaming reduces congestion
imagine count publicgood luck finding problems
type(foo) :: obj:! obj not created on entry!$omp parallel private(obj,...)istat = create(obj, ...): ! do computationsistat = destroy(obj)!$omp end parallel! obj undefined
function foo_create(this,...) :!$omp critical (c_count) count = count + 1!$omp end critical end function foo_create
function foo_destroy(this) :!$omp critical (c_count) count = count 1!$omp end critical end function foo_destroy
... and don't forget to switch on OpenMP everywhere!
©2006-8 LRZ 37
Global variables (3)migrating COMMON blocks
problems with COMMONprogramming effort does not scale wellneeds extensive documentation
keep track of all read/write accesses
replace by module globalsreplace include by useminimal effort: public attribute for all globals
retains disadvantage of access to all globals by all program units
improve by encapsulating
adding accessor routinesneed for large-scale access may require some redesign
©2006-8 LRZ 38
Recommendations:The EQUIVALENCE statement
Used in Fortran 77 under three possible motivations:1. reuse of storage2. referencing3. changing representation
Should not be used in modern codesmotive 1: Obsolete. Replace by dynamic memory managementmotive 2: Replace by pointers (see later) motive 3: If you're absolutely sure you need this, use the transfer() intrinsic
... a fully polymorphic one at thatsource and mold can be of any type, scalar or array
function result is of type molddistinct storage area
transfer(source, mold[, size])
©2006-8 LRZ 39
An example for the use of transfer()
from type(xtf)
to an integer array
required size of out(:) is unknown
type, public :: xtf integer :: n real(dk) :: d(20) character(len=17) :: strend type xtf:subroutine xtf_to_int(out,in) integer, intent(out) :: out(:) type(xtf), intent(in) :: in integer :: mold out(:) = transfer(in, mold, & size(out))end subroutine xtf_to_int
integer function xtf_size(this) type(xtf), intent(in) :: this integer :: mold(1) xtf_size = & size(transfer(this, mold))end function xtf_size: ! and here the usagetype(xtf) :: xinteger :: iinteger, allocatable :: istore(:)x = xtf(...) ! initializei = xtf_size(x)allocate(istore(i))call xtf_to_int(istore, x):
use special property of transfer()
returns array of size needed
©2006-8 LRZ 40
Recommendations: Statement functions
Fortran 77 idiom
note access to hostoften inlined by compiler for efficient executionlimitations:
cannot use as function argument
no explicit interface
Replace byinternal procedure
still cannot use as function argument
module procedurenot as optimizable
real(rk) :: parab, a, b, cparab(x) = a * x * x + b * x + c:a = ...; b = ...; c = ...y1 = parab(x1)y2 = parab(x2)
program myprog implicit none real(rk) :: a, b, c a = ...; b = ...; c = ... y1 = parab(x1) y2 = parab(x2)contains real(rk) function parab(x) :end program
©2006-8 LRZ 41
A case study:Function arguments and threading (1)
Typical task: numerical integrationuse a canned routine (NAG: D01AHF)
do multiple integrations why not in parallel?!$omp parallel dodo i=istart,iend ... ! prepare call d01ahf(..., my_fun, ...)end do!$omp end parallel do
Pitfalls:Is the vendor routine thread-safe? documentation/testsHow are function calls (my_fun) treated? discussed now
©2006-8 LRZ 42
A case study:Function arguments and threading (2)
Discrepancy:interface required by vendor
interface provided by user
real(dk) function arg_fun(x) real(dk), intent(in) :: xend function
subroutine user_fun(x, n, p, r) real(dk), intent(in) :: x, p integer, intent(in) :: n real(dk), intent(out) :: rend function
©2006-8 LRZ 43
A case study:Function arguments and threading (3)
Wrap user_fun() with globals
module mod_user_fun double precision, save :: par integer, save :: n!$omp threadprivate (par, n)contains function arg_fun(x) result(r) double precision :: r, x
call user_fun(x, n, par, r) end function arg_fun subroutine user_fun(...) : end subroutine user_funend module my_fun_module
possible client usageassume par depends on integration result
par = ...!$omp parallel do copyin(par) do i=istart, iend n = ... call d01ahf(..., & arg_fun, ...) par = ...! depends on previous call end do!$omp end parallel do
©2006-8 LRZ 44
A case study:Function arguments and threading (4)
Still rather cumbersome to use„non-local programming“thread-private versus shared and locked variable from previous example
need to know exactly what to use where
account for:values undefined for thread-privates without copyin
values not preserved across multiple parallel regions
note: serial regions OK, value of master thread
Question: is there not a better way on the language level?what about using generics?
not allowed as arguments for procedures
©2006-8 LRZ 45
Fortran pointers:a contrast to C
C pointersreference an addresscan be associated with a type but need not be
e.g., polymorphic void *
can be used for dynamically allocated storageiterative referencing possible
int **p e.g., for construction of 2d arrays
Fortran pointersreference data („target“)
rather like C++ referencestarget requires correspondingly named attribute
strongly typedin particular, statically typed in Fortran 95
target can be created dynamicallymay reference target array (slice)
possibly with strides in each dimension
„pointer to pointer“ is not a Fortran concept
©2006-8 LRZ 46
Fortran pointers: declaration and possible status
pointer declaration:type (xx), pointer :: & p_xx => null()
real, dimension(:), & pointer :: p_r => null()
pointer status can be
1. associated2. disassociated3. undefined
associated(ptr[,target]) intrinsic
logical functionallows to distinguish cases 1. and 2. above
undefined pointers:no dereferencing possibleonly usable intrinsic: nullify()
=> null() initialization:introduced in Fortran 95enforce disassociation at beginning of program
©2006-8 LRZ 47
Fortran pointers: definition variants
There are three possibilities for assignmentpointer assignment
turns previously undefined pointer into associated pointer orchanges target of previously associated pointer
pointer allocationassociates pointer with dynamically allocated storageotherwise similar to pointer assignment
target assignmentcopying between targetsneeds care, especially where dynamically sized entities are concerned
©2006-8 LRZ 48
Fortran pointers: pointer assignment and allocation
point at an existing target:type (xx), target :: ttype (xx), pointer :: & p_xx, q_xx => null():p_xx => t
p_xx is associated with t
dereferences go to t -
Example pointer assignment:
q_xx => p_xx does the same (rhs
dereference) as
q_xx => t
generate target dynamically:
previous example: pointer to array
real, dimension(:), & pointer :: p_r => null():allocate(p_r(1000))
p_r is associated with allocated storage areastorage area automatically has target attributedereferences go to storage area
©2006-8 LRZ 49
Notes (1): Some differences between the pointer and allocatable attributes
Pointer usage Allocatable usage
subroutine do_stuff(...,r,...) real, target :: r : real, pointer :: a_loc(:) real, pointer :: s_loc
allocate(a_loc(...)) s_loc => r : if (associated(a_loc)) then : end if deallocate(a_loc)end subroutine
subroutine do_stuff(...,r,...) real, target :: r : real, allocatable :: a_loc(:)! real, allocatable :: s_loc
allocate(a_loc(...))! s_loc = r : if (allocated(a_loc)) then : end if! deallocate(a_loc)end subroutine
©2006-8 LRZ 50
Notes (2)Pointers to arrays
may reference discontiguous storage area:
real, dimension(:), & pointer :: p_r => null():p_r => a(1:253:8)
dereferences go to a(1),a(9),a(17),...
if specified as actual subroutine argument
compiler may need to use copy-in/copy-out
otherwise no loop optimization possible inside subroutine
performance impact due to copying
what about array of pointers?not as a separate Fortran conceptbut can use derived type
type arr_xxptr type(xx), pointer :: xx end type : type(xx), target :: x type(arr_xxptr), & dimension(100) :: xxp : xxp(23)%xx => x
©2006-8 LRZ 51
Fortran pointers: target assignment
„=“ assignment:assume xx is a type with static components
could also be intrinsic type
type (xx), pointer :: p2 type (xx), target :: tt : p_xx => tt : allocate(p2) p2 = p_xx
target of p_xx is copied to target of p2i.e. both left and right hand sides are dereferenced
both p_xx and p2 must be associated with a target
types with dynamic components: to be discussed later
Intel compiler:check pointer optionshould identify incorrect target assignments at run time
©2006-8 LRZ 52
Fortran pointers:handling subroutine arguments
ActualArgument
object
pointer
target
Dummy Argument object pointer target
usually by reference,copy-in/copy-out
allowed,no-alias assumption
must be associated, dereference to target,
may need copy-in/copy-out (efficiency)
usually by reference,copy-in/copy-out
allowed,no-alias assumption
not allowed
not allowed
same rank, assoc. status passed, beware invalid target
(upon return)
pointer assoc. with dummy arg. is preserved.
copy-in/copy-outnot allowed for
scalar and assumedshape array dummies,same shape required
pointer assoc. withdummy argument
becomes undefinedon return
explicit interface required
©2006-8 LRZ 53
Fortran pointers: overview of potential problems
dangling referencesif target is deallocated or goes out of scope
associated pointers become undefined (non-locally)
memory leaksif all references to a dynamically allocated target are disassociated from this target
possibly due to pointer going out of scope
dereference undefined pointers
behaviour is not specified by standard
not a standard conforming program
anything may happencrash of program
error message from run time system
performance issues for run time checking
©2006-8 LRZ 54
Derived data typeswith dynamical components
Motivations:In practice, the size of object (array) components is often unknown at compile timeWant to implement information structures like lists and trees
may need to reference type recursively (or in a multiply recursive manner) within a type definition
(potential) Issues:memory management: prevent memory leaks
type :: list_xx type(xx) :: xx type(list_xx), pointer :: & next => null()end type
type definition simple linked list
type :: cluster integer :: num_bodies = 0 real, allocatable :: & mass(:) ! must be array :end type
type definition cluster of bodies
©2006-8 LRZ 55
Types with pointer components:Assignment rules extended
Suppose we have
then the following two alternatives are equivalent:
in particular, no new storage is allocatedi.e., pointer components are pointer assignedthis is also called „shallow copy“
type(list_xx) :: l1, l2type(xx) :: o_xx
o_xx = ...l1%xx = o_xxallocate(l1%next)
l2 = l1l2%xx = l1%xxl2%next => l1%next
©2006-8 LRZ 56
Types with pointer componentsStructure constructors
Need either a target or null() for pointer componentExample:
Further requirement: Eitheraccess to type definition(s) by host association, orpublic types with public components
type(list_xx) :: l1type(list_xx), target :: l2
l2 = list_xx(xx(...), null())
l1 = list_xx(xx(...), l2)
©2006-8 LRZ 57
Types with allocatable components:Assignment rules extended
Two equivalent code sections
assignment automatically (re)allocates c2%mass(:) to the right size„deep copy“ is performed i. e., the content is physically duplicated or cloned
Again, access to components must be allowed
type(cluster) :: c1, c2:c1%num_bodies = 5allocate(c1%mass(5))c1%mass = (/ ... /):c2 = c1
type(cluster) :: c1, c2:
c1 = cluster(5, (/ ... /))
:c2 = c1
©2006-8 LRZ 58
Further properties of pointer vs. allocatable type components
Property pointer component allocatable component
enable sizing at run time yes yes
may reference type recursively yes no
default initialization null() only no
auto-allocation no yes
auto-deallocation when out of scope no yes
assignment performs shallow copy deep copy
object with parameter attribute null() only no (yes in Fortran 2003)
scalar component yes no (yes in Fortran 2003)
©2006-8 LRZ 59
Allocating dynamic entitieswithin subroutines
Given the situation
shape of allocatable typically generated within a subroutineif values are to be read into array as well, a second subroutine is needed. This is not very economical
allows following factory method:
program myprog : type(foo), allocatable :: f(:,:) :
subroutine alloc_foo_arr(f, unit) type(foo), allocatable, intent(out) :: f(:,:) integer, intent(in) :: unit integer :: n, m read(unit) :: n, m ! checks omitted allocate(f(n, m), stat=...) read(unit) :: fend subroutine
pointer possible, but with performance issues
©2006-8 LRZ 60
Rules for interfaces using allocatable dummy arguments
explicit interface requiredactual argument must be
allocatable, andhave same type, kind parameters and rank as dummy argument
allocation status:descriptor is received by dummy upon callcopy-in/copy-out of descriptor is allowed
no reference to actual argument is allowed during execution of procedure (e.g., module variable)
array itself:copy-in/copy-out is permitted unless both actual and dummy argument have the target attribute
specifying intentintent(in) refers to both descriptor and array
useless except as constraint on actual argument
intent(out): allocation status becomes deallocated upon starting procedure execution
©2006-8 LRZ 61
Some properties of functions (1)
Function result:is an objectis not a dummy argument
even if behaviour in some respects like an intent(out) argument
exists temporarily onlyuntil assignment to lhs of function call completed
can be an object of any typecan be an arraycan be a pointercan be allocatable
explicit interface needed for most of the above
Assigning function results
usually, standard assignment rules hold
beware validity of pointer components
assignment may have been overloaded
lhs might even be different type than rhs
type(foo) function foo_xx(...) :end function foo_xx: type(foo) :: res res = foo_xx(...)
©2006-8 LRZ 62
Some properties of functions (2):functions with pointer result
Size of result unknown
explicit interface needed
Client use:
Possible problems:undefined pointer if target becomes undefined
automatic or allocatable targets - programming error
subobjects of persistent objects – useful but require tracking
memory leak if allocated items are
not deallocated before leaving scope
target assigned instead of pointer assigned (example left)
function do_stuff(...) result(r) real, pointer :: r(:) :! calculate size isz of result allocate(r(isz))! fill r(:) with valuesend function do_stuff
real, pointer :: res_p(:)real :: res_a(ndim):res_p => do_stuff(...)res_a = do_stuff(...) ! memory leak
©2006-8 LRZ 63
Some properties of functions (3):functions with allocatable result
Fix some of the problems:
explicit interface needed
Client use:
Semantics:function result unallocated on entry
behaves as if it were dummy argument with intent(out)
must be allocated and have defined value on return
intermediate allocation / deallocation is allowed
after dereferencing: result array is automatically deallocated
prevents memory leakassignment of result still clunky in
function do_stuff(...) result(r) real, allocatable :: r(:) :! calculate size isz of result allocate(r(isz))! fill r(:) with valuesend function do_stuff
real, allocatable :: res_a(ndim):allocate(res_a(size(do_stuff(...)))! relies on absence of side effectsres_a = do_stuff(...)