CPC782
Fundamentos de Programação
Introdução ao Fortran
aula 2/3
Renato N. Elias / Marcos A. D. Martins
material disponível em:
http://www.nacad.ufrj.br/~rnelias/fortran
Revisão da Aula 1/3 – parte 1
 Programas
– instruções utilizadas pelo computador para realizar uma tarefa
 Construindo programas (programando):
– Redação do programa em linguagem de ser humano utilizando uma
sintaxe própria (linguagem de programação)
– Tradução da linguagem de ser humano para a linguagem de máquina
(compilação)
– Empacotamento dos arquivos, em linguagem de máquina, que irão
compor as instruções que o computador irá executar (“linkedição”)
 Fortran: uma dentre várias linguagens de programação
existentes
–
–
–
–
Fácil de aprender
Excelente para realização de cálculos
Péssima para computação gráfica, internet, bancos de dados
Milhares de bibliotecas científicas desenvolvidas em Fortran e
disponíveis para uso
Revisão da Aula 1/3 – parte 2
 Fortran – elementos da linguagem:
– Definições básicas que definem a linguagem: formatos de arquivo,
estrutura de um programa, símbolos, caracteres de comentários e
continuação de linha, operações aritméticas e lógicas, tipos, declaração
de variáveis, comandos condicionais, comandos de repetição
– Formato fixo (F77) e livre (F90 e mais novos)
– Não é sensível a MAIÚSCULAS e minúsculas
– Variável: nome que identifica uma posição de memória onde contém
um valor armazenado
– Tipo: identifica o quanto uma variável ocupa na memória
– Tipos básicos em Fortran:
integer, real*4, real*8, character, logical, complex
– Comandos condicionais:
(if, then, else, elseif, endif), (select case, end select)
– Comandos de repetição:
do, do while, do infinito
Aula 2
 Comandos de Entrada e Saída (E/S)
– PRINT, WRITE, READ, FORMAT, OPEN, CLOSE
 Variáveis indexadas
– Declaração e dimensionamento de arrays (DIMENSION)
–
–
–
–
–
–
Terminologia (Posto, Extensão, Forma e Tamanho)
Iniciando e acessando arrays
Seleção de trechos de arrays e armazenamento na memória
Operações simples com arrays
Arrays em funções intrínsecas
Comandos condicionais para arrays (WHERE e FORALL)
– Funções específicas para operações com arrays
 Alocação dinâmica de memória
– ALLOCATABLE, ALLOCATE, DEALLOCATE e ALLOCATED
 Ponteiros em Fortran90
Comandos de Entrada e Saída (E/S)
 São comandos utilizados para informar os dados que o
programa irá processar (dados de entrada) e como o programa
irá mostrar os resultados para nós (dados de saída).
 Comandos básicos de entrada e saída:
– print: saída de dados (somente na tela)
– write: saída de dados (tela, arquivo, etc...)
– read: entrada de dados (tela, arquivo, etc...)
 Alguns comandos auxiliares de entrada e saída
– format: formatação de entrada e saída em ASCII
– open, close, inquiry, eof: comandos associados a
manipulação de arquivos
Unidades de entrada e saída (E/S)
 As unidades de entrada e saída são as fontes de dados
utilizados pelo Fortran;
 As unidades mais comumente usadas em Fortran são: tela
(saída), teclado (entrada) e arquivo (entrada e saída);
 Internamente o Fortran identifica uma unidade de E/S através
de um número inteiro;
 As unidades 0, 5 e 6 são reservadas para uso interno do
Fortran como unidades de erro, saída e entrada padrão;
 O símbolo * (asterisco) pode ser utilizado em substituição aos
números que identificam as unidades padrão (0,5 e 6)
Comandos de entrada/saída de dados
 PRINT: comando exclusivo para SAÍDA de dados na TELA
– Forma geral:
print *, <lista de variáveis>
ou
print <formato>, <lista de variáveis>
– Exemplo:
print *, ‘O resultado do calculo e:’
print ‘(3F10.3)’, x, y, z
print 100, x, y, z
100 format(3F10.3)
! FORMAT?! O que isso faz? 
Formatação de entrada/saída
 A formatação de dados permite que especifiquemos como os dados
serão escritos ou lidos de uma unidade de E/S (número de casas
decimais, tamanho máximo ocupado pelo dados, quebras de linhas,
etc...)
 A formatação de E/S é feita através do comando FORMAT ou aplicandose a máscara de formatação diretamente ao comando de E/S utilizado
 FORMAT: forma geral do comando
