前言
在GRAPES、WRF等模式中常见到相似 namelist.input 或 .nml 文件。文件里放入一些如预报区域范围、预报时间,技术方案选择及运行模式所需进程数等控制模式运行的配置变量。实际上 namelist 是 Fortran 中一种特殊的I/O读写格式。本文首先介绍 namelist 语法及如何读写,而后介绍 GRAPES 模式中是如何应用 namelist 的。app
namelist 语法
namelist 把一组相关变量封装在一块儿,输入/出这一组变量时,只要在 write/read中的nml字段赋值要使用哪个namelist就行。dom
namelist 文件格式
namelist文件格式:ui
1 2 3 4 5 6 7 8 9 10 11 |
&nml_name1 ! &接某一组namelist名字 var1 = value, ! 输出变量名称,等号,值及逗号 var2 = value, ... / ! 除号结束这一组namelist ... &nml_nameN ! 第n组namelist ... / |
namelist 声明
namelist声明相似common语法,但nml必定要取名字,必须在执行语句前声明。首先对各个变量进行声明,而后声明各组namelist。在输入/出namelist前,必须先声明namelist。以下:spa
1 2 3 4 |
integer :: var1 !先对每一个变量如日常同样声明 real :: var2 namelist /nml_name1/ var1,var2 !而后声明那些变量属于哪一个namelist组 |
namelist 输出
1
|
write(unit, nml=nml_name) ! nml_name指每组namelist的名字 |
在write的nml字段中指定输出哪一个namelist,就把nml中变量所有输出。输出的namelist不能规定输出格式。每一个数值内容使用什么格式来输出,由编译器决定。code
namelist 输入
1
|
read(unit, nml=nml_name) |
若是从键盘读入namelist,必须按照必定的格式输入,以下所示:进程
1 2 |
&nml_name1 var1=1 var2=2.0 / !以&开始,紧接namelist名字, !而后以var=value输入每一个变量,以 / 结束 |
读取namelist时,能够不填入全部变量的值,只要以 &nml_name 开始输入,给一个除号就能够结束输入。变量能够不按照顺序输入,程序会自动按照变量名称来设置数值,变量甚至能够重复输入,不过变量会获得最后一次设置的值。input
namelist一般使用文本文件进行读写,nml文件常以 .nml 后缀标示其文件属性 (这个不必定,Linux系统不之后缀名肯定文件类型,但用 .nml 结尾能够很方便识别文件属性)。编译器
nml 使用read从文件中读取数据时,会自动从 目前的位置向下寻找存放namelist的地方。it
GRAPES中的namelist
GRAPES中有好几个namelist : RUN/namelist,input, RUN/rrtmg.nml, RUN/colm.nml(这个是 SRC/physics/CoLM/build.colm.nml 的软连接) 。io
namelist.input
主要查看namelist.input,其余两个相似
该文件保存了模式的一些配置信息(都是标量),配置变量在 shared/module_configure模块中声明。
该模块中子程序 initial_config 用于读入namelist.input变量。步骤:
-
声明子程序临时配置变量,而后把一组组相关变量封装在各组namelist中。
-
打开namelist.input文件
1 2 3 4 5 |
OPEN ( UNIT = 10 , & FILE = "namelist.input" , & FORM = "FORMATTED" , & STATUS = "OLD" , & IOSTAT = io_status ) |
-
临时配置变量先赋一个初值,即默认值。以防namelist中没有这个变量,保证变量都有值。
-
输入/出namelist,代码以下
1 2 3 4 5 |
REWIND ( UNIT = nml_unit ) READ ( UNIT = nml_unit , NML = namelist_01 , ERR = 9200 , END = 9200 ) WRITE ( UNIT = * , NML = namelist_01 ) ... 重复以上三句输入/出下一组namelist |
rewind表示回到文件nml_unit 的开始,在用rewind以前必须保证该文件已打开(即以前有open操做且成功了)。
read语句从文件开头开始查找nml字段为namelist_name的相关变量,err字段用来设置当前文件打开错误时,程序跳跃到label所指的代码处继续执行。end指在读写到文件末尾时,转移到某个行代码来继续执行程序。这里都是到9200处。
write语句向标准输出写入namelist,GRAPES中已重定向到 std.out.** 文件。
- 而后向全部进程广播临时配置变量
1 2 |
call grapes_bcast( s_we ,1 ) ... |
- 最后将临时配置变量赋给对应的派生数据类型 config_flags (该派生数据类型是在本模块中声明的),关闭文件,结束namelist输入。
1 2 3 4 |
config_flags % s_we = s_we ... CLOSE ( UNIT = 10 , IOSTAT = io_status ) |
- 另:配置变量经过 shared/module_domain模块中cpconfig子程序赋给状态变量 grid 。
总结
由以上分析可得出添加GRAPES配置变量的通常流程:
-
在namelist.input中按照nml格式添加变量,并给出其值
-
在shared/module_configure模块中grid_config_rec_type声明中添加相应变量
-
并在子程序 initial_config 声明临时配置变量,赋初值,读入,广播,赋给配置变量