quarta-feira, 14 de março de 2012

Página FORTRAN BR no Facebook

Pessoal, a comunidade Fortran BR, que antes estava no orkut, está oficialmente se mudando para o facebook. Os objetivos da comunidade são: discutir coisas relacionadas à linguagem Fortran, compartilhar conhecimentos e, acima de tudo, tentar ajudar o pessoal que programa em Fortran em alguma eventual dúvida.

Caso algum de vocês queira participar:

http://www.facebook.com/pages/Fortran-BR/175672819217170

Até mais!

terça-feira, 11 de outubro de 2011

Como determinar se um número é PAR ou ÍMPAR em FORTRAN

Acredito que a forma mais fácil de determinar se um número é PAR ou ÍMPAR em FORTRAN é utilizando a função intrínseca MOD(.), que retorna o resto de uma divisão. Se o resto de uma divisão por 2 é igual a zero, o número é par, se é igual a um, o número é ímpar.
Nesse caso, para determinar se X é par, tem-se:

!PARA O CASO DE X REAL:
IF ( MOD( X , 2.D0) == 0 ) THEN  !  ->  X é PAR!

!PARA O CASO DE X INTEIRO:

IF ( MOD( X , 2) == 0 ) THEN  !  ->  X é PAR!

Caso contrário, X é ÍMPAR.

domingo, 4 de abril de 2010

COMO MODIFICAR ALGO QUE JÁ FOI ESCRITO NA TELA - MOSTRAR PORCENTAGEM DE PROCESSAMENTO...

"Modificar" algo que foi escrito na tela não é algo difícil. Neste post mostra-se como fazer isso em Windows, utilizando o Compaq Visual Fortran 6.6. O procedimento deve ser semelhante para outros compiladores e outros sistemas operacionais.
Basta declarar uso da biblioteca que permite manipular a saída padrão (Standard Output) obter o handle (identificador) da mesma, posicionar o cursor no local que se deseja modificar o que foi escrito, e escrever o que quiser.
Em outras palavras...

PROGRAM MAIN

USE DFLIB !PARA PODER UTILIZAR A FUNÇÃO SLEEP
USE DFWIN !PARA TER ACESSO ÀS FUNÇÕES RELACIONADAS AO CONSOLE
INTEGER :: I, HANDLE1 !UM INTEIRO PARA A PORCENTAGEM,
!OUTRO PARA O IDENTIFICADOR
TYPE(T_COORD) WPOS1 !PARA ARMAZENAR A POSIÇÃO
LOGICAL LSTAT1

!OBTENDO O IDENTIFICADOR DA SAÍDA PADRÃO
HANDLE1 = GETSTDHANDLE(STD_OUTPUT_HANDLE)

! POSIÇÃO ONDE SE VAI ESCREVER
WPOS1.X = 0 ! 0 CARACTERES PARA A ESQUERDA
WPOS1.Y = 0 ! 0 LINHAS PARA BAIXO

DO I=1,100
!POSICIONANDO
LSTAT1 = SETCONSOLECURSORPOSITION(HANDLE1, WPOS1)
!ESCREVENDO
WRITE(*,*) I,'%'
!ESPERANDO
CALL SLEEPQQ(200)
END DO

END PROGRAM MAIN

terça-feira, 23 de março de 2010

Inserindo um CRONÔMETRO no seu programa - MEDIÇÃO DO TEMPO DE EXECUÇÃO

Neste post é apresentado um cronômetro simples com interface gráfica mais simples ainda, que permite mostrar o tempo (em segundos) decorrido desde o início da execução de um código qualquer. A figura abaixo dá uma idéia do cronômetro supracitado (pequena caixa de diálogo que aparece no canto superior esquerdo da figura).


OBSERVAÇÃO: Primeiro de tudo, não esqueça que o acoplamento deste cronômetro ao seu código deixará sua aplicação um pouco mais lenta!

ACOPLANDO O CRONÔMETRO À SUA APLICAÇÃO

O primeiro passo é baixar o código fonte (um projeto completo utilizando o cronômetro, mostrado na figura acima), para isto basta clicar aqui e baixar o arquivo .zip hospedado no rapidshare!

