Mars utility NetCDF 和 COMMON helper 边界

源码范围:

本文只说明 Mars utility 的 NetCDF 读写方式、COMMON helper 的真实边界和复现排错顺序;start/restart/archive 文件职责见 Mars start/restart/archive 边界,COMMON 状态恢复见 Mars utility COMMON 状态使用链路

结论

Mars newstart/start2archive/archive 工具链没有直接使用 COMMON netcdf95 聚合模块,也没有直接调用 handle_err_mnew_unit_m。这些 Mars utility 主要通过:

include "netcdf.inc"
  -> NF_OPEN / NF_CREATE
  -> NF_INQ_* / NF_GET_* / NF_PUT_*
  -> 手写 ierr 检查
  -> write/print + stop 或 call abort

COMMON netcdf95 wrapper 的 nf95_* -> handle_err -> abort_physic 语义只适用于实际调用 nf95_* 的 COMMON 代码,例如 dynredem/dynredem_p 写 restart、guide_mod/guide_p_mod 写 guide 系数。不要把这套错误处理自动套到 Mars archive utility 的 NF_* 调用上。

直接 COMMON helper 交集主要是 getindatareadnc.F 通过 getin("datadir",datadir) 定位 surface.nc,1D/testphys1d 路径通过 getin 读取列模式配置。NetCDF archive 读写本身仍是 Mars 侧 F77 NetCDF API 和 Mars 侧 helper 组合。

参与者对照

文件或模块 NetCDF/helper 使用 错误处理 复现关注点
datareadnc.F include "netcdf.inc"NF_OPENsurface.ncNF_INQ_VARIDNF_GET_VAR_DOUBLE/REAL 读经纬度与 surface 变量;getin("datadir") 覆盖数据目录。 缺变量或读取失败时 write(*,*)stop datadirsurface.nc 路径、变量名、单/双精度 build。
newstart.F NF_OPEN 打开 start_archive.ncstart.nc/startfi.nc;读取 controle 后进入 lect_start_archivedynetat0/phyetat0 多处手写 ierr 检查、stopcall abort 输入选择、controle 是否存在、archive 分支与 start/startfi 分支的关闭和后续写出。
start2archive.F NF_OPENstartfi.nc 控制表;NF_OPEN(...,NF_WRITE)NF_CREATEstart_archive.nc;写 Time 后调用 ini_archive/write_archive CALL abortNF_STRERROR(ierr) + stop startfi.nc 可读、archive 是否可写、Time unlimited 维和追加位置。
ini_archive.F 定义 archive 维度、变量和属性,写 controle、经纬度、垂直坐标和固定字段。 每段写操作局部检查;不经过 handle_err_m header 变量完整性、controle 前 50/后 50 段和垂直坐标变量。
write_archive.F NF_INQ_VARID,缺变量时查维度并调用 Mars def_var,再 NF_PUT_VARA_DOUBLE/REALTime 写。 打印 NF_STRERROR(ierr)call abort 懒定义变量、维度匹配、def_var 是 Mars helper 而非 COMMON wrapper。
readhead_NC.F NF_OPEN 读 archive header、controle、经纬度、aps/bps 等。 严格缺字段时 PRINT* + CALL abortSTOP 文件维度必须匹配当前编译维度;header 缺项通常不是 fallback。
lect_start_archive.F 大量 NF_INQ_DIMID/DIMLEN/VARIDNF_GET_VAR* 读取 archive 变量,再插值/缩放。 缺字段按变量语义分为 fallback、默认或 abort。 旧 archive 兼容逻辑集中在此处,不能外推到所有 header 读取器。
COMMON netcdf95 nf95_open/create/def/get/put/att/close wrapper,供 COMMON 调用者使用。 未传 ncerr 时调用 handle_err,可关闭 ncidabort_physic 只对 nf95_* 调用生效;Mars utility NF_* 不进入此链。
COMMON new_unit_m new_unitunit=0 开始 INQUIRE,找存在且未打开的 Fortran unit。 无 NetCDF 错误处理。 当前源码没有 10..99 上限;不要沿用旧描述。

datareadnc.F 的输入链

datareadnc.F 是 Mars surface 数据读取入口。它从 datafile_mod 取默认 datadir="/u/lmdz/WWW/planets/mars/datadir",随后调用 getin("datadir",datadir) 允许 .def 文件覆盖路径,再打开 surface.nc

