Personal tools

Fortran

From MohidWiki

Revision as of 15:58, 21 June 2010 by Guillaume (talk | contribs) (Countries program)
Jump to: navigation, search

Fortran95 is the language of choice to program in MOHID. Although a primitive form of language it proves to be the most efficient and performant in the area of scientific computing. Still widely used in numerical computation. Here's a crash course. Here's a free manual.

Examples

Hello World program

program helloworld

implicit none

write (*,*) "Hello world!"

end program helloworld


Hello world in a module

module modulehelloworld

implicit none

private

public :: showhelloworld

contains

subroutine showhelloworld()
        
        write(*,*) "Hello world!"

end subroutine showhelloworld

end module modulehelloworld


program helloworld

use modulehelloworld, only: showhelloworld

implicit none

call showhelloworld

end program helloworld


Subroutines & functions

Subroutine

program subfunc

implicit none

real :: a,b,c,root1,root2
logical :: realroots
write (*,*) "Hello world!"

write (*,10)
read (*,*) a,b,c

call solvit(a,b,c,root1,root2,realroots)
write (*,20) root1,root2

if (realroots) then
        write(*,*) 'Sorry, there are no real roots'
end if        

10 format('Enter 3 coefficients')
20 format('The roots are ', 2f12.6)
end program subfunc


subroutine solvit(a,b,c,root1,root2,realroots)

!Arguments
real ::a,b,c,root1,root2
logical :: realroots

!Locals
real :: test

test = b**2-4*a*c

if(test>=0.0) then
        root1 = (-b + sqrt(test))/(2.0*a)
        root2 = (-b - sqrt(test))/(2.0*a)
        realroots = .true.
else
        realroots = .false.        
end if

return
end subroutine solvit


Function

program subfunc

implicit none

real :: a,b,c,root1,root2,bigroot
logical :: realroots
write (*,*) "Hello world!"

write (*,10)
read (*,*) a,b,c

!call solvit(a,b,c,root1,root2,realroots)
!write (*,20) root1,root2
write(*,20) bigroot(a,b,c)

if (realroots) then
        write(*,*) 'Sorry, there are no real roots'
end if        

10 format('Enter 3 coefficients')
!20 format('The roots are ', 2f12.6)
20 format('The biggest root is ', f12.6)
end program subfunc


function bigroot(a,b,c)

!Arguments
real :: a,b,c,bigroot

!Local
real :: root1, root2, test

if(test>=0.0) then
        root1 = (-b + sqrt(test))/(2.0*a)
        root2 = (-b - sqrt(test))/(2.0*a)
        if (root1 .gt. root2) then
                bigroot = root1
        else
                bigroot = root2
        end if
else
        bigroot = -9.0e35
end if

return
end function bigroot


Interface procedure

Type variables & arrays

Variables

The variable declaration is as such


real            :: x, y
real, parameter :: z
integer         :: m, n
real(8)         :: w
character(len=30) :: frase


Arrays

real, dimension(3) :: vector
real, dimension(3,2) :: matriz3x2
integer, dimension(:)   :: vector-n
integer, dimension(:,:) :: matriz-mxn

!alocação do espaço em memória
allocate(vector-n(21))
allocate(matriz-mxn(4,5))
...
!Limpar a casa no final do programa
deallocate(vector-n)
deallocate(matriz-mxn)


Types

public :: T_Pais
type T_Pais
    character(len=128) :: nome
    character(len=128) :: capital
    integer            :: pop
end type T_Pais


Flow control

If

if (.not. associated(pais)) then
    allocate(pais)
else
    write(*,*) 'The country ', pais%nome, 'is already allocated.'
end if


Do

Loop that increments the counter.

do i=1,10
   write(*,*) 'Couting ',i
end do


Loop that increments the counter by two.

do i=1,21,2
   write(*,*) 'Counting pair ',i-1
end do


Loop that decrements the counter.

do i=20,1,-1
   write(*,*) 'Reverse counting of even ',i*2-1
end do


Case

Samples

Average program

