Entrada e saída por NAMELIST
Uma das áreas que mais se desenvolveram na Meteorologia nos últimos anos foi a
Previsão Numérica do Tempo e do Clima. Em resumo, seu foco é a solução numérica das equações
que descrevem os movimentos atmosféricos, com o objetivo de prever o estado futuro da atmosfera.
Além da previsão do tempo e do clima, a solução numérica das equações proporcionam
ao Meteorologista a possibilidade de realizar experimentos, que seriam impossíveis de se realizar –
como retirar montanhas, eliminar continentes, inserir fontes de calor – para entender o
comportamento da atmosfera. O conjunto de programas usado para resolver as equações
atmosféricas são normalmente chamados de modelos numéricos.
Em sua grande maioria, se não em sua totalidade, os modelos numéricos de previsão de
tempo são escritos na linguagem Fortran. Devido a sua altíssima complexidade, a realização de
experimentos requer um meio rápido e fácil de se redefinir parâmetros, tempo de duração do
experimento e várias outras informações que precisam ser alteradas entre distintos testes.
Assim, é comum encontrar nos modelos numéricos de previsão do tempo, arquivos que
contém uma série de variáveis que podem ser alteradas sem a necessidade de uma recompilação de
todo o código fonte (programa Fortran) do modelo.
A leitura desses arquivos é feita, na grande maioria das vezes, por meio de um
NAMELIST. O EXEMPLO 1 ilustra um arquivo desse tipo para o modelo WRF, muito utilizado
hoje em dia na previsão numérica do tempo e em experimentos numéricos. Outros modelos como
ETA, BRAMS e MM5, por exemplo, também usam NAMELIST para essa finalidade.
A entrada e saída de dados por NAMELIST é uma maneira conveniente de escrever ou
escrever uma lista fixa de nomes de variáveis e valores. Um namelist é uma lista de nomes de
variáveis que são sempre lidas e escritas como um grupo. A forma de um namelist é
NAMELIST / nome_grupo / var1 [, var2, …]
sendo nome_grupo o nome do namelist, e var1, var2, etc são as variáveis na lista. O NAMELIST é
um comando de especificação e, portanto, deve aparecer antes do primeiro comando executável do
programa, a exemplo dos comandos de especificação INTEGER e REAL, por exemplo. Se há mais
de um comando NAMELIST com o mesmo nome, então as variáveis serão unidas e tratadas como
se estivesse num único e grande comando. Então os comandos
NAMELIST / grupo_1 / x,y,z
NAMELIST / grupo_1 / a,b,c
têm exatamente o mesmo efeito do comando
NAMELIST / grupo_1 / x,y,z,a,b,c
&time_control
run_days = 0,
run_hours = 12,
run_minutes = 0,
run_seconds = 0,
start_year = 2000, 2000, 2000,
start_month = 01, 01, 01,
start_day = 24, 24, 24,
start_hour = 12, 12, 12,
start_minute = 00, 00, 00,
start_second = 00, 00, 00,
end_year = 2000, 2000, 2000,
end_month = 01, 01, 01,
end_day = 25, 25, 25,
end_hour = 12, 12, 12,
end_minute = 00, 00, 00,
end_second = 00, 00, 00,
interval_seconds = 21600
…
…
EXEMPLO 1: Parte do arquivo namelist.input do modelo numérico de previsão de tempo WRF
(Weather and Research Forecasting) usado para alterar parâmetros e opções. Nesse exemplo, as
variáveis iniciadas com start_ referem-se às datas de início das simulações/previsões e aquelas
iniciadas com end_ referem-se às suas datas finais.
As variáveis listadas num NAMELIST podem ser lidas e escritas como se fossem
unidades de entrada e saída, respectivamente, usando comandos de entrada e saída.
Um comando de entrada e saída para um NAMELIST se parece com um comando de
entrada e saída que usa formatos, exceto que a opção FMT= é substituída pela opção NML=. A
forma de um comando WRITE para um NAMELIST é
WRITE ( UNIT=unidade, NML=nome_grupo,[...])
sendo unidade o local onde o dado será escrito e nome_grupo é o nome do namelist a ser escrito.
Quando um comando WRITE para um namelist é executado, os nomes de todas as variáveis no
namelist são impressos juntos com os seus valores numa ordem especial. O primeiro item a ser
impresso é um caractere &, seguido pelo nome do namelist. Após, uma série de valores na forma
“NOME=valor” é impressa. Esses valores podem aparecer numa única linha, separados por
vírgulas, ou em linhas separadas, dependendo da maneira que o compilador implementa o namelist.
Finalmente, a lista é terminada com uma barra, /. O PROGRAMA 1 ilustra uma saída de valores
usando NAMELIST.
A forma geral de um comando READ para um NAMELIST é
READ ( UNIT=unidade, NML=nome_grupo,[...])
sendo unidade o local de onde se está lendo dados e nome_grupo é o nome do namelist a ser lido.
Quando um comando READ para um namelist é executado, o programa procura pelo marcador
&nome_grupo,
que indica o início do namelist. Então, todos os valores da lista são lidos até o
caractere barra, /, ser encontrado. Os valores na lista de entrada podem aparecer em qualquer linha,
desde que estejam dentro dos marcadores &nome_grupo e /. Os valores são atribuídos às variáveis
do namelist de acordo com os nomes dados na lista de entrada. Não há necessidade do comando
READ atribuir valores a todas as variáveis do namelist. Se alguma variável do namelist não estiver
incluída na lista de entrada, então o seu valor permanecerá inalterado. O PROGRAMA 2 ilustra o
uso do comando READ para namelist.
PROGRAM saida_namelist
IMPLICIT NONE
INTEGER :: a=987, b=­123
INTEGER, DIMENSION(3:5) :: c=(/3,4,5/)
REAL :: x=6.54, y=0.00009876
COMPLEX :: q=(4.5,6.7)
CHARACTER(LEN=23) :: s="Testando saida NAMELIST"
NAMELIST /xyz/a,b,c,x,y,q,s
WRITE (UNIT=*,NML=xyz)
END PROGRAM saida_namelist
&XYZ
A= 987,
B= ­123,
C= 3, 4, 5,
X= 6.53999996 ,
Y= 9.87599997E­05,
Q=( 4.50000000 , 6.69999981 ),
S="Testando saida NAMELIST",
/
PROGRAMA 1: Programa que ilustra o uso de NAMELIST para saída de dados. Em negrito, o
resultado da execução do programa.
PROGRAM entra_namelist
IMPLICIT NONE
INTEGER :: a=0,b=0
INTEGER, DIMENSION(3:5) :: c=0
REAL :: x=0.,y=0.
COMPLEX :: q=0.
CHARACTER(LEN=23) :: s
NAMELIST /xyz/a,b,c,x,y,q,s
READ (UNIT=*,NML=xyz)
PRINT *,'Variaveis lidas:'
PRINT *,a
PRINT *,b
PRINT *,c
PRINT *,x
PRINT *,y
PRINT *,q
PRINT *,s
END PROGRAM entra_namelist
Variaveis lidas:
987
­123
3 4 5
6.53999996 9.87599997E­05
( 4.50000000 , 6.69999981 )
Testando saida NAMELIST
PROGRAMA 2: Programa que ilustra o uso do NAMELIST para entrada de dados. Em negrito o
resultado do programa. O programa usa a saída do PROGRAMA 1, que pode ser fornecida pela
entrada padrão (teclado) ou por meio de um arquivo.
Comandos READ para namelist são muito úteis. Suponha que um programa contém 100
variáveis de entrada. As variáveis serão inicializadas aos seus valores-padrão, definido no
programa. Durante qualquer execução em particular do programa, qualquer um dos 10 primeiros
valores precisam ser alterados, mas os outros devem permanecer com os valores padrão. Neste caso,
é possível incluir todos os 100 valores em um namelist e incluir um comando READ para um
namelist no programa. Sempre que um usuário quiser rodar o programa, ele pode listar apenas
aqueles valores a serem alterados. O PROGRAMA 3 ilustra a atualização de algumas variáveis de
um namelist.
PROGRAM atualizaNML
IMPLICIT NONE
INTEGER :: i = 1, j = 2
REAL :: a = ­999., b = 0.
CHARACTER(LEN=12) :: string = 'String teste'
NAMELIST / lista / i, j, string, a, b
OPEN( UNIT=7, FILE='entrada.nml' )
WRITE(UNIT=*,FMT='(1X,A)') 'NAMELIST antes da atualizacao:'
WRITE(UNIT=*,NML=lista)
READ(UNIT=7,NML=lista)
WRITE(UNIT=*,FMT='(1X,A)') 'NAMELIST depois da atualizacao:'
WRITE(UNIT=*,NML=lista)
END PROGRAM atualizaNML
NAMELIST antes da atualizacao:
&LISTA
I= 1,
J= 2,
STRING="String teste",
A= ­999.000000 ,
B= 0.00000000 ,
/
NAMELIST depois da atualizacao:
&LISTA
I= ­111,
J= 2,
STRING="diferente! ",
A= ­999.000000 ,
B= 123456.000 ,
/
&LISTA
I=­111
STRING='teste 1.'
STRING='diferente!'
B=123456.
/
PROGRAMA 3: Programa que ilustra a leitura de algumas das variáveis de um NAMELIST. Em
negrito, o resultado do programa e, em itálico, o conteúdo do arquivo entrada.nml, lido pelo
PROGRAMA 3.
Com o resultado do PROGRAMA 3 é possível perceber, também, que um namelist
pode conter valores para a mesma variável mais de uma vez, mas o valor final dessa variável é
fornecido pela última atribuição.
Nomes de arranjos, seções de arranjos e elementos de arranjos podem aparecer num
comando NAMELIST. Se um nome de arranjo aparece num namelist, então quando o comando
WRITE para namelist é executado, cada elemento do arranjo é impresso, um após o outro. Quando
um comando READ para namelist é executado, cada elemento do arranjo pode ser definido
separadamente e somente aqueles cujos valores devam ser alterados precisam ser informados ao
comando READ.
Argumentos fictícios e variáveis que são criadas dinamicamente não podem aparecer
em um NAMELIST. Isto inclui arranjos usados como argumentos fictícios sem limites constantes,
variáveis caractere sem comprimento constante, variáveis automáticas e ponteiros.
FONTE: Chapman, S. J. Fortran 95/2003 for Scientists and Engineers. 3rd edition, McGrawHill. 2007. 1008p.
Download

Entrada e saída por NAMELIST