Mars 垂直坐标与动力-物理共享状态约定

源码:

本文只覆盖 COMMON 垂直坐标状态如何生成、复制到物理侧、被 Mars utility/physics 使用;Mars 文件只作为使用位置和接口边界。

结论

Mars/Generic 默认垂直坐标链是:

iniconst
  -> disvert_type default = 2 when planet_type != "earth"
  -> disvert_noterre
      -> read esasig.def or z2sig.def
      -> write comvert_mod: ap/bp/aps/bps/presnivs/pseudoalt
  -> inigeom
  -> iniphysiq
      -> inigeomphy
          -> init_vertical_layers(...)
          -> copy comvert_mod state into phy_common/vertical_layers_mod
  -> Mars physiq/outputs/1D/archive consumers

comvert_mod 是动力侧固定维度数组状态;vertical_layers_mod 是物理侧 ALLOCATABLE, SAVE, THREADPRIVATE 状态。两者不是自动共享内存,必须通过 inigeomphy -> init_vertical_layers 或 1D 初始化显式复制。

状态表

状态 所在模块 维度 单位/含义 主要使用位置
ap(llm+1) comvert_mod, vertical_layers_mod interface Pa,hybrid pressure contribution pression, Mars physics, archive/output
bp(llm+1) 同上 interface sigma contribution pression, vertical velocity, Mars physics
aps(llm) 同上 mid-layer Pa,mid-layer pressure contribution Mars vertical interpolation, physics zplay
bps(llm) 同上 mid-layer sigma contribution Mars vertical interpolation, physics zplay
presnivs(llm) 同上 mid-layer reference mid-layer pressure, Pa history/XIOS vertical axes, physics diagnostics, dissipation profiles
pseudoalt(llm) 同上 mid-layer km, -scaleheight*log(presnivs/preff) Mars/XIOS/stats/diagfi altitude axis
pa comvert_mod scalar Pa,hybrid 坐标转 pressure-dominated 的参考压力 disvert, disvert_noterre, restart constants
preff comvert_mod and copied to vertical_layers_mod scalar Pa,reference surface pressure pressure axes and pseudo altitude
scaleheight comvert_mod and copied to vertical_layers_mod scalar km pseudoalt, dissipation/profile diagnostics
disvert_type comvert_mod scalar 1 Earth automatic, 2 planets z2sig/ esasig iniconst branch
pressure_exner comvert_mod scalar layer pressure computation option Exner/pressure helper consumers

disvert_noterre 生成逻辑

disvert_noterre 是 Mars/Generic 默认路径。入口先设置:

esasig.def 分支

esasig.def 分支读取:

  1. scaleheight
  2. dz0
  3. dz1
  4. nhaut

然后把 dz0/dz1 除以 scaleheight,用指数和双曲正切构造 interface sig(1:llm+1)。该分支还构造 s(l) 并归一化,源码注释强调它来自能量守恒相关旧方案。

z2sig.def 分支

z2sig.def 分支读取:

  1. 第一行 scaleheight
  2. 接下来 llmzsig(l)

若行数少于 llm,调用 abort_gcm(modname,"z2sig.def too short?",1)。若多于 llm,只写 WARNING,不 abort。

interface sigma 的构造是:

sig(1) = 1
sig(l) = 0.5 * ( exp(-zsig(l)/scaleheight)
               + exp(-zsig(l-1)/scaleheight) ), l=2..llm
sig(llm+1) = 0

这意味着 z2sig.def 给的是层中心或目标高度序列,disvert_noterre 用相邻高度的指数压力平均构造 interface sigma。

hybrid 与 sigma 分支

nivsigs(l)=lnivsig(l)=l 只是垂直层索引。

hybrid=.true.

sig_hybrid(sig(l), pa, preff, newsig)
bp(l) = exp(1 - 1/newsig**2)
ap(l) = pa * (newsig - bp(l))
bp(llm+1) = 0
ap(llm+1) = 0

sig_hybrid 求解的目标方程是:

(1 - pa/preff) * exp(1 - 1/newsig**2)
  + (pa/preff) * newsig = sig

sig*preff/pa < 0.25 时,源码直接用 newsig=sig*preff/pa;其他情况使用二分迭代,收敛标准按 pseudo-altitude 误差约束。

hybrid=.false.

ap(l) = 0
bp(l) = sig(l)
ap(llm+1) = 0
bp(llm+1) = 0

mid-layer 与参考压力

大多数层:

aps(l) = 0.5 * (ap(l) + ap(l+1))
bps(l) = 0.5 * (bp(l) + bp(l+1))