program average
 
  ! Read in some numbers and take the average
  ! As written, if there are no data points, an average of zero is returned
  ! While this may not be desired behavior, it keeps this example simple
 
  implicit none
 
  real, dimension(:), allocatable :: points
  integer                         :: number_of_points
  real                            :: average_points=0., positive_average=0., negative_average=0.
 
  write (*,*) "Input number of points to average:"
  read  (*,*) number_of_points
 
  allocate (points(number_of_points))
 
  write (*,*) "Enter the points to average:"
  read  (*,*) points
 
  ! Take the average by summing points and dividing by number_of_points
  if (number_of_points > 0) average_points = sum(points) / number_of_points
 
  ! Now form average over positive and negative points only
  if (count(points > 0.) > 0) then
     positive_average = sum(points, points > 0.) / count(points > 0.)
  end if
  if (count(points < 0.) > 0) then
     negative_average = sum(points, points < 0.) / count(points < 0.)
  end if
 
  deallocate (points)
 
  ! Print result to terminal
  write (*,'(a,g12.4)') 'Average = ', average_points
  write (*,'(a,g12.4)') 'Average of positive points = ', positive_average
  write (*,'(a,g12.4)') 'Average of negative points = ', negative_average
 
end program average


Countries program

        program progtypes

        use modulePais

        implicit none

        type(T_Pais), pointer :: portugal

        !1a aula de tipos
        call lerPais(portugal)
        call escrevePais(portugal)
        write(*,*) ''

        !2a aula de tipos
        call novoPais
        write(*,*) ''

        call novoPais
        write(*,*) ''

        call listarPaises

        pause

        end program progtypes


        module modulePais

        implicit none

        private

        !Declaração do alcance das subrotinas
        !Rotinas que mexem com o tipo "T_Pais"
        public :: lerPais
        public :: escrevePais

        !Rotinas que mexem com o tipo "T_Atlas"
        public :: novoPais
        public :: listarPaises
        private :: novoAtlas
        private :: removeAtlas

        !Declaração de tipos e variáveis globais do módulo
        public :: StringLength
        integer, parameter  :: StringLength = 128
        
        public :: T_Pais
        type T_Pais
                character(len=StringLength) :: nome
                character(len=StringLength) :: capital
                integer                     :: pop
                real                        :: pib
        end type T_Pais

        public :: T_Atlas
        type T_Atlas
                type(T_Pais), pointer   :: pais
                type(T_Atlas), pointer   :: prim
                type(T_Atlas), pointer   :: prox
        end type T_Atlas

        type(T_Atlas), pointer          :: Me

        contains

        subroutine lerPais(pais)

                type(T_Pais), pointer :: pais

                allocate(pais)

                write(*,*) 'Insira o nome do pais'
                read(*,*) pais%nome

                write(*,*) 'Insira a sua capital'
                read(*,*) pais%capital

                write(*,*) 'Insira a população'
                read(*,*) pais%pop

                write(*,*) 'Insira o PIB em milhões de euros'
                read(*,*) pais%pib

        end subroutine lerPais

        subroutine escrevePais(pais)

                type(T_Pais), pointer :: pais

                write(*,*) 'O pais ', trim(pais%nome),','
                write(*,*) 'cuja capital eh ', trim(pais%capital),','
                write(*,*) 'tem uma populacao de', pais%pop,'habitantes'
                write(*,*) 'e um pib de ', pais%pib, 'milhoes de euros.'

        end subroutine escrevePais

        subroutine novoPais(neoPais)

                !Variável pais
                type(T_Pais), pointer, optional   :: neoPais
                type(T_Pais), pointer		  :: novPais
                type(T_Atlas), pointer            :: novAtlas

                !Um novo país é criado
                if (.not. present(neoPais)) then
                        call lerPais(novPais)
		else
			novPais => neoPais
                end if

                !Se o Atlas ainda não existe, então é criado
                if (.not. associated(Me)) then
                        call novoAtlas(Me, novPais, Me)
                !Senão o Atlas é incrementado
                else
                        call novoAtlas(novAtlas, novPais, Me%prim)
                        Me%prox => novAtlas
                        Me => Me%prox
                end if

        end subroutine novoPais

        subroutine novoAtlas(atlas, pais, prim)

                type(T_Atlas), pointer :: atlas, prim
                type(T_Pais), pointer :: pais

                allocate(atlas)
                atlas%pais => pais
                atlas%prim => prim
                nullify(atlas%prox)

        end subroutine novoAtlas

        subroutine removeAtlas
                
                type(T_Atlas), pointer :: oldAtlas               
                
                !Rewind the Me global variable
                Me => Me%prim

                !Loop through the Atlas items
                do while(associated(Me))
                        oldAtlas => Me
                        Me => Me%prox
                        deallocate(oldAtlas%pais)
                        deallocate(oldAtlas)
                end do

        end subroutine removeAtlas

        subroutine listarPaises

                type(T_Atlas), pointer :: atlas

                atlas => Me%prim

                do while(associated(atlas))
                        write(*,*) atlas%pais%nome
                        atlas => atlas%prox
                end do

        end subroutine

        end module modulePais


MOHID templates

Module

Program

Other languages