<rótulo> format(<máscara de formatação>)
<rótulo>: número inteiro inserido nas 5 primeiras colunas do arquivo-fonte e
que identifica o rótulo
<máscara de formatação>: Texto que especifica como o dado será lido/escrito
OBS: o comando format pode ser localizado em qualquer parte do corpo do
programa
Máscaras de formatação
 A : Texto
FORMATO
A6
A6
A6
A6
A6
A6
A6
A6
ENTRADA
PAGE^#
PAGE^#
PAGE^#
PAGE^#
PAGE^#
PAGE^#
PAGE^#
PAGE^#
VALOR
#
E^#
PAGE^#
PAGE^#^^
#
^#
GE^#
PAGE^#^^
TIPO DE DADO
CHARACTER(LEN=1)
CHARACTER(LEN=3)
CHARACTER(LEN=6)
CHARACTER(LEN=8)
LOGICAL(1)
INTEGER(2)
REAL(4)
REAL(8)
Máscaras de formatação
 i : inteiro
FORMATO
I4
I3
I9
ENTRADA
2788
-26
^^^^^^312
FORMATO
I3
I4
I4
I5
I2
I3
I7
I4.0
I4.2
I4.4
VALOR
284
-284
0
174
3244
-473
29.812
0
1
1
VALOR
2788
-26
312
SAÍDA
284
-284
^^^0
^^174
**
***
An error; the decimal point is invalid
^^^^
^^01
0001
Máscaras de formatação
 f: Real de precisão simples
FORMATO
F8.5
F8.5
F8.5
F5.2
ENTRADA
123456789
-1234.567
24.77E+2
1234567.89
FORMATO
F8.5
F9.3
F2.1
F10.4
F5.2
F5.2
VALOR
2.3547188
8789.7361
51.44
-23.24352
325.013
-.2
VALOR
123.45678
-1234.56
2477.0
123.45
SAÍDA
^2.35472
^8789.736
**
^^-23.2435
******
-0.20
Máscaras de formatação
 d,e: Real de precisão simples e dupla em notação exponencial
FORMATO
E9.3
E12.4
E15.3
E12.5
BZ,D10.2
D10.2
D15.3
FORMATO
E11.2
E11.5
E12.3
E10.3
E5.3
E14.5E4
E13.3E6
D14.3
D23.12
D9.6
ENTRADA
734.432E3
^^1022.43E
52.3759663^^^^^
210.5271D+10¹
12345^^^^^
^^123.45^^
367.4981763D+04
VALOR
475867.222
475867.222
0.00069
-0.5555
56.12
-1.001
0.000123
0.0363
5413.87625793
1.2
VALOR
734432.0
1022.43E-6
52.3759663
210.5271E10
12345000.0D0
123.45D0
3.674981763D+06
SAÍDA
^^^0.48E+06
0.47587E+06
^^^0.690E
-0.556E+00
*****
-0.10010E+0001
0.123E-000003
^^^^^0.363D-01
^^^^^0.541387625793D+04
*********
Máscaras de formatação
 ES: Notação científica
FORMATO
ES11.3
ES11.3
ES12.3
ES12.3
ENTRADA
^^5.321E+00
-6.000E-03
^^^3.150E-03
^^^3.829E+03
VALOR
5.32100
-.60000
.00315
3829.0
FORMATO
ES11.2
ES11.5
ES12.3
ES10.3
ES11.2
VALOR
473214.356
473214.356
0.00069
-0.5555
0.0
SAÍDA
^^^4.73E+05
4.73214E+05
^^^6.900E-04
-5.555E-01
^0.000E+00
Máscaras de formatação
 EN: Notação de engenharia
FORMATO
EN11.3
EN11.3
EN12.3
EN12.3
ENTRADA
^^5.321E+00
-600.00E-03
^^^3.150E-03
^^^3.829E+03
VALOR
5.32100
-.60000
.00315
3829.0
FORMATO
EN11.2
EN11.5
EN12.3
EN10.3
EN11.2
VALOR
475867.222
475867.222
0.00069
-0.5555
0.0
SAÍDA
^475.87E+03
***********
^690.000E-06
**********
^000.00E-03
Máscaras de formatação
 G: Formato geral
VALOR
0.01234567
-0.12345678
1.23456789
12.34567890
123.45678901
-1234.56789012
12345.67890123
123456.78901234
-1234567.89012345
FORMATO
G13.6
G13.6
G13.6
G13.6
G13.6
G13.6
G13.6
G13.6
G13.6
SAIDA COM G
^0.123457E-01
-0.123457^^^^
^^1.23457^^^^
^^12.3457^^^^
^^123.457^^^^
^-1234.57^^^^
^^12345.7^^^^
^^123457.^^^^
-0.123457E+07
FORMATO
F13.6
F13.6
F13.6
F13.6
F13.6
F13.6
F13.6
F13.6
F13.6
SAÍDA COM F
^^^^^0.012346
^^^^-0.123457
^^^^^1.234568
^^^^12.345679
^^^123.456789
^-1234.567890
^12345.678901
123456.789012
*************
Máscaras de formatação
 B: Formato binário
