typed getin* 解析约定:scalar/1D/2D integer/real/logical/character

输入范围

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

本页范围

本页覆盖 ioipsl_getincom.F90 中 12 个 typed getin* specific procedure 和 ioipsl_getin_p_mod.F90 中 11 个 getin_p_* 并行 wrapper 的完整解析约定。getin-fallback-file-precedence 覆盖文件来源和 key 表机制;本页聚焦每个 typed procedure 的签名、tmp 缓冲、2D 线性化、类型特异性和并行 wrapper 差异。

12 个 typed specific procedure 总览

Procedure 类型 维度 行号 tmp 缓冲策略
getinis INTEGER scalar 122-151 DIMENSION(1) 栈数组
getini1d INTEGER 1D 153-191 ALLOCATABLE, SAVE + tmp_ret_size 追踪
getini2d INTEGER 2D 193-248 ALLOCATABLE, SAVE + 列优先线性化
getinrs REAL scalar 252-281 DIMENSION(1) 栈数组
getinr1d REAL 1D 283-321 ALLOCATABLE, SAVE + tmp_ret_size 追踪
getinr2d REAL 2D 323-378 ALLOCATABLE, SAVE + 列优先线性化
getincs CHARACTER scalar 382-411 CHARACTER(LEN=100), DIMENSION(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 DIMENSION(1) 栈数组
getinl1d LOGICAL 1D 543-581 ALLOCATABLE, SAVE + tmp_ret_size 追踪
getinl2d LOGICAL 2D 583-638 ALLOCATABLE, SAVE + 列优先线性化

所有 12 个 procedure 通过 INTERFACE getin 泛型绑定,调用方只需 CALL getin(target, ret_val) 即可由编译器自动分派。

通用调用模式

所有 typed procedure 遵循相同的 6 步模式:

① get_findkey(i_tab=1, target, pos)     ! key_tab 线性查找
② tmp_ret_val ← ret_val                  ! 保存调用方默认值到 tmp
③ IF (pos < 0) THEN                       ! key_tab 未命中
④   get_fil(target, status, fileorig, <typed>_val=tmp_ret_val)
⑤   get_wdb(target, status, fileorig, size, <typed>_val=tmp_ret_val)
⑥ ELSE                                    ! key_tab 命中
⑦   get_rdb(pos, size, target, <typed>_val=tmp_ret_val)
⑧ ENDIF
⑨ ret_val ← tmp_ret_val                  ! 回写到调用方

关键约定点:

Scalar 约定

标量 procedure(getinis/getinrs/getincs/getinls)使用固定的 DIMENSION(1) tmp 数组:

INTEGER, DIMENSION(1) :: tmp_ret_val    ! 或 REAL/CHARACTER(LEN=100)/LOGICAL
tmp_ret_val(1) = ret_val
CALL get_fil(target, status, fileorig, i_val=tmp_ret_val)
ret_val = tmp_ret_val(1)

无需动态分配,size_of_in 恒为 1。

1D 约定

1D procedure(getini1d/getinr1d/getinc1d/getinl1d)使用 ALLOCATABLE, SAVE tmp 数组配合 tmp_ret_size 追踪:

INTEGER, DIMENSION(:), ALLOCATABLE, SAVE :: tmp_ret_val
INTEGER, SAVE :: tmp_ret_size = 0
!-
size_of_in = SIZE(ret_val)
IF (.NOT.ALLOCATED(tmp_ret_val)) THEN
  ALLOCATE(tmp_ret_val(size_of_in))
ELSE IF (size_of_in > tmp_ret_size) THEN
  DEALLOCATE(tmp_ret_val)
  ALLOCATE(tmp_ret_val(size_of_in))
  tmp_ret_size = size_of_in
ENDIF
tmp_ret_val(1:size_of_in) = ret_val(1:size_of_in)

约定要点:

2D 约定与列优先线性化

2D procedure(getini2d/getinr2d/getinc2d/getinl2d)需要额外的维度处理:

INTEGER :: size_1, size_2, jl, jj, ji
size_of_in = SIZE(ret_val)         ! 总元素数 = size_1 * size_2
size_1 = SIZE(ret_val, 1)          ! 第一维
size_2 = SIZE(ret_val, 2)          ! 第二维

2D → 1D 线性化采用 Fortran 列优先顺序

! 2D → 1D(写入前)
jl = 0
DO jj = 1, size_2
  DO ji = 1, size_1
    jl = jl + 1
    tmp_ret_val(jl) = ret_val(ji, jj)
  ENDDO
ENDDO

! 1D → 2D(读回后)
jl = 0
DO jj = 1, size_2
  DO ji = 1, size_1
    jl = jl + 1
    ret_val(ji, jj) = tmp_ret_val(jl)
  ENDDO
ENDDO

这意味着 2D key 在 .def 文件中的向量元素按列优先排列:key__00001 对应 (1,1)key__00002 对应 (2,1)(假设 size_1 >= 2),以此类推。

类型特异性

get_qtyp 类型检测

所有底层子程序(get_filget_wdbget_rdb)通过 get_qtyp 检测实际传入的 OPTIONAL 参数类型:

k_typ = 0
IF (COUNT([PRESENT(i_v), PRESENT(r_v), PRESENT(c_v), PRESENT(l_v)]) /= 1) THEN
  CALL ipslerr(3, 'get_qtyp', 'Invalid number of optional arguments', '(/= 1)', ' ')
ENDIF
IF     (PRESENT(i_v)) THEN; k_typ = k_i; c_vtyp = 'INTEGER'
ELSEIF (PRESENT(r_v)) THEN; k_typ = k_r; c_vtyp = 'REAL'
ELSEIF (PRESENT(c_v)) THEN; k_typ = k_c; c_vtyp = 'CHARACTER'
ELSEIF (PRESENT(l_v)) THEN; k_typ = k_l; c_vtyp = 'LOGICAL'
ENDIF

必须且只能有一个 typed OPTIONAL 参数被传入。get_qtyp 同时返回类型码和名称字符串(用于错误消息)。

INTEGER 特异性

REAL 特异性

CHARACTER 特异性

LOGICAL 特异性

压缩字段类型限制

类型 支持压缩 原因
INTEGER MINVAL/MAXVAL 可比较
REAL MINVAL/MAXVAL 可比较
CHARACTER 字符串无自然序比较
LOGICAL 布尔值无自然数值比较

压缩条件:所有元素相同(MINVAL == MAXVAL 元素数 > compress_lim=20。满足时 keycompress = size_of_inkeymemlen = 1

getin_p 并行 wrapper 对照

ioipsl_getin_p_mod.F90 提供 11 个并行 wrapper(无 character 2D):

Wrapper 对应 getin bcast 方式
getinrs_p getinrs bcast(VarOut) 标量
getinr1d_p getinr1d bcast(VarOut) 整体
getinr2d_p getinr2d bcast(VarOut) 整体
getinis_p getinis bcast(VarOut) 标量
getini1d_p getini1d bcast(VarOut) 整体
getini2d_p getini2d bcast(VarOut) 整体
getincs_p getincs bcast(VarOut) 标量
getinc1d_p getinc1d 逐元素 bcast(VarOut(i))
getinls_p getinls bcast(VarOut) 标量
getinl1d_p getinl1d bcast(VarOut) 整体
getinl2d_p getinl2d bcast(VarOut) 整体

每个 wrapper 的模式:

!$OMP BARRIER
IF (is_master) THEN
  CALL getin(VarIn, VarOut)
ENDIF
CALL bcast(VarOut)

character 1D 逐元素 bcast

getinc1d_p 是唯一不直接整体 bcast 的 wrapper:

DO i = 1, size(VarOut)
  CALL bcast(VarOut(i))
ENDDO

原因:Fortran CHARACTER(LEN=*) 数组的内存布局可能不连续(每个元素有独立的长度描述符),不能安全地作为单一 buffer 广播。

缺失的 getinc2d_p

基础 getin 接口有 getinc2d(character 2D),但 getin_p 没有对应的 getinc2d_p。如果并行上下文需要读取 2D character 配置,需要手动实现 master-read + 逐元素 bcast。

默认值保留语义

所有 typed procedure 在进入文件解析前,先将 ret_val 复制到 tmp_ret_val。这意味着:

  1. 若 key 在文件中不存在(get_fil 返回 status=2),tmp_ret_val 保持调用方原始默认值。
  2. 对于向量 key,部分找到的元素被文件值覆盖,未找到的保留默认值(status=3)。
  3. "def""default" 作为 value 时,该元素被视为未找到,保留默认值。

调用方模式:

INTEGER :: niter = 100          ! 默认值 100
CALL getin('niter', niter)      ! 若 run.def 中有 niter=200,则 niter=200
                                ! 若 run.def 中无 niter,则 niter=100(保留默认)

类型不匹配错误

get_rdb 在从 key 表读取时校验类型:

IF (key_tab(pos)%keytype /= k_typ) THEN
  CALL ipslerr(3, 'get_rdb', &
    'Wrong data type for keyword '//TRIM(target), &
    '(NOT '//TRIM(c_vtyp)//')', ' ')
ENDIF

如果同一 key 名第一次被 INTEGER getin 写入 key_tab(keytype=k_i),后续用 REAL getin 读取同一 key 会触发 fatal error。这要求调用方对同一 key 始终使用相同类型。

数组长度不匹配错误

get_rdb 同时校验数组长度:

! 非压缩字段
IF (key_tab(pos)%keymemlen /= size_of_in) THEN
  CALL ipslerr(3, 'get_rdb', 'Wrong array length', 'for keyword '//TRIM(target), ' ')
ENDIF

! 压缩字段
IF (key_tab(pos)%keycompress /= size_of_in .OR. key_tab(pos)%keymemlen /= 1) THEN
  CALL ipslerr(3, 'get_rdb', 'Wrong compression length', 'for keyword '//TRIM(target), ' ')
ENDIF

调用方数组大小必须与首次写入时的大小一致。

Mars 侧典型使用

相关页面