Difference between revisions of "Fortran"
From MohidWiki
(→Countries program) |
(→Countries program) |
||
| Line 329: | Line 329: | ||
pause | pause | ||
| + | |||
| + | call removeAtlas | ||
end program progtypes | end program progtypes | ||
| Line 351: | Line 353: | ||
public :: listarPaises | public :: listarPaises | ||
private :: novoAtlas | private :: novoAtlas | ||
| − | + | public :: removeAtlas | |
!Declaração de tipos e variáveis globais do módulo | !Declaração de tipos e variáveis globais do módulo | ||
Revision as of 15:01, 21 June 2010
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.
Contents
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
call removeAtlas
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
public :: 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