顶层特殊处理:

然后:

presnivs(l) = aps(l) + bps(l) * preff
pseudoalt(l) = -scaleheight * log(presnivs(l)/preff)

源码注释提醒:顶层 mid-layer 选择是人为约定,并要求与 exner_milieu.F 使用相同假设。

disvert.F90 对照

disvert.F90 是 Earth/通用自动生成路径,iniconstplanet_type=="earth" 时默认选择它。它支持 vert_sampling

它同样写入 comvert_mod: ap/bp/nivsigs/nivsig/preff/pa/presnivs/dpres/scaleheight,但 Mars/Generic 默认不走这条路径,除非 run.def 显式覆盖 disvert_type=1

动力侧压力使用

动力核通过 pression(ngrid, ap, bp, ps, p) 计算 interface pressure:

p(:,l) = ap(l) + bp(l) * ps(:)

典型使用位置包括:

复制到物理侧

Mars iniphysiq_mod.F90 先调用 COMMON inigeomphyinigeomphy_mod.F90 第 22-24 行 USE comvert_mod 读取 preff, ap, bp, aps, bps, presnivs, scaleheight, pseudoalt,第 243-245 行调用:

CALL init_vertical_layers(nlayer, preff, scaleheight,
                          ap, bp, aps, bps, presnivs, pseudoalt)

vertical_layers_mod 为物理侧分配数组并复制这些值。由于该模块变量是 THREADPRIVATE,OpenMP 运行中每个线程有自己的物理侧垂直层状态。

Mars physiq_mod.F 直接 USE vertical_layers_mod, ONLY: ap,bp,aps,bps,presnivs,pseudoalt

Mars callphysiq_mod.F90 仍从动力-物理接口接收 zplev/zplay/presnivs,但 physics 内部的垂直坐标常量来自 vertical_layers_mod

Mars utility 和 archive 约定

ini_archive.F

ini_archive.Fcomvert_mod 读取 ap,bp,aps,bps,pa,preff,presnivs,pseudoalt,写入 archive 变量:

readhead_NC.F

readhead_NC.F 用于读取 header/control。它 USE comvert_mod, ONLY: aps,bps,preff,并要求 NetCDF 中存在 apsbps;缺失或读取失败都会 CALL abort

lect_start_archive.F

lect_start_archive.F 读取旧 archive 做插值:

这说明 archive 兼容层对旧文件有 fallback,但当前 header 读取链对 aps/bps 更严格。

newstart.Fstart2archive.F

newstart.F 在初始化 physics 前调用 iniphysiq,因此会经 inigeomphy 初始化 vertical_layers_mod;后续在写新 start/startfi 前调用 pression(ip1jmp1, ap, bp, ps, p3d)

start2archive.F 先调用 iniconst/inigeom/inifilr,再调用 iniphysiq,随后用 pression(ap,bp,ps,p3d)exner_hyb 准备 archive 转换。

1D/testphys1d 约定

Mars 1D 初始化 init_testphys1d_mod.F90 直接使用 COMMON 转发的 comvert_mod

  1. 设置或读取 psurfpapreff
  2. 设置 hybrid=.true.,再由 getin("hybrid",hybrid) 覆盖。
  3. 调用 disvert_noterre
  4. 调用 init_vertical_layers(nlayer,preff,scaleheight,ap,bp,aps,bps,presnivs,pseudoalt)
  5. 计算 plev=ap+psurf*bpplay=aps+psurf*bps

这条链不经过 3D iniphysiq,所以 1D 必须自己完成 comvert_mod -> vertical_layers_mod 的复制。

复现检查清单

  1. 确认 planet_typedisvert_type:Mars/Generic 默认 disvert_type=2
  2. 确认运行目录有 esasig.defz2sig.def;若两者都有,esasig.def 优先。
  3. 确认 pa/preff 来源:restart controleconf_planete、或 1D 初始化默认/输入。
  4. 确认 hybrid:默认 .true.,可由 getin("hybrid") 覆盖为纯 sigma。
  5. 检查 ap/bp/aps/bps 是否写入 comvert_mod 后再调用 inigeomphy 或 1D init_vertical_layers
  6. 若处理 archive,检查 aps/bps 是否存在;旧 archive 只有 sig_s 时只能走 lect_start_archive fallback,不适合所有读取器。
  7. 若排查输出坐标,确认 presnivs 是 Pa,history 常把它除以 100 写成 mb,而 pseudoalt 是 km。

风险和待确认

相关页面