Difference between revisions of "Fortran"
From MohidWiki
(→Samples) |
|||
Line 299: | Line 299: | ||
end program average | end program average | ||
+ | </pre> | ||
+ | </htm> | ||
+ | |||
+ | ===Countries program=== | ||
+ | |||
+ | <htm> | ||
+ | <pre name="code" class="fortran"> | ||
+ | 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 | ||
</pre> | </pre> | ||
</htm> | </htm> |
Revision as of 14:56, 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
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