73480343-apostila-f90.pdf

101
FORTRAN 90 Sintaxe das Principais Estruturas da Linguagem e Exemplos Jaci Maria Bernardo Guigon COPPE/UFRJ

Upload: juliano-deividy-b-santos

Post on 09-Aug-2015

87 views

Category:

Documents


18 download

TRANSCRIPT

Page 1: 73480343-APOSTILA-F90.pdf

FORTRAN 90 Sintaxe das Principais Estruturas da Linguagem e Exemplos

Jaci Maria Bernardo Guigon COPPE/UFRJ

Page 2: 73480343-APOSTILA-F90.pdf

1

Índice

1. PROGRAMAÇÃO EM FORTRAN 77/FORTRAN 90 1.1 - O COMPILADOR FORTRAN90 ....................... 3 1.2 - EXEMPLOS DE BIBLIOTECAS NUMÉRICAS, ESTATÍSTICAS E PARA PARALELIZAÇÃO DE ALGORITMOS INTEGRADAS AO FORTRAN 90

.......................

6

1.3 - GNUPLOT - SOFTWARE DE VISUALIZAÇÃO ....................... 7 2 – ESTRUTURA DA LINGUAGEM 2.1 – ESCREVENDO O CÓDIGO FONTE ....................... 8 2.2 – USANDO O COMPILADOR FORTRAN NO LINUX ....................... 11 3 – ELEMENTOS DE PROGRAMAÇÃO 3.1 – TIPOS DE DADOS E VARIÁVEIS ....................... 13 3.2 – IMPLICIT NONE ....................... 14 3.3 – O ATRIBUTO KIND – FORTRAN90 ....................... 17 3.4 – ARITMÉTICA INTEIRA, REAL E MISTA ....................... 21 3.5 – VALORES CONSTANTES – PARAMETER ....................... 22 3.6 – DECLARAÇÃO DATA ....................... 22 3.7 –OPERADORES E EXPRESSÕES ARITMÉTI CAS E LÓGICAS ....................... 23 3.8 – OPERADOR DE CONCATENAÇÃO E SUBSTRINGS ....................... 24 3.9 – FUNÇÕES PARA CADEIAS DE CARACTERES ....................... 25 3.10 – HIERARQUIA DOS OPERADORES ....................... 26 3.11 – ATRIBUTOS DE UMA VARIÁVEL ....................... 27 4 - COMANDOS BÁSICOS E ESTRUTURAS DE CONTROLE DE EXECUÇÃO 4.1 – STOP ....................... 28 4.2 – END ....................... 28 4.3 – PAUSE ....................... 29 4.4 – GO TO ....................... 29 4.5 – IF ....................... 30 4.6 – SELECT … CASE ....................... 32 4.7 – DO LOOP ....................... 33 5 – ARRAYS 5.1 – DIMENSION ....................... 38 5.2 – SIMPLIFICAÇÃO NA ESCRITA E UTILIZAÇÃO DE ARRAYS – FORTRAN90 ....................... 40 5.3 – LEITURA E GRAVAÇÃO DE ELEMENTOS DO ARRAY – DO IMPLÍCITO ....................... 43 5.4 – WHERE – SIMPLIFICANDO AS OPERAÇÕES COM ARRAYS ....................... 44 5.5 - FUNÇÕES INTRÍNSECAS PARA MATRIZES E VETORES - FORTRAN90 ....................... 46 6 - USER-DEFINED DATA TYPE – TIPOS DERIVADOS ....................... 48 7 – LEITURA E GRAVAÇÃO DE DADOS – FILES 7.1 – READ, WRITE, PRINT ....................... 52 7.2 – FORMATAÇÃO PARA LEITURA DE DADOS ....................... 55 7.3 – FORMATAÇÃO PARA GRAVAÇÃO DE DADOS ....................... 58 7.4 – LEITURA E GRAVAÇÃO DE DADOS EM ARQUIVOS ....................... 61

Page 3: 73480343-APOSTILA-F90.pdf

2

8 – SUBPROGRAMAÇÃO 8.1 – FUNÇÕES INTRÍNSECAS ....................... 65 8.2 – FUNÇÃO DECLARAÇÃO – FORTRAN77 ....................... 68 8.3 – FUNÇÕES EXTERNAS ....................... 69 8.4 – SUBROTINAS EXTERNAS ....................... 70 8.5 – SUBPROGRAMAS INTERNOS ....................... 71 8.6 – MÓDULOS ....................... 73 8.7 – COMPARTILHANDO DADOS COM SUBPROGRAMAS ....................... 76 8.8 - PASSANDO ARRAYS PARA SUBPROGRAMAS ....................... 78 8.9 – PERMISSÕES DE ACESSO PARA PARÂMETROS PASSADOS PARA MÓDULOS E SUB -PROGRAMAS

.......................

82

8.10 – RECURSIVE FUNCTIONS-RECURSIVIDADE EM SUB ROTINAS E FUNÇÕES - FORTRAN90

.......................

85

9 – ESTRUTURAS DINAMICAS DE DADOS – ARRAYS E POINTERS 9.1 - ARRAYS ALOCÁVEIS ( ALLOCATABLE ARRAYS ) ....................... 87 9.2 – POINTERS ....................... 89 9.3 – ESTRUTURAS DINAMICAS DE DADOS – LISTAS LINKADAS ....................... 93 9.4 – AUTOMATIC ARRAYS ....................... 94 10 – MIXED LANGUAGE PROGRAMMING 10.1 – VISUAL BASIC X FORTRAN90 – EXEMPLO ....................... 95 10.2 – FORTRAN90 X C – EXEMPLO ....................... 96 10.3 – DELPHI X FORTRAN90 – EXEMPLO ....................... 97 11 – REFERENCIAS ....................... 101

Page 4: 73480343-APOSTILA-F90.pdf

3

Programação em FORTRAN77/FORTRAN 90

1.1 - O compilador Fortran 90 O Fortran (FORmula TRANslation) teve a sua primeira versão desenvolvida entre 1954

e 1957, sendo considerada a mais antiga linguagem de programação destinada à

computação científica. Antes deste período, os códigos eram executados em linguagem

de máquina. Foi inicialmente desenvolvido para executar em um computador IBM

Type704, e já em 1958, mais da metade dos códigos utilizados naquele computador

estavam escritos na linguagem FORTRAN. Tal popularidade fez com que grupos

diferentes começassem a escrever os seus próprios compiladores - em 1962 surgiu a

versão FORTRAN IV. Para contornar o problema da portabilidade, a linguagem foi

oficialmente padronizada em 1966, sob responsabilidade do American National

Standards Institute(ANSI) e denominada Fortran 66. A partir de 1977, o Fortran passou

por grandes modificações, surgindo em 1980 uma nova versão padronizada - o

Fortran 77.

Paralelamente às modificações decorrentes destas versões, foram surgindo novas

linguagens com recursos de programação e conceitos mais modernos. Apesar disto, a

comunidade científica continuou utilizando e adotando a linguagem para o

desenvolvimento de códigos, especialmente por possuir algumas características:

î Linguagem de programação de fácil codificação

î Grande potencial para cálculos, devido à disponibilidade de um grande número de

funções intrínsecas, operações e representações de dados

î Boa interface com bibliotecas (matemáticas e estatísticas) externas amplamente

utilizadas em aplicações científicas

î Surgimento de implementações destinadas à otimização do código

î Dificuldade de migração de milhões de linhas de código implementadas

originariamente em Fortran, para uma outra linguagem

Page 5: 73480343-APOSTILA-F90.pdf

4

Apesar de seu uso intensivo durante as décadas seguintes à sua padronização e já

englobando conceitos mais modernos de programação do que as suas versões

anteriores, o Fortran 77 ainda continuava defasado, quando comparado às modernas

linguagens de programação recém-criadas. Alguns exemplos da deficiência da

linguagem podem ser citados: utilização de formato fixo na codificação dos programas;

inexistência de estruturas para acesso dinâmico aos dados; problemas relacionados

com a portabilidade numérica; ausência de recursividade; problemas na manipulação de

dados globais, dentre outros.

Com o intuito de eliminar tais restrições, foram introduzidas grandes modificações

surgindo o Fortran 90, padronizado em 1993. O Fortran 90 é considerado um superset

do Fortran 77, mantendo todas as estruturas anteriores da linguagem. Desta forma,

programas escritos em Fortran 77 podem ser submetidos ao compilador do Fortran 90,

muito embora, vários comandos sejam considerados obsoletos, sendo desaconselhado

o seu uso em novos programas.

Características do Fortran90 î Código Fonte em Formato livre

î Tipos de Dados Parametrizados (KIND)

î Derived Types

î Otimização de Arrays

î Pointers

î Alocação Dinâmica de Memória

î Otimização de Subprogramas

î Módulos

î Novas Procedures Intrínsecas

Compiladores FORTRAN 90/95 O Fortran 90, assim como o C e o C++ são as linguagens mais utilizadas nos sistemas de work-stations e em máquinas destinadas à Computação de alto desempenho em geral. Também existem versões para micro-computadores, disponíveis para todos os sistemas operacionais.

Page 6: 73480343-APOSTILA-F90.pdf

5

Para máquinas destinadas a computação de alto desempenho, existe versões Fortran HPF (High Performance Fortran) , próprias para a execução do código em paralelo e outras otimizações relacionadas com a computação intensiva. Para sistemas LINUX, pode-se citar os compiladores Lahey Fortran, Intel, AbSoft Fortran, g95, dentre outros. Para os sistemas da Microsoft, o Fortran PowerStation foi bastante difundido, existindo até a versão 4. Posteriormente, a versão da Compaq (Compaq Visual Fortran) também preservava o mesmo ambiente de programação. Atualmente, o compilador Fortran Intel é a nova denominação para o antigo MS Fortran PowerStation, posteriormente denominado COMPAQ Fortran. O Fortran 90 também faz parte do conjunto de linguagens de Programação do Visual Studio .NET. As versões do compilador para os sistemas Microsoft são bastante amigáveis, oferecendo um ambiente de programação integrando as fases de edição, compilação, debug e execução do programa.

1.2 - Bibliotecas Numéricas, Estatísticas e para Paralelização de Algoritmos î IMSL Fortran Library - Biblioteca de rotinas matemáticas e estatísticas integrada ao

compilador Fortran 90 î NAG Numerical Libraries for Fortran 90 Users î Numerical Recipes - Fontes de Algorítmos Numéricos de domínio público

disponíveis no módulo Numerical Recipes î OpenMP - OpenMP API User's Guide – Diretivas para

Multiprocessamento/Paralelização de Algoritmos

Page 7: 73480343-APOSTILA-F90.pdf

6

1.3 – GNUPLOT - Software de visualização Vários aplicativos de visualização podeM ser utilizados para visualização dos arquivos de dados gerados pelos códigos Fortran90, seja em formato ASCII ou binário. Alguns aplicativos podem ser integrados aos códigos de processamento, gerando gráficos de forma interativa. Um exemplo de aplicativo freeware para visualização de gráficos e superfícies é o GNUPLOT.

GNUPLOT

O Aplicativo gnuplot é utilizado para visualização de gráficos e superfícies, comuns nas aplicações científicas. Este aplicativo é de domínio público, tendo versões para diversos sistemas operacionais tais como Unix, Linux, Windows, etc.

O GNUPLOT pode ser utilizado para traçar curvas (2 dimensões) e superfícies (3 dimensões). Em 3D, as funções podem ser plotadas na forma de malha, superfícies em três coordenadas ou isolinhas no plano x-y. Em 2D, há muitas opções incluindo linhas, pontos, gráficos de barras, etc. Pode-se utilizar títulos para o gráfico e para os eixos, data/hora, legendas, etc.

Formas de utilização do gnuplot

1) Linhas de comandos do aplicativo

2) Criação de scripts contendo comandos. O script é executado dentro do

aplicativo, a través do comando “load”

3) O Script contendo os comandos do gnuplot poderá ser executado

dinamicamente dentro de um programa Fortran90

4) Uso de bibliotecas contendo funções do gnuplot. Utilizadas na linguagem C.

Page 8: 73480343-APOSTILA-F90.pdf

7

2 - Estrutura da Linguagem 2.1 - Escrevendo o código fonte O formato padrão para a escrita de novos códigos em Fortran90 é o formato livre, ou seja, sem alinhamentos específicos por colunas conforme será visto a seguir. No entanto, programas em formato fixo (alinhados em colunas específicas) escritos de acordo com a sintaxe das versões anteriores da linguagem, também serão compilados. O tipo de formatação que estiver sendo usado, deverá ser especificada para o compilador através da extensão do nome do programa. Programas escritos em formato livre deverão ter uma das extensões: .f90, .F90, .f95 ou F95. Programas escritos em formato fixo, deverão ter a extensão .f, .F, .for ou .FOR O compilador também aceita fontes com a extensão .f03 or .F03. Eles são tratados de forma equivalente a .f95 e .F95 e poderia ser utilizado para indicar que o fonte contém extensões do Fortran 95 (versão FORTRAN 2003).

Elementos da Linguagem O FORTRAN utiliza como caracteres básicos as letras A-Z ( não case-sensitive ) e os dígitos 0-9; como caracteres especiais podem ser utilizados: + - / * , ´= . ( ) $ “ : FORMATO FIXO Tamanho da linha do código e linhas de continuação Um programa em formato fixo deverá ser escrito em linhas de no máximo 80 colunas. Um comando ou conjunto de comandos (ou expressões) em Fortran pode ocupar uma ou mais linhas. São consideradas linhas de continuação, aquelas que contém qualquer caracter diferente de branco na coluna 6. No FORTRAN 77, pode-se ter até 19 linhas de continuação.

Page 9: 73480343-APOSTILA-F90.pdf

8

Comentários As linhas de comentário são utilizadas para documentação do programa. Qualquer caracter (em geral, ‘*’ ou ‘C’) colocado na primeira coluna, irá caracterizar a linha como “comentário” sendo portanto, ignorada pelo compilador. Também pode-se comentar uma linha de comando; neste caso, utilizar o caracter “!”, após o comando e precedendo o comentário. Rótulos (labels) Usados para identificar uma linha de comando ou formato, a ser referenciado posteriormente. Corresponde a um valor numérico (1-99999) digitado nas cinco colunas iniciais. Texto Representa o programa propriamente dito. Aqui, texto refere-se às declarações e os comandos da linguagem Fortran. O texto deve ser escrito entre as colunas 7 e 72. Qualquer texto digitado após a 72ª coluna, será ignorado. O texto não é case-sensitive, podendo ser utilizadas letras maiúsculas e minúsculas, tendo o mesmo significado.

FORMATO LIVRE Tamanho da linha do código e linhas de continuação Cada linha do programa-fonte pode ter até 132 caracteres. Uma linha de continuação é identificada através do caracter '&' digitado ao final da linha anterior. No formato livre pode-se ter normalmente até 39 linhas de continuação.

Exemplo: format (/”A area de ”, f4.1, “ por “, f4.1, & “do retangulo é “, f6.2 )

Page 10: 73480343-APOSTILA-F90.pdf

9

Comentários ! Exemplo de utilização de comentarios em FORTRAN 90 temp = x ! uso de comentario apos comando Rótulos (labels) No formato livre, qualquer …. (colocar tbem quando nao é numero...) read(5,100) a, b ; 100 format (i5, a10)

Texto Os comandos podem iniciar a partir de qualquer coluna. No FORTRAN 90, pode-se ter vários comandos na mesma linha, separados pelo caracter ';' . Exemplo: if ( I = = 1) then; I =2; else if (I >= 2)then; I = 1; endif Different Fortran standards

Fortran 66 Fortran 77 Fortran 90 Fortran 95 Properties Fixed form Fixed form Fixed Free (Fixed) Free

Whole Fortran 66 = -2 -2 -2 -5 -5 Whole Fortran 77 - = = = -5 -5 Whole Fortran 90 - - = = -5 -5 Whole Fortran 95 - - -14 -14 = = Continuation line indicated in column 6 on the next line

+ + + - + -

Continuation line indicated with & at the end of the present line

- - - + - +

Blank line as comment - + + + + + Significant blanks - - - + - + Generic functions - + + + + + User-defined generic functions - - + + + +

REAL*8 - - - - - - Comment symbol C C * C * ! ! C * ! ! Extension in Unix .f .f .f .F90 .f .F90 Extension in DOS .FOR .FOR .FOR .F90 .FOR .F90