No exemplo, o cronômetro foi inserido em um projeto FORTRAN CONSOLE APPLICATION. Tudo foi desenvolvido em Compaq Visual Fortran 6.6.

Após baixar os arquivos, copie ATUALIZA_CRON.F90, CRONOMETRO_DIALOG.rc e RESOURCE.fd para a pasta do seu projeto.

(Procedimento verificado apenas em CVF 6.6)

Com seu projeto aberto no CVF, clique no menu Project, vá em Add to Project e clique em Files. Adicione os arquivos CRONOMETRO_DIALOG.rc e RESOURCE.fd.

Na subrotina que você quer cronometrar, insira as definições para utilizar o cronômetro:

!******************************************************************
! DEFINIÇÕES PARA UTILIZAR O CRONÔMETRO
USE DFPORT !PARA USAR A FUNÇÃO TIMEF
USE DFLOGM
INCLUDE 'RESOURCE.FD'
TYPE (DIALOG) DLG
LOGICAL RETLOG
REAL*8 :: TEMPO
!******************************************************************

E logo após a definição das variáveis de sua subrotina, insira o código para inicializar o cronômetro:

!*******************************************************************
!INICIALIZANDO O CRONÔMETRO
RETLOG = DLGINIT(101,DLG) !INICIALIZANDO A CAIXA DE DIÁLOGO
IRET = DLGMODELESS(DLG) !IMPRIMINDO A CAIXA NA TELA (NÃO MODAL)
TEMPO = TIMEF() !INICIALIZANDO A CONTAGEM DO TEMPO
!*******************************************************************

PRONTO!!!

Agora é só chamar a subrotina que atualiza o tempo dentro dos principais loops da subrotina a ser cronometrada:


CALL ATUALIZACRON(DLG) !ATUALIZAR TEMPO MOSTRADO NA CAIXA DE DIÁLOGO

O CRONÔMETRO PODE SER MODIFICADO E MELHORADO CONFORME SUAS NECESSIDADES.


Para modificá-lo, vá em ResourceView e clique duas vezes em IDD_DIALOGTEMPO. A aba ResourceView fica imediatamente abaixo de onde aparecem os nomes dos arquivos do seu projeto.


Uma ótima referência sobre Interfaces Gráficas em CVF 6.6 é encontrada no post Desenvolver interfaces gráficas.

segunda-feira, 22 de março de 2010

Comparação: MATMUL versus DGEMM (Multiplicação de Matrizes)

Neste post é feita uma comparação de tempo de processamento (utilizando a função CPU_TIME) entre multiplicações de matrizes quadradas utilizando a função intrínseca MATMUL e a subrotina DGEMM da biblioteca IMSL.

Os dois casos explicados a seguir foram feitos para TAM = 1000, ou seja, para matrizes de tamanho 1000 x 1000.

PRIMEIRO CASO
Para o primeiro caso, as matrizes a serem multiplicadas (A*B) são definidas como:
DO i=1,TAM
DO j=1,TAM
A(i,j) = i + j
B(i,j) = i + j
END DO
END DO

SEGUNDO CASO
Para o segundo caso, as matrizes a serem multiplicadas (A*B) são definidas como:
DO i=1,TAM
DO j=1,TAM
A(i,j) = i - j
B(i,j) = i + j
END DO
END DO



RESULTADOS


Os resultados estão resumidos no seguinte gráfico:



Para os dois casos estudados, MATMUL foi cerca de 5 vezes mais lento que DGEMM.

CONCLUSÕES


Caso você tenha acesso à biblioteca IMSL, vale a pena gastar um pouco de tempo substituindo a função MATMUL pela DGEMM em todos os seus programas que utilizem multiplicação de matrizes.


Caso não tenha acesso a esta biblioteca, vale a pena ver se há outra subrotina que você possa utilizar no lugar da MATMUL e fazer uma breve comparação entre elas.



domingo, 21 de março de 2010

Comparação (de velocidade de processamento): mesclando código .FOR + .F90, usando ou não subrotinas (funções)...

O QUE É COMPARADO?

