F90 – Resumão – IF – UFRGS
Resumo adaptado do original: (IF-UFRGS – Origem: Wikipédia, a enciclopédia livre.).
A linguagem de programação Fortran foi desenvolvida na década de 1950 e continua a ser usada hoje em dia. O nome tem como origens a expressão Formula Translator (ou Translation). A linguagem Fortran é principalmente usada em ciências da computação e análise numérica.
O primeiro compilador de Fortran foi desenvolvido para o IBM 704 em 1954-57. O compilador era optimizado, pois os autores acreditavam que ninguém iria usar essa linguagem se a sua prestação não fosse comparável com a da linguagem assembly A linguagem Fortran foi largamente adoptada por cientistas para a escrita de programas numericamente intensivos, o que encorajou os produtores de compiladores a escrever compiladores que gerassem código mais rápido. A inclusão de um tipo de dados de número complexo na linguagem tornou a linguagem Fortran particularmente apta para a computação científica. Ao longo dos tempos foram-se dando algumas revisões da linguagem. Entre elas encontram-se:
- FORTRAN IV (também conhecida como FORTRAN 66)
- FORTRAN 77,
- Fortran 90, 95, 2003 e 2008
Olá Mundo
Exemplos de código típico e mínimo para testar se o Fortran 90 está instalado (há um equivalente para cada linguagem)
print*,"olá Mundo" end
Editar
Essas duas linhas devem estar dentro de um arquivo (ex: ola.f90
), isto pode ser feito, no terminal linux por exemplo, com cat
linha por linha ou com um editor de texto qualquer, por exemplo no linux (vi
, nano
, emacs
, etc…)
Compilar
ola.f90
deve ser compilado, isto é traduzido de linguagem de Fortran (código fonte) para Assembler (código objeto ou de maquina) com a seguinte instrução:
> f90 ola.f90 -o ola
f90
invoca o compilador que faz a dita conversão
-o nome
é uma opção para nomear o código objeto (o programa executável) que no exemplo terá o nome ola
sem essa opção o executável criado terá o nome a.out
Rodar (executar)
ola.f90
não é executável, o computador não sabe o que fazer com ele, para isso o compilador traduz para una série de instruções que o computador sim sabe executar)
Para rodar fazemos:
> ./ola
./
é uma espécie de “comando” que deve ir na frente do nome do programa, necessário para que o intérprete de comandos (shell
) do terminal (ou sistema) linux saiba que o programa está no diretório de trabalho. Ao ser executado será exibido na tela do computador o seguinte:
olá Mundo
Desta forma completamos o pequeno ciclo de teste de existência de compilador Fortran 90 no computador que estamos usando e também de ter criado nosso primeiro código Fortran, compilado e executado o mesmo.
Código fonte do programa Olá Mundo
na versão padrão de formato-sintaxe: program ... end program
:
program ola print*,"olá Mundo" end program ola
Esta versão está no estilo Fortran 90, mesmo que com declarações opcionais como program nome
(terminada com end program
) é útil quando temos códigos longos com subrotinas (programas chamados pelo programa principal)
NOTA: A título de curiosidade, a única declaração obrigatória em Fortran é o comando end
.
Variáveis
Em linguagem de programação Variáveis são nomes definidos pelo programador onde podem ser armazenados números ou texto para uso posterior, sobre os quais podem ser feitas operações matemáticas, lógicas ou de manipulação de caracteres, e que também podem ser alteradas ou substituídas por novos conteúdos dependendo das instruções do programa.
Um programa é feito de constantes, variáveis e instruções de operações entre elas que definem uma tarefa a ser desenvolvida automaticamente pelo computador.
Em Fortran existem cinco tipos primitivos de variáveis:
Tipo Primitivo | Descrição |
---|---|
INTEGER | inteira, exemplo: 0, 1, 100 -34 |
REAL | real ou de ponto flutuante, exemplo: 3.14, -0.003, 3.2E-10, -5.02E100 (notação científica) |
COMPLEX | complexa, exemplo: \[(2,3 + 0i):\] (2.3, 0) \[(-i):\] (0, -1.0) \[(1,2 \times 10^{-5} – 1 \times 10^{-3}i):\] (1.2E-5, -0.001) |
LOGICAL | logica, exemplo: .TRUE. .FALSE. |
CHARACTER | caractere, exemplo: “ola”, “Entre seu nome!” |
No programa a definição de variáveis, ou declaração de variáveis, é feita no início e depois seguem as instruções de execução, veja a forma no seguinte exemplo:
Program test Integer I, J, K Real a, x, velocidade, tempo_0, Temp Logical prova Character*10 Titulo, nome ...
Bytes
Em computação byte é uma unidade de medida de armazenagem de informação, tipicamente de oito bits.
O bit, pela sua vez, é a mínima quantidade de informação possível, ou seja a menor unidade de medida de armazenagem de informação.
É onde podemos guardar apenas dois estados: 0 ou 1, sim ou não, etc.
Menos do que isso não é informação nenhuma, pois de fato, menos do que isso é um estado único que só pode ser sempre 0 ou 1 ou 2, mais é sempre igual, ele só pode tomar esse único valor e não mudar. Para ter informação então, no mínimo precisamos de dois estados: ora é um, ora é zero.
Por isso alguém chamou o bit de
a mínima diferença que faz a diferença.
A origem do bit é anterior ao computador, provavelmente de 1936, e o nome vem da contração de binary digit em inglês.
Os dígitos binários eram usados anteriormente e são apenas uma representação dos números como é a decimal, porem com base nas potências de 2. Assim, um número binário só pode estar composto de 0 e 1 (como um decimal esta só composto dos dígitos de 0 a 9).
Como exemplo, o numero binário (7 bits) 1001100 representa o número decimal 76.
1 | 0 | 0 | 1 | 1 | 0 | 0 |
---|---|---|---|---|---|---|
6 | 5 | 4 | 3 | 2 | 1 | 0 |
\[1 \times 2^6\] | \[0 \times 2^5\] | \[0 \times 2^4\] | \[1 \times 2^3\] | \[1 \times 2^2\] | \[0 \times 2^1\] | \[0 \times 2^0\] |
64 | 0 | 0 | 8 | 4 | 0 | 0 |
\[64+8+4 = 76\]
(Mais informações: Byte, Bit, Sistema binário )
Entrada e Saída
São as intruções READ
e WRITE
(ou PRINT
)
O READ
permite entrar dados antes ou durante a execução do programa.
Com o WRITE
podemos ver os resultado final da execução do código ou
acompanhar o desenvolvimento do mesmo.
Exemplos:
READ (*,*) I, Velocidade ... Write (*,*) Titulo, Temp
Esta última é equivalente a
PRINT*, Titulo, Temp
Todas essa representam entrada/saída pelo terminal. Entrada pelo Teclado. Saída na Tela.
São as chamadas entrada/saida padrão (standard)
Se quisermos ler ou gravar num arquivo:
OPEN (1, FILE="entrada.dat") READ(1,*) I, Velocidade OPEN (2, FILE="saida.dat") WRITE (2,*) Titulo, Temp CLOSE(1) CLOSE(2)
Operadores matemáticos
Operador | Função |
---|---|
. |
ponto decimal |
+ |
soma |
- |
subtração |
* |
multiplicação |
/ |
divisão |
** |
potência |
( ) |
parênteses |
Exemplo usando todas as operações
Equação:
\[z = 3,14 + \frac{\sqrt(x)}{3} – 4,3\times10^{-6}\]
z = 3.14+x**(1./2)/3 - 4.3E-6
Funções intrínsecas
Estas são as funções pré-definidas no compilador, entre as quais encontramos a mais comummente utilizadas como
raiz quadrada, trigonométricas, exponencial, etc:
A sintaxe de uso é o nome da função (geralmente três letras) e o argumento entre parêntesis:
raiz quadrada: sqrt
trigonométricas: sin, cos, tan, asin
exponencial: exp
logaritmo natural: log
módulo: abs
Exemplos:
a = sqrt(2.) b = sin(x) Pi = 2.*asin(1.) ! uma forma pratica de ter Pi como constante dentro de um programa y = (x - exp(-lam*x**2))/sqrt(x) z = x**(1./4.) ! Cuidado Teste com 1/4 em lugar de 1./4. e verá a grande diferença
Lista das funções intrínsecas mais comuns
Function Generic Specific Data type name name Arg Res Square root SQRT SQRT R R DSQRT D D CSQRT C C Exponential EXP EXP R R DEXP D D CEXP C C Natural LOG ALOG R R logarithm DLOG D D CLOG C C Common LOG10 ALOG10 R R logarithm DLOG10 D D Sine SIN SIN R R DSIN D D CSIN C C Cosine COS COS R R DCOS D D CCOS C C Tangent TAN TAN R R DTAN D D Arcsine ASIN ASIN R R DASIN D D Arccosine ACOS ACOS R R DCOS D D Arctangent ATAN ATAN R R DATAN D D ATAN2 ATAN2 2R R DATAN2 2D D Hyperbolic SINH SINH R R sine DSINH D D Hyperbolic COSH COSH R R cosine DCOSH D D Hyperbolic TANH TANH R R tangent DTANH D D
Ciclos ou laços (loop)
O grande lance dos programas (e do computador claro) é poder repetir operações sem ter que fazer uma de cada vez. Ou seja, utilizando a lógica para repetir tarefas que podem ter variações especificadas pelo programador dentro de um ciclo. Vejamos um exemplo usando a instrução do i =... end do
:
... do i = 1, 100 x = i * 0.1; y = x**2 print*, x,y end do ...
Nota
há diferenciação no shell
onde maiúsculas e minúsculas são diferentes (A é diferente de a) no Fortran elas são interpretadas da mesma forma (print = PRINT = PrInT=…).
Porem, é recomendado, por uma questão de estilo, usar preferencialmente minúsculas, reservando maiúsculas para aquilo que se quer chamar a atenção. O Ponto e vírgula `;` permite separar instruções diferentes em uma mesma linha
a interpretação do do
é a seguinte:
* comece com i=1
* faca o que esta entre `do ... end do`
* incremente i em 1 e veja se ultrapassou o valor máximo de i (no exemplo 100)
* se a resposta e não faca de novo com o novo valor de i
* o ciclo se repete até o valor máximo de i (= 100 no exemplo)
* quando i ultrapassa esse valor o laço é interrompido e o programa continua com a seguinte instrução depois de `end do`
Pergunta: Qual será no exemplo acima o valor da variável i finalizado o laço?
Exemplo: MRUA
Neste exemplo criamos um programa que gera a trajetória x(t) (unidimensional) de um objeto com aceleração constante:
\[x(t) = x_0 + v_0t + \frac{at^2}{2}\]
x(t) = x(0) + v(0)*t + 0.5*a*t²
program mrua implicit none ! isto nos obriga a declarar todas as variáveis que usaremos (recomendável) real :: x0, x, v0, a, t, dt ! variáveis reais (ponto flutuante) integer :: I, N print*, 'entre x0, v0, a, t, N' read*, x0, v0, a, t, N dt = t/N ! passo de tempo: definido pelo tempo máximo e o numero de pontos da trajetória t = 0 do i = 1, N x = x0 + v*t + 0.5*a*t**2 print*, t, x t = t + dt end do end program mrua
Desafio: este programa contém um erro que você deve consegue descobrir? Se sim comente no formulário no final do post. :o)
Controle de Fluxo (IF e CASE)
Possibilitam a escolha de rumos diferentes no programa dependendo de valores de variáveis ou condições entre elas.
IF … THEN …
A sintaxe é:
if (condição) then instruções executadas quando condição verdadeira else instruções executadas quando condição falsa end if
Para apreciar o poder dela primeiro vejamos:
Operadores relacionais e lógicos
Operador | análogo | Função |
---|---|---|
== |
.eq. |
igual |
/= |
.ne. |
diferente |
> |
.gt. |
maior |
>= |
.ge. |
maior ou igual |
< |
.lt. |
menor |
<= |
.le. |
menor ou igual |
.and. |
.and. |
E lógico |
.or. |
.or. |
OU lógico |
.not. |
.not. |
NÃO lógico |
Eles são usados junto com as instruções de controlo como o IF
(se), exemplo:
! exemplo de divisão a x b: ... read*, a, b if (b /= 0) then c = a/b else stop 'b=0' end if print*, 'a/b=', c ...
CASE
Este serve para quando temos muitas opções ou escolhas para tomar rumos diferentes no programa. Vejamos a sintaxe diretamente no exemplo:
Select Case (J) Case(1) print*, "caso 1" Case(2) print*, "caso 2" Case (4:10) print*, "caso 4-10" .... Case Default print*, "não foi nenhum dos casos contemplados" End Select
Ciclo infinito (Do … end Do)
Se não especificamos com um índice o numero de vezes que o laço deve ser executado este será executado infinitamente. Exemplo:
do print*, "seja aproximadamente exato, não exatamente errado!" enddo
o programa ficará rodando infinitamente, fazendo a frase ser escrita na tela em um laço infinito, que só poderá ser cancelado teclando CTRL C
no terminal.
Para que um ciclo infinito tenha utilidade prática, em algum momento (lógico) do programa é preciso lançar mão do comando exit
, como no exemplo abaixo:
Do Print*, "Digite o número 1 ou 2" Read*, num Select Case (num) Case (1) Print*, "Você digitou 1" Exit Case (2) Print*, "Você digitou 2" Exit Case Default Print*, "Opção inválida" End Select End Do
Se queremos um programa a prova de fogo (que não de erro por entrada de dados) podemos fazer uma pequena modificação:
Na qual foi usado ERR=100
para o código se recuperar de dado inesperado, transferindo o controle do programa para a linha com esse número em caso de erro (texto em lugar de número por exemplo).
Ciclo condicional (Do While)
O do while
é executado enquanto uma condição lógica é satisfeita. Exemplo:
i = 1 do while ( i .le. 100 ) i = i + 1; print *, i end do
Resulta equivalente a:
do i + 1, 100 print*, i End do
Porem é de utilidade quando a condição não é trivial. Exemplo:
fac = 1. + 1./3.; imax = 1.E6 I = 1; print*, I do while ( i .lt. imax ) i = fac * i; print*, i end do
Arranjos (Arrays)
Tecnicamente, são tipos de dados ou variáveis estruturadas.
De outra forma, um arranjo é um conjunto de dados escalares, todos do mesmo tipo (REAL ou INTEGER, etc), organizados de
forma regular de maneira que é fácil atribuir ou extrair valores deles.
Assim como um escalar real é definido como
Real A
um array
real pode ser definido assim:
Real A(10)
No primeiro exemplo A pode conter apenas um valor por vez, enquanto no segundo, 10 diferentes valores podem ser armazenados
em A, cada um dos quais pode ser referido via o índice assim
A(1) = 0; A(2:7) = 4; A(8) = -1; A(9:10) = 2 Do i =2, 10, 2 print*, A(i) !imprimindo só as posições pares End do
Rodando esse programa teremos na tela:
4.000000
4.000000
4.000000
-1.000000
2.000000
Arranjos Estáticos
Arranjo estático e aquele cuja dimensão (números de elementos do arranjo) é definido nas declarações (instruções no início do programa e que não são executadas durante o tempo de rodada), é um número fixo que não pode ser mais alterado durante a execução. Exemplos:
Real A(10), B(30) Integer GG(10,10), ax(5,20), FG(6,10,5)
Também pode ser assim:
Character*10, Dimension (10,10) :: A, B, C, D
A dimensão é definida com Dimension(10,10)
para todos os arrays (A,B,C,D), todos eles da mesma forma (shape
).
NOTA: quando mais de um atributo é aplicado a uma ou mais variáveis (arrays ou escalares) os dois pares de pontos (::
quadrupleto) entre atributos e variáveis é mandatório sempre que houver atribuição inicial na declaração.
Arranjos Dinâmicos
A diferença com os anteriores é que a dimensão destes é definida durante durante a execução do programa, pudendo até ser modificada durante o mesmo. Isto se consegue com o atributo ALLOCATABLE
. Vejamos o exemplo:
Real, Allocatable :: A(:), B(:,:) Integer, Allocatable :: K(:), AJ(:,:,:)
Nesses exemplos definimos A e K como arrays
vetoriais, B matricial, e AJ tensorial.
O número de elementos deles é definido durante o tempo de execução com ALLOCATE.
A seguir um exemplo que ilustra a vantagem de usar arranjos dinâmicos
Real, Allocatable :: A(:), B(:,:) Integer I, N, M Read*, N Allocate (A(N), B(N,N)) Do I = 1, N A(I) = 2*I End Do Do i =1, N B(i,:) = A + i End do ... if (j .gt. 0) then Deallocate (B) else Deallocate (A) end if ... Select Case (J) Case(-1) Allocate (A(N/2) Case(2) Allocate (B(N,N/2)) End Select case
Funções e Subrotinas
São módulos independentes para fazer tarefas especificas definidas pelo programador.
Com a declaração FUNCTION é possível definir funções matemáticas diferentes ou além do conjunto de funções intrínsecas do compilador. Elas podem ser de uma ou mais variáveis, porem devolvem um valor só.
ATENÇÃO: a sintaxe na declaração de função se escreve g(x) (primeira linha nos exemplos onde se declara o nome da função e das variáveis). Na definição da função, implementada em Fortran, se escreve:
g = ...
não se colocam os argumentos ou variáveis a esquerda, elas devem aparecer só a direita da instrução.
Quanto a subrotina ela e um procedimento mais geral que pode operar em um conjunto ou todas as variáveis que estão no programa principal, e no retorno ao programa não há limite nas variáveis que pode devolver. Vejamos a sintaxe de cada uma:
Function
A sintaxe é:
REAL FUNCTION NOME(VARIAVEL) ... NOME = operações com VARIAVEL END FUNCTION NOME
Vamos para o exemplo:
\[g(x)=x^{2} sin(x)\]
Real Function g(x) Implicit None Real x g = x**2 * sin(x) End Function g
Exemplo de duas variáveis:
Real Function paraboloide(z,w) Implicit None Real z,w paraboloide = z**2 + w**2 End Function paraboloide
É possível também definir funções não analíticas, como por exemplo:
... if (x .le. 0) then g = 0. else g = 1. end if ...
Logo na execução, dentro do programa principal, se chama como qualquer função intrínseca do Fortran. Vejamos um exemplo completo de programa com definição de função.
! este e o program principal que usa a função h(x) program exemplo_uso_funcao implicit None real, external :: h(x) ! external pq está depois do end program real :: x, dx, y integer :: i,N Print*, "programa para construir tabela de h(x)" Print*, "entre o primeiro e ultimo x e o numero de pontos a graficar" read*, x0, xf, N dx = (xf - x0)/N do i = 0, N x = x0 + i*dx print*, x, h(x) enddo end program exemplo_uso_funcao ! aqui a definicao de funcao h(x) real function h(x) real x h = exp(-x**2)/2.0 end function h
Subrotina (subroutine)
A sintaxe de subrotina e:
SUBROUTINE EXEMPLO (Argumentos) ... END SUBROUTINE
No meio todas as instruções Fortran são validas, pois a subrotina é um programa. A idéia é que se um conjunto de operações se repete muito, então resulta conveniente colocá-las num módulo e chamá-lo cada vez que for necessário, assim:
PROGRAM Principal ... CALL EXEMPLO(Argumentos) ... DO ... CALL EXEMPLO(Argumentos) ... END DO ... END PROGRAM Principal
Exemplo:
program main implicit None real, dimension(3,3) :: A=0., B=0. call matriz(A,B) print*,"Matriz A" print'(3(f5.3,1x))',A print*,"Matriz B" print 100,B 100 format (3(f5.3,1x)) stop("Programa finalizado!") end program main subroutine matriz(A,B) real, dimension(3,3) :: A,B A = B + 1 end subroutine matriz
Resultado:
Matriz A
1.000 1.000 1.000
1.000 1.000 1.000
1.000 1.000 1.000
Matriz B
0.000 0.000 0.000
0.000 0.000 0.000
0.000 0.000 0.000
Module
Esta estrutura permite definir variáveis de uso comum entre o programa principal e as subrotinas sem se preocupar de passar elas como argumentos das mesmas. Vejamos um exemplo:
module variaveis real a, b integer N end module
Depois no programa e subrotina
program principal use variaveis !o main sabe agora de a,b,N implicit None ... read (*,*) a, b, N !estes valores de a,b,N serão passados para sub call Sub ... end program subroutine sub use variaveis !a Subrotina sabe de a,b,N implicit none ... h = (a-b)/N !e pode usá-las com os valores que tinham quando foi chamada ... end subroutine
Links
—
IDPGPT-1890
Deixe um comentário