Fortran 90/95

João Batista Aparecido

DEM/FEIS/UNESP
Ilha Solteira, SP/BR – Agosto 2013

Fortran 90/95

Caros leitores:
Possíveis correções/sugestões devem ser enviadas para JBA em
jbaparecido@dem.feis.unesp.br e/ou jbaparecido@gmail.com. Para efeito de referência essa é
a versão F9095.JBA.22.AGO.2013.
Cheers, JBA

Versão primeira de janeiro 1999. Versao atual impressa (*.pdf) em 22 de agosto de 2013
Autor: João Batista Aparecido – jbaparecido@dem.feis.unesp.br e jbaparecido@gmail.com

2

Fortran 90/95

CAPÍTULO 1
INTRODUÇÃO À LINGUAGEM FORTRAN
O ser humano sempre esteve envolvido com as questões de contar, calcular, e
armazenar informações. Ao longo do tempo desenvolveu-se os mais variados objetos para
atingir estes objetivos. Até uns trinta anos atrás utilizava-se nos cursos de engenharia as
réguas de cálculo. Uma das mais importantes invenções deste século foi computador
eletrônico que realiza estes objetivos com razoável precisão e com bastante velocidade.
Um programa (ou conjunto de programas) armazenados na memória do computador
informa a ele qual seqüência de cálculo é necessária e em quais dados executar as instruções.
1.1 O computador
Na Figura 1.1 mostra-se um diagrama de bloco de um computador típico, constituído
pela Unidade de Processamento Central (CPU-Central Processing Unit), pela memória
principal, pela memória secundária, e pelas unidades de entrada e saída de dados.
Unidade de processamento central

Unidades de
entrada de
dados

Memória interna (registros)

Unidades
de saída de
dados

Unidade de controle

Memória
principal
Unidade de lógica aritmética

Memória
secundária

Figura 1.1- Esquema de um computador.

1.1.1. A CPU
A parte principal do computador é a Unidade de Processamento Central (CPU-Central
Processing Unit). Ela é constituída pela Unidade de Controle, que controla as outras partes do
computador; pela Unidade de Lógica Aritmética (ALU-Arithmetic Logic Unit); e pelas
memórias internas (também conhecidas como registros).
Versão primeira de janeiro 1999. Versao atual impressa (*.pdf) em 22 de agosto de 2013
Autor: João Batista Aparecido – jbaparecido@dem.feis.unesp.br e jbaparecido@gmail.com

3

Como memória secundária pode-se mencionar: discos rígidos. microfone. A memória principal. Dados são introduzidos no computador via teclado. 1. Como dito anteriormente o computador tem dois tipos principais de memória: a principal e a secundária. 1. assim quando uma nova informação for necessária e não estiver disponível na memória RAM. Depois que estes dados não são mais necessários na CPU eles são armazenados na memória principal ou secundária.1. uma vez que a esperança estatística de que ela esteja lá é grande.unesp. Vamos aqui considerar apenas o caso da tecnologia atual que é o binário. A memória RAM é utilizada para armazenar os programas e os dados. e servem como repositórios intermediários de informação entre a memória secundária.Fortran 90/95 A CPU interpreta as instruções dos programas. é volátil.2 Memória principal. como por exemplo o saldo bancário das pessoas. unidades de fita. porém operando a velocidades bem mais baixas. Assim quando a CPU necessita de alguma informação que não se encontra na memória RAM. Pelo menos enquanto estiverem funcionando adequadamente. podem ser desligados e a informação permanece sem corrupção de seu conteúdo. Portanto. se também não a encontrar aí.4 Unidades de entrada e saída de dados. e a memória RAM. As memórias Cache são de menor dimensão (em bytes). então efetua a procura na memória secundária.br e jbaparecido@gmail.com 4 . e placas de aquisição de dados. Quando o processador encontra a informação desejada na memória secundária. quando o computador é desligado a informação ali contida é corrompida. ou como repositório de informação não volátil. Os dados podem sair do computador via impressora. ele a procura nas memórias Cache. scanners. Assim a atual tecnologia é basicamente binária.feis. tela.2 Representação de dados em um computador.1. a memória de um computador é constituída de chaves que podem estar apenas nos estados ligado ou desligado. projetor multimídia.1. efetuas as instruções aritméticas na ALU e armazena o resultado nos registros. Versao atual impressa (*. de grandes dimensões em bytes e de baixo custo por unidade de informação armazenada. em geral.3 Memória secundária. floppy-disks e discos compactos (CD-compact disk). unidades de disco. 1. o processador irá procurá-la na memória Cache. Em geral são utilizados como uma extensão lógica da memória principal. A atual tecnologia computacional baseia-se no fato de que uma dada porção de matéria está magnetizada ou não. mais rápidas e mais caras. A memória secundária em geral é lenta. ele captura um bloco de informações da dimensão em bytes da memória Cache que vai armazenar aquelas informações. Especula-se sobre a exploração de outros princípios físicos que implicariam em computadores baseados em sistemas numéricos não binários. Cada chave então representa apenas um dígito Versão primeira de janeiro 1999. Estes acessórios mencionados que funcionam como memória secundária apresentam a capacidade de armazenar as informações de forma persistente ou não volátil. fitas magnéticas. isto é. câmeras digitais. plotter e auto-falante. 1.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. A memória principal é constituída em geral de chips semicondutores e em geral é constituída da memória de acesso randômico (RAM-Random Access Memory) e de uma ou mais memórias Cache. em geral a mais lenta. pega os dados nas unidades de entrada de dados ou nas memórias principal e secundária e armazena-os nos registros.

ligado ou desligado. este número é então convertido para o sistema de armazenamento natural do computador.768 a +32. 4. Em geral precisamos trabalhar com números que não sejam apenas o zero e o um.2.unesp. Desta forma o número 77 decimal pode ser representado da seguinte maneira nas diferentes bases 7710  10011012  1158  4D16 . Tipos básicos de dados do Fortran 90. mais adiante voltaremos aos tipos derivados ou especiais.feis. reais.535 = 216-1) e com quatro bytes de -2147483648 a +2147483647 (4294967295 = 232-1). Manipulando-se a quantidade de bytes que se utiliza e o tipo de uso que é feito destes bytes em uma palavra pode-se armazenar na memória outros tipo de dados que não apenas inteiros.2.2. outros sistemas de números também podem ser convertidos para binários e vice-versa. Dados do tipo inteiro Versão primeira de janeiro 1999. No momento trataremos apenas dos inteiros. Quando entramos via teclado com um número decimal em um programa Fortran.767 (65. 128 unidades para a esquerda tem-se números variando de –128 a +127.1.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.1 O sistema binário de números inteiros. O grupo de bits maior ou igual ao byte é a palavra (word). Esta é a menor informação que um computador representa. Um byte é um grupo de 8 bits agrupados em conjunto para representar um número binário. Os tipo comuns de dados que se pode armazenar são: inteiros. definidos pelo usuário (UDT-User Defined Type) a partir destes cinco tipos fundamentais. 2. Da mesma forma com dois bytes pode-se representar números de –32. 1. alfanuméricos.2. O tamanho das palavras variam de computador para computador. que pode usar 1. podendo representar números maiores em um sistema binário. Versao atual impressa (*.2. Pode-se resolver esta questão juntando vários bits. na próxima seção veremos outros tipo de dados. Os outros sistemas de números que o Fortran 90 suporta são o Octal (base 8 = 23) e o Hexadecimal (base 16 = 24). o binário. por exemplo o número 354 no sistema decimal pode ser escrito como segue na bases binária 35410  3  102  5  101  4  100   1  2 8  0  2 7  1  2 6  1  2 5  0  2 4  0  2 3  0  2 2  1  21  0  2 0 O maior número que pode ser representado em um byte é 11111111 que corresponde ao número 255 (28-1) na base 10. Existe também os tipos de dados derivados. 1. O menor grupo de bits é chamado de byte. Quando o computador vai imprimir um número. Até o momento discutimos apenas o armazenamento na memória de números inteiros. Se interpretarmos o estado ligado como sendo o número um e o estado desligado como sendo o número zero. reais e alfanuméricos. podemos assim representar os números zero e um.br e jbaparecido@gmail. 8 ou mais bytes consecutivos para representar um número binário. Pode-se representar números inteiros em diferentes bases. complexos e lógicos.Fortran 90/95 binário. 1. conhecida como bit. Como o sistema decimal pode ser convertido em binário. Se transladarmos os números de 0 a 255.com 5 . ele converte o número que está no sistema binário para decimal e imprime.

unesp. Os bits estão divididos em duas partes. onde n é a quantidade de bits da palavra. 1. Um sistema típico para representação de uma linguagem ocidental deve incluir os seguintes símbolos: Versão primeira de janeiro 1999. suficientes para recuperar. ou seja com este tipo de representação a precisão que se obtém é de aproximadamente 7 dígitos decimais.2. o tipo de dado inteiro consiste de uma quantidade de inteiros positivos. Isto ocorre porque quando um número com mais de 7 dígitos decimais é armazenado em um tipo real com mantissa de 24 bits. O tipo real armazena dados em um forma de notação científica. e o menor inteiro = -2n-1.2.1 e o 1234567. Neste caso é impossível distinguir qualquer diferença entre os números 1234567. No computador o sistema é semelhante. o dígitos além do sétimo estarão perdidos para sempre. os processadores incluem o tipo de dado real ou floating-point. 16.Fortran 90/95 Como mostrado anteriormente.br e jbaparecido@gmail. Dados alfanuméricos O tipo de dado alfanumérico (character) consiste de caracteres alfanuméricos e símbolos. 2.3.7651010. Em geral o maior e o menor inteiros representados são fornecidos por: maior inteiro = 2n-1-1.2. O tamanho da palavra para armazenar inteiros varia de processador a processador (processador = computador + sistema operacional + compilador). visto que são infinitos e a quantidade de bits para representá-los é finita.765 e o expoente é 10. As duas partes de um número expresso em notação científica são chamados de mantissa e expoente. 4 e 8 bytes ou 8.2. A precisão depende do número de bits na mantissa e a faixa depende do número de bits no expoente. Este é o erro de arredondamento (round-off error). Quanto ao tamanho em bytes. ou seja o valor absoluto da mantissa é maior ou igual a zero e menor que a unidade. Dados do tipo real Os números inteiros não conseguem representar números racionais ou irracionais. 32 e 64 bits. aproximadamente. ou seja entre 10-38 e 10+38. aproximadamente. 1. porém no caso de usar 4 bytes tem-se apenas uma precisão de 7 dígitos decimais.2. como segue valor do numero  mantissa  2 exp oente . Também não representam números muito grandes ou muito pequenos. Uma mantissa com 24 bits pode armazenar números de -223 a +223. Precisão é a quantidade dígitos significativos que são preservados em um número. a mantissa com 24 bits e o expoente com 8 bits.2. e a faixa é a diferença entre o maior e o menor número que pode ser representado.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. Em conseqüência os dados do tipo real são caracterizados por dois indicadores: a precisão e a faixa. Por exemplo no número 5. Um expoente com 8 bits pode representar números entre 2-128 e 2128. Versao atual impressa (*.feis. uma de inteiros negativos e o zero. o valor do número representado. Para contornar estas duas deficiências de representação de números não inteiros em uma quantidade finita de bytes.com 6 . os números reais mais comuns nos processadores são o tipo real de 4 bytes ou 32 bits. apenas a base numérica é binária ao invés de decimal e os números reais são normalizados. Convertendo para a base decimal tem números de –107 a +107. mas os tamanho mais comuns são palavras de 1. A mantissa contém um número normalizado e portanto entre -1 e +1 e o expoente contém uma potência de 2. Note que o tipo real de dados pode representar números muito maiores ou muito menores que o tipo inteiro pode. Este tipo de representação não consegue representar exatamente todos os números entre zero e a unidade. a mantissa é 5.

Assim para armazenar 10 caracteres serão necessário 10 bytes. O Fortran existe a mais de 50 anos e é uma linguagem projetada para cômputos científicos. consequentemente é de alto nível. Este primeiro Fortran foi o Fortran I. diferindo em detalhes. Em cada um destes grupos existem inúmeras linguagens com as mais diferentes características. enquanto os usuários humanos preferem uma linguagem a mais próxima possível de sua maneira de se comunicar. Existem excelentes bibliotecas de rotinas científicas escritas para esta linguagem. Esta versão do Fortran tinha muitas melhorias e tornou-se o standard da linguagem por 15 anos. 1. tais como: çàáõ. Chinês.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. mas não nos esqueçamos que existem várias outras camadas por trás até chegar à máquina física propriamente dita. Em outras palavras. as linguagens dentro de cada grupo são muito parecidas na sua concepção geral.feis. Símbolos variados. Versao atual impressa (*. as orientadas a rotina (Fortran. Árabe. 1. ficando os blocos restantes designados para as diferentes linguagens: Japonês. 26 letras minúsculas de ‘a’ a ‘z’. Existem várias camadas de linguagens entre o usuário e a máquina propriamente dita. tendo assim uma larga tradição em resolver problemas de engenharia e ciências aplicadas em geral. Existem outros sistemas semelhantes ao ASCII. tal como o BRASCII. etc. A linguagem Fortran. Hebreu. Logo após em 1958 a IBM lançou o Fortran II. e assim por diante.unesp.com 7 . Pascal e C). na sintaxe e na semântica. A evolução do Fortran continuou rapidamente até o aparecimento do Fortran IV em 1962. Em 1966 o Fortran IV foi a primeira linguagem a ser padronizada pela ANSI (American National Standard Institute). O nome FORTRAN é derivado de FORmula TRANslation. Versão primeira de janeiro 1999.4 História do Fortran O Fortran é o avô de todas as linguagens de computação. O conjunto de caracteres mais utilizado no mundo ocidental é o ASCII (American Standard Code for Information Interchange). Grego. Símbolos especiais requeridos pela linguagem. Vamos nos ater aqui ao compilador.3 Linguagens de computador. Hoje. Assim quase todas as linguagens de programação são de alto nível. quase todas apresentam recursos de alto nível e algumas apresentam alguns recursos de baixo nível. Como algumas linguagens tal como o Japonês e o Chinês têm milhares de símbolos (aproximadamente 4000) faz-se necessário um sistema com mais caracteres. com poucos recursos de baixo nível. tais como: !@#$%^&*(){}[]. sendo então renomeado para Fortran 66. Uma vez que o número de caracteres usando por uma linguagem ocidental não excede a 256 (28) pode-se utilizar um byte para armazenar um dado caracter.Fortran 90/95 26 letras maiúsculas de ‘A’ a ‘Z’. Existem três famílias de linguagens computacionais: as orientadas a objeto (SmallTalk). e as mistas (C++).’’<>?/~. assim surgiu o Unicode que armazena cada caracter em 2 bytes podendo assim abrigar 65536 (216) caracteres. Os primeiros 128 caracteres do Unicode são os mesmos do ASCII.br e jbaparecido@gmail. O Fortran foi criado originalmente na IBM entre 1954 e 1957. Russo. Português. 10 números ‘0’ a ‘9’. Duas delas mais familiares ao usuário são o sistema operacional e o compilador. Isto é necessário porque a máquina só entende a linguagem dos fenômenos físicos sobre os quais o computador baseia-se.

O Fortran 90 é um superconjunto do Fortran 77 e estende a linguagem em novas direções. Lahey. o Fortran 95. novas estruturas de arrays.Fortran 90/95 Em 1977 o padrão Fortran tem uma nova grande melhoria com sintaxe e comandos que facilitavam a produção de programas estruturados. operação com arrays completos.feis. Em 1995 surgiu uma pequena atualização do Fortran 90.unesp. Versao atual impressa (*. Versão primeira de janeiro 1999. desde que a CPU tenham dois ou mais processadores. porém mostrando os aditivos feitos no Fortran 95.br e jbaparecido@gmail. tipos de dados derivados. Outro grande aspecto do Fortran 90 é suportar processamento paralelo SIMD (Single Instruction Multiple Data). Digital. Este padrão foi um sucesso e passou a ser conhecido como Fortran 77. Entre as novidades incluídas no Fortran 90 estão: livre formato do código fonte. Vamos nos dedicar prioritariamente ao Fortran 90. Novamente em 1990 o Fortran passou por uma grande mudança. Ainda não popular no Brasil. e interfaces explicitas. significando que é candidata a ser deletada do padrão nas futuras versões do Fortran. A forma fixa do código fonte foi abandonada no Fortran90 e declarada obsolescente no Fortran 95.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. O Fortran 90 já é suportado pelos principais compiladores disponíveis no mercado (Absoft. em uso corrente até o momento.com 8 . e Microsoft).

as declarações podiam ter no máximo 72 colunas.1.2. Assim. Até o Fortran 77 o formato do código fonte era fixo.unesp. No padrão do Fortran 77 era praticamente obrigatório o uso de labels. Se a declaração é muito longa então pode colocar o símbolo (&) e continuar a declaração na próxima linha. Cada linguagem tem um conjunto de caracteres básicos.1 – Conjunto de símbolos do Fortran 90. no Fortran 90 eles continuam existindo mas são praticamente desnecessários ou de uso restrito. As declarações podem ser executáveis e não-executáveis. e ditado pelo antigo formato dos cartões perfurados. todos os compiladores. em Fortran uma variável escrita como “velocidade” é a mesma escrita como “Velocidade” ou “VELOCIDADE”. mas são suportadas por.Fortran 90/95 CAPÍTULO 2 ELEMENTOS BÁSICOS DO FORTRAN 90 Neste capítulo apresenta-se os elementos básicos do Fortran 90. Outros símbolos não são permitidos e causará erro de sintaxe no programa.feis.1 O conjunto de caracteres do Fortran 90.* / ** 17 símbolos variados ( ) .com 9 . praticamente.1 Formato livre do código fonte. O alfabeto do Fortran 90 (Fortran character set) consiste de 59 símbolos mostrados na Tabela 2. Quantidade de símbolos Descrição Símbolo 26 letras maiúsculas A-Z 10 números 0-9 1 underscore _ 5 símbolos aritméticos + .2 A estrutura de uma declaração Fortran 90. exceto em variáveis do tipo caracter onde. o Fortran 90 possui um conjunto bem definido de símbolos que podem ser usados. No formato livre atual não é mais necessário atender a estas restrições. As declarações não executáveis provêm informações necessárias ao correto funcionamento do programa. Ao final será possível criar uma programa computacional para efetuar algum cálculo simples. Tabela 2. Declarações executáveis descrevem ações que o programa deve realizar quando executado. e deviam começar na sétima coluna. Tal como o Chinês e o Português. 2. < > ? branco As letras minúsculas “a-z” não fazem parte do conjunto de símbolos do Fortran90. ‘ $ : ! “ % & .br e jbaparecido@gmail. são consideradas como dados e portanto não são corrompidas. Uma declaração pode usar até 40 linhas consecutivas. Versão primeira de janeiro 1999. Versao atual impressa (*. = . Um programa consiste de uma seqüência de declarações destinadas a atingir um determinado objetivo. toda letra minúscula que é encontrada pelo compilador é convertida para letra maiúscula. As declarações podem começar na primeira coluna e cada linha pode ter até 132 caracteres. 2. Quem já utilizou cartões perfurados sabe que tinha 80 colunas. e assim por diante.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. 2. Em realidade.

1 apresenta-se um primeiro programa em Fortran 90 que contém os principais elementos de todo programa Fortran 90. isto é.3.1 Estilo de programação O Fortran é case insensitive. no começo do programa. !programador: joão batista aparecido !data: 03 de dezembro de 1999 !modificado: 26 de julho de 2001 program primeiro_programa Versão primeira de janeiro 1999.3 A estrutura de um programa Fortran 90. defina um estilo e siga-o em todo o programa.2. cpx_angulo e flt_temperatura.3. Forme nomes para as variáveis que façam algum sentido e que não sejam muito longas. vou usar preferencialmente letras minúsculas nos programas. execução e terminação. Também é possível desenvolver uma notação onde cada nome de variável tem um radical inicial que indica o tipo da variável. Desta forma. Primeiro programa em Fortran 90 Na Listagem 2. pode-se escrever os nomes int_vel. Este símbolo pode aparecer em qualquer coluna do programa e não apenas na primeira coluna. para variáveis do tipo inteiro. Como dito anteriormente um programa Fortran é um conjunto de declarações executáveis e não executáveis organizadas em uma ordem apropriada. 2. Sempre use o código fonte no formato livre quando escrevendo programas em Fortran 90/95. Assim não use o formato fixo em qualquer programa novo. Como os compiladores atuais mostram na tela as palavras-chave em cor diferenciada do restante.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. Utilize o underscore para unir duas palavras.feis. significando que é candidato a ser deletado nas próximas versões do Fortran. De qualquer forma. “flt” para reais (floating point) e assim por diante para outros tipos de dados definidos pelo usuário. se possível também em outros programas que realizar. O formato fixo foi declarado obsolescente no Fortran 95. Todo programa Fortran pode ser dividido em até três seções: declaração. que define o nome do programa e as variáveis. lógica. complexa e real. “bol” para lógicas.br e jbaparecido@gmail. caracter. assim aumentarão as chances de reutilização do código.com 10 . bem como seus tipos. A seção de declaração consiste de um grupo de declarações não-executáveis. Listagem 2. “chr” para caracter.1 Um programa Fortran 90 simples. eixo_principal.unesp. A seção de terminação consiste de declarações parando o processamento do programa e informando ao compilador onde o programa termina. respectivamente. que serão referenciados na seção de execução. Versao atual impressa (*. 2. chr_nome. como era no padrão Fortran 77.Fortran 90/95 Qualquer coisa que venha após o símbolo “!” será interpretado como comentário pelo compilador. “cpx” para complexas. formando uma única variável. “int” para inteiros. neste caso o símbolo para comentários era a letra “C”. A seção de execução consiste de um conjunto de declarações executáveis descrevendo as ações que o programa executará. 2. por exemplo. por exemplo. não diferencia entre letras maiúsculas e minúsculas. bol_teste.

Constantes e variáveis inteiras Conforme discutido anteriormente o tamanho (kind) de uma constante ou variável inteira depende da quantidade de bits utilizado para armazenar a informação. as declarações executáveis e o final do programa. as declarações não executáveis. Uma variável ou constante em Fortran possui nome único e duas destas grandezas não podem ter o mesmo nome. Quando o compilador Fortran encontra uma constante ou uma variável ele reserva um bloco de memória. w !atribui valores a x e y x = 2. ou seja durante a compilação.feis. Não poderão ter nomes que coincidam com palavras reservadas da linguagem. !Somar dois números reais x e y.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.0 y = 3. Crie um dicionário de dados (variáveis e constantes) para cada programa. y e w write(*. 2. de dimensão adequada.unesp. O valor de uma variável Fortran pode ser ou não ser inicializado antes do programa ser executado. declara-se da seguinte maneira Versão primeira de janeiro 1999. e !imprimir. sempre que possível. colocar em uma variável w.4 Constantes e Variáveis Uma constante em Fortran é um dado que é definido antes do programa rodar.x.br e jbaparecido@gmail. Uma variável em Fortran é um dado que pode mudar durante a execução do programa.' w = '. visando facilitar a manutenção.' y = '. !declara variáveis real :: x.com 11 . Para declarar que uma variável inteira numero_de_alunos procede-se da seguinte maneira integer :: numero_de_alunos numero_de_alunos = 30 ou de uma forma mais compacta integer :: numero_de_alunos = 30 No caso de uma constante inteira.1. Versao atual impressa (*.4.w !termina o programa stop end program primeiro_programa No programa acima percebe-se claramente o início do programa.*) ' x = '. 2. para armazená-la.0 w=x+y !soma x e y !imprime x.y. e não será alterado durante a execução do programa.Fortran 90/95 !Objetivo: !Mostrar alguns aspectos básicos de um programa Fortran 90. y. Use nomes de variáveis com algum significado.

número de Computador número total número de precisão de bits bits na decimal bits do mantissa expoente 32 24 7 8 VAX 64 56 15 8 32 24 7 8 IBM PC 64 53 15 11 32 24 7 8 Sun Sparc 64 53 15 11 Cray 64 49 14 15 faixa expoente do 10-38 a 1038 10-38 a 1038 10-38 a 1038 10-308 a 10308 10-38 a 1038 10-308 a 10308 10-2465 a 102465 Para declarar uma variável real procede-se da seguinte forma real :: x x = 10.33 2.4.2-Precisão e faixa de números reais em vários computadores. Constantes e variáveis alfanuméricas O tipo de dados character consiste de grupos de símbolos alfanuméricos. parameter :: y = 10. parameter :: numero_de_alunos = 30 2. como segue real.br e jbaparecido@gmail. Por exemplo.Fortran 90/95 integer.feis. Versao atual impressa (*.true. A maneira de declarar o tipo e atribuir valores a uma variável lógica é logical :: w w = . y. as quais só podem assumir dois valores TRUE ou FALSE.true. parameter :: w = .2. ou logical :: w = . mostrados na Tabela 2. No caso de constantes lógicas. 2. Constantes e variáveis reais Podem existir variáveis e constantes de todos os tipos que o compilador suportar. w ! variaveis com 14 caracteres Versão primeira de janeiro 1999.com 12 . Tabela 2.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.unesp. pode-se declará-las como logical.4. variáveis do tipo real podem ter diferentes tamanhos (kinds). Constantes e variáveis lógicas O Fortran 90 suporta variáveis lógicas.4.true.4.3. Pode-se declarar o tipo e atribuir valores a uma variável caracter das seguintes maneiras character (len = 14) :: x.2.33 e no caso de uma constante real.

M. Para melhorar a consistência e o entendimento do código.4. a*b. Este default pode ser alterado usando o comando IMPLICIT. Para se declarar constantes do tipo caracter.Fortran 90/95 character :: r. a – b.q x = ‘Joseh da Silva’ ! variaveis com 1 caracter ! variaveis com 12 caracteres ! atribui valores a x O termo (len = 14) que aparece logo acima refere-se à quantidade de caracteres na variável ou constante.4. caso contrário o compilador acusará o erro. Mantendo as constantes consistentes em um programa Evite ficar definindo uma mesma constante em diferentes posições do programa com diferentes precisões.N e real no restante dos casos.feis.K. reais e lógicas. 2. Neste caso a variável k é adicionada de uma unidade é armazenada na mesma posição de memória que k ocupava anteriormente à soma.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. apresenta-se uma outra maneira de se evitar a duplicidade e corrupção de constante.5. já comentados acima. Se não for definido o tipo de uma variável.com 13 .5 Declaração de atribuição e cálculos aritméticos Cálculos são feitos em Fortran 90 utilizando-se declarações de atribuição do tipo nome_da_variável = expressão_aritmética por exemplo k = k + 1.unesp. Definindo variáveis inteiras ou reais por default ou explicitamente.L. utilizando-se módulos. dê um nome à cada constante importante e as use pelo nome em todo o programa. a**b. e mesmo de variáveis. suponhamos que existe uma constante chamada um_terco e que vale um terço.33 e em outro um_terco = 0. O mais adequado é usar nas declarações iniciais de um programa a declaração implicit none que obrigará o programador a definir todas as variáveis sendo utilizadas. Mantenha as constantes precisas e consistentes em todo o programa.br e jbaparecido@gmail. Versão primeira de janeiro 1999. Mais adiante. em outro capítulo. Da mesma forma o termo (12) refere-se à quantidade de caracteres.s character(12) :: t. por default ela será inteira se começar com I. 2. procede-se de maneira semelhante aos casos de dados dos tipos inteiros.J.6. a/b. Por exemplo. 2. Versao atual impressa (*.33333. Os operadores aritméticos do Fortran 90 são + * / ** adição subtração multiplicação divisão exponenciação Os operadores aritméticos mencionados acima são operadores binários significando que devem aparecer entre duas variáveis tal como a + b. assim evite num local definir um_terco = 0.

666666. por exemplo.unesp.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. 2. Para remover qualquer ambigüidade que poderia ocorrer se a ordem dos operadores fosse alterada. Esta regra é importante principalmente quando existe divisão de dois inteiros. Mas o que acontecerá quando. No caso que propus acima o que vai acontecer é que o Versão primeira de janeiro 1999./3. Versao atual impressa (*.4 Aritmética mista Quando operações aritméticas são realizadas utilizando números reais e números inteiros. 2/3 = 0.Fortran 90/95 adicionalmente.3. = 0. = 1. partindo do mais interno para fora. 3/3 = 1.br e jbaparecido@gmail.333333. duas expressões teoricamente idênticas podem freqüentemente fornecer resultados ligeiramente diferentes. 2. Devido à precisão limitada./3. 3) Todas as multiplicações e divisões são efetuadas. então diz-se que é uma aritmética mista.5.1 Aritmética inteira Aritmética inteira é aquela realizada apenas com números inteiros. 4/3 = 1. Se estiver em dúvida. Preste atenção na aritmética com inteiros. os símbolos + e – podem ocorrer como operadores unários. como segue +a ou –b. = 1. Hierarquia das operações Freqüentemente várias operações aritméticas ocorrem combinadas em apenas uma expressão.. Por exemplo 1. 2.5. somamos um real e um inteiro? Além do mais existem muitas outras combinações (em realidade infinitas) onde pode aparecer reais e inteiros juntos. 4) Todas as adições e subtrações são avaliadas. 3./3. Aritmética com inteiros sempre produz resultados inteiros./3. 2) Todas as exponenciais são calculadas. 6/3 = 2.333333. Por exemplo 1/3 = 0. operando da esquerda para a direita. Preste atenção na aritmética com reais. Estas regras são semelhantes às da álgebra. operando da direita para a esquerda. o resultado não poderá ser fracionário. 2. Quando somamos dois números reais o resultado também será um número real. Quando somamos dois números inteiros o resultado será também um inteiro.com 14 .2 Aritmética real Aritmética real ou aritmética de ponto flutuante (floating-point arithmetic) é aquela envolvendo constantes e variáveis reais. operando da esquerda para a direita. 2. = 0. 4. 5/3 = 1. As operações são realizadas na seguinte ordem de prioridade 1) O conteúdo de todos os parênteses são calculados.5. use parênteses o suficiente fazer que as equações fiquem claras e simples para entender. Fortran 90 estabelece uma série de regras que governam a ordem que as operações são realizadas em uma expressão.feis.5. A aritmética real produz resultados reais que geralmente espera-se. Divisão de inteiros sempre fornece resultados inesperados. significando que podem ser aplicados a apenas uma variável.

Seja o seguinte exemplo 2. o qual será então transformado para zero (real) e adicionado com o 2.feis.5.6 Declaração de atribuição e cálculos lógicos Da mesma forma que cálculos aritméticos. Caso a resposta seja positiva a exponenciação é efetuada tal como no caso em que o expoente era inteiro. que em geral tem a forma Versão primeira de janeiro 1999. cálculos lógicos também são efetuados com declarações de atribuição.0. Alguns compiladores (nem todos) tem alguma habilidade em verificar se o real x pode ser representado de forma exata por um inteiro. Uma solução para este problema é transformar (durante a operação) todos os valores inteiros para reais. 2.br e jbaparecido@gmail. resultando em um número real.5 real É necessário muito cuidado em expressões mistas. é na exponenciação.com 15 .0.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem./2 2. Nunca eleve um número negativo a um expoente real. então no processo de soma o valor inteiro é transformado para real (note que a variável continua com o valor inteiro) e somado com o outro real. Expressões do tipo misto são perigosas por que são difíceis de entender e podem produzir resultados enganosos./2. Veja abaixo três exemplos de diferentes tipos de operações Tipo de expressão Operação Resultado Tipo de resultado Expressão inteira 5/2 2 inteiro Expressão real 5. os termos de cada divisão tem apenas inteiros.5. Por outro lado se temos a seguinte expressão w = y**x onde y é real negativo e x é também real. 2. e o resultado das três divisões na expressão serão zero (inteiro).0 As divisões na expressão acima tem prioridade sobre a soma. então é uma aritmética inteira. Os compiladores atuais interpretam esta expressão como: tome o valor y e multiplique-o por si mesmo n vezes. Veremos como fazer isto mais adiante. esta expressão será calculada internamente no computador da seguinte forma w = exp(x*lny).Fortran 90/95 programa vai perceber que se está tentando somar um inteiro e um real.unesp.0 + 1/3 + 1/5 + 1/7 = 2. principalmente onde exista divisão. com resultado final igual a 2. 2. Versao atual impressa (*. sempre que possível.5 real Expressão mista 5. Se temos uma expressão w = y**n onde y é um real negativo e n é um inteiro. Use expoentes inteiros ao invés de expoentes reais. Aritmética mista e exponenciação Existe uma situação onde a aritmética mista é desejável. Evite-as sempre que possível. como y é negativo o programa será descontinuado devido ao erro fatal.

true. Versao atual impressa (*.operador.and. Existem quatro operadores combinatoriais binários: .eqv. caso contrário retornará .true.le. . .false.w2 w1. . .w2 w1. 3<5 = .false. Por exemplo 3>5 = .1 Operadores relacionais lógicos Operadores relacionais lógicos são operadores com dois números ou caracteres que fornecem um resultado do tipo lógico (logical).or.Fortran 90/95 nome_da_variável_lógica = expressão_lógica A expressão lógica do lado direito da expressão acima pode ser qualquer combinação de variáveis lógicas. variáveis. .false. fornecendo um resultado final do tipo lógico. .true. .6. 2.ge.. .3 Tabela 2.gt.eqv. Um operador lógico é um operador sobre dados numéricos.2 Operadores combinatoriais lógicos Operadores combinatoriais lógicos são operadores com um ou dois operandos lógicos que fornecem um resultado lógico.feis. e . Versão primeira de janeiro 1999. variáveis ou constantes. constantes lógicas e operadores lógicos. constantes ou caracteres. e . menor ou igual a Se a relação entre v1 e v2 é verdadeira o operador retorna . .operador. A forma geral de uma operação com combinatorial lógica com operador binário é w1.. . . .true.true.true. 2.w2 w1. .false. caracter ou lógico. e operador é um dos operadores relacionais mostrado na Tabela 2.FALSE...4-Tabela da verdade para operadores combinatoriais lógicos.com 16 . maior que >= . .eq.false.br e jbaparecido@gmail. por isto são chamados operadores relacionais.and.true. . .neqv.. . maior ou igual a < . ‘B’<’D’ = . w1 w2 w1.6.3-Operadores relacionais lógicos Operação Novo estilo Estilo antigo Significado == . . .true.unesp.false.true.false.w2 onde w1 e w2 são expressões lógicas.false. . menor que <= .or.TRUE.false.false. Tabela 2. como resultado. e um operador unário. igual a /= . A forma geral do operador relacional é v1 operador v2 onde v1 e v2 são expressões aritméticas. diferente > .false.ne.neqv. é um dos operadores combinatoriais mostrados na Tabela 2.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.not.false.4. O resultado depende da relação entre os dois valores...lt.w2 .

operando da esquerda para a direita.true. e . Se o lado direito da expressão acima é menor do que o da esquerda. operando da esquerda para a direita. w1 .false. /=.5.not. . são executados.true. <=) são calculados.br e jbaparecido@gmail. são executados. Esta especificação de sub-caracteres é definida colocando-se valores inteiros que representem o início e o final dos caracteres selecionados. .eqv. os caracteres em excesso serão descartados.true.7. 2. >. 2) Todos os operadores relacionais (==. Por exemplo.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.1 Especificação de sub-caracteres A especificação de sub-caracteres seleciona uma parte de uma variável caracter e a trata como se fosse uma variável independente.true. Porém se o lado direito é maior do que o da esquerda. os operadores lógicos combinatoriais são calculados depois das operações aritméticas e de todos os operadores lógicos relacionais.w1 . . operando da esquerda para a direita. <. Na hierarquia das operações. . a declaração character (len = 5) :: x x = ‘ijk’ armazena o valor ‘ijk ’ na variável x. 6) Todos os operadores .true. . enquanto que character (len = 2) :: x x = ‘ijk’ armazena o valor ‘ij’ na variável x.unesp. Um operador caracter (character operator) é aquele que opera em dados que permitem um resultado do tipo caracter.5 apresenta-se a tabela da verdade para o operador unário .false. A ordem na qual os operadores em uma expressão são executados é: 1) Todos os operadores aritméticos são calculados de acordo com a seqüência apresentadas anteriormente.feis. são executados.and. algumas posições são ocupados com os caracteres atribuídos e o restante é preenchido com brancos. 2. 5) Todos os operadores . . 3) Todos os operadores . operando da esquerda para a direita.Fortran 90/95 .com 17 . são executados.neqv.7 Declaração de atribuição e variáveis do tipo caracter Manipulações de variáveis do tipo caracter são efetuadas com a seguinte declaração de atribuição nome_da_variável_caracter = expressão_com_variáveis_caracter.Tabela da verdade para o operador unário .false.true. .not. >=. Versão primeira de janeiro 1999. 4) Todos os operadores .not.or.true. . Na Tabela 2. Versao atual impressa (*. Tabela 2.not.

7. Versão primeira de janeiro 1999. a seguinte seqüência a = ‘abcdef’ b = ‘1234567’ c = a(1:2)//b(3:4)//a(3:6) irá produzir o resultado c = ‘ab34cdef’.6.6 – Vinte funções intrínsecas suportadas pelo Fortran 90/95.8 Funções intrínsecas Existe um subconjunto das funções matemáticas que associa a um ou mais argumentos um único resultado. Se um caracter é igual ou diferente de outro é fácil. Por exemplo: ‘BBBCFR’ é maior ou menor que ‘BBC’? O algoritmo usado no compilador Fortran 90 compara o primeiro caracter de cada variável. Isto pode levar a resultados surpreendentes se o usuário mover o seu programa de um local com padrão para outro com outro padrão.3. Abaixo. Por exemplo se a = ‘abC4567’ b = a(3:5) então b = ‘C45’.unesp. Funções criadas pelo próprio usuário podem ser definidas como funções externas (external function)ou funções internas (internal function). Tabela 2.feis.2 Operador de concatenação O operador (//) combina duas ou mais variáveis caracter para formar ou outra. Por exemplo. No entanto é difícil dizer se um caracter é. chamadas funções intrínsecas (intrinsic functions). existem certos padrões normalizados de dados do tipo caracter. A seguinte expressão ‘a’<’A’ é verdadeira ou falsa? Dentro do padrão ASCII a expressão é falsa. será necessário desenvolver uma nova. aí compara-se os segundos caracteres. o ‘C’ é maior que o ‘B’. Uma segunda pergunta interessante é: Como comparar variáveis do tipo caracter com vários caracteres. apresenta-se algumas das funções intrínsecas suportadas pelo Fortran 90/95. Evite usar operadores lógicos relacionais operando em variáveis do tipo caracter. então compara-se os terceiros caracteres que são diferentes. logo após o nome da variável. e ‘a’ é o de número 97. por que o ‘A’ é o elemento de número 65. por exemplo o ASCII. então ‘BBC’>‘BBBCFR’. 2. A seqüência de caracteres pode variar de forma catastrófica. no caso são iguais.br e jbaparecido@gmail. Por esta convenção ‘a’ é maior que ’A’. Versao atual impressa (*. Retornaremos a este assunto mais adiante. Nos cálculos técnicos e científicos faz-se necessário calcular diferentes tipos de funções. a partir dos fundamentos do cálculo. Caso o usuário não consiga reduzir sua função de interesse a combinações das funções intrínsecas. aproximadamente 112. Operadores relacionais lógicos com variáveis do tipo caracter Como já se disse anteriormente. Estas funções podem muitas vezes ser escritas como combinação de outras funções mais básicas.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. maior que outro. destas funções básicas. O compilador Fortran 90 apresenta um conjunto.7.com 18 . na Tabela 2. por exemplo. também são iguais.Fortran 90/95 colocando-os entre parentes e separados por vírgula. 2. 2.

b) min(a.0 + 1/5 = 2.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.*) lista_de_variáveis. program entrada_saida integer :: i. evitando assim os inconvenientes da aritmética mista. 2. Da mesma forma uma declaração de saída de dados escreve um ou mais dados em um equipamento de saída de dados.b) a-p*int(a/p) max(a.0 pode ser re-escrita como 2. uma declaração de saída de dados é write(*.br e jbaparecido@gmail. Uma forma simplificada de declaração de entrada de dados é read(*.*) lista_de_variáveis. Assim a expressão 2. Analogamente.b) asin(x) sin-1(x) acos(x) cos-1(x) atan(x) tan-1(x) Tipo de argumento real real/inteiro inteiro real real real real real real char(1) real real inteiro real/inteiro real/inteiro real/inteiro real real real Tipo de resultado real real/inteiro char(1) real real real real real real inteiro inteiro inteiro real real/inteiro real/inteiro real/inteiro real real real Comentários raiz quadrada de x valor absoluto de x retorna caracter ASCII seno de x co-seno de x tangente de x exponencial de x logaritmo natural de x logaritmo base 10 de x posição de c no ASCII parte inteira de x inteiro próximo de x converte inteiro para real resto de a/b pega o maior de a e b pega o menor de a e b inverso do seno de x inverso do co-seno de x inverso da tangente de x Note que na tabela acima tem uma função para converter inteiros em reais.j Versão primeira de janeiro 1999.9 Declarações de entrada e saída de dados Uma declaração de entrada de dados lê um ou mais dados de um equipamento de entrada de dados. Esta função é a real(i).0 + real(1)/real(5) = 2.feis.2 Programa para demonstrar capacidades mínimas de entrada e saída de dados. Abaixo apresenta-se um exemplo que lê duas variáveis inteiras e imprime as duas inteiras e mais duas reais já definidas no programa Listagem 2. Versao atual impressa (*.unesp.Fortran 90/95 Função e Definição argumentos matemática sqrt(x) x abs(x) |x| achar(i) sin(x) sin(x) cos(x) cos(x) tan(x) tan(x) exp(x) ex log(x) loge(x) log10(x) log10(x) iachar(c) int(x) nint(x) real(i) mod(a.2.com 19 .

Versão primeira de janeiro 1999.br e jbaparecido@gmail.com 20 . Defina sempre e explicitamente todas as variáveis do programa e use a declaração implicit none para ajudar a localizar variáveis não declaradas e variáveis digitadas incorretamente.q stop end entrada_saida Imprima na tela.p. inicialize todas as variáveis de um programa antes de usá-las.feis. para certificar que foram digitadas e processadas corretamente. Sempre que possível. quando possível. Versao atual impressa (*. quando são impressas podem conter qualquer valor que represente o estado dos bits daquelas posições de memória que o compilador lhes atribuiu.*) m. 2.x end program inicializa Uma vez que as variáveis m e x não foram inicializadas.10 Inicialização de variáveis Considere o seguinte programa program inicializa integer :: m real :: x write(*. 2.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. Em todo o caso os resultados podem ser catastróficos.j. Se algumas variável foi digitadas errada. quando da compilação o compilador emitirá um erro indicando que existe uma variável não declarada. Alguns compiladores zeram as variáveis não inicializadas.11 Declaração implicit none Uma declaração não executável de muita utilidade é a implicit none.*)i.0 write(*.0. Quando utiliza-se implicit none todos os defaults de digitação são desabilitados e o programador terá obrigatoriamente que definir todas as variáveis utilizadas.*)'digite i e j' read(*. q = 7.*)i.j write(*.unesp. A declaração implicit none deverá aparecer logo após a declaração program e antes das declarações de tipos de variáveis. todas as variáveis que são lidas por um programa.Fortran 90/95 real :: p = 1.

sem haver nenhuma iteração ou desvio.unesp. onde todos os comandos vão sendo executados um após o outro até chegar ao final do programa.Fortran 90/95 CAPÍTULO 3 ESTRUTURAS DE CONTROLE Um programa Fortran pode ser apenas seqüencial. Estrutura do tipo ELSE e ELSE IF Na estrutura bloco IF mostrada acima uma porção do programa é executada se uma expressão lógica é verdadeira.1. para satisfazer este tipo de necessidade. dependendo dos dados. tem-se algumas variantes da declaração IF.feis. e bifurcações (branches).1 Bifurcações Como estabelecido acima as bifurcações selecionam porções de código que serão executadas. enquanto salta outras porções que não serão executadas.1. A forma do bloco IF é if (expressão_lógica) then declarações_executáveis end if Sempre indente o corpo de um bloco IF de alguns espaços para melhorar a leitura do código. loops). Estrutura do tipo bloco IF A forma mais comum de declaração IF é o bloco IF. uma ou mais declarações ELSE IF podem ser adicionadas ao bloco IF. Caso contrário o bloco de código será saltado e portanto não executado. como nas listagens apresentadas no Capítulo 2. No entanto existem situações onde deseja-se executar um bloco de declarações se a expressão lógica for verdadeira. Entretanto existem problemas onde. Versao atual impressa (*. Se for falsa o bloco de declarações é simplesmente pulado. Basicamente.br e jbaparecido@gmail.com 21 . 3.2. 3. onde o programa fica executando um conjunto de declarações ciclicamente. Este capítulo trata basicamente das implementações no compilador Fortran 90. e a declaração SELECT CASE. destes dois conceitos: laços e bifurcações. Esta estrutura define que um determinado bloco de código só será executado se uma determinada expressão lógica for verdadeira.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. por exemplo. deseja-se executar apenas uma parte do programa deixando o restante sem executar. O bloco IF com declarações ELSE e ELSE IF tem. Estas estruturas de controle podem ser classificadas em dois grupos: laços (ciclos. Para criar este efeito necessita-se de estruturas de programação mais complexas do que as vistas até o momento.1. onde o programa chega a um determinado ponto da execução e toma a decisão em dos qual dos ramos da bifurcação o processamento continuará. Uma declaração ELSE seguida de nenhuma. a seguinte forma if (expressão_lógica_1) then declarações_executáveis_1 else if (expressão_lógica_2) then declarações_executáveis_2 else Versão primeira de janeiro 1999. e um outro bloco se a expressão lógica for falsa. 3.

unesp.br e jbaparecido@gmail.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. Isto é..true. Estrutura do tipo IF. Se for verdadeira executa-se declarações_executáveis_2. A nomeação destas estruturas é opcional mas pode ser usada para evitar ambigüidades e facilitar a leitura e a manutenção do código. l2 = . Abaixo apresenta-se um programa exemplo deste tipo IF nomeado program if_nomeado logical :: l1 = . l3 = . Destine um nome a todas as estruturas grandes e complicadas de IFs do programa. integer :: i externo: if(l1) then i=1 medio: if(l2) then i=2 interno: if(l3) then i=3 end if interno end if medio Versão primeira de janeiro 1999. caso ao digitar seja esquecido alguma declaração end.feis.true.1. o compilador acusará um erro que muitas vezes é difícil de encontrar. nomeado Todas as formas de declaração IF podem ser nomeadas..3. A forma do bloco IF nomeada será então nome: if (expressão_lógica) then declarações_executáveis end if nome O bloco IF com declarações ELSE e ELSE IF nomeado tem a seguinte forma nome: if (expressão_lógica_1) then declarações_executáveis_1 else if (expressão_lógica_2) then declarações_executáveis_2 else declarações_executáveis_3 end if nome Quando tem-se estruturas com muitos laços e bifurcações indentados uns dentro dos outros. pode-se dar nomes a cada uma destas estruturas.com 22 . se for falsa executa-se declarações_executáveis_3.false. para facilitar a leitura e a manutenção.Fortran 90/95 declarações_executáveis_3 end if Na estrutura mostrada acima se a expressão_lógica_01 for verdadeira executa-se então declarações_executáveis_1 e a estrutura completa sua tarefa. A forma mais simples da estrutura ELSE é if (expressão_lógica_1) then declarações_executáveis_1 else declarações_executáveis_2 end if 3. Versao atual impressa (*. Se a expressão_lógica_1 for falsa o programa verifica se a expressão_lógica_2 é verdadeira ou falsa.

com 23 . A forma geral da estrutura CASE é nome: select case (expressão_case) case (seletor_case_1) nome declarações_executáveis_1 case (seletor_case_2) nome declarações_executáveis_2 case (selector_case_3) nome declarações_case_3 … case default nome declarações_default end select nome Se a expressão_case estiver de acordo com o seletor_case_1 as declaracções_executáveis_1 serão executadas e o restante será pulado.*)'Digite o talher!' read(*.br e jbaparecido@gmail. Versao atual impressa (*. então as declarações_default serão executadas. caracter e lógico. e colher.*)'O talher é uma faca' Versão primeira de janeiro 1999. Abaixo apresenta-se um exemplo de utilização da declaração select case ! Objetivo: Demonstrar a utilidade da declaração CASE ! Distingue entre as palavras faca. program select_case character(6) :: x write(*. Se a expressão_case não estiver de acordo com nenhum dos seletor_case. Caso não exista o case default e a expressão_case não atenda nenhum dos seletor_case.*)x select case(x) case ('faca') write(*. então nenhum dos blocos será executado.5 A estrutura CASE A estrutura CASE é uma forma de implementar múltiplas bifurcações simultâneas.1.1. O case default é opcional.unesp.4 Declaração IF lógico Quando a estrutura bloco IF tem apenas uma declaração executável então ela assume uma forma especial mais simplificada. entre vários. O mesmo acontece se a expressão_case estiver de acordo com o seletor_case_2 as declaracaoes_executáveis_2 serão executadas e o restante será pulado.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.Fortran 90/95 end if externo stop end program if_nomeado 3. garfo. Torna-se então uma declaração de apenas uma linha.feis. E assim por diante. baseando em uma expressão envolvendo dados dos tipos inteiro. Permite ao programador escolher um determinado bloco de código a ser executado. como segue if(expressão_lógica) declaração_executável 3. e será executado quando a expressão_case não coincidir com nenhum seletor_case.

Por outro lado o laço com terminação bem definida. uma vez que o mesmo se repetiria eternamente.Fortran 90/95 case ('garfo') write(*. e laços com terminação bem definida. Não existe um laço puro. Versao atual impressa (*. 3. Neste caso não há o risco da execução continuar indefinidamente.com 24 .' end select stop end program select_case 3. Se não for bem projetado este tipo de laço pode continuar indefinidamente. nem colher. As duas formas básicas de laços são: laços com terminação indefinida.1. muito menos um garfo.unesp. Assim todo laço possui na sua estrutura (implícita ou explicitamente) uma bifurcação responsável pela saída do laço. Nos laços de terminação indefinida.feis.*)'O talher é uma colher' case default write(*. este tipo de laço executa um bloco de declarações indefinidamente até que uma determinada condição seja atingida.*) i end do stop end program looping Versão primeira de janeiro 1999.*)'Não é faca.2 Laços Laços são estruturas de controle que permitem a execução de um bloco de código várias vezes em seqüência. executa uma quantidade finita de laços e termina sua execução.*)'O talher é um garfo' case ('colher') write(*.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.br e jbaparecido@gmail. O laço com terminação indefinida Como falado acima. o laço continua indefinidamente até que uma da condição de controle seja atendida e completa-se a execução do laço.2. A forma geral desta declaração em Fortran 90/95 é do declarações_executáveis_1 if(expressão_lógica) exit declarações_executáveis_2 end do Abaixo apresenta-se um exemplo deste tipo de laço ! Testando um laço indefinido program looping integer :: i = 0 do i = i+1 if(i >= 10) exit write(*.

assim esta implementação alternativa. O número total de iterações (i_iter) que será executado em um laço de contagem pode ser obtido aproximadamente por i_iter = (i_end-i_start+i_incr)/i_incr. Portanto. A variáveis inteiras i_start. 3. chamada de do while tem a seguinte forma do while (expressão_lógica) declarações_executáveis end do Nesta estrutura acima o bloco de declarações_executáveis será executada indefinidamente. Este caso eqüivale ao mostrado acima onde não se tenha nenhuma declaração no sub-bloco declarações_executáveis_1. até atingir o valor i_end. inclusive.feis. i_incr declarações_executáveis end do onde index é uma variável do tipo inteiro usada como um contador do laço.Fortran 90/95 Na estrutura acima o bloco de declarações executáveis entre do e end do será executado indefinidamente até que a expressão_lógica seja verdadeira. O laço com terminação bem definida Este tipo de laço tem terminação garantida porque o laço será executado uma quantidade bem definida de vez e então terminará. nunca dependa do valor de uma variável de controle de laço de DO depois que o laço termina. O laço com contagem é construído da seguinte forma do index = i_start.2. Versao atual impressa (*. vai sendo acrescido de i_incr.3. i_end.unesp. entretanto em caso em que a expressão_lógica seja complexa é difícil de se saber. mais simples. Entretanto. de implementar a estrutura mostrada no item anterior.2. 3. não devendo ser modificada (externamente) durante a execução do laço. Após o término do laço DO o valor da variável de controle index é indefinido (dependendo de cada implementação de compilador).2. o compilador (Microsoft V4) não acusou erro e o programa quando rodou foi descontinuado por erro fatal. Embora. O critério de parada do laço em realidade é index*i_incr > i_end*i_incr. Os valores assumidos por index começam com o valor i_start.br e jbaparecido@gmail. testando o caso patológico onde i_incr = 0. Pode ser inserido um comando IF (expressão_lógica) EXIT no interior deste tipo de laço para provocar uma interrupção precoce quando a expressão_lógica for verdadeira.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. O parâmetro i_incr é opcional e o seu valor default é a unidade. Às vezes este tipo de laço pode ser chamado também de laço iterativo ou laço com contagem. Existe a possibilidade de que este tipo de laços nunca atinja terminação. na maioria dos casos seu valor é (i_end + 1). elas controlam os valores assumidos por index durante a execução do laço. A seguir tem-se uma implementação deste tipo de laço Versão primeira de janeiro 1999. Neste tipo de estrutura também é possível que o laço não atinja terminação. definido desta forma esta mais apto a tratar de casos patológicos. É proibido fazer um desvio incondicional (go to) de fora para dentro de um laço DO. neste caso seja claro que a terminação do laço seja atingida. i_end e i_incr são parâmetros do laço de contagem. A variável de controle index tem um escopo interno do laço. Outra implementação do laço com terminação indefinida O compilador do Fortran 90/95 tem uma forma alternativa.com 25 . enquanto a expressão_lógica for verdadeira.

4.br e jbaparecido@gmail. O uso de variável real como variável de controle de laço de DO foi declarado obsolescente no Fortran 90 e foi deletado do Fortran 95.*) i end do stop end program looping_2 Nunca use incremento nulo em laços de contagem e nunca modifique o valor da variável de controle de laço DO enquanto o laço está sendo executado. i_incr = 1 do i = i_start. i_end.com 26 . 1 if(i == 5) cycle write(*. m = 10 do i = 1. 3. As declarações CYCLE e EXIT Pode-se utilizar adicionalmente as declarações cicle e exit para controlar as operações enquanto executa-se algum tipo de laço. Adaptando-se o exemplo acima para testar o efeito da declaração EXIT tem-se program exiting integer :: i. i_incr write(*.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. m = 10 do i = 1. A variável de controle então será incrementada e o processamento continuará.Fortran 90/95 ! Testando um laço definido program looping_2 integer :: i = 0. i_end = 10. Abaixo mostra-se um exemplo de tal aplicação program cycling integer :: i. 1 if(i == 5) exit write(*.*) i end do stop Versão primeira de janeiro 1999.unesp.2. Se a declaração cicle for usada dentro de um laço a execução será parada e o controle retornará ao começo do laço. m. Versao atual impressa (*. m. i_start = 1.feis.*) i end do stop end program cycling Quando a declaração EXIT é utilizada dentro de um laço de DO a execução do laço será interrompida e o controle da execução será passada para a primeira declaração executável após o laço.

com 27 . Ninho de laços Quando vários laços estão um dentro do outro.3 A declaração GO TO Versão primeira de janeiro 1999.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. Os dois tipos principais de laços podem ser nomeados da seguinte maneira nome: do declarações_executáveis_1 if(expressão_lógica_1) cycle nome declarações_executáveis_2 if(expressão_lógica_2) exit nome declarações_executáveis_3 end do nome nome: do index = i_start. Se estas declarações não tiverem referências a qual laço se aplicam.4. diz-se que o laços estão aninhados ou que formam um ninho de laços.br e jbaparecido@gmail.feis.6. i_end. 3.unesp.5 Laços nomeados Da mesma maneira que as bifurcações (IFs) podem ser nomeadas. Versao atual impressa (*. Use declarações CYCLE e EXIT nomeadas em ninho de laços para deixar claro que a declaração afete o laço correto.2. então se aplicarão ao laço externo mais imediato no sentido de dentro para fora.Fortran 90/95 end program exiting 3. i_incr declarações_executáveis_1 if(expressão_lógica_1) cycle {nome} declarações_executáveis_2 if(expressão_lógica_2) exit {nome} declarações_executáveis_3 end do nome Dê nomes aos principais laços no programa para deixar claro quais declarações executáveis pertencem a um determinado laço. Abaixo tem-se um exemplo deste tipo de ninho de laços nome_2: do declarações_executáveis_1 nome1: do declarações_executáveis_2 if(expressão_lógica_1) cycle nome_1 declarações_executáveis_3 if(expressão_lógica_2) exit nome_2 declarações_executáveis_4 end do nome_1 declarações_executáveis_5 end do nome_2 As declarações cycle e exit que aparecem acima têm que referir a qual laço a declaração se aplica quando existe mais de um laço. 3. os laços (DOs e WHILEs) também podem.

pois estão destinados a desaparecer da linguagem. Prova disto é que todas as linguagens possuem o conceito de GO TO. Versao atual impressa (*. Esta afirmação não é necessariamente verdadeira. O uso excessivo de GO TO deve ser evitado porque tende a produzir códigos difíceis de entender e de manter. CASE SELECT. Conceitualmente. além do mais necessário. Não use outros formatos de GO TO. EXIT. o GO TO é importante. restará apenas o GO TO simples.br e jbaparecido@gmail. sob este ângulo as declarações CYCLE e EXIT cumprem o mesmo papel. porém de uma forma menos selvagem uma vez que seu desvio incondicional é para alguma posição bem sabida.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.Fortran 90/95 Muitos dizem: programas que contém GO TO não são bons programas.feis. que na maioria das vezes vai produzir o mesmo efeito. evitando assim programas com lógica desnecessariamente complexa.unesp. GO TO em programas.com 28 . na medida do possível. use as estruturas IF. Versão primeira de janeiro 1999. Evite usar. porém com um melhor controle do código. O GO TO é em realidade um desvio incondicional. no entanto existem situações onde seu uso é necessário. CYCLE.

Sua forma geral é r(Iw) ou r(Iw.unesp.1)i.i3.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. O compilador Fortran 90 suporta vários tipos de formatações. j = 17.1 Saída de dados inteiros: O descritor I O descritor usado para formatar a apresentação de inteiros é o descritor I.1.1 têm-se os tipos mais comuns de símbolos auxiliares dos descritores de formato usados. 4.feis. l = 7689 write(*.com 29 .m) onde r. w e m tem os significados mostrados na Tabela 4.*) que aparecem nas declarações significam: não estou lhe passando nenhuma informação adicional. k.1-Simbolos usados com os descritores de formato.*). program formato_inteiro implicit none integer :: i = 0. Este formato é o formato default destas declarações. As estrelas (*. l 1 format(4(1x. que veremos neste capítulo. juntamente com seus significados. j.3)) stop end program formato_inteiro O resultado da impressão acima será algo do tipo 000 017 254 *** Versão primeira de janeiro 1999.*) e write(*. Símbolo Significado c Número da coluna d Número de dígitos à direita do ponto decimal m Número mínimo de dígitos a ser apresentado n Número de espaços para pular r Número de vezes que o formato é repetido w Número de caracteres a ser usado 4.Fortran 90/95 CAPÍTULO 4 CONCEITOS BÁSICOS DE ENTRADA E SAÍDA DE DADOS No capítulo anterior utilizou-se as declarações read(*.1. Na Tabela 4. Versao atual impressa (*. Tabela 4.1 Descritores de formato Existem vários descritores de formato utilizado na entrada e/ou saída de dados. Abaixo tem-se um pequeno exemplo do uso da formatação para inteiros.br e jbaparecido@gmail. faça um procedimento padrão. k = 254.

também conhecido como notação exponencial. Esta formatação consiste em imprimir um número normalizado entre 0 e 1.567 write(*.Fortran 90/95 As estrelas que aparecem acima significam que o formato foi insuficiente para imprimir o dado.3 Saída de dados reais: O descritor E Muitas vezes dados do tipo real variam muito de faixa e torna-se difícil imprimi-los usando o descritor F. l = 1234.d) Abaixo apresenta-se um programa com algumas impressões usando o formato F. program formato_real_F implicit none real :: i = 1.123456789. multiplicado por uma potência de 10. O formato geral do descritor E é r(Ew..1234 ******* 4.feis.d) Alterando o programa anterior para usar a formatação E tem-se program formato_real_E implicit none real :: i = 1./3.1.. l = 1234..123456789.unesp. k = 21.7)) stop end program formato_real_E O resultado deste programa será . j = 1.br e jbaparecido@gmail. j.3333 21.0000 . l 1 format(4(1x. k = 21. j. k. k. 4.567 write(*.1..3333333E+00 . l 1 format(4(1x.4)) stop end program formato_real_F O resultado do programa acima será 01.1234567E+02 Versão primeira de janeiro 1999.2112346E+02 .F7.E14. Versao atual impressa (*.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.1)i./3.2 Saída de dados reais: O descritor F Um dos descritores usados para formatar dados reais é o F. j = 1. Um outro descritor para números reais é o descritor E.1)i.com 30 . Sua forma geral é r(Fw.1000000E+01 .

ES14.4 Saída de dados reais: O descritor ES O descritor ES é muito semelhante ao descritor E.33333330E-01 2.. 4.1.2345670E+03 Quando imprimindo dados do tipo real muito grandes ou muito pequenos. j = 1./3. k. Esta formatação consiste em imprimir um número normalizado entre 1 e 10 (lembre-se que no descritor E este número era entre 0 e 1). write(*.0000000E+00 3. l 1 format(4(1x. Para este tipo de formato é necessário que w  d+7 4.567 write(*.1.d) Alterando o programa anterior para usar a formatação ES tem-se program formato_real_ES implicit none real :: i = 1.L1)) stop end program formato_logico_L Versão primeira de janeiro 1999.1)x. porque é idêntico à notação científica e os resultados poderão ser entendidos mais facilmente pelo usuário.123456789.unesp. O formato geral do descritor ES é r(ESw. e sua forma geral é r(Lw) O programa abaixo program formato_logico_L implicit none logical :: x = . j.com 31 . l = 1234. Versao atual impressa (*..pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.br e jbaparecido@gmail..Fortran 90/95 Percebe-se que este formato é mais adequado que o formato F quando deseja-se ler ou imprimir números ou muito pequenos ou muito grandes.1)i. k = 21.5 Saída de dados lógicos: O descritor L O descritor L é usado para formatar dados do tipo lógico. utilize o descritor ES.false.true. y 1 format(2(1x.feis.1123460E+01 1. multiplicado por um potência de 10. y = .7)) stop end program formato_real_ES O resultado deste programa será 1.

O descritor T tem a forma Tc Versão primeira de janeiro 1999.5 Saída de dados caracter: O descritor A Dados do tipo caracter são formatados com o descritor A.1.6 Posicionamento horizontal: Os descritores X e T Estes dois descritores operam quando os dados já estão no buffer.1. destinadas a inserir um branco na primeira coluna e assim informar ao compilador que se desejava espaçamento simples. O descritor X insere brancos nos locais designados.unesp.2)x write(*.Fortran 90/95 irá produzir o seguinte resultado TF 4.1)x write(*. através de declarações do tipo 1X. que tem a seguinte forma geral r(A) ou r(Aw) Abaixo apresenta-se um programa que explora o descritor A program formato_caracter_A implicit none character(len = 15) :: x = 'Como vão vocês?' write(*. e o T tabula a coluna para onde se deve ir. Versao atual impressa (*.A20) stop end program formato_caracter_A Este programa quando executado fornece o seguinte resultado Como vão vocês? C Como Como vão vocês? Como vão vocês? 4.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.3)x write(*.5)x 1 format(1x. O descritor X tem o seguinte formato nX onde n é a quantidade de branco que se quer inserir em um determinado local.br e jbaparecido@gmail. Lembre-se que nos programas anteriores utilizou-se o descritor X.A1) 3 format(1x.4)x write(*.A) 2 format(1x.A15) 5 format(1x.feis.A5) 4 format(1x.com 32 .

4.br e jbaparecido@gmail. Versao atual impressa (*. Veja o exemplo abaixo program formato_XT implicit none integer :: i = 1. j = 2.false.2. k = 3 write(*.4x. write(*.unesp. j. Se colocarmos vários slashes seguidos o efeito será pular várias linhas de impressão.t4.6 Trocando as linhas de saída: O descritor slash (/) O descritor / (slash) quando encontrado em uma declaração format envia o conteúdo do buffer para a impressora e inicia um novo buffer. isto eqüivale a dizer que o descritor / inicializa uma nova linha de impressão. O efeito que o descritor T causa é ficar saltando de um coluna para outra durante a impressão.1. y 1 format(2(1x. 4.true. Caso isto não ocorra o programa irá falhar durante a execução.1)x.t2.i1..1)i. Declarações READ formatadas Versão primeira de janeiro 1999. No programa abaixo mostra-se o efeito causado pelo descritor slash program formato_slash implicit none logical :: x = .i1. y = . como o mostrado acima.Fortran 90/95 onde c é o número da coluna para onde deve-se ir.i1) stop end program formato_XT cujo resultado final será 321 Quando utilizando descritor T seja cuidadoso para não produzir resultados aparentemente falsos.feis.L1//)) stop end program formato_slash O resultado impresso deste programa é T F Esteja certo que exista uma relação um-para-um entre os tipos de dados em uma declaração write e os tipos de formato especificados na declaração format correspondente.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.com 33 . k 1 format(1x.

2.com 34 . Este tipo de acesso é mais usado em unidades de fita magnética.br e jbaparecido@gmail. Várias declarações do Fortran são destinadas ao controle deste processo de ler ou escrever dados em um arquivo (file).2-Declarações Fortran de entrada e saída de dados Declaração de entrada ou saída Função Associa um arquivo em disco com um número de open entrada ou saída. Nos computadores esta entidade que armazena dados em disco (ou mesmo em fitas ou outros dispositivas de armazenamento de dados) é conhecida como FILE. necessita-se ler grandes arquivos armazenados em disco.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. em ordem consecutiva. Sua forma é open(lista_open) onde lista_open contém uma série de especificações sobre a unidade de entrada ou saída de dados.feis. um record por vez. Todo file é constituído de um conjunto de linhas chamadas de RECORD.2. Veremos neste capítulo algumas destas Versão primeira de janeiro 1999. A maneira de direcionar uma declaração read ou write para um determinado dispositivo de entrada ou saída de dados é feita colocando o número correspondente daquela unidade no lugar do primeiro asterisco que aparece nas declarações read e write usadas nos programas mostrados anteriormente. Versao atual impressa (*. Termina a associação iniciada com a declaração close open Lê dados de uma unidade de entrada de dados read especificada Escreve dados em uma unidade de saída de dados write especificada Move o ponteiro para o começo do arquivo rewind Move o ponteiro um record para traz em um backspace arquivo 4. As discutidas neste capítulo estão na Tabela 4.Fortran 90/95 As regras de formatação de declarações READ são semelhantes às de declarações WRITE. um record de cada vez. Quando se lê dados em um arquivo. e informações de como acessar o arquivo. As várias especificações dentro da lista_open são separadas por vírgulas. Tabela 4. e também gravar grandes arquivos em disco. O Fortran é capaz de ler ou escrever informações em um file. dizse que este é o acesso seqüencial.1 A declaração OPEN A declaração open associa um arquivo (file) com um número dado de unidade de entrada ou saída de dados.2. Freqüentemente. Introdução a arquivos e processamento de arquivos Em todos programas mostrados até o momento as entradas de dados foram pelo teclado e a saída na tela. o nome do arquivo. A quantidade de dados de entrada e de saída eram pequenas. Quando salta-se livremente de um record para outro sem ordem específica.unesp. 4. diz-se que este é um acesso direto.

Se o processo não for bem sucedido o sistema retornará em variável_inteira um número positivo correspondente ao código de mensagem de erro. A expressão old refere-se a arquivos já existentes.br e jbaparecido@gmail. O formato desta declaração é close(lista_close) onde a lista_close deve conter o número de entrada e saída associado ao arquivo que se deseja fechar. outras apenas em outros capítulos mais adiante. new refere-se a arquivos novos. unit character(len = 5) :: file_name unit = 25 file_name = ’saida’ open (UNIT = unit. STATUS = ’old’.dat’. apenas para escrita. Se a abertura do arquivo é bem sucedida o valor zero (inteiro) será retornado na variável_inteira. Um exemplo é o que fecha o arquivo associado ao número de entrado e saída igual a oito. 4) ACTION = expressão_caracter: Esta especificação indica se o arquivo deve ser aberto apenas para leitura. ou para a leitura e escrita.2. ACTION = ’read’. unknown refere-se tanto a arquivos antigos quanto novos. scratch refere-se a arquivos que serão deletados pelo sistema quando a execução do programa terminar. 4. IOSTAT = i_error) integer :: i_error.unesp. dependendo se está lendo ou escrevendo no arquivo. ‘NEW’. como segue Versão primeira de janeiro 1999. Os próprios títulos são auto-explicativos.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. Esta prática vai prevenir erros tais como escrever em cima de um arquivo que deseja-se preservar. 2) FILE = expressão_caracter: Esta especificação estabelece o nome do arquivo a ser aberto. e replace significa que um arquivo vai ser aberto para saída de dados.feis. independente da existência de outro arquivo com o mesmo nome. e ‘READWRITE’. e ‘UNKNOWN’. Nestes três casos a expressão_caracter assume os seguintes valores: ‘READ’. ‘WRITE’. Abaixo segue alguns fragmentos de código mostrando alguns casos de declarações open integer :: i_error open (UNIT = 8. As cinco especificações mais importantes são: 1) UNIT = expressão_inteira: Esta especificação indica qual é o número inteiro que vai se usar para associar com arquivo. 5) IOSTAT = variável_inteira: Esta especificação indica o nome de uma variável inteira na qual o status da operação open será retornado. FILE = file_name. Versao atual impressa (*. & ACTION = ’WRITE’.com 35 . 3) STATUS = expressão_caracter: onde expressão_caracter pode assumir os seguintes valores: ‘OLD’.2 A declaração CLOSE A declaração CLOSE fecha o arquivo e libera o número de entrada e saída que estava associado com aquele arquivo. IOSTAT = i_error) Sempre tenha cuidado ao especificar os argumentos da declaração OPEN. ‘REPLACE’. Pode existir nesta lista outros argumentos que serão discutidos em outro capítulo.Fortran 90/95 especificações. ‘SCRATCH’. STATUS= ’REPLACE’. FILE = ’exemplo.

quando a leitura é bem sucedida o sistema irá retornar um valor zero para i_err.feis. y. y. e o REWIND que reposiciona o ponteiro no início do arquivo.5 Posicionamento em arquivos Conforme escrito anteriormente um dos tipos de arquivos em Fortran são os seqüenciais.Fortran 90/95 close(UNIT = 8) ou simplesmente close(8) 4. y.4 O uso da especificação IOSTAT= nas declarações READ A especificação IOSTAT= pode ser usada juntamente com a declaração READ (ou mesmo com WRITE) quando se estiver operando com arquivos em disco.*) x. z em formato livre.2. ou escrever duas vezes na mesma posição. z open (UNIT = 8. O número 10 é o label da declaração format que especificará a formatação de leitura. Se a leitura for malsucedida o programa não descontinuará e retornará um valor não nulo para i_err. O BACKSPACE que move o ponteiro um record para trás de cada vez. i read(7. Isto provê um meio gracioso de detectar excepcionalidades em operações com arquivos. 4.IOSTAT = i_err) i Neste caso a declaração read tentará ler a variável inteira i no arquivo que estiver vinculado ao número 7 de entrada e saída de dados. x irá ler no arquivo exemplo. Com a introdução deste novo argumento IOSTAT = i_err.com 36 .3 READs e WRITEs a arquivos em disco Uma vez que um arquivo foi conectado a um número de entrada e saída de dados através de um declaração open será possível ler do arquivo ou escrever no arquivo utilizando as declarações read e write já utilizadas anteriormente. Às vezes é necessário ler um mesmo dado duas vezes. A declaração read ficará então com o seguinte aspecto integer :: i_err. O Fortran apresenta duas declarações para resolver este tipo de problema. que devem ser lidos ou escritos um record após o outro em uma ordem consecutiva.2. Tudo isto já se fazia antes. utilizando um IF está situação pode ser detectada e alguma providência tomada para resolver o problema ou fazer uma terminação elegante do programa ao invés das terminação selvagens que ocorre quando este recurso não é usado. Por exemplo o seguinte bloco de declarações real :: x. IOSTAT = i_error) read (8. quando a leitura era bem sucedida o programa continuava a execução. 4.unesp.dat.dat’. e o programa continuará. As formas destas duas declarações são como segue backspace (UNIT = unit_number) Versão primeira de janeiro 1999. STATUS = ’OLD’.br e jbaparecido@gmail. já existente os dados reais x. Sempre inclua a especificação IOSTAT = quando lendo (ou mesmo escrevendo) um arquivo de disco.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. Da forma anterior. Versao atual impressa (*. Quando a leitura era malsucedida o programa descontinuava.2. FILE = ’exemplo.10.

com 37 . para detectar possíveis erros no posicionamento do arquivo.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.feis.br e jbaparecido@gmail.Fortran 90/95 e rewind (UNIT = unit_number) onde unit_number é o número da unidade de entrada e saída à qual está associado o arquivo. sem causar a descontinuação. Estas duas declarações podem ainda estar munidas da especificação IOSTAT=.unesp. Versão primeira de janeiro 1999. Versao atual impressa (*.

e seus elementos por índices que indicam a sua posição dentro do array. Versao atual impressa (*. matriz e tensor. dimension(16) :: x nesta declaração tem-se um vetor x com 16 elementos do tipo real. Existe um paralelismo entre estes conceitos da matemática e algumas formas de organizar dados em computação. produz-se então o mesmo efeito de empilhar as colunas. Os componentes de um array são os elementos do array. os dados estão dispostos como se estivessem em um plano retangular. porém estão organizados com um aspecto bidimensional. Para evitar a proliferação de nomes. 5. quanto ao tipo e à quantidade de elementos que possui.9) e c(1.9. Nos arrays com rank 1 os dados subsequentes são armazenados em posições subsequentes na memória do computador. Um vetor (tensor de ordem 1) é uma entidade composta de vários escalares com um definida ordem. de tal forma que o índice mais à direita correspondesse ao laço mais externo e o índice mais à esquerda correspondesse ao laço mais interno.br e jbaparecido@gmail. Da matemática tem-se os conceitos de vetor.9.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.feis. os dados são colocados em linha.com 38 . e assim por diante até a última coluna. Desta forma as expressões a(7). para informar ao compilador que tipo de dado será armazenado e quanto será usado de memória.100) do array c. Os vetores computacionais seriam arrays unidimensionais (ou arrays com rank 1). ao elemento na posição (6. digamos. dimension(100) :: y Versão primeira de janeiro 1999. as matrizes seriam arrays bidimensionais (ou arrays com rank 2).100) referem-se ao sétimo elemento do array a. e assim sucessivamente. tudo se passa como se os índices mais à direita fossem colocados nos laços mais externos dos DOs. depois incrementa-se o índice da direita e varia o da esquerda mais rápido. vamos aqui chamar estas formas organizadas de dados simplesmente de arrays.9) do array b.1 Declarando arrays Antes de começar a usar um array é necessário declará-lo. um aspecto unidimensional. Em arrays com rank 2 o armazenamento do array faz-se seqüencialmente pela primeira coluna (como em um array de rank 1).unesp. character(len = 25). e assim por diante até o conceito de arrays n-dimensionais (ou arrays com rank n).Fortran 90/95 CAPÍTULO 5 ARRAYS Para facilitar as operações sobre os dados de um programa. Generalizando para arrays n-dimensionais. O conceito e o uso de arrays facilita tremendamente a execução das operações de álgebra linear sobre um dado conjunto de dados. Cada array é identificado por um nome. e ao elemento (1. isto pode ser dito ainda da seguinte forma: se imaginarmos os índices do array como componentes de um ninho de DOs. Estes tipos de estruturas quando estão dispostos de uma forma em que as dimensões sejam maiores que 2 em geral são chamados de tensores. em geral é interessante ordenar estes dados de alguma forma especial e dar-lhes um nome de tal forma que possam ser referenciados facilmente. Uma matriz (tensor de ordem 2) também tem seus componentes básicos organizados. Olhando de outra forma. congela-se o índice direito do array e varia o da esquerda. Abaixo apresenta-se algumas declarações de arrays: real. depois empilha-se seqüencialmente a segunda coluna. Os vetores têm. b(6.

/) 5.5. integer.2 Usando elementos de array em declarações Fortran Aqui apresenta-se algumas informações de como utilizar elementos de arrays em declarações Fortran. usando um construtor de arrays. foi inicializado utilizando um declaração para cada elemento. dimension(5) :: w = (/1../) as duas /s existentes no exemplo acima funcionam como o início e o final dos dados do array sendo inicializado. A forma de um array é definida pelo seu rank e pelas extensões do array nas várias direções.com 39 . Abaixo apresenta-se alguns exemplos integer.. e portanto podem ser inseridas em qualquer expressão aritmética ou lógica.2 Inicializando elementos de array Os elementos de um array podem ser inicializados por declaração de atribuição.. Dois arrays tem a mesma forma se possuem o mesmo rank e as mesmas extensões em cada direção.Fortran 90/95 nesta tem-se um vetor y com 100 elementos do tipo character(25).. 5.3.4.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.2. 5. Um array constante é aquele que possui todos seus elementos constantes. Versao atual impressa (*. 30) :: i aqui tem-se um array de rank 3 x com 102030 elementos do tipo integer.4. dimension(10. dimension(1000) :: k integer :: i Versão primeira de janeiro 1999. Para um array constante o código acima seria modificado para real.1 Elementos de array Cada elemento de um array é uma variável tal como todas as outras já apresentadas até o momento nos capítulos anteriores. dimension(5) :: w w = (/1. O número de elementos do array em uma dada direção chama-se extensão do array naquela direção.2. Pode-se definir arrays constantes.unesp. 20.2.. Para arrays pequenos isto é possível. parameter.2. O tamanho de um array é o total de elementos declarados naquele array. Assim vejamos o seguinte exemplo integer. para arrays grandes é melhor utilizar estruturas de laços para efetuar tal tarefa...br e jbaparecido@gmail. dimension(3) :: k k(1) = 5 k(2) = 4 k(3) = 1 neste caso o array k.3. Inicializa-se um array constante ou não.feis. com elementos inteiros..5. Abaixo apresenta-se um exemplo de uso do construtor de array real.

pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.0 5. Entretanto este processo torna os programas mais lentos. Quando o programa estiver na forma final é desejável que a versão final seja compilada com a verificação de limites de array desligada. seus elementos seriam normalmente numerados de 1 a 11. A dimensão numa dada direção (i) é obtida por extensao_i = valor_alto_i – valor_baixo_i + 1 5.1000)/) também é possível fazer operações mais complexas. dimension (valor_baixo : valor_alto) :: x ou para um array rank 2 real. Versao atual impressa (*. ao se tentar acessar o suposto décimo quinto elemento. dimension (valor_baixo_1 : valor_alto_1.5/) se todos os elementos de um array assumem o mesmo valor é possível. e o n-ésimo de n.br e jbaparecido@gmail. Imagine um array com 11 elementos.com 40 . O Fortran suporta este tipo de nomenclatura que é expressa da seguinte forma para um array rank 1 real. que a quantidade de elementos seria os mesmos 11. i = 1.2. Desta forma é aconselhável que esta capacidade fique ligada quando o programa estiver sendo criado e compilador. 1000 k(i) = i*i end do Sempre inicialize os elementos de um array antes de utilizá-lo. Isto pode ser diferente. Assim em geral esta capacidade de fazer a verificação de limites de array é opcional nos compiladores. dimension(10) :: k = (/(0.unesp. dimension(1000) :: k = (/(i*i. o que acontecerá? Isto depende de processador para processador.3 Modificando a faixa de subscritos de um array Os elementos de um array rank 1 são endereçados normalmente numerando o primeiro de 1. como integer.feis.5). Em alguns o programa rodando verificará se todos os elementos usados estão na faixa adequada. No entanto também poderíamos numerá-los de –5 a 5.Fortran 90/95 do i = 1. O bloco de programa acima também poderia ter sido inicializado utilizando-se um laço implícito (uma forma especial de laço do tipo DO). escrever-se real. digamos 10 elementos. valor_baixo_2 : valor_alto_2) :: x para ranks maiores procede-se de maneira semelhante ao rank 2. j = 1. Versão primeira de janeiro 1999. Como segue integer.2. Caso seja identificado casos fora da faixa.4 Subscritos de array fora da faixa de definição Para um array rank 1 com. simplesmente. dimension(55) :: t t = 7. i = 1. o segundo de 2. o programa emitirá um mensagem e descontinuará a execução.

i_max) :: array1. i_max do j = 1.1 Operações com arrays completos Sob certas circunstâncias é possível efetuar operações sobre arrays completos com uma notação similar àquela usada para variáveis escalares.5 O uso de constantes na declaração de arrays O uso de constantes pode ser utilizado para melhorar e tornar mais claro a declaração da extensão de arrays em cada direção. array3 ! inicialização dos arrays do i = 1. visando torná-los fáceis de ler.5 array3(i.tamanho) Sempre use constantes para declarar o tamanho de arrays em programas Fortran. e de modificar. Forma tradicional ! Este programa mostra operações sobre arrays. i_max array1(i.j) = 1.j) = 0. array2.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.Fortran 90/95 5.3 Usando arrays completos e sub-conjuntos de arrays Conforme mencionado anteriormente é possível fazer as operações clássicas da álgebra sobre os elementos de um array. 5. Se dois arrays tem a mesma forma.unesp. Algumas funções intrínsecas aplicam-se a arrays completos. utilizando módulos. numa estratégia elemento-a-elemento. parameter :: tamanho = 1000 real :: array1(tamanho) real :: array2(tamanho+5) real :: array3(tamanho*tamanho) real :: array4(tamanho. j character(1) :: word real.br e jbaparecido@gmail.j) = 2. Abaixo mostra-se alguns exemplos de tal uso integer. Além disto o uso de constantes protege a grandeza contra a corrupção de seu valor.com 41 .2. um escrito na forma tradicional.feis. Abaixo mostra-se dois programas. dimension(i_max. escritas da forma tradicional ! usando laços de DO ! program operacao_sobre_arrays implicit none ! declarações de variáveis integer. Vamos ver nesta seção como fazer operações sobre arrays completos ou sobre subconjuntos de arrays.3. 5. Em outro capítulo apresenta-se uma outra forma ainda mais elaborada de encapsular os dados. Versao atual impressa (*. ou escrito usando operações sobre arrays completos. parameter :: i_max = 100 integer :: i.5 array2(i.0 end do end do !somando o array1 com o array2 e colocando no array3 Versão primeira de janeiro 1999. eles podem ser usados em algumas operações aritméticas como se fossem escalares.

j) end do end do !calculando a raiz quadrada de dos elementos de array3 do i = 1.j) + array2(i.5 array2 = 2.*)'Digite algo!' read(*.Fortran 90/95 do i = 1. i_max write(*. i_max do j = 1.j) end do end do !criando um efeito pause write(*.*)array3 !criando um efeito pause write(*.feis.com 42 . i_max array3(i.j)) end do end do !imprimindo os resultados do i = 1. parameter :: i_max = 100 character(1) :: word real.j) = array1(i.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.*)word !terminação do programa Versão primeira de janeiro 1999. escritas da forma usando ! operações sobre arrays completos ! program operacao_sobre_arrays implicit none ! declarações de variáveis integer.br e jbaparecido@gmail. array2. array3 ! inicialização dos arrays array1 = 1. Versao atual impressa (*. i_max array3(i.*)word !terminação do programa stop end program operacao_sobre_arrays Forma usando operações arrays completos ! Este programa mostra operações sobre arrays. i_max) :: array1. dimension(i_max.j) = sqrt(array3(i.unesp.*)array3(i. i_max do j = 1. i_max do j = 1.*)'Digite algo!' read(*.0 !somando o array1 com o array2 e colocando no array3 array3 = array1 + array2 !calculando a raiz quadrada de dos elementos de array3 array3 = sqrt(array3) !imprimindo os resultados write(*.5 array3 = 0.

2) :: array6 = array2(1:3:1.14.3.2. Se dois arrays não tem a mesma forma então não poderão executar operações do tipo array completo.5.4.6.15. está-se informando ao compilador que a soma deve ser feita naquela seqüência.9.2) :: array5 = array2(1:2:1.2.3. Sejam os seguintes arrays originais integer. dimension(7) :: array1 = (/1. Se indice_1 não aparece na trinca o seu default é o primeiro índice de elemento para aquela direção. dimension(3.13.3:4:1) integer. o seu default é a unidade. dimension(5) :: array4 = array1(1:5:1) integer.15.4) :: array2 = (/1.com 43 .7.5. e incr é o incremento que se fará ao longo do array completo. e incr quando não aparece na trinca.2. dimension(4) :: array3 = array1(1:7:2) integer.6.4.3.Fortran 90/95 stop end program operacao_sobre_arrays Fica claro que todos os resultados impressos são iguais a 2.10.4) :: array2 = (/1. dimension(2.6.14. Esta definição pode ser aplicada para cada direção do array.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. Assim a notação de operações sobre arrays completos também leva a processamento paralelo do tipo SIMD quando houver suporte para tal. 5.4. dimension(7) :: array1 = (/1. nas estruturas passíveis deste tipo de paralelismo e quando o computador tiver dois ou mais processadores.9. Versao atual impressa (*.7.5. está-se informando ao compilador que a soma dos elementos pode ser efetuada de uma maneira não necessariamente seqüencial.16/) integer.12.8. Se indice_2 não aparece na trinca o seu default é o último índice de elemento para aquela direção. Quando se utiliza a notação compacta de operações sobre arrays completos. dimension(4.13.unesp.6.3. Na operação com arrays completos basta que os arrays envolvidos numa operação tenha a mesma forma.1:2:1) Um ou todos os elementos da trinca podem ser default. dimension(4.2 Definindo e operando com subconjuntos de arrays Para definir um subconjunto de um array ou seção de array (array section) faz-se necessário usar uma trinca de índices que tem a forma geral indice_1 : indice_2 : incr onde indice_1 é o primeiro subscrito a ser incluído no subconjunto do array.br e jbaparecido@gmail. não importando se as faixas das extensões de cada array em cada direção usem notação diferenciada. um elemento após outro.7/) integer. indice_2.7/) integer. Quando se faz um laço de DO para se somar dois arrays.3.0.11. Todas as combinações abaixo são possíveis e legais indice_1 : indice_2 : incr indice_1 : indice_2 Versão primeira de janeiro 1999.8.12. Abaixo apresenta-se alguns exemplos de definição de subconjuntos de arrays. Conforme já mencionado no Capítulo 1 o Fortran90/95 é capaz de efetuar por si só processamento paralelo do tipo SIMD.feis. é o último subscrito a ser incluído.11.2.4.5.10.16/) assim pode-se definir os seguintes exemplos de subconjuntos de arrays integer.

e funções de transformação (transformational functions). array2) stop end program reformatacao_de_arrays Como o construtor de arrays só funciona com arrays rank 1. array2) onde array1 contém os dados para reformatar e array2 é um array rank 1 descrevendo a nova forma. ! program reformatacao_de_arrays implicit none ! declarações de variáveis integer.com 44 .unesp.Fortran 90/95 indice_1 : indice_1 :: incr : indice_2 : indice_2 : incr :: incr : 5. O array3 é o resultado da reformatação. 5. funções de questionamento (inquiry functions). j_max) :: array3 integer. a declaração reshape serve para transformar arrays criados rank 1 em arrays que não sejam rank 1. ! Este programa mostra a reformatação de arrays. Algumas funções de cada um destes grupos são projetadas para operar com arrays. parameter :: i_max = 100. Abaixo apresenta-se um programa que reformata um vetor com cem elementos para uma matriz quadrada (1010). por exemplo.4 Usando funções intrínsecas Fortran com arrays O Fortran 90/95 têm três tipos de funções intrínsecas: funções elementares (elemental functions).pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. Versao atual impressa (*. dimension(j_max.3. j_max = 10.br e jbaparecido@gmail. para um array rank 2 (1010) ou mesmo um array rank 2 (520). O número de elementos em array1 deve o mesmo número de elemento para forma especificada para array2. mantendo os valores e o mesmo nome. Para tal utiliza-se a função intrínseca RESHAPE cuja formato é array3 = reshape(array1.10/) ! inicialização do array1 do i = 1.feis. quando bem sucedida. dimension(i_max) :: array1 real. caso contrário a declaração reshape irá falhar. i_max array1(i) = i end do !reformatando o array1 para array3 array3 = reshape(array1. O número de elementos em array2 é igual ao número de dimensões no array de saída e os seus valores são iguais à dimensão em cada direção. rank = 2 integer :: i real. Versão primeira de janeiro 1999.3 Reformatando arrays Um array rank 1 com cem elementos pode ser reformatado para. dimension(rank) :: array2 = (/10.

Estes dois arrays deverão ter o mesmo formato. Versao atual impressa (*. Se o argumento de uma função elementar é um escalar o resultado será um escalar. Este tipo de funções não operam sobre escalares. Caso contrário retorna o tamanho do array ubound(array.4.4. Versão primeira de janeiro 1999.feis.com 45 . Alguns exemplos são y = sin(x) y = cos(x) y = sqrt(x) onde x e y ou são ambos escalares ou são dois arrays de mesmo formato.1-Algumas funções comuns de questionamento Função e seus argumentos Utilidade allocated(array) Determina se um array alocável está alocado ou não.4.br e jbaparecido@gmail.2.Fortran 90/95 5.dim) Retorna todos os limites inferiores das dimensões de um array se dim não está presente (o retorno é um array).pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.dim) Retorna a dimensão do array em cada direção se dim está presente.1 Funções intrínsecas elementares São funções que projetadas para operar com escalares trabalham também com arrays. Freqüentemente o resultado deste tipo de função é um array com formato diferente dos arrays de entrada.3 Funções intrínsecas de transformação Funções intrínsecas de transformação são funções que tem um ou mais arrays como argumento ou um array como resultado. Se dim está presente retornará o maior dos limites superiores (o retorno é um escalar) 5.unesp. Por exemplo LBOUND(force) é uma função de questionamento que retorna o menor subscrito do array force.2 Funções intrínsecas de questionamento Funções intrínsecas de questionamento são funções cujo resultado depende do formato e da natureza do argumento. se o argumento é um array o resultado será também um array. apenas sobre arrays completos. O Fortran 90/95 têm muitas funções intrínsecas de transformação. Se dim está presente retornará o menor dos limites inferiores (o retorno é um escalar) shape(array) Retorna a forma de um array size(array.1 apresenta-se algumas destas funções mais usadas. Na Tabela 5. A maioria das funções intrínsecas que aceitam escalares como argumentos também aceitam arrays. algumas são apresentadas na Tabela 5. Tabela 5. 5. lbound(array.dim) Retorna todos os limites superiores das dimensões de um array se dim não está presente (o retorno é um array).

com 46 .mask) Retorna o menor valor no array entre aqueles para os quais MASK é TRUE. Versao atual impressa (*.2-Algumas funções de transformação comuns. O Fortran 90/95 suporta operação sobre array considerando uma máscara que informa sobre quais elementos deve-se fazer ama operação e quais devem ficar com a outra operação. Função e argumentos Utilidade all(mask) Função lógica. (mask é opcional) product(array. MASK é opcional.array2) Constrói um novo array a partir do array1 e das informações do novo array contidas em array2 rank 1.vet_2) Calcula o produto interno de dois arrays rank 1 de mesmo formato matmul(matriz_1.1 A estrutura WHERE do Fortran 90 A forma geral da estrutura WHERE do Fortran é nome: where (mask) Versão primeira de janeiro 1999. minval(array.mask) Retorna o local onde ocorre o elemento de menor valor entre aqueles para os quais MASK é TRUE.br e jbaparecido@gmail. se não estiver presente o produto é feito com todos os elementos do array.5. minloc(array. nas posições correspondentes às quais deseja-se fazer a primeira operação no array.mask) Calcula o produto dos elementos de um array para os quais MASK é TRUE.Fortran 90/95 Tabela 5.5 Atribuição de arrays com máscara: a estrutura WHERE Considere a necessidade de se fazer algum tipo de operação apenas sobre alguns elementos de um array e outro tipo sobre os restantes. transpose(matriz) retorna a transposta de um array rank 2. (mask é opcional) 5.unesp. retorna TRUE se todos os valores no array mask são TRUE any(mask) Função lógica.mask) Retorna o local onde ocorre o elemento de maior valor entre aqueles para os quais MASK é TRUE. O resultado é um array rank 1 contendo os subscritos da posição. se não estiver presente a soma é feito com todos os elementos do array. sum(array.matriz_2) Multiplica duas matrizes conformáveis maxloc(array. valores igual a TRUE. maxval(array. retorna TRUE se qualquer dos valores no array mask é TRUE count(mask) Retorna a quantidade de elementos TRUE em mask dot_product(vet_1.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. Deve-se colocar nesta máscara.mask) Calcula a soma dos elementos de um array para os quais MASK é TRUE. reshape(array1.mask) Retorna o maior valor no array entre aqueles para os quais MASK é TRUE. 5. e no restante das posições coloca-se FALSE.feis. MASK é opcional. O resultado é um array rank 1 contendo os subscritos da posição. Esta máscara em realidade é um array lógico com o mesmo formato do array a ser operado.

expressão_lógica) declarações_executáveis end forall nome Cada índice na declaração FORALL é especificado por uma trinca. na forma Versão primeira de janeiro 1999. o FORALL. Os elementos a serem operados são definidos pelos índices e também por uma expressão lógica.2 A estrutura WHERE do Fortran 95 O Fortran 95 apresenta uma forma mais complexa de estrutura WHERE. 5.Fortran 90/95 declarações_1_com_array elsewhere nome declarações_2_com_array end where nome No código acima faz-se declarações_1_com_array sobre todos os elementos do array para os quais os elementos correspondentes de mask é TRUE. 5.6.…. Sua forma é where(mask) declarações_com_array neste caso será feito determinado conjunto de operações apenas sobre os elementos do array que correspondem aos elementos com valores TRUE em mask. A forma geral da estrutura WHERE do Fortran 95 é nome: where (mask_1) declaracoes_com_array_1 elsewhere (mask_2) nome declaracoes_com_array_2 elsewhere nome declaracoes_com_array_3 end where nome 5. onde permite-se o uso de vários ELSEWHERE com máscara e apenas um ELSEWHERE sem máscara. Versao atual impressa (*. que foi projetado para permitir um conjunto de operações a serem aplicadas a um conjunto de elementos de um array.br e jbaparecido@gmail.6. A estrutura FORALL O Fortran 95 apresenta um novo tipo de estrutura.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. in_2 = trinca_2.feis. As operações ocorrerão apenas sobre os elementos do array que atendam as restrições contidas nos índices bem como aquela contida numa expressão lógica. Para aquelas posições correspondentes aos elementos com valor FALSE em mask aplica-se declarações_2_com_array. 5. Use a estrutura WHERE para modificar somente os elementos de um array que passem em um determinado teste.5. A forma da estrutura FORALL A forma geral da estrutura FORALL é nome: forall (in_1 = trinca_1.3 A declaração WHERE O Fortran 90/95 também tem uma estrutura WHERE com apenas um linha de declaração.5.com 47 .unesp.

e sempre verifique o valor retornado.Fortran 90/95 trinca_1 = indice_1 : indice_2 : incr já definidos anteriormente quando tratamos de subconjuntos de arrays. STAT = status) que é um array de 5061 elementos.com 48 . É desejável que o tamanho de um array seja definido durante a execução para se moldar às necessidades de armazenamento. Um array em Fortran que terá suas dimensões definidas dinamicamente. dimension(:. Após utilizar um array alocável é necessário desalocá-lo para liberar memória útil para outros propósitos. Isto pode ser feito usando a declaração executável DEALLOCATE. utilizando a declaração executável DEALLOCATE. que variam de caso a caso sendo executado. 5. Neste caso o programa define automaticamente o tamanho dos arrays de acordo com a necessidade e durante o período de execução. Se array já estiver alocado o retorno será TRUE. Sempre inclua a especificação STAT = em qualquer declaração ALLOCATE. Uma melhor solução é desenvolver um programa que use alocação dinâmica de memória. A forma geral desta declaração é deallocate (lista_de_arrays_para_desalocar. Para o programa definir durante a execução o tamanho do array é necessário o uso da declaração executável ALLOCATE que tem a seguinte forma allocate (lista_de_arrays_para_alocar. uma vez que o tamanho dos arrays nunca são definidos durante a execução do programa. deve-se liberar a memória que ele ocupava. STAT = status) Um exemplo característico é Versão primeira de janeiro 1999.unesp. STAT = status) Um exemplo típico é allocate(array1(50.-10:50). Para dotar um array de reais com o atributo de alocável procede-se como segue real.br e jbaparecido@gmail. caso contrário será FALSE. Arrays alocáveis Todos os arrays utilizados até o momento tiveram suas dimensões definidas durante o período de compilação e não podem ser alteradas durante a execução do programa.7.feis. Versao atual impressa (*. Caso se tenha dúvida se um array alocável já está alocado.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. de tal forma que o programa termine de maneira elegante sempre que a memória a alocar para os arrays seja insuficiente. allocatable.:) :: array1 note que na declaração acima o tipo do array fica definido. pode-se descobrir esta informação usando a função de questionamento ALLOCATED(array). e é alocado usando a declaração executável ALLOCATE. mas não o seu tamanho. Esta é a chamada alocação estática de memória. Quando um array alocável não vai mais ser utilizado. deverá ser declarado alocável usando o atributo ALLOCATABLE na declaração de tipo de variável.

STAT = status) onde a especificação STAT = tem o mesmo significado daquela usado na declaração ALLOCATE.feis. Abaixo apresenta-se um programa que faz a alocação dinâmica de uma matriz.i).Fortran 90/95 deallocate(array1.*)'Digite i (inteiro) = ' read(*.:) :: x !array alocável !Entra com o inteiro i write(*.unesp. allocatable.*) ’A alocação falhou!” stop end if !Atribui valores ao elementos do array x x = 5. status real. ! ! Programador: João Batista Aparecido ! Ilha Solteira.0 !Desaloca a memória ocupada por x deallocate(x. ! program alocacao_dinamica implicit none !declara variáveis integer :: i.*)i !Faz a alocacao de memória para o array x allocate(x(i.com 49 .*) ’A desalocação falhou!” stop end if !Terminação do programa stop end program alocacao_dinamica Versão primeira de janeiro 1999.br e jbaparecido@gmail. !Programa para mostrar a alocacao dinâmica de arrays. dimension(:.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. stat = status) !Teste para verificar se a alocação foi bem sucedida if(status /= 0) then write(*. Criado em 9/12/1999 ! Modificado em 27/07/2001. stat = status) !Teste para verificar se a desalocação foi bem sucedida if(status /= 0) then write(*. Versao atual impressa (*.

E fazendo um paralelo na área de programação computacional. este é invocado. isto produz um certo grau de encapsulamento dos dados. Em métodos numéricos esta idéia é muito utilizada. Versao atual impressa (*. podendo ser editadas e compiladas separadamente. termina a execução. Subrotinas e funções podem chamar outras subrotinas e funções.Fortran 90/95 CAPÍTULO 6 FUNÇÕES E SUBROTINAS No primeiro livro considerado de ciência política.br e jbaparecido@gmail. Estas partes podem ser desenvolvidas de um maneira razoavelmente independente. E assim sucessivamente tantos quantos sub-programas sejam encontrados pelo programa principal durante a execução. Para estes grandes grupos naturalmente é necessário a existência de um gerente de projeto. 6. As funções recebem um ou mais argumentos do programa e retornam apenas um argumento. O uso de subrotinas e funções é vantajoso porque permite dividir um programa que seria muito grande em partes modulares. robustas e precisas. o autor Nicolau Maquiavel. Estes programas são usados da seguinte maneira: Quando o programa principal vai sendo executado e encontra uma referência a um sub-programa. divide-se tarefas para diferentes programadores e depois vai-se integrando o resultado final. evitando em parte que a execução de um subrotina ou função corrompa os dados do programa principal ou mesmo de outras subrotinas ou funções. podendo ser um array. Talvez seria melhor neste caso adaptá-la para: dividir para calcular. escrito no entorno de 1500. O debugamento destas rotinas em separado torna-se mais fácil do que se estivessem em um programa único. A questão então é como dividir um programa? Em Fortran tem-se o programa principal (único) e programas auxiliares. poderão ser reusadas em qualquer outro programa que seja necessário. Se as subrotinas e funções estiverem bem desenvolvidas. O uso de subrotinas e funções também facilitam a manutenção do programa. o sub-programa recebe o controle da execução.unesp. o programa principal passa-lhe as variáveis necessárias. As subrotinas recebem um ou mais argumentos do programa e retornam um ou mais argumentos para o programa. também chamados de sub-programas. Pode-se ter subrotinas que não retornem nenhum argumento para o programa. executa as declarações.com 50 .feis. Para invocar functions dentro de um programa Fortran basta mencionar seu nome em uma expressão aritmética ou lógica. Devido ao fato de que as variáveis de uma function ou subroutine são na sua maioria locais. ela recebe alguns argumentos de entrada e retorna outros argumentos de saída.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. A forma geral de declarar uma subrotina é subroutine nome (lista_de_argumentos) declaracoes_não_executaveis Versão primeira de janeiro 1999.1 Subrotinas Uma subrotina é um sub-programa Fortran que é invocado utilizando a declaração CALL antes do nome da subrotina. poderíamos também dizer: dividir para programar. Pode-se ter elementos de grupos de trabalhos mesmo em países diferentes. Uma outra vantagem é que isto facilita o trabalho em equipe. Existem dois tipos principais de sub-programas: as funções (functions) e as subrotinas (subroutines). já ensinava: dividir para conquistar. sem necessidade de desenvolvê-las de novo. e passa de volta o controle da execução ao programa principal. Para invocar subroutines é necessário utilizar a declaração CALL antes do nome da subrotina.

O nome da subrotina pode ter até 31 caracters porém o primeiro deve ser alfabético.0.feis. a não que tenha sido declarada recursiva (recursive).unesp. quando de sua execução a passagem de dados é feita de uma forma apropriada e o resultado produzido é o correto. Quando um programa passa um argumento para uma subrotina. com isto a subrotina pode fazer uso do seu valor.br e jbaparecido@gmail. Na lista _de_ argumentos têm-se as variáveis e arrays que serão passadas.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. Em realidade é isto que ocorre com os chamados argumentos de retorno. por referência. 11 dezembro 1999 ! implicit none real :: x = 1. A forma de invocar uma subrotina é como segue call nome (lista_de_argumentos) onde os argumentos na lista_de_argumentos deve ter uma relação biunívoca com os listados na declaração de argumentos da subrotinas. b. z = 4. c !soma dois reais c=a+b return end subroutine soma Neste programa. a questão se é de entrada ou de saída Versão primeira de janeiro 1999. b. z) stop end program soma_dois_reais subroutine soma(a. ao tipo e ao uso que se destina.com 51 . a subrotina escreve algo naquela posição de memória que foi indicada pelo programa principal. da mesma forma que um programa pode ter vários STOPs. Versao atual impressa (*. quanto à quantidade. Uma subrotina não pode chamar a si mesma. Fica claro que a subrotina pode modificar o valor que está naquele endereço mediante uma simples operação de atribuição. Abaixo apresenta-se um programa que tem uma subrotina program soma_dois_reais !O objetivo deste programa eh mostrar o uso de uma subrotina ! !Programmer: joao batista aparecido ilha solteira.5. em realidade ele está passando um ponteiro que aponta para a posição de memória onde aquela variável está. A declaração return retorna o controle da execução ao programa principal. Como uma subrotina (ou função) é um programa independente pode-se utilizar variáveis com os mesmos nomes de variáveis usadas no programa principal e outras subrotinas sem a possibilidade de conflito. y = 2.Fortran 90/95 declaracoes_executaveis return end subroutine nome No bloco de código acima a primeira linha marca o início da subrotina e a última linha marca o final da subrotina.5. c) implicit none real :: a. pelo programa principal quando invocar a subrotina. uma subrotina pode ter vários RETURNs. z !invocando a subrotina call soma(x. y.

A seguir apresenta-se um programa onde pode haverá algum tipo de corrupção de dados program corrupcao_de_dados !O objetivo deste programa eh mostrar a corrupcao de !dados quando se utiliza subrotinas ! !Programmer: joao batista aparecido ilha solteira. y = 2. y = 2. Dependendo da estrutura do programa a informação corrompida poderá se propagar contaminado os resultados intermediários e o resultado final. 11 dezembro 1999 ! implicit none real :: x = 1. c) implicit none real :: a.0 no entanto o resultado será z = 6. b. y. Percebe-se então que é possível haver a corrupção dos dados do programa principal através de uma alteração indevida ocorrida em uma subrotina. isto ocorreu porque uma operação dentro da subrotina que alterou o valor que estava armazenado no endereço da variável y.5. Isto pode ocorrer por digitacao distraida em um código !grande. neste ficam os valores e y e z corrompidos. z !invocando a subrotina call soma(x.5.5. z Versão primeira de janeiro 1999. z) stop end program corrupcao_de_dados subroutine soma(a.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. por fragmentos de codigo não deletado e assim por diante. Agora apresenta-se outro caso de corrupção de dados. c !corrompendo o dado b.5.unesp. Versao atual impressa (*. b=b*2 !soma dois reais c=a+b return end subroutine soma Neste caso o resultado deveria ser z = 4.feis. via definição incorreta dos tipos das variáveis na subrotina program corrupcao_de_dados_2 !O objetivo deste programa é mostrar a corrupção de dados !quando se utiliza subrotinas ! !Programmer: joao batista aparecido ilha solteira.5. b.br e jbaparecido@gmail.com 52 .Fortran 90/95 (até este ponto) está mais na cabeça do programador. 11 dezembro 1999 ! implicit none real :: x = 1.

pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. c) implicit none !introduzindo a corrupção nos dados. apresentado na seção anterior. Este mecanismo reforça o encapsulamento de dados que ocorre na execução de uma subrotina. ou a definição conflitante dos tipos das variáveis no programa principal e na subrotina. quais são de saída e quais são de entrada e saída. Via uma declaração !incorreta de tipo na subrotina integer :: a.br e jbaparecido@gmail. A declaração INTENT é um atributo da variável e deve ser declarado no local de declaração de variáveis. A declaração INTENT especifica em uma subrotina quais argumentos são de entrada. Este atributo pode tomar as seguintes três formas intent(in) Usado apenas para passar dados de entrada para a subrotina intent(out) Usado apenas para passar dados de saída para o programa principal intent(inout) Usado nos dois casos. c !soma dois reais c=a+b return end subroutine soma A execução deste programa não irá corromper o valor da variável y mas irá produzir um resultado totalmente errado para a variável z. b.com 53 .unesp. 6. O objetivo do atributo INTENT é informar ao compilador como o programador quer usar cada um dos argumentos listados. ou seja os argumentos de saída. neste caso haverá a corrupção dos resultados gerados. Apresenta-se a seguir a solução para os problemas de corrupção de dados mostrados no primeiro exemplo. agora escrito utilizando o atributo INTENT.1 O atributo INTENT Percebe-se da análise dos dois exemplos apresentados acima que duas formas de corrupção de dados são: via a modificação acidental do valor das variáveis de entrada ou saída. program eliminando_corrupcao_de_dados Versão primeira de janeiro 1999.feis. Com isto o programa quando estiver executando não permitirá que um subrotina faça alterações no valor de uma variável de entrada. posteriormente retornaremos aos apresentados no segundo exemplo. y.1. ou seja no início da subrotina. z) stop end program corrupcao_de_dados_2 subroutine soma(a. Isto ajudará a detectar erros ainda durante a fase de compilação. Versao atual impressa (*.Fortran 90/95 !invocando a subrotina call soma(x. Apresenta-se abaixo o primeiro programa exemplo sob corrupção de dados. b. para receber e passar dados.

!por fragmentos de código não deletado e assim por diante.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. uma vez que sua forma é passada explicitamente. Basta compilar para ver! Portanto. ! !Programmer: joao batista aparecido ilha solteira.2 Passando arrays para subrotinas Como estabelecido anteriormente.br e jbaparecido@gmail. o compilador acusará de imediato o erro.5. Isto pode ocorrer por digitação distraída !em um código grande.unesp.1. b real. A pergunta que surge é: Como a subrotina fica sabendo do da forma e das extensões do array? O rank do array será definido no atributo dimension colocado na subrotina. sempre declare o atributo INTENT para todos os argumentos de uma subrotina. y. intent(out) :: c !corrompendo o dado b. Versao atual impressa (*. um escalar é passando do programa principal para um subrotina simplesmente passando um ponteiro que aponta para a variável. A primeira forma de se fazer isto é passar as extensões do array via argumentos da própria subrotina e então utilizar esta informação em uma declaração de atributo dimension e definir por completo a forma do array.com 54 . z !invocando a subrotina call soma(x. 6. 11 dezembro 1999 ! implicit none real :: x = 1. A seguir apresenta-se um programa que utiliza este tipo de passagem de argumentos do tipo array program passando_array_1 !Objetivo: Mostrar a passagem de um array do program principal !para um subrotina de forma explicita ! !programmer: joao batista aparecido ilha solteira.feis. 11 dezembro 1999 ! Versão primeira de janeiro 1999.5. ajuda !a combater a corrupção de dados dentro de uma subrotina (ou function). b = b*2 !soma dois reais c=a+b return end subroutine soma Quando da compilação. z) stop end program eliminando_corrupcao_de_dados subroutine soma(a. Existem três formas de informar à subrotina quais as extensões do array em cada direção. mas ainda fica faltando a informação sobre a extensão do array em cada direção. y = 2. Se o argumento é um array o programa principal passa um ponteiro que aponta para o primeiro elemento do array. c) implicit none real. b.Fortran 90/95 !O objetivo deste programa é mostrar que o bom uso do atributo INTENT. e mostrará claramente qual o erro e onde encontra-se. Os arrays passados desta forma são denominados de arrays com forma explicita. intent(in) :: a.

j_max. x. array1. intent(in). j_max.feis. dimension(i_max.0 !invocando a subrotina passa_array call passa_array(i_max.Fortran 90/95 implicit none integer. dimension(i. a seguir o código program passando_array_2 !Objetivo: Mostrar a passagem de um array do program principal !para um subrotina de forma implicita ! !programmer: joao batista aparecido ilha solteira.j) :: x real. Neste caso o compilador não sabe nada sobre as dimensões do array. O programa mostrado acima é adaptado para fazer passagem de array neste novo formato.j_max) :: array1. array2) stop end subroutine passa_array(i.br e jbaparecido@gmail.com 55 . array2) stop end subroutine passa_array(i. intent(in) :: i. intent(in) :: i. j.j) :: y y = sqrt(x) return end subroutine passa_array Note que este tipo de passagem de array suporta operações sobre arrays completos. y) implicit none integer. Os arrays passados desta forma são chamados de arrays de tamanho presumido. array2 !atribuição de valores aos arrays array1 = 5.0 !invocando a subrotina passa_array call passa_array(i_max. Versao atual impressa (*. Uma segunda maneira de se passar as informações de um array para o compilador é declarar na subrotina cada extensão do array com um asterisco. 11 dezembro 1999 ! implicit none integer. array2 !atribuição de valores aos arrays array1 = 5. dimension(i. y) implicit none integer.j_max) :: array1. dimension(i_max. j real. j_max = 120 real.unesp. parameter :: i_max = 100. j integer :: m Versão primeira de janeiro 1999. parameter :: i_max = 100.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. x. j_max = 120 real. intent(out). e as operações de verificação de limites do array e operações sobre arrays inteiros não são permitidas. j. array1.

pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.Fortran 90/95 !note a seguir os asteriscos nos atributos dimension real. dimension(*) :: x real. ele interpreta que trata-se um um array rank 1.i*j y(m) = sqrt(x(m)) end do return end subroutine passa_array Note que neste caso o programa não suporta a operação sobre array completo y = sqrt(x).x. dimension(*) :: y do m = 1. No entanto isto não funcionou. Aí então funciona. Procure sempre fazer a passagem de arrays pelo método da forma explicita ou da forma presumida com interface explicita. bastando colocar um asterisco no local onde apareceria o seu tamanho. Evite. 6. porque como o compilador não sabe nada sobre o rank nem as extensões do array em cada direção. a passagem de arrays para subrotinas pelo método do tamanho presumido.3 Passando variáveis caracter para subrotinas Quando uma variável caracter é passada para um subrotina não é necessário passar o tamanho da variável. para cobrir as duas extensões dos arrays rank 2.' é = '.*)'O tamanho da variável caracter '. fortemente. Se for necessário saber o tamanho da variável caracter pode-se usar a função intrínseca LEN(variável_caracter). intent(in). Uma terceira forma de fazer a passagem de array é utilizando arrays de forma presumida juntamente com uma interface explicita para a subrotina. Então ao invés de colocar dois DOs.com 56 .br e jbaparecido@gmail. e é intuitivo que no lugar desta expressão devêssemos colocar dois laços de DO uma vez que no programa principal estes arrays são rank 2. tive que colocar apenas um DO com laço igual ao tamanho (quantidade de elementos) do array. intent(out). Versao atual impressa (*.feis. Veremos mais adiante neste capítulo como fazer isto.len(x) return end subroutine caracter Versão primeira de janeiro 1999. no código da subrotina. Ver exemplo abaixo program passando_caracter implicit none character(len = 5) :: word = 'manga' call caracter(word) stop end program passando_caracter subroutine caracter(x) implicit none character(len = *)x write(*. no formato em que os dados são armazenados na memória.unesp.1.

save :: lista_de variáveis integer.4 Compartilhando dados usando módulos (modules) Pelo visto até o momento o programa principal e as subrotinas são programas distintos que trocam informações entre si. normalmente volátil entre duas chamadas.q. 6. dimension (5. use arrays automáticos para criar locais temporários de trabalho em subrotinas. De qualquer forma evite fiar-se em valores voláteis armazenados na memória entre um chamada e outra da subrotina. passando apenas as extensões do array via argumentos da subrotina. Surge então a seguinte pergunta: Quando a subrotina for acessada por um segunda vez qual será o valor inicial assumido por uma determinada variável local da subrotina? Pela afirmação na primeira linha deste parágrafo pode-se dizer que o valor será indeterminado.Fortran 90/95 6. O Fortran provê um mecanismos para tornar perene o valor de uma variável local de uma subrotina.com 57 . exceto aqueles que receberam o atributo SAVE. Assim programas Fortran. Pode-se fazer o mesmo em subrotinas. Em Fortran 95 os arrays alocáveis criados dentro de subrotinas são automaticamente destruídos assim que a execução da rotina termina.br e jbaparecido@gmail.q) implicit none real. uma vez que o programa (ou sistema operacional) poderá ter destinando um novo endereço na memória para aquela variável local. Use arrays alocáveis para criar locais de trabalho temporários de trabalho no programa principal ou que vai ser criado em uma subrotina e destruído em outra. embora algumas vezes estes valores parecem permanentes. dimension array1(p. ou seja ela torna-se indefinida depois que a execução da subrotina termina. Considerando que toda variável local de subrotina é volátil. y 6. Módulo é Versão primeira de janeiro 1999. pode-se criar arrays locais.feis.unesp. subrotinas e funções podem compartilhar informações usando módulos (modules).3 Arrays automáticos Aprendeu-se no capítulo anterior a alocar arrays alocáveis em programas principais bem como a desalocá-los. É o atributo SAVE que tornará permanente o valor da variável local entre chamadas consecutivas de uma subrotina. via uma lista de argumentos. como veremos mais adiante) que é mais flexível e segura. Pode acontecer também que a posição de memória ocupada pela variável local pela primeira vez tenha sido usada posteriormente para outra finalidade e o seu valor tenha mudado.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. Sua declaração é como segue real. Versao atual impressa (*. O Fortran 90/95 possui uma nova forma de passar dados (e outras informações também. 6) :: x.) outras_declaracoes_executaveis return end subroutine array_automatico Assim. Veja a seguinte uma subrotina criando um array rank 2 local chamado array1 com extensões p e q subroutine array_automatico(p.2 A declaração e o atributo SAVE Os valores de todas as variáveis locais de uma subrotina tornam-se indefinidos toda vez que a subrotina termina de executar. no entanto existe uma forma mais fácil e prática de conseguir o mesmo efeito. save.

m real. ! !programmer: joao batista aparecido ilha solteira. dimension(m) :: t.feis. module constantes implicit none save !definindo as constantes real :: pi = 3. parameter :: i_max = 10 real.14159.com 58 . Para uma unidade de programa acessar os dados no módulo. s) use constantes implicit none integer :: i. Esta declaração deve ir logo após a declaração do nome do programa ou sub-programa. i_max x(i) = sqrt(real(i)/i_max) y(i) = cos(real(i)*pi*x(i)) end do call sub_seno(i_max.br e jbaparecido@gmail.unesp. dimension(i_max) :: x. s do i = 1.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. basta mencionar o nome do módulo logo após a declaração USE. z) stop end program modulo subroutine sub_seno(m. Versao atual impressa (*.Fortran 90/95 uma unidade de programa compilada separadamente que contém as definições e valores iniciais dos dados que deseja-se compartilhar entre o programa e os sub-programas. z integer :: i do i = 1. 11 de dezembro 1999 ! use constantes implicit none integer. e = 2. t.718281828 end module constantes program modulo !Objetivo: Mostrar o uso de modulos para compartilhar dados entre programas. y. A seguir temos um exemplo de um módulo para compartilhar constantes. m Versão primeira de janeiro 1999. x. Para que os dados contidos no módulo não fiquem voláteis é necessário utilizar a declaração SAVE na seção de declaração de variáveis. A forma geral de definir um módulo é module nome_do_modulo declarações end module nome_do_modulo A forma geral de invocar um módulo é usar a seguinte declaração use nome_do_modulo na primeira linha após o cabeçalho do programa ou sub-programa.

Esta declaração diz ao compilador que o restante de código são subprogramas inclusos. que são chamadas então subprogramas-módulo.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. b) call sub2(j.Fortran 90/95 s(i) = sin(real(i)*pi*t(i)) end do end subroutine sub_seno 6.unesp. intent(in) :: x real. a. como segue module banco implicit none save real :: pi = 3.com 59 . Os subprogramas inclusos em um módulo devem vir depois da declaração de dados compartilhados e devem ser precedidos pela declaração CONTAINS. intent(in) :: x real. intent(out) :: y integer.feis.14159. intent(in) :: m y = exp(real(m)*x)/e return end subroutine sub2 end module banco program banco_de_rotinas use banco implicit none real :: a = 2. c integer :: j = 5 call sub1(a.718281828 contains subroutine sub1(x. x. Versao atual impressa (*. intent(out) :: y y=sin(pi*x) return end subroutine sub1 subroutine sub2(m. Assim um módulo pode conter uma coleção de subrotinas. c) Versão primeira de janeiro 1999. y) implicit none real.5 Sub-programas módulo Além de dados os módulos podem conter subrotinas e funções. y) implicit none real.br e jbaparecido@gmail. b. Estes subprogramas-módulo são compilados como componentes do módulo e são disponibilizados para as unidades de programa através do uso da declaração USE.0. e = 2.

Um sub-programa compilado dentro de um módulo e acessado através de uma declaração USE têm uma interface explicita. o compilador apenas assume que tudo vai transcorrer bem.1 Usando módulos para criar interfaces explicitas Sabe-se que é possível criar e compilar subrotinas separadamente e depois colocá-las juntas usando o linker.unesp. Versao atual impressa (*. ou seja que a quantidade e os tipos dos argumentos estão corretos. Quando compilando um programa deste tipo. Um exemplo disto é o programa mostrado acima chamado corrupcao_de_dados_2 onde os argumentos da subrotina estão declarados de forma errada.com 60 . b. Enquanto deveriam ser reais. Se algo estiver errado o programa falhará totalmente. Então o compilador do Fortran automaticamente sabe explicitamente todos os detalhes sobre cada argumento no subprograma sempre que este é usado e verifica a interface para confirmar que está sendo usada adequadamente. c) implicit none !introduzindo a corrupção nos dados. se o argumento é um array ou não. 11 dezembro 1999 ! Versão primeira de janeiro 1999. de tal forma que mais informações sobre as subrotinas estarão disponíveis ao compilador. e que o tamanho dos arrays estão corretos. Quando o programa (usando módulo) é compilado. o compilador verifica o número de argumentos. module auxiliar contains subroutine soma(a. que poderá então fazer um melhor controle do programa. compilar e depois lincar de novo? A razão é que o módulo provê uma maneira superior de compartilhamento de dados. Então porque ter o trabalho extra de colocar estas subrotinas em um módulo.br e jbaparecido@gmail. os tipos dos argumentos. Mais adiante mostraremos a solução para evitar este tipo de corrupção de dados utilizando o conceito de módulo. que estão na ordem correta. e assim por diante. Via uma declaração !incorreta de tipo na subrotina integer :: a. os atributos INTENT de cada argumento.Fortran 90/95 stop end program banco_de_rotinas 6. Mostra-se abaixo o programa corrupcao_de_dados_3 que é o corrupcao_de_dados_2 com a subrotina escrita dentro de um módulo.feis.c !soma dois reais c=a+b return end subroutine soma end module auxiliar program corrupcao_de_dados_3 !O objetivo deste programa eh mostrar a corrupção de dados quando !se utiliza subrotinas ! !Programmer: joao batista aparecido ilha solteira.5. Estes subprogramas têm um interface implícita.b.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. Quando os subprogramas não estão dentro de um módulo o compilador têm pouca informação sobre os subprogramas. estão declarados como inteiros.

Fortran 90/95
use auxiliar
implicit none
real :: x = 1.5, y = 2.5, z
!invocando a subrotina
call soma(x, y, z)
stop
end program corrupcao_de_dados_3

Após a compilação deste programa (usando o Compildor da Microsoft V4.0) percebe-se
que o resultado não é tão bom quanto esperado. O compilador, dependendo das diretivas
internas (três: no warning, normal warning, and warning treated as error) pode acontecer três
coisas: 1) na opção no warning, não emite nada, ignorando o erro; 2) na opção normal
warning, identifica claramente o erro mas emite mensagem apenas de warning; e 3) na opção
warning treated as error o compilador emitiu os mesmos warnings do item 2, mas identificou
que tinha um erro.
É digno de nota que o resultado (da compilação, com os warnings tratados com erros)
apresentado quando compilando os programas corrupcao_de_dados_3 e corrupcao_de_dados_2
foram praticamente idênticos, ou seja este compilador está implicitamente instruído a fazer a
verificação dos argumentos de um subrotina mesmo quando não possui uma interface
explicita. A literatura mostra que nem todos compiladores fazem isto.
Quando ainda estiver na fase de desenvolvimento de um programa, sempre use as
opções de emissão de warnings da forma mais restritiva possível, para evitar deixar escapar
erros importantes disfarçados de simples warnings.
6.5.2 Passando arrays para subrotinas usando módulos e arrays de forma assumida.
Como dito anteriormente, quando uma subrotina tem uma interface explicita, toda a
informação necessária sobre os argumentos estarão disponíveis para o compilador. Assim
podemos então desenvolver a terceira forma de passar arrays para uma subrotina, mencionada
anteriormente neste capítulo. Vimos anteriormente duas formas de passagem: A explicita
onde as informações sobre os arrays são passadas via argumento da subrotina e então usados
por ela. Outra forma era a do tamanho assumido do array, onde a subrotina apenas assume
que o array é rank 1 e que tem um determinado tamanho.
Veremos agora a terceira forma onde as informações sobre o rank e as extensões do
array são passadas via uma interface explicita usando módulo. Abaixo apresenta-se uma nova
versão do program passando_array_1, a passando_array_3,
module passando_array
contains
subroutine passa_array(x,y)
implicit none
real, intent(in), dimension(:,:) :: x
real, intent(out), dimension(:,:) :: y
integer :: i1, i2, j1, j2, m1, m2, n1, n2
!Se necessario as dimensoes dos arrays podem ser recuperadas
!diretamente, como abaixo
i1 = lbound(x,1)
i2 = ubound(x,1)
j1 = lbound(x,2)

Versão primeira de janeiro 1999. Versao atual impressa (*.pdf) em 22 de agosto de 2013
Autor: João Batista Aparecido – jbaparecido@dem.feis.unesp.br e jbaparecido@gmail.com

61

Fortran 90/95
j2 = ubound(x,2)
m1 = lbound(y,1)
m2 = ubound(y,1)
n1 = lbound(y,2)
n2 = ubound(y,2)
y = sqrt(x)
return
end subroutine passa_array
end module passando_array
program passando_array_3
!Objetivo: Mostrar a passagem de um array do program principal
!para um subrotina usando array de forma assumida e módulo
!
!programmer: joao batista aparecido
ilha solteira, 12 dezembro 1999
!
use passando_array
implicit none
integer, parameter :: i_max = 10, j_max = 12
real, dimension(i_max,j_max) :: array1, array2
!atribuição de valores aos arrays
array1 = 5.0
!invocando a subrotina passa_array
call passa_array(array1, array2)
stop
end program passando_array_3

É interessante notar que neste método de passagem de arrays não é necessário passar
explicitamente a extensão do array em cada direção, estes valores podem ser obtidos na
própria subrotina usando as declarações LBOUND e UBOUND. Os arrays passados assim
suportam operações sobre array completo.
6.6 Funções Fortran 90/95
Uma função é um subprograma Fortran que produz apenas um resultado de saída,
embora podendo ser um array. O nome da função pode ser usado no lado direito de uma
função aritmética como uma variável qualquer. O Fortran têm suas próprias funções
intrínsecas (já falado anteriormente) e suporta também funções definidas pelo programador. O
uso das funções definidas pelo usuário é similar aquele das funções intrínsecas. A forma geral
de uma função é
function nome_da_função (lista_de_argumentos)
declaracções_não_executáveis
declarações_executáveis
nome_da_função = expresão
return
end function nome_da_função

Versão primeira de janeiro 1999. Versao atual impressa (*.pdf) em 22 de agosto de 2013
Autor: João Batista Aparecido – jbaparecido@dem.feis.unesp.br e jbaparecido@gmail.com

62

Fortran 90/95
A função deve começar com a declaração FUNCTION e terminar com a declaração END
FUNCTION. O nome da função pode conter até 31 caracteres sendo que o primeiro deve ser
alfabético.
Uma função é invocada quando seu nome é mencionado em uma expressão aritmética.
Quando isto ocorre o programa para a execução e passa o controle da execução para a
primeira linha da função que efetua sua execução, quando esta termina, o controle é retornado
ao programa que invocou a função. Quando a função retorna, o seu valor é usado para
continuar o processamento onde ocorria seu nome na expressão aritmética. Uma função pode
ser vazia de argumentos, neste caso deve-se colocar os dois parênteses sem nada entre. Como
o nome da função retorna um valor, então este nome deve ser declarado na seção de
declaração de variáveis, tanto no programa que invoca quanto na própria função.
A passagem de argumentos nas funções ocorre da mesma forma que nas subrotinas.
program funcao
!Objetivo: Mostrar a técnica de uso de uma function, calculando
!o valor assumido por uma parabola, sendo conhecido os coeficientes
!a, b, c e a coordenada x.
!
!programmer: joao batista aparecido ilha solteira, 12 de dezembro 1999
!
implicit none
real :: a = 2.0, b = 3.5 , c = -5.0 , x = 1.0 , y, parabola
y = parabola(a, b, c, x)
stop
end program funcao
function parabola(r, s, t, w)
implicit none
real :: r, s, t, w, parabola
parabola = (r*w+s)*w+t
return
end function parabola

6.7 Funções puras (pure functions) e funções elementares (elemental functions)
Duas novas classes de funções disponíveis em Fortran 90/95, destinadas principalmente
(porém não somente) ao processamento paralelo do tipo SIMD (single instruction multiple
data) são as funções puras (pure functions) e as funções elementares (elemental function).
6.7.1 Funções puras (pure functions)
Funções puras são aquelas que não têm efeitos colaterais, isto é os seus argumentos
não podem ser modificados, nem outros dados podem ser modificados tais como aqueles
contidos em módulos. Adicionalmente, variáveis locais não podem ter o atributo SAVE, e
também não podem ser inicializadas em declarações de tipo (uma vez que isto implicitamente
implicaria em SAVE). Qualquer função invocada por uma função pura também deverá ser
pura. Todos os argumentos de uma função pura devem ter a declaração de atributo
INTENT(IN), além do mais não devem fazer nenhuma operação de entrada e saída de dados.

Versão primeira de janeiro 1999. Versao atual impressa (*.pdf) em 22 de agosto de 2013
Autor: João Batista Aparecido – jbaparecido@dem.feis.unesp.br e jbaparecido@gmail.com

63

Para declarar um função pura basta acrescentar o prefixo PURE antes da palavra FUNCTION como segue pure function nome_da_funcao (lista_de_argumentos) 6. 6. onde podem ser executadas em (paralelo) qualquer ordem. quando o subprograma é executado.8 Passando subprogramas como argumentos para outros subprogramas Quando um subprograma é invocado.Fortran 90/95 Uma vez que funções puras não tem efeitos colaterais. Esta passagem por referência pode ser estendida para permitir passar também ponteiros que apontem para outros subprogramas. Isto proíbe o uso de arrays automáticos. Funções elementares definidas pelo programador devem ser também funções puras e atender também as seguintes restrições: 1) Todos os argumentos devem ser escalares e não devem ter o atributo POINTER (voltaremos ao pointer em outro capítulo). elas são ideais para se utilizar junto com a declaração FORALL.feis.br e jbaparecido@gmail. a lista de argumentos é passada como um conjunto de ponteiros que apontam para as posições de memória ocupadas por aqueles argumentos. O resultado que sai de uma função elementar tem a mesma forma do argumento de entrada. se o argumento é um escalar o resultado será um escalar.unesp. 2) A função deve ser escalar e não deve ter o atributo POINTER.8. Funções intrínsecas elementares são disponíveis em Fortran 90 e Fortran 95.1 Passando funções como argumento Se o nome de uma função é mencionado na lista de argumentos de um subprograma.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. Como cada posição de memória é interpretada pelo subprograma depende do tipo e tamanho declarado no subprograma. Em Fortran funções e subrotinas podem ser passadas como argumento para outras funções ou subrotinas. Funções elementares são especificadas para escalares mas que podem também ser usadas com argumentos do tipo array.7.2 Funções elementares (elemental functions) Funções elementares são aquelas que operando com escalares como argumento também operam com arrays ou seções de arrays como argumento. Versão primeira de janeiro 1999. Se o argumento correspondente à função for mencionado internamente no subprograma. mas funções elementares definidas pelo programador são suportadas apenas no Fortran 95. 3) Argumentos da função não podem ser usados em declarações de tipo. Funções puras propriamente ditas só são definidas no Fortran 95. Isto é. se o argumento é um array o resultado será um array com a mesma forma do array de entrada. então um ponteiro é passado para o subprograma. então a função receberá o comando da execução.com 64 . embora seja possível criar algo parecido em Fortran 90 declarando todos os argumentos da função com o atributo INTENT(IN). Versao atual impressa (*. Para declarar um função elementar basta acrescentar o prefixo ELEMENTAL antes da palavra FUNCTION como segue elemental function nome_da_funcao (lista_de_argumentos) 6.

i_max x(i) = real(i)/10. program funcao_como_argumento !Objectivo: Mostrar o uso de uma função Fortran como argumento de !um outro subprograma: função ou subrotina.br e jbaparecido@gmail. ! !programmer: joao batista aparecido ilha solteira.Fortran 90/95 Todo função usada como argumento deverá ter o atributo EXTERNAL. j real. dimension(i_max) :: x. s) !Subrotina que extrai os valores da função nas posições definidas !no programa principal !declaração de variáveis. Note que aqui chamei localmente a funcao de g implicit none real :: g integer :: m. external :: f real. definida pelo usuário call extrai_valor(f.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. m. t. dimension(m) :: t. i_max.feis. do j = 1. f f = sin(x)+x ! A funcao sendo avaliada para o argumento x. Abaixo apresenta-se um exemplo de uma subrotina que extrai valores de uma função em certas posições definidas pela subrotina. Versao atual impressa (*. Versão primeira de janeiro 1999. y) !terminação do programa stop end program funcao_como_argumento subroutine extrai_valor(g. m s(j) = g(t(j)) ! Aqui a funcao sendo invocada end do !Finalizando a execução da subrotina return end subroutine extrai_valor function f(x) !Função que recebe um escalar e retorno o valor da função para aquele argumento !Declaracao de variáveis implicit none real :: x. x. y !Laço de atribuição de valores a x do i = 1. parameter :: i_max = 100 real. s !Laço onde a funcao é invocada para os vários valores do argumento. 12 dezembro 1999 ! !Declarando as variáveis do programa principal.0 end do !Rotina para extrair os valores de uma função f.unesp.com 65 . !Note que a função f aparece aqui com os atributos real e external implicit none integer :: i integer.

br e jbaparecido@gmail. return end function f Versão primeira de janeiro 1999.unesp.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.feis.com 66 .Fortran 90/95 !Completando a execução da função. Versao atual impressa (*.

Na Tabela 7. aproximadamente. A seguir tem-se algumas exemplos de como efetuar esta declaração de tamanho de variáveis ou constantes reais real(kind = 4) :: r. um para representar a mantissa e o outro para representar o expoente. Conforme explicado em capítulo anterior estes 32 bits são divididos em dois grupos.1 Tamanhos de dados para variáveis e constantes do tipo real Como o Fortran provê para tipos de dados reais mais de um tamanho (kind) é necessária a existência de uma maneira de declará-los.Fortran 90/95 CAPÍTULO 7 OUTROS TIPOS DE DADOS Neste capítulo vamos apresentar números reais e inteiros com comprimentos (kind) diferentes daqueles apresentados até o momento. A primeira terminologia enfatiza que este tipo de dado é definido pelo usuário.br e jbaparecido@gmail. Este conceito. mas ainda dependente do processador. 7. contrariamente aos tipos básicos de dados. Assim kind = 4 pode na maioria dos computadores significar uma palavra com 32 bits. nestes casos a implementação mais comum é usar 53 bits para a mantissa e 11 bits para o expoente.unesp. Para tal existe o parâmetro de tamanho (kind type parameter) para declarar os diferentes tamanhos. 16 casas decimais. aproximadamente. para construir algo que transcende. Na maioria dos computadores hoje operando o tamanho default da variável real. ou abstrai. e os 11 bits do expoente são suficientes para representar números em uma faixa de 10-308 a 10+308. mas em outros pode significar uma palavra com 64 bits. também chamado de precisão simples (single precision) é usualmente 4 bytes.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. ou seja 32 bits. também é conhecido por ADT (Abstract Data Type).s ou real(4) :: r. 7 casas decimais e os números estarão em uma faixa de 10-38 a 10+38. A segunda terminologia enfatiza que este tipo de dados parte de algo básico.feis. 7. os tipos básicos de dados. de escrever o trecho de código acima é Versão primeira de janeiro 1999.com 67 . Versao atual impressa (*. e o tipo de dados definido pelo usuário (UDT – User Data Type). Uma maneira mais elegante. Os 53 bits da mantissa são suficientes para representar. Apresenta-se também o tipo de dados COMPLEX.1 apresenta-se os tamanhos e os tipos de números reais de alguns compiladores Fortran 90. então será necessário utilizar variáveis reais com tamanhos maiores que 32 bits. previamente definidos no compilador. Caso seja necessário ou desejável representar números reais com mais de 7 casas decimais e com uma faixa maior que de 10-38 a 10+38.1. O Fortran possui um tipo de dados com tamanho maior para representação de dados com maior precisão e maior faixa. Uma variável real com dupla precisão tem usualmente 8 bytes ou 64 bits. A implementação padrão de tipos de dados reais com precisão simples em geral terá uma precisão de. O tipo de dados reais com maior tamanho são denominados de dupla precisão (double precision).1 Outros tamanhos de dados para variáveis do tipo real Como já visto anteriormente o tipo real de dados é usado para representar números com ponto flutuante. ou não abstrato. UDT.s real(kind = 8) :: w ou real(8) Cada fabricante de compilador é livre para definir o tamanho da palavra para cada representação de dados reais. Assim o fragmento de código escrito acima torna-se dependente de cada processador.

o restante dos bits não utilizados.33333333333333333_double Versão primeira de janeiro 1999.br e jbaparecido@gmail. em realidade estará operando com precisão simples. a primeira atribuição interpreta 37. parameter :: single = 4.5_double Na maioria dos compiladores para microcomputadores. O que teria ocorrido para o valor original 0. e a variável x.3333333.Fortran 90/95 integer. então assume que o tamanho daquela variável é de 4 bytes e portanto o que é realmente armazenado.8* 16 DEC/DEC Fortran 90 4* 8 NA PC/Lahey Fortran 90 4* 8 NA PC/Microsoft Powerstation 4 4* 8 NA PC/NAGWare FTN90 1* 2 NA * Parâmetro default É possível declarar o tamanho de um dado real colocando um apêndice na atribuição do dado. No passo seguinte o compilador executa a atribuição na qual um número em precisão simples é atribuído a uma variável real.s ou real(single) :: r.unesp.5 y = 37. A maneira correta de evitar este erro é integer(4).5 é representado em precisão dupla que em geral corresponde a 64 bits. Versao atual impressa (*.3333333.3333333? A explicação está na maneira em que o compilador interpreta o código fonte. como segue x = 37.5_4 z = 37.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.33333333333333333 neste caso o valor armazenado em x será 0. na segunda 37. parameter :: double = 8 real(double) :: x = 0.33333333333333333 fosse corrompido e se tornasse 0. na quarta 37. de maneira útil.feis. Um erro muito sutil que pode ocorrer e é muito difícil de detectar é o seguinte: suponha que alguém desejando uma representação em precisão dupla escrevesse o seguinte integer(4).5E0 w = 37. De qualquer forma o erro já foi cometido. x. do número é 0. O que ocorreu foi o seguinte: o compilador ao interpretar o código encontra o número 0.com 68 . a quinta corresponde exatamente à quarta. de dupla precisão.5 é representado por um tamanho que corresponde ao parâmetro de tamanho igual a 4.s real(kind = double) :: w ou real(double) Tabela 7.33333333333333333. double = 8 real(kind = single) :: r.3333333.5D0 t = 37. a terceira corresponde exatamente à primeira. nestes casos em geral mas nem sempre (ver tabela acima) corresponde também a 32 bits. assumirão valores nulos. ainda no procedimento intermediário. que por fim assumirá o valor x = 0. definida de precisão dupla. como não encontra nenhum indicador extra. nas atribuições acima. parameter :: double = 8 real(double) :: x = 0.1-Parâmetros de tamanho (kind) e tamanho em bits de variáveis reais em compiladores Fortran 90 Computador/Compilador real de 32 bits real de 64 bits real de 128 bits Cray T90 Supercomputer/CF90 NH 4. ou algo muito próximo.5 como sendo um dado do tipo precisão simples (32 bits).

Desta forma dependendo do processador que se usa a interpretação do que é simples e dupla precisão poderá variar. quando executada retorna o parâmetro de tamanho necessário a uma variável real. kind(37. para aquele processador específico. No entanto outros computadores utilizam 64 bits para dupla precisão e 32 bits para precisão simples.r = 350) stop end program usando_selected_kind Versão primeira de janeiro 1999.r = 35) valor_kind = selected_real_kind(p = 7) valor_kind = selected_real_kind(r = 30) valor_kind = selected_real_kind(p = 20.2 Determinando o tamanho (kind) de uma variável O Fortran 90/95 provê uma função intrínseca KIND para determinar o parâmetro de tamanho de um variável. & kind(37.unesp. Versao atual impressa (*.1.r = 10) valor_kind = selected_real_kind(p = 5. kind(37.5d0).feis.Fortran 90/95 7. O Fortran 90/95 apresenta uma função intrínseca que auxilia nesta tarefa. e se retorna –3 é porque nenhum parâmetro de tamanho satisfaz a precisão e a faixa especificadas. Se esta função retornar (–1) significa que nenhum parâmetro de tamanho satisfaz a precisão especificada.br e jbaparecido@gmail.5). O programa abaixo mostra como usar a função KIND program usando_kind implicit none integer.f) onde p é a precisão em casas decimais desejada e f é a faixa do expoente requerido em potência de dez.5_double) stop end program usando_kind 7. kind(37.com 69 . A seguir tem-se alguns exemplos de uso desta função intrínseca program usando_selected_kind implicit none integer :: valor_kind valor_kind = selected_real_kind(p = 2. A função chamada SELECTED_REAL_KIND. parameter :: double = 8 write(*.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.5e0). A função retorna o menor parâmetro de tamanho que satisfaz as condições especificadas. É interessante utilizarmos alguma maneira de definir a precisão de um variável de uma forma o mais independente possível do processador.*)kind(37.1. que corresponde a uma precisão e faixa especificadas. se retornar (–2) significa que nenhum parâmetro de tamanho satisfaz a faixa especificada.5_4). independentemente do processador As expressões precisão simples e precisão dupla não possuem unicidade em Fortran. implicando muitas vezes em resultados totalmente inesperados. A forma geral desta função é parametro_de_tamanho = selected_real_kind(p. uma vez que em um processador a precisão simples pode estar usando 64 bits e a precisão dupla 128 bits.2 Definindo a precisão de uma variável.

suportam também valores reais com precisão dupla. o segundo valor de valor_kind será também 4. mostradas na Tabela 7. e por fim o último valor será –3 indicando que nenhum parâmetro de tamanho atende aquela especificação. pois necessita-se especificar apenas a faixa que o número deve satisfazer.2.r) Retorna o menor valor do parâmetro de tamanho com um mínimo de p casas decimais e uma faixa  10r selected_int_kind(r) Retorna o menor valor do parâmetro de tamanho com um range  10r kind(x) Retorna o parâmetro de tamanho da variável x.3 O tipo de dados COMPLEX Versão primeira de janeiro 1999.3 têm-se os parâmetros de tamanho para dados do tipo inteiro para alguns processadores.8 casas decimais.2 Tabela 7. Existem ainda outras funções intrínsecas relacionadas ao parâmetro de tamanho (kind). Se o argumento for precisão simples o retorno será precisão simples. onde x é uma constante ou variável de qualquer tipo. real ou complexo 7.2 Outros tamanhos (kinds) de dados para variáveis inteiras No caso de dados do tipo inteiro a idéia geral é totalmente semelhante àquela dos dados do tipo real. ou seja abaixo de 7.1. onde é inteiro. porque em um PC (onde estou testando os programas) os dados reais em precisão simples usa 4 bytes ou 32 bits e portanto atende ao requisitado.4 6* 8 DEC/DEC Fortran90 1 2 4* NA 8 PC/Lahey Fortran 90 1 2 4* NA NA PC/Microsoft Powerstation 4.0 1 2 4* NA NA PC/NAGWare FTN90 1 2 4* NA NA *Valores default 7.br e jbaparecido@gmail.3. range(x) Retorna o expoente decimal de x. precision(x) Retorna a precisão decimal de x.3-Parâmetros de tamanho (kind) e tamanho de variáveis inteiras em compiladores Fortran 90 Computador/Compilador inteiro inteiro inteiro inteiro inteiro 8 bits 16 bit 32 bits 48 bits 64 bits Cray T90 Supercomputer/CF90 NA NA 1.com 70 . 7. Versao atual impressa (*. Na Tabela 7. Precisão dupla em funções intrínsecas Todas as funções genéricas do Fortran 90/95 que operam com precisão simples.feis.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. se o argumento for precisão dupla a resposta será também precisão dupla. Tabela 7.Fortran 90/95 No programa acima o primeiro valor_kind será 4.2-Funções intrínsecas comuns relacionadas ao parâmetro de tamanho (kind) Função intrínseca Descrição selected_real_kind(p. onde x é real ou complexo. No caso dos inteiros é mais simples. o terceiro será 8 porque uma variável de 4 bytes provê uma precisão de apenas 6. no quarto caso será 4 porque a faixa de uma variável com 4 bytes será de até 38.unesp.

Um dado derivado é definido como uma seqüência de declarações precedidas da declaração TYPE e completado com a declaração END TYPE.0) ! Declarando e inicializando uma constante complexa complex. O Fortran permite ao usuário definir os seus próprios tipos de dados (UDT ou ADT). 2. reais. caracteres. 5.feis. lógicos e complexos.3. <.b) o real da esquerda é a componente real do dado do tipo complexo e b é a parte imaginária. 7. Uma das vantagens dos dados derivados é o encapsulamento.unesp. Versao atual impressa (*.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.com 71 . dimension(55) :: y ! Declarando um array com 55 elementos complexos complex :: z = (-1. Os outros operadores relacionais >. Um número complexo em realidade é uma dupla de dados reais que satisfazem um álgebra especial. 7. de uma maneira semelhante à definição de um array como um conjunto de elementos. parameter :: x = (1. Porém a sintaxe é diferente. Praticamente tudo que se disse até o momento sobre tipos reais aplica-se também aos dados do tipo complexo. Assim tem-se algumas funções implícitas que aplicam-se para complexos. Para declarar variáveis e constantes do tipo complexo procede-se da seguinte maneira complex.br e jbaparecido@gmail. >= e <= não podem ser usados com complexos.4 Tipos de dados derivados Os tipos de dados básicos do Fortran são: inteiros. Um dado do tipo derivado é uma maneira conveniente de agrupar um conjunto de informações.Fortran 90/95 O tipo COMPLEX é uma das formas básicas de representação de dados em compiladores Fortran 90.2 Utilizando operadores relacionais com complexos É possível comparar dois dados complexos usando o operador relacional == e pode-se também verificar se são diferentes usando o operador /=.3. são os chamados tipos derivados de dados. A forma geral de declaração de um UDT é type :: nome_do_tipo componentes_da_declaração end type nome_do_tipo Abaixo apresenta-se um caso concreto de um dado derivado destinado a descrever quantidade de frutos type :: frutos_no_cesto integer :: numero_bananas integer :: numero_laranjas Versão primeira de janeiro 1999.1 Aritmética mista entre dados complexos e não complexos Quando um complexo vai sofrer uma operação com um número não complexo o programa converte o valor do dado não complexo para complexo e executa a operação. Eles são derivados porque devem ser construídos utilizando aqueles tipos básicos mencionados acima e eventualmente outros tipos de dados derivados já definidos. e cada elemento é referenciado por um nome ao invés de por um número. 7. isto é os componentes internos dos dados derivados devem ser acessado explicitamente.0.5.5) ! Declarando e inicializando uma variável complexa onde na dupla (a.

comprimento e largura. 9 ao numero_laranjas. Versao atual impressa (*. Assim. Uma estrutura pode ser usada como elemento em outra estrutura. faz-se quantidade_goiabas = cesto1. logo acima.numero_goiabas + cesto2.com 72 . 6) Na primeira linha de código. O mais comum em todas linguagens é usar o ponto. cesto_pequeno Um dado derivado também é chamado de estrutura. 0 ao numero_cajus. usando % ou usando . e 5 ao numero_goiabas. um UDT para descrever caixas deste tipo seria type :: caixa real :: largura real :: profundidade real :: comprimento end type caixa Uma vez que uma determinado UDT esteja definido é possível utilizá-lo e produzir as seguintes declarações type (frutos_no_cesto) :: cesto1.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.numero_bananas = 13 estas duas formas acima. dimension(20) :: cesto_grande. cesto_na_prateleira type (frutos_no_cesto).Fortran 90/95 integer :: numero_cajus integer :: numero_mangas integer :: numero_goiabas end type frutos_no_cesto Outro exemplo simples é aqueles destinado a descrever as dimensões de um caixa Cartesiana. que possui altura. Para somar o número de goiabas no cesto1 e no cesto2.br e jbaparecido@gmail. 3. 5) cesto2 = frutos_no_sexto (0. o construtor da estrutura cesto1 irá atribuir 12 ao numero_bananas. 0.numero_goiabas Versão primeira de janeiro 1999. como segue cesto1 = frutos_no_sexto(12.1 Acessando elementos de uma estrutura Os componentes numéricos básicos de uma estrutura podem ser usados de acordo com as operações que cada tipo suporta. Uma estrutura pode ser inicializada utilizando um construtor de estruturas. para acessá-los será necessário usar o seletor de componentes (component selector) No exemplo dos cestos de frutos mostrados acima pode-se atribuir valor a um componente da estrutura da seguinte maneira cesto1%numero_bananas = 13 ou cesto1. 9.4. de um forma semelhante ao construtor de arrays. 2 ao numero_mangas.feis. 24. 7. 0. cesto2. são equivalentes.unesp. Como estes elementos estão encapsulados dentro da estrutura. O mesmo vale para os componentes do tipo caracter. 2.

5 caixa1. volume2 caixa1.comprimento = 5.6 Armazenamento de UDT na memória e a declaração SEQUENCE Devido à sua característica de realizar processamento paralelo SIMD o compilador Fortran90 não armazena. Entretanto.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.0.profundidade = 2. sob certas circunstâncias pode ser necessário garantir que os membros da UDT estejam em seqüência na memória.comprimento stop end program UDT_caixa 7.comprimento volume2 = caixa2. definido anteriormente program UDT_caixa implicit none type :: caixa real :: largura real :: profundidade real :: comprimento end type caixa type (caixa) :: caixa1.0 caixa1.profundidade*caixa2.5.largura = 1. necessariamente. evitando ter que defini-los em todas as unidades de programa. 8.unesp.Fortran 90/95 Os tipos de dados derivados podem ser definidos dentro de módulos.5 Imprimindo UDTs Na impressão de uma UDT os membros serão impressos na seqüência em que foram declarados. A formatação de cada componente segue as mesmas regras de formatação das variáveis básicas.br e jbaparecido@gmail. assim utiliza-se a declaração SEQUENCE que informa ao compilador para proceder em conformidade.) volume1 = caixa1. utilizando o seletor de componentes. Abaixo apresenta-se o uso do UDT caixa. Também é possível imprimir cada componente. Versao atual impressa (*.7 caixa2 = caixa(3.largura*caixa1. 2. caixa2 real :: volume1. separadamente.largura*caixa2. os membros de uma UDT em posições contíguas de memória. Segue abaixo um exemplo de UDT utilizando a declaração SEQUENCE type :: pessoa sequence caracter(64) :: nome integer(1) :: idade real(4) :: altura real(4) :: peso caracter(11) :: cpf caracter(11) :: rg end type pessoa Versão primeira de janeiro 1999.profundidade*caixa1.com 73 . 7.feis.

Objetos locais são definidos apenas dentro de algumas unidades do programa. e os dos módulos. Estas características permitem definir subrotinas e funções com argumentos opcionais. Um subprograma interno recebe todas as variáveis e constantes definidas no seu hospedeiro. também chamadas de unidades de escopo. subrotinas e módulos. porém o mesmo nome pode ser usado para outra variável em outra unidade de escopo. Um objeto também pode ter como escopo declaração do tipo DO implícito em construtores de arrays. e módulos. Adicionalmente apresenta-se maneiras de definir operações sobre tipos derivados de dados (UDTs). Alguns exemplos são: programas. Os subprogramas internos são compilados juntamente com a compilação do programa hospedeiro.br e jbaparecido@gmail. visando ter um controle mais seguro da transferência de dados entre estas unidades de programa. Objetos globais são aqueles cuja definição atinge todas as instâncias do programa (programa principal e subprogramas).pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. SUBROTINAS E MÓDULOS Neste capítulo apresenta-se alguns aspectos mais avançados de funções. caracter e UDT) são: global. funções. em outras palavras todas as variáveis e constantes do programa hospedeiro são globais para os seus subprogramas internos.2 Escopo de variáveis e constantes Os escopos possíveis de todos os tipos de objetos (inteiro. com argumentos que variam de tipo.1 Subprogramas internos Até o momento todos os subprogramas que definimos. os das subrotinas. real. complexo. quando todas as unidades de programa referenciarem um determinado módulo de compartilhamento de dados. ou de algum outro subprograma. 8. De outra forma. consequentemente os nomes destes objetos devem ser únicos em todas as unidades do programa. funções. e por conseguinte não consegue acessar o valor contido na variável do mesmo nome no programa hospedeiro. todos os subprogramas internos deverão estar entre a declaração CONTAINS e a finalização do programa. lógico. O nome de um subprograma interno não pode ser passado como argumento de linha de comando a outro subprograma. Vamos ver agora como construir os chamados subprogramas internos.feis. e antes das declarações STOP e END PROGRAM. local e declaração. Separando os subprogramas internos do restante do código deve-se usar apenas a palavra CONTAINS. subrotinas. então esta variável passa a ter um caráter local. Versao atual impressa (*. abaixo tem-se um exemplo de onde pode ocorrer este tipo de escopo de variáveis Versão primeira de janeiro 1999.Fortran 90/95 CAPÍTULO 8 ASPECTOS AVANÇADOS DE FUNÇÕES. que tenha o mesmo nome de uma variável do programa hospedeiro. eram do tipo externo. que são funções e subrotinas que ficam dentro do programa principal. 8. Quando define-se uma variável no subprograma interno. O nome de um objeto de ser único dentro de sua unidade de escopo.unesp. e podem ser invocadas apenas por ele. Os únicos objetos que gozam desta propriedade são o nome do programa principal. O Fortran 90/95 suporta os subprogramas internos. subrotinas e módulos. O local no programa em que fica um subprograma interno é logo após a última declaração executável do programa.com 74 . Utilizando-se módulos também pode-se produzir variáveis que tenham um escopo global. os nomes das funções.

Para evitar problemas de interpretação ao Versão primeira de janeiro 1999. este é o escopo de declaração.100/) Abaixo mostra-se um programa exemplo que apresenta todos os tipos de escopo: global. dimension(k) :: a do i = 1. este laço inicializa o vetor a seis vezes. parameter :: j = 5 end module global program escopo !Objetivo: Demonstrar os tipos de escopo: global. cuja variável de controle também é (i) que vai atribuir valores a cada posição do array. k)/) end do call sub(k. também o inteiro j definido no módulo têm escopo global. parameter :: k = 6 integer :: i real.a) use global implicit none integer :: k.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. nem erro de execução.a) stop end program escopo subroutine sub(k. 14 dezembro 1999 !programmer: joao batista aparecido ilha solteira. da subrotina e do módulo.Fortran 90/95 array1 = (/i**2. note que não ocorre erro de compilação. j a(i) = sin(a(i)) end do return end subroutine sub No programa acima além do nome do programa. 02 agosto 2001 ! !Declarando variáveis use global implicit none integer. i real. i = 1. nem erro de link. local e de declaração. No programa principal tem-se um laço de DO em que o índice (i) vai de 1 a k (= 6). k ! Note que existem dois i’s um no DO e outro no construtor de array a = (/(i*j. dimension(k) :: a do i = 1. Versao atual impressa (*.com 75 . local e declaração ! !programmer: joao batista aparecido ilha solteira.br e jbaparecido@gmail. e dentro daquele laço tem o laço de DO implícito. isto porque a variável (i) do laço interno tem escopo apenas dentro do laço implícito.unesp.feis. module global implicit none save integer. i = 1. deixando de existir assim que o laço completa-se.

A seguir apresenta-se um programa para tal. Um exemplo clássico de uso de subrotina recursiva é para calcular o fatorial de um inteiro n. então a subrotina passa o controle da execução ao programa principal e o valor armazenado na variável i ainda é i = 7. utilizando-se de uma subrotina recursiva. Abaixo apresenta-se um programa que faz o cômputo do fatorial de um inteiro n. program recursivo implicit none integer :: n = 5. colocado antes da palavra FUNCTION ou SUBROUTINE. utilizando-se de uma subrotina recursiva.feis. valor) stop end program recursivo recursive subroutine fatorial(i. não podendo alterar o valor da variável i que encontra-se também no programa principal. program recursivo2 implicit none integer :: n = 2 real :: x = 2.com 76 . 8. aux if (i >= 1) then call fatorial(i-1. Alguns tipos de problemas podem ser resolvidos mais facilmente se determinada função ou subrotina é recursiva. quer seja diretamente ou indiretamente.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. Significa dizer que os subprogramas comuns do Fortran não são recursivos. Isto ocorre porque a variável i da subrotina tem escopo apenas local.3 Subprogramas recursivos As funções e subrotinas comuns do Fortran 90/95 não podem invocar a si mesmas.unesp. Quando o laço de DO. aux) x = i*aux else x=1 end if return end subroutine fatorial Outro exemplo de uso de subrotina recursiva é para efetuar a exponenciação inteira (n) de um valor real (x). Versao atual impressa (*. x. O valor de i dentro da subrotina vai variar de 1 a 5 e quando a subrotina completar o valor de i será i = 6.br e jbaparecido@gmail. valor call fatorial(n. e lá dentro dela existe outro laço de DO no qual a variável de controle também é (i). do programa termina o valor da variável i será i = 7. O Fortran 90/95 suporta funções e subrotinas recursivas desde que tenham o atributo RECURSIVE.Fortran 90/95 se ler o código procure escrever o nome das variáveis de controle dos DOs implícitos diferentes das dos DOs explícitos que envolvem em seu laço DOs implícitos. x) implicit none integer :: i. exp Versão primeira de janeiro 1999. então a subrotina sub é invocada.

programa abortado!' stop end if stop end program recursivo2 recursive subroutine exponenciacao(i. agora utilizando uma função recursiva program recursivo3 implicit none integer :: n = 5. de tal forma que o resultado retorne na variável_de_retorno. valor. fatorial valor = fatorial(n) stop end program recursivo3 recursive function fatorial(i) result(retorno) implicit none integer :: i. x.Fortran 90/95 if(n >= 0) then call exponenciacao(n. x. Versao atual impressa (*.br e jbaparecido@gmail.feis. podendo ser utilizado de um forma semelhante à das subrotinas. Como já vimos anteriormente para invocar uma função é necessário que ela esteja em uma expressão aritmética. Por outro lado para receber o valor que retorna o nome da função teria que estar do lado esquerdo do (=). isto é do lado direito da declaração de atribuição (=). Este problema foi resolvido da seguinte forma: colocando-se uma especificação RESULT (variável_de_retorno) após a lista de variáveis da função.com 77 .0 end if return end subroutine exponenciacao No caso de definição de funções recursivas existe um complicação extra. y if (i > 0) then call exponenciacao(i .*)' Valor negativo de n. x. retorno if (i >= 1) then Versão primeira de janeiro 1999. ao invés de retornar no nome da função. exp) else write(*. y) implicit none integer :: i real :: x. Abaixo apresenta-se uma declaração de um função recursiva func que usa o argumento arg para retornar o valor recursive function func(lista_de_variaveis) result(arg) Abaixo tem-se uma nova versão do programa para calcular o fatorial de n.1.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.unesp. y) y = x*y else y = 1.

Esta técnica a ser descrita só funcionará se o subprograma tiver uma interface explicita. b = 2. Existem situações nas quais é possível modificar a ordem em que os argumentos aparecem na chamada e no subprograma.0. Versao atual impressa (*.feis. module sub contains subroutine sub1(r.0. u) implicit none real :: r. Se o subprograma possuir uma interface explicita então é possível usar argumentos nomeados. de compilação.Fortran 90/95 retorno = i*fatorial(i-1) else retorno = 1 end if return end function fatorial 8. s. Já foi dito várias vezes que a quantidade. O resultando em os ambos os casos será o mesmo. Vamos ilustrar estas idéias construindo um programa que chama uma subrotina duas vezes. mesmo com o argumentos embaralhados na lista. Um argumento nomeado é um argumento com a seguinte forma palavra_chave = argumento_verdadeiro onde palavra_chave é o nome do argumento que está sendo associado com o argumento verdadeiro. Como já foi dito anteriormente uma das maneiras de prover uma interface explicita é colocar o subprograma dentro de um módulo. t.4 Argumentos com palavras-chave e argumentos opcionais. e mesmo assim o programa operar corretamente. c = 3. t.br e jbaparecido@gmail. consiste em prover explicitamente blocos de interface.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. o tipo e o tamanho dos argumentos de uma função ou subrotina devem coincidir onde ela é invocada e com sua definição. d Versão primeira de janeiro 1999. no programa que está invocando o subprograma. que veremos mais adiantes. Na primeira chamada os argumentos estão colocados na lista de argumentos sem usar palavras-chave. Caso contrário haverá algum tipo de erro. e na segunda vez está com os argumentos embaralhados porém usando palavras-chave. u u=r+s+t return end subroutine sub1 end module sub program argumento_embaralhado use sub implicit none real :: a = 1. então os argumentos na chamada podem ser arranjados em qualquer ordem porque as palavras-chave auxiliam o compilador a saber qual argumento corresponde a qual. de tal forma que seja possível ao programa saber onde está cada argumento da lista de argumentos e fazer a associação correta. Se a invocação de um subprograma usa palavras-chave.com 78 .unesp.0. A outra forma. s. de lincagem ou de execução.

and.not.and.i_s).and.and.and. Obviamente argumentos opcionais só serão possíveis em subprogramas com interface explicita.i_s). intent(in) :: r.i_s).and.and.i_s.i_t)) u = r if((. s. i_t i_r = present(r) i_s = present(s) i_t = present(t) if(i_r.(.not.not.i_r).*) d call sub1(u = d.(.not.and. Uma rotina que tem argumentos do tipo OPTIONAL pode usar a função intrínseca PRESENT para verificar se um dado argumento está presente.Fortran 90/95 call sub1(a.(.not.i_t)) u = s if(i_r.i_r). Com este tipo de declaração será possível ter argumentos opcionais.not.i_s.i_s.i_t) u = t if((.*) d stop end program argumento_embaralhado Esta prática é um pouco mais segura porém é necessário um gasto maior de tempo escrevendo os argumentos da chamada do subprograma em uma forma mais complexa. Estes argumentos opcionais deverão ser declarados com o atributo OPTIONAL.(. s = b.and.i_t) u = r + t if((.and.and.and.not.and. Abaixo apresenta-se o programa anterior modificado para suportar a falta de alguns argumentos de entrada.and.i_t)) u = 0.d0 return end subroutine sub1 end module sub program argumento_opcional use sub Versão primeira de janeiro 1999.i_r).not.i_r). t = c) write(*.i_s. t. c. s. se estiver ausente PRESENT retornará FALSE.i_s). além do mais o compilador terá condições de saber qual é o argumento que não está presente.unesp. r = a. optional. Versao atual impressa (*.br e jbaparecido@gmail. b. u) implicit none real.not.(. Argumentos opcionais são aqueles que podem ou não aparecer na lista de argumentos e o subprograma não acusará erro de compilação e a execução continuará.com 79 .not.i_t)) u = r + s if(i_r.and. i_s.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.feis.(.not. intent(out) :: u logical :: i_r.(. module sub contains subroutine sub1(r. A principal conseqüência desta técnica no entanto é outra. PRESENT retornará TRUE. Se o argumento estiver presente.and. d) write(*.(.not. t real.i_t) u = r + s + t if(i_r.i_t) u = s + t if((.

A forma geral para criar um bloco de interface é interface subroutine nome_da_subrotina (lista_argumentos) declaracoes_de_atributos_dos_argumentos end subroutine nome_da_subroutine function nome_da_function (lista_argumentos) declaracoes_de_atributos_dos_argumentos end function nome_da_function end interface A forma acima apresenta apenas um função e uma subrotina. Desta forma é útil alguma ferramenta que permita a construção de interfaces explicitas sem necessariamente ter que alterar o código original. Estas informações contidas na interface são suficientes para que o compilador reconheça a quantidade. um programa exemplo Versão primeira de janeiro 1999.br e jbaparecido@gmail.5. s = b) stop end program argumento_opcional O programa acima é capaz de suportar e identificar os argumentos fora de ordem. 8. de tal forma que tenham automaticamente uma interface explicita. 8. Uma interface é criada duplicando as informações das declarações de atributo de todas as variáveis da lista de argumentos. c = 3. t = c. t = c) call sub1(u = d. e colocadas entre as declarações INTERFACE e END INTERFACE.0.feis. s = b. Criando blocos de interface Os blocos de interface são criados no programa que invoca os subprogramas. Versao atual impressa (*. mas podem ser empilhadas tantas quantas forem necessárias.1. c. t = c) call sub1(u = d. Evidentemente. d) call sub1(u = d. A maneira de se fazer isto é utilizando blocos de interface. ou uma biblioteca antiga e muito grande que ficaria muito caro re-escreve-la novamente.5 Interfaces para subprogramas e blocos de interfaces Conforme já foi dito anteriormente é desejável que o programador coloque as subrotinas e funções dentro de um módulo. s = b) call sub1(u = d) call sub1(u = d. ou ainda uma biblioteca escrita em outra linguagem. São várias as situações: imagine um conjunto de rotinas que não se têm o código fonte para fazer as modificações. r = a. b.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. se existe algum argumento faltando é necessário executar procedimentos compatíveis. Assim implementou-se algumas somas que levaram em consideração apenas os argumentos presentes. abaixo. Se existe algum argumento ausente. d call sub1(a. Segue. b = 2.0. r = a. colocados na seção de declaração de variáveis.com 80 .unesp.0. tipo e tamanho dos argumentos. e se existe algum. o compilador consegue identificar qual é. No entanto nem sempre é possível colocar-se estas informações dentro de um módulo.Fortran 90/95 implicit none real :: a = 1.

not.unesp.i_t) u = t if((. s = b) call sub1(u = d) call sub1(u = d. s = b.not.and.and.not. b = 2.(. c = 3.i_s. t real. Versão primeira de janeiro 1999.feis.0.0.(.and.not.i_s. r = a.not.and.not. produzida via um bloco de interface. s.i_r).i_t)) u = r if((.i_r). u) implicit none real.br e jbaparecido@gmail. s.and. intent(out) :: u end subroutine sub1 end interface real :: a = 1. t = c) call sub1(u = d. ordem e tamanho com aqueles do subprograma que se está interfaceando.(. s.0. tipo.and. i_s.and.not.i_s).i_s). d) call sub1(u = d. t = c) call sub1(u = d. Os parâmetros listados em um bloco de interface deve coincidir em quantidade.i_t) u = s + t if((.i_t) u = r + t if((. optional.not. u) implicit none real. t = c.(.com 81 .and.and. b.not.i_s. t real.(. intent(in) :: r.i_t) u = r + s + t if(i_r. mas não é necessário que o nome seja o mesmo.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.not. s. d call sub1(a.(.(.not.(.i_s. Versao atual impressa (*. c. produz exatamente o mesmo resultado que outro mostrado mais acima que tinha uma interface explicita produzida pelo fato da subrotina estar imersa em um módulo. r = a. i_t i_r = present(r) i_s = present(s) i_t = present(t) if(i_r.and.and.i_t)) u = 0.i_r).i_r).and.and. optional.not. intent(out) :: u logical :: i_r.and.and.and.i_t)) u = r + s if(i_r.d0 return end subroutine sub1 Este programa usando uma interface explicita.i_t)) u = s if(i_r.i_s).i_s). intent(in) :: r. t. s = b) stop end program interface_explicita subroutine sub1(r.Fortran 90/95 program interface_explicita implicit none !Definindo o bloco de interface interface subroutine sub1(r. t.

Fortran 90/95 Sempre que possível coloque as subrotinas e funções dentro de um módulo de tal forma que tenham um interface explicita. As específicas operam apenas sobre um determinado tipo de dado. O Fortran 90/95 suporta funções genéricas definidas pelo programador. reais e arrays de inteiros e reais. 8. diferente do nome dos subprogramas dentro da interface. A seguir apresenta-se um programa que adiciona dois números reais ou inteiros e de comprimentos diferentes. Suponha a existência de várias rotinas capazes de somar dois dados de diferentes tipos e tamanhos. b. sem utilizar blocos de interface. intent(out) :: c end subroutine soma1 subroutine soma2(a. intent(in) :: a. por exemplo: inteiros.6 Subprogramas genéricos O Fortran 90/95 inclui entre suas funções intrínsecas. e que queiramos produzir apenas um rotina que seja capaz de operar sobre todos os tipos de dados e retornar um resultado compatível. então coloque os dentro de um módulo e as acesse via uma declaração USE. ilha solteira. então o compilador Fortran 90/95 será capaz de entender que todos os subprogramas contidos dentro daquela interface são versões especiais do subprograma genérico que se quer construir. 8. As genéricas operam sobre dados de diferentes naturezas.feis.6. b integer(longo). funções de uso genérico e funções de uso específico. simples = 4. c) !Interface da subrotina que soma inteiros curtos use tipo_dado implicit none integer(curto). longo = 4.com 82 . e o subprograma só funciona para aquele tipo.1 Subprogramas genéricos definidas pelo programador Viemos até o momento tratando com subprogramas (definidos pelo programador) apenas do tipo específico onde fixa-se o tipo de variável. Se definirmos um nome genérico para a interface. c) use tipo_dado implicit none !Interface da subrotina que soma inteiros longos integer(longo). parameter :: curto = 2. intent(out) :: c Versão primeira de janeiro 1999. b integer(curto).pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.br e jbaparecido@gmail. 15 de dezembro 1999 ! use tipo_dado implicit none !Definição da interface genérica (soma) interface soma subroutine soma1(a. module tipo_dado !Módulo para compartilhar os parâmetros de tamanhos das variáveis save integer. Versao atual impressa (*. b. Se for necessário criar vários blocos de interface. duplo = 8 end module tipo_dado program soma_generica !Objetivo: Mostrar como se define uma função genérica ! !programador: joao batista aparecido. intent(in) :: a.unesp.

intent(in) :: a.com 83 .Fortran 90/95 end subroutine soma2 subroutine soma3(a.e0/3. b real(duplo).unesp. s = -1. c) use tipo_dado implicit none !Interface da subrotina que soma reais duplos real(duplo). intent(in) :: a. n. y. intent(in) :: a. z real(duplo) :: r = 1. y = -1. b integer(longo). b. c) use tipo_dado implicit none !Interface da subrotina que soma reais simples real(simples). t) stop end program soma_generica subroutine soma1(a.d0. b.j = 5.d0. c) !Subrotina que soma dois reais simples use tipo_dado implicit none Versão primeira de janeiro 1999. intent(out) :: c end subroutine soma3 subroutine soma4(a.e0. t call soma(i. b. b. k) call soma(m. z) call soma(r. intent(out) :: c end subroutine soma4 end interface integer(curto) :: i = 1. k integer(longo) :: m = 2. Versao atual impressa (*. o real(simples) :: x = 1. intent(out) :: c c = a+ b return end subroutine soma2 subroutine soma3(a. c) !Subrotina que soma dois inteiros longos use tipo_dado implicit none integer(longo). s. o) call soma(x. b.br e jbaparecido@gmail.feis. intent(out) :: c c = a+ b return end subroutine soma1 subroutine soma2(a. n = 9. j.e0. intent(in) :: a.d0/3. c) !Subrotina que soma dois inteiros curtos use tipo_dado implicit none integer(curto). b integer(curto). b real(simples).pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.

pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. a interface genérica para a subrotina soma deve ser da seguinte forma interface soma module procedure soma1 module procedure soma2 module procedure soma3 module procedure soma4 end interface O bloco de interface deve ser colocado no mesmo módulo onde estão os subprogramas componentes do subprograma genérico.com 84 .6. O Fortran apresenta uma declaração especial para efetuar esta tarefa a declaração MODULE PROCEDURE. A forma desta declaração é module procedure lista_nome_procedure onde procedure lista_nome_procedure é a lista de subprogramas que compõem a função genérica. intent(out) :: c c = a+ b return end subroutine soma4 Use blocos de interface genéricos para definir subprogramas que podem operar com tipos de dados variáveis.7 Estendendo o Fortran com declarações e operadores definidos pelo programador Versão primeira de janeiro 1999. que pode ser usada em bloco de interface genérica. então como definir um interface mais genérica se o conceito de módulo proíbe a definição de uma interface explicitamente dentro dele uma vez que ela já é gerada automaticamente. intent(out) :: c c = a+ b return end subroutine soma3 subroutine soma4(a. c) !Subrotina que soma dois reais duplos use tipo_dado implicit none real(duplo). 8. Versao atual impressa (*.br e jbaparecido@gmail. b real(duplo). A dificuldade em se fazer isto em um módulo é que se os subprogramas já está no módulo.Fortran 90/95 real(simples). eles automaticamente já tem cada um uma interface.feis. b real(simples). intent(in) :: a. 8. Subprogramas genéricos facilitam operações com diferentes tipos de dados.unesp.2 Interfaces genéricas para subprogramas em módulos No item anterior mostrou-se como criar um subprograma genérico usando interfaces explicitas via bloco de interface. Para o caso mostrado no programa acima. b. intent(in) :: a. Agora mostra-se como fazer a mesma coisa porém usando módulo.

ao compilador. lógico. Ou de outra forma como definir operadores para estes novos tipos de dados.feis. com a devida imaginação é possível dar novos sentidos para adição. Porém não foi possível fazer operações sobre as variáveis como um todo. Já vimos como definir tipos novos de dados.DIVIDIR. A forma desta interface é interface operator (simbolo_do_operador) module procedure nome_da_function end interface onde simbolo_do_operador é qualquer um dos operadores intrínsecos (+. As operações básicas dos operadores aritméticos binários e unários não funcionam para dados derivados. mas será necessário que estes subprogramas possam ser distinguidos uns dos outros através da análise dos tipos e tamanhos de seus argumentos. Como isto pode ser feito? O primeiro passo é construir um subprograma que execute o desejado e colocá-lo em um módulo. Mais de um tipo de subprograma pode estar associado a um dado operador. etc.*.com 85 . Qualquer extensão do sentido da soma deve atender a este requisito.) ou qualquer símbolo definido pelo programador. Assim.>. Pode-se estender também o sentido da declaração de atribuição (=) de uma maneira similar./. Quando o compilador encontra um operador. O argumento da esquerda corresponde ao lado esquerdo da atribuição e o direito ao da direita. complexo e caracter). Um operador definido pelo programador pode ter até 31 caracteres cercado por um ponto antes e um ponto depois. o operador será tratado como uma referência para a função. Para se fazer isto utiliza-se o bloco interface de atribuição. vamos ver agora como definir novos operadores. divisão e comparações de dados derivados. Se o operador sendo definido pela interface utiliza os símbolos dos operadores intrínsecos (+. O segundo é o argumento de entrada e deve ter o atributo intent(in).-. subtração. 2) O número de argumentos em uma função deve ser consistente com suas natureza. se tem apenas um é unário. Uma vez definido. para se construir uma álgebra própria de cada tipo específico de dado derivado. Abaixo apresenta-se uma aplicação para executar operações sobre um tipo de dado derivado que é um vetor com três componentes. Versão primeira de janeiro 1999. Versao atual impressa (*.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem./. real.Fortran 90/95 Quando definimos no capítulo anterior os tipos de dados derivados conseguimos apenas atribuir valores às componentes dos dados derivados.) então tem-se alguns restrições adicionais: 1) Não se pode mudar o sentido dos operadores intrínsecos quando estes operam sobre os tipos básicos de dados (inteiro. multiplicação. O segundo passo é associar este subprograma com um operador (símbolo) usando um bloco de interface de operador. tal como . A subrotina deverá ter dois argumentos O primeiro é o argumento de saída e deve ter o atributo intent(out).*. então procura pelo correspondente subprograma. O Fortran 90/95 é uma linguagem extensível de tal forma que o programador pode ir adicionando novos aspectos para acomodar tipos especiais de dados.br e jbaparecido@gmail. ou seja em uma adição só se pode somar dois números de cada vez. Se o operador tem dois argumentos então é um operador binário.-.< etc. No entanto estes operadores podem ser estendidos em outros sentidos para quando estiverem operando com dados derivados.unesp. que tem a seguinte forma interface assignment (=) module procedure nome_subroutine end interface Para o operador de atribuição a interface deve ter uma subrotina ao invés de uma function. Isto porque o programador deve fornecer informações suficientes.

and cross _product.dot.Fortran 90/95 MODULE vectors !Purpose: !To define a derived data type called vector and the !operations that can be performed on it. vector_div_real. !vector_subtract.Vector addition + ! 4.unesp.Conversion to a real array = ! 3. !vector_div_int.Vector-scalar multiplication (4 cases) * ! 6. The module !defines eight operations that can be performed on vectors: ! ! 1.Creation from a real array = ! 2.) Versão primeira de janeiro 1999.br e jbaparecido@gmail.com 86 . int_times_vector. vector_times_real.Cross product * ! !It contains a total of 12 procedures to implement those !operations: array_to_vector.feis. ! implicit none ! declare vector data types: type :: vector real :: x real :: y real :: z end type ! declare interface operators: interface assignment (=) module procedure array_to_vector module procedure vector_to_array end interface interface operator (+) module procedure vector_add end interface interface operator (-) module procedure vector_subtract end interface interface operator (*) module procedure vector_times_real module procedure real_times_vector module procedure vector_times_int module procedure int_times_vector module procedure cross_product end interface interface operator (/) module procedure vector_div_real module procedure vector_div_int end interface interface operator (. ! 8.Vector-scalar division (2 cases) / ! 7. dot _product.dot. real_times_vector. vector_add.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. !vector_times_int.Vector subtraction ! 5. vector_to_array.Dot product . Versao atual impressa (*.

z = vec_1.z = vec_1.y = vec_1.y = vec_1.x vector_subtract. vec_2 vector_subtract.y vector_subtract.x real_times_vector.y * real_2 vector_times_real.y vector_add.y .z end function vector_add function vector_subtract(vec_1.x + vec_2. Versao atual impressa (*.x .z . vec_2) type (vector) :: real_times_vector real. vec_1) real.z end function vector_subtract function vector_times_real(vec_1.x vector_add.z end subroutine vector_to_array function vector_add(vec_1. intent(out) :: vec_result real.x = vec_1.y real_times_vector.x = real_1 * vec_2. intent(in) :: vec_1.vec_2. intent(in) :: vec_1.Fortran 90/95 module procedure dot_product end interface ! now define the implementing functions. vec_2) type (vector) :: vector_add type (vector).x = array(1) vec_result.x = vec_1. vec_2 vector_add.y = array(2) vec_result. contains subroutine array_to_vector(vec_result. intent(in) :: vec_1 integer.z + vec_2.x * real_2 vector_times_real. real_2) type (vector) :: vector_times_real type (vector). dimension(3). intent(out) :: array_result type (vector). intent(in) :: vec_1 real.unesp.vec_2.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. intent(in) :: real_2 vector_times_real.x = vec_1. intent(in) :: int_2 Versão primeira de janeiro 1999. dimension(3). vec_2) type (vector) :: vector_subtract type (vector).y = vec_1.y + vec_2. int_2) type (vector) :: vector_times_int type (vector). intent(in) :: vec_1 array_result(1) = vec_1.y = real_1 * vec_2.br e jbaparecido@gmail.y array_result(3) = vec_1.x array_result(2) = vec_1. intent(in) :: array vec_result. intent(in) :: real_1 type (vector).z end function real_times_vector function vector_times_int(vec_1.feis.z = vec_1. intent(in) :: vec_2 real_times_vector.z = real_1 * vec_2.z * real_2 end function vector_times_real function real_times_vector(real_1.vec_2. array) type (vector).z = array(3) end subroutine array_to_vector subroutine vector_to_array(array_result.com 87 .

y cross_product. vec_2 cross_product.Fortran 90/95 vector_times_int.x = vec_1.y * real(int_2) vector_times_int. vec_2) type (vector) :: int_times_vector integer.z*vec_2.x / real_2 vector_div_real.x int_times_vector.y = vec_1.x = vec_1.x*vec_2.y .y int_times_vector. intent(in) :: vec_1 real.z / real_2 end function vector_div_real function vector_div_int (vec_1.x . Versao atual impressa (*.x end function cross_product end module vectors program test_vectors !purpose: !to test the definitions.y = real(int_1) * vec_2.y & + vec_1.z * real(int_2) end function vector_times_int function int_times_vector(int_1.z / real(int_2) end function vector_div_int function dot_product (vec_1.z end function int_times_vector function vector_div_real(vec_1. intent(in) :: int_2 vector_div_int.x*vec_2. intent(in) :: real_2 vector_div_real.vec_1.y = vec_1. real_2) type (vector) :: vector_div_real type (vector).com 88 .y*vec_2.feis.z cross_product.z = vec_1. vec_2) type (vector) :: cross_product type (vector).pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. vec_2 dot_product = vec_1.z = vec_1. intent(in) :: vec_1.z*vec_2. int_2) type (vector) :: vector_div_int type (vector). intent(in) :: int_1 type (vector). intent(in) :: vec_1.vec_1.z end function dot_product function cross_product (vec_1.z = vec_1.z = vec_1.y = vec_1. operations.br e jbaparecido@gmail.y*vec_2.y / real_2 vector_div_real. and assignments !associated with the vector data type. vec_2) real :: dot_product type (vector).x * real(int_2) vector_times_int.x = vec_1.z .unesp.y = vec_1.y / real(int_2) vector_div_int.z = real(int_1) * vec_2.x*vec_2.x + vec_1.z*vec_2. ! use vectors implicit none ! list of variables: Versão primeira de janeiro 1999.vec_1. intent(in) :: vec_2 int_times_vector. intent(in) :: vec_1 integer.x = real(int_1) * vec_2.y*vec_2.x = vec_1.x / real(int_2) vector_div_int.

/) vec_2 = (/1. 20. 1. No entanto as vezes não há interesse que determinados dados do interior de um módulo esteja disponível fora do módulo. vec_2. /) write (*. 20.Fortran 90/95 real. 2. vec_1 . vec_1*vec_2 end program test_vectors 8. vec_1*2 ! test division by a scalar.. /) vec_2 = (/ -1. 2. vec_1 = (/10. O atributo PUBLIC é o default e torna uma variável totalmente disponível. vec_2 ! output array ! test vectors ! test assignments by assigning an array to vec_1 and ! assigning vec_1 to array_out. Por outro lado ela continuará totalmente disponível no interior do módulo. vec_1 + vec_2. 3. 3. 30. 30.*) vec_1. vec_2. vec_1/5 ! test dot product.br e jbaparecido@gmail. /) write (*. vec_2 ! test cross product. public :: tension type (caixa). vec_1/5.. /) write (*.. vec_1 = (/ 1. Então a questão é: Como esconder alguns dados do interior de um módulo? O Fortran apresenta dois atributos para tratar esta questão... array_out ! test addition and subtraction. o PUBLIC e o PRIVATE. ela ficará totalmente indisponível fora do ambiente do módulo. Abaixo tem-se alguns exemplos de como efetuar esta declaração integer. 2.com 89 . vec_1*2. 2*vec_1.dot. dimension(3) :: array_out type (vector) :: vec_1. quer seja internamente ao módulo quer seja externamente. 1. 3.. vec_1-vec_2 ! test multiplication by a scalar...pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.. A melhor maneira para ser fazer isto é incluir o atribute Versão primeira de janeiro 1999.8 Restringindo acesso ao conteúdo de um módulo Até o momento todos os dados que foram colocados nos módulos estavam totalmente disponíveis e acessíveis.*vec_1.. /) array_out = vec_1 write (*.. -1.. /) write (*.*) vec_1. 1. /) write (*. private :: conta real. /) vec_2 = (/1. 3. 2....*) vec_1... 2..*) vec_1.. 3. private :: caixa_sapato É aconselhável esconder qualquer dado ou subprograma de um módulo que não precisem ser acessados de fora. Versao atual impressa (*.*) vec_1.feis. vec_1 = (/ 1. vec_2. vec_1 = (/ 1. Se declararmos uma variável interna de um módulo de PRIVATE.unesp. 2.. vec_1 = (/1. vec_1 = (/10.*) vec_1.

A forma de se fazer é use nome_do_modulo. assim é interessante que se acesse apenas as que forem necessárias.br e jbaparecido@gmail. No entanto nem todas as informações disponíveis serão usadas. Também é possível renomear dados ou subprogramas de um módulo quando usando a declaração USE.Fortran 90/95 em cada módulo. Versão primeira de janeiro 1999. lista_para_renomear use nome_do_modulo. PRIVATE 8. Nesta lista os itens são separados por vírgula.com 90 . Para restringir este acesso pode-se adicionar a especificação ONLY à declaração USE. e listar os itens específicos que se quer deixar visíveis em uma declaração específica com o atributo PUBLIC.unesp.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.9 Opções avançadas da declaração USE Quando um programa acessa um módulo através de uma declaração USE todas as informações ali contidas ficam disponíveis para o programa que o está acessando. Outra razão surge quando um dado que é usado com muita freqüência e tem um nome muito grande. localmente. pode-se então renomeá-lo com um nome pequeno e economizar em tempo de digitação. para lsqfit. Versao atual impressa (*. As formas de usar a declaração USE para permitir ao programador renomear algum dado ou subprograma são use nome_do_modulo. De todos os dados e subprogramas que este módulo tem. only : sp_real_least_square_fit => lsqfit utiliza-se um módulo chamado data_fit. only : lista_only onde nome_do_modulo é o nome do módulo e lista_only é a lista dos itens do módulo a serem usadas. utiliza-se apenas o chamado sp_real_least_square_fit que está sendo renomeado. Uma das razões para renomear um item é a existência em algum local do programa de uma outra variável com o mesmo nome. only: lista_para_renomear onde lista_para_renomear toma a forma nome_no_modulo => nome_local Na declaração abaixo use data_fit. Fazendo esta renomeação não vai haver conflito de nomes. exceto aquelas protegidas com o atributo PRIVATE.feis.

Isto é. Podem existir ponteiros apontando para variáveis do tipo derivado. dimension(:. Uma variável ponteiro deverá ter o mesmo tipo declarado da variável para qual aponta. mas se você diz José da Silva mora em São Paulo. e a localização de José da Silva será muito mais rápida. pointer. mas armazenam o endereço de uma outra variável. Um exemplo simbólico do poder dos ponteiros é: Se você diz que José da Silva mora na cidade de São Paulo. o array que guarda estas informações enquanto na memória principal precisará ser incrementado de uma unidade com o programa já executando e com os dados já existentes já alocados na memória. De outra forma. certamente existirá a necessidade de introduzir ou retirar números da base de dados.feis. Quase todas as variáveis dos tipos básicos do Fortran são estáticas. um ponteiro só poderá apontar para uma variável que seja do seu mesmo tipo. Imagine um programa que manipule a base de dados dos CPFs dos brasileiros. ou através de um declaração POINTER. Adiante apresenta-se alguns exemplos da sintaxe para definir ponteiros real.1 Ponteiros e alvos Uma variável é ponteiro (pointer) quando possui o atributo POINTER na sua declaração de variável. dimension(:. são criadas no início da execução do programa e permanecem da mesma forma e na mesma posição de memória até o final da execução.:.:) :: p_w pointer. Por isto o nome. Versao atual impressa (*. Algumas maneiras de definir ponteiros para arrays são integer. As exceções a esta realidade são os arrays alocáveis e os arrays automáticos (em subprogramas). o significado será muito mais claro. Neste capítulo apresenta-se uma outra maneira de definir estruturas de dados que podem ser dinamicamente criadas e podem ter o tamanho variável ao longo da execução. Como fazer isto? Veremos neste capítulo. 40.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.Fortran 90/95 CAPÍTULO 9 PONTEIROS E ESTRUTURAS DINÂMICAS DE DADOS Ponteiros são variáveis que não armazenam seu valor próprio. Considere que vamos aumentar um número de CPF na lista. neste caso na declaração do ponteiro estará explicito o rank do array mas não a sua extensão.unesp. real. Ponteiros também podem apontar para arrays.:) :: p_z Versão primeira de janeiro 1999. 9. têm um significado. dimension(:). na Rua Fantasia. pointer :: p_x ou real :: p_x pointer :: p_x Como foi dito anteriormente um ponteiro não têm valor próprio mas guarda o endereço de memória de uma outra variável. Os ponteiros são fundamentais para viabilizar a existência de tais estruturas. além das atribuições de verificação de dados. mas também muita responsabilidade para o programador. de qualquer forma o ponteiro aponta para o primeiro elemento do array. Apartamento 105. aquele que aponta para uma outra variável. Isto também ocorre com variáveis do tipo derivado. uma vez que o mau uso de ponteiros pode levar a resultados catastróficos. pointer :: p_y real.com 91 . ponteiro. O conceito de ponteiro introduz muita flexibilidade na construção de muitos algoritmos.br e jbaparecido@gmail.

1 Declaração de atribuição de ponteiro Um ponteiro pode ser associado a uma variável alvo através de uma declaração de atribuição de ponteiro. Um ponteiro pode apontar para outro ponteiro. dimension(5).10) :: w 9. 9. respectivamente. Esta declaração tem o seguinte formato ponteiro => alvo onde ponteiro é o nome da variável ponteiro que irá conter o endereço do alvo. A situação de todos os ponteiros da lista passará então para desassociados.Fortran 90/95 Os ponteiros acima apontam para arrays rank 1. qualquer referência ao ponteiro é em realidade uma referência à variável alvo. rank 2 e rank 3. indefinido (undefined) e desassociado (disassociated). quando associado a um alvo a situação é então associado. target :: x integer. Um valor que está armazenado em uma variável alvo pode ser obtido referenciado a variável alvo ou então referenciado o ponteiro que está apontado para ela.unesp.1 Situação de um associação ponteiro-alvo A situação da associação de um ponteiro e de um alvo indica se um dado ponteiro está associado a um dado alvo. Para tal é necessário apenas executar uma declaração NULLIFY com o seguinte formato nullify(lista_de_ponteiros) onde nullify irá desassociar todos os ponteiros lista na lista_de_ponteiros de todos os seus respectivos alvos.com 92 . no entanto um alvo pode ser apontado por um. Quando um alvo está sendo apontado por dois ponteiros e um dos ponteiros é movido.feis. Para uma variável tornar-se um alvo é necessário que a mesma tenha o atributo TARGET ou através de uma declaração TARGET. resta vermos como desassociar um ponteiro de seu alvo. Uma boa conduta na definição de variáveis do tipo ponteiro é colocar um p no início do nome da variável para se ter uma distinção clara quando se lê um programa de quais variáveis são ponteiros e quais não são. Depois que um ponteiro foi associado a uma variável alvo. Versao atual impressa (*. Em outras palavras. dois ou mais ponteiros. Já vimos como declarar um ponteiro e como associar um ponteiro a um alvo.1.br e jbaparecido@gmail. Quando um ponteiro é criado em uma declaração de tipo sua situação é indefinido.1. Para que seja possível que um ponteiro aponte para uma variável é necessário que a mesma seja um alvo. Em outras palavras um ponteiro não pode apontar para dois alvos simultaneamente. e alvo é a variável apontada pelo ponteiro. target.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. target :: y real. neste caso em realidade os dois ponteiros estarão apontando para o mesmo alvo. Versão primeira de janeiro 1999. É possível três situações: associado (associated). Se um ponteiro está associado a uma variável alvo e então é novamente associado a uma segunda variável alvo. dimension(5. um alvo é uma variável que foi disponibilizada para o uso com ponteiros. a primeira associação será desfeita. A seguir alguns exemplos de declaração de variáveis como alvo real. e quando desassociado do alvo sua situação torna-se desassociado. o outro ponteiro não será modificado.

pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. Como a situação indefinida é ambígua é importante que todos os ponteiros sejam nulificados usando nullify logo após sua definição. p_y. p_aux) !Nulificando os ponteiros p_x => x !Atribuindo o ponteiro p_x Versão primeira de janeiro 1999. ou desassociado de um dado alvo basta usar a função lógica ASSOCIATED. j_max = 100 integer :: i. Adicionalmente. A partir de então a situação daquele ponteiro será associado ou desassociado. sua forma geral de uso é variavel_logica = associated(ponteiro) que responderá se ponteiro já está associado ou não.feis. 02 de agosto. ou seja a variável alvo de p_y. a qual retornará um valor TRUE se estiver associado e um valor FALSE se não estiver associado. Versao atual impressa (*. Esta função apresenta a característica de suportar quantidade variável de argumentos. assim p_x ficará apontando para a mesma posição de memória que p_y. no lugar de um valor numérico então o valor da variável para a qual ele está apontando é usado. No caso de possuir apenas um argumento. Quando se escreve p_x = p_y o valor que está na variável alvo apontada por p_y é atribuída à posição de memória da variável alvo apontada por p_x. Para descobrir se um dado ponteiro está associado. y !Definindo os alvos real. Abaixo apresenta-se um programa que utiliza ponteiros para trocar a posição de duas matrizes program usando_pointer !Objetivo: Mostrar o uso de ponteiros ! !programador: joão batista aparecido ilha solteira. dimension(i_max. alvo) a qual retornará a situação da associação de ponteiro e alvo. Um ponteiro só pode referenciar uma variável se estiver a ela associado.2 Usando ponteiros em declarações de atribuição Quando um ponteiro aparece em uma expressão aritmética.:) :: p_x. parameter :: i_max = 100. podendo ter um ou dois argumentos.com 93 . se escrevemos p_x => p_y significa que estamos apontando o ponteiro p_x para o ponteiro p_y. p_aux !Definindo os ponteiros nullify(p_x. A segunda forma de uso desta função é com dois argumentos variavel_logica = associated(ponteiro. i_max) :: x. target.br e jbaparecido@gmail. p_y. 9. 2001 ! implicit none integer. 16 de dezembro.Fortran 90/95 Um ponteiro terá sua situação indefinida desde quando é definido até o ponto que sofre uma atribuição.unesp. 1999 !programador: joão batista aparecido ilha solteira. j real :: aux real. pointer. dimension(:.

y !Fazendo o swap das matrizes da forma clássica do i = 1. aquele objeto estará perdido para sempre.0 y = 6. Porém ainda ocupando as posições de memória. x !Inicializando a matriz.0 y = 5.…. e desalocados usando DEALLOCATE. Por isto é importante que a memória que foi alocada usando ALLOCATE seja desalocada usando DEALLOCATE. que está associado a este objeto sem nome.br e jbaparecido@gmail.j) = y(i. da seguinte maneira Versão primeira de janeiro 1999. j_max/2) stop end program usando_pointer 9. Neste caso a declaração ALLOCATE fica da seguinte forma allocate(ponteiro_1(forma_do_ponteiro_1). A operação descrita acima criará um ponteiro que apontará para um conjunto de dados sem nome. e assim por diante. ou seja o rank e a extensão em cada direção que possui a estrutura para a qual o ponteiro vai apontar. Versao atual impressa (*. j_max aux = x(i. criando o chamado vazamento de memória.j) = aux end do end do x = 2.3 Alocação dinâmica de memória usando ponteiros Um dos aspectos mais poderosos do uso de ponteiros em alocação dinâmica é que ele permite não só a criação de espaços na memória como também depois de criados aumentar ou diminuir estes espaços sem destruir os dados já armazenados. caso contrário seu valor será dependente da implementação de cada compilador. Se o ponteiro (ou ponteiros).*) p_x(i_max/2.unesp. j_max/2) !Fazendo o swap das matrizes usando ponteiros p_aux => p_x p_x => p_y p_y => p_aux write(*.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. sendo necessário consultar o manual do fabricante. j) x(i.feis. Devido ao fato deste objeto não ter nome ele poderá ser acessado apenas via ponteiro. j) y(i.Fortran 90/95 p_y => y x = 1.stat = status) onde ponteiro_1 é o nome do primeiro ponteiro a ser alocado.*) p_x(i_max/2. Se a alocação for bem sucedida seu valor é zero. e status é o resultado para operação.com 94 . for nulificado ou redirecionado para outro objeto. Depois que a rotina acima é executada com sucesso a situação do ponteiro será associado.0 !Redefinindo a matriz. i_max do j = 1. x !Redefinindo a matriz. y write(*. A maneira de se fazer isto é parecida com aquela já vista usando arrays alocáveis. Espaços em memória são alocados usando a declaração ALLOCATE. forma_do_ponteiro_1 é a respectiva forma de ponteiro_1.0 !Atribuindo o ponteiro p_y !Inicializando a matriz.

p_y(i_max. como se fosse um array.br e jbaparecido@gmail. stat = status) !Alocando memória p_x = 1. parameter :: i_max = 100. p_aux !Definindo os ponteiros nullify(p_x. p_y. pointer. Pode-se inclusive inserir estruturas no meio da seqüência sem a Versão primeira de janeiro 1999. até o primeiro. Versao atual impressa (*. stat=status) !Desalocando memória stop end program usando_pointer 9. j_max =100 integer :: status real. e assim por diante.j_max). stat=status) !Desalocando memória deallocate(p_aux. Logo abaixo apresenta-se a versão semelhante ao programa anterior.*) p_x(i_max/2.com 95 .j_max). stat=status) !Desalocando memória deallocate(p_y.:) :: p_x. e um ponteiro que aponta para outra estrutura do mesmo tipo. dimension(:.p_aux) !Nulificando os ponteiros allocate(p_x(i_max. automaticamente o ponteiro que apontava para aquele objeto é nulificado. 1999 ! implicit none integer.feis. e para regredir o processo basta ir nulificando os ponteiros que foram abertos. Estes elementos podem ser alocados dinamicamente e esta pilha pode ir crescendo o quanto se desejar.0 !Inicializando o array para onde aponta p_x !Inicializando o array para onde aponta p_y !Fazendo o swap das matrizes usando ponteiros p_aux => p_x p_x => p_y p_y => p_aux write(*.unesp. e que apontem para outras estruturas do mesmo tipo.p_y. stat = status) Quando um espaço de memória é desalocado usando DEALLOCATE.0 p_y = 5. Para parar o processo basta nulificar a ponta do ultimo ponteiro. dos últimos para os primeiros.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. Desta forma cria-se uma estrutura capaz de armazenar reais seqüencialmente. j_max/2) deallocate(p_x. pointer :: p end type Esta estrutura de dados acima toda vez que é definida (instanciada) armazena um valor real.Fortran 90/95 deallocate(ponteiro. Assim seja a seguinte estrutura derivada de dados type :: real_value real :: value type(real_value). 16 de dezembro.4 Usando ponteiros com estruturas derivadas de dados Pode-se colocar ponteiros dentro de estruturas derivadas de dados. agora usando alocação dinâmica de memória program usando_pointer !Objetivo: Mostrar alocação dinâmica usando ponteiros ! !programador: joão batista aparecido ilha solteira. mas cujo tamanho pode crescer ou decrescer continuamente em tempo de execução.

Existem outras. program linked_list ! ! ! ! ! ! ! ! ! purpose: to read in a series of real values from an input data file and store them in a linked list.com 96 . tal como árvore binária. seqüencialmente.br e jbaparecido@gmail. after the list is read in.feis.unesp. pointer :: p end type ! list of variables: type (real_value). file = filename. status = 'old'.'(a20)') filename ! open input data file. igualmente conhecidas. aux ! ! ! ! ! ! ! pointer to head of list input data file name number of data read temporary pointer pointer to tail of list status: 0 for success temporary variable ! get the name of the file containing the input data. pointer :: tail integer :: istat real :: temp. so read the data from ! it. de tamanho desconhecido. input: do Versão primeira de janeiro 1999. Abaixo apresenta-se um exemplo de utilização deste tipo de dado onde um arquivo com números reais. basta apontar o ponteiro da estrutura anterior para a nova estrutura e o ponteiro da nova estrutura para a estrutura subsequente. pointer :: head character(len = 20) :: filename integer :: nvals = 0 type (real_value).pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. até o final. open ( unit = 9. it will be written back to the standard output device. action = 'read'.Fortran 90/95 necessidade de mover dados de suas posições de memória. Esta estrutura é clássica em computação e é conhecida como lista lincada. record of revisions: date programmer ==== ========== 01/28/95 s. pointer :: ptr type (real_value). j. é lido. chapman ! description of change ! ===================== ! original code implicit none ! derived data type to store real values in type :: real_value real :: value type (real_value). write (*. and store it in the linked list. Versao atual impressa (*. O programa é capaz de dinamicamente ir aumentando o tamanho da estrutura geral de dados para abrigar novas informações. iostat = istat ) ! was the open successful? fileopen: if ( istat == 0 ) then ! open successful ! the file was opened successfully.*) 'enter the file name with the data to be read: ' read (*.

not.0 7. assim uma extensão nesta direção seria.value = temp end if end do input ! now. istat end if fileopen end program A seguir um exemplo de arquivo de dados para se testar o programa acima 1. stat = istat) tail => head nullify (tail.value ptr => ptr. write out the data.0 -4. int2 real :: value1. pointer :: p end type Versão primeira de janeiro 1999. value3 character(20) :: nome1. value2. iostat = istat) temp ! get value if ( istat /= 0 ) exit ! exit on end of data nvals = nvals + 1 ! bump count if (.value = temp else allocate (tail. ptr => head output: do if (. tell user.0 5.p end do output ! no values in list ! allocate new value ! tail pts to new value ! nullify p in new value ! store number ! values already in list ! allocate new value ! tail pts to new value ! nullify p in new value ! store number ! pointer valid? ! yes: write value ! get next pointer else fileopen ! else file open failed.0 -8.*) ptr.associated(ptr)) exit write (*.p nullify (tail.0 -10.0 9.br e jbaparecido@gmail.not. *. complexos. stat = istat) tail => tail.unesp.p) tail. nome2 logical :: logic1. inteiros. o que segue type :: various_values complex :: c1 integer :: int1.p. logic2.com 97 .*) 'file open failed--status = '.feis.0 -6.0 -2. caracteres. Versao atual impressa (*. por exemplo.p) tail.Fortran 90/95 read (9. write (*. associated(head)) then allocate (head.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. logic3 type(various_values).000 A estrutura derivada de dados utilizada acima pode ser estendida para conter no seu interior vários valores reais.0 3. lógicos.

A seguir o programa que usa esta estrutura de dados module btree ! ! purpose: ! to define the derived data type used as a node in the ! binary tree. na estrutura de dados acima. pointer :: p1. find_node ! declare type for a node of the binary tree. Uma estrutura razoavelmente genérica de uma árvore binária seria type :: various_values_and_two_pointers complex :: c1 integer :: int1. logic3 type(various_values_and_two_pointers).br e jbaparecido@gmail. and find a value in the tree. pointer :: before type (node). ! ! record of revisions: ! date programmer description of change ! ==== ========== ===================== ! 02/04/96 s. type :: node character(len = 10) :: last character(len = 10) :: first character :: mi character(len = 16) :: phone type (node). operator(<). this module also contains the ! subroutines to add a node to the tree. value3 character(20) :: nome1. formando assim uma arvore binária. int2 real :: value1. and to define the operations >. operator(==) public :: add_node. write out the ! values in the tree. operator(>).com 98 . private public :: node. segundo e terceiro nomes de uma pessoa bem como o seu respectivo telefone. chapman original code ! implicit none ! restrict access to module contents. and == ! for this data type. Um exemplo bem conhecido na literatura é a arvore binária que acrescenta mais um ponteiro ao tipo derivado de dados. é incorporar mais de um ponteiro. logic2. write_node. pointer :: after end type interface operator (>) module procedure greater_than end interface interface operator (<) module procedure less_than end interface Versão primeira de janeiro 1999.unesp. um ou dois outros elementos.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.feis. <. value2. j.Fortran 90/95 Um outro tipo de extensão. Versao atual impressa (*. p2 end type Imagine-se uma arvore binária para armazenar e disponibilizar os primeiro. Assim cada elemento na estrutura global estará apontando para nenhum. nome2 logical :: logic1.

Fortran 90/95
interface operator (==)
module procedure equal_to
end interface
contains
recursive subroutine add_node (ptr, new_node)
!
! purpose:
! to add a new node to the binary tree structure.
!
type (node), pointer :: ptr ! pointer to current pos. in tree
type (node), pointer :: new_node ! pointer to new node
if ( .not. associated(ptr) ) then
! there is no tree yet. add the node right here.
ptr => new_node
else if ( new_node < ptr ) then
if ( associated(ptr.before) ) then
call add_node ( ptr.before, new_node )
else
ptr.before => new_node
end if
else
if ( associated(ptr.after) ) then
call add_node ( ptr.after, new_node )
else
ptr.after => new_node
end if
end if
end subroutine add_node
recursive subroutine write_node (ptr)
!
! purpose:
! to write out the contents of the binary tree
! structure in order.
!
type (node), pointer :: ptr ! pointer to current pos. in tree
! write contents of previous node.
if ( associated(ptr.before) ) then
call write_node ( ptr.before )
end if
! write contents of current node.
write (*,"(1x,a,', ',a,1x,a)") ptr.last, ptr.first, ptr.mi
! write contents of next node.
if ( associated(ptr.after) ) then
call write_node ( ptr.after )
end if
end subroutine write_node
recursive subroutine find_node (ptr, search, error)
!
! purpose:
! to find a particular node in the binary tree structure.
! "search" is a pointer to the name to find, and will
! also contain the results when the subroutine finishes

Versão primeira de janeiro 1999. Versao atual impressa (*.pdf) em 22 de agosto de 2013
Autor: João Batista Aparecido – jbaparecido@dem.feis.unesp.br e jbaparecido@gmail.com

99

Fortran 90/95
! if the node is found.
!
type (node), pointer :: ptr ! pointer to curr pos. in tree
type (node), pointer :: search ! pointer to value to find.
integer :: error
! error: 0 = ok, 1 = not found
if ( search < ptr ) then
if ( associated(ptr.before) ) then
call find_node (ptr.before, search, error)
else
error = 1
end if
else if ( search == ptr ) then
search = ptr
error = 0
else
if ( associated(ptr.after) ) then
call find_node (ptr.after, search, error)
else
error = 1
end if
end if
end subroutine find_node
logical function greater_than (op1, op2)
!
! purpose:
! to test to see if operand 1 is > operand 2
! in alphabetical order.
!
type (node), intent(in) :: op1, op2
character(len=10) :: last1, last2, first1, first2
character :: mi1, mi2
call ushift (op1, last1, first1, mi1 )
call ushift (op2, last2, first2, mi2 )
if (last1 > last2) then
greater_than = .true.
else if (last1 < last2) then
greater_than = .false.
else ! last names match
if (first1 > first2) then
greater_than = .true.
else if (first1 < first2) then
greater_than = .false.
else ! first names match
if (mi1 > mi2) then
greater_than = .true.
else
greater_than = .false.
end if
end if
end if
end function greater_than
logical function less_than (op1, op2)
!
! purpose:
! to test to see if operand 1 is < operand 2

Versão primeira de janeiro 1999. Versao atual impressa (*.pdf) em 22 de agosto de 2013
Autor: João Batista Aparecido – jbaparecido@dem.feis.unesp.br e jbaparecido@gmail.com

100

Fortran 90/95
! in alphabetical order.
!
type (node), intent(in) :: op1, op2
character(len=10) :: last1, last2, first1, first2
character :: mi1, mi2
call ushift (op1, last1, first1, mi1 )
call ushift (op2, last2, first2, mi2 )
if (last1 < last2) then
less_than = .true.
else if (last1 > last2) then
less_than = .false.
else ! last names match
if (first1 < first2) then
less_than = .true.
else if (first1 > first2) then
less_than = .false.
else ! first names match
if (mi1 < mi2) then
less_than = .true.
else
less_than = .false.
end if
end if
end if
end function less_than
logical function equal_to (op1, op2)
!
! purpose:
! to test to see if operand 1 is equal to operand 2
! alphabetically.
!
type (node), intent(in) :: op1, op2
character(len=10) :: last1, last2, first1, first2
character :: mi1, mi2
call ushift (op1, last1, first1, mi1 )
call ushift (op2, last2, first2, mi2 )
if ( (last1 == last2) .and. (first1 == first2) .and. &
(mi1 == mi2 ) ) then
equal_to = .true.
else
equal_to = .false.
end if
end function equal_to
subroutine ushift( op, last, first, mi )
!
! purpose:
! to create upshifted versions of all strings for
! comparison.
!
type (node), intent(in) :: op
character(len=10), intent(inout) :: last, first
character, intent(inout) :: mi

Versão primeira de janeiro 1999. Versao atual impressa (*.pdf) em 22 de agosto de 2013
Autor: João Batista Aparecido – jbaparecido@dem.feis.unesp.br e jbaparecido@gmail.com

101

they are written out in sorted order. and the program ! recovers the data associated with that name.mi call ucase (last) call ucase (first) call ucase (mi) end subroutine ushift subroutine ucase ( string ) ! ! purpose: ! to shift a character string to upper case. chapman original code ! use btree implicit none Versão primeira de janeiro 1999. ! ! record of revisions: ! date programmer description of change ! ==== ========== ===================== ! 11/25/95 s.first mi = op. length if ( ( string(i:i) >= 'a' ) . then the ! user is prompted for a name to retrieve.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.32 ) end if end do end subroutine ucase end module btree program binary_tree ! ! purpose: ! to read in a series of random names and phone numbers ! and store them in a binary tree. intent(inout) :: string ! declare local variables: integer :: i ! loop index integer :: length ! length of input string ! get length of string length = len ( string ) ! now shift lower case letters to upper case. 11/25/95 s.feis. j. chapman original code ! 1. ! ! record of revisions: ! date programmer description of change ! ==== ========== ===================== ! 02/06/95 s.br e jbaparecido@gmail. after the values are ! stored. & ( string(i:i) <= 'z' ) ) then string(i:i) = achar ( iachar ( string(i:i) ) .unesp. j. Versao atual impressa (*. do i = 1.com 102 . chapman modified for any collating seq ! implicit none ! declare calling parameters: character(len=*).and.Fortran 90/95 last = op.last first = op. j.

status='old'.'(a)') temp.a1.'(a)') temp. error ) check: if ( error == 0 ) then write (*. status is old because the input data must ! already exist.a)') 'enter name to recover from tree:' write (*.first write (*. and insert it into the ! binary tree.first. temp. iostat=istat) temp.a)'. write (*. temp) ! add to binary tree end do input ! now.stat=istat) ! allocate node nullify ( temp.last write (*.'(1x. '.phone else write (*.1x.'(1x.advance='no') 'first name: ' read (*.'(/.'(/. pointer :: temp ! temp pointer to node ! nullify new pointers nullify ( root. open ( unit=9. temp.mi.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.'(/. temp.'(/. '. Versao atual impressa (*. ' '. write out the sorted data.a)'.1x. write (*.7a)') temp.'(1x.advance='no') 'last name: ' read (*.a)'. temp.1x.mi ! locate record call find_node ( root. & temp. ' '.com 103 .a)') 'specified node not found!' end if check else fileopen Versão primeira de janeiro 1999.before.a10. file=filename. & temp.'(a20)') filename ! open input data file. input: do allocate (temp.Fortran 90/95 ! list of variables: integer :: error ! error flag: 0=success character(len=20) :: filename ! input data file name integer :: istat ! status: 0 for success type (node).'(1x.last.first.1x. read the data into that node. allocate space for each ! node.last.'(a)') temp.feis.1x.*) 'enter the file name with the input data: ' read (*. temp. action='read'. pointer :: root ! pointer to root node type (node).1x.after) ! nullify pointers read (9. write (*.advance='no') 'middle initial: ' read (*.unesp.a16) if ( istat /= 0 ) exit input ! exit on end of data call add_node(root.a)') 'the record is:' write (*.br e jbaparecido@gmail.1x. temp ) ! get the name of the file containing the input data. 100.phone ! read data 100 format (a10. & iostat=istat ) ! was the open successful? fileopen: if ( istat == 0 ) then ! open successful ! the file was opened successfully.mi. temp.a)') 'the sorted data list is: ' call write_node(root) ! prompt for a name to search for in the tree.

tell user. write (*.unesp.'(1x.i6)') 'file open failed--status = '. istat end if fileopen end program A seguir um arquivo de dados para se testar este programa Carneiro Silva Forte Ricieri Alves Honda Park Smith Chung Ling Paulo João Ronaldo Maria Paula Eiko Sum John Chang Ding S M P R B H L W S P (602) (309) (987) (276) (145) (849) (743) (478) (586) (667) 534-2398 234-8534 854-4590 794-8520 639-7856 466-8866 136-3484 375-3678 975-8766 889-6544 Versão primeira de janeiro 1999.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.feis. Versao atual impressa (*.com 104 .br e jbaparecido@gmail.a.Fortran 90/95 ! else file open failed.

e assim por diante.1 Bibliotecas de programas fonte Pode-se desenvolver uma coleção de código-fonte. tornou-se possível colecionar conjuntos de subprogramas. precisa e eficiente. intent(in) :: a. De qualquer forma trata-se de objetos virtuais que fazer uso de uma linguagem escrita.br e jbaparecido@gmail. O termo parecer um tanto inapropriado.Fortran 90/95 CAPÍTULO 10 BIBLIOTECAS DE SUBROTINAS E FUNÇÕES Desde a mais remota antigüidade o ser humano tem tentado formas de perenizar a informação. Naturalmente.. De qualquer forma são conhecidas como bibliotecas. intent(in) :: a. b) implicit none integer(1). as bibliotecas computacionais. que seja confiável.unesp. Rotinas para efetuar soma ! Function que soma inteiros de 1 byte function soma_int1(a. sem a necessidade de se reprogramar os mesmos algoritmos repetidas vezes. subrotinas ou funções. Seja abaixo uma coleção de rotinas para cumprir o objetivo enunciado acima. O Fortran90/95. provê meios para se criar e/ou utilizar bibliotecas computacionais. 10. este problema é trivial mas servirá perfeitamente da demonstrar os conceitos envolvidos. Vamos imaginar uma biblioteca de programas para realizar as operações básicas (+. e que possa ser usada repetidas vezes. isto também ocorrem com programas computacionais. Versao atual impressa (*.com 105 . bibliotecas gráficas. Existem as mais variadas. bibliotecas estatísticas. b) implicit none integer(2). e portanto tem uma certa semelhança com livros. Com o passar do tempo. Uma das formas mais antigas de preservar a informação foi através das coleções de livros. hoje são totalmente desconhecidas porque não deixaram qualquer registro. Com o desenvolvimento de algoritmos eficientes e robustos para o mais variados tipos de tarefas. apresenta-se algumas maneiras de explorar o conceito de bibliotecas ou coleções de programas. as bibliotecas./) da aritmética sobre os tipos de dados básicos. conforme os casos. b integer(2) :: soma_int2 Versão primeira de janeiro 1999.*. Obviamente. previamente estabelecidos. As civilizações que não conseguiram perenizar a informação e já desapareceram. surgiram vários tipos de coleções que receberam nomes específicos. uma vez que os objetos da coleção não são livros nem são objetos reais. b integer(1) :: soma_int1 soma_int1 = a + b end function soma_int1 ! Function que soma inteiros de 2 bytes function soma_int2(a.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. para as mais diferentes tarefas: bibliotecas de cálculo diferencial e integral. Neste capítulo.feis.

b) implicit none real(8). intent(in) :: a. b integer(4) :: soma_int4 soma_int4 = a + b end function soma_int4 ! Function que soma reais de 4 bytes function soma_real4(a.feis. Versao atual impressa (*.com 106 . b real(8) :: soma_real8 soma_real8 = a + b end function soma_real8 ! Function que soma complexos de 4 bytes function soma_complex4(a. b) implicit none real(4).Fortran 90/95 soma_int2 = a + b end function soma_int2 ! Function que soma inteiros de 4 bytes function soma_int4(a. b) implicit none complex(8).unesp.br e jbaparecido@gmail. intent(in) :: a. intent(in) :: a. b) implicit none integer(4). b) implicit none complex(4).pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. intent(in) :: a. b complex(8) :: soma_complex8 soma_complex8 = a + b end function soma_complex8 ! Function que soma lógicos Versão primeira de janeiro 1999. b real(4) :: soma_real4 soma_real4 = a + b end function soma_real4 ! Function que soma reais de 8 bytes function soma_real8(a. intent(in) :: a. b complex(4) :: soma_complex4 soma_complex4 = a + b end function soma_complex4 ! Function que soma complexos de 8 bytes function soma_complex8(a.

b real(4) :: subtrai_real4 subtrai_real4 = a . Versao atual impressa (*. b) implicit none Versão primeira de janeiro 1999.Fortran 90/95 function soma_logical(a. b) implicit none integer(1). b) implicit none logical. intent(in) :: a. b) implicit none integer(2). b logical :: soma_logical soma_logical = a + b end function soma_logical Rotinas para efetuar subtração ! Function que subtrai inteiros de 1 byte function subtrai_int1(a. b integer(4) :: subtrai_int4 subtrai_int4 = a .br e jbaparecido@gmail. b integer(2) :: subtrai_int2 subtrai_int2 = a . b integer(1) :: subtrai_int1 subtrai_int1 = a . b) implicit none integer(4).com 107 .unesp. b) implicit none real(4). intent(in) :: a.b end function subtrai_real4 ! Function que subtrai reais de 8 bytes function subtrai_real8(a. intent(in) :: a. intent(in) :: a.feis.b end function subtrai_int1 ! Function que subtrai inteiros de 2 bytes function subtrai_int2(a. intent(in) :: a.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.b end function subtrai_int4 ! Function que subtrai reais de 4 bytes function subtrai_real4(a.b end function subtrai_int2 ! Function que subtrai inteiros de 4 bytes function subtrai_int4(a.

Fortran 90/95
real(8), intent(in) :: a, b
real(8)
:: subtrai_real8
subtrai_real8 = a - b
end function subtrai_real8
! Function que subtrai complexos de 4 bytes
function subtrai_complex4(a, b)
implicit none
complex(4), intent(in) :: a, b
complex(4)
:: subtrai_complex4
subtrai_complex4 = a - b
end function subtrai_complex4
! Function que subtrai complexos de 8 bytes
function subtrai_complex8(a, b)
implicit none
complex(8), intent(in) :: a, b
complex(8)
:: subtrai_complex8
subtrai_complex8 = a - b
end function subtrai_complex8
! Function que subtrai lógicos
function subtrai_logical(a, b)
implicit none
logical, intent(in) :: a, b
logical
:: subtrai_logical
subtrai_logical = a - b
end function subtrai_logical

Rotinas para efetuar multiplicação
! Function que multiplica inteiros de 1 byte
function multiplica_int1(a, b)
implicit none
integer(1), intent(in) :: a, b
integer(1)
:: multiplica_int1
multiplica_int1 = a * b
end function multiplica_int1
! Function que multiplica inteiros de 2 bytes
function multiplica_int2(a, b)
implicit none
integer(2), intent(in) :: a, b
integer(2)
:: multiplica_int2

Versão primeira de janeiro 1999. Versao atual impressa (*.pdf) em 22 de agosto de 2013
Autor: João Batista Aparecido – jbaparecido@dem.feis.unesp.br e jbaparecido@gmail.com

108

Fortran 90/95
multiplica_int2 = a * b
end function multiplica_int2
! Function que multiplica inteiros de 4 bytes
function multiplica_int4(a, b)
implicit none
integer(4), intent(in) :: a, b
integer(4)
:: multiplica_int4
multiplica_int4 = a * b
end function multiplica_int4
! Function que multiplica reais de 4 bytes
function multiplica_real4(a, b)
implicit none
real(4), intent(in) :: a, b
real(4)
:: multiplica_real4
multiplica_real4 = a * b
end function multiplica_real4
! Function que multiplica reais de 8 bytes
function multiplica_real8(a, b)
implicit none
real(8), intent(in) :: a, b
real(8)
:: multiplica_real8
multiplica_real8 = a * b
end function multiplica_real8
! Function que multiplica complexos de 4 bytes
function multiplica_complex4(a, b)
implicit none
complex(4), intent(in) :: a, b
complex(4)
:: multiplica_complex4
multiplica_complex4 = a * b
end function multiplica_complex4
! Function que multiplica complexos de 8 bytes
function multiplica_complex8(a, b)
implicit none
complex(8), intent(in) :: a, b
complex(8)
:: multiplica_complex8
multiplica_complex8 = a * b
end function multiplica_complex8
! Function que multiplica lógicos

Versão primeira de janeiro 1999. Versao atual impressa (*.pdf) em 22 de agosto de 2013
Autor: João Batista Aparecido – jbaparecido@dem.feis.unesp.br e jbaparecido@gmail.com

109

Fortran 90/95
function multiplica_logical(a, b)
implicit none
logical, intent(in) :: a, b
logical
:: multiplica_logical
multiplica_logical = a * b
end function multiplica_logical

Rotinas para efetuar divisão
! Function que divide inteiros de 1 byte
function divide_int1(a, b)
implicit none
integer(1), intent(in) :: a, b
integer(1)
:: divide_int1
if(0 == b) then
write(*,*)'Erro fatal, divisão por zero!'
stop
end if
divide_int1 = a / b
end function divide_int1
! Function que divide inteiros de 2 bytes
function divide_int2(a, b)
implicit none
integer(2), intent(in) :: a, b
integer(2)
:: divide_int2
if(0 == b) then
write(*,*)'Erro fatal, divisão por zero!'
stop
end if
divide_int2 = a / b
end function divide_int2
! Function que divide inteiros de 4 bytes
function divide_int4(a, b)
implicit none
integer(4), intent(in) :: a, b
integer(4)
:: divide_int4

if(0 == b) then
write(*,*)'Erro fatal, divisão por zero!'
stop
end if
divide_int4 = a / b
end function divide_int4

Versão primeira de janeiro 1999. Versao atual impressa (*.pdf) em 22 de agosto de 2013
Autor: João Batista Aparecido – jbaparecido@dem.feis.unesp.br e jbaparecido@gmail.com

110

unesp. b) implicit none complex(4). b) implicit none complex(8). b complex(8) :: divide_complex8 Versão primeira de janeiro 1999. divisão por zero!' stop end if divide_real4 = a / b end function divide_real4 ! Function que divide reais de 8 bytes function divide_real8(a. b) implicit none real(8).Fortran 90/95 ! Function que divide reais de 4 bytes function divide_real4(a.feis. b real(4) :: divide_real4 if(0 == b) then write(*.br e jbaparecido@gmail. intent(in) :: a. b complex(4) :: divide_complex4 if(0 == b) then write(*.*)'Erro fatal. intent(in) :: a. b) implicit none real(4). divisão por zero!' stop end if divide_real8 = a / b end function divide_real8 ! Function que divide complexos de 4 bytes function divide_complex4(a.*)'Erro fatal. intent(in) :: a.com 111 .pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. b real(8) :: divide_real8 if(0 == b) then write(*. Versao atual impressa (*. divisão por zero!' stop end if divide_complex4 = a / b end function divide_complex4 ! Function que divide complexos de 8 bytes function divide_complex8(a. intent(in) :: a.*)'Erro fatal.

b integer(1) :: soma_int1 end function soma_int1 ! Function que soma inteiros de 2 bytes function soma_int2(a. intent(in) :: a. b) implicit none integer(2). Versao atual impressa (*.unesp. basta construir um programa que possa usá-las adequadamente. b) implicit none logical. Também vou dotar esta interface de funcionalidade genérica. program lib_demo_sources implicit none !***** Interface genérica para soma ***** interface soma ! Function que soma inteiros de 1 byte function soma_int1(a. sendo invocadas por seus nomes ou pode-se criar uma interface explicita para melhor informar ao compilador sobre a biblioteca.*)'Erro fatal. Para UDTs procede-se da mesma maneira. conforme explicado em capítulos anteriores. Estas rotinas podem ser usadas diretamente.feis. intent(in) :: a. De posse de uma biblioteca de códigos fonte.br e jbaparecido@gmail. b integer(2) :: soma_int2 end function soma_int2 ! Function que soma inteiros de 4 bytes function soma_int4(a. de tal forma a esconder do usuário alguns detalhes internos. b) implicit none integer(1). o conceito de operações para uma UDT abstrata será também abstrato. b logical :: divide_logical divide_logical = a / b end function divide_logical Este é um conjunto de functions para realizar operações aritméticas básicas sobre tipos básicos de dados. divisão por zero!' stop end if divide_complex8 = a / b end function divide_complex8 ! Function que divide lógicos function divide_logical(a.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. Segue abaixo um programa teste para fazer da biblioteca.Fortran 90/95 if(0 == b) then write(*. Também pode-se construir uma interface genérica que tenha funcionalidade genérica. b) implicit none Versão primeira de janeiro 1999. intent(in) :: a. Para utilizar a biblioteca de fontes de uma maneira segura vou prover no programa principal uma interface explicita. Evidentemente.com 112 .

b integer(4) :: soma_int4 end function soma_int4 ! Function que soma reais de 4 bytes function soma_real4(a. intent(in) :: a. Versao atual impressa (*.com 113 . b real(4) :: soma_real4 end function soma_real4 ! Function que soma reais de 8 bytes function soma_real8(a. b) implicit none real(4).Fortran 90/95 integer(4). b) implicit none logical.feis. intent(in) :: a. intent(in) :: a. b integer(1) :: subtrai_int1 end function subtrai_int1 ! Function que subtrai inteiros de 2 bytes function subtrai_int2(a. b logical :: soma_logical end function soma_logical end interface !soma !***** Interface genérica para subtração ***** interface subtrai ! Function que subtrai inteiros de 1 byte function subtrai_int1(a.br e jbaparecido@gmail.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. b complex(8) :: soma_complex8 end function soma_complex8 ! Function que soma lógicos function soma_logical(a. intent(in) :: a. intent(in) :: a. b) implicit none complex(4).unesp. b) implicit none complex(8). b) Versão primeira de janeiro 1999. b) implicit none integer(1). b integer(2) :: subtrai_int2 end function subtrai_int2 ! Function que subtrai inteiros de 4 bytes function subtrai_int4(a. intent(in) :: a. b complex(4) :: soma_complex4 end function soma_complex4 ! Function que soma complexos de 8 bytes function soma_complex8(a. intent(in) :: a. b) implicit none integer(2). intent(in) :: a. b real(8) :: soma_real8 end function soma_real8 ! Function que soma complexos de 4 bytes function soma_complex4(a. b) implicit none real(8).

b) implicit none integer(1). b) implicit none real(8). b integer(4) :: subtrai_int4 end function subtrai_int4 ! Function que subtrai reais de 4 bytes function subtrai_real4(a. intent(in) :: a.feis. intent(in) :: a. b complex(8) :: subtrai_complex8 end function subtrai_complex8 ! Function que subtrai lógicos function subtrai_logical(a. intent(in) :: a.br e jbaparecido@gmail. b real(8) :: subtrai_real8 end function subtrai_real8 ! Function que subtrai complexos de 4 bytes function subtrai_complex4(a. intent(in) :: a. b) implicit none logical. b logical :: subtrai_logical end function subtrai_logical end interface !***** Interface genérica para multiplicação ***** interface multiplica ! Function que multiplica inteiros de 1 byte function multiplica_int1(a.Fortran 90/95 implicit none integer(4). b) implicit none integer(2). intent(in) :: a.unesp. b) implicit none complex(8). b integer(2) :: multiplica_int2 end function multiplica_int2 ! Function que multiplica inteiros de 4 bytes Versão primeira de janeiro 1999.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. intent(in) :: a. intent(in) :: a. b) implicit none complex(4). intent(in) :: a.com 114 . b integer(1) :: multiplica_int1 end function multiplica_int1 ! Function que multiplica inteiros de 2 bytes function multiplica_int2(a. b complex(4) :: subtrai_complex4 end function subtrai_complex4 ! Function que subtrai complexos de 8 bytes function subtrai_complex8(a. b real(4) :: subtrai_real4 end function subtrai_real4 ! Function que subtrai reais de 8 bytes function subtrai_real8(a. b) implicit none real(4). Versao atual impressa (*.

b) implicit none integer(1). intent(in) :: a. b real(4) :: multiplica_real4 end function multiplica_real4 ! Function que multiplica reais de 8 bytes function multiplica_real8(a. b) implicit none complex(4). b) implicit none complex(8). b) implicit none logical. intent(in) :: a. b integer(4) :: multiplica_int4 end function multiplica_int4 ! Function que multiplica reais de 4 bytes function multiplica_real4(a. b logical :: multiplica_logical end function multiplica_logical end interface !***** Interface genérica para divisão ***** interface divide ! Function que divide inteiros de 1 byte function divide_int1(a. b real(8) :: multiplica_real8 end function multiplica_real8 ! Function que multiplica complexos de 4 bytes function multiplica_complex4(a. b complex(4) :: multiplica_complex4 end function multiplica_complex4 ! Function que multiplica complexos de 8 bytes function multiplica_complex8(a. intent(in) :: a.unesp.Fortran 90/95 function multiplica_int4(a.com 115 . b) implicit none real(4). b complex(8) :: multiplica_complex8 end function multiplica_complex8 ! Function que multiplica lógicos function multiplica_logical(a. b integer(2) :: divide_int2 end function divide_int2 Versão primeira de janeiro 1999. Versao atual impressa (*. intent(in) :: a. b) implicit none integer(4). intent(in) :: a.br e jbaparecido@gmail. intent(in) :: a.feis. b) implicit none integer(2). b) implicit none real(8). intent(in) :: a. b integer(1) :: divide_int1 end function divide_int1 ! Function que divide inteiros de 2 bytes function divide_int2(a. intent(in) :: a.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.

real_b8 = 3. cplx_b4 =(3. cplx_c8 logical :: logical_a = .true. intent(in) :: a. real_b4 = 3. int_c2 integer(4) :: int_a4 = 1_4. b real(8) :: divide_real8 end function divide_real8 ! Function que divide complexos de 4 bytes function divide_complex4(a._4. logical_b = ._4. b logical :: divide_logical end function divide_logical end interface !Declaração de variáveis para teste integer(1) :: int_a1 = 1_1. Versao atual impressa (*. intent(in) :: a.3._4). intent(in) :: a.1. b complex(4) :: divide_complex4 end function divide_complex4 ! Function que divide complexos de 8 bytes function divide_complex8(a._8.1.br e jbaparecido@gmail. b) implicit none integer(4). logical_c ! Teste da operações básicas sobre inteiros de 1 byte int_c1 = soma(int_a1._8).. intent(in) :: a. cplx_b8 =(3. intent(in) :: a.Fortran 90/95 ! Function que divide inteiros de 4 bytes function divide_int4(a. b real(4) :: divide_real4 end function divide_real4 ! Function que divide reais de 8 bytes function divide_real8(a. cplx_c4 complex(8) :: cplx_a8 =(1.feis._8). int_c4 real(4) :: real_a4 = 1._8. int_b1) Versão primeira de janeiro 1999. b) implicit none complex(8)._8. int_b4 = 3_4.true._4.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. b integer(4) :: divide_int4 end function divide_int4 ! Function que divide reais de 4 bytes function divide_real4(a._4.3. b) implicit none complex(4). real_c4 real(8) :: real_a8 = 1. b) implicit none logical. real_c8 complex(4) :: cplx_a4 =(1._8. int_b1 = 3_1..unesp. b) implicit none real(8)._4). b complex(8) :: divide_complex8 end function divide_complex8 ! Function que divide lógicos function divide_logical(a. intent(in) :: a. b) implicit none real(4). int_b2 = 3_2. int_c1 integer(2) :: int_a2 = 1_2. int_b1) int_c1 = subtrai(int_a1.com 116 .

da biblioteca e do programa aplicativo. cplx_b8) ! Teste da operações básicas sobre lógicos logical_c = soma(logical_a. Versão primeira de janeiro 1999. cplx_b4) ! Teste da operações básicas sobre complexos de 8 bytes cplx_c8 = soma(cplx_a8. int_b4) ! Teste da operações básicas sobre reais de 4 bytes real_c4 = soma(real_a4. produzindo o arquivo executável. int_b1) ! Teste da operações básicas sobre inteiros de 2 bytes int_c2 = soma(int_a2. real_b8) real_c8 = multiplica(real_a8. int_b4) int_c4 = divide(int_a4. int_b4) int_c4 = multiplica(int_a4.com 117 . int_b1) int_c1 = divide(int_a1. int_b2) int_c2 = multiplica(int_a2. protegendo os códigos fonte e possibilitando o comércio das bibliotecas. real_b4) real_c4 = subtrai(real_a4. real_b4) real_c4 = divide(real_a4. int_b2) int_c2 = subtrai(int_a2. compila-se e linca-se. cplx_b8) cplx_c8 = multiplica(cplx_a8. a partir dos códigos fonte. real_b8) ! Teste da operações básicas sobre complexos de 4 bytes cplx_c4 = soma(cplx_a4. cplx_b4) cplx_c4 = subtrai(cplx_a4. Outra possibilidade é utilizar arquivos objeto produzidos por outros programadores. cplx_b8) cplx_c8 = subtrai(cplx_a8. cplx_b4) cplx_c4 = divide(cplx_a4. 10. logical_b) end program lib_demo_sources De posse de todos os códigos fonte. int_b4) int_c4 = subtrai(int_a4. logical_b) logical_c = subtrai(logical_a. int_b2) ! Teste da operações básicas sobre inteiros de 4 bytes int_c4 = soma(int_a4. int_b2) int_c2 = divide(int_a2. real_b4) real_c4 = multiplica(real_a4. os respectivos arquivos objeto (*. logical_b) logical_c = divide(logical_a.Fortran 90/95 int_c1 = multiplica(int_a1. cplx_b4) cplx_c4 = multiplica(cplx_a4. real_b4) ! Teste da operações básicas sobre reais de 8 bytes real_c8 = soma(real_a8. cplx_b8) cplx_c8 = divide(cplx_a8. real_b8) real_c8 = subtrai(real_a8.br e jbaparecido@gmail.feis.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.2 Bibliotecas de arquivos objeto Uma outra possibilidade para produzir e usar bibliotecas é gerar. Uma vantagem dos arquivos objeto é que eles escondem a implementação dos algoritmos.unesp. Versao atual impressa (*.obj) da biblioteca. logical_b) logical_c = multiplica(logical_a. real_b8) real_c8 = divide(real_a8.

como mostrado abaixo module arithmetic !Biblioteca criado utilizando o conceito de módulo. em realidade um arquivo do tipo (*. e compilar e lincar os códigos fonte da biblioteca.lib). pode-se desenvolver um aplicativo para utilizar aquela biblioteca. Esta denominação deve-se ao fato de que este tipo de biblioteca tem que ser lincada antes do início da execução.lib). Basicamente. implicit none ! Interfaces interface soma module procedure soma_int1 module procedure soma_int2 module procedure soma_int4 module procedure soma_real4 module procedure soma_real8 module procedure soma_complex4 module procedure soma_complex8 module procedure soma_logical end interface interface subtrai module procedure subtrai_int1 module procedure subtrai_int2 module procedure subtrai_int4 module procedure subtrai_real4 module procedure subtrai_real8 module procedure subtrai_complex4 module procedure subtrai_complex8 module procedure subtrai_logical end interface interface multiplica module procedure multiplica_int1 module procedure multiplica_int2 module procedure multiplica_int4 module procedure multiplica_real4 module procedure multiplica_real8 module procedure multiplica_complex4 Versão primeira de janeiro 1999. De posse de um arquivo do tipo (*.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. independente de quem o produziu. 10. ao final basta lincar o arquivo objeto (*. que depende de cada compilador.lib).unesp. basta colocar este arquivos em diretório apropriado. da biblioteca e do aplicativo.obj) do aplicativo com o arquivo da biblioteca (*.br e jbaparecido@gmail. Versao atual impressa (*.4 Bibliotecas utilizando Módulos Uma forma bastante prática de se produzir uma biblioteca é utilizando módulos.feis. Para produzir uma biblioteca estática basta usar as diretivas corretas do compilador.Fortran 90/95 De qualquer maneira.com 118 . 10. coloca-se os códigos fonte em um módulo. O resultado final será uma biblioteca estática. que depende de cada fabricante. então compila-se o programa que está sendo desenvolvido e por fim linca-se todos os arquivos objeto.3 Bibliotecas estáticas O Fortran da suporte ao conceito de bibliotecas estáticas (static library). para produzir o arquivo executável. com arquivos objeto próprios ou de outra procedência.

Fortran 90/95 module procedure multiplica_complex8 module procedure multiplica_logical end interface interface divide module procedure divide_int1 module procedure divide_int2 module procedure divide_int4 module procedure divide_real4 module procedure divide_real8 module procedure divide_complex4 module procedure divide_complex8 module procedure divide_logical end interface contains ! Function que soma inteiros de 1 byte function soma_int1(a. Versao atual impressa (*.feis. b integer(4) :: soma_int4 soma_int4 = a + b end function soma_int4 ! Function que soma reais de 4 bytes function soma_real4(a. intent(in) :: a.br e jbaparecido@gmail. b integer(1) :: soma_int1 soma_int1 = a + b end function soma_int1 ! Function que soma inteiros de 2 bytes function soma_int2(a.unesp. b) implicit none integer(2). intent(in) :: a. b real(4) :: soma_real4 soma_real4 = a + b end function soma_real4 Versão primeira de janeiro 1999. intent(in) :: a. b) implicit none real(4). b integer(2) :: soma_int2 soma_int2 = a + b end function soma_int2 ! Function que soma inteiros de 4 bytes function soma_int4(a. intent(in) :: a. b) implicit none integer(4). b) implicit none integer(1).com 119 .pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.

intent(in) :: a.Fortran 90/95 ! Function que soma reais de 8 bytes function soma_real8(a.b end function subtrai_int1 ! Function que subtrai inteiros de 2 bytes function subtrai_int2(a.unesp. b) implicit none complex(8). intent(in) :: a. b logical :: soma_logical soma_logical = a + b end function soma_logical ! Function que subtrai inteiros de 1 byte function subtrai_int1(a.com 120 . b complex(8) :: soma_complex8 soma_complex8 = a + b end function soma_complex8 ! Function que soma lógicos function soma_logical(a.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. b) implicit none integer(1). intent(in) :: a. b) implicit none Versão primeira de janeiro 1999.feis.br e jbaparecido@gmail. b) implicit none real(8). intent(in) :: a. Versao atual impressa (*. intent(in) :: a. b) implicit none logical. b) implicit none complex(4). b integer(1) :: subtrai_int1 subtrai_int1 = a . b real(8) :: soma_real8 soma_real8 = a + b end function soma_real8 ! Function que soma complexos de 4 bytes function soma_complex4(a. b complex(4) :: soma_complex4 soma_complex4 = a + b end function soma_complex4 ! Function que soma complexos de 8 bytes function soma_complex8(a.

pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.br e jbaparecido@gmail. intent(in) :: a.com 121 . b) implicit none real(8).unesp. Versao atual impressa (*. intent(in) :: a.b end function subtrai_real8 ! Function que subtrai complexos de 4 bytes function subtrai_complex4(a. b integer(4) :: subtrai_int4 subtrai_int4 = a .b Versão primeira de janeiro 1999. intent(in) :: a. b) implicit none complex(4).b end function subtrai_real4 ! Function que subtrai reais de 8 bytes function subtrai_real8(a. b real(8) :: subtrai_real8 subtrai_real8 = a .feis.b end function subtrai_complex4 ! Function que subtrai complexos de 8 bytes function subtrai_complex8(a. b) implicit none complex(8). b) implicit none integer(4). intent(in) :: a.b end function subtrai_int4 ! Function que subtrai reais de 4 bytes function subtrai_real4(a.Fortran 90/95 integer(2). b complex(8) :: subtrai_complex8 subtrai_complex8 = a . intent(in) :: a. intent(in) :: a. b real(4) :: subtrai_real4 subtrai_real4 = a . b) implicit none real(4). b complex(4) :: subtrai_complex4 subtrai_complex4 = a .b end function subtrai_int2 ! Function que subtrai inteiros de 4 bytes function subtrai_int4(a. b integer(2) :: subtrai_int2 subtrai_int2 = a .

b) implicit none Versão primeira de janeiro 1999.b end function subtrai_logical ! Function que multiplica inteiros de 1 byte function multiplica_int1(a. b integer(2) :: multiplica_int2 multiplica_int2 = a * b end function multiplica_int2 ! Function que multiplica inteiros de 4 bytes function multiplica_int4(a. b integer(1) :: multiplica_int1 multiplica_int1 = a * b end function multiplica_int1 ! Function que multiplica inteiros de 2 bytes function multiplica_int2(a. intent(in) :: a. b) implicit none integer(1). b) implicit none real(4). b integer(4) :: multiplica_int4 multiplica_int4 = a * b end function multiplica_int4 ! Function que multiplica reais de 4 bytes function multiplica_real4(a.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.unesp. b) implicit none integer(4).br e jbaparecido@gmail. intent(in) :: a.feis. intent(in) :: a. intent(in) :: a. Versao atual impressa (*. b real(4) :: multiplica_real4 multiplica_real4 = a * b end function multiplica_real4 ! Function que multiplica reais de 8 bytes function multiplica_real8(a.com 122 . b) implicit none logical. b logical :: subtrai_logical subtrai_logical = a . intent(in) :: a.Fortran 90/95 end function subtrai_complex8 ! Function que subtrai lógicos function subtrai_logical(a. b) implicit none integer(2).

b) implicit none complex(4). intent(in) :: a.unesp. intent(in) :: a. b) implicit none integer(1). b) implicit none Versão primeira de janeiro 1999. b) implicit none logical.Fortran 90/95 real(8). b complex(8) :: multiplica_complex8 multiplica_complex8 = a * b end function multiplica_complex8 ! Function que multiplica lógicos function multiplica_logical(a. intent(in) :: a.br e jbaparecido@gmail. b integer(1) :: divide_int1 if(0 == b) then write(*.*)'Erro fatal. Versao atual impressa (*. b logical :: multiplica_logical multiplica_logical = a * b end function multiplica_logical ! Function que divide inteiros de 1 byte function divide_int1(a.feis. b) implicit none complex(8). divisão por zero!' stop end if divide_int1 = a / b end function divide_int1 ! Function que divide inteiros de 2 bytes function divide_int2(a. b real(8) :: multiplica_real8 multiplica_real8 = a * b end function multiplica_real8 ! Function que multiplica complexos de 4 bytes function multiplica_complex4(a. intent(in) :: a.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. b complex(4) :: multiplica_complex4 multiplica_complex4 = a * b end function multiplica_complex4 ! Function que multiplica complexos de 8 bytes function multiplica_complex8(a. intent(in) :: a.com 123 .

divisão por zero!' stop end if divide_int4 = a / b end function divide_int4 ! Function que divide reais de 4 bytes function divide_real4(a. intent(in) :: a.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. intent(in) :: a.feis. b real(8) :: divide_real8 if(0 == b) then write(*. b real(4) :: divide_real4 if(0 == b) then write(*. b integer(4) :: divide_int4 if(0 == b) then write(*.*)'Erro fatal. Versao atual impressa (*. intent(in) :: a. divisão por zero!' stop end if divide_int2 = a / b end function divide_int2 ! Function que divide inteiros de 4 bytes function divide_int4(a. b integer(2) :: divide_int2 if(0 == b) then write(*.Fortran 90/95 integer(2).*)'Erro fatal. b) implicit none real(4).*)'Erro fatal. b) implicit none real(8).unesp.*)'Erro fatal. divisão por zero!' stop end if divide_real4 = a / b end function divide_real4 ! Function que divide reais de 8 bytes function divide_real8(a. divisão por zero!' stop end if divide_real8 = a / b end function divide_real8 Versão primeira de janeiro 1999. b) implicit none integer(4). intent(in) :: a.br e jbaparecido@gmail.com 124 .

unesp.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. intent(in) :: a.Fortran 90/95 ! Function que divide complexos de 4 bytes function divide_complex4(a. por si só é capaz de extrair automaticamente uma interface explicita. Estes arquivos constituem a biblioteca contida dentro de um módulo. intent(in) :: a.not.br e jbaparecido@gmail.*)'Erro fatal. program module_lib_demo_sources use arithmetic Versão primeira de janeiro 1999. b logical :: divide_logical if(. b complex(8) :: divide_complex8 if(0 == b) then write(*. b) implicit none complex(8).mod). divisão por zero!' stop end if divide_complex8 = a / b end function divide_complex8 ! Function que divide lógicos function divide_logical(a. b) implicit none complex(4). divisão por zero!' stop end if divide_logical = a / b end function divide_logical end module arithmetic Este programa fonte acima quando compilado irá produzir um arquivo objeto (*. Neste caso não foi necessário prover uma interface explicita para as rotinas.feis. divisão por zero!' stop end if divide_complex4 = a / b end function divide_complex4 ! Function que divide complexos de 8 bytes function divide_complex8(a.b) then write(*.obj) e um arquivo modulo (*. Versao atual impressa (*. A seguir apresenta-se o aplicativo modificado. que vai utilizar a biblioteca. intent(in) :: a. uma vez que o módulo. b) implicit none logical.*) 'Erro fatal em divide_logical.com 125 .*)'Erro fatal. b complex(4) :: divide_complex4 if(0 == b) then write(*.

1. logical_b) Versão primeira de janeiro 1999. int_c4 real(4) :: real_a4 = 1. cplx_b4 =(3. real_b8) real_c8 = multiplica(real_a8.br e jbaparecido@gmail._4). cplx_b8) cplx_c8 = subtrai(cplx_a8. logical_c ! Teste da operações básicas sobre inteiros de 1 byte int_c1 = soma(int_a1._8. int_b2) int_c2 = subtrai(int_a2. int_b1) int_c1 = multiplica(int_a1. int_b2) int_c2 = divide(int_a2.1._8. real_b4) real_c4 = multiplica(real_a4.unesp. int_b1) int_c1 = divide(int_a1._4. real_b4) real_c4 = subtrai(real_a4.. real_c4 real(8) :: real_a8 = 1._8). int_b2) int_c2 = multiplica(int_a2. cplx_b8) cplx_c8 = multiplica(cplx_a8. int_b1) int_c1 = subtrai(int_a1._4. logical_b = . int_b2) ! Teste da operações básicas sobre inteiros de 4 bytes int_c4 = soma(int_a4. real_b4) ! Teste da operações básicas sobre reais de 8 bytes real_c8 = soma(real_a8._4. real_b8 = 3. cplx_c4 complex(8) :: cplx_a8 =(1._8._8. int_b1 = 3_1. real_b4) real_c4 = divide(real_a4. int_b2 = 3_2. cplx_b4) ! Teste da operações básicas sobre complexos de 8 bytes cplx_c8 = soma(cplx_a8.Fortran 90/95 implicit none !Declaração de variáveis para teste integer(1) :: int_a1 = 1_1._4.3. int_b4) ! Teste da operações básicas sobre reais de 4 bytes real_c4 = soma(real_a4. real_c8 complex(4) :: cplx_a4 =(1.feis. real_b8) real_c8 = subtrai(real_a8. real_b8) ! Teste da operações básicas sobre complexos de 4 bytes cplx_c4 = soma(cplx_a4.3.com 126 . int_c1 integer(2) :: int_a2 = 1_2. real_b8) real_c8 = divide(real_a8._4).pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.true. cplx_b4) cplx_c4 = subtrai(cplx_a4.true. int_b4) int_c4 = multiplica(int_a4. int_b1) ! Teste da operações básicas sobre inteiros de 2 bytes int_c2 = soma(int_a2. cplx_b8 =(3. cplx_b8) ! Teste da operações básicas sobre lógicos logical_c = soma(logical_a. cplx_c8 logical :: logical_a = . int_b4 = 3_4. cplx_b4) cplx_c4 = divide(cplx_a4.. int_b4) int_c4 = subtrai(int_a4. Versao atual impressa (*. int_b4) int_c4 = divide(int_a4. logical_b) logical_c = subtrai(logical_a. int_c2 integer(4) :: int_a4 = 1_4. cplx_b8) cplx_c8 = divide(cplx_a8. cplx_b4) cplx_c4 = multiplica(cplx_a4._8). real_b4 = 3.

Para acessar as informações na biblioteca foi necessário usar a declaração use arithmetic. rule = 2 !Extremo esquerdo do intervalo de integração a = 0._8 Versão primeira de janeiro 1999. No caso do compilador Microsoft basta colocar a seguinte declaração use msimslmd. 03/08/2001 ! program exemplo_imsl !Declaração para acessar a biblioteca use msimslmd. são IMSL (International Mathematical and Statistical Library) e NAG (Numerical Algorithm Group). logical_b) end program module_lib_demo_sources Note-se que neste caso não foi necessário construir no corpo do aplicativo a interface explicita. provavelmente. A que conheço bem e tenho usado desde 1986 é a IMSL. Os seus manuais estão impressos em cinco volumes com alguns milhares de páginas. pelo fato da biblioteca estar inserida dentro de um módulo. !para funções com picos acentuados use rule igual a 1. err_rel. Estas bibliotecas são comercializadas pelo fabricantes. desenvolvidas ao longo de décadas de pesquisas. Abaixo apresenta-se um pequeno exemplo de como efetuar a integração de uma função dada ! Este programa demonstra como utilizar uma dada rotina ! da biblioteca IMSL ! ! O exemplo escolhido é a integração de uma função de uma variável ! ! Programador: joão batista aparecido. res. Esta biblioteca possui mais de mil rotinas científicas nos mais variados ramos da matemática e da estatística. logical_b) logical_c = divide(logical_a. Para utilizar-se destas rotinas. na linha logo após as palavras: program. Versao atual impressa (*. err_abs. only: integral => dqdag implicit none external f integer :: rule real(8) :: f. err_est !Para a maioria das funções use rule igual a 2.feis.unesp. As duas principais bibliotecas científicas. precisa-se estudar os respectivos manuais e as diretivas do compilador para incluí-las. possui grandes bibliotecas de rotinas. subroutine e function.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. a. 10._8 !Extremo direito do intervalo de integração b = 1. A biblioteca NAG também é muito usada.Fortran 90/95 logical_c = multiplica(logical_a. b. neste caso já construída automaticamente. !e para funções oscilatórias use rule = 6.com 127 .4 O uso de bibliotecas comerciais A linguagem Fortran por ser uma das mais antigas em operação contínua e também por ser uma linguagem eminentemente científica.br e jbaparecido@gmail.

pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.br e jbaparecido@gmail.unesp.com 128 . b.d0 return end function f É importante que o usuário leia atentamente os manuais das rotinas. err_rel. err_abs. err_est) ! Impressão da integral e de seu erro estimado write(*. relativo err_abs = 1.*)'Erro estimado da integral = '.d0*dsqrt(1. pois muitas delas são de natureza complexa. rule. e não será difícil cometer erros de julgamento e usar rotinas pensando que se está fazendo uma coisa e em realidade está-se fazendo totalmente outra.feis.Fortran 90/95 !Erros: absoluto. err_est end program exemplo_imsl ! Função a ser integrada function f(x) implicit none real(8) :: x. res write(*.d-10 call integral(f. f f = 3. a. Versão primeira de janeiro 1999.d-10 err_rel = 1. Versao atual impressa (*. res.*)'Resultado da integral = '.d0-x)/2.

um curso apenas de programação seria bastante distinto. Desta forma o encapsulamento dos dados é bastante bom. O contexto matemático do problema em questão não é importante.unesp. Evitou-se totalmente o uso da declaração COMMON. É preciso antes de tudo ter-se uma idéia muito clara das estruturas de dados que serão utilizadas. Versão primeira de janeiro 1999. uma vez que o uso de módulos a substituem com grande vantagem. mas como as linguagens computacionais são usadas para programação computacional é inevitável praticar-se a programação.br e jbaparecido@gmail. Este curso é basicamente de linguagem.Fortran 90/95 CAPÍTULO 11 PROGRAMA EXEMPLO Neste capítulo apresenta-se um programa exemplo. Uma idéia final que gostaria de mencionar é Antes de começar a programar. Muitos tendem a pensar apenas nos métodos esquecendo-se dos dados. mas é uma regra heurística que pode lhe economizar muitas horas de retrabalho para acertar um código no qual as estruturas de dados mudaram no meio do desenvolvimento do projeto. Porém. Fez-se um uso extensivo de módulos.com 129 .feis. nem é muito. Um pouco de código sempre é bom para inspiração. Aliás este é o objetivo quando se aprende uma linguagem. O acesso das rotinas aos dados fez-se através do uso controlado e racional da declaração USE. O importante são a estrutura do programa e as soluções encontradas. Versao atual impressa (*. Procurou-se criar módulos de dados e módulos de rotinas. pense profundamente nos dados envolvidos no algoritmo que se quer implementar.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. Isto não é tudo.

! ! programador: joão batista aparecido.d0 gim = 0.unesp. ! ! o polinomio que define a parede eh do terceiro grau. ! o fluido é modelado como um fluido perfeito devido ao alto número de reynolds ! e também porque tem-se mais interesse sobre o escoamento fora da camada limite.com 130 .eijmn.d0 void = computebijmn() void = computecijmn() void = computedijmn() void = computegim() call dlinrg(m0*m0.m0*m0) call prod_matrix_vector(m0*m0. ! ! programador: joão batista aparecido. ! a condição de contorno na saída da contração é do tipo derivada nula. only : xpos use sist_lin_data use bcdijmn use matrixlib use outputwriting implicit none real(double) :: void void = computeeigenvalues_y() void = computeeigenconstants_y() void = computeeigenvaluessquared_y() void = computeeigenvalues_x() void = computeeigenconstants_x() void = computeeigenvaluessquared_x() void = computeaii() void = computebij() void = computecij() void = computegi() void = basicgrid() void = modifiedgrid() eijmn = 0.Fortran 90/95 program rectangular_contraction ! este programa destina-se a resolver a equação de laplace sobre um domínio ! irregular formado por uma contração.eijmn.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.feis.yq) void = assignyim() void = fieldsstreamfunctionvelsuv() void = axialquantities() Versão primeira de janeiro 1999. ilha solteira. use data_type use global_data use eigenproblem use aiibijcij use msimslmd use grid use velocity_field_data. 11 de março de 2000.m0*m0.br e jbaparecido@gmail. Versao atual impressa (*. 16 de maio de 2000.gim. ilha solteira.eijmn.

Versao atual impressa (*.feis.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.Fortran 90/95 void = averagevelocityu() void = averagevelocityv() void = printing() end program rectangular_contraction Versão primeira de janeiro 1999.br e jbaparecido@gmail.unesp.com 131 .

feis. double = 8 end module data_type !==== module constants use data_type ! ! this module defines common constants that are frequently used.br e jbaparecido@gmail. parameter :: unity = 1. parameter :: pi = 3. long = 4. parameter.unesp. ! ! programmer: joão batista aparecido ! place : ilha solteira ! date : january 19.d0 end module constants !==== Versão primeira de janeiro 1999. parameter :: zero_int = 0_4 real(double).0d0 real(double).com 132 . parameter :: zero_real = 0. public :: short = 2.Fortran 90/95 !==== module data_type ! ! this module defines four integers parameters for using in the definition of ! kinds of integers: short and long.414213562373d0 real(double). single = 4. and two kinds of reals: single and double. Versao atual impressa (*. 2000 ! implicit none save integer(long). ! ! programmer: joão batista aparecido ! place : ilha solteira ! date : january 1. parameter :: root_of_two = 1.141592653589793d0 real(double). 2000 ! implicit none save integer(2).pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.

eigenfunctions_y real(double). dimension(m0) :: eigenvalues_y.25d0 real(double). parameter :: l1 = 1.feis. dimension(m0) :: eigenvalues_x. eigenfunctions_x real(double). eigenconstants_y real(double). dimension(m0) :: eigenvaluessquared_x. parameter :: l2 = 3. gi real(double).pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.0d0 real(double).d0 real(double). dimension(m0) :: eigenfunctions_ydrv_y. dimension(m0) :: eigenfunctions_xdrv_x real(double). dimension(m0.m0) :: bij. eigenconstants_x real(double). dimension(m0) :: aii.Fortran 90/95 module global_data use data_type ! ! this module define the main global variables. dimension(m0) :: eigenvaluessquared_y. parameter :: l3 = 0. 2000 ! implicit none save ! number of terms in the series integer(long). parameter :: m0 = 10 ! number of terms in the series ! characteristic lengths real(double). Versao atual impressa (*. cij end module global_data Versão primeira de janeiro 1999.br e jbaparecido@gmail. ! ! programmer: joão batista aparecido ! place : ilha solteira ! date : march 11.unesp. eigenfunctions_ydrv_x real(double).com 133 .

Fortran 90/95 module sist_lin_data use data_type use constants use global_data. only : m0 implicit none save real(double).m0) :: yim end module sist_lin_data Versão primeira de janeiro 1999.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.com 134 .br e jbaparecido@gmail. dimension(m0*m0. dimension(m0*m0) :: yq real(double).feis.unesp. dimension(m0*m0) :: gim real(double). m0*m0) :: eijmn real(double). dimension(m0. Versao atual impressa (*.

Versao atual impressa (*. vw.Fortran 90/95 module velocity_field_data use data_type implicit none save ! number of nodes in each direction integer(long). uav. ypos end module velocity_field_data Versão primeira de janeiro 1999. parameter :: mx = 101. psi.feis. p0. dimension(my. uw. v0. pw.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. xpos.com 135 .mx) :: u. vav real(double). p. dimension(mx) :: x_axis.br e jbaparecido@gmail. u0. my = 101 real(double).unesp. v.

b_vector) implicit none integer(long) :: i.c_vector) Versão primeira de janeiro 1999.b_vector.a_matrix.a_vector.Fortran 90/95 module matrixlib use data_type use constants implicit none contains !ccccccccccccccccccccccccc !c this routine setts a vector to zero !c========================== subroutine zero_vector(n_vec. Versao atual impressa (*.a_vector. b_vector and return in c_vector !c========================== subroutine add_vector(n_vec.feis. b_vector.unesp.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.n_vec a_vector(i) = zero_real end do return end subroutine zero_vector !ccccccccccccccccccccccccc !c this routine adds two vector a_vector. dimension(n_vec) :: a_vector do i=1.n_vec c_vector(i)=a_vector(i)+b_vector(i) end do return end subroutine add_vector !ccccccccccccccccccccccccc !c this routine equal vector a_vector toa vector b_vector !c========================== subroutine equal_vector(n_vec. dimension(n_vec) :: a_vector. n_vec real(double).b_vector. c_vector do i=1.br e jbaparecido@gmail.n_vec b_vector(i)=a_vector(i) end do return end subroutine equal_vector !ccccccccccccccccccccccccc !c this routine does the product of a square matrix a_matrix by a !c vector b_vector and return in a c_vector !c========================== subroutine prod_matrix_vector(n_vec. dimension(n_vec) :: a_vector. n_vec real(double).com 136 . n_vec real(double). a_vector) implicit none integer(long) :: i.c_vector) implicit none integer(long) :: i.b_vector do i=1.

Versao atual impressa (*. j.Fortran 90/95 implicit none integer(long) :: i. dimension(n_vec) :: b_vector.n_vec) :: a_matrix do i=1.n_vec c_vector(i)=0. c_vector real(double).a_vector.n_vec c_vector(i) = zero_real do j=1. n_vec real(double).d0 do j=1. b_vector prod = zero_real do i = 1.n_vec) :: a_matrix do i=1.br e jbaparecido@gmail.prod) implicit none integer(long) :: i.n_vec c_vector(i)=c_vector(i)+a_matrix(j. dimension(n_vec) :: a_vector.n_vec prod = prod+a_vector(i)*b_vector(i) end do return end subroutine prod_int_vector !ccccccccccccccccccccccccc !c this routine does the product of a transpose square matrix a_matrix !c by a vector b_vector and return in a c_vector !c========================== subroutine prod_trans_matrix_vector(n_vec.com 137 . dimension(n_vec) :: b_vector. n_vec real(double) :: prod real(double).j)*b_vector(j) end do end do return end subroutine prod_matrix_vector !ccccccccccccccccccccccccc !c this routine does the iner product of a vector a_vector by a !c vector b_vector and return prod !c========================== subroutine prod_int_vector(n_vec.b_vector.n_vec c_vector(i)=c_vector(i)+a_matrix(i. c_vector real(double).unesp. dimension(n_vec.feis.i)*b_vector(j) end do end do return end subroutine prod_trans_matrix_vector !ccccccccccccccccccccccccc !c this routine does the product of a diagonal square matrix a_matrix Versão primeira de janeiro 1999.c_vector) implicit none integer(long) :: i.a_matrix. j. n_vec real(double).b_vector. dimension(n_vec.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.

unesp.const.a_vector) implicit none integer(long) :: i. Versao atual impressa (*. dimension(n_vec) :: a_vector do i=1.br e jbaparecido@gmail. n_vec Versão primeira de janeiro 1999. dimension(n_vec) :: a_vector n=n_vec/2 do i=1. n.a_vector) implicit none integer(long) :: i. dimension(n_vec) :: a_matrix.a_matrix. n_vec complex(double) :: aux complex(double). n_vec real(double).Fortran 90/95 !c (stored in vector form) by a vector b_vector and return in a c_vector !c========================== subroutine prod_diag_matrix_vector(n_vec.n_vec c_vector(i)=a_matrix(i)*b_vector(i) end do return end subroutine prod_diag_matrix_vector !ccccccccccccccccccccccccc !c this routine multiply a vector a_vector by -1.n_vec a_vector(i) = -a_vector(i) end do return end subroutine oposite_vector !ccccccccccccccccccccccccc !c this routine invert the order of elements in a vector !c========================== subroutine reverse_vector(n_vec.feis. c_vector do i=1. b_vector.n aux=a_vector(i) a_vector(i)=a_vector(n_vec-i+1) a_vector(n_vec-i+1)=aux end do return end subroutine reverse_vector !ccccccccccccccccccccccccc !c this routine shifts the elements of vector by a constant !c========================== subroutine shift_vector(n_vec.com 138 .a_vector) implicit none integer(long) :: i. n_vec real(double).c_vector) implicit none integer(long) :: i.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.b_vector. !c========================== subroutine oposite_vector(n_vec.

j.n_vec-j+1) a_matrix(i.n_vec aux = a_matrix(i. n_vec complex(double) aux complex(double). n_vec Versão primeira de janeiro 1999.n_vec write(*. j.n_vec-j+1) = aux end do end do return end subroutine reverse_matrix !ccccccccccccccccccccccccc !c this routine prints a given matrix by columns !c========================== subroutine print_matrix(n_vec.a_matrix(i.j) = a_matrix(i. n. j.unesp.n_vec) :: a_matrix do j=1.n do i = 1.n_vec a_vector(i)=a_vector(i)+const end do return end subroutine shift_vector !ccccccccccccccccccccccccc !c this routine invert the order of columns in a matrix !c========================== subroutine reverse_matrix(n_vec. Versao atual impressa (*.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.dimension(n_vec.*)i.j) a_matrix(i.n_vec) :: a_matrix n = n_vec/2 do j = 1.n_vec write(*.a_matrix) implicit none integer(long) :: i. j. dimension(n_vec) :: a_vector do i=1.Fortran 90/95 real(double) :: const real(double).j) end do end do return end subroutine print_matrix !ccccccccccccccccccccccccc !c this routine prints a given matrix in a full form !c========================== subroutine print_matrix2(n_vec. n_vec real(double).br e jbaparecido@gmail.feis.com 139 .a_matrix) implicit none integer(long) :: i.*) do i=1.a_matrix) implicit none integer(long) :: i. dimension(n_vec.

n_vec write(*.*)(a_vector(j). dimension(n_vec.feis.n_vec) :: a_matrix do i=1.n_vec) return end subroutine print_vector end module matrixlib Versão primeira de janeiro 1999.n_vec) end do 100 format(1x.4(f11.j).2x)) return end subroutine print_matrix2 !ccccccccccccccccccccccccc !c this routine prints a given vector !c========================== subroutine print_vector(n_vec.Fortran 90/95 real(double).j=1.a_vector) implicit none integer(long) :: j. dimension(n_vec) :: a_vector write(*.unesp. Versao atual impressa (*.i2.br e jbaparecido@gmail.com 140 .(a_matrix(i. n_vec real(double).100)i.5.2x.j=1.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.

d0*eigenvalues_y(i)*eigenvalues_y(j)/ & (eigenvaluessquared_y(i)-eigenvaluessquared_y(j)) if((i+j)/2*2 /= (i+j)) bij(i. m0 do j = 1.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.unesp. eigenvalues_y. m0 aii(i) = unity end do ! diagonal elements equal to unity computeaii = unity end function computeaii !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computebij() use global_data. since aij is ! a diagonal matrix it is stored as a vector.d0*eigenvaluessquared_y(i))/12. m0 do j = 1.d0 + 4.feis. eigenvaluessquared_y integer(long) :: i.Fortran 90/95 module aiibijcij use data_type use constants ! this module is designed to compute the matrix aij. m0 if(i == j) then cij(i. bij. eigenvaluessquared_y integer(long) :: i.bij(i. eigenvalues_y. aii integer(long) :: i real(double) :: computeaii do i = 1. only : m0. j real(double) :: computecij do i = 1.br e jbaparecido@gmail.j) end if end do end do computebij = unity end function computebij !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computecij() use global_data. cij.com 141 . Versao atual impressa (*.j) = zero_real else bij(i.j) = 4.j) = -(3. m0 if(i == j) then bij(i. bij and cij.j) = . only : m0. j real(double) :: computebij do i = 1. only : m0.d0 Versão primeira de janeiro 1999. implicit none contains !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computeaii() use global_data.

cij(i. gi. only : m0. eigenvalues_y integer(long) :: i real(double) :: computegi do i = 1.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. Versao atual impressa (*.j) end if end do end do computecij = unity end function computecij !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computegi() use global_data.j) = -2.Fortran 90/95 else cij(i.j) = .unesp.feis.com 142 .d0*eigenvalues_y(i)*eigenvalues_y(j)/ & (eigenvaluessquared_y(i)-eigenvaluessquared_y(j))**2 if((i+j)/2*2 /= (i+j)) cij(i.br e jbaparecido@gmail. m0 gi(i) = -root_of_two/eigenvalues_y(i) !gi(i) = root_of_two/eigenvalues_y(i) if(i/2*2 /= i ) gi(i) = -gi(i) end do computegi = unity end function computegi end module aiibijcij Versão primeira de janeiro 1999.

j real(double) :: computecij_x. bij use wall_functions. only : p.unesp. x. cij.j)*(aux1**2) else computecij_x = cij(i.d0*aux1*aux1 aux4 = -aux2 + 3. eigenvaluessquared_y use wall_functions. dpx.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.com 143 . aux3. px. only : i. only : m0.d0*aux1*aux1 if(i == j) then computecij_x = cij(i. px. aux1 ! computing p(x) and its derivative px = p(x) dpx = deriv_p(x) aux1 = dpx/px ! filling the forth quarter if(i == j) then computebij_x = zero_real else computebij_x = bij(i.j)* & ! (eigenvaluessquared_y(j)*aux3 . deriv_p. x. only : p.feis. aux1. deriv2nd_p use ijmn_transfer. Versao atual impressa (*. j real(double) :: computebij_x.Fortran 90/95 module aiibijcij_x use data_type use constants implicit none contains !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computebij_x(x) use global_data. only : m0. aux4 ! computing p(x) and its derivative px = p(x) dpx = deriv_p(x) d2px = deriv2nd_p(x) aux1 = dpx/px aux2 = d2px/px aux3 = aux2 + aux1*aux1 !aux4 = aux2 + 3.j)*aux1 end if end function computebij_x !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computecij_x(x) use global_data. only : i. deriv_p use ijmn_transfer. aux2.eigenvaluessquared_y(i)*aux4) (eigenvaluessquared_y(j)*aux3 + eigenvaluessquared_y(i)*aux4) end if end function computecij_x Versão primeira de janeiro 1999. dpx. d2px.br e jbaparecido@gmail.

x. Versao atual impressa (*. only : m0. only : i implicit none real(double) :: computegi_x. px.com 144 .feis. dpx.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. h ! computing p(x) and its derivative px = p(x) dpx = deriv_p(x) d2px = deriv2nd_p(x) h = (d2px-2. deriv_p. gi use wall_functions.unesp. only : p.br e jbaparecido@gmail.Fortran 90/95 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computegi_x(x) use global_data.d0*(dpx**2)/px)/dsqrt(px) !!!!!!!!verificar computegi_x = h*gi(i) end function computegi_x end module aiibijcij_x Versão primeira de janeiro 1999. deriv2nd_p use ijmn_transfer. d2px.

errest. errabs.m0 jconta=jconta+1 !if(jconta. bij. result iconta=0 Versão primeira de janeiro 1999. only : fc integer(long) :: iconta.l2. l2.d-6 errel=0.lt.br e jbaparecido@gmail.irule.errabs. irule real(double) :: computebijmn. only : m0.jconta) + result !eijmn(jconta.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.unesp.feis. errel. jconta. irule real(double) :: computecijmn.Fortran 90/95 module bcdijmn use data_type use constants implicit none contains !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computebijmn() use global_data. Versao atual impressa (*. bij.d0. errel. only : computecij_x use ijmn_transfer use sist_lin_data. eigenvalues_y.m0 iconta=iconta+1 jconta=0 do j=1.d0 irule=6 ! call dqdag(fb.0.m0 do m=1. result iconta=0 do i=1. l2. errest. eigenvaluessquared_y use aiibijcij_x.errel.m0 do n=1. only : fb integer(long) :: iconta. eigenvalues_y.iconta) cycle ! errabs=1. jconta.result.jconta) = eijmn(iconta.errest) ! eijmn(iconta.jconta) end do end do end do end do computebijmn = unity return end function computebijmn !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computecijmn() use global_data.com 145 . only : eijmn use fbfcfd. only : eijmn use fbfcfd. eigenvaluessquared_y use aiibijcij_x.iconta)=eijmn(iconta. only : computebij_x use ijmn_transfer use sist_lin_data. errabs. only : m0.

m0 jconta=jconta+1 !if(jconta. only : fd integer(long) :: iconta.d-6 errel=0.m0 do m=1.errabs.lt.unesp. eigenvaluessquared_y.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.errest) eijmn(iconta. only : eijmn use fbfcfd. irule real(double) :: computedijmn.errabs. errabs. l2.0.m0 do n=1. errel.m0 iconta=iconta+1 jconta=0 do j=1.errel.l2. result iconta=0 do i=1. only : m0. eigenvaluessquared_x use aiibijcij_x.l2.jconta) end do end do end do end do computecijmn = unity return end function computecijmn !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computedijmn() use global_data. bij.iconta)=eijmn(iconta.jconta) + result !eijmn(jconta.result.com 146 . errest.jconta) = eijmn(iconta.m0 do n=1.jconta) = eijmn(iconta.br e jbaparecido@gmail.errest) ! eijmn(iconta.iconta) cycle ! errabs=1.d0 irule=6 ! call dqdag(fc.m0 jconta=jconta+1 !if(jconta.lt.irule.irule.errel.m0 do m=1.0.m0 iconta=iconta+1 jconta=0 do j=1.result.feis.d0. jconta.iconta) cycle ! errabs=1. Versao atual impressa (*. only : computecij_x use ijmn_transfer use sist_lin_data.iconta)=eijmn(iconta.jconta) .Fortran 90/95 do i=1.d0 irule=6 ! if(i == j) then call dqdag(fd.& eigenvaluessquared_y(i)*result !eijmn(jconta.d-6 errel=0.jconta) end if Versão primeira de janeiro 1999.d0.

br e jbaparecido@gmail.m0 do m=1. Versao atual impressa (*.feis. only : m0 use sist_lin_data. only : fg integer(long) :: iconta. l2.com 147 .Fortran 90/95 if((m == n). errel.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.m0 do m=1. eigenvalues_y.jconta) .unesp.eigenvaluessquared_x(m) end if end do end do end do end do computedijmn = unity return end function computedijmn !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computegim() use global_data.d0. yim integer(long) :: i.d0 irule=6 ! call dqdag(fg. irule real(double) :: computegim.(i==j)) then eijmn(iconta.and. m. only : computegi_x use ijmn_transfer use sist_lin_data. only : gim use fbfcfd.0.m) = yq(iconta) Versão primeira de janeiro 1999. bij. iconta real(double) :: assignyim iconta = 0 do i=1.irule.m0 iconta = iconta + 1 ! errabs=1.d-6 errel=0. only : m0.l2.jconta) = eijmn(iconta. result iconta = 0 do i=1.errabs.errest) ! gim(iconta) = result end do end do computegim = unity return end function computegim !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function assignyim() use global_data.result.m0 iconta = iconta + 1 ! yim(i. errest. eigenvaluessquared_y use aiibijcij_x. only : yq.errel. errabs.

feis.br e jbaparecido@gmail.unesp.com 148 .pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.Fortran 90/95 ! end do end do assignyim = unity return end function assignyim end module bcdijmn Versão primeira de janeiro 1999. Versao atual impressa (*.

only : m0. eigenvaluessquared_y use constants ! this function compute the eigenvalues squared implicit none integer(long) :: i real(double) :: computeeigenvaluessquared_y do i = 1.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.unesp.feis. eigenvalues_y use constants. only : pi ! this function compute the eigenvalues_y implicit none integer(long) :: i real(double) :: computeeigenvalues_y do i = 1. eigenvalues_y.Fortran 90/95 module eigenproblem use data_type use constants. eigenconstants_y use constants ! this function compute the eigenconstants implicit none integer(long) :: i Versão primeira de janeiro 1999. only : m0. only : m0.br e jbaparecido@gmail. Versao atual impressa (*.com 149 . m0 ! compute the eigenvalues squared eigenvaluessquared_y(i) = eigenvalues_y(i)*eigenvalues_y(i) end do computeeigenvaluessquared_y = unity ! return value to the main program return end function computeeigenvaluessquared_y !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computeeigenconstants_y() use global_data. only : unity implicit none contains !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computeeigenvalues_y() use global_data. m0 eigenvalues_y(i) = real(i)*pi end do ! compute the eigenvalues computeeigenvalues_y = unity ! return value to the main program return end function computeeigenvalues_y !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computeeigenvaluessquared_y() use global_data.

y) use global_data. px px = p(x) ! compute the wall position do i = 1.y) use global_data. only : m0.Fortran 90/95 real(double) :: computeeigenconstants_y do i = 1. eigenvalues_y. only : m0. Versao atual impressa (*. only : p ! this function computes the eigenfunctions implicit none integer(long) :: i real(double) :: computeeigenfunctions_y. only : p ! this function computes the eigenfunctions derivatives regarding y-axis implicit none integer(long) :: i real(double) :: computeeigenfunctions_ydrv_y. m0 eigenconstants_y(i) = root_of_two end do ! compute the eigenconstants computeeigenconstants_y = unity ! return value to the main program return end function computeeigenconstants_y !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computeeigenfunctions_y(x. eigenconstants_y use constants. only : unity use wall_functions.br e jbaparecido@gmail. eigenfunctions_y. x.com 150 .y) eigenfunctions_ydrv_y(i) = eigenconstants_y(i)*eigenvalues_y(i)* & dcos(eigenvalues_y(i)*y/px)/(px*dsqrt(px)) end do computeeigenfunctions_ydrv_y = unity ! return value to the main program return Versão primeira de janeiro 1999. eigenconstants_y use constants. only : unity use wall_functions.feis. x. y. eigenvalues_y.y) eigenfunctions_y(i) = eigenconstants_y(i)*dsin(eigenvalues_y(i)*y/px)/dsqrt(px) end do computeeigenfunctions_y = unity ! return value to the main program return end function computeeigenfunctions_y !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computeeigenfunctions_ydrv_y(x. m0 ! compute the eigenfunctions y-derivative at the position (x. m0 ! compute the eigenfunctions at the position (x.unesp. px px = p(x) ! compute the wall position do i = 1.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. y. eigenfunctions_ydrv_y.

px. only : m0.feis. only : m0.y) use global_data.br e jbaparecido@gmail.unesp.d0*l2) ! compute the eigenvalues end do computeeigenvalues_x = unity ! return value to the main program return end function computeeigenvalues_x !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computeeigenvaluessquared_x() use global_data. only : unity ! this function compute the eigenvalues squared implicit none integer(long) :: m Versão primeira de janeiro 1999.Fortran 90/95 end function computeeigenfunctions_ydrv_y !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computeeigenfunctions_ydrv_x(x.com 151 . eigenconstants_y use constants use wall_functions. dpx px = p(x) dpx = deriv_p(x) ! compute the wall position p(x) ! compute derivative of p(x) do i = 1.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. only : pi. deriv_p ! this function computes the eigenfunctions derivatives regarding x-axis implicit none integer(long) :: i real(double) :: computeeigenfunctions_ydrv_x. only : m0. eigenvalues_y. eigenvalues_x.d0)*(2. unity ! this function compute the eigenvalues implicit none integer(long) :: m real(double) :: computeeigenvalues_x do m = 1. eigenvalues_x. Versao atual impressa (*. m0 eigenvalues_x(m) = real(2*m-1)*pi/(2. y.y) eigenfunctions_ydrv_x(i)=-(eigenconstants_y(i)/2. m0 ! compute the eigenfunctions x-derivative at the position (x. eigenfunctions_ydrv_x. only : p. x. l2 use constants.d0*y*eigenvalues_y(i)* & dcos(eigenvalues_y(i)*y/px)+px*dsin(eigenvalues_y(i)*y/px))*dpx/ & ((px**2)*dsqrt(px)) end do computeeigenfunctions_ydrv_x = unity ! return value to the main program return end function computeeigenfunctions_ydrv_x !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computeeigenvalues_x() use global_data. eigenvaluessquared_x use constants.

feis. m0 ! compute the eigenvalues squared eigenvaluessquared_x(m) = eigenvalues_x(m)*eigenvalues_x(m) end do computeeigenvaluessquared_x = unity ! return value to the main program return end function computeeigenvaluessquared_x !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computeeigenconstants_x() use global_data. only : root_of_two. only : m0. eigenconstants_x use constants. unity ! this function computes the eigenfunctions implicit none integer(long) :: m real(double) :: x. only : m0. eigenfunctions_xdrv_x.Fortran 90/95 real(double) :: computeeigenvaluessquared_x do m = 1. eigenfunctions_x. eigenconstants_x use constants.com 152 .y) eigenfunctions_x(m) = eigenconstants_x(m)*dsin(eigenvalues_x(m)*x) end do computeeigenfunctions_x = unity return end function computeeigenfunctions_x !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computeeigenfunctions_xdrv_x(x) use global_data. computeeigenfunctions_x do m = 1. Versao atual impressa (*. l2. unity ! this function compute the eigenconstants implicit none integer(long) :: m real(double) :: computeeigenconstants_x do m = 1. l2. only : m0. eigenvalues_x. m0 ! compute the eigenfunctions at the position (x.unesp. m0 eigenconstants_x(m) = root_of_two/dsqrt(l2) ! compute the eigenconstants end do computeeigenconstants_x = unity ! return value to the main program return end function computeeigenconstants_x !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function computeeigenfunctions_x(x) use global_data. only : root_of_two. & eigenconstants_x Versão primeira de janeiro 1999.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. eigenvalues_x.br e jbaparecido@gmail.

x) use global_data. Versao atual impressa (*.com 153 . l2.Fortran 90/95 use constants. eigenvalues_x.br e jbaparecido@gmail. only : unity ! this function computes the eigenfunctions derivatives regarding y-axis implicit none integer(long) :: m real(double) :: computeeigenfunctions_xdrv_x. eigenvalues_x. only : m0.y) eigenfunctions_x_v2 = eigenconstants_x(m)*dsin(eigenvalues_x(m)*x) return end function eigenfunctions_x_v2 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function eigenfunctions_xdrv_x_v2(m.x) use global_data. m0 ! compute the eigenfunctions x-derivative at the position (x) eigenfunctions_xdrv_x(m) = eigenconstants_x(m)*eigenvalues_x(m)* & dcos(eigenvalues_x(m)*x) end do computeeigenfunctions_xdrv_x = unity return end function computeeigenfunctions_xdrv_x !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function eigenfunctions_x_v2(m. eigenconstants_x ! this function computes the eigenfunctions implicit none integer(long) :: m real(double) :: x.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. x ! compute the eigenfunctions x-derivative at the position (x) eigenfunctions_xdrv_x_v2 = eigenconstants_x(m)*eigenvalues_x(m)* & dcos(eigenvalues_x(m)*x) return end function eigenfunctions_xdrv_x_v2 end module eigenproblem Versão primeira de janeiro 1999.unesp. only : m0. eigenconstants_x use constants ! this function computes the eigenfunctions derivatives regarding y-axis implicit none integer(long) :: m real(double) :: eigenfunctions_xdrv_x_v2. x do m = 1. eigenfunctions_x_v2 ! compute the eigenfunctions at the position (x.feis.

pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. eigenfunctions_xdrv_x_v2 implicit none real(double) :: x.n use aiibijcij_x. only : m.x)*eigenfunctions_xdrv_x_v2(n.unesp. only : eigenfunctions_x_v2 use wall_functions.x)/(p(x)**2) end function fd !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function fg(x) use ijmn_transfer use eigenproblem. only : p implicit none real(double) :: x.br e jbaparecido@gmail.x)*eigenfunctions_x_v2(n.x) end function fc !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function fd(x) use ijmn_transfer use eigenproblem. fb fb = computebij_x(x)*eigenfunctions_x_v2(m. fd fd = eigenfunctions_x_v2(m. only : computebij_x use eigenproblem.Fortran 90/95 module fbfcfd use data_type use constants implicit none contains !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function fb(x) use ijmn_transfer.x) end function fb !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function fc(x) use ijmn_transfer use aiibijcij_x. fc fc = computecij_x(x)*eigenfunctions_x_v2(m. only : eigenfunctions_x_v2. only : computecij_x use eigenproblem. only : computegi_x implicit none real(double) :: x. only : eigenfunctions_x_v2 use wall_functions. only : eigenfunctions_x_v2 implicit none real(double) :: x. only : p use aiibijcij_x. fg Versão primeira de janeiro 1999.x)*eigenfunctions_x_v2(n.feis.com 154 . Versao atual impressa (*.

x) end function fg end module fbfcfd Versão primeira de janeiro 1999.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.unesp. Versao atual impressa (*.Fortran 90/95 fg = computegi_x(x)*eigenfunctions_x_v2(m.com 155 .feis.br e jbaparecido@gmail.

ypos integer(long) :: i. my. only : mx. only : eigenfunctions_ydrv_y.mx xpos(i.j)) end do end do modifiedgrid = unity return end function modifiedgrid !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function fieldsstreamfunctionvelsuv() use velocity_field_data. only : mx. only : mx.my do j = 1. j real(double) :: basicgrid.j) = xpos(i. xpos. only : eigenfunctions_y. ypos use velocity_field_data. v use global_data.j) = y end do end do basicgrid = unity return end function basicgrid !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function modifiedgrid() use velocity_field_data. only : l2 use wall_functions. only : m0 use global_data. u. ypos use global_data.j) = ypos(i.unesp. mx x = real(j-1)/real(mx-1) xpos(i.Fortran 90/95 module grid use data_type use constants implicit none contains !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function basicgrid() use velocity_field_data. Versao atual impressa (*.j)*p(xpos(i.com 156 . xpos. my.j) = x ypos(i. only : psi.br e jbaparecido@gmail. x. only : p integer(long) :: i.j)*l2 ypos(i. my. xpos. eigenfunctions_x use global_data.feis.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. my y = real(i-1)/real(my-1) do j = 1. eigenfunctions_ydrv_x Versão primeira de janeiro 1999. y do i = 1. j real(double) :: modifiedgrid do i = 1.

1. px. only : computeeigenfunctions_y. xpos use velocity_field_data. -1 do m = m0.t) = soma_psi + y/px u(s.br e jbaparecido@gmail.my do t = 1.m)*(eigenfunctions_ydrv_x(i)*eigenfunctions_x(m)+& eigenfunctions_y(i)*eigenfunctions_xdrv_x(m)) end do end do psi(s. i. -1 soma_psi = soma_psi + yim(i. Versao atual impressa (*.m)*eigenfunctions_ydrv_y(i)*eigenfunctions_x(m) soma_v = soma_v+yim(i.t) = soma_u + 1. deriv_p use sist_lin_data. soma_u.com 157 . only : computeeigenfunctions_xdrv_x integer(long) :: s.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.feis. only : p. only : u.t) = -soma_v + y*dpx/(px**2) end do end do fieldsstreamfunctionvelsuv = unity end function fieldsstreamfunctionvelsuv !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function axialquantities() use velocity_field_data. only : mx.d0 do i = m0.y) void = computeeigenfunctions_x(x) void = computeeigenfunctions_ydrv_y(x. dpx real(double) :: soma_psi. only : yim use eigenproblem. v Versão primeira de janeiro 1999. m real(double) :: fieldsstreamfunctionvelsuv. x .Fortran 90/95 use global_data.d0 soma_u = 0. void.d0/px v(s. t.t) y = ypos(s. computeeigenfunctions_x use eigenproblem. 1. soma_v do s = 1.unesp. y.t) px = p(x) dpx = deriv_p(x) void = computeeigenfunctions_y(x.y) void = computeeigenfunctions_ydrv_x(x. my. only : eigenfunctions_xdrv_x use wall_functions. computeeigenfunctions_ydrv_x use eigenproblem.mx x = xpos(s.m)*eigenfunctions_y(i)*eigenfunctions_x(m) soma_u = soma_u + yim(i.d0 soma_v = 0.y) void = computeeigenfunctions_x(x) soma_psi = 0. only : computeeigenfunctions_ydrv_y.

Versao atual impressa (*.aux_uav. px. delta_y.t) v0(t) = v(1. my. vw.t) end do call simpson(my.v0(t)*v0(t) uw(t) = u(my.t) px = p(x) delta_y = px/real(my-1) do s = 1. result real(double). x.unesp. my. only : u.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. only : uw.result) uav(t) = result/px end do averagevelocityu = unity end function averagevelocityu !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function averagevelocityv() use velocity_field_data.com 158 . xpos use velocity_field_data. dimension(my) :: aux_uav do t = 1.uw(t)*uw(t) . uav use wall_functions. vav Versão primeira de janeiro 1999.t) x_axis(t) = x u0(t) = u(1. p0. u0. v0. t real(double) :: averagevelocityu.t) p0(t) = unity .vw(t)*vw(t) end do axialquantities = unity end function axialquantities !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function averagevelocityu() use velocity_field_data.mx x = xpos(1.t) pw(t) = unity . x do t = 1. x_axis integer(long) :: t real(double) :: axialquantities.feis. only : mx. only : mx.delta_y.Fortran 90/95 use velocity_field_data. xpos use velocity_field_data.t) vw(t) = v(my.u0(t)*u0(t) . only : v. only : p use integrationlib. my aux_uav(s) = u(s.br e jbaparecido@gmail. pw.mx x = xpos(1. only : simpson integer(long) :: s.

only : p use integrationlib.t) px = p(x) delta_y = px/real(my-1) do s = 1. my aux_vav(s) = v(s. dimension(my) :: aux_vav do t = 1.mx x = xpos(1. t real(double) :: averagevelocityv.unesp.result) vav(t) = result/px end do averagevelocityv = unity end function averagevelocityv end module grid Versão primeira de janeiro 1999.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.com 159 . px.delta_y. delta_y. x. result real(double).Fortran 90/95 use wall_functions.t) end do call simpson(my.br e jbaparecido@gmail. only : simpson integer(long) :: s.feis.aux_vav. Versao atual impressa (*.

m.pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.unesp. Versao atual impressa (*. n end module ijmn_transfer Versão primeira de janeiro 1999. j.br e jbaparecido@gmail.feis.Fortran 90/95 module ijmn_transfer use data_type implicit none save integer(long) :: i.com 160 .

Fortran 90/95
module integrationlib
implicit none
contains
!=========================
! this routine computes a integral algorithm using simpson's rule...
!====================
subroutine simpson(n,vet,delta,result)
use data_type
use constants
implicit none
integer(long) :: i, n !n must be odd.
real(double) :: delta, result, summ, summ2, summ4
real(double), dimension(n) :: vet
summ2=zero_real
summ4=zero_real
do i=2,n-1,2
summ4=summ4+vet(i)
end do
do i=3,n-2,2
summ2=summ2+vet(i)
end do
summ=vet(1)+4.d0*summ4+2.d0*summ2+vet(n)
result=delta*summ/3.d0
return
end subroutine simpson
end module integrationlib

Versão primeira de janeiro 1999. Versao atual impressa (*.pdf) em 22 de agosto de 2013
Autor: João Batista Aparecido – jbaparecido@dem.feis.unesp.br e jbaparecido@gmail.com

161

Fortran 90/95
module outputwriting
use data_type
use constants
contains
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
function printing()
use velocity_field_data, only : u, v, psi, mx, my, xpos, ypos
use velocity_field_data, only : uw, vw, pw, u0, v0, p0, uav, vav, x_axis
use wall_functions
use global_data, only : l2

implicit none
integer(long) :: s, t
real(double) :: x, y, aux, printing
open(unit = 10, file='u.dat',status = 'unknown')
!open(unit = 20, file='v.dat',status = 'unknown')
open(unit = 30, file='psi.dat',status = 'unknown')
open(unit = 40, file='uwvwpw.dat',status = 'unknown')
open(unit = 50, file='ppxdpx.dat',status = 'unknown')
write(10,*)'variables = "x", "y", "u"'
write(10,*)'zone i=',mx,', j=',my,', f=point'
!write(20,*)'variables = "x", "y", "v"'
!write(20,*)'zone i=',mx,', j=',my,', f=point'
write(30,*)'variables = "x", "y", "psi"'
write(30,*)'zone i=',mx,', j=',my,', f=point'
!write(40,*)'variables = "x", "uw", "vw", "pw", "u0", "v0", "p0", "px", "ipx", "dpx", "d2dpx"'
!write(40,*)'zone i=',mx,', f=point'
write(50,*)'zone i=',mx,', f=point'
do s = 1,my
do t = 1,mx
x = xpos(s,t)
y = ypos(s,t)
write(10,100) x, y, u(s,t), v(s,t)
!write(20,*) x, y, v(s,t)
write(30,*) x, y, psi(s,t)
100 format(1x,4(f14.7,1x))
end do
end do
do t = 1,mx
aux = x_axis(t)
!write(40,10)x_axis(t), uw(t), vw(t), pw(t), u0(t), p0(t), &
!
1.d0/p(aux), deriv_p(aux), vav(t)
write(40,10)x_axis(t)/l2, uw(t), vw(t), pw(t), u0(t)
10 format(1x, 9(f8.4,1x))

Versão primeira de janeiro 1999. Versao atual impressa (*.pdf) em 22 de agosto de 2013
Autor: João Batista Aparecido – jbaparecido@dem.feis.unesp.br e jbaparecido@gmail.com

162

Fortran 90/95
end do
do t = 1,mx
aux = x_axis(t)
write(50,20)x_axis(t), p(aux), v0(t), p0(t), &
1.d0/p(aux), uav(t), deriv_p(aux), vav(t)
20 format(1x, 8(f9.4,1x))
end do

close(10)
!close(20)
close(30)
close(40)
close(50)
printing = unity
return
end function printing
end module outputwriting

Versão primeira de janeiro 1999. Versao atual impressa (*.pdf) em 22 de agosto de 2013
Autor: João Batista Aparecido – jbaparecido@dem.feis.unesp.br e jbaparecido@gmail.com

163

pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem. deriv_p return end function deriv_p !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function deriv2nd_p(x) use global_data. l2. intent(in) :: x aux = x/l2 aux2 = aux*aux p = l1 + (l3-l1)*(3. intent(in) :: x aux = x/l2 aux2 = aux*aux ! return the value of p(x) derivative deriv_p = 6.*) "dp = ". l2. l3 ! this function computes the derivative value of p(x) implicit none real(double) :: deriv_p. p return end function p !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function deriv_p(x) use global_data.d0*aux)/(l2*l2) !write(*. l3 ! this function computes the value of p(x) implicit none real(double) :: p. only : l1. aux.br e jbaparecido@gmail. aux2 real(double). only : l1.aux)*aux/l2 !write(*.d0 . aux2 real(double). deriv2nd_p Versão primeira de janeiro 1999. intent(in) :: x aux = x/l2 ! return the value of p(x) derivative deriv2nd_p = 6.*) "p = ". l2.d0*(l3-l1)*(1 .2.2. Versao atual impressa (*.Fortran 90/95 module wall_functions use data_type implicit none contains !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! function p(x) use global_data. only : l1.com 164 .unesp.*) "d2p = ". aux real(double).feis. l3 ! this function computes the derivative value of p(x) implicit none real(double) :: deriv2nd_p.d0*aux)*aux2 ! return the value of p(x) !write(*.d0*(l3-l1)*(1.d0 . aux.

unesp. Versao atual impressa (*.feis.com 165 .pdf) em 22 de agosto de 2013 Autor: João Batista Aparecido – jbaparecido@dem.Fortran 90/95 return end function deriv2nd_p end module wall_functions Versão primeira de janeiro 1999.br e jbaparecido@gmail.