Fonte: http://www.nsc.liu.se/~boein/FORTRAN 77to90

Page 11: 73480343-APOSTILA-F90.pdf

10

Na Tabela acima, -2 na posição Whole Fortran 66 / Fortran 90 significa que duas propriedades desapareceram na transição do Fortran66 para o Fortran90. Isto aplica-se tanto ao formato fixo quanto ao formato livre.

Nas primeiras quarto linhas, o sinal = indica que nada foi modificado; já o sinal -, indica que várias propriedades estão faltando.

Nas sete linhas seguintes, um sinal + indica que a propriedades está presente; o sinal – indica propriedade ausente.

O uso do Formato fixo é desencorajado no Fortran 95.

REAL*8 é uma variante da declaração DOUBLE PRECISION, introduzida pela IBM e usada pela Digital. Existem várias outras formas de declaração.

É recomendado o uso do símbolo “!” para indicar linhas de comentário; este símbolo é também válido nas implementações do Fortran77.

No UNIX, não há extensões da linguagem. As extensões não fazem parte do Fortran Standard, sendo de responsabilidade de desenvolvedores específicos.

2.2 - Usando o compilador Fortran no LINUX A seguir é dada uma breve descrição de como utilizar o compilador e executar códigos desenvolvidos em Fortran90.

O primeiro passo é utilizar um editor (vi, emacs, etc..) para criar o arquivo-fonte, lembrando que tal arquivo deverá ter uma das extensões: .f, .for, .f90, .f95, .F, .F90, ou .F95 .

Exemplo – O programa a seguir mostra uma mensagem na tela demo% cat exemplo.f PROGRAM EXEMPLO PRINT *, 'Programming in Fortran 90 – Simple Code Example!' END demo% g95 exemplo.f demo% a.out Programming in Fortran 90 – Simple Code Example! demo%

Page 12: 73480343-APOSTILA-F90.pdf

11

No exemplo acima, o g95 compila o código fonte exemplo.f , faz os links necessários e produz o executável a.out, por default. Para executar o programa, o nome do arquivo executável, a.out, deverá digitado na linha de comandos.

Tradicionalmente, os compiladores UNIX/LINUX escrevem a saída dos arquivos executáveis em a.out. Para especificar um nome diferente para o arquivo executável, utilize a opção de compilação –o: Exemplo demo% g95 exemplo.f –o exemplo demo% exemplo

a.out também poderá ser renomeado posteriormente através do comando mv.

A seguir, um exemplo de compilação de dois códigos contidos em diferentes arquivos (inclusive, em formatos diferentes – vide extensão), produzindo um executável chamado heat; a opção –g ativa o debug de erros durante a execução. Exemplo demo% f95 -g -o heat heat.f fft.f95

A seguir, a compilação e geração de executável com programa principal em Fortran e subrotina em C. A compilação é feita em separado, gerando os códigos-objeto relacionados com cada unidade de programa. Depois é feita a link-edição entre os objetos, gerando o código executável. Exemplo 1 demo% f95 -c -fast sbr.f demo% cc -c -fast simm.c demo% f95 -fast sbr.o simm.o

Exemplo 2 Utilizando o exemplo anterior, se forem utilizadas opções de compilação, elas deverão ser aplicadas na geração de todos os objetos em separado, assim como na fase de link. demo% f95 -c -fast sbr.f demo% cc -c -fast simm.c

demo% f95 -fast sbr.o simm.o link step; passes -fast to th e linker

Page 13: 73480343-APOSTILA-F90.pdf

12

3. Elementos de Programação 3.1 - Tipos de Dados e variáveis

Tipos de Dados î Inteiros (INTEGER)

î Reais de precisão simples (REAL)

î Reais de precisão dupla (DOUBLE PRECISION*)

î Complexos (COMPLEX)

î Lógicos (LOGICAL)

î Caracteres (CHARACTER)

Nomes de Variáveis Variáveis são nomes associados a tipos de dados. Os nomes (identificadores) de variáveis, podem conter caracteres alfabéticos, números e o símbolo “_”, iniciando obrigatoriamente por um caracter alfabético. Nomes de variáveis podem ter até 31 caracteres (standard). O valor contido em uma variável poderá mudar no decorrer da execução do programa, através de novas atribuições. São consideradas variáveis simples, àquelas com capacidade para armazenar apenas um valor. As variáveis deverão ser obrigatoriamente declaradas no início do programa, antes de qualquer linha de comando.

Declaração de Variáveis Todas os tipos de variáveis devem ser declaradas em Fortran antes de serem

utilizadas, EXCETUANDO-SE as variáveis reais de precisão simples e inteiras. Caso

uma variável real ou inteira não seja declarada, a primeira letra do nome do identificador

irá indicar o tipo da mesma; isto porque o Fortran possui declarações implícitas pré-

Page 14: 73480343-APOSTILA-F90.pdf

13

definidas, estabelecendo que todas as variáveis iniciando com letras no intervalo I-N,

são inteiras (caso não sejam declaradas) e as demais (ou seja, iniciando nos intervalos

A-H, O-Z ) são reais de precisão simples.

3.2 - Implicit None (Fortran 90) A declaração IMPLICIT NONE quando utilizada no início do programa, obriga a

declaração de todas as variáveis que serão utilizadas no programa. Este recurso visa

minimizar a ocorrência de erros devido à enganos na digitação de variáveis e facilitar a

documentação do programa. O uso desta declaração é altamente recomendável.

IMPLICIT (não recomendável) A não necessidade de declaração das variáveis inteiras e reais, deve-se ao fato de já

existir, internamente na linguagem, um IMPLICIT associado aos nomes das variáveis

reais e inteiras. Como exemplo, a declaração IMPLICIT REAL (A) , define que toda

variável existente no programa, iniciada com a letra A, será automaticamente de tipo

REAL.

Exemplos

IMPLICIT INTEGER (I-N)

IMPLICIT DOUBLE PRECISION (A-H, O-Z)

IMPLICIT CHARACTER*6 (R)

IMPLICIT LOGICAL (L)

Exemplos de declarações de variáveis Valores Inteiros INTEGER SOMA INTEGER TOT1, TOT2, INDICE Atribuindo um valor SOMA = 0

Page 15: 73480343-APOSTILA-F90.pdf

14

Valores Reais de precisão simples REAL CONTA REAL X1, X2, TOTAL Atribuindo um valor CONTA = 1.0

Valores Reais de precisão dupla REAL*8 VETOR1 DOUBLE PRECISION DP1, DP2, DP3 REAL(KIND=8) :: VAR1 Atribuindo um valor VETOR1 = 10.D0 VETOR1 = 10.0 Observação: Prefira o uso do atributo KIND=8 ou REAL(8) para definir variáveis em dupla precisão.

Números Complexos COMPLEX CP1 COMPLEX VCOMP1, VCOMP2 Atribuindo um valor: CP1 = (5.0,2.0) equivalente a 5 + 2i

Valores Lógicos

LOGICAL FIM LOGICAL ACHOU, FLAG Atribuindo um valor: FIM = .FALSE. FLAG = .TRUE.

Page 16: 73480343-APOSTILA-F90.pdf

15

Cadeia de Caracteres CHARACTER(LEN=10) :: PALAVRA (Forma preferencial) CHARACTER C1*3, C2 CHARACTER*8 ALFA, BETA*4, GAMMA Ao utilizar a declaração de uma variável na forma CHARACTER(LEN=N) ou CHARACTER*N, o valor N, correspondente ao tamanho da cadeia, não deverá exceder a 255 caracteres. Exemplo Como devem estar declaradas as variáveis XIS, SOMA, TOTAL, VALOR, CURSO, SUBLEN, FORMULA, COMP, TAM e SY, no início do programa? XIS = .FALSE. SOMA = INT(15.2)+MOD(18,5) TOTAL = 19853 VALOR = 488.D0 CURSO = ‘CURSO MESTRADO – COPPE’ SUBLEN = ‘C’ FORMULA = SQRT(XY) COMP = X.LT.5.OR.Y.GE.10.0 TAM=LEN(S) SY = SIN(A)+COS(B) Primeiro Exemplo de Programa – Formato Fixo C FIXED FORM EXAMPLE – READ ANGLE AND HYPOTENUSE; C CALCULATE THE LENGTHS OF SIDES A AND B C PROGRAM TRIANGLE

REAL A, B, C, THETA WRITE (*,*) "ENTER THE LENGTH OF THE HYPHOTENUSE C:" READ(*,*) C

C WRITE (*,*) "ENTER THE ANGLE THETA IN DEGREES:" READ(*,*) THETA A = C * COS(THETA) B = C * SIN(THETA) WRITE (*,*) "THE LENGTH OF THE ADJACENT SIDE IS: ",

* A WRITE (*,*) "THE LENGTH OF THE OPPOSITE SIDE IS: ", B END

Page 17: 73480343-APOSTILA-F90.pdf

16

Primeiro Exemplo de Programa – Formato Livre PROGRAM TRIANGLE ! FREE FORM EXAMPLE – READ ANGLE AND HYPOTENUSE; ! CALCULATE THE LENGTHS OF SIDES A AND B ! REAL A, B, C, THETA WRITE (*,*) "ENTER THE LENGTH OF THE HYPHOTENUSE C:" READ(*,*) C WRITE (*,*) "ENTER THE ANGLE THETA IN DEGREES:" READ(*,*) THETA A = C * COS(THETA) B = C * SIN(THETA) WRITE (*,*) "THE LENGTH OF THE ADJACENT SIDE IS: ", & A WRITE (*,*) "THE LENGTH OF THE OPPOSITE SIDE IS: ", B END

3.3 - KIND (FORTRAN 90) Cada tipo de dado possui um ou mais valores de um atributo KIND associado a ele. Tipos de dados com diferentes valores KIND, usa um número diferente de bytes para armazenar informação. Isto significa que tipos de dados numéricos com diferentes parâmetros KIND têm intervalos distintos de possíveis valores e/ou diferentes níveis de acurácia numérica. As variáveis, utilizando o atributo KIND, poderão ser declaradas da seguinte forma: REAL ( KIND = Y ) VALOR REAL ( KIND = X ) SIMPLES

KIND - Portabilidade do código entre diferentes arquiteturas A utilização da declaração DOUBLE PRECISION pode gerar problemas de portabilidade do algoritmo entre máquinas com diferentes tamanhos de palavras Um exemplo são máquinas que necessitam de variáveis em dupla precisão, obtida com 64 bits, migrando para um equipamento, cujo tamanho de palavra (precisão simples) já é de 64 bits.

Page 18: 73480343-APOSTILA-F90.pdf

17

O uso do atributo KIND permite que a variável se ajuste automaticamente à arquitetura da máquina que está sendo utilizada. Desta forma, o atributo KIND proporciona independência da arquitetura da máquina, sendo especialmente importante em programas que serão migrados de equipamento. KIND para tipo REAL Uma variável de tipo REAL pode ser declarada como REAL ou DOUBLE PRECISION, ou ter seu intervalo e precisão especificado através do atributo KIND. Se o atributo KIND é especificado, ele deve ter um dos seguintes valores: Valores para PC’s: Kind Intervalo Precisão 4 (default) 2**-126 a 2**127 16 bits -6dígitos de precisão 8 2**-1012 a 2**1023 32 bits -18dígitos de precisão Valores para sistemas CRAY (arquitetura 64 bits): Kind Intervalo Precisão 4 2**-8189 a 2**8190-1 64 bits - 14 dígitos de precisão 8 (default) 2**-8189 a 2**8190-1 64 bits - 14 dígitos de precisão 16 2**-8189 a 2**8190-1 128 bits-29 dígitos de precisão Exemplo Deseja-se trabalhar com a variável BIGVAR, em uma work-station de 32 bits; Esta variável deve ter 14 dígitos de precisão. Sabe-se que após, o programa irá rodar em uma máquina com palavra de 64 bits. Como deve ser feita a declaração desta variável? Possibilidade 1: double precision BIGVAR Problema: Se o uso de dupla-precisão não for desabilitado na segunda máquina, a variável irá requerer 128 bits (que corresponde à dupla-precisão naquele equipamento), e os resultados poderão não ser de acordo com o esperado; Há ainda a possibilidade

Page 19: 73480343-APOSTILA-F90.pdf

18

de degradação de performance do algoritmo e utilização excessiva de memória, desnecessariamente. Possibilidade 2: real (kind=8) BIGVAR Com esta opção, a variável vai requerer duas palavras de memória (64 bits) na work-station, fornecendo 15 dígitos de precisão e ao migrar para a segunda máquina em questão, irá ajustar-se ao kind=8 daquele equipamento, que corresponde a sua precisão simples (64 bits) e 19 dígitos de precisão. Kind para tipo INTEGER No Fortran tradicional, os tipos de dados eram baseados em um modelo de memória onde um tipo real, integer ou logical era representado em uma unidade numérica de memória. Para os inteiros, a especificação do KIND representa o intervalo numérico de representação do dado. Valores para PC’s: Kind Intervalo 1 +-127 2 +-32.767 4(default) +-2.147.483.647 Valores para sistemas CRAY: Kind Intervalo 1 +- 2.147.483.647 2 +- 2.147.483.647 3 +- 2.147.483.647 6(default) +- 35.184.372.088.831 8 +- 9.223.372.036.854.775.807

Page 20: 73480343-APOSTILA-F90.pdf

19

Size Notation for Numeric Data Types

Nonstandard Declarator Short Form Meaning

INTEGER*1 INTEGER(KIND=1) INTEGER(1) One-byte signed integers

INTEGER*2 INTEGER(KIND=2) INTEGER(2) Two-byte signed integers

INTEGER*4 INTEGER(KIND=4) INTEGER(4) Four-byte signed integers

LOGICAL*1 LOGICAL(KIND=1) LOGICAL(1) One-byte logicals

LOGICAL*2 LOGICAL(KIND=2) LOGICAL(2) Two-byte logicals

LOGICAL*4 LOGICAL(KIND=4) LOGICAL(4) Four-byte logicals

REAL*4 REAL(KIND=4) REAL(4) IEEE single-precision four-byte floating-point

REAL*8 REAL(KIND=8) REAL(8) IEEE double-precision eight-byte floating-point

REAL*16 REAL(KIND=16) REAL(16) IEEE quad-precision sixteen-byte floating-point

COMPLEX*8 COMPLEX(KIND=4) COMPLEX(4) Single-precision complex (four bytes each part)

COMPLEX*16 COMPLEX(KIND=8) COMPLEX(8) Double-precision complex (eight bytes each part)

Fonte: http://docs.sun.com/source/819-3686/4_f95.html IEEE - Institute of Electrical and Electronics Engineers, Inc.

Page 21: 73480343-APOSTILA-F90.pdf

20

Exemplo Como é feita a representação numérica para INTEGER INTEGER (KIND=1) = NUM De acordo com as tabelas xx e yy, KIND=1 corresponde a inteiros assinalados, armazenados em 1 byte, tendo portanto representação numérica máxima de +127:

8 BITS +/- 1 1 1 1 1 1 1

62 52 42 32 22 12 02 =64 =32 =16 =8 =4 =2 =1

= + 127

3.4 - Aritmética Inteira, Real e Mista Em Fortran, não é o operador aritmético e sim a forma de representação do dado, que define o resultado da operação aritmética. Inteira 3/5 à 0 13/4 à 3

Real 3.0/5.0 à 0.6 3./5. à 0.6 13./4.0 à 3.25 Mista 3.0/5 à 0.6 13/4.0 à 3.25 Atenção! A conversão automática de tipo pode ocorrer quando o nome da variável for de tipo diferente do resultado da expressão numérica. Exemplo NRES = 1.25 + 9 / 4 NRES é um tipo inteiro enquanto o resultado da expressão é real ( = 3.25 ). Este resultado é automaticamente convertido para inteiro e NRES armazenará o valor 3.

Page 22: 73480343-APOSTILA-F90.pdf

21

3.5 - Valores Constantes - PARAMETER Em Fortran, um valor considerado constante no decorrer da execução do programa, é

representado por um identificador, assim como as variáveis. O que determina a

característica constante do valor é o comando não-executável PARAMETER.

Toda constante (PARAMETER) deve ser previamente declarada, independente do uso

ou não, da declaração Implicit None.

Exemplo - FORTRAN 77 REAL DIMAT PARAMETER (DIMAT = 100) Exemplo - FORTRAN 90 REAL, PARAMETER :: DIMAT = 100