FORMATO
B4
B1
B2
ENTRADA
1001
1
0
VALOR
9
1
0
FORMATO
B4
B2
VALOR
9
0
SAÍDA
1001
^0
 Outros formatos importantes
X: espaços em branco
/: quebra de linha
\: continuação de linha
Comando de escrita (saída)
 WRITE: comando utilizado para gravar um saída na unidade
especificada com formatação ou não. O comando write possui vários
parâmetros de controle, porém, neste curso só trataremos de sua
forma mais básica.
 Forma básica:
write(unit=<unidade de saida>,fmt=<formato>)
unit = número inteiro identificando a unidade
fmt = rótulo de formatação ou o símbolo * para formatação
livre
Exemplo:
write(*,99) 3.14
99 format(‘O valor de PI e:’,f5.2)
A seguinte saída será produzida na tela (saída padrão)
O valor de PI é: 3.14
Comando de leitura (entrada)
 READ: O comando read é utilizado para leitura de dados de uma
unidade de entrada e possui forma básica idêntica a do comando
write.
 Forma básica:
read(unit=<unidade de entrada>,fmt=<formato>)
unit = número inteiro identificando a unidade
fmt = rótulo de formatação ou o símbolo * para formatação
livre
Exemplo:
print *, ‘Entre com o valor de PI?’
read(*,*) pi
! O comando read direcionado para a unidade * fará com
! que o programa aguarde a entrada do valor pelo teclado
! (entrada padrão)
Entrada e saída de dados com arquivos
 OPEN: O comando open é usado para abrir um arquivo para que
ele possa ser usado em operações de leitura e/ou escrita.
Assim como os comandos write e read o comando open
possui várias opções, porém, só iremos tratar das suas opções
mais básicas aplicadas a arquivos do tipo ASCII.
 Forma geral:
open(unit=<unidade>, file=<arquivo>)
unit = número inteiro identificando a unidade
file = nome do arquivo que será aberto
Exemplo:
open(11,file=‘dados.txt’)
Entrada e saída de dados com arquivos
 CLOSE: O comando close, ao contrário do comando open, é
usado para fechar um arquivo.
 Forma geral:
close(unit=<unidade>)
 Curiosidades:
– O Fortran é uma linguagem muito pouco exigente, ou seja, ela faz de
tudo para que os pequenos erros não interfiram na execução normal do
programa. Em Fortran se uma unidade for inadvertidamente deixada
aberta a própria linguagem se encarrega de fechá-la ao término do
programa. O programador pode inclusive escrever em um arquivo que
não foi previamente aberto. Neste caso, um arquivo com o nome
fort.unit (onde unit é o numero da unidade usada na escrita) será
aberto para manter o programa funcionando.
Está na hora de praticarmos
 Fazer um programa que grave no arquivo fatorial.txt o fatorial dos
números de 1 a 10
 Avaliando o problema:
– Como eu calculo o fatorial de um número? Normalmente é mais fácil pensarmos
em um exemplo simples do que em uma fórmula geral, então, tomemos como
exemplo o fatorial de 3
3! = 3 x 2 x 1
! tem cara de laço de repetição (loop)...
– A variável de controle do loop pode ser usada nos cálculos (sem que seu valor
seja alterado)
– Precisarei calcular o fatorial de 10 números, ou seja, precisarei calcular o fatorial
10 vezes (tem cara de outro loop).
– O fatorial por definição será um número inteiro positivo
1-fatorial
Programa fatorial
program fatorial
implicit none
integer :: NumberOfFactorials = 10
integer :: i, j, TemporaryFactorial
open(7,file=‘fatorial.txt’)
! Este laço faz com que sejam calculados os fatoriais de 1 a NumberOfFactorial
do i=1,NumberOfFactorials
! A variavel abaixo armazena e acumula o resultado do fatorial
TemporaryFactorial = 1
! Este laço calcula do fatorial de i
do j=1,i
TemporaryFactorial = TemporaryFactorial*j
enddo
write(7,9) i, TemporaryFactorial
write(*,9) i, TemporaryFactorial
enddo
close(7)
9 format(‘O fatorial de ‘, I3, ‘ e: ‘, I10)
end program
Variáveis indexadas estáticas
(desvendando os poderes do Fortran 9x)
 Variáveis indexadas ou arrays:
– As variáveis indexadas ou simplesmente arrays são estruturas
utilizadas para o armazenamento de dados do mesmo tipo em áreas
contíguas de memória permitindo que os dados sejam acessados
diretamente através de seu índice.
Os arrays estáticos ocupam
um espaço fixo na memória
durante TODA a execução
do programa
Declaração e dimensionamento de arrays:
 Em Fortran, a declaração de um array segue as mesmas regras de
declaração de qualquer outra variável acrescentando-se (ou não) o
comando dimension para especificação do numero de dimensões,
limites ou tamanho do array :
integer, dimension(10) :: idx
! Forma 1 – usando dimension
integer :: idx(10) ! Forma 2 – diretamente sem usar dimension
! Forma 3 – declaração e dimensionamento separados
integer idx
dimension idx(10)
! IMPORTANTE: Array com limite inferior diferente de 1
integer, dimension(-9:9) :: idx !  Qual o tamanho de idx?
! idx armazenara 19 valores inteiros
Declarando arrays em Fortran
 Mais exemplos:
! Declarando arrays que não iniciam em 1
logical :: used(-1:9) ! Armazena 11 valores lógicos
! Um array de character
character column(5)*25 ! 5 strings de 25 caracteres cada
! Com o uso de parametros constantes
integer, parameter :: nsize = 100 ! COMANDO NOVO: PARAMETER
real*8 MeuArray(nsize)
OBS: Os parametros designam valores constantes para o programa, ou seja,
eles nunca poderão ser modificados em tempo de execução.
Note que em qualquer lugar do programa onde estiver escrito nsize subentende-se que está escrito o seu valor: 100.
Variáveis indexadas - Terminologia
 Posto:
– O posto (rank) de uma matriz é o número de dimensões da mesma. Assim, um
escalar tem posto 0, um vetor tem posto 1 e uma matriz tem posto maior ou
igual a 2
 Extensão:
– A extensão (extent) de uma matriz se refere a uma dimensão em particular e é o
número de componentes naquela dimensão
 Forma:
– A forma (shape) de uma matriz é um vetor cujos componentes são a extensão
de cada dimensão da matriz.
 Tamanho:
– O tamanho (size) de uma matriz é o número de elementos que compõe a matriz.
Este número pode ser zero, em cujo caso denomina-se matriz nula
Terminologia na prática
real*4, dimension(-3:4,7) :: a
 A matriz “a” declarada acima possui:
– Posto 2
– Extensão 8 e 7
– Forma (/8,7/) ! Os símbolos “/” são arrays constructors
– Tamanho 56
a(-3,1) a(-3,2) a(-3,3) a(-3,4) a(-3,5) a(-3,6) a(-3,7)
a(-2,1) a(-2,2) a(-2,3) a(-2,4) a(-2,5) a(-2,6) a(-2,7)
a(-1,1) a(-1,2) a(-1,3) a(-1,4) a(-1,5) a(-1,6) a(-1,7)
a( 0,1) a( 0,2) a( 0,3) a( 0,4) a( 0,5) a( 0,6) a( 0,7)
a( 1,1) a( 1,2) a( 1,3) a( 1,4) a( 1,5) a( 1,6) a( 1,7)
a( 2,1) a( 2,2) a( 2,3) a( 2,4) a( 2,5) a( 2,6) a( 2,7)
a( 3,1) a( 3,2) a( 3,3) a( 3,4) a( 3,5) a( 3,6) a( 3,7)
a( 4,1) a( 4,2) a( 4,3) a( 4,4) a( 4,5) a( 4,6) a( 4,7)
Iniciando Arrays
! 1) Na declaração e com valor constante
integer, dimension(-10,10) :: idx = 1
! 2) Na declaração e com loop implicito
integer :: idx(10) = (/(2*i,i=1,10)/)
! 3) Na declaração e com valores explicitamente indicados
integer :: idx(3) = (/-1,-2,-3/)
! 4) No corpo do programa, atribuindo valores diretamente:
idx = 3 ! ou idx(:) = 3
! 5) No corpo do programa com um loop explicito (forma F77)
do i=-10,10
idx(i) = i
enddo
! 6) No corpo do programa usando a seleção de alguns trechos
idx(-10:1) = 99
idx(0)
= 0
idx(1:10) = -99
Iniciando Arrays (continuação)
! 7) Com dados lidos de algum lugar (arquivo ou tela) em loop explicito
do i=-10,10
read(iunit,*) idx(i)
enddo
! 8) Com dados lidos de algum lugar (arquivo ou tela) em loop implicito
read(iunit,*) (idx(i),i=-10,10)
! 9) Com dados lidos de algum lugar (arquivo ou tela) diretamente
read(iunit,*) idx(:) ! ou simplesmente “idx” sem o (:)
! 10) Com dados lidos de algum lugar (arquivo ou tela) por trechos
read(iunit,*) idx(-10:0)
read(iunit,*) idx(0)
read(iunit,*) idx(1:10)
! 11) Atribuicao em arrays de dimensoes e formas diferentes
real*4, dimension(15,5) :: a1 = 10.0
real*4, dimension(
5) :: a2
! a2 recebera o conteudo das linhas 1 a 5 da coluna 2 de a1
a2(:) = a1(1:5,2)
2-IniciandoArrays
Iniciação de arrays (continuação)
Suponha a seguinte matriz:
Qual das formas abaixo seria correta para iniciá-la durante sua declaração?
integer, dimension(2,3) :: idx = (/1,2,3,1,2,3/)
integer, dimension(2,3) :: idx = (/1,1,2,2,3,3/)
RESPOSTA:
A segunda opção é a correta pois o Fortran armazena os arrays por coluna,
vejam no próximo slide o que isso significa na prática...
Como o Fortran armazena arrays na memória?
C/C++ e Pascal (por linhas)
Fortran (por colunas)
idx(1,1) idx(1,2) idx(1,3)
idx(1,1)
idx(1,2)
idx(1,3)
idx(2,1)
idx(2,2)
idx(2,3)
idx(2,1) idx(2,2) idx(2,3)
integer :: idx(2,3) = (/1,1,2,2,3,3/)
integer :: idx(2,3) = (/1,2,3,1,2,3/)
Acessando matrizes eficientemente em Fortran
Qual seria a forma mais adequada de acessar a matriz “idx”?
do i=1,2
do j=1,3
do j=1,3
do i=1,2
idx(i,j) = j
idx(i,j) = j
OU
enddo
enddo
enddo
enddo
idx(1,1)
idx(1,2)
idx(1,3)
idx(1,1)
idx(1,2)
idx(1,3)
idx(2,1)
idx(2,2)
idx(2,3)
idx(2,1)
idx(2,2)
idx(2,3)
Acessando dados em um array
real*8 :: a(6,6)
a(2,3)
a(:,:)
a(2,:)
a(:,3)
a(1:3,2)
a(2,3:5)
!
!
!
!
!
!
Elemento na linha 2 e coluna 3
Matriz inteira
Todos os elementos da linha 2
Todos os elementos da coluna 3
3 primeiras linhas da coluna 2
a(2,3), a(2,4), a(2,5)
a(1:6:2,1:6:2) ! a(1,1), a(1,3), a(1,5)
! a(3,1), a(3,3), a(3,5)
! a(5,1), a(5,3), a(5,5)
Acessando dados em um array
a(2,3)
a(:,:)
1,1 1,2 1,3 1,4 1,5 1,6
a(2,:)
2,1 2,2 2,3 2,4 2,5 2,6
a(:,3)
a(1:3,2)
a(2,3:5)
a(1:6:2,1:6:2)
3,1 3,2 3,3 3,4 3,5 3,6
4,1 4,2 4,3 4,4 4,5 4,6
5,1 5,2 5,3 5,4 5,5 5,6
6,1 6,2 6,3 6,4 6,5 6,6
Operações com arrays (Fortran90)
 O Fortran90 tornou possível que as operações com arrays, que
anteriormente só eram possíveis através do uso de laços, passassem
a ser efetuadas exatamente da mesma forma como se faz para uma
variável escalar.
real*8, dimension(10,10) :: array1 = 1.d0
real*8, dimension(10,10) :: array2 = 3.3d0
real*8, dimension(10,10) :: array3
! Em F90 podemos fazer:
array3(:,:) = array1(:,:)+array2(:,:)
! ou simplesmente: array3 = array1+array2
! O uso do (:,:) é desnecessário mas aconselhável pois ajuda
! a distinguir o que é um array do que é um escalar
! Em F77 teríamos de fazer:
do i=1,10
do j=1,10
array3(j,i) = array1(j,i)+array2(j,i)
enddo
enddo
Programa-exemplo: Subtraindo 2 arrays
program SomaMatrizes
integer, parameter :: n=3
real*8 :: mat1(n,n) = 1.5d0
real*8 :: mat2(n,n) = 0.5d0
real*8 :: mat3(n,n)
! subtrai mat2 de mat1 e armazena o resultado em mat3
mat3 = mat1+mat2
do i=1,n
print *, '[', mat3(i,1:n), ' ]'
enddo
end program
3-SomaMatriz
arrays e Funções intrínsecas (Fortran90)
 As funções intrínsecas do Fortran90 operam em