读取顺序可按以下方式复现:

  1. 确认运行目录或配置文件能让 getin 看到 datadir;没有配置时使用源码默认路径。
  2. 确认 surface.nc 存在,并包含 latitudelongitude 和所需 surface 变量。
  3. 代码按 NC_DOUBLE 编译分支选择 NF_GET_VAR_DOUBLENF_GET_VAR_REAL
  4. 读取后的 360x180 数据补周期列,再经 dyn3d/interp_horiz 映射到当前动力网格。

这里唯一直接 COMMON 配置 helper 是 ioipsl_getincom:getin。NetCDF 读取本身不走 netcdf95,所以缺变量时表现为局部 writestop,不是 abort_physic("NetCDF95 handle_err",...)

newstart.F 的两条 NetCDF 入口

newstart.F 先由用户选择输入类型:

复现时要把 NF_OPEN 层的“文件是否可打开”和后续恢复层分开排查。newstart 读到 controle 之后,还会重建 comconst_mod/comvert_mod/geometry_mod 等 COMMON 状态;因此 NetCDF 文件存在并不等于状态已经可写 restart。

start2archive.Fini_archive.Fwrite_archive.F

start2archive.F 是写 archive 的顶层:

startfi.nc controle
  -> dynetat0/phyetat0 恢复 start/startfi
  -> gr_fi_dyn 把物理字段转回动力 scalar 网格
  -> NF_OPEN start_archive.nc for write
  -> 若不存在则 NF_CREATE + ini_archive
  -> 写 Time
  -> write_archive 按字段追加

ini_archive.F 定义固定 header、坐标和垂直坐标变量。write_archive.F 负责按时间记录追加字段;如果字段不存在,它会调用 Mars 侧 def_var 定义变量。这是 Mars archive helper,不是 COMMON nf95_def_var

复现写出失败时,优先检查:

  1. startfi.nccontrole 能否读取。
  2. 当前目录对 start_archive.nc 是否有写权限,已有文件是否可 NF_WRITE 打开。
  3. Time 维和变量是否已由 ini_archive 定义。
  4. write_archive 要写的变量维度是否和 def_var 分支匹配。

readhead_NC.Flect_start_archive.F

readhead_NC.F 是相对严格的 header 读取器:读取 controle 后检查 im/jm/lllm 是否匹配当前编译维度,再读取经纬度、面积、地形和 aps/bps 等固定字段。缺关键字段时通常直接 CALL abortSTOP

lect_start_archive.F 更像兼容层。它读取旧 archive 的维度、垂直坐标和变量,判断是否需要水平/垂直插值,并对部分缺失变量提供 fallback 或默认行为。这个兼容性属于 archive 重建路径,不能推广为所有 NF_GET_* 调用都可以容错。

COMMON netcdf95 的边界

COMMON netcdf95.F90 聚合 simplenf95_def_var_mnf95_get_var_mnf95_put_var_m、attribute wrapper 和 handle_err_m。调用方若不传可选 ncerr,wrapper 会在底层 nf90_* 返回错误时进入:

handle_err(message,ncerr,ncid,varid)
  -> print message and nf90_strerror
  -> optional nf90_close(ncid)
  -> abort_physic("NetCDF95 handle_err","",1)

这条链在 COMMON dynredem/dynredem_pguide_mod/guide_p_modnf95_* 调用点成立。Mars utility 的 include "netcdf.inc" + NF_* 调用点不会自动进入这条链;其错误消息和终止方式取决于每个 Mars 文件自己的 ierr 分支。

复现检查清单

排查 Mars utility NetCDF 问题时,按实际路径分流:

  1. datareadnc surface 输入:检查 datadirsurface.nclatitude/longitude 和 surface 变量名。
  2. newstart archive 输入:检查 start_archive.nccontroletabfi 物理控制段、lect_start_archive 缺字段日志。
  3. newstart start/startfi 输入:检查 start.ncstartfi.nc 都存在且各自 controle 可读;再看 dynetat0/phyetat0 选择的 Time
  4. start2archive 写出:检查 startfi.nc 控制表、start_archive.nc 写权限、Time 维和 write_archive 变量定义。
  5. COMMON wrapper 报错:只有看到 nf95_*NetCDF95 handle_err 上下文时,才按 netcdf95 wrapper 链排查。

风险和待确认

相关页面