3.6 - Declaração DATA (obsoleto) Utilizado para inicialização de variáveis. Os valores são associados às variáveis na fase

de compilação e não na fase de execução do programa.

Exemplo 1 - Inicialização de uma variável real

INTEGER ANGULO REAL RAD, PI, SENO DATA PI /3.1416/ ANGULO = 47 RAD = ANGULO* PI / 180. PRINT *, RAD END

Exemplo 2 - Inicialização de grupo de variáveis reais DATA PI, X, Y / 3.1415, 0.0, 1.2 / Este comando deveria ser substituído por: REAL :: PI=3.1415, Y=0.0, Y=1.2

Page 23: 73480343-APOSTILA-F90.pdf

22

3.7 – Operadores e Expressões Aritméticas e Lógicas Operadores Aritméticos SÍMBOLO OPERAÇÃO EXEMPLO + SOMA A + B

- SUBTRAÇÃO X – Y

/ DIVISÃO ALFA/BETA

* MULTIPLICAÇÃO BETA*GAMMA

** POTENCIAÇÃO A**B

Toda expressão aritmética deve ser escrita na forma linear, observando-se a hierarquia das operações. Operadores Relacionais Símbolo Símbolo FORTRAN 90

(opcional) Operação

.EQ. == IGUAL

.NE. /= DIFERENTE

.GT. > MAIOR QUE

.GE. >= MAIOR OU IGUAL

.LT. < MENOR

.LE. <= MENOR OU IGUAL

Operadores Lógicos .AND. .OR. .NOT. .EQV. .NEQV. Exemplo - combinação de operadores lógicos e relacionais LOGICAL FIM FIM = ISOMA .GT. 100 .AND. ISOMA .LT. 1000 (observe que ISOMA é de tipo INTEGER)

Page 24: 73480343-APOSTILA-F90.pdf

23

3.8 - Operador de Concatenação e Substrings Duas ou mais strings ou sub-strings podem ser combinadas para a formação de uma única string (cadeia de caracteres). Esta operação é denominada “concatenação”. Exemplo 1 Concatenação de strings de caracteres: ‘AB’ // ‘CD” O resultado da operação acima é uma string: ‘ABCD’ Exemplo 2 Operações com strings – definição de sub-string

Dada a string C:

C = ‘ABCDEFG’

Pode-se extrair sub-strings da seguinte forma:

C(3:7) à ‘CDEFG’ C(:3) à ‘ABC’ C(5:) à ‘EFG’ Observação: A primeira expressão inteira define o primeiro caracter que irá compor a substring; a segunda expressão inteira define o último caracter da substring. Exemplo 3 Concatenação e sub-strings PROGRAM TEST CHARACTER(LEN=10) :: A CHARACTER(LEN=8) :: B, C A = “ABCDEFGHIJ” B = “12345678” C = A(1:3) // B(4:5) // A(6:8) PRINT (“(A)”) C END PROGRAM

Page 25: 73480343-APOSTILA-F90.pdf

24

Valor Impresso: “ABC45FGH”

3.9 - Funções para Cadeias de Caracteres

ADJUSTL(STRING) Ajusta a string à esquerda

ADJUSTR(STRING) Ajusta a string à direita

INDEX(STRING, SUBSTRING, back)

Retorna a posição onde inicia a substring, dentro da string. Se BACK = true, será retornada a posição da última substring, se for false, retorna a posição da primeira.

LEN_TRIM(STRING) Retorna o tamanho da string, sem

caracteres brancos no inicio ou final da mesma.

LGE(STRING_A, STRING_B) LGT(STRING-A, STRING_B) LLE(STRING_A, STRING_B) LLT(STRING_A, STRING_B) As rotinas acima, comparam duas

strings, utilizando a ordenação de caracteres da tabela ASCII. Se uma string for mais curta do que a outra, serão adicionados brancos ao final, para que tenham o mesmo tamanho.

REPEAT(STRING, NCOPIES) Concatena a string NCOPIES vezes,

gerando uma nova cadeia de caracteres

TRIM(STRING) Retorna a string sem os espaços em

branco não significativos (antes do início, ou depois do final da string).

LEN(STRING) Retorna o tamanho da string de

caracteres.

Page 26: 73480343-APOSTILA-F90.pdf

25

3.10 - Hierarquia dos Operadores

Operações com parênteses, iniciando pelos parênteses mais internos

Cálculo de Funções

Operações com exponeciais, iniciando da esquerda para a direita

Operações de multiplicação e divisão, iniciando da esquerda para a direita

Operações de adição e subtração, iniciando da esquerda para a direita

Operadores relacionais (==, /=, >, >=, <, <=), iniciando da esquerda para a

direita

Concatenação

Operadores .NOT.

Operadores .AND. iniciando da esquerda para a direita

Operadores .OR. iniciando da esquerda para a direita

Operadores .EQV. e .NEQV., iniciando da esquerda para a direita

Sempre em caso de igualdade de hierarquia, resolve-se a expressão da esquerda para a direita; para quebrar a hierarquia, faça uso dos parênteses. O uso de parênteses para indicar a ordem das operações é altamente recomendável. Em caso de igualdade de hierarquia, resolve-se a expressão da esquerda para a direita; para quebrar a hierarquia, faça uso dos parênteses. O uso de parênteses para indicar a ordem das operações é altamente recomendável. Exemplo X + 1 / X – 1

difere de : ( X + 1 ) / ( X – 1 )

Page 27: 73480343-APOSTILA-F90.pdf

26

3.11 - Atributos de uma variável Observação: As diversas especificações para uma variável, podem ser declaradas em uma mesma linha. Para isto, utilize o símbolo '::' Exemplo 1 (FORTRAN 77)

REAL A, B, C PARAMETER ( A = 3.141592654 ) DIMENSION B(3) DATA B/1.0, 2.0, 3.0/ DIMENSION C(100) DATA C/100*0.0/

As linhas acima, escritas em FORTRAN 90, ficariam de uma forma mais resumida:

REAL, PARAMETER :: A = 3.141592654 REAL :: B(3) = (/1.0,2.0,3.0/) REAL :: C(1:100) = 0.0

Exemplo 2 (FORTRAN 90) REAL, DIMENSION(3), PARAMETER :: & a = (/10.0, 0.0, 0.0/ ), b=(/1.0, 1.0, 1.0/) COMPLEX, DIMENSION(10) :: vortex

Page 28: 73480343-APOSTILA-F90.pdf

27

4. Comandos Básicos e Estruturas de Controle de Execução STOP END PAUSE GO TO IF IF...ELSE...ENDIF DO ... ENDDO DO WHILE... ENDDO SELECT...CASE CYCLE EXIT

4.1 - STOP (obsoleto) O comando STOP encerra a execução do programa. Embora pouco utilizado, é comum ser visto em programas mais antigos, com a função de por exemplo, separar o bloco de comandos executáveis dos não-executáveis (exemplo: comandos executáveis de bloco de linhas de formato). Exemplos

STOP STOP 99 STOP ‘final de programa’ Quando o comando STOP é executado, o conteúdo do rótulo ou da string será exibido no terminal, se o processamento for interativo.

4.2 - END O comando END indica para o compilador o final de uma unidade de programa, devendo ser portanto, o último comando a ser executado. O seu uso é obrigatório no final de cada unidade de programa, ou seja, programa principal, sub-programa ou módulo.

Page 29: 73480343-APOSTILA-F90.pdf

28

4.3 – PAUSE (obsoleto) O comando PAUSE suspende temporariamente a execução de um programa, aguardando que qualquer tecla seja ativada, para que seja dada sequência ao processamento. Opcionalmente exibe mensagem no terminal do programador.

4.4 – GO TO (não recomendável) Este é considerado um comando de desvio, possibilitando a alteração do fluxo seqüencial do código; o seu uso no entanto, é altamente desaconselhável na programação atual. O conhecimento de tais estruturas deverá apenas contribuir para a compreensão de códigos antigos. GO TO incondicional O fluxo do programa é desviado imediatamente para o rótulo especificado GO TO 10 .... .... ! linhas de comandos .... 10 A = A + 1 GO TO computado (não recomendável) Dada uma lista de m rótulos, e uma expressão aritmética de valor N, o programa é desviado para o n-ésimo rótulo da lista. Caso N seja menor ou igual a zero, ou maior que m, o programa seguirá para o comando seguinte, não fazendo desvio para nenhum dos rótulos. Este comando deverá ser substituído pelo select...case. Exemplo 1 GO TO (10, 11, 15, 30) J/10 No exemplo, se J/10 tem valor 1, o programa é transferido para o primeiro rótulo da lista (10); se J/10 tem valor 3, o programa é transferido para o terceiro rótulo da lista (15) Exemplo 2 GO TO (100, 200, 300) LMN No exemplo, se LMN tem valor 2, o programa é transferido para o segundo rótulo da lista (200); se LMN tem valor 0 ou 4 por exemplo, o programa continua a execução na próxima linha de comando, sem fazer desvio.

Page 30: 73480343-APOSTILA-F90.pdf

29

4.5 - IF (comando condicional) Utilizado para testar uma expressão lógica e tomar decisões baseadas nos resultados. Existem três possibilidades para o comando IF: 1. IF lógico

2. IF aritmético

3. IF bloco (estruturado)

IF lógico Permite que se execute ou não um comando, dependendo do resultado da expressão lógica. Exemplos IF ( A .GT. 1.0 ) A = 0.0 IF ( I .EQ. 0 .AND. K .GT. 5 ) X = X + 1 IF ( Z3 .LE. 10 ) GO TO ( 10, 20, 30 ) Z2

IF aritmético (obsoleto) É um desvio com três saídas. O programa escolherá uma delas a partir do resultado de uma expressão aritmética. Exemplo:

IF ( K*3 – A/9) 10, 20, 30 ... 20 ... 10 ... 30 No exemplo acima, se: expressão aritmética < 0 à desvio para rótulo 10 expressão aritmética = 0 à desvio para rótulo 20 expressão aritmética > 0 à desvio para rótulo 30 IF bloco Serve para a execução de um bloco de comandos a partir de uma expressão lógica. Neste caso, o comando IF deverá ser usado em conjunto com o comando ENDIF (ou END IF) e opcionalmente, com os comandos ELSE ou ELSE IF para formar a estrutura.

Page 31: 73480343-APOSTILA-F90.pdf

30

Comandos:

IF ... THEN ELSE ELSE IF ..... THEN END IF

Exemplo 1 IF ( B .GT. C ) THEN

A = A + 1 C = 0

ENDIF Exemplo 2 IF ( B .GT. C ) THEN

A = A + 1 C = 0

ELSE A = A – 1 B = 10

ENDIF

Exemplo 3 IF ( B .GT. C ) THEN

A = A + 1 C = 0

ELSE IF (C .EQ. A) THEN A = A – 1 B = 10

ENDIF

Exemplo 4 Dada a Tabela: 95 < grade A 86 < grade < 95 B 76 < grade <= 86 C 66 < grade <= 76 D 0 < grade <= 66 F

Page 32: 73480343-APOSTILA-F90.pdf

31

A estrutura em Fortran 90 para avaliar em qual intervalo encontra-se um valor numérico e imprimir a letra correspondente, poderia ser escrita da seguinte forma: IF ( grade > 95.) THEN write(*,*) “The grade is A.” ELSE IF ( grade > 86.) THEN write(*,*) “The grade is B.” ELSE IF ( grade > 76.) THEN write(*,*) “The grade is C.” ELSE IF ( grade > 66.) THEN write(*,*) “The grade is D.” ELSE write(*,*) “The grade is F.” END IF

4.6 - SELECT …. CASE (FORTRAN 90) Este comando pode substituir um conjunto de if’s e go to’s. No entanto, ele só é aplicável à variáveis de tipo INTEGER e CHARACTER. Exemplo 1

integer IVAR SELECT CASE (IVAR) CASE (:1)

! todos os numeros negativos print *, ‘Numero Negativo’

CASE (0) ! ivar = 0 print *, ‘Zero’

CASE (1:9) ! numero de um digito print *, ‘Digito’, IVAR

CASE (10:99) numero de dois digitos print *, ‘Numero ‘, IVAR

CASE DEFAULT ! todos os casos restantes print *, ‘Numero muito grande’

END SELECT

Page 33: 73480343-APOSTILA-F90.pdf

32

Exemplo 2

CHARACTER*10 COR COR = 'VERDE' SELECT CASE (COR) CASE ('VERMELHO')

Stop CASE ('AMARELO')

call aguarde CASE ('VERDE')

call siga END SELECT

4.7 - DO (LOOP) – Repetição de Trechos do código Os LOOPS são estruturas que permitem a execução de uma seqüência de declarações por várias vezes. As duas formas básicas de LOOPS são as construções WHILE e os Loops Iterativos , sendo que a principal diferença entre eles é em como a repetição é controlada. No caso de Loops iterativos, a variável de controle não pode ser alterada no interior do loop. DO Códigos antigos normalmente utilizam a instrução não executável CONTINUE como limite do comando DO. Atualmente, seu uso não é recomendável. N_FACTORIAL = 1 DO 10 I = 1, N N_FACTORIAL = N_FACTORIAL * I 10 CONTINUE em formato Fixo: N_FACTORIAL = 1 DO 10 I = 1, N N_FACTORIAL = N_FACTORIAL * I 10 CONTINUE

Page 34: 73480343-APOSTILA-F90.pdf

33

Exemplo 2 Mesmo comando do exemplo 1. Prefira o uso do enddo como delimitador do trecho de loop. N_FACTORIAL = 1 DO I = 1, N N_FACTORIAL = N_FACTORIAL * I ENDDO Exemplo 3 Nas versões antigas do Fortran, era comum o uso de variáveis de tipo REAL como contadores, conforme exemplo abaixo – no entanto, o seu uso em códigos atuais é desaconselhado. Esta estrutura será descontinuada nas próximas versões da linguagem. H = 0.1 DO X = 4.0, 7.9, H

Y = 3 * X ** 2 – 4 * X + 2 AREA = AREA + Y * H

ENDDO Exemplo 4

DO 20 I=1, 10, 2 .... DO 10 J=1, N

.... ...

10 CONTINUE 20 CONTINUE Exemplo 5 DO I = 10, 1, -1

.... WRITE(*,*)X*I ....

ENDDO Pergunta: No exemplo anterior, qual o valor final da variável I ?

Page 35: 73480343-APOSTILA-F90.pdf

34

DO While – Loop condicional

Ao invés de executar o laço n vezes, conforme foi visto no comando DO anterior, a

utilização do DO WHILE faz com que o trecho seja executado enquanto a expressão

lógica especificada for verdadeira – a expressão é avaliada a cada iteração do loop.

Exemplo

I = 1 DO WHILE ( I <= 15 )

AMAX (I) = SQRT(I) I = I + 1

ENDDO

While Loop (FORTRAN 90)

DO IF (expressão_logica) EXIT ENDDO

Devido à não existência de uma variável de controle para encerrar a repetição após um número finito de vezes, é necessário estabelecer uma condição para por fim ao loop. Desta forma, o do loop infinito pode ser interrompido através do comando EXIT , combinado com a verificação de alguma condição de término (comando IF). Exemplo 1 DO

… INDEX = A * SQRT(B) IF ( INDEX < 0 ) EXIT IF ( INDEX == 0 ) CYCLE ...

ENDDO

DECLARAÇÔES CYCLE e EXIT CYCLE e EXIT são duas declarações adicionais que podem ser utilizadas para controle de operação de DO LOOPS.

Page 36: 73480343-APOSTILA-F90.pdf

35

CYCLE O comando CYCLE dentro de uma declaração DO ou DO WHILE faz com que os comandos subsequentes dentro do loop sejam ignorados, passando direto para uma próxima iteração. Exemplo PROGRAM TESTE_CYCLE INTEGER :: I DO I = 1, 5 IF (I == 3) CYCLE WRITE (*,*) I END DO WRITE (*,*) “FINAL DO LOOP!” END PROGRAM Resultado %> teste_cycle 1 2 4 5 FINAL DO LOOP! EXIT O comando EXIT termina a execução de uma construção DO ou DO WHILE, antes de completar as demais iterações. PROGRAM TESTE_EXIT INTEGER :: I DO I = 1, 5 IF (I == 3) CYCLE WRITE (*,*) I END DO WRITE (*,*) “FINAL DO LOOP!” END PROGRAM Resultado %> teste_exit 1 2 FINAL DO LOOP!

