zoukankan      html  css  js  c++  java
  • GRAPES源码分析之namelist

    前言

    在GRAPES、WRF等模式中常见到类似 namelist.input 或 .nml 文件。文件里放入一些如预报区域范围、预报时间,技术方案选择及运行模式所需进程数等控制模式运行的配置变量。实际上 namelist 是 Fortran 中一种特殊的I/O读写格式。本文首先介绍 namelist 语法及如何读写,然后介绍 GRAPES 模式中是如何应用 namelist 的。

    namelist 语法

    namelist 把一组相关变量封装在一起,输入/出这一组变量时,只要在 write/read中的nml字段赋值要使用哪一个namelist就行。

    namelist 文件格式

    namelist文件格式:

    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。如下:

    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不能规定输出格式。每个数值内容使用什么格式来输出,由编译器决定。

    namelist 输入

    1
    
    read(unit, nml=nml_name)

    如果从键盘读入namelist,必须按照一定的格式输入,如下所示:

    1
    2
    
    &nml_name1 var1=1 var2=2.0 /    !以&开始,紧接namelist名字,
                                  	!然后以var=value输入每个变量,以 / 结束

    读取namelist时,可以不填入所有变量的值,只要以 &nml_name 开始输入,给一个除号就可以结束输入。变量可以不按照顺序输入,程序会自动按照变量名称来设置数值,变量甚至可以重复输入,不过变量会得到最后一次设置的值。

    namelist通常使用文本文件进行读写,nml文件常以 .nml 后缀标示其文件属性 (这个不一定,Linux系统不以后缀名确定文件类型,但用 .nml 结尾可以很方便识别文件属性)。

    nml 使用read从文件中读取数据时,会自动从 目前的位置向下寻找存放namelist的地方。

    GRAPES中的namelist

    GRAPES中有好几个namelist : RUN/namelist,input, RUN/rrtmg.nml, RUN/colm.nml(这个是 SRC/physics/CoLM/build.colm.nml 的软链接) 。

    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 声明临时配置变量,赋初值,读入,广播,赋给配置变量

  • 相关阅读:
    hbase 2.0.2 分布式安装配置/jar包替换
    hive character '' not supported here
    request.getSession().getServletContext().getRealPath()的一些坑
    hive 自定义函数
    hive 导出数据的几种方式
    hive 分区表与数据产生关联的三种方式
    hive 日志配置/表头配置
    hive 3.1.0 安装配置
    zookeeper 客户端操作
    linux 循环读取文件的每一行
  • 原文地址:https://www.cnblogs.com/Parallel-Life/p/3231842.html
Copyright © 2011-2022 走看看