arrays da mesma forma que operam em escalares
real*8, dimension(3,3) :: array1 = -1.d0
array1 = dabs(array1)
! array1 fica igual a 1.d0
array1 = array1 - 2.d0 ! array1 volta a ser -1.d0
array1 = dacos(array1) ! array1 fica igual a PI
4-FuncoesIntrinsecas
Comandos condicionais específicos para arrays
 O Fortran90 assimilou alguns comandos
condicionais específicos para tratamento de arrays,
são eles: where e forall
 WHERE: Aplica uma operação lógica a todo o
conteúdo de um array simultaneamente.
integer, dimension(5) :: iarray = (1,0,-1,3,2)
logical, dimension(5) :: flag = .false.
teste: where (iarray<0)
flag = .true.
elsewhere
flag = .false.
end where teste
! como o vetor flag foi previamente iniciado poderiamos fazer:
where(iarray<0) flag =.true. ! flag resultara em (F,F,T,F,F)
Comandos condicionais específicos para arrays
 FORALL: Este comando foi incluído ao padrão
Fortran95 e é uma generalização do comando where
real, dimension(10,10) :: array = 0.0
forall (i=1:5)
array(i,i) = 1.0
end forall
! Repare que o exemplo acima poderia ser feito com a atribuição direta:
array(1:5,1:5)=1.0
! Entao vamos fazer algo mais ilustrativo...
real, dimension(3,3) :: array = (/1.,-.5,2.,0.,3.5,.7,1.3,0.,-1.4/)
array = sqrt(array)
! * * * DARA ERRO DE EXECUCAO DEVIDO AOS VALORES NEGATIVOS * * *
! Vamos usar o comando FORALL para realizar a inversao com segurança
FORALL (i=1:3,j=1:3, array(i,j) > 0.)
array(i,j) = sqrt(array(i,j))
END FORALL
obs: geralmente o comando FORALL pode ser escrito na forma de uma série de laços DO
associados com blocos condicionais IF
5-FORALL
Funções específicas para arrays (Fortran90)
maxval
minval
minloc
maxloc
sum
count
all
any
reshape
transpose
matmul
dot_product
pack
unpack
: Retorna o maior valor
: Retorna o menor valor
: Retorna a posição do menor valor
: Retorna a posição do maior valor
: Retorna o somatório de todos os termos
: Retorna o número de valores verdadeiros
: Verifica se todos os valores de um array são verdadeiros
: Verifica a existência de qualquer valor verdadeiro em um array
: Modifica a forma (shape) de um array
: Transpõe um array de posto (rank) 2
: Multiplicação de matrizes
: produto escalar de 2 arrays de posto 1
: Extrai elementos de um array baseado em uma máscara e retorna o resultado
em um array de posto 1
: Injeta elementos de um array de posto 1 em um array de posto superior
baseado em uma máscara
Programa-exemplo: Usando funções de arrays
program ArrayFunctions
integer, parameter
:: n = 9
real*4 , dimension(n) :: a = (/-.84,.95,.53,-.48,-.79,.98,-.51,.49,-.75/)
logical, dimension(n) :: b = .false.
vmin = minval(a)
vmax = maxval(a)
asum = sum(a)
where (a.lt.0.0)
nlt1 = count(b)
!
!
!
b
!
extrai o valor minimo de a
extrai o valor maximo de a
soma todos os valores de a
= .true. ! atribui verdadeiro as posicoes de b onde a<0
conta quantos valores de "a" sao < 0)
write(*,'(1x,a4,7x,a5)') 'a', 'a<0.0‘
write(*,'(20("="))')
write(*,5) ((a(i),b(i)),i=1,n)
write(*,'(20("="))')
write(*,*) ' valor minimo:', vmin, ' na posicao:', minloc(a)
write(*,*) ' valor maximo:', vmax, ' na posicao:', maxloc(a)
write(*,*) ' Soma de todos os valores do vetor a:', asum
write(*,*) ' Numero de valores de a < 0.0:', nlt1
5 format('[',F4.2, '] --> [',l5, ']')
end program
6-ArrayFunctions
Mais um programa-exemplo para praticarmos...
 Dadas as seguintes matrizes e vetores:
 Utilizar funções intrínsecas matmul, transpose e
dot_product do F90 para realizar as seguintes operações:
 OBS: Não esquecer da compatibilidade de dimensões...
