Mars utility 常量和垂直坐标使用链路

源码范围:

本文只解释 Mars utility 如何读取、重建、写回 COMMON 常量和垂直坐标状态;更宽的 start/restart/archive 文件职责见 Mars start/restart/archive 边界,垂直离散公式见 Mars 垂直坐标约定

NetCDF 读写和 helper 边界见 Mars utility NetCDF 和 COMMON helper 边界:Mars archive utilities 主要直接使用 netcdf.inc/NF_*,COMMON netcdf95/handle_err 只适用于实际 nf95_* 调用链。

结论

Mars newstart/start2archive/archive 工具不是只搬 NetCDF 变量。它们会把 archive 或 start/startfi 中的控制量重新灌回 COMMON 状态模块,再调用 COMMON 初始化链重建当前编译网格下的常量、垂直坐标和物理侧垂直层副本。

核心链路是:

archive/start header or Mars defaults
  -> comconst_mod: rad/omeg/g/cpp/kappa/r/daysec/dtvr/dtphys
  -> comvert_mod: ap/bp/aps/bps/pa/preff/presnivs/pseudoalt
  -> iniconst/inigeom/iniphysiq
  -> inigeomphy -> init_vertical_layers
  -> vertical_layers_mod physical-side copy
  -> archive write, vertical interpolation, physics restart/writeout

这条链的关键边界是:comvert_mod 是动力侧固定维度数组,vertical_layers_mod 是物理侧 ALLOCATABLE, SAVE, THREADPRIVATE 副本。两者不会自动同步,必须由 inigeomphy -> init_vertical_layers 或 1D 初始化显式复制。

状态提供者

模块 状态 维度和含义 Mars utility 使用方式
comconst_mod im,jm,lllm, dtvr, daysec, dtphys, rad, omeg, g, r, cpp, kappa, pi 动力维度、时间步和行星常量 newstart/readhead_NC/ini_archive/start2archive 读写 controlelect_start_archivekappa/g/pi 重构热力和守恒量,datareadncg/pi 做地形和角度换算。
comvert_mod ap,bp,aps,bps,presnivs,pseudoalt,pa,preff,scaleheight 动力侧 hybrid/sigma 垂直层状态 ini_archive 写入 archive;lect_start_archive 用新旧 ap/bp/aps/bps/preff 做垂直重映射;newstart/start2archive 在压力、Exner 和写出前使用。
vertical_layers_mod ap,bp,aps,bps,presnivs,pseudoalt,preff,scaleheight 物理侧 allocatable/threadprivate 副本 inigeomphy 或 1D init_testphys1dinit_vertical_layers 后供 Mars physics/XIOS/diagfi 使用。

vertical_layers_mod.F90init_vertical_layers(nlayer,...) 只分配并复制输入数组,不重新计算垂直坐标。因此上游必须先保证 comvert_mod 中的 ap/bp/aps/bps/presnivs/pseudoalt 已经由 restart/header 或 disvert_noterre 等初始化路径生成。

newstart.F 的重建顺序

newstart.F 读取 start_archive.ncstart.nc/startfi.nc 后,会同时恢复 Mars 物理控制量和 COMMON 动力状态:

  1. 入口 USE comvert_mod, ONLY: ap,bp,pa,preff,并从 comconst_modlllm/daysec/dtphys/dtvr/cpp/kappa/rad/omeg/g/r/pi
  2. 初始 Mars 常量先给默认值:cpp=744.499preff=610.。这不是最终唯一来源,后续会结合 controletabfi 重写。
  3. 从 archive 或 start/startfi 读取 controle,把 kappa 和守恒基准量写回 COMMON 动力状态。
  4. tabfi 读 Mars physics 控制量,再写回 rad/omeg/g/daysec;随后根据 day_step 计算 dtvr=daysec/day_step,并派生 dtphys=dtvr*iphysiq
  5. iniconstinigeom 后再调 Mars iniphysiqiniphysiq 内会进入 COMMON inigeomphy,把动力侧垂直层复制到 vertical_layers_mod
  6. 从 archive 分支进入 lect_start_archive;从 start/startfi 分支进入 dynetat0/phyetat0。二者之后再写新的 restart.nc/restartfi.nc

复现要点:newstartpreff=610. 是 Mars utility 保护性默认值,但 archive/start 分支仍会把大量控制量从文件读回。不要把这一行理解为所有垂直坐标都绕过 controledisvert_noterre

start2archive.F 的合并顺序