Page 37: 73480343-APOSTILA-F90.pdf

36

Exemplo – CYCLE e EXIT no mesmo trecho SOMA = 0.0 XX: DO I = 1, 10

X = TAB(I) YY: DO J = 1, 20 IF ( X > TAB(J)) CYCLE XX X = X + TAB(J)

ENDDO YY SOMA = SOMA + X IF ( SOMA >= 17.0 ) EXIT XX END DO XX

Page 38: 73480343-APOSTILA-F90.pdf

37

5 – ARRAYS e TIPOS DERIVADOS

Variáveis Indexadas - ARRAYS Um array corresponde a um grupo de valores, todos de mesmo tipo e identificados pelo mesmo nome. Cada valor individual é denominado elemento do array, e deve ser acessado através de índice(s). O número de índices para a identificação de cada elemento corresponde ao número de dimensões do array. Em FORTRAN, um array pode conter até sete dimensões. Os elementos de um array ocupam posições contíguas na memória. Ao contrário de outras linguagens, o FORTRAN armazena os elementos do array de acordo com a disposição dos dados em colunas. Como exemplo, considere o array NUMEROS, inicializado com valores: INTEGER, DIMENSION(3,3) :: NUMEROS = (/1,4,7,2,5,8,3,6,9/) Ao imprimir a estrutura do array NUMEROS já preenchido com os valores, os dados estarão dispostos da seguinte forma:

NUMEROS =

1 2 3

4 5 6

7 8 9

O acesso (leitura, gravação, atribuição de valores, cálculos) ao conjunto de valores de uma variável indexada, normalmente é feito através de comandos de repetição, tal como o DO...END DO.

5.1 - Dimension Exemplo 1 INTEGER A REAL B DIMENSION A(0:10), B(5,5) Primeiro elemento de A: A(0) Primeiro elemento de B: B(1,1)

Page 39: 73480343-APOSTILA-F90.pdf

38

Exemplo 2 Dimensionamento automático de VET INTEGER I, VET(10) REAL(8) MAT (3,5), X (6) Exemplo 3 Leitura de valores para a variável indexada VET(10) DO I=1,10

READ(*,*) VET(I) ENDDO Exemplo 1 PROGRAM SQUARES IMPLICIT NONE INTEGER :: I INTEGER, DIMENSION(10) :: NUMBER, SQUARE ! INITIALIZE NUMBER AND CALCULATE SQUARE DO I=1, 10 NUMBER(I) = I ! INITIALIZE NUMBER SQUARE(I) = NUMBER(I)**2 ! CALCULATE SQUARE END DO ! WRITE OUT THE NUMBER AND ITS SQUARE DO I = 1, 10 WRITE(*,100) NUMBER(I), SQUARE(I) END DO 100 FORMAT (1X, “Number = “, i6, “Square = “, i6) END PROGRAM

Page 40: 73480343-APOSTILA-F90.pdf

39

5.2 - Simplificação na escrita e na utilização de Arrays Uma das mais importantes características na evolução do FORTRAN 77 para o FORTRAN 90 é a simplificação nas operações com arrays. O FORTRAN 90 permite que quase todas as operações que eram anteriormente aplicadas a elementos individuais do array, sejam agora aplicadas ao array inteiro, ou a seções dele. Como isto, no FORTRAN 90 os valores poderão ser atribuídos aos arrays de uma forma bastante concisa. Isto oferece como vantagens:

simplicidade e redução da escrita do programa-fonte, facilitando o desenvolvimento e a manutenção de aplicações

maior eficiência (otimização) do código a ser executado em máquinas vetoriais e paralelas

Como exemplo, considere A, B, C como arrays de mesmas dimensões. A operação para armazenamento da soma de A e B no array C, era antes escrito da forma:

DO I=1, 100 DO J=1,50 C(I,J) = A(I,J) + B(I,J) ENDDO ENDDO

Utilizando o FORTRAN 90, a mesma operação poderá ser escrita simplesmente na forma C=A+B. A operação C = A + B, pode ser realizada sendo C, A, B, arrays de mesmo formato. A possibilidade de utilização de um array como se fosse um escalar, facilita as operações de pesquisa, paralelização de algorítmos, além de reduzir o tamanho do programa-fonte. Além disso, esta implementação é internamente mais otimizada pelo compilador e oferece melhor desempenho na computação em máquinas vetoriais e paralelas. Outras implementações que facilitam a manipulação de conjuntos de dados são os tipos derivados e a alocação dinâmica de arrays, permitindo a alocação de memória durante a execução do programa. Além disso, funções podem retornar um array . Muitas funções intrínsecas funcionam independente de o argumento passado ser um escalar, vetor ou array multi-dimensional. As funções intrínsecas que realizam operações sobre arrays eliminam a necessidade de do-loops . De acordo com o exemplo a seguir, o argumento angles pode ser uma variável escalar ou um array; o resultado será na estrutura correspondente: print *, sin(angles)

Page 41: 73480343-APOSTILA-F90.pdf

40

Mais exemplos de atribuição de valores a um Array em FORTRAN 90: Exemplo 1 FORTRAN 77 REAL SUMS DIMENSION SUMS(2,3) DO J = 1, 3

DO I = 1, 2 SUMS(I, J) = 0.0 ENDDO

ENDDO FORTRAN 90 REAL DIMENSION(2,3) :: SUMS = 0.0 Exemplo 2 Um array pode ainda ser referenciado como se fosse um escalar. REAL, DIMENSION(3) :: ARRAY = 0.0 Exemplo 3 Os valores podem ser atribuídos como listas simples. REAL, DIMENSION(3) :: ARRAY = ( / 2.0, 4.0, 6.0 /)

Exemplo 4 Os valores podem ser atribuídos na forma de construções utilizadas normalmente em comandos DATA, READ e WRITE. REAL, DIMENSION(3) :: ARRAY = ( / (2 * I, I=1,3 )/) Exemplo 5 Os valores podem ser atribuídos na forma de um do-loop implícito. REAL, DIMENSION(3) :: ARRAY = ( /(I, I= 2, 6, 2)/) Observe nos exemplos mostrados, que as atribuições de valores para elementos específicos do array são sempre delimitadas por “(/ “ e “/)”. Quais os valores contidos em array após as declarações a seguir? REAL, DIMENSION(3) :: ARRAY = (/(I, I=2,6,2)/) ARRAY = ARRAY – 1.0

Page 42: 73480343-APOSTILA-F90.pdf

41

Exemplo 6 - Sintaxe FORTRAN 77 versus FORTRAN 90

REAL :: A(10), B(10), C(5) REAL, DIMENSION (5,5) :: X

Os comandos da primeira e segunda coluna são equivalentes:

A = B

DO I=1,10 A(I) = B(I) END DO

C = A(3:7)

DO I=1,5 C(I) = A(I+2) END DO

A(2:10:2) = C

DO I=1,5 A(2*I) = C(I) END DO

A = SIN(B)

DO I=1,10 A(I) = SIN(B(I)) END DO

Exemplo 7 Atribuição de valores a seções de Arrays. . REAL, DIMENSION (2, 3) :: ARRAY REAL, DIMENSION ( 3) :: ULT_COLUNA REAL, DIMENSION (2 ) :: PRIM_LINHA PRIM_LINHA (:) = ARRAY(1, : ) ! TODOS ELEM. DA PRIMEIRA LINHA ULT_COLUNA (:) = ARRAY (: ,3) ! TODOS OS ELEM. DA ULTIMA COLUNA

Exemplo 8 Passando valores contidos em seções de Arrays, como argumentos para subprogramas. PROGRAM SLICE REAL, DIMENSION(2,3) :: ARRAY .... CALL LISTA (ARRAY(1, : ) ) END PROGRAM SLICE

Page 43: 73480343-APOSTILA-F90.pdf

42

Exemplo 9 PROGRAM ADD_ARRAYS IMPLICIT NONE INTEGER :: I REAL, DIMENSION(4) :: A = (/1.,2.,3.,4./) REAL, DIMENSION(4) :: B = (/5.,6.,7.,8./) REAL, DIMENSION(4) :: C, D ! ELEMENT-BY-ELEMENT ADDITION DO I = 1,4 C(I) = A(I) + B(I) END DO ! WHOLE ARRAY ADDITION D = A + B ! WRITE RESULTS WRITE (*,100) “C” , C WRITE (*,100) “D” , D 100 FORMAT(‘ ‘, A, “=”, 5(6.1,1X)) END PROGRAM

5.3 - LEITURA E GRAVAÇÃO DE ELEMENTOS DO ARRAY - DO IMPLICITO Utilizado para auxiliar no processo de leitura ou gravação de dados provenientes de vetores e matrizes. Neste tipo de operação, utiliza-se o comando READ, ou WRITE, em conjunto com a especificação de índices que substituirão um ou mais comandos DO. Exemplo 1 READ (*,*) (VET(I), I = 1, 10) Exemplo 2 READ(*,*) (( MAT(I,J), J=1,5), I=1,3)

Page 44: 73480343-APOSTILA-F90.pdf

43

5.4 - WHERE - Simplificando as operações com Arrays O comando WHERE é aplicável a arrays, realizando operações sobre todos os elementos simultaneamente. Pode-se considerar que o WHERE substitui um conjunto de IF’s e Do loops. Sintaxe: [name:] WHERE (EXPRESSAO RELACIONAL) COMANDO OU BLOCO DE COMANDOS I ELSEWHERE [name] COMANDO OU BLOCO DE COMANDOS II END WHERE [name] Exemplo 1

FORTRAN 77 source:

INTEGER A(10,10),B(10,10) · DO I=1,10 DO J=1,10 IF (A(I,J).LT.B(I,J)) A(I,J)=B(I,J) END DO END DO END

Fortran 90 or Fortran 95 source: INTEGER A(10,10),B(10,10) · WHERE (A.LT.B) A=B END

Page 45: 73480343-APOSTILA-F90.pdf

44

Exemplo 2 PROGRAM CLIMA CHARACTER*1, DIMENSION(18) :: HEMISFERIO REAL, DIMENSION(18) :: TEMPERATURA, PRESSAO, LATITUDE LOGICAL , DIMENSION(18) :: CHUVA INTEGER :: INC ... ! DEFINE HEMISFERIO WHERE ( LATITUDE > = 0 ) ! VERIFICA TODOS OS ELEM. DE LATITUDE

HEMISFERIO = 'N' ! ATRIBUI VALORES ELSEWHERE HEMISFERIO = 'S' ! IDEM, CASO ELEM. EM LATITUDE SEJA < 0 END WHERE ... WHERE ( PRESSAO <= 1.0 ) PRESSAO = PRESSAO + INC ! INCREMENTA VALORES PARA END WHERE ! VALORES <= 1.0 DE PRESSAO Exemplo 3 Como a declaração abaixo seria escrita no FORTRAN 77?

WHERE ( B .NE. 0 ) A = A/B Exemplo 4 O trecho abaixo:

DO I = 1, N DO J = 1, M LOGVAL(I,J) = LOG(VALUE(I,J)) END DO END DO

é equivalente a:

LOGVAL = LOG(VALUE)

Page 46: 73480343-APOSTILA-F90.pdf

45

Agora deseja-se calcular o logaritmo apenas para os valores positivos, para os quais a função está definida: Utilizando o método tradicional: DO I = 1, N DO J = 1, M IF ( value(i,j) > 0.0 ) THEN LOGVAL(I,J) = LOG(VALUE(I,J)) ELSE LOGVAL(I,J) = -99999 END IF END DO END DO Utilizando a construção WHERE, o trecho acima ficará reduzido a: WHERE (value > 0.) Logval = log(value) ELSEWHERE LOGVAL = -99999 END WHERE

Page 47: 73480343-APOSTILA-F90.pdf

46

5.5 - Funções intrínsecas para matrizes e vetores (FORTRAN 90) DOT_PRODUCT(VECTOR_A, VECTOR_B) Retorna o produto escalar entre

dois vetores, os quais devem ter o mesmo tamanho (mesmo número de elementos).

MATMUL(MATRIX_A, MATRIX_B) Retorna o produto de duas matrizes que devem ser consistentes, isto é, ter dimensões como (M, K) e (K, N).

MAXVAL(ARRAY, dim, mask) Retorna o maior valor contido em ARRAY.

MINVAL(ARRAY, dim, mask Retorna o menor valor contido em ARRAY.

PRODUCT(ARRAY, dim, mask) Retorna o produto de todos os elementos contidos em ARRAY.

SUM (ARRAY, dim, mask) Retorna a soma de todos os elementos contidos em ARRAY.

ALLOCATED(ARRAY) Função lógica que devolve true se array tiver sido alocado.

LBOUND(ARRAY, dim) Retorna o limite inferior do array.

SHAPE(ARRAY) Retorna o formato (dimensões) do array.

SIZE(ARRAY, dim) Retorna o número de elementos contidos no array.

UBOUND(ARRAY, dim) Retorna o limite superior do array.

Page 48: 73480343-APOSTILA-F90.pdf

47

Um Exemplo de uso de Função Intrínseca para Arrays - RESHAPE

A função intrínseca RESHAPE permite modificar a estrutura de um array, desde que a estrutura anterior e a especificada, contenham a mesma quantidade de elementos. Observe que o RESHAPE atribui os dados de uma mesma maneira, que é feita pelo comando READ.

RESHAPE ( / 1, 4, 7, 2, 5, 8, 3, 6, 9 /), ( /3, 3/) 1 2 3 4 5 6 7 8 9

Exemplo 2 - Dados os valores para SOURCE, SHAPE e PAD, observe o resultado da função RESHAPE. SOURCE = [1,2,3,4,5,6] SHAPE = [2,5] PAD = [0,0] RESHAPE(SOURCE, SHAPE, PAD) = 1 3 5 0 0

Page 49: 73480343-APOSTILA-F90.pdf

48

6 - USER-DEFINED DATA TYPE – TIPOS DERIVADOS - FORTRAN 90 Assim como os arrays, um user-defined data type pode ter muitos elementos, com a diferença de que este conjunto pode conter dados de tipos diferentes. Ou seja, um componente pode ser de tipo inteiro, outro de tipo real e assim por diante. Além disso, cada elemento é identificado por um nome e não por um número (indice) como no caso do array. Estas estruturas são similares à construção RECORD (Pascal) ou STRUCT (C). Sintaxe: TYPE < nome da estrutura > Definição dos componentes (campos) da estrutura END TYPE < nome da estrutura > Exemplo 1 Exemplo de declaração de um user-defined data type. TYPE PESSOA INTEGER IDADE CHARACTER (LEN=50) NOME END TYPE PESSOA Exemplo 2 Cada elemento do tipo derivado pode ser acessado de forma independente. O símbolo ‘%’ é utilizado para referenciar componentes específicos da estrutura.

TYPE PESSOA INTEGER IDADE CHARACTER (LEN=50) NOME END TYPE PESSOA TYPE (PESSOA) :: MARIA MARIA%IDADE = 15 MARIA%NOME = ‘MARIA SCHNEIDER’

Criando uma Estrutura “Array de user-defined data type” Uma vez criada a estrutura (type ... end type ), podem ser criadas variáveis simples daquele tipo type(pessoa) :: maria, como no exemplo anterior, assim como arrays, da seguinte forma:

Page 50: 73480343-APOSTILA-F90.pdf

49

TYPE (PESSOA), DIMENSION(25) :: CADASTRO Esta ultima declaração dimensiona um array de 25 elementos de tipo pessoa. Exemplo 1 Criação de um cadastro

PROGRAM USER_TYPE TYPE PESSOA INTEGER IDADE CHARACTER (LEN=50) NOME END TYPE PESSOA ! TYPE (PESSOA), DIMENSION(25) :: CADASTRO TYPE (PESSOA) FIM_CADASTRO ! CADASTRO(3)%IDADE = 36 CADASTRO(3)%NOME = 'LUIS CARLOS' ! ! OUTRA FORMA DE ASSOCIACAO DE DADOS AO REGISTRO: ! CADASTRO(4) = PESSOA (26, 'ANA BEATRIZ') FIM_CADASTRO = (0, “ “) ! PRINT*,CADASTRO(3) PRINT*,CADASTRO(4) PRINT*,FIM_CADASTRO END

SAÍDA DO PROGRAMA: 36 LUIS CARLOS 26 ANA BEATRIZ 0

Page 51: 73480343-APOSTILA-F90.pdf

50

Criando estruturas mais complexas usando derived types.

TYPE STAFF CHARACTER (LEN=20) :: PRIMEIRO_NOME, ULTIMO_NOME INTEGER :: IDENTIFICACAO, DEPTO END TYPE TYPE EMPRESA CHARACTER (LEN=20) :: NOME_EMPRESA TYPE (STAFF), DIMENSION(100) :: STAFF_CADASTRO END TYPE . . TYPE (EMPRESA), DIMENSION(10) :: VARIAS_EMPRESAS

Associando valores aos campos A atribuição de valores pode ser realizada diretamente sobre um campo específico:

varias_empresas(1)%nome_empresa = ‘PETROBRAS’ Associando valores, sem especificação de nomes de campos varias_empresas(1)%staff_cadastro(3) = (‘Jose’, ‘Silva’, 113, 03)

Page 52: 73480343-APOSTILA-F90.pdf

51

7 - Leitura e Gravação de Dados, FILES As operações de leitura e gravação servem para transferir dados de meios de armazenamento externos tais como unidades de disco, para a memória e vice-versa. Para a realização destas operações, o Fortran oferece três comandos: READ, WRITE e PRINT.

7.1 – Read, Write, Print READ - Comando para Leitura de dados Sintaxe: READ ( UNIT=<unidade lógica> , FMT=<formato>, REC=<registro>, ERR=<rótulo>, IOSTAT=<variável inteira>, END=<rótulo> ) <lista de variáveis> Onde: <unidade lógica> : número do arquivo a ser lido. O uso do número 5 ou “*”, indica que a entrada de dados será via teclado, considerada a unidade default, para leitura de dados. <formato> : como o dado está ou será representado, de acordo com seu tipo <registro> : representa o registro a ser lido dentro do arquivo (para arquivos de acesso direto) <variável inteira> : retorna o código de finalização do comando para uma variável inteira. 0 = leitura normal valor negativo = fim de arquivo valor positivo = erro na leitura do dado <rótulo> : rótulo para desvio após erro (ERR) ou leitura do dado (END) <lista de variáveis> : lista de variáveis a serem lidas Exemplo 1 Variáveis A, B, C digitadas através do teclado

READ (5,*) A, B, C READ (*,*) A, B, C

Page 53: 73480343-APOSTILA-F90.pdf

52

WRITE - Comando para saida de dados Utilizado para mostrar dados na tela ou gravá-los em um arquivo; a sintaxe é a mesma do comando READ. Todas as opções do comando READ são válidas, exceto a cláusula “END”. Uma outra diferença é que a unidade lógica do comando, corresponde ao número do arquivo a ser gravado. O uso do número 6 ou “*”, indica impressão de dados na tela do computador, que é considerada a unidade default. Exemplo 1 Variáveis A, B, C terão seus valores exibidos na tela do computador

WRITE (6,*) A, B, C WRITE (*,*) A, B, C

PRINT - Comando para gravação de dados Sintaxe: PRINT *, <lista de variáveis> ou PRINT <formato>, <lista de variáveis> Este comando poderá ser utilizado somente para a exibição de dados em tela, não podendo ser aplicado à gravação em arquivos. Exemplo 1

PRINT *, A, B, C Formatação de Dados Muitas vezes, é necessário realizar a leitura ou gravação de dados de maneira formatada, especificando por exemplo, um número máximo de casas decimais, ou tamanho total de um campo. Ou seja, é a forma como o dado está codificado externamente, ou será codificado, nas operações de leitura ou gravação respectivamente. Em Fortran existem duas formas de especificar a formatação:

1) através de um rótulo, que servirá como referência para a linha aonde o formato está especificado (através do FORMAT), ou uma variável de tipo

