fortran basics

63
Fortran 95: Building blocks for object-based programming

Upload: repisky

Post on 22-Nov-2014

156 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Fortran Basics

Fortran 95: Building blocksfor object-based programming

Page 2: Fortran Basics

©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

Page 3: Fortran Basics

©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

Page 4: Fortran Basics

©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

Page 5: Fortran Basics

©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:), ...

Page 6: Fortran Basics

©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(:)

Page 7: Fortran Basics

©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

Page 8: Fortran Basics

©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

Page 9: Fortran Basics

©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

Page 10: Fortran Basics

©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

Page 11: Fortran Basics

©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

Page 12: Fortran Basics

©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

Page 13: Fortran Basics

©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

Page 14: Fortran Basics

©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

Page 15: Fortran Basics

©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“

Page 16: Fortran Basics

©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“

Page 17: Fortran Basics

©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

Page 18: Fortran Basics

©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“)

Page 19: Fortran Basics

©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

Page 20: Fortran Basics

©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_;};

Page 21: Fortran Basics

©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();};

Page 22: Fortran Basics

©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

Page 23: Fortran Basics

©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: ­gen­interfaces

interface  subroutine stuff_1(x,...)    type(...), ... :: x    :  end subroutine stuff_1 end interface

Page 24: Fortran Basics

©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

Page 25: Fortran Basics

©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

Page 26: Fortran Basics

©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

Page 27: Fortran Basics

©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!

Page 28: Fortran Basics

©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     

Page 29: Fortran Basics

©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)

Page 30: Fortran Basics

©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!

Page 31: Fortran Basics

©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

Page 32: Fortran Basics

©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

Page 33: Fortran Basics

©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.)

Page 34: Fortran Basics

©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!

Page 35: Fortran Basics

©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.

Page 36: Fortran Basics

©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!

Page 37: Fortran Basics

©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

Page 38: Fortran Basics

©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])

Page 39: Fortran Basics

©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

Page 40: Fortran Basics

©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

Page 41: Fortran Basics

©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

Page 42: Fortran Basics

©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

Page 43: Fortran Basics

©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

Page 44: Fortran Basics

©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

Page 45: Fortran Basics

©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

Page 46: Fortran Basics

©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

Page 47: Fortran Basics

©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

Page 48: Fortran Basics

©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

Page 49: Fortran Basics

©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

Page 50: Fortran Basics

©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

Page 51: Fortran Basics

©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

Page 52: Fortran Basics

©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

Page 53: Fortran Basics

©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

Page 54: Fortran Basics

©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

Page 55: Fortran Basics

©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

Page 56: Fortran Basics

©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)

Page 57: Fortran Basics

©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

Page 58: Fortran Basics

©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)

Page 59: Fortran Basics

©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

Page 60: Fortran Basics

©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

Page 61: Fortran Basics

©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(...)

Page 62: Fortran Basics

©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

Page 63: Fortran Basics

©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(...)