program MultiplicaMatrizes
real*4 :: A(2,3), tmp(2,3), B(3,2)
real*4 :: C(2,2) ! armazenara o resultado de AxB
real*4 :: d( 2) = (/0.3,0.9/)
real*4 :: e( 2) ! armazenara o resultado de Cxd
data a / 1.3, 2.1, -1.1, 0.2, -0.5, -0.9/
data tmp /-1.4, 0.3, 0.5, 0.0, -1.2, 3.2/
C
e
dot
b
=
=
=
=
matmul(A, B) ! Para a multiplicacao ser possivel temos de transpor B
matmul(C,d)
dot_product(e,d)
transpose(tmp)
! ESTA PARTE SO FOI INSERIDA PARA IMPRESSAO DOS RESULTADOS...
write(*,1) A(1,1:3),B(1,1:2),C(1,1:2)
write(*,2) A(2,1:3),B(2,1:2),C(2,1:2)
write(*,3)
B(3,1:2)
write(*,4) C(1,1),C(1,2),d(1),e(1)
write(*,5) C(2,1),C(2,2),d(2),e(2)
write(*,6) e(1),e(2),d(1),dot
write(*,7)
d(2)
1 format(/"PRODUTO MATRICIAL DE A x B^T",//&
"[", 3(1x,f5.2,1x), "]
[", 2(1x,f5.2,1x), "]
[", 2(1x,f5.2,1x), "]")
2 format( "[", 3(1x,f5.2,1x), "] X [", 2(1x,f5.2,1x), "] = [", 2(1x,f5.2,1x), "]")
3 format( 1x,
21x , "
[", 2(1x,f5.2,1x), "]"/)
4 format(/"PRODUTO ENTRE A MATRIZ C E O VETOR e",//&
"[", 2(1x,f5.2,1x), "] X [", (1x,f5.2,1x), "] = [", (1x,f5.2,1x), "]" )
5 format( "[", 2(1x,f5.2,1x), "]
[", (1x,f5.2,1x), "]
[", (1x,f5.2,1x), "]"/ )
6 format(/"PRODUTO ESCALAR ENTRE OS VETORES e e d",//&
"[",2(1x,f5.2,1x),"] X [", (1x,f5.2,1x), "] = ", (1x,f5.2) )
7 format( 1x,
14x,"
[", (1x,f5.2,1x), "]
"
)
end program
7-MultiplicaMatrizes
Exercício proposto para a próxima aula
 Fazer um programa que calcule as coordenadas dos nós de uma
grade e grave as coordenadas obtidas em um arquivo de texto.

O programa deverá conter as seguintes linhas iniciais:
program Grade
real*8, parameter :: xmin
ymin
xmax
ymax
dx
dy
= 0.d0 &
= 0.d0 &
= 10.d0 &
= 10.d0 &
= 2.d0 &
= 2.d0
real*8, allocatable(:,:) :: xyz
! Desenvolva o algoritmo aqui
End program
Alocação Dinâmica de Memória
 A alocação dinâmica de memória foi um grande avanço no Fortran a partir do padrão
Fortran90 pois permitiu um uso mais racional da memória do sistema;
 A alocação dinâmica de memória permite ao programador decidir pela requisição de
uma quantidade de memória para uso em arrays somente quando esta se faz,
realmente, necessária;
 Tal recurso também viabilizou a compilação e execução de programas; que antes se
utilizavam de alocação estática e que não eram viáveis devido ao excessivo
consumo de memória; em computadores com disponibilidade de recursos limitado;
 A tarefa de gerenciamento de memória em Fortran77 era árdua e normalmente feita
através da manipulação explícita de grandes áreas de memória estaticamente
alocadas. Tais áreas eram mutuamente utilizadas por arrays de tipos distintos e
frequentemente era necessária alguma operação de manutenção dos espaços
vazios deixados. Além disso, o programador tinha de se certificar que a alocação
estática assumida era suficiente para o programa rodar.
 Uma outra limitação da alocação estática era a necessidade de recompilação do
programa a cada vez que a quantidade de memória requerida fosse diferente
daquela existente no programa. Isso pode parecer algo simples para programas
caseiros, mas imaginem um programa comercial tendo que ser recompilado
simplesmente porque necessitou de mais memória.
Alocação Dinâmica de Memória - Curiosidades
 Quanto representa a memória do computador para um programa? Para
respondermos a essa pergunta, vamos fazer algumas considerações:
– Suponha um computador com 1Gb de memória e que 100% desta memória
estará disponível para o nosso programa.
– Suponha também que o programa só utilizará números reais de precisão dupla,
então:
1 GBytes = 1024 MBytes = 10242 KBytes = 10243 Bytes
se 1 número real de dupla precisão consome 16 bytes, então:
10243/16 = 67108864 números reais de precisão dupla
Parece muito... mas o quanto isso equivale em relação a um array quadrado?
671088641/2 = 8192
CONCLUSÃO: O tamanho máximo do array, neste caso, seria:
real*8, dimension(8192,8192) :: array
 Obviamente que nosso programa não terá 100% da memória disponível
 É óbvio também que a alocação dinâmica não soluciona esse problema, mas
ajuda a amenizá-lo, pois a memória pode ser alocada e desalocada de acordo
com a necessidade do programa;
Alocação dinâmica e seus comandos
 Os comandos associados a alocação dinâmica de memória em
Fortran90 são:
– allocatable : específica que um array pode ser dinamicamente
alocado durante a execução do programa;
– allocate : comando utilizado no ato de alocação de memória;
– deallocate: comando utilizado para desalocar, e consequentemente,
devolver a memoria para o sistema;
– allocated : verifica se um array está alocado ou não
Declarando arrays alocáveis
 ALLOCATABLE: O comando allocatable é usado na
declaração de um array para designar que o mesmo poderá ser
dinâmicamente alocado durante a execução do programa.
! Forma 1: shape no nome da variavel
real*8, allocatable :: arr1(:,:)
! Forma 2: shape no comando allocatable
real*8, allocatable(:,:) :: arr1
! Forma 3: shape no comando dimension
real*8, allocatable, dimension(:,:) :: arr1
! As formas 2 e 3 são uteis quando se deseja declarar
! vários arrays alocaveis com o mesmo shape
Alocando arrays alocáveis
 ALLOCATE: O comando allocate efetivamente faz a requisição
de memória do sistema para que possa ser usada pelo array.
 Forma geral:
allocate( <lista de arrays>, stat=<istatus> )
<lista de arrays>: um ou mais arrays que se deseja alocar
juntamente com o tamanho do array.
<istatus> (OPCIONAL): Inteiro que retorna o valor 0 se o array
for alocado com sucesso e maior que zero em caso de erro
! Exemplo: alocando 3 vetores
real*8, allocatable(:) :: a, b, c
n = 1000
allocate(a(n),b(n),c(n),stat=ierr)
if (ierr.ne.0) print *, ‘Erro ‘, ierr, ‘ na alocacao de memoria’
Alocando arrays alocáveis
 Outros exemplos:
real*8, allocatable(:) :: arr1, arr2, arr3, arr4, arr5
print *, ‘ Entre com o tamanho do vetor arr1:’
read(*,*) n
allocate(arr1(n)) ! A partir desse ponto o vetor arr1 pode ser usado
allocate(arr2(1000)) ! alocacao com tamanho explicito
allocate(arr3(-100:100)) ! alocacao com indice inicial diferente de 1
allocate(arr4(10),stat=i) ! alocacao com verificacao
if (i.ne.0) print *, ‘ Algum problema ocorreu...’
allocate(arr5(0)) ! alocacao de array nulo.
Desalocando arrays previamente alocados
 DEALLOCATE: O comando Deallocate devolve a memória
utilizada por um array desalocando-o da memória.
 Forma geral:
deallocate( <lista de arrays>, stat=<istatus> )
<lista de arrays>: um ou mais arrays que se deseja alocar
<istatus> (OPCIONAL): Inteiro que retorna o valor 0 se o array
for alocado com sucesso e maior que zero em caso de erro
! Exemplo: desalocando 3 vetores simultaneamente
deallocate(a,b,c,stat=ierr)
if (ierr.eq.0) ‘ Arrays desalocados com sucesso...’
Verificando se um array está alocado
 ALLOCATED: O comando allocated é utilizado para verificar o
status de alocação de um array e é normalmente utilizado em
associação com o comando allocate. O comando retorna
.true. caso o array esteja alocado e .false. caso contário.
 Forma geral:
allocated(<array>)
! Exemplo: desalocando 3 vetores simultaneamente
real*8, allocatable(:,:) :: arr1
! so aloca a matriz arr1 caso ela NAO esteja alocada
if (.not.allocated(arr1)) allocate(arr1(-10:10))
! so desaloca a matriz arr1 caso ela esteja alocada
if (allocate(arr1)) deallocate(arr1)
Programa-exemplo
 Ler os dados do seguinte
arquivo e armazená-los em um
array devidamente alocado:
arquivo dados.txt
10 3
-3.13
-7.32
-7.44
-6.35
1.56
-0.54
7.05
-1.80
8.98
6.57
-8.31
-4.43
1.65
9.87
-5.45
-3.67
-9.53
-1.82
6.84
-2.82
0.25
9.86
3.53
4.24
2.84
5.73
-5.25
3.38
9.96
-0.84
program MemoryAllocation
real*4, allocatable :: a(:,:)
open(9,file="dados.txt")
read(9,*) n1, n2
if (.not.allocated(a)) then
allocate(a(n1,n2))
endif
do i=1,n1
read (9,*) (a(i,j),j=1,n2)
write(*,*) (a(i,j),j=1,n2)
enddo
close(9)
end program
8-Alocacao
Download

CPC782-Fortran-02-03 - nacad/coppe-ufrj