2) através de uma declaração de formatação, dentro do comando read ou write.

Page 54: 73480343-APOSTILA-F90.pdf

53

Exemplo: As declarações abaixo são equivalentes

1) read (5, FMT=“(i2)”)) x 2) read (5,20) x 20 format (I2)

Formato livre : usado quando se deseja ler ou imprimir valores sem se preocupar com o formato. Para tal, basta utilizar um ‘*’ no lugar da especificação do rótulo, no comando read ou write. Controle de Espacejamento: No Fortran, a primeira posição de um registro gravado é reservada para controle de espacejamento. Esta é uma característica remanescente das primeiras versões da linguagem. Esta posição nunca é impressa e o seu conteúdo servia para determinar a movimentação do papel (cursor, para terminais), antes da impressão do registro. Sendo assim, ao utilizar o comando PRINT ou WRITE, é sempre conveniente deixar um espaço antes do texto ou da primeira variável a ser impressa.

Page 55: 73480343-APOSTILA-F90.pdf

54

7.2 – Formatos para Leitura de Dados

I - INTEGER

Formato Valor Externo Valor Lido I4 2216 2216 I3 -40 -40 I8 bbbb1234 1234 I3 1 2 102 I8 1234bbbb 12340000

F - REAL (Precisão Simples)

Formato Valor Externo Valor Lido F5.2 12345 123.45 F5.2 1.234 1.234 F5.2 -1234 -12.34 F5.2 12 34 120.34

X - Ignora caracteres Exemplo

READ (5,10) I,J 10 FORMAT ( I3, 2X, I4 ) Supondo que o conteúdo do registro fosse: 123456789 os valores lidos seriam: I = 123; J = 6789

Page 56: 73480343-APOSTILA-F90.pdf

55

A - CHARACTER Sintaxe: A <constante inteira> Exemplo

Formato Valor Externo Valor Lido A3 ‘ABCbb ‘ ‘ABC’ A5 ‘ABCDE’ ‘ABCDE’

D e E - REAL (Precisão simples ou dupla) em notação exponencial Na leitura, o valor pode ter notação científica (no Fortran, o valor é normalizado entre 0.1 e 10 e multiplicado por alguma potência de 10). O formato D é considerado obsloleto, sendo o seu uso desaconselhado em novos programas. Sintaxe: E <w=constante inteira>.<d=constante inteira> Onde: w : valor inteiro representando o campo total. Para evitar overflow, normalmente ele deve satisfazer a seguinte expressão: w >= d+7 d: valor inteiro suficiente para representar o símbolo E, o sinal do expoente e o expoente. Exemplo

Formato Valor Externo Valor Lido E11.4 25046 2.5046 E10.3 1268E+3 b1268000.0 D10.2 12345000.00

0.12345D+8

ES - Notação Científica A especificação do formato ES, segue a mesma norma do formato E, visto no ítem anterior. A única diferença é que este formato segue o exatamente a convenção de notação científica, normalizando o valor a ser representado entre 1. E 10., multiplicado por uma potência de 10.

Page 57: 73480343-APOSTILA-F90.pdf

56

/ - Pular para o próximo registro Exemplo

Suponha os registros: 123456 789012 Utilizando o comando: READ (5,10) J1, J2, J3, J4 10 FORMAT (I4,I2,/,I3,I3) Os valores lidos serão: J1=1234, J2= 56, J3 = 789, J4=12

Page 58: 73480343-APOSTILA-F90.pdf

57

7.3 - Formatos para Gravação de Dados Integer

Formato Valor Valor Gravado I4 1234 1234 I3 -5 -5 I5 123 123 I4.2 1 01 I4.4 1 0001 I3 -473 ***N

Reais - Precisão Simples

Formato Valor Valor Gravado F6.2 123.0 123.00 F5.2 -4.3 -4.30 F5.2 1.234 1.23 F5.2 -10.4 ******

X - Imprime espaços em branco Exemplo

WRITE (6,20) I, A 20 FORMAT (3X, I3, 2X, F4.2 ) Supondo I = 123 e A = 1.23 Seria impresso: bb123bb1.23 CHARACTER Sintaxe: A <constante inteira> Exemplo

Formato Valor Valor Gravado A5 ‘ABCDE’ ‘ ABCDE’ A3 ‘ABCDE’ ‘ABC’ A5 ‘ABC’

‘ ABC’

Page 59: 73480343-APOSTILA-F90.pdf

58

D e E - REAL (Precisão simples ou dupla) em notação exponencial Na gravação, a notação científica será representada por D ou E, de acordo com a especificação. O formato D é considerado obsloleto, sendo o seu uso desaconselhado em novos programas. Exemplo

Formato Valor Valor Gravado D10.3 0.0363 bb.363D-01 E10.5 -36.7929 *********** D11.5 -36.7929 b-.36793D+02

Formato Texto - Imprime uma cadeia de caracteres

Exemplo

I = 10 WRITE (6, 15) I 15 FORMAT ( ‘o valor de I =‘, I3 )

A saida impressa será:

o valor de I = 10 Exemplo os formatos a seguir são equivalentes. FORMAT( 4I4, 3F5.2, 2(I3,2X)) FORMAT( I4,I4,I4,I4,F5.2,F5.2,F5.2,I3,2X,I3,2X) FORMAT( 2(3I2,1X),F5.3) FORMAT( I2, I2, I2, 1X, I2, I2, I2, 1X, F5.3 )

Page 60: 73480343-APOSTILA-F90.pdf

59

Formato para tipos Derivados É possivel imprimir uma estrutura de um tipo derivado, definindo o nome da estrutura como sendo uma variável simples e especificando a sequência de formatos para os seus diversos elementos. A mesma definição vale para a leitura de dados. Exemplo TYPE string INTEGER LENGTH CHARACTER (LEN=20) WORD END TYPE STRING TYPE (STRING) :: TEXT WRITE(*, '(I2,A)') TEXT

Non Advancing - Impede salto de linhas entre comandos de leitura e gravação. Exemplo

write(6,100) 100 format(' ', Digite um numero: ') read (5,*) i

Resultado: Entre com um numero:

123 < ------valor digitado write(6,100,advance='NO')

100 format(' ', 'Digite um numero: ') read (5,*) i

Resultado:

Entre com um numero: 123

G - Formato Geral Como exemplo, o formato F dado por F7.3, pode representar um valor real da forma: ddd.ddd ou –dd.ddd. No entanto, se este número for >=1000 ou <= -100, a saída especificada não será suficiente sendo então representada por um campo de asteriscos. Desta forma, se ao invés do descritor F, for utilizado o G, o número, quando muito grande ou pequeno, será automaticamente substituído pelo formato E. O formato geral G pode ser utilizado também para representar dados inteiros, lógicos ou character, assumindo o formato conveniente em cada caso.

Page 61: 73480343-APOSTILA-F90.pdf

60

7.4 - Leitura e Gravação de Dados em Arquivos Um arquivo consiste de várias linhas contendo dados e que poderá ser acessado como uma unidade. Cada linha de informação no arquivo é denominada “registro”. Em termos práticos, um arquivo físico existente em uma unidade de disco por exemplo, deverá ser associado a uma unidade lógica dentro do programa, para que possa ser acessado. O FORTRAN pode ler informações ou gravar em um arquivo, um registro por vez. Uma unidade lógica dentro do programa poderá ser conectada a um arquivo em disco através do comando OPEN.

OPEN Associa um nome de arquivo a um descritor (numero da unidade), tornando um arquivo em disco disponível para leitura ou gravação de dados. O comando OPEN realiza a associação entre o nome “real” do arquivo (que está ou que será gravado em disco) e o número especificado como unit. A partir daí, toda vez tal número aparecer em um comando READ ou WRITE, significa que o arquivo correspondente será acessado. A operação a ser realizada (leitura ou gravação) também poderá ser especificada através de opções dentro do comando OPEN. Opções: OPEN ( UNIT=<unidade>, IOSTAT=<variável>, FILE=<nome>, STATUS=<stat>, ACCESS=<acc>, FORM= <form>, RECL=<tam> ) Onde: <unidade> : número do arquivo lógico (descritor) <rótulo erro> : é o rótulo de um comando para onde será desviado o programa em caso de erro no OPEN. <variável> : variável inteira, retornando valor diferente de zero em caso de erro no OPEN <nome> : é uma expressão CHARACTER contendo o nome externo do arquivo <stat> : ‘OLD’ – arquivo já existente ‘NEW’- será criado um novo arquivo ‘SCRATCH’ – arquivo temporário ‘UNKNOWN’ – sem informações a respeito da existência ou não do arquivo <acc> : ‘SEQUENTIAL’ – acesso sequencial ‘DIRECT’ - acesso direto <form> : ‘FORMATTED’ – arquivo com dados formatados ‘UNFORMATTED’ – arquivo sem formatação de dados <tam> : expressão inteira que corresponde ao tamanho do registro

Page 62: 73480343-APOSTILA-F90.pdf

61

Exemplos: 1) OPEN (UNIT=8, FILE=’ARQ1.DAT’, STATUS=’OLD’) 2) OPEN(UNIT=31,FILE=’DADOS.TXT’,STATUS=’REPLACE’, FORM=’FORMATTED’) CRIANDO NOMES DE ARQUIVOS DINAMICAMENTE - TRANSFORMAÇÃO DE NUMERO EM STRING INTEGER VALUE CHARACTER*2 STRING VALUE = 24 WRITE (STRING, '(I2)'), VALUE PRINT *, STRING OPEN (UNIT=2, FILE="ARQ"//STRING ) WRITE (2,*) "TESTE!!" CLOSE (2) END Observação: A leitura de arquivo com uso da cláusula “end=” dentro do comando read, não é recomendável no desenvolvimento de novos códigos. Prefira o controle de fina/dados através do uso da opção iostat. implicit none integer :: io-status, x integer :: line = 0 open ( unit=4, file=’a2.dat’) io-status = 0 do while (io-status == 0 ) line = line + 1 read (5, FMT=“(i2)”), iostat=io-status) x if ( io-status == 0 ) then write (6, 102) line, x else write (6, 103) io-status endif enddo 102 format(‘line’, i2, ‘tem inteiro x = ‘, i2) 103 format(‘Codigo iostat no fim de arquivo (EOF)= ‘, i9) end

Page 63: 73480343-APOSTILA-F90.pdf

62

Exemplo 2 Verificação do final de arquivo com uso do IOSTAT OPEN (UNIT=8, FILE=”TESTE.DAT”, STATUS=”OLD”) ! READ INPUT DATA NVALS = 0 DO READ(8, 100, IOSTAT = ISTAT) TEMP ! CHECK FOR THE END OF THE FILE (DATA) IF (ISTAT < 0) EXIT NVALS = NVALS + 1 ARRAY(NVALS) = TEMP END DO Exemplo 3 Verificação do final de arquivo com uso da opção END OPEN (UNIT=8, FILE=”TESTE.DAT”, STATUS=”OLD”) ! READ INPUT DATA NVALS = 0 READ(8, 100, END=500) TEMP NVALS = NVALS + 1 ARRAY(NVALS) = TEMP 500 CLOSE(UNIT=8)

CLOSE Desconecta o arquivo lógico de um arquivo físico, tornando-o indisponível para uso no programa. O seu uso é altamente recomendável após a utilização de arquivos. Exemplo CLOSE (8) CLOSE (UNIT=8)

Page 64: 73480343-APOSTILA-F90.pdf

63

8 – Subprogramas (Funções, Subrotinas, Módulos e interfaces) Sub-programas são unidades criadas em separado do programa-principal, com o objetivo de executar tarefas específicas. Os sub-programas podem ser chamados a partir de qualquer ponto do programa solicitante. A criação de sub-programas ajuda na clareza da documentação, evita a repetição de comandos e auxilia na construção de bibliotecas de programas. Os sub-programas são compilados à parte do programa principal. Na geração do código executável, os códigos-objeto do programa principal e dos sub-programas são ligados (link), para que seja possível a interação entre eles. Em FORTRAN 77, os tipos de subprogramas disponíveis são: î Funções intrínsecas

î Funções declaração

î Funções externas

î Subrotinas

Novas implementações para Subprogramas no Fortran 90

O Fortran 90 possui novas implementações que tornam mais fácil o uso de Procedures.

1) A Interface, as características dos argumentos ou as procedures externas podem ser especificados explicitamente em uma Interface Block.

2) Uma Interface Block genérica pode especificar um nome que poderá acessar quaisquer procedures específicas dentro do bloco, dependendo da natureza atual dos argumentos.

3) Procedures Internas contidas dentro de um programa principal ou outro subprograma permitem acesso direto às entidades(variáveis) definidas no programa host.

