ioipsl_getincom.F90

源码基线:LMDZ.COMMON-6.3\LMDZ.COMMON。 Mars 运行参与度:必经/条件经过。Mars physics 通过 getin_p 读取大量配置;无外部 IOIPSL getin 时会落到本模块。Mars utility 和 COMMON 动力配置也可直接调用本模块的 getin

源码范围

LMDZ.COMMON-6.3\LMDZ.COMMON\libf\misc\ioipsl_getincom.F90

文件 1980 行,定义 MODULE ioipsl_getincom。公开接口只有:

PUBLIC :: getin, getin_dump
INTERFACE getin
  MODULE PROCEDURE getinrs, getinr1d, getinr2d, &
                   getinis, getini1d, getini2d, &
                   getincs, getinc1d, getinc2d, &
                   getinls, getinl1d, getinl2d
END INTERFACE

模块依赖本地 IOIPSL helper:

依赖 用途
ioipsl_errioipsl:ipslerr warning/fatal 错误报告;fatal 默认 STOP
ioipsl_stringop:nocomma 将 value 中逗号替换为空格。
ioipsl_stringop:cmpblank 压缩连续空白,便于拆分多值。
ioipsl_stringop:strlowercase logical value 大小写规整。

模块角色

ioipsl_getincom.def 风格配置读取的本地 fallback。调用方传入默认值和 key 名:

CALL getin("day_step", day_step)

模块会懒加载 run.defINCLUDEDEF 指定的其它文件,查找 key,按调用方变量的类型和维度解析值;找不到 key 时保留调用方默认值。首次读取后,解析结果被写入 key_tab 和 typed memory 池,后续同 key 调用直接从内存读。

公开过程

过程 行号 作用
getin generic 22-44 根据 ret_val 类型和维度分派到 12 个 typed procedure。
getin_dump 1744-1897 将 key 数据库按 .def 风格写出到文件,用于调试或 abort dump。

12 个 getin specific

Procedure 类型 维度 行号 临时缓冲
getinis integer scalar 122-151 长度 1 栈数组
getini1d integer 1D 153-191 ALLOCATABLE, SAVE
getini2d integer 2D 193-248 ALLOCATABLE, SAVE + 列优先线性化
getinrs real scalar 252-281 长度 1 栈数组
getinr1d real 1D 283-321 ALLOCATABLE, SAVE
getinr2d real 2D 323-378 ALLOCATABLE, SAVE + 列优先线性化
getincs character scalar 382-411 CHARACTER(LEN=100) 长度 1 栈数组
getinc1d character 1D 413-451 CHARACTER(LEN=100), ALLOCATABLE, SAVE
getinc2d character 2D 453-508 CHARACTER(LEN=100), ALLOCATABLE, SAVE + 列优先线性化
getinls logical scalar 512-541 长度 1 栈数组
getinl1d logical 1D 543-581 ALLOCATABLE, SAVE
getinl2d logical 2D 583-638 ALLOCATABLE, SAVE + 列优先线性化

所有 typed procedure 都遵循同一模式:

copy caller default -> tmp_ret_val
get_findkey(i_tab=1, target, pos)       ! 查 key_tab cache
if miss:
  get_fil(target, status, fileorig, typed tmp)
  get_wdb(target, status, fileorig, size, typed tmp)
else:
  get_rdb(pos, size, target, typed tmp)
copy tmp_ret_val -> caller ret_val

2D procedure 用 Fortran 列优先顺序把 (i,j) 展平成一维向量;因此 .defkey__00001key__00002 的顺序对应第一维先变。

文件读取和文本层

getin_read 是懒初始化入口,由 SAVE :: allread 保证只执行一次。初始化步骤:

  1. 分配文本表、key 表和四类 typed memory。
  2. filelist(1) 设为硬编码的 run.defnbfiles=1
  3. 循环读取 filelist(current);若遇到 INCLUDEDEF,追加文件名到 filelist,最多 max_files=100
  4. 全部文件读完后调用 getin_checkcohe 处理重复 key。

文本层使用四个并行数组:

数组 类型 含义
targetlist(:) CHARACTER(LEN=30) key 名;向量 key 使用 TARGET__NNNNN
fichier(:) CHARACTER(LEN=100) 原始 value 文本。
fromfile(:) integer 来源文件下标。
compline(:) integer 压缩行重复次数;非压缩为 -1

初始文本容量为 i_txtslab=1000 行,getin_alloctxt 按 1000 行扩容。

.def 语法行为

初始文件和 include

初始文件固定为 run.defINCLUDEDEF = file1.def file2.def 会把文件追加到 filelist,随后在同一个 DO WHILE (current <= nbfiles) 循环中读取。

文件打开失败时调用 ipslerr(2,...),属于 warning,不终止运行;相关 key 后续会回落到调用方默认值。

key/value 解析

getin_readdef 用第一个 = 分割 key 和 value:

多值和压缩

getin_decrypt 将空格分隔的多值拆成 TARGET__00001TARGET__00002 等条目。N*value 形式表示压缩重复值,compline 保存重复次数。

读取时,如果 compline(pos) > 0get_fil 会把单个解析值填充到请求数组的所有位置,并检查压缩长度是否等于请求长度。

key 数据库

缓存表类型:

TYPE :: t_key
  CHARACTER(LEN=l_n) :: keystr
  INTEGER :: keystatus, keytype, keycompress, &
             keyfromfile, keymemstart, keymemlen
END TYPE t_key

key_tab(:)memslabs=200 个条目为单位扩容。值本身存在四个 typed memory 池中:

类型 位置计数器
i_mem(:) integer i_mempos
r_mem(:) real r_mempos
c_mem(:) CHARACTER(LEN=100) c_mempos
l_mem(:) logical l_mempos

get_wdb 写缓存,get_rdb 读缓存。类型不匹配或数组长度不匹配会调用 ipslerr(3,...) fatal 终止。

keystatus

含义 设置条件
1 来自文件 请求的值全部在 .def 文本表中找到。
2 使用默认值 key 缺失,或 value 为 def/default
3 部分默认 向量中只有部分元素在文件中找到。

重复 key 由 getin_checkcohe 处理:先出现的 key 被置空,后出现的 key 保留。因此同一文件后面的值、或后读取 include 文件中的值会覆盖之前值。

类型解析

类型 解析方式 压缩写缓存
integer 格式化 READ 支持;所有元素相同且长度 > compress_lim=20 时压缩
real 自由格式 READ 支持;同 integer
character 直接截取到 CHARACTER(LEN=100) 不压缩
logical 小写化后匹配 tru/y/fal/n 不压缩

get_qtyp 要求 get_fil/get_wdb/get_rdb 只收到一种 typed OPTIONAL 参数;否则 fatal。它也是 get_rdb 类型一致性检查的基础。

getin_dump

getin_dump(fileprefix) 遍历 filelistkey_tab,按来源文件重建 .def 风格输出。它会:

注意:abort_physic 中的 getin_dump 调用在 CPP_IOIPSL 代码块内;非 IOIPSL fallback 虽然提供本过程,是否实际调用取决于编译宏和调用方代码块。

并行入口关系

本文件只实现串行 getin 语义。并行安全读取由 phy_common/ioipsl_getin_p_mod.F90 提供:

getin_p caller
  -> OMP barrier
  -> is_master thread calls getin(...)
  -> bcast result via mod_phys_lmdz_transfert_para

因此 Mars 并行 physics 配置读取依赖两层:

  1. 本文件负责从 .def 文件解析 key/value。
  2. getin_p 负责只让 master 读取并广播结果。

Mars 复现要点

  1. 先确认实际构建是否定义 CPP_IOIPSL;若定义,getin_p 可能调用外部 IOIPSL getin,否则调用本模块。
  2. 对 fallback 路径,首个读取文件一定是当前工作目录下的 run.def
  3. 缺失 include 文件是 warning,不是 fatal;很多配置错误会表现为静默使用默认值。
  4. 逗号和连续空格会被标准化;向量值可写成一行多值、续行或 key__NNNNN
  5. 同一 key 重复出现时后值覆盖前值。
  6. 同一 key 首次以某类型写入 cache 后,后续用不同类型读取会 fatal。
  7. CHARACTER 内部存储长度固定为 100,长字符串有截断风险。

待确认

相关页面