start2archive.Fstart.nc/startfi.nc 合成 start_archive.nc

  1. USE comvert_mod, ONLY: ap,bp,并从 comconst_moddaysec/dtphys/rad/g/r/cpp
  2. defrun_newinfotrac_init,再调用 dynetat0start.nc 恢复动力状态。
  3. iniconst/inigeom/inifilr/iniphysiq 之后,COMMON 常量、几何和物理侧垂直层状态才对后续 archive 写出可用。
  4. 物理网格字段通过 gr_fi_dyn 回到动力 scalar 网格。
  5. 若 archive 不存在,调用 ini_archive 写头、controle 和垂直坐标;随后写当前 Time=day_ini+hour_ini 以及 2D/3D 变量。

复现要点:start2archive 依赖 dynetat0phyetat0/tabfi 分别恢复动力与物理状态,但 archive 头中的常量和垂直坐标来自当前 COMMON 全局状态。因此如果先前的 iniconst/inigeom/iniphysiq 顺序被跳过,ini_archive 写出的 header 会不完整或不一致。

archive header 的写回和读取

ini_archive.F 是写出方向。它从 comconst_modcomvert_mod 读取状态,填入长度 100 的 tab_cntrl

同一例程还定义并写出 ap,bp,aps,bps,presnivs,pseudoalt。这些变量让后续 archive 可同时支持动力侧 pressure 计算、物理侧 vertical axis 和旧网格到新网格的垂直插值。

readhead_NC.F 是读取方向。它把 controle 写回 im/jm/lllm/day_ini/rad/omeg/g/cpp/kappa/daysec/dtvr 和能量基准量,再设置 r=kappa*cpp。源码中 preff=610. 覆盖了注释里的 tab_cntrl(18) 读取路径,并带有“diagfi 不一定适用”的注释。这是 Mars utility 的特殊边界:readhead_NC 并不等价于完整反序列化 ini_archive 的每一个字段。

lect_start_archive.F 的垂直插值使用

lect_start_archive.Fnewstart 从 archive 重建 start 的核心读入器。它直接 USE comvert_mod, ONLY: ap,bp,aps,bps,preff,并从 comconst_modkappa,g,pi

关键使用点:

复现要点:lect_start_archive 是兼容旧 archive 的地方。它可以处理某些旧变量名或缺失分支,但这种 fallback 不应推广到 readhead_NCini_archive 或其他读取器。

datareadnc.F 的常量使用

datareadnc.F 不使用垂直坐标,但使用 COMMON 常量接口。它从 comconst_modg,pi,读取 surface.nc 并把地形、反照率、热惯量等插值到当前动力网格:

这说明 Mars utility 的常量使用不只在 archive header 内,也贯穿 surface 初始化和网格插值输入准备。

1D/testphys1d 边界

Mars 1D 路径通过 phymars/dyn1d 转发文件暴露 COMMON 模块名,但初始化顺序不同于 3D GCM:

  1. init_testphys1d_mod.F90 手写 Mars 常量:rad=3397200., daysec=88775., g=3.72, mugaz=43.49,并派生 r/cpp/rcp
  2. 默认 psurf=610.pa=50.preff=610.,也可以从 start1D.txttestphys1d.def 覆盖。
  3. disvert_noterre 写入 comvert_mod
  4. 立即调用 init_vertical_layers(nlayer,preff,scaleheight,ap,bp,aps,bps,presnivs,pseudoalt)
  5. plev=ap+psurf*bpplay=aps+psurf*bpsphysiq 调用;主循环中 surface pressure 变化后再重算 plev/play

复现要点:1D 是接口兼容路径,不走 3D newstart/start2archive 的 archive header 链,也不应把 1D 的手写常量顺序误写成 3D GCM 的正常初始化顺序。

检查清单

复现或排查 Mars utility 常量/垂直状态时,按以下顺序检查:

  1. 文件来源:当前路径是 archive、start/startfi、还是 1D 文本 restart。
  2. 常量来源:rad/omeg/g/daysec/kappa/cpp/r/dtvr/dtphys 是从 controle/tabfi 恢复,还是由 1D/Mars 默认值重建。
  3. 垂直坐标来源:ap/bp/aps/bps/presnivs/pseudoalt 是从当前 disvert_noterre 生成,还是由 archive 变量参与插值。
  4. 物理侧副本:是否已经调用 iniphysiq -> inigeomphy -> init_vertical_layers,或 1D 直接调用 init_vertical_layers
  5. preff 边界:newstart/readhead_NC/init_testphys1d 存在 Mars 610 Pa 默认或覆盖,不能简单假设 tab_cntrl(18) 在所有工具中原样生效。
  6. 旧 archive 兼容:lect_start_archive 的 fallback 只属于 archive 读入插值路径,不能替代 header 读取器的要求。

风险和待确认

相关页面