4) Procedures recursivas são permitidas no Fortran 90; funções e subroutinas podem chamar a si mesmas direta ou indiretamente.

Page 65: 73480343-APOSTILA-F90.pdf

64

No FORTRAN 90, os tipos de subprogramas disponíveis são: î Funções intrínsecas î Funções externas î Subrotinas externas î Subrotinas e funções internas î Módulos î Interfaces î Recursividade

8.1 - Funções Intrínsecas São funções pré-definidas na linguagem. Abaixo, alguns exemplos:

Função Valor Retornado ABS(X) |X| ALOG(X) Ln X ALOG10(X) Log X SIN(X) Seno(X) COS(X) Coseno(X) MOD(I1,I2) Resto de divisão inteira entre

I1 e I2 EXP(X) ex Exemplos de funções pré-definidas pelo compilador

Y = SIN(A) + SIN(B) Z = SQRT (B**2 - 4*A*C) X = COS(SQRT(A)) TIME FUNCTION DTIME – Devolve o tempo decorrido desde o início do processamento do ultimo processo (em segundos). Exemplo REAL(4) I, TA(2), result I = DTIME(TA, result) write(*,*) 'Program has been running for', I, 'seconds.' write(*,*) ' This includes', TA(1), 'seconds of user time and', & TA(2), 'seconds of system time.'

Page 66: 73480343-APOSTILA-F90.pdf

65

Intrinsic Functions List – Fortran90 Function Definition abs(x) Absolute value of x

achar(i) ASCII Character corresponding to integer value i

acos(x) Returns the arccosine (inverse cosine) of x (x is real)

adjustl(string) Returns a character string "string" left justified

adjustr(string) Right justifies character string "string"

asin(x) Returns the arcsine (inverse sine) of x (x is real)

associated(P,T) Checks on the association status of a pointer

atan(x) Returns the arctan (inverse tangent) of x (x is real)

cos(x) Returns the cosine of x (x is not an integer)

cshift(array,shift,dim) Performs a circular shift of array along dimension dim.

dot_product(A,B) Returns the dot product of vectors A and B

exp(x) Calculates e (2.7183...) to the x power (x is not an integer)

huge(x) Returns the largest number that can be represented by a number of the same type and kind as x.

iachar(string) Returns the integer value associated with an individual character in the Ascii character set

lbound(array,dim) Returns the lower bounds declared for array along dimension dim.

len(string) Length declared for character entity "string"

len_trim(string) Returns the number of characters in "string" not including trailing blanks

log(x) Calculates the natural logarithm of x (x is not an integer and x>0)

log10(x) Calculates the base 10 log of x (x is not an integer and x>0)

matmul(a,b)

Returns the matrix which is the result of the matrix multiplication between matrices A and B. Arguments must have one or two dimensions.

max(x1, x2,...) Returns the maximum of x1, x2,... (arguments must be of the same type)

maxloc(array,mask) Returns the location of the largest

Page 67: 73480343-APOSTILA-F90.pdf

66

integer or real array element

maxval(array,dim,mask) Returns the maximum value of array along dimension dim

min(x1, x2,...) Returns the minimum of x1, x2,... (arguments must be of the same type)

minloc(array,mask) Returns the location of the array element with the smallest value

minval(array,dim,mask) Returns the minimum value of array along dimension dim

mod(i,j) Produces the remainder of the division of i by j (modulo function)

nint(x) Returns the nearest integer to the real number x

random_number(harvest) Sets a random number from the normal distribution between zero and one.

scan(string,set,back) Returns the location of the first occurrence of character in "set" within "string." Returns zero if none found.

selected_int_kind(i)

Delivers the integer specifying the KIND attribute of an integer variable that can contain numbers with at least "i" decimal digits

selected_real_kind(i,j)

Delivers the integer specifying the KIND attribute of a real variable with decimal precision of at least i digits and a decimal exponent range of j

sin(x) Returns the sine of x (x is not an integer)

sqrt(x) Returns the square root of x (x is not an integer and >0)

sum(array,dim,mask) Returns the sum of all of the elements along dimension dim.

system_clock(count, count_rate,count_max)

Subroutine which returns information about the clock of the host system.

tan(x) Returns the tangent of x (x is not an integer)

tiny(x) Returns the smallest number that can be represented by a real of the same type.

ubound(array,dim) Returns the upper bounds declared for array along dimension dim.

verify(string,set,back) Returns the location of the first character in "string" that is not in "set"

Page 68: 73480343-APOSTILA-F90.pdf

67

8.2 - Função declaração (FORTRAN 77) São funções que representam uma única expressão ( aritmética, lógica ou caracter ). Sintaxe: <nome da função>(<lista de parâmetros>) = <expressão> Onde: <nome da função> : o tipo do identificador deve concordar com o tipo da expressão Exemplo 1 - Exemplos de funções-declaração

DELTA(A,B,C)=SQRT(B**2- 4*A*C) POLY(X)= 3*X**2 - 4*X + 2 TRIG(X,Y) = SIN(X)**2 + COS(Y)**2 LOGICAL COMP COMP(X,Y) = X .LT. 7.5 .OR. Y .GT. 10

Exemplo 2 - Tabela da função 3x2-4x+2 (formato FORTRAN 77) - Observe que f(x) devolve o resultado da expressão digitada no início do programa de acordo com o valor do parâmetro x. REAL F, X, Y C DECLARACAO DA FUNCAO F(X)=3*X**2-4*X+2 C LOOP PARA A IMPRESSAO DA TABELA C NO INTERVALO [ 1.0, 5.0] com incremento 0.1 DO 100 X = 1.0,5.0, 0.1 Y=F(X) WRITE(6, 10) X, Y 10 FORMAT(‘’,10X,’X=‘,F3.1,2X,’F(X)=‘, F8.3) 100 CONTINUE END

Page 69: 73480343-APOSTILA-F90.pdf

68

8.3 – Funções Externas Retorna apenas um valor ao programa solicitante. É definida externamente, ou seja, em uma unidade separada do programa principal ou de qualquer sub-programa. A função externa tem seu início identificado pela declaração: FUNCTION <nome da função>, necessitando do comando END para indicar seu final físico. No Fortran 77, o ponto de retorno ao programa solicitante é definido através do RETURN, sendo desaconselhado o uso deste comando em novos programas. Observação: o nome da função deve aparecer pelo menos uma vez à esquerda de um comando de atribuição no corpo da função. Sintaxe: <tipo da função> FUNCTION <nome da função> (<parâmetros>) .... RETURN END Onde <tipo da função> pode ser: î INTEGER î REAL î DOUBLE PRECISION î LOGICAL î CHARACTER î ARRAY Deve corresponder ao tipo de dado retornado pela função. Exemplo REAL FUNCTION QUADF (X, A, B, C) ! FUNCTION TO EVALUATE A QUADRATIC POLYNOMIAL OF THE FORM ! QUADF = A * X ** 2 + B * X + C IMPLICIT NONE ! DECLARE ARGUMENTS REAL, INTENT(IN) :: X REAL, INTENT(IN) :: A REAL, INTENT(IN) :: B REAL, INTENT(IN) :: C ! EVALUATE EXPRESSION QUADF = A * X ** 2 * B * X * C

Page 70: 73480343-APOSTILA-F90.pdf

69

END FUNCTION Observação: O valor a ser retornado deve estar associado pelo menos uma vez, ao nome da função. PROGRAM TEST_QUADF IMPLICIT NONE REAL :: QUADF REAL :: A, B, C, X WRITE(*,*) "ENTER QUADRATIC COEFFICIENTS A, B, C: " READ (*,*) A, B, C WRITE(*,*) "ENTER LOCATION AT WHICH TO EVALUATE EQUATION:" READ (*,*) X ! WRITE OUT RESULT WRITE (*,100) "QUADF(', X, ")', QUADF(X,A,B,C) 100 FORMAT (A,F10.4,F12.4) END PROGRAM

8.4 – SUBROTINAS EXTERNAS Unidade de programa que pode retornar vários resultados para o programa solicitante. A forma do programa solicitante ativar uma determinada subrotina é através do comando CALL Sintaxe: SUBROUTINE <nome da subrotina> (<lista de parâmetros>)

......... BLOCO DE COMANDOS .........

RETURN END

Page 71: 73480343-APOSTILA-F90.pdf

70

Exemplo C SUBROTINA PARA INVERTER UM VETOR CONTENDO N ELEMENTOS SUBROUTINE INVERTE_VETOR(A, N) INTEGER :: N, TEMP, I INTEGER, DIMENSION(N) :: A DO I=1,N/2 TEMP=A(N+1-I) A(N+1-I) = A(I) A(I)= TEMP END DO END C PROGRAMA QUE CHAMA A ROTINA INVERT INTEGER A(50), DIM DIM=10 WRITE(*,*) “DIGITE VALORES PARA ELEMENTOS DO VETOR A” READ(5,*) (A(I), I=1, DIM) WRITE(*,*) “VALORES CONTIDOS NO VETOR A – ANTES SUBROUTINE” WRITE(6,*) (A(I), I=1,DIM) CALL INVERTE_VETOR(A, DIM) WRITE(*,*) “VALORES CONTIDOS NO VETOR A – DEPOIS SUBROUTINE” WRITE(6,*) (A(I), I=1,DIM) STOP END

8.5 - Sub-programas Internos São similares aos sub-programas já conhecidos (functions e subroutines), porém devendo ser inseridos dentro do programa principal ou de outros subprogramas. A declaração CONTAINS separa um sub-programa interno, do programa que o contém. Um fator limitante é que este tipo de subprograma só pode ser chamado a partir da unidade dentro da qual ele está especificado. Por outro lado, este tipo de sub-programa “herda” as variáveis do programa que o contém não sendo necessária a passagem de parâmetro, uso de common-blocks ou qualquer outra estratégia para disponibilizar o valor de uma variável a ser utilizada neste sub-programa. Ou seja, as variáveis do programa host, são consideradas globais para o sub-programa.

Page 72: 73480343-APOSTILA-F90.pdf

71

Exemplo 1 – Observe que a variável X não precisou ser passada como parâmetro! SUBROUTINE OUTER REAL X, Y ..... CALL INNER ..... CONTAINS SUBROUTINE INNER REAL Y Y = X + 1 END SUBROUTINE INNER END SUBROUTINE OUTER Exemplo 2 PROGRAM TRIANGULO REAL A, B, C PRINT *, 'ENTRE COM OS TRES LADOS DO TRIANGULO' READ *, A, B, C PRINT *, 'AREA DO TRIANGULO: ',AREATRIANGULO (A, B, C) CONTAINS FUNCTION AREATRIANGULO (A, B, C) REAL AREATRIANGULO REAL, INTENT(IN) :: A, B, C REAL THETA REAL ALTURA THETA = ACOS( (A**2 + B**2 - C**2) / (2.0*A*B) ) ALTURA = A * SIN(THETA) AREATRIANGULO = 0.5 * B * ALTURA END FUNCTION AREATRIANGULO

Page 73: 73480343-APOSTILA-F90.pdf

72

8.6 - MÓDULOS Os módulos podem substituir todos os usos de declarações include, common e funções declaração, disponibilizando variáveis, estruturas e subprogramas entre unidades. Mais abrangentes do que os common block, poderão ser feitas especificações de parâmetros, variáveis e/ou tipos; Pode-se ainda, ter um subprograma contido no módulo. Um subprograma de uso global, se existente, deverá ser iniciado pela declaração CONTAINS e estar em forma de SUBROUTINE ou FUNCTION. Subprogramas especificados dentro de módulos recebem o nome especial de MODULE PROCEDURE. Sistemas Microsoft: os módulos quando utilizados dentro de um projeto, significa que será comum ao programa principal e a todas as rotinas que chamarem o mesmo (use). Para que não dê erro na compilação do projeto, o módulo necessita ser compilado antes do programa principal (para que seja gerado o arquivo modulo.mod).

Nos sistemas UNIX/LINUX, os módulos também devem ser compilados antes do programa principal, da seguinte forma:

demo% f95 -c mod_one.f90 mod_two.f90 demo% f95 -c main.f90 demo% f95 -o main main.o mod_one.o mod_two.o

Ao compilar o programa principal main.f90, o compilador procura pelos objetos mod_one.mod e mod_two.mod. Os módulos devem ser compilados antes de quaisquer arquivos que façam referência a eles, através de declarações USE. Os módulos podem substituir todos os usos de declarações include, common e funções declaração, disponibilizando variáveis, estruturas e subprogramas entre unidades. Mais abrangentes do que os common block, poderão ser feitas especificações de parâmetros, variáveis e/ou tipos; Pode-se ainda, ter um subprograma contido no módulo. Um subprograma de uso global, se existente, deverá ser iniciado pela declaração CONTAINS e estar sob forma de SUBROUTINE ou FUNCTION. Subprogramas especificados dentro de módulos recebem o nome especial de MODULE PROCEDURE. As variáveis ou subprogramas contidos no módulo serão globais a todas as unidades que solicitarem o seu uso. Esta solicitação pode ser feita através do comando USE. Observação: SUBROUTINES e/ou FUNCTIONS contidas no módulo poderão ter, por sua vez, subprogramas internos. Dica: Variáveis que não devem ser globais ( que devem estar disponíveis somente dentro do módulo e ocultas para qualquer unidade de programa que utilize o módulo ) poderão utilizar o atributo PRIVATE. Por default, todos os dados são do tipo PUBLIC. INTEGER, PRIVATE :: N, X

Page 74: 73480343-APOSTILA-F90.pdf

73

Importante: Um módulo pode conter arrays alocáveis globais USE A declaração USE, torna um módulo disponível, proporcionando acesso a todos os objetos de dados públicos, tipos derivados, interfaces e subprogramas, contidos no módulo nomeado. Sintaxe: USE <nome do módulo> Exemplo 1 - Observe que, apesar de não serem utilizadas nem as listas de argumentos, nem o common, a subrotina "reconhece" os valores das variáveis a e b. Estes valores estão sendo compartilhados através do module. MODULE VARIAVEIS INTEGER A, B END MODULE PROGRAM TROCA USE VARIAVEIS A = 10 B = 20 CALL SUB PRINT *, A, B ! Valor Impresso pelo programa: 20, 10 END PROGRAM SUBROUTINE SUB USE VARIAVEIS INTEGER CTEMP CTEMP = A A = B B = CTEMP END SUBROUTINE

Page 75: 73480343-APOSTILA-F90.pdf

74

Exemplo 2 MODULE MatrixVectorOperations INTEGER, PARAMETER :: N = 3 ! n=3 -> constante global CONTAINS FUNCTION MatrixVectorMultiply ( A, B ) RESULT (C) IMPLICIT NONE REAL, DIMENSION (:, :), INTENT (IN) :: A REAL, DIMENSION (:), INTENT (IN) :: B REAL, DIMENSION(SIZE(B)) :: C INTEGER N INTEGER I N = SIZE(B) C = 0.0 DO I = 1, N

C = C + B( I ) * A ( :, I ) ENDDO END FUNCTION MatrixVectorMultiply END MODULE MatrixVectorOperations PROGRAM MatrixVector USE MatrixVectorOperations IMPLICIT NONE REAL, DIMENSION ( N, N ) :: A REAL, DIMENSION ( N ) :: B, C ! Preenche A e B com entradas randômicas CALL RANDOM_NUMBER (A) CALL RANDOM_NUMBER (B) ! Calcula o produto A * B C = MatrixVectorMultiply ( A, B) PRINT *, ‘ O produto e : ‘, C END PROGRAM MatrixVector

Page 76: 73480343-APOSTILA-F90.pdf

75

8.7 – COMPARTILHANDO DADOS COM SUBPROGRAMAS No FORTRAN 77, o compartilhamento de valores entre programa principal e subprogramas (ou entre subprogramas), podia ser realizado de duas formas: a) Através de lista de Argumentos b) Utilizando-se o COMMON Block No Fortran 90, além destas duas formas, existe uma terceira que é a utilização de módulos, conforme foi visto em exemplo anterior. Em todos estes casos, o compartilhamento de dados é realizado através de passagem por referência (Pass-by_Reference Scheme); Isto significa que as alterações realizadas sobre um determinado argumento dentro de um subprograma são definitivas, retornando ao programa solicitante com valor alterado. A lista de variáveis e/ou subprogramas inseridos dentro de um módulo tornam-se globais à todas as unidades que utilizá-lo. O uso de módulos é fortemente recomendado em substituição às declarações COMMON. Utilizando-se o COMMON Block , é preciso que se tenha um controle rigoroso para garantir que todas as variáveis aparecem na mesma ordem, tendo o mesmo tipo e tamanho em todas as unidades que o contém. A seguir, são mostrados exemplos utilizando as opções COMMON, lista de argumentos e módulos. Opção 1 – Lista de Argumentos C programa exemplo utilizando lista de argumentos SUBROUTINE ROTINA(X) X = X + 20 END SUBROUTINE INTEGER C C = 15 CALL ROTINA(C) PRINT *, ‘C= ‘, C END Valor Impresso: C= 35

