It is good practice to initialize all variables before they are used, including data members of derived types and allocatable arrays each time they are allocated. It is not safe to assume that they will always be set to zero. This is also important because the behavior may differ across compilers or architectures. Members of derived types can be initialized as follows:
type :: mytype
real(dp) :: value = 0.0_dp
integer :: n = 0
end type
Add comments while coding and use an automatic documentation generation program such as f90doc to generate HTML reference documentation to accompany your program.
kind attributeIn Fortran 90?, intrinsic types such as real and integer have a kind attribute which guarantees a specific precision and/or range. real*8 and counterparts should not be used (Chin, Worth, and Greenough, 2006, p. 5). double precision is no longer needed and can be thought of as a kind of real. The following example declares two real variables a and b which are guaranteed to have at least 15 significant digits of precision and an exponent rage of at least 307 (Lemmon and Schafer, 2005, p. 20–22):
integer, parameter :: dp = selected_real_kind(15, 307)
real(kind=dp) :: a
real(dp) :: b
One can also guarantee precision up to that of the machine-compiler-specific double precision real by using the kind function to get the kind of 1.d0:
integer, parameter :: dp = kind(1.d0)
Another possibility, suggested by Metcalf, et. al (2004, p. 71), ensures that the double and quad types are actually twice and four times the precision of a single:
integer, parameter :: &
sp = kind(1.0), &
dp = selected_real_kind(2*precision(1.0_sp)), &
qp = selected_real_kind(2*precision(1.0_dp))
In object-oriented languages such as C++, one can define classes that contain both data and methods which operate on that data. One can then create separate instances of the class, each with its own data. A method called from an instance of the class will work on the data held by that particular instance.
In Fortran, modules may contain data, but there is no notion of separate instances of a module. In order to obtain class-like behavior, one can use a combine a module, which contains the methods that operate on the class, with a derived type containing the data. There can be separate “instances” of the type in that we can allocate many variables of that type which can be passed as parameters to the methods contained in the module.
To illustrate these points consider a simple Circle class, based on an example in Akin (2003, p. 34):
module class_Circle
implicit none
private
public :: Circle, circle_area, circle_print
real :: pi = 3.1415926535897931d0 ! Class-wide private constant
type Circle
real :: radius
end type Circle
contains
function circle_area(this) result(area)
type(Circle), intent(in) :: this
real :: area
area = pi * this%radius**2
end function circle_area
subroutine circle_print(this)
type(Circle), intent(in) :: this
real :: area
area = circle_area(this) ! Call the circle_area function
print *, 'Circle: r = ', this%radius, ' area = ', area
end subroutine circle_print
end module class_Circle
program circle_test
use class_Circle
implicit none
type(Circle) :: c ! Declare a variable of type Circle.
c = Circle(1.5) ! Use the implicit constructor, radius = 1.5.
call circle_print(c) ! Call a class subroutine
end program circle_test
New features in Fortran 2003 allow us to improve upon the object-oriented approach above by using type-bound procedures which allow us to write
a = c%area
call c%print
instead of the more verbose
a = circle_area(c)
call circle_print(c)
The program above, modified to use type-bound procedures, looks like this
module class_Circle
implicit none
private
real :: pi = 3.1415926535897931d0 ! Class-wide private constant
type, public :: Circle
real :: radius
contains
procedure :: area => circle_area
procedure :: print => circle_print
end type Circle
contains
function circle_area(this) result(area)
class(Circle), intent(in) :: this
real :: area
area = pi * this%radius**2
end function circle_area
subroutine circle_print(this)
class(Circle), intent(in) :: this
real :: area
area = this%area() ! Call the type-bound function
print *, 'Circle: r = ', this%radius, ' area = ', area
end subroutine circle_print
end module class_Circle
program circle_test
use class_Circle
implicit none
type(Circle) :: c ! Declare a variable of type Circle.
c = Circle(1.5) ! Use the implicit constructor, radius = 1.5.
call c%print ! Call the type-bound subroutine
end program circle_test
Note that we have changed the dummy parameters from type(Circle) to class(Circle). We can then call the class functions in an object-oriented fashion as a = c%area and call c%print, where the type is passed to the first argument of the functions circle_area and circle_print automatically. See Metcalf, Reid, and Cohen (2004, p. 279) for additional information.
Mathematical Libraries
Software Repositories
Free Compilers
Commercial Compilers
Utilities
Akin, Ed (2003): Object-Oriented Programming Via Fortran 90/95, Cambridge University Press (pdf).
Chin, L.S., D.J. Worth and C. Greenough (2006): Thoughts on using the Features of Fortran 95, Software Engineering Group Notes SEG-N-003 (html), (pdf)
Cohen, Malcolm (1999): Object orientation and Fortran 2002: part II, ACM SIGPLAN Fortran Forum, 18, 14–21.
Decyk, Viktor K., Charles D. Norton, and Boleslaw K. Szymanski: Object Oriented Fortran 90 Programming
Dubois, P. F. (1999): Ten good practices in scientific programming. Computing in Science and Engineering, 1:7–11.
Gray, M. G. and R. M. Roberts (1997): Object-based programming in Fortran 90 (PDF, 183K). Computers in Physics, 11:355–361.
Lemmon and Schafer (2005): Developing Statistical Software in Fortran 95, Springer.
Markus, Arjen (2006): Design patterns and Fortran 90/95, ACM SIGPLAN Fortran Forum, 25, 13–29.
Metcalf, Michael, John Reid, and Malcolm Cohen (2004): Fortran 95/2003 Explained, Oxford University Press.
Metcalf, Michael: Re: Type Declarations using kind, February 8, 2005 on comp.lang.fortran.