Neste post são comparados alguns resultados (de tempo de processamento) para a realização de um conjunto determinado de operações, englobando os casos a seguir. Todos os exemplos foram desenvolvidos utilizando o Compaq Visual Fortran 6.6.


1. F90
O código é todo escrito em Fortran 90. São feitos dois arquivos, MAIN.F90 e FUNC.F90. O programa MAIN chama a função presente em FUNC.F90 um total de NUM_ITE vezes, e repete o procedimento um total de NUM_REPETICOES vezes, obtendo a média do tempo de processamento.


2. F90 + FOR
Semelhante ao caso .F90, sendo que o arquivo MAIN é um .F90, e o arquivo FUNC é um .FOR (formato fixo).


3. F90 Direto
O arquivo FUNC deixa de existir, as operações são inseridas no arquivo MAIN diretamente. O código é todo escrito em F90.


4. FOR Direto
Semelhante ao F90 Direto, mas o código é todo escrito em formato fixo (.FOR).


5. F90 mesclado
Todo o código do arquivo FUNC é inserido após o fim do programa MAIN, de forma que se trabalha com uma subrotina (função) à parte, mas tanto o programa quanto a função ficam presentes no mesmo arquivo. Todo o código é escrito em formato livre (.F90).


6. FOR mesclado
Semelhante ao F90 mesclado, mas o código é escrito em formato fixo.





QUAIS SÃO AS OPERAÇÕES EFETUADAS?


Foram executados três exemplos com diferentes conjuntos de operações, para todos os casos NUM_REPETICOES = 3 (para efetuar a média de tempo de processamento).



PRIMEIRO CONJUNTO DE OPERAÇÕES
Y = X**2
Y = Y + 0.02D0
NUM_ITE = 1E9



SEGUNDO CONJUNTO DE OPERAÇÕES
Y = X**2
Y = Y + 0.02D0
Y = SQRT(Y)
Y = Y/2.25D0
NUM_ITE = 5E8



TERCEIRO CONJUNTO DE OPERAÇÕES
Y = X**2.2D0
Y = Y + 0.0225D0
Y = SQRT(Y)
Y = SIN(Y)
Y = Y/2.25673D0
Y = COS(Y)
NUM_ITE = 5E7






QUAIS FORAM OS RESULTADOS?



O tempo de processamento para cada caso é mostrado na figura abaixo.



CONCLUSÕES

Para os casos estudados:

1 - Mesclar códigos escritos em .FOR com códigos em .F90 não leva a grandes diferenças de custo computacional.

2 - Utilizar subrotinas (funções) em diferentes arquivos ou mescladas num mesmo arquivo não leva a grandes diferenças também.

3 - Efetuar as operações diretamente no código principal é mais rápido do que efetuar as operações em subrotinas (funções) à parte. No entanto, à medida que a complexidade das operações aumenta, o custo de chamada da função perde importância.

Portanto, para grandes problemas (com operações complexas) a clareza de código obtida utilizando subrotinas supera de longe o acréscimo de custo computacional.

4 - Para problemas mais complexos (conjunto de operações 3) todos os seis casos apresentaram praticamente o mesmo custo computacional.


-------------------- x ----------------------- x -----------------------

domingo, 13 de dezembro de 2009

MATLAB versus FORTRAN - 1 - somatório simples

Pretendo fazer algumas comparações entre MATLAB e FORTRAN, e este é o primeiro post com tal objetivo. Dois aspectos principais serão verificados: a quantidade de linhas do código fonte, que se relaciona com a facilidade de escrita na linguagem, e o tempo de processamento, que está diretamente vinculado ao tempo de execução. Como se sabe, o MATLAB, por ser uma linguagem interpretada (sem geração de código executável) tende a ser mais lento, no entanto, existem muitas facilidades no mesmo que diminuem o tempo de programação requerido.


No intuito de medir o tempo nos dois ambientes sem que haja muita diferença no método de medição, optou-se por utilizar as funções tic e toc, no MATLAB, e a função TIMEF() do FORTRAN (biblioteca DFPORT). A descrição destas funções é a seguinte:





O primeiro exemplo é um somatório simples, para i variando de 1 a 1 bilhão, conforme o código abaixo (em MATLAB):



j=0;
tic
for i=1:1000000000
j=j+1;
end
toc

O número de linhas do código fonte foi de 6 linhas para o MATLAB contra 10 linhas do FORTRAN (sem contar cabeçalho e finalização da função).



O tempo médio de execução para 10 repetições é mostrado a seguir:

Verificou-se que, para este exemplo, o MATLAB foi quase duas vezes mais lento que o FORTRAN.






quinta-feira, 29 de outubro de 2009

VISITAS... Onde se programa em FORTRAN no Brasil?

Este post traz apenas uma curiosidade: as visitas a este blog no mês de outubro (na verdade de 28 de setembro a 28 de outubro) divididas por cidade. Dá pra se ter uma idéia superficial de lugares nos quais o FORTRAN tem sido utilizado no Brasil... Rio de Janeiro aparece em primeiro lugar com 25 visitas, seguido por Salvador com 20 visitas e São Paulo com 19 visitas.


O Blog recebeu ainda 20 visitas internacionais este mês.

Agradeço a todos que visitaram o Fortran-BR, e peço que deixem mais comentários nos posts ou, pelo menos, digam o que acharam por meio das reações ao final de cada post (péssimo, ruim, bom, interessante...). Até mais!

OBS.: Os dados das visitas foram obtidos por meio do serviço Google Analytics.




Convertendo CHARACTER para REAL ou INTEGER

Como esqueço o tempo todo como fazer essas conversões, decidi escrever aqui um resumo do processo.

Tomando-se as seguintes 3 variáveis:


CHARACTER(100) :: TEXTO
REAL*8 :: VALOR_REAL
INTEGER :: VALOR_INTEIRO


Se um "número" é armazenado no TEXTO, por exemplo:
TEXTO = '5.6987'
a conversão pode ser feita utilizando o READ() de forma bem simples.

READ(TEXTO,*) VALOR_REAL
READ(TEXTO,*) VALOR_INTEIRO.




Converter variáveis FORTRAN, conversão de variáveis, texto para número, caracter para real, caracter para inteiro.

segunda-feira, 19 de outubro de 2009

Overflow condition - números inteiros em Fortran

Uma pequena explicação sobre números inteiros e "overflow condition".
A chamada overflow condition ocorre quando se tenta armazenar numa variável do tipo inteiro um número maior que o valor máximo possível ou menor que o valor mínimo possível.
Esses limites existem pois, quando declaramos uma variável, um determinado espaço de memória é reservado para guardar o valor da tal variável.
Considerando um inteiro de n bits, usualmente o menor número que pode ser armazenado é dado por:
menor_valor_inteiro = -2**(n-1)
e o maior valor é dado por:
maior_valor_inteiro = 2**(n-1) -1 !(O '-1' é o espaço reservado ao zero) .

O tipo mais comum de inteiros nos computadores de hoje em dia são os inteiros de quatro bytes (1 byte = 8 bits; 4 bytes = 32 bits), que, portanto, podem armazenar qualquer número inteiro entre -2,147,483,648 e 2,147,483,647.

Portanto, se você tiver problemas com overflow condition, a solução pode ser simplesmente ter que trocar um INTEGER por um INTEGER*8.

terça-feira, 4 de agosto de 2009

Programa para renomear projetos: Compaq Visual Fortran 6.6

Depois de ter perdido muito tempo procurando como renomear um projeto dentro do Compaq Visual Fortran 6.6 e não conseguindo, terminei por descobrir uma forma de renomear o projeto fora do mesmo. O processo é bastante simples, mas decidi fazer um programa para torná-lo ainda mais fácil e rápido.
O pequeno programa, que trabalha em cima dos arquivos .dsw e .dsp, deve ser copiado para a pasta onde se encontram os arquivos .dsw e .dsp do projeto que se deseja renomear e lá executado. Depois de pedir o nome atual do projeto e o novo nome, o programa cria dois novos arquivos (um .dsw e um .dsp) com o novo nome. Verifique se está tudo ok com o projeto renomeado abrindo-o (abra o workspace '.dsw' no Developer Studio). Se tiver dado tudo certo você pode deletar os antigos arquivos .dsw e .dsp.

OBS.: É recomendável fazer um backup do projeto antes de utilizar este programa, pois o mesmo não foi testado exaustivamente, tendo sido feito apenas para suprir a necessidade do próprio autor.


Faça aqui do download do programa (450Kb), pelo rapidshare.


P.S.1: Caso você, leitor, se interesse pelo código fonte deste pequeno programa, deixe seu comentário neste post. Posso disponibilizar o projeto completo posteriormente.

sexta-feira, 31 de julho de 2009

ERROS COMUNS: Exponenciação - número negativo elevado a um potência real

Sabe-se que a expressão:
y = x ** n,
onde y e x são reais, e n é um inteiro, equivale a simplesmente multiplicar x por ele mesmo n vezes, e é isso exatamente que o computador faz ao encontrar uma expressão desse tipo.

No entanto, quando se tem algo do tipo:
y = x ** z,
onde y, x e z são reais, z pode ser igual a, por exemplo, 2.5. É fisicamente impossível multiplicar um número por ele mesmo 2.5 vezes, e portanto é necessário recorrer a métodos indiretos para calcular x ** z. O método mais comum para este caso é o seguinte:
x ** z = exp(z*ln(x)).
Portanto, como não existe logaritmo natural de número negativo, o seguinte "ERRO" pode ocorrer:
(-2.0)**(2.5) = NaN (Not a number)
( 2.0)**(2.5) = 5.656854.

ERROS COMUNS: Divisão em "modo misto"

Um erro bastante comum, do qual eu e alguns colegas já fomos vítimas, é a divisão envolvendo reais e inteiros. De uma forma geral, as expressões em "modo misto" devem ser evitadas, visto que são relativamente difíceis de entender e podem levar a resultados diferentes dos desejados.

Em operações aritméticas entre um número real e um inteiro, o inteiro é convertido para real pelo computador e o resultado é do tipo real.
Isso explica porque:
(1 + 1/2) = 1
(1. + 1/2) = 1.0
(1 + 1./2) = 1.5
(1 + 1/2.) = 1.5
No primeiro e no segundo caso ocorre que 1/2 = 0, por se tratar de uma divisão entre dois números inteiros. No terceiro e no quarto casos, 1./2 = 1/2. = 0.5, o inteiro é convertido para real e a aritmética para números reais é utilizada.

Portanto, é necessário ter atenção redobrada para casos tais como:
(2**(1/2)), que resulta igual 1, diferentemente de
(2**(1./2)) ou (2**(1/2.)), cujo resultado é 1.414214...

segunda-feira, 6 de julho de 2009

Comparação - ACESSANDO MATRIZES... (RANK 2 ARRAYS)

Acho que muitos já devem saber (ou ter ouvido falar) que o fortran guarda matrizes na memória "coluna por coluna". Dessa forma, o acesso às mesmas deve ser feito também coluna por coluna, para maior velocidade de execução. O conceito de coluna varia um pouco quando se trabalha com matrizes de mais de duas dimensões, mas de uma forma geral os loops mais internos devem se referir à dimensão mais à esquerda da matriz.
Por exemplo, com uma matriz de três dimensões se teria:

!LOOP mais rápido
DO K=1,N3
DO J=1,N2
DO I=1,N1
A(I,J,K) = ...
END DO
END DO
END DO

Qualquer alteração da ordem desses LOOPs resulta num código mais lento.

Tomando-se o caso de duas dimensões apenas, qual seria a diferença de velocidade do loop mais rápido para o mais lento?

Na busca por respostas para essa pergunta, foi desenvolvido um pequeno projeto no Compaq Visual Fortran 6.6 ( 288Kb). Para uma matriz A de dimensão NxN, onde N=5000, foram rodados 20 vezes os códigos que permitiram colocar o valor de cada elemento da matriz como sendo
A(I,J) = A(I,J) + I**2 + J**2,
acessando linha por linha (mais lento) e coluna por coluna (mais rápido).
O tempo médio e o tempo médio relativo foram obtidos para comparação.
Os resultados foram os seguintes:

Ou seja, para este caso específico a diferença já mostrou ser muito grande. O acesso coluna por coluna chega a ser quase 5 vezes mais rápido que o acesso linha por linha. Um bom motivo para varrer seus códigos-fonte e excluir os loops coluna por coluna deles sempre que possível.

sexta-feira, 19 de junho de 2009

CONCLUSÃO da comparação - LOOPs (DO x DO WHILE x DO "INFINITO")

Após a exposição do caso (http://fortranbr.blogspot.com/2009/06/comparacao-loops-do-x-do-while-x-do.html) e a apresentação de um resultado, seguiu-se longa discussão na comunidade Fortran Brasil. O mesmo projeto foi testado com diferentes casos e diferentes compiladores. Agradecimentos ao pessoal que participou da discussão na comunidade, em especial ao Alexandre, que foi o "causador" da mesma.

ALGUMAS CONCLUSÕES...
O tipo de loop mais rápido varia com os códigos executados no loop e depende também do compilador. De qualquer forma, nos casos em que o DO WHILE foi melhor que os outros, os outros ficaram muito próximos. E no geral o loop do tipo DO foi o que se saiu melhor, pois ele é o mais rápido em alguns casos, e nas vezes que não é ainda assim fica bem próximo do melhor.

Esse loop seria definido genericamente por:
CASO 1 : LOOP DO
DO I=1,N
.
.
.
END DO

E seria "o mais rápido" dos três casos verificados.

quinta-feira, 18 de junho de 2009

Comparação - LOOPs (DO x DO WHILE x DO "INFINITO")

Efetuei uma pequena comparação entre Loops utilizando DO, DO WHILE e DO "INFINITO", baseada na afirmação de Francisco Franco, proprietário da comunidade do orkut Fortran Brasil [], de que o DO WHILE é mais lento que os outros dois.
Os Loops em estudo são definidos genericamente da seguinte forma, onde N é um inteiro:

CASO 1 : LOOP DO
DO I=1,N
.
.
.
END DO

CASO 2 : LOOP DO WHILE
DO WHILE (I<=N) .
.
.
I = I + 1
END DO

CASO 3 : LOOP DO "INFINITO"
LOOP1 : DO
.
.
.

I = I + 1
IF (I==N) EXIT LOOP1
END DO LOOP1

Os resultados INICIAIS encontrados, apresentados na tabela abaixo, confirmaram que o DO WHILE é mais lento que os outros loops acima mostrados.

A tabela mostra os valores obtidos para uma função qualquer, comprovando que a mesma coisa estava sendo calculada nos três casos. Foram feitos dois loops, um dentro do outro, com N=25000, ou seja, 625 milhões de cálculos da função (X = X + (-1**J)*X/N, onde J varia em um dos loops). Tomou-se um tempo relativo ao tempo do Loop Do "Infinito".
Constatou-se PARA ESTE N ESPECÍFICO que o caso 2 demora cerca de 2% a mais de tempo do que a referência, enquanto que o caso 3 leva cerca de 0,7%.

O estudo foi feito utilizando o Compaq Visual Fortran 6.6, e o projeto completo está disponível para download aqui (294Kb).

ATUALIZAÇÃO:
Este mesmo post gerou discussões e mais discussões na comunidade supracitada. Algumas conclusões podem ser vistas AQUI.

sexta-feira, 12 de junho de 2009

Apostila Visual FORTRAN - Desenvolver interfaces


Apostila que aborda desde o básico até aspectos de desenvolvimento de Interfaces Gráficas de Usuário (GUIs) em FORTRAN, desenvolvida por Wilton Pereira da Silva, Cleiton e Cleide Maria D. P. S. e Silva. A apostila em formato PDF pode ser baixada diretamente neste link num único arquivo zipado (1934KB), ou, se preferir, você pode baixar a versão dos autores neste link, em formato hlp, e que necessita instalação de um pequeno aplicativo.
Os códigos fonte desenvolvidos podem ser baixados AQUI. E a página dos autores sobre o tutorial é a seguinte:
http://br.geocities.com/pextensao/vf.html .

Até mais.

quinta-feira, 11 de junho de 2009

Otimização de códigos FORTRAN

Guia RÁPIDO de OTIMIZAÇÃO de códigos FORTRAN visando maior VELOCIDADE de execução...
Detalhes muito interessantes que encontrei no site da Pós Graduação em Engenharia Civil da UFRGS. Vale a pena dar uma lida:
http://www.cpgec.ufrgs.br/masuero/otimizacao/otimizacao.htm .

terça-feira, 9 de junho de 2009

Apostilas básicas de FORTRAN.

Cinco apostilas de FORTRAN básico para download em um arquivo zipado (950KB):

http://rapidshare.com/files/1523197554/Apostilas-FORTRAN_fortranbr.blogspot.com.zip .

sexta-feira, 5 de junho de 2009

Como utilizar a Derivação automática? - EXEMPLO COMPLETO

Um exemplo de derivação automática com alguns comentários. O projeto COMPLETO, desenvolvido em Compaq Visual Fortran 6.6, pode ser baixado AQUI.
São três arquivos diferentes denominados no meu projeto como sendo: MAIN.F90, que contem o código PROGRAM TEST dado abaixo, FUNCOES.F90, que contem o módulo FUNCOES, também dado abaixo, e DERIV_CLASS.F90, o módulo de derivação cujo link está disponível no post Derivação Automática.

----------------- CÓDIGO PARA O MAIN.F90 ----------------------

PROGRAM TEST
USE DERIV_CLASS ! torna o módulo de derivação disponível
USE FUNCOES
INTEGER, PARAMETER :: TAM_X=3 !tamanho do vetor x
REAL*8 :: F_, X_(TAM_X), DF(TAM_X) !variáveis p/ armazenar valores de f, x e derivada
REAL*8 :: DDF(TAM_X * (TAM_X + 1) / 2) !variável p/ armazenar valor da 2a derivada
TYPE (FUNC) :: X(TAM_X), F !Para usar o módulo é preciso utilizar estes tipos

!Valores de X para os quais se deseja calcular a derivada
X_(1) = 1.0D0
X_(2) = 1.3D0
X_(3) = 1.8D0

! Zerando o valor da derivada até então
DF = 0.0D0
CALL DERIVATIVE(2) !declara a ordem da derivada - 2 indica 1a e 2a derivadas
! DECLARAR AS VARIÁVEIS INDEPENDENTES(X) E SEUS VALORES (X_)
CALL INDEPENDENT(1, X(1), X_(1)) !primeira variável independente
CALL INDEPENDENT(2, X(2), X_(2)) !segunda variável independente
CALL INDEPENDENT(3, X(3), X_(3)) !terceira variável independente
F = F1(X,TAM_X) !definindo q a função é calculada pela função f1, presente no módulo funcoes

!Extraindo valores das derivadas e mostrando os mesmo na tela.
CALL EXTRACT(F, DF, DDF)
WRITE(*, *) 'DF',DF
WRITE(*, *) 'DDF',DDF

END PROGRAM TEST


----------------- CÓDIGO PARA O MÓDULO FUNCOES ----------------------

MODULE FUNCOES

USE DERIV_CLASS

CONTAINS

FUNCTION F1(X,TAM_X) RESULT(Y)
INTEGER :: TAM_X
TYPE (FUNC) :: X(TAM_X), Y

!AQUI PODE SER ESCRITA QUALQUER FUNÇÃO DE X(TAM_X)
Y = 2*X(1)**2 + X(2)**3 + COS(X(3))

END FUNCTION

END MODULE FUNCOES


-------------------------MUITO IMPORTANTE -----------------------------------
----------------- ALTERAÇÃO NO MÓDULO DERIV_CLASS ----------------------
MODULE deriv_class IMPLICIT NONE
PRIVATE
INTEGER, PARAMETER :: n = 3 ! <<< AQUI precisa-se colocar o valor de tam_x

------------------------------------------------------------------------------------

Como o código é aberto, podem ser feitas as alterações que o usuário achar necessário. Por exemplo, pode-se colocar o parâmetro n do módulo Deriv_class em função do TAM_X já declarado anteriormente.

Até mais.