Page 77: 73480343-APOSTILA-F90.pdf

76

Opção 2 - COMMON C programa exemplo utilizando COMMON SUBROUTINE ROTINA COMMON /VARIAVEL/ X X = X + 20 END SUBROUTINE INTEGER C COMMON /VARIAVEL/ C C = 15 CALL ROTINA PRINT *, ‘C= ‘, C END Valor Impresso: C= 35

Opção 3 - Módulos MODULE SHARE INTEGER C END MODULE SUBROUTINE ROTINA USE SHARE C = C + 20 END SUBROUTINE C programa exemplo utilizando MODULE USE SHARE C = 15 CALL ROTINA PRINT *, ‘C= ‘, C END Valor Impresso: C= 35

Page 78: 73480343-APOSTILA-F90.pdf

77

8.8 - Passando arrays para Sub-Programas Há pelo menos cinco diferentes formas de passar arrays de tamanho desconhecido para sub-programas. Três delas, foram herdadas do Fortran 77 e duas, são implementações novas do Fortran 90. Considere a seguinte declaração e inicialização de um array 2 x 3:

program unknown integer, parameter :: n = 2 integer, parameter :: m= 3 integer :: length = n*m integer, dimension(n,m) :: table table = reshape ((/1, 2, 3, 4, 5, 6/), (/n, m/) ) print *, ‘Programa Principal’ print 100, table

100 format (‘ ‘, 3i5) Resultado: 1 2 3 4 5 6

UTILIZANDO O ARRAY DECLARADO, SERÃO MOSTRADAS DIFERENTES FORMAS DE UTILIZÁ-LO EM SUBROTINAS

Passagem de Arrays para Sub-Rotinas - Técnicas Tradicionais 1) Declarando array como vetor de um elemento, dentro da subrotina

Chamada no Programa Principal Subrotina length = m*n call ones ( table, length)

subroutine ones (table, length ) integer table(1) , length do I = 1, length table(I) = table(I) + 6 enddo print 100, ( table(I), I= 1, length ) 100 format (‘ones’, 3i5 ) end subroutine ones

Resultado: 7 8 9

10 11 12

Page 79: 73480343-APOSTILA-F90.pdf

78

Esta técnica esconde a forma (shape) do vetor na sub-rotina, mas é preciso conhecer o número total de elementos para poder realizar qualquer operação com o array , tais como no do-loop e print. Ou seja, neste caso, não é possível escrever simplesmente (o sub-programa não sabe que o array possui seis elementos ):

table = table + 6 ou

print 100, table Além disso, nenhuma das construções de array ou intrínsecas do Fortran90 podem ser utilizadas, pois table tem o mesmo tamanho, tanto no programa principal quanto na subrotina ONES, mas não tem a mesma forma (shape) Compartilhando array de tamanho desconhecido através do caracter *. O uso de um asterisco no dimensionamento de um array dentro de uma rotina, serve para defini-lo como sendo um array assumed size, ou seja, de tamanho conforme o que foi definido no programa principal.

Chamada no Programa Principal Subrotina length = m*n call star ( table, length )

subroutine star(table, length) integer table(*), length do I = 1, length table(I) = table(I) + 6 enddo print 100, (table(I), I = 1, length ) 100 format( ‘star ‘, 3i5 ) end subroutine star

Resultado:

star 13 14 15 star 16 17 18 Também neste caso, o tamanho do array permanece desconhecido, porém nenhuma operação com arrays proveniente do Fortran 90 está disponível

Page 80: 73480343-APOSTILA-F90.pdf

79

3) Declarando explicitamente o array, exceto para a última dimensão O shape é utilizado, mas o último tamanho não é especificado. Ou seja, estes arrays são declarados com tamanho explícito em todas as dimensões, exceto na última, que é deixada ilimitada.

Chamada no Programa Principal Subrotina length = m*n call asize ( table, length, n )

subroutine asize (table, length, n) integer table (n,*), length k = length/n do j = 1, k do I = 1, n table(I,j) = table(I,j) + 6 enddo print 100, ((table(I,j), I=1,n), j=1,k) 100 format (‘Assumed Size ‘, 3i5) end subroutine asize

Resultado:

Assumed Size 19 20 21 Assumed Size 22 23 24 Todas as restrições discutidas para os dois exemplos anteriores ainda se aplicam a este caso. Somente as funções LBOUND, UBOUND, SIZE do Fortran90 são permitidas dentro da subrotina, mesmo assim para as dimensões declaradas explicitamente Passagem de Arrays para Sub-Rotinas – Técnicas do Fortran90 No Fortran90, foram introduzidas duas técnicas para esconder o shape e size de um array dentro de um subprograma. Tal escolha depende do fato de o sub-programa ser declarado como interno ou externo.

Page 81: 73480343-APOSTILA-F90.pdf

80

Sub-Programa Interno Conforme foi visto, a declaração CONTAINS sinaliza o início de um sub-programa interno. Os arrays nos subprogramas internos devem sempre ter o mesmo número de dimensões definido no programa principal, mas cada dimensão pode ter um número qualquer de elementos Exemplo 1 - Programa Principal com Subrotina Interna

program unknown . . call inside(table) . . contains subroutine inside(table) integer, dimension(:, :) :: table table = table + 6 print 100, table 100 format ('Assumed Shape ', 3i5) end subroutine inside end program unknown

Resultado:

Assumed Shape 25 26 27 Assumed Shape 28 29 30 Neste sub-programa o formato(shape) do array table é fixado em duas dimensões, concordando com o programa solicitante, enquanto que o tamanho de cada dimensão é herdado dele. Todas as operações do FORTRAN 90 para a manipulação de arrays são permitidas neste caso.

Page 82: 73480343-APOSTILA-F90.pdf

81

Sub-Programa Externo Para os tradicionais subprogramas externos, a técnica para array de tamanho assumido requer uma outra nova implementação do FORTRAN 90, a Interface Block. Tais blocos fazem a interface explícita entre procedures.

program unknown interface subroutine ashape(table) integer, dimension(:,:) :: table end subroutine ashape end interface integer, parameter :: n = 2 integer, parameter :: m= 3 integer :: length = n*m integer, dimension(n,m) :: table . . call ashape(table) .

end program unknown

Page 83: 73480343-APOSTILA-F90.pdf

82

8.9 – Permissões de Acesso para parâmetros passados para Módulos e Sub-Programas PUBLIC X PRIVATE PUBLIC(default): especifica que elementos contidos em um módulo são globais. Poderão ser acessados fora do módulo através da declaração USE PRIVATE: tornam os objetos contidos em um módulo, acessíveis somente dentro deste. Não estão disponíveis para o programa que acessa o módulo via declaração USE Pode-se ter Tipos Derivados declarados dentro de módulos com atributo PUBLIC, que contenham campos do tipo PRIVATE Exemplo

MODULE M PRIVATE, REAL :: R, K, TEMP(100) ! R, K, TEMP são PRIVATE REAL, PUBLIC :: A(100), B(100) ! A e B são PUBLIC END MODULE M

INTENT Este atributo especifica a forma de acesso aos parâmetros passados para um subprograma (leitura, gravação, leitura e gravação); permite controle e proteção aos dados compartilhados entre unidades, sendo útil na criação de bibliotecas e rotinas externas. Argumentos utilizados na especificação deste atributo: IN : Os parâmetros passados para o subprograma não podem ter seus valores alterados OUT : O parâmetro será definido dentro do subprograma e terá seu valor retornado para o programa principal INOUT: O parâmetro será utilizado para comunicação de informações entre o programa principal e o subprograma, fornecendo valores a este e retornando com novos dados Obs: A declaração INTENT só pode ser utilizada dentro de sub-programas e Interfaces.

Page 84: 73480343-APOSTILA-F90.pdf

83

Exemplo

SUBROUTINE MOVE (FROM, TO) USE PERSON_MODULE TYPE(PERSON), INTENT(IN) :: FROM TYPE (PERSON), INTENT(OUT) :: TO ....... SUBROUTINE SUB(X, Y) INTEGER, INTENT(INOUT) :: X, Y

OPTIONAL Com este atributo, parâmetros podem ser passados ou não para a procedure, dependendo de uma condição específica. A função Intrínseca PRESENT pode ser usada para testar a presença de um parâmetro opcional dentro da procedure; este teste pode ser usado para controlar o processamento na procedure. Exemplo

CALL SORT_X ( X = VECTOR_A ) ..... SUBROUTINE SORT_X (X, SIZEX, FAST) REAL, INTENT (INOUT) :: X (:) INTEGER, INTENT(IN), OPTIONAL :: SIZEX LOGICAL, INTENT(IN), OPTIONAL :: FAST ..... INTEGER TSIZE ..... IF (PRESENT(SIZEX) ) THEN TSIZE = SIZEX ELSE TSIZE = SIZE(X) END IF IF (.NOT. PRESENT(FAST) .AND. & TSIZE > 1000 ) THEN CALL QUICK_SORT(X) ELSE CALL BUBBLE_SORT(X) END IF

....

Page 85: 73480343-APOSTILA-F90.pdf

84

8.10 – RECURSIVE FUNCTIONS RECURSIVIDADE EM SUBROTINAS E FUNÇÕES - FORTRAN 90 Os sub-programas tradicionais escritos em Fortran, não possuem característica recursiva. Existem certos problemas que são mais facilmente resolvidos de forma recursiva. Como exemplo, a função fatorial pode ser definida como:

Esta definição pode ser implementada recursivamente, através de um procedimento que calcula N!, chamando a ele mesmo para calcular (N-1)! , que por sua vez calcula (N-2)! , etc, até calcular 0!. Para a resolução de tais problemas, o Fortran permite que funções e subrotinas sejam declaradas como recursivas. Ou seja, se uma subrotina ou função for declarada como recursiva, o compilador irá implementá-la de forma que ela possa chamar a ela mesma, direta ou indiretamente. Para a utilização da recursividade, uma FUNCTION ou SUBROUTINE deverá ter sintaxe diferente daquela normalmente utilizada, contendo uma nova palavra-chave: RECURSIVE A declaração RECURSIVE, serve para que o compilador possa preparar a função ou subrotina adequadamente para a sua auto-chamada ( através do uso de stacks para as variáveis locais). O uso de uma function recursiva, ainda permite o uso da palavra-chave RESULT, que servirá para armazenar o valor final a ser retornado pela função.

Sintaxe: <tipo> recursive function <nomedafunção> ( argumentos ) result ( variável ) ou recursive <tipo> function <nomedafunção> ( argumentos ) result ( variável )

Exemplo: Implementação de Função Recursiva para calcular fatorial recursive function fact(n) result(answer) integer :: n, answer if ( n >= 1 ) then answer = n * fact(n-1) else answer = 1 endif end function fact

=>=−

=0n;1

1n;)!1n(n!N

Page 86: 73480343-APOSTILA-F90.pdf

85

9 – ESTRUTURAS DINÂMICAS DE DADOS - Arrays e Pointers No Fortran tradicional, somente era permitida a alocação de memória estática, sequencial. Em muitas circunstâncias, este modelo de alocação tornava-se dispendioso, sobretudo quando não era possível precisar a priori, a quantidade de elementos que iriam ser utilizados no decorrer do programa. A utilização de declarações tais como o COMMON e o EQUIVALENCE, ajudava a resolver tal problema, permitindo o uso compartilhado de áreas de memória por unidades diferentes de programa. No entanto, tais implementações, além de não resolver definitivamente o problema de alocação de recursos, ainda são consideradas inseguras: Um pequeno deslize na programação pode causar superposição e destruição indesejada de valores contidos na memória. Já o Fortran90 oferece a possibilidade de uso de memória dinâmica, permitindo a alocação de unidades de memória no decorrer da execução do programa. Isto é possível através das seguintes implementações: î Arrays tipo allocatable î Pointer î Arrays tipo automatic î arrays tipo assumed-shape

Page 87: 73480343-APOSTILA-F90.pdf

86

9.1 - ARRAYS ALOCÁVEIS ( ALLOCATABLE ARRAYS ) Se o número de elementos para a dimensão de um array não for especificado, isto significa que este deverá ter o atributo Allocatable ou Pointer. O uso do atributo allocatable, exige que um array seja declarado com dimensões definidas e limites indefinidos. Ou seja, os limites de uma dada dimensão é estabelecida durante a execução do programa. Isto evita o tradicional super-dimensionamento de arrays no início dos programas. Um array declarado com este atributo, somente estará disponível após a utilização da declaração ALLOCATE.

INTEGER N REAL, DIMENSION (:), ALLOCATABLE :: WORK

.... N = 50 ALLOCATE ( WORK(N) ) .... .... .... END Exemplo Temperatura medida nas escalas: Fahrenheit, Celsius e Kelvin. A alocação do array com limites que variam em cada escala, pode ser feita da forma a seguir:

program temperatura integer, dimension( : ), allocatable :: graus integer :: erro integer, dimension(3, 2) :: limites = & / -460, 0, -274, 212, 100, 374 / integer :: escala = 0 logical :: true_false print *, 'Fahrenheit, Centigrados ou Kelvin? ( 1, 2, 3 ) ' read (*,*) escala allocate ( graus(limites(escala,1):limites(escala,2),stat=erro) if (erro.eq. 0) then print *, 'Erro de Alocação: ') else print *, 'GRAUS alocado de ', & limites(escala,1) ', 'ate ',limites(escala,2) endif end program temperatura

Page 88: 73480343-APOSTILA-F90.pdf

87

Observação: Atenção à disposição dos valores iniciais no array limites! Se por algum motivo, a memória não puder ser alocada, o status do comando allocate devolverá algum valor positivo

ALLOCATED Informa se um array já foi alocado ou não Exemplo:

true_false = allocated(graus) if ( true_false ) then print *, 'Array GRAUS ja foi alocado' else print *, ' Array nao possui limites definidos' endif

DEALLOCATE Libera memória anteriormente alocada para um array. Exemplo 1 - utilização do comando deallocate

deallocate ( graus, stat=erro ) if ( erro .ne. 0 ) then

print *, 'Erro! Array nao foi alocado anteriormente! ' endif

Exemplo 2 - utilização do comando deallocate ao final do uso do array

program query_array_size integer, dimension(:), allocatable :: array integer :: array_length write (*, 100, ADVANCE='NO') 100 format ( ' ', 'Entre com o tamanho do array : ' read (*, *) array_length allocate ( array(array_length)) ... ! operacoes com o array.... deallocate(array) end program query_array_size

Page 89: 73480343-APOSTILA-F90.pdf

88

Arrays alocáveis não podem aparecer definidos em um COMMON. Sendo assim, como então passar arrays alocáveis para sub-programas? A solução é através da estrutura MODULE que deixa o array disponível para subprogramas da seguinte forma:

module global integer, dimension(:) , allocatable :: graus end module global

Para disponibilizar o módulo em um programa, utilize a declaração USE: use global

Observação: O resultado (RESULT) de uma função recursiva não pode ser um array alocável. Esta implementação pode ser substituida por POINTERs e TARGETs.

9.2 - POINTERS Pointers (ponteiros) são tipos especiais de variáveis que contém o endereço de memória de outra variável que contém um valor. Uma vez que novas variáveis podem ir sendo endereçadas dinamicamente, estas estruturas são úteis quando é necessário criar e destruir variáveis durante a execução do código e quando não é conhecido o número total de variáveis a serem utilizadas. O uso de ponteiros possibilita a criação de: î Seções dinâmicas de arrays î Estruturas de dados ajustáveis î Listas linkadas î Árvores î Grafos Exemplo 1

REAL, TARGET :: B(10,10) REAL, POINTER :: A( :, : ) A => B

Page 90: 73480343-APOSTILA-F90.pdf

89

Exemplo 2

program point integer, pointer :: p, q integer, target :: n integer m n = 5 p => n q => p allocate (p) p = 4 m = p + q + n print *, “m=“, m end program point

O significado do atributo TARGET Um pointer é uma variável, que contém a locação de memória de outra variável, com atributo target. O target é uma variável comum, de mesmo tipo do pointer. Se o target é uma variável comum, por que é necessário associar este atributo especial para a mesma? Outras linguagens tais como o C, não trabalham desta forma. A razão deve-se à forma como os compiladores FORTRAN funcionam. O FORTRAN normalmente é usado para problemas numericamente intensivos e os compiladores contém implem entações para produzir resultados o mais rápido possível. Estes compiladores incluem um otimizador como parte do processo de compilação do algoritmo. O otimizador examina o código, re-arranja, desmembra loops, elimina sub-expressões comuns e etc., a fim de aumentar a velocidade final de execução. Como parte deste processo de otimização, algumas variáveis no programa original podem desaparecer no processo de compilação, tendo sido combinadas ou substituídas por valores temporários nos registradores. Então, o que aconteceria se uma variável que desejamos apontar, fosse otimizada, deixando de existir? Ocorreria um erro ao apontá-la! É possível para o compilador, analisar um programa e determinar quando ou não cada variável individual será utilizada como um target, mas o processo é pouco prático. Sendo assim, o atributo target diz ao compilador que uma determinada variável será utilizada por um pointer e que por isto, não deve ser eliminada durante o processo de compilação do código.

Page 91: 73480343-APOSTILA-F90.pdf

90

Exemplo 3 - Exemplo de POINTER associado a um TARGET, durante a execução do programa.

program switch integer, target :: a(2, 2) integer, target :: b(3, 3) integer, pointer :: p( :, : ) a = reshape ( / 1, 2, 3, 4 /), (/ 2, 2 /) b = reshape (/ 5, 6, 7, 8, 9, 10, 11, 12, 13 /), ( / 3, 3 /) write ( *, 100, advance = 'NO ') 100 format ( ' ', ‘Selecione a(2,2) ou b( 3,3 ) – ‘,& ‘digite a ou b : ' ) read (*,*) choice if ( choice .eq. 'a' ) p => a if ( choice .eq. 'b' ) p => b print *, ' Ponteiro direcionado para array ', choice, ': ' print *, ' P = ', p nullify (p) end program switch

î O atributo target informa ao computador quais são as variáveis que podem ser

utilizadas por ponteiros î O símbolo ‘=>’ associa um target a um pointer î Um pointer tem três estados possiveis: Associated, Disassociated ou Undefined Veja o exemplo de uso de POINTER no código HEAT.F95 Exemplo – Código completo: Inserção e remoção de elementos de uma lista de ponteiros

PROGRAM POINT TYPE LISTA INTEGER :: NUM TYPE(LISTA), POINTER :: PROXIMO END TYPE LISTA TYPE(LISTA), POINTER :: INICIO, PROX, TEMP ALLOCATE(INICIO) PROX => INICIO DO PRINT *, 'ENTRE COM UM NUMERO:' READ *, PROX%NUM

Page 92: 73480343-APOSTILA-F90.pdf

91

IF (PROX%NUM == 0) EXIT ALLOCATE(PROX%PROXIMO) PROX => PROX%PROXIMO ENDDO NULLIFY(PROX%PROXIMO)

! IMPRESSAO DOS NUMEROS DIGITADOS PROX => INICIO DO

IF (.NOT. ASSOCIATED(PROX%PROXIMO)) EXIT WRITE(*,*) PROX%NUM PROX => PROX%PROXIMO ENDDO ! ROTINA PARA INSERIR ELEMENTO NA LISTA (APÓS 4. ELEMENTO) CALL INSERE ! ROTINA PARA RETIRAR ELEMENTO DA LISTA (O 4. ELEMENTO) CALL REMOVE CONTAINS SUBROUTINE INSERE PROX => INICIO I = 1 DO WHILE (I < 4) PROX => PROX%PROXIMO I = I + 1 ENDDO ALLOCATE(TEMP) PRINT *, 'DIGITE NUMERO A SER INSERIDO:' READ *, TEMP%NUM TEMP%PROXIMO => PROX%PROXIMO PROX%PROXIMO => TEMP ! IMPRESSAO DOS NUMEROS DA LISTA PROX => INICIO DO IF (.NOT. ASSOCIATED(PROX%PROXIMO)) EXIT WRITE(*,*) PROX%NUM PROX => PROX%PROXIMO ENDDO END SUBROUTINE INSERE ! SUBROTINA PARA REMOCAO DE NUMERO

Page 93: 73480343-APOSTILA-F90.pdf

92

SUBROUTINE REMOVE PROX => INICIO I = 1 DO WHILE (I < 4) PROX => PROX%PROXIMO I = I + 1 ENDDO PROX = PROX%PROXIMO ! DEALLOCATE (PROX%PROXIMO) ! IMPRESSAO DOS NUMEROS DA LISTA

PROX => INICIO DO IF (.NOT. ASSOCIATED(PROX%PROXIMO)) EXIT WRITE(*,*) PROX%NUM PROX => PROX%PROXIMO ENDDO END SUBROUTINE REMOVE ! OBS: OBRIGATORIO A ESPECIFICACAO: SUBROUTINE <NOME> END ! FIM PROGRAMA PRINCIPAL

9.3 - ESTRUTURAS DINÂMICAS DE DADOS - LISTAS LINKADAS A técnica básica para a utilização de uma lista linkada é criar um tipo derivado que consistirá de um ou mais elementos de dados e pelo menos um ponteiro. Sendo assim, a memória é alocada para conter o dado e o ponteiro é setado para a próxima ocorrência de dado. Se houver apenas um ponteiro a lista é simplesmente linkada e poderá ser percorrida em apenas uma direção. Exemplo 1 – Código completo: Inserção de elementos na lista linkada Program lista_link type person integer :: age character(len=50) :: name type (person), pointer :: forward end type person type (person), pointer :: inic, prox

Page 94: 73480343-APOSTILA-F90.pdf

93

type (person) :: temp integer :: io temp % age = 0 temp % name= ' ' nullify ( temp%forward ) allocate( inic ) if (.not. associated (inic)) stop "erro de alocacao" ! primeiro passo - le para a lista prox => inic do prox = temp read (*,*,iostat=io) prox%age, prox%name if ( io < 0 .or. prox%age .eq. 0) exit allocate(prox%forward) if ( .not. associated (prox%forward)) stop "erro" prox => prox % forward end do 100 continue ! imprime prox => inic do if (.not. associated ( prox%forward ) exit write (*,*) prox%age, prox%name prox => prox%forward end do end

9.4 - AUTOMATIC ARRAYS Os arrays criados são locais e temporários. A memória para o array é alocada quando o subprograma inicia e é liberada ao final da execução do mesmo. Exemplo

SUBROUTINE SOMA(I,J,K) REAL, DIMENSION(I,J,K) :: X ou SUBROUTINE SOMA(I,J,K) REAL :: X(I,J,K)

Page 95: 73480343-APOSTILA-F90.pdf

94

10 - MIXED LANGUAGE PROGRAMMING A seguir, são mostrados alguns exemplos de interação entre códigos escritos em FORTRAN e outras linguagens (C, Visual Basic, Delphi).

10.1 – Visual Basic x FORTRAN90 Programa Principal em VISUAL BASIC e Subrotina em FORTRAN 90. A Subrotina em FORTRAN é salva como DLL e chamada dentro do VISUAL BASIC para cálculos.

I - PARTE FORTRAN (DLL) subroutine ROTINA_FORTRAN (IEP, NMAT, rT1, rT2, RCALOR, TRMAX1) !DEC$ ATTRIBUTES DLLEXPORT :: ROTINA_FORTRAN !DEC$ ATTRIBUTES ALIAS:' ROTINA_FORTRAN ' :: ROTINA_FORTRAN IMPLICIT NONE INTEGER NDIV parameter (ndiv = 10) ! DEFINICAO DAS VARIAVEIS EXTERNAS - RECEBIDAS DO VISUAL BASIC INTEGER, INTENT(IN) :: IEP, NMAT REAL(8), INTENT(IN) :: rT1, rT2 REAL(8), INTENT(IN) :: rCALOR(*) ! DEFINICAO DAS VARIAVEIS ENVIADAS PARA O VISUAL BASIC REAL(8), INTENT(OUT) :: TRMAX1(40,2)

Page 96: 73480343-APOSTILA-F90.pdf

95

II - PARTE VISUAL BASIC – DECLARACOES PUBLICAS DA ROTINA E CHAMADA. FOI CRIADO UM MODULE DENTRO DO PROJETO VB 'Declaração da DLL Declare Sub ROTINA_FORTRAN Lib "ROTINA_FORTRAN.dll" Alias " ROTINA_FORTRAN " (ByVal dir As String, ByVal nc As Long)

10.2 – FORTRAN90 X C I – PROGRAMA PRINCIPAL EM FORTRAN QUE CHAMA SUBROTINA EM C NO VISUAL FORTRAN É NECESSÁRIO CRIAR INTERFACE PARA COMPARTILHAR VARIAVEIS QUE SERÃO PASSADAS COMO PARAMETROS PARA AS ROTINAS EM C. NOS SISTEMAS LINUX, BASTA COMPILAR OS PROGRAMAS SEPARADAMENTE E DEPOIS LINK-EDITÁ-LOS, TENDO O CUIDADO DE COMPATIBILIZAR OS TIPOS DE VARIÁVEIS ENTRE AS LINGUAGENS. INTERFACE SUBROUTINE routine1(a, b, c) !DEC$ ATTRIBUTES C :: routine1 INTEGER C real(8) A(*), B(*) END SUBROUTINE routine1 END INTERFACE REAL(KIND=8), DIMENSION(3) :: A = (/1., 2.,3./) REAL(KIND=8), DIMENSION(2) :: B = (/100.,200./) INTEGER :: C = 1000 CALL ROUTINE1(A,B,C) print * END

Page 97: 73480343-APOSTILA-F90.pdf

96

#include <stdio.h> void routine1 (a, b, c) double *a, *b; int c; { int x; printf ("%d\n",c); for(x=0;x< 1;x++); { printf("%d,%f\n",x,a[x]); } }

10.3 – PROGRAMA PRINCIPAL EM DELPHI x FUNÇÃO EM FORTRAN90 I - PROGRAMA .PAS – DELPHI unit Calldvf1; interface uses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, DVFRoutines; type TFCallDvf = class(TForm) LGetInteger: TLabel; LGetFloat: TLabel; LGetString: TLabel; EGetInteger: TEdit; EGetFloat: TEdit; EGetString: TEdit; BCallFortran: TButton; LPutInteger: TLabel; LPutFloat: TLabel; LPutString: TLabel; EPutInteger: TEdit; EPutFloat: TEdit;

Page 98: 73480343-APOSTILA-F90.pdf

97

EPutString: TEdit; BOk: TButton; BClear: TButton; procedure BCallFortranClick(Sender: TObject); procedure BOkClick(Sender: TObject); procedure BClearClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var FCallDvf: TFCallDvf; implementation {$R *.DFM} procedure TFCallDvf.BCallFortranClick(Sender: TObject); var tmpInt1 : Longint; tmpInt2 : Longint; tmpSingl1 : Single; tmpSingl2 : Single; tmpPChar2 : array[1..80] of Char; tmpPCharLen : Longint; begin tmpInt1 := strToInt(EGetInteger.Text); tmpInt2 := FortFunInt(tmpInt1); EPutInteger.Text := intToStr(tmpInt2); tmpSingl1 := strToFloat(EGetFloat.Text); tmpSingl2 := FortFunSingle(tmpSingl1); EPutFloat.Text := FLoatToStr(tmpSingl2); tmpPCharLen := 80; FortFunString(@tmpPChar2, tmpPCharLen, PChar(EGetString.Text)); EPutString.Text := tmpPChar2; BOk.default := true; end; procedure TFCallDvf.BOkClick(Sender: TObject); begin close; end; procedure TFCallDvf.BClearClick(Sender: TObject);

Page 99: 73480343-APOSTILA-F90.pdf

98

begin EGetInteger.clear; EGetFloat.clear; EGetString.clear; EPutInteger.clear; EPutFloat.clear; EPutString.clear; BCallFortran.default := true; BOk.default := false; end; end.

II - PROGRAMA FORTRAN COM INTERFACE PARA DELPHI ! This Fortran code is intended to be called from another language ! In this sample, that is Borland Delphi ! There are three routines in this file: ! Function FortFunInt (integer*4 IArg) ! returns 2xIarg as Integer*4 ! Function FortFunSingle (real*4 FArg) ! returns SQRT(Farg) or 0 if Farg < 0 ! Function FortFunString (string Sarg) ! returns a string with the case inverted ! The string argument is passed by reference only ! and the return argument is returned in hidden ! first and second arguments. ! This project is provided as x86-only INTEGER*4 Function FortFunInt (iArg) !DEC$ ATTRIBUTES STDCALL, DLLEXPORT :: FortFunInt !DEC$ ATTRIBUTES ALIAS : "_fortfunint" :: FortFunInt integer iArg; FortFunInt = 2*iArg return end function FortFunInt Real*4 Function FortFunSingle (fArg) !DEC$ ATTRIBUTES STDCALL, DLLEXPORT :: FortFunSingle !DEC$ ATTRIBUTES ALIAS : "_fortfunsingle" :: FortFunSingle Real *4 fArg if (fArg .le. 0) then FortFunSingle = 0

Page 100: 73480343-APOSTILA-F90.pdf

99

else FortFunSingle = SQRT(fArg) endif return end function FortFunSingle Character *(*) function FortFunString (sArg) Implicit none !DEC$ ATTRIBUTES STDCALL, DLLEXPORT :: FortFunString !DEC$ ATTRIBUTES ALIAS : "_fortfunstring" :: FortFunString character(255) sArg !Passed in as a null-terminated string !DEC$ ATTRIBUTES REFERENCE :: sArg Integer lenInput integer lenOutput Integer i, j lenInput = index(sArg, char(0)) lenOutput = len(FortFunString)-1 i = min(leninput, lenoutput) do j=1, i if (sArg(j:j) .le. 'z' .and. sArg(j:j) .gt. 'a') then FortFunString(j:j) = char (ichar(sArg(j:j)) - 32) else if (sArg(j:j) .le. 'Z' .and. sArg(j:j) .gt. 'A') then FortFunString(j:j) = char (ichar(sArg(j:j)) + 32) else FortFunString(j:j) = sArg(j:j) endif endif enddo FortFunString(i+1:i+1) = char(0) return end

Page 101: 73480343-APOSTILA-F90.pdf

100

11- REFERÊNCIAS î Stephen J. Chapman; “Fortran 90/95 for Scientists and Engineers”, Mc-Graw-Hill,

Boston, USA, 1998 î James Kerrigan; “Migrating to Fortran90”, O’Reilly & Associates, Inc. î William Press [et al.]; “ Numerical Recipes in Fortran”, Cambridge University

Press, 1992 î http://www.nsc.liu.se/~boein/FORTRAN 77to90 - Tutorial and Exercises

î http://acesgrid.org/ - The Alliance for Computational Earth Science (ACES) at M.I.T focuses on developing and deploying advanced computational technologies to address challenging problems of Earth science.

î ACES is a platform for cross-disciplinary collaboration between Earth science researchers and computer science researchers at MIT. Several different groups are participating in the ACES effort - you can read about some of their projects on this web site.

î http://www.kcl.ac.uk/kis/support/cit/fortran/engfaq.html - Fortran 90 Frequently Asked

about News î http://www.openmp.org/drupal/ - The OpenMP Application Program Interface (API)

supports multi-platform shared-memory parallel programming in C/C++ and Fortran on all architectures, including Unix platforms and Windows NT platforms. Jointly defined by a group of major computer hardware and software vendors, OpenMP is a portable, scalable model that gives shared-memory parallel programmers a simple and flexible interface for developing parallel applications for platforms ranging from the desktop to the supercomputer.

î http://www.posc.org/ - POSC, the Petrotechnical Open Standards Consortium, is an

international, not-for-profit, membership organization. POSC is uniquely designed to unite industry people, issues and ideas to collaboratively address E&P information challenges and opportunities. POSC's energy eStandards are open specifications for improving E&P business performance by leveraging Internet technologies in the integration of oil and gas business processes.