nlthermeq.F
路径
LMDZ.MARS\libf\phymars\nlthermeq.F
所属目录 / 模块
libf/phymars
文件定位
nlthermeq.F 提供 nlthermeq_mod 模块和唯一入口 nlthermeq,负责在辐射调用链中计算 LTE 长波/短波辐射还需要覆盖到第几层。计算结果不作为参数返回,而是写入 yomlw_h::nlaylte 这个共享状态;随后 callradite_mod.F 只在 1:nlaylte 层运行 LTE 辐射,blendrad.F 在这些层内把 LTE 与 NLTE 倾向平滑混合,并在 nlaylte+1:nlayer 层放弃 LTE 倾向。
它不是 NLTE 冷却率本体。nltecool.F 与 nlte_tcool_mod.F 计算 zdtnlte,nlteparams_h.F90 给出 ptrans/zw/pminte/zwi,而本文件只把 pminte=0.04 Pa 这类阈值投影到当前 GCM 垂直层索引 nlaylte 上。
定义的符号
| 符号 |
类型 |
行号 |
作用 |
nlthermeq_mod |
module |
1 |
封装 LTE 覆盖层选择入口。 |
nlthermeq |
subroutine |
7 |
根据当前层压强剖面和 callnlte 开关写入 yomlw_h::nlaylte。 |
igpmax |
saved local integer |
29 |
首次调用时记录表面压力最大的水平格点索引,后续调用沿用。 |
firstcall |
saved local logical |
30 |
控制首次调用初始化、打印过渡参数和 igpmax 搜索;与 igpmax 一起声明为 OpenMP THREADPRIVATE。 |
依赖的模块
| use 模块 |
only 列表 |
用途 |
待确认 |
yomlw_h |
nlaylte |
保存 LTE 辐射计算的层数上限;本文件写入,长波/短波辐射和 blendrad 读取。 |
否 |
nlteparams_h |
ptrans, pminte, zw |
首次调用时打印过渡中心和半宽;用 pminte 作为 nlaylte 搜索阈值。 |
否 |
callkeys_mod |
callnlte |
决定是否执行 NLTE 模式的阈值搜索;关闭时强制 nlaylte=nlayer。 |
否 |
调用的关键例程
| 被调用例程 |
所在模块 / 文件 |
调用位置 |
作用 |
ismax |
外部例程,未在本文件 use |
44 |
在 pplev 的第一列跨度上寻找最大表面压力格点索引,作为保守参考列。 |
输入
| 输入 |
来源 |
类型 / 维度 |
单位 |
含义 |
ngrid |
physiq_mod.F 调用参数 |
integer |
- |
水平格点数。 |
nlayer |
physiq_mod.F 调用参数 |
integer |
- |
GCM 垂直层数。 |
pplev(ngrid,nlayer+1) |
physiq_mod.F::zplev |
real array |
Pa |
层界面压强;首次调用时用于寻找最大表面压力格点。 |
pplay(ngrid,nlayer) |
physiq_mod.F::zplay |
real array |
Pa |
层中心压强;用于在参考列上从顶向下寻找 pplay > pminte 的第一层。 |
callnlte |
callkeys_mod |
logical saved config |
- |
NLTE 辐射开关;关闭时 LTE 覆盖全部层。 |
pminte |
nlteparams_h |
real parameter |
Pa |
LTE 辐射至少应覆盖到的压强阈值,当前为 0.4*ptrans=0.04 Pa。 |
输出
| 输出 |
去向 |
类型 / 维度 |
单位 |
含义 |
nlaylte |
yomlw_h |
saved integer |
层索引 |
LTE 长波/短波辐射的有效层数上限;callradite、lw*、sw* 和 blendrad 读取。 |
| 标准输出诊断 |
运行日志 |
text |
- |
首次调用打印 ptrans/zw/pminte,每次调用打印 LTE rad. calculations up to layer 和 nlaylte。 |
共享状态与副作用
nlaylte 是 yomlw_h.F90 中的 integer,save,并且在 yomlw_h 中声明为 OpenMP THREADPRIVATE。本文件的主要副作用就是写入该共享变量。
igpmax 与 firstcall 是本文件内部 save 状态,也声明为 THREADPRIVATE(firstcall,igpmax)。每个线程首次进入时都会重新找一次最大表面压力格点并打印过渡参数。
physiq_mod.F 在每个 sol 的第一个物理步附近调用 nlthermeq:源码注释写明 “done only once per sol”,调用条件是 MOD((icount-1),steps_per_sol).EQ.0。
- 本文件不会读写外部文件,也不会分配数组;副作用集中在共享整数、局部缓存和标准输出。
核心逻辑
- 首次进入当前线程时,调用
ismax(ngrid, pplev, 1) 找到表面压力最大的水平格点 igpmax。源码注释把它称为 worst possible case,并说明在有地形时该位置变化不大。
- 同一次首次调用打印
ptrans、zw 和 pminte,然后把 firstcall 置为 .false.。
- 若
callnlte=.true.,从顶层 nlayer 向下扫描参考列 pplay(igpmax,:),把循环变量本身作为 nlaylte。遇到第一层满足 pplay(igpmax,nlaylte) > pminte 时跳出。
- 若
callnlte=.false.,直接令 nlaylte=nlayer,表示 LTE 辐射覆盖全部层。
- 打印最终
nlaylte。下游 callradite_mod.F 会把 nlaylte+1:nlayer 的 LTE 短波和长波倾向置零,blendrad.F 则在 1:nlaylte 计算 LTE/NLTE 权重混合。
伪代码
if firstcall for this OpenMP thread:
igpmax = index of maximum pplev(:,1)
print ptrans, zw, pminte
firstcall = false
if callnlte:
for nlaylte from nlayer down to 1:
if pplay(igpmax, nlaylte) > pminte:
exit loop
else:
nlaylte = nlayer
print nlaylte
参与的主题流程
| 主题 |
参与方式 |
| 辐射计算 |
在 physiq 的辐射调用前确定 LTE 辐射覆盖层数,限制 callradite、长波和短波辐射的有效层范围。 |
| LTE/NLTE 辐射过渡 |
把 nlteparams_h::pminte 映射为层索引 nlaylte,供 blendrad 在 LTE 与 NLTE 倾向之间切换。 |
| 高层大气 NLTE |
与 nltecool / nlte_tcool_mod 互补:它不计算 NLTE 冷却率,只决定 LTE 方案还需要算到哪里。 |
写法特点
- 固定格式 Fortran 文件,使用列 1 的
c 注释和标签 100 / 10 / 20 / 30。
- 循环变量
nlaylte 直接是模块变量,不是局部临时量;do nlaylte = nlayer, 1, -1 结束或 go to 100 后,下游读取的就是该模块状态。
- 首次调用缓存
igpmax 的策略刻意牺牲一般性来减少重复搜索。源码注释明确指出 MESOSCALE nesting 或并行 GCM 可能有问题,但又说明当前 pminte=0.04 和 hybrid 垂直坐标使过渡点处于纯压力层,因此通常相同。
复现要点
pplev 和 pplay 必须使用 Pa,与 nlteparams_h::pminte 的单位一致。
nlthermeq 需要在 callradite 和 blendrad 之前运行;physiq_mod.F 当前调用顺序满足这一点。
- 若
callnlte=.false.,nlaylte=nlayer,后续不应调用 blendrad,physiq_mod.F 当前也在该分支直接相加 zdtsw+zdtlw+zdtnirco2。
- 复现风险:如果改用复杂地形、嵌套网格或并行域分解,
igpmax 的线程私有首次缓存可能不再代表全局最保守列;源码自己把这一点标为待清理。
- 复现风险:如果垂直层顶不足以出现
pplay > pminte 的扫描命中,Fortran 循环结束后的 nlaylte 值依赖编译器对终止循环变量的处理;当前常规火星 GCM 垂直网格预期会命中该阈值。
待确认
ismax 的具体实现不在本文件内;本页只按调用语义和注释记录它用于寻找最大 pplev(:,1) 位置。
pminte=0.04 Pa 处于纯压力层这一稳健性假设来自本文件注释,尚未用实际网格样例数值复算。
nlthermeq 是否在所有并行运行模式下都由每个线程以一致的 pplev/pplay 调用,需要结合运行时域分解继续确认。
相关页面