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.def 和 INCLUDEDEF 指定的其它文件,查找 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) 展平成一维向量;因此 .def 中 key__00001、key__00002 的顺序对应第一维先变。
文件读取和文本层
getin_read 是懒初始化入口,由 SAVE :: allread 保证只执行一次。初始化步骤:
- 分配文本表、key 表和四类 typed memory。
- 将
filelist(1)设为硬编码的run.def,nbfiles=1。 - 循环读取
filelist(current);若遇到INCLUDEDEF,追加文件名到filelist,最多max_files=100。 - 全部文件读完后调用
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.def。INCLUDEDEF = file1.def file2.def 会把文件追加到 filelist,随后在同一个 DO WHILE (current <= nbfiles) 循环中读取。
文件打开失败时调用 ipslerr(2,...),属于 warning,不终止运行;相关 key 后续会回落到调用方默认值。
key/value 解析
getin_readdef 用第一个 = 分割 key 和 value:
- key 经过
ADJUSTL/TRIM。 - value 先经
nocomma将逗号转为空格,再经cmpblank压缩连续空格。 - 无
=的非空行被视为上一 key 的续行,用于向量值。 key__1这类下标会规整为 5 位零填充:key__00001。
多值和压缩
getin_decrypt 将空格分隔的多值拆成 TARGET__00001、TARGET__00002 等条目。N*value 形式表示压缩重复值,compline 保存重复次数。
读取时,如果 compline(pos) > 0,get_fil 会把单个解析值填充到请求数组的所有位置,并检查压缩长度是否等于请求长度。
key 数据库
缓存表类型:
TYPE :: t_key
CHARACTER(LEN=l_n) :: keystr
INTEGER :: keystatus, keytype, keycompress, &
keyfromfile, keymemstart, keymemlen
END TYPE t_keykey_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) 遍历 filelist 和 key_tab,按来源文件重建 .def 风格输出。它会:
- 为 include 文件写出
INCLUDEDEF = ...。 - 根据
keystatus写注释,区分来自run.def、全部默认、部分默认。 - 按
keytype从对应 typed memory 池写 value。 - 对压缩或长向量使用
key__NNNNN形式展开。
注意: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 配置读取依赖两层:
- 本文件负责从
.def文件解析 key/value。 getin_p负责只让 master 读取并广播结果。
Mars 复现要点
- 先确认实际构建是否定义
CPP_IOIPSL;若定义,getin_p可能调用外部 IOIPSLgetin,否则调用本模块。 - 对 fallback 路径,首个读取文件一定是当前工作目录下的
run.def。 - 缺失 include 文件是 warning,不是 fatal;很多配置错误会表现为静默使用默认值。
- 逗号和连续空格会被标准化;向量值可写成一行多值、续行或
key__NNNNN。 - 同一 key 重复出现时后值覆盖前值。
- 同一 key 首次以某类型写入 cache 后,后续用不同类型读取会 fatal。
CHARACTER内部存储长度固定为 100,长字符串有截断风险。
待确认
- 外部 IOIPSL
getin与本 fallback 在 INCLUDEDEF、重复 key 和压缩字段上的细微兼容性未在本页验证;本页只覆盖 COMMON fallback 源码。 getin_dump在当前 Mars 标准非 IOIPSL构建中是否实际触发,需要结合具体编译宏和abort_physic分支确认。