Vous êtes sur la page 1sur 25

Object Oriented Programming

with Fortran 2003

Patrick Tripp – IMSG @ EMC/NCEP


June 26, 2014
NCWCP, College Park, MD
Outline
• Scope of this presentation
– Intended audience: Fortran developers, scientists
• Fortran Versions
• Compiler Implementation Levels
• Object-Oriented Programming Defined
– Object Oriented Analysis and Design
– Use cases and other design tools and examples
– Unified Modeling Language (UML)
• OOP Costs versus Benefits
6/26/2014 P. Tripp 2
Outline
• OO Fortran
• Java, C++, Fortran
• Code Examples
– Abstract Data Type
– Objects and classes, Encapsulation
– Inheritance
– Polymorphism
• Topics for future presentation
– Object-Oriented Design and Analysis
– Unified Modeling Language (UML)
• References and Recommended Reading
• Discussion
6/26/2014 P. Tripp 3
Scope
• Intended audience: Model developers, scientists
– Quote from SSD re: bridging the disciplines of
computer science with physics modeling science
• An introduction to OO Fortran
– Continual learning process
– Cover the basics
– Difficult language to master
– Difficult/impractical to show every feature in one
example
– Fortran allows a lot of flexibility
– Programming is an art as well as a science
6/26/2014 P. Tripp 4
Fortran Versions
• Fortran version history
– Compiler developers slow in implementing new
standards
• Fortran 77
• Fortran 90/95
– Object based
• Fortran 2003 (Mostly implemented
– Object oriented
• Fortran 2008
– Added more parallelism features such as coarrays
amongst other things
6/26/2014 P. Tripp 5
Compiler Implementation Levels
The following links shows what parts of each standard
are implemented in different vendor’s compilers,
including Intel v.14
• Fortran 2003 Status Wiki
– http://fortranwiki.org/fortran/show/Fortran+2003+status
• Fortran 2008 Status Wiki
– http://fortranwiki.org/fortran/show/Fortran+2008+status

6/26/2014 P. Tripp 6
Object Oriented Programming Defined
• An object is a collection of data and the methods
that manipulate that data.
– Inheritance: classes can extend their parent class
– Encapsulation
• “the act of partitioning data and procedures for operating on
that data into modules.” [SSD]
– Information Hiding
• Data privacy
– Polymorphism
• From greek poly (many), morphe (form)
• Static and Dynamic Polymorphism
• Operator overloading
– Code reuse
– Not every project is a candidate for OO
6/26/2014 P. Tripp 7
OO Costs versus Benefits
• Efficiency, execution speed
– Pareto Principle
• “… roughly 20% of the participants occupy 80% of the resources.”
– Or, “approximately 20% of the lines [of code] occupy 80% of the execution time.”
– Amdahls Law
• Speedup is proportional to the amount of code that can parallelized.
– “structure 80% of the code to reduce development time rather than run time. Focus run-time
reduction efforts on the 20% of the code that occupies the largest share of the run-time.”
[SSD]
– Hot-spot analysis on GSM revealed majority of the time spent is with exp() function.
• Software Quality Attributes
– Shortened timeframe for code development
– Extensibility
– Modifiability
– Flexibility
– Maintainability
– Readability
• Overhead
– Minimal impact on speed for optimized compilers.
– “by inlining the set and get routines the Intel compiler can deliver the same performance for
encapsulated data as for publicly accessible data in a derived type.” [Worth, 2008]

6/26/2014 P. Tripp 8
OO Fortran
• Objects and Classes
– An abstract data type
• Skeleton
– Code examples
• Public/Private/Protected
– Public: Global visibility
– Private: Only visibility is within the module, accessor functions (get, set)
– Protected: Visible outside, but only modifiable within module
• Type-bound procedures
– % syntax
• Encapsulation: Data and methods as a package
• Information Hiding: Private methods and data
• Inheritance: Child classes inherit data and methods of parent class
– Abstract types
• Polymorphism
– Static – determined at compile time
– Dynamic – determined at run time, e.g. passing a type as an argument (use the CLASS keyword)
– Unlimited Polymorphic Objects - Class(*)
• Function Overloading – Same name but different number and/or types of arguments
– Operator Overloading
• Function Overriding – Same name and signature, but the function of the child class is used
• Inquiry Functions
– result = SAME_TYPE_AS( A, B )
– result = EXTENDS_TYPE_OF( A, MOLD )

6/26/2014 P. Tripp 9
Java, C++, Fortran
• Multiple inheritance, (extends)
– C++ allows multiple inheritance
– Java sort of allows it with multiple “implements”
– Fortran, no multiple inheritance but can create hierarchies of classes
– Member functions or methods (Java, C++)
– Type-bound procedures (Fortran)
• Objects
– Everything is an object in Java, Object class is base class for everything
– C++, Java – Class
– Fortran – module Type, class and type keywords have different context
• Scope/Visibility
– Namespaces (C++)
– Packages (Java)
– Modules (Fortran)
• Abstract/Virtual
– C++ – virtual classes
– Java – abstract classes
– Fortran – abstract interfaces
• Constructors, destructors
– C++: Constructors and destructors must be implemented
– Java: Only constructors (new) required, auto garbage collection
– Fortran: Constructors/Destructors not required, but style may suggest it (final)
• Memory management
– C++, no auto garbage collection
– Java, automatic garbage collection
– Fortran, allocated or pointer variables automatically deallocated when out of scope?
6/26/2014 P. Tripp 10
ADT Skeleton
! Abstract datatype skeleton (adapted from [SSD])

module module_name

use some_module, only: some_kind

implicit none

private
integer, parameter :: some_kind=8
public :: sometype

type sometype
private
real (kind=some_kind) :: item

contains ! default is public


procedure aprocedure => specific_procedure
end type

! Define specific procedures


contains

subroutine specific_procedure (this, arga, argb)


class(sometype) :: this ! default first argument, passed automatically
real (kind=some_kind) :: arga, argb

! Do something, e.g.
this%item = arga * argb
end subroutine

end module
6/26/2014 P. Tripp 11
Example 1, Objects and Classes
module field_class_1

use kind_parameters, only: kind_phys


! use, intrinsic :: iso_fortran_env

implicit none

private

public :: field

type field

private

real (kind=kind_phys), allocatable, dimension (:) :: data ! Allocatable array to hold data
integer :: size_i ! size_i of the array

contains

! default is public
procedure :: set => set_field
procedure :: get => get_field
procedure :: print => print_field
end type

! Define specific procedures


contains

subroutine set_field(this, size_i, data)


class(field) :: this
integer size_i
real (kind=kind_phys), allocatable, dimension(:) :: data
integer stat

if (allocated(this%data)) then
deallocate(this%data)
end if

allocate(this%data(size_i), stat=stat)

! Build in quality, robustness


if (stat == 0) then
this%data = data
this%size_i=size(this%data)
else
print *, "ERROR in field_class%set_field : unable to allocate data"
end if
end subroutine
6/26/2014 P. Tripp 12
Example 1, Objects and Classes, page 2
subroutine get_field(this, data)
class(field) :: this
integer size_i
real (kind=kind_phys), dimension(:) :: data
data = this%data
end subroutine

subroutine print_field(this)
class(field) :: this
print *, "SIZE = ", this%size_i
print *, this%data
end subroutine
end module

The Test Driver


program test_driver
use kind_parameters, only: kind_phys
use field_class_1
type (field) :: flux
integer :: idim = 10
real (kind=kind_phys), allocatable, dimension(:) :: arr_data
allocate(arr_data(idim))

! some test data


arr_data=(/0., 1., 1., 2., 3., 5., 8., 13., 21., 34./)

call flux%set(idim, arr_data)


call flux%print()

arr_data=0.0
print *, "local: arr_data: ", arr_data

call flux%get(arr_data)
print *, "local: arr_data: ", arr_data

end program
6/26/2014 P. Tripp 13
Example 1 Output
SIZE = 10
0.000000000000000E+000 1.00000000000000 1.00000000000000
2.00000000000000 3.00000000000000 5.00000000000000
8.00000000000000 13.0000000000000 21.0000000000000
34.0000000000000

local: arr_data: 0.000000000000000E+000 0.000000000000000E+000


0.000000000000000E+000 0.000000000000000E+000 0.000000000000000E+000
0.000000000000000E+000 0.000000000000000E+000 0.000000000000000E+000
0.000000000000000E+000 0.000000000000000E+000

local: arr_data: 0.000000000000000E+000 1.00000000000000


1.00000000000000 2.00000000000000 3.00000000000000
5.00000000000000 8.00000000000000 13.0000000000000
21.0000000000000 34.0000000000000

6/26/2014 P. Tripp 14
Example 2, Using a pointer
module field_class_2
use kind_parameters, only: kind_phys
implicit none
private
public :: field

type field
private
real (kind=kind_phys), pointer, dimension (:) :: data => null() ! Pointer to array of data
integer :: size_i ! size_i of the array

contains
! default is public
procedure :: set => set_field
procedure :: get => get_field
procedure :: print => print_field
end type
contains
subroutine set_field(this, size_i, data)
class(field) :: this
integer size_i
real (kind=kind_phys), target, dimension(:) :: data
integer stat

this%data => data


this%size_i=size(data)
end subroutine

subroutine get_field(this, data)


class(field) :: this
integer size_i
real (kind=kind_phys), dimension(:) :: data
data = this%data
end subroutine

end module
6/26/2014 P. Tripp 15
Example 2 Output
SIZE = 10
0.000000000000000E+000 1.00000000000000 1.00000000000000
2.00000000000000 3.00000000000000 5.00000000000000
8.00000000000000 13.0000000000000 21.0000000000000
34.0000000000000

local: arr_data: 0.000000000000000E+000 0.000000000000000E+000


0.000000000000000E+000 0.000000000000000E+000 0.000000000000000E+000
0.000000000000000E+000 0.000000000000000E+000 0.000000000000000E+000
0.000000000000000E+000 0.000000000000000E+000

local: arr_data: 0.000000000000000E+000 0.000000000000000E+000


0.000000000000000E+000 0.000000000000000E+000 0.000000000000000E+000
0.000000000000000E+000 0.000000000000000E+000 0.000000000000000E+000
0.000000000000000E+000 0.000000000000000E+000

6/26/2014 P. Tripp 16
Example 3, Instantiating an object
(Not working correctly, doing something wrong but wanted to include it for an example anyways)

module field_class_3

implicit none

private
public :: field

type field

private

real (kind=kind_phys), allocatable, dimension (:) :: data ! Array of data


integer :: size_i ! size_i of the array

contains

! default is public
procedure :: set => set_field
procedure :: get => get_field
procedure :: print => print_field
end type

interface field
module procedure init_field
end interface

contains

type(field) function init_field(asize, adata)

integer :: asize
real (kind=kind_phys) :: adata
allocate (new_field%data(size_i))
end function

6/26/2014 P. Tripp 17
Example 3 Driver

program test_driver

use kind_parameters, only: kind_phys


use field_class_3

type (field) :: flux


type (field) :: tmp_flux

integer :: idimension = 10
real (kind=kind_phys), allocatable, dimension(:) :: arr_data

allocate(arr_data(idimension))

! some test data


arr_data=(/0., 1., 1., 2., 3., 5., 8., 13., 21., 34./)

! Create an instance of the object


flux = field(idimension, arr_data)

call flux%print()

arr_data=0.0
print *, "local: arr_data: ", arr_data

tmp_flux=flux%get()
call tmp_flux%print()

end program

6/26/2014 P. Tripp 18
Example 4, Inheritance and Function Overriding
module field_class_4

use field_class_1
use kind_parameters, only: kind_phys

implicit none
private
public :: field_meta

type, extends(field) :: field_meta


private
character (len=64) :: varname

contains
procedure :: set => set_field_meta
procedure :: get => get_field_meta
procedure :: print => print_field_meta
end type

contains

subroutine set_field_meta(this, size_i, data, varname)


class(field_meta) :: this
integer size_i
real (kind=kind_phys), allocatable, dimension(:) :: data
character (len=64), optional :: varname
integer stat
allocate(this%data(size_i), stat=stat)
this%data = data
this%size_i=size(this%data)
if (present(varname)) varname=this%varname
end subroutine

6/26/2014 P. Tripp 19
Example 5, Polymorphism
Source: [PG2]

subroutine init(sh)

! Unlimited polymorphic objects


class(*), target :: sh
class(*), pointer :: p

! class(shape) :: sh

p => sh

select type(p)
class is (shape)
… ! shape specific code
type is (integer)
… ! integer specific code
type is (real)
… ! real specific code
type is (complex)
… ! complex specific code
end select
end subroutine

6/26/2014 P. Tripp 20
Example 6, Operator Overloading
module some_module
type mytype
private

contains
procedure :: mytype_plus_mytype
generic, public :: operator(+) => mytype_plus_mytype

end type
contains

type(mytype) function mytype_plus_mytype(lhs, rhs)



end function
end module

program test

type(mytype) :: a
type(mytype) :: b
type(mytype) :: c

c=a+b

end program

6/26/2014 P. Tripp 21
Topics for Future Discussion
• Object-Oriented Analysis and Design
– Unified Modeling Language (UML)
– Design Patterns
• Identifying code for OO Re-engineering?
• Refactoring as a continual process in
maintenance and quality control

6/26/2014 P. Tripp 22
References and Recommended Reading
• [SSD] Scientific Software Design: The Object-Oriented Way, D. Rousan, J.
Xia, X. Xu, Cambridge University Press, 2011
• [MFE] Modern Fortran Explained, M. Metcalf, J. Reid, M. Cohen, Oxford
University Press, 2011
• Design Patterns: Elements of Reusable Object-Oriented Software,
E.Gamma, R. Helm, R. Johnson, J. Vlissides. 1994
• [Holcomb] Scientific Programming in Fortran 2003, A tutorial Including
Object-Oriented Programming, Katherine Holcomb 2012
• [Worth, 2008] State of the Art in Object Oriented Programming with
Fortran, D. J. Worth, 2008, RAL-TR-2008-002
• [PG1] Object-Oritented Programming in Fortran 2003 Part 1: Code
Reusability, Mark Leair, Technical News from the Portland Group , 2011
– https://www.pgroup.com/lit/articles/insider/v3n1a3.htm
• [PG2] Object-Oritented Programming in Fortran 2003 Part 2: Data
Polymorphism, Mark Leair, Technical News from the Portland Group , 2011
– https://www.pgroup.com/lit/articles/insider/v3n2a2.htm
6/26/2014 P. Tripp 23
Q&A and Discussion

6/26/2014 P. Tripp 24
6/26/2014 P. Tripp 25

Vous aimerez peut-être aussi