drag_noro_mod.F90
路径
LMDZ.MARS\libf\phymars\drag_noro_mod.F90
所属目录 / 模块
libf\phymars
文件定位
drag_noro_mod.F90 定义 drag_noro_mod 模块和 drag_noro 子程序,是 calldrag_noro_mod.F90 与 orodrag_mod.F90::ORODRAG 之间的地形重力波包装层。它不读取配置,也不决定哪些全局格点启用方案;上游 calldrag_noro 已按 ndomainsz 切分子域,并用 zstd > oro_gwd_zstdthread 填好 kgwd/kdx/ktest。
本例程的职责是把当前子域的温度、风和压力垂直顺序翻转为 ORODRAG 需要的排列,按静力关系构造 zgeom,调用 ORODRAG 计算地形重力波 tendency,再把 tendency 翻回原始层序并乘以 ptimestep 形成每个物理步长的增量。文件名中的 noro 不应理解为非地形重力波;源码注释写明它是 sub-grid scale orographic scheme,下游调用的是 ORODRAG。
定义的符号
| 符号 |
类型 |
行号 |
作用 |
drag_noro_mod |
module |
1 |
封装地形重力波拖曳的垂直重排和 ORODRAG 调用层 |
drag_noro |
subroutine |
7 |
对一个 ndomainsz 子域执行地形重力波拖曳,返回温度/风增量、低层风和低层 stress |
依赖的模块
| use 模块 |
only 列表 |
用途 |
待确认 |
dimradmars_mod |
ndomainsz |
固定本例程局部数组第一维;ngrid 是当前子域实际点数,数组仍按 ndomainsz 声明。 |
- |
orodrag_mod |
orodrag |
下游地形重力波参数化核心,返回 pdudt/pdvdt/pdtdt tendency。 |
- |
comcstfi_h |
g, r |
r 用于静力积分构造 zgeom,g 用于把风 tendency 垂直积分为 stress。 |
- |
调用的关键例程
| 被调用例程 |
所在模块 / 文件 |
调用位置 |
作用 |
ORODRAG |
orodrag_mod.F90 |
行 129-132 |
接收翻转后的压力、温度、风、地形统计量和筛选索引,计算地形重力波对风和温度的 tendency。 |
输入
| 输入 |
来源 |
类型/维度 |
单位 |
含义 |
ngrid |
calldrag_noro 当前子域 |
integer scalar |
grid points |
当前子域实际列数,最大为 ndomainsz。 |
nlayer |
physiq / calldrag_noro |
integer scalar |
- |
大气垂直层数。 |
ptimestep |
physiq |
real scalar |
s |
物理时间步长;本例程用它把 tendency 转为本步增量。 |
pplay |
calldrag_noro 子域拷贝 |
real (ndomainsz,nlayer) |
Pa |
全层压力。 |
pplev |
calldrag_noro 子域拷贝 |
real (ndomainsz,nlayer+1) |
Pa |
半层压力。 |
pvar |
surfdat_h:zstd 子域切片 |
real (ndomainsz) |
m |
次网格地形标准差;传给 ORODRAG。 |
psig |
surfdat_h:zsig 子域切片 |
real (ndomainsz) |
- |
次网格坡度统计量;传给 ORODRAG。 |
pgam |
surfdat_h:zgam 子域切片 |
real (ndomainsz), intent(inout) |
- |
地形各向异性参数;本文件不直接赋值,但按 inout 传入 ORODRAG 链。 |
pthe |
surfdat_h:zthe 子域切片 |
real (ndomainsz) |
rad 或角度制待源数据确认 |
地形主轴角;本文件仅透传。 |
kgwd, kgwdim, kdx, ktest |
calldrag_noro 筛选结果 |
integer scalar / arrays |
- |
标记当前子域中哪些格点进入地形 GW 计算。 |
t, u, v |
calldrag_noro 子域拷贝 |
real (ndomainsz,nlayer) |
K, m/s, m/s |
温度、纬向风、经向风,按原始物理层序传入。 |
输出
| 输出 |
去向 |
类型/维度 |
单位 |
含义 |
pulow, pvlow |
calldrag_noro 局部数组 |
real (ndomainsz) |
m/s |
ORODRAG 返回的低层纬向/经向风。 |
pustr, pvstr |
calldrag_noro 局部数组 |
real (ndomainsz) |
源码按 g * tendency * pressure thickness 累加 |
本例程对每层风 tendency 垂直积分得到的低层 stress 摘要。 |
d_t |
calldrag_noro,随后除以 ptimestep 写回 pdtgw |
real (ndomainsz,nlayer) |
K |
地形 GW 对温度的每步增量。 |
d_u |
calldrag_noro,随后除以 ptimestep 写回 pdugw |
real (ndomainsz,nlayer) |
m/s |
地形 GW 对纬向风的每步增量。 |
d_v |
calldrag_noro,随后除以 ptimestep 写回 pdvgw |
real (ndomainsz,nlayer) |
m/s |
地形 GW 对经向风的每步增量。 |
共享状态与副作用
- 本文件没有
save 变量、THREADPRIVATE 声明、文件 I/O、日志输出或配置读取。
pgam 在接口上是 intent(inout),本文件没有直接写它,但会把它传给 ORODRAG 及其下游链路。
pulow/pvlow/pustr/pvstr/d_t/d_u/d_v 和局部 tendency 数组在进入主计算前清零;若 kgwd=0 或 ktest 全部关闭,下游返回值仍从零态开始。
pustr/pvstr 在 ORODRAG 返回后由本文件逐层累加,使用翻转后的半层压力厚度 inv_pplev(i,k+1)-inv_pplev(i,k)。
核心逻辑
- 对当前子域
i=1..ngrid 初始化低层风、stress、增量数组和 ORODRAG tendency 工作数组为 0。
- 将温度、风、全层压力和半层压力按垂直方向翻转:
inv_pt(i,k)=t(i,nlayer-k+1)
inv_pu/inv_pv/inv_pplay 同理;
inv_pplev(i,k)=pplev(i,nlayer+1-k+1),最后令 inv_pplev(i,nlayer+1)=pplev(i,1)。
- 用
r*T*log(p ratio) 构造 zgeom。源码注释称其为 g*dz 和 geopotential height;由于公式未除以 g,这里更接近位势差量而不是几何高度米。
- 调用
ORODRAG(ngrid,nlayer,kgwd,kgwdim,kdx,ktest,ptimestep,inv_pplev,inv_pplay,zgeom,inv_pt,inv_pu,inv_pv,pvar,psig,pgam,pthe,...)。
- 将
pdudt/pdvdt/pdtdt 翻回原始层序,并乘以 ptimestep 得到 d_u/d_v/d_t;同时把风 tendency 乘以 g 和半层压力厚度累加到 pustr/pvstr。
伪代码
drag_noro(current_subdomain):
zero pulow, pvlow, pustr, pvstr
zero d_t, d_u, d_v and pdudt, pdvdt, pdtdt
for k in 1..nlayer:
source_k = nlayer - k + 1
inv_pt(:,k) = t(:,source_k)
inv_pu(:,k) = u(:,source_k)
inv_pv(:,k) = v(:,source_k)
inv_pplay(:,k) = pplay(:,source_k)
inv_pplev(:,k) = pplev(:,nlayer + 2 - k)
inv_pplev(:,nlayer+1) = pplev(:,1)
zgeom(:,nlayer) = r * inv_pt(:,nlayer) * log(inv_pplev(:,nlayer+1) / inv_pplay(:,nlayer))
for k from nlayer-1 down to 1:
zgeom(:,k) = zgeom(:,k+1)
+ r * average(inv_pt(:,k), inv_pt(:,k+1))
* log(inv_pplay(:,k+1) / inv_pplay(:,k))
ORODRAG(... inverted fields, topography statistics, kgwd/kdx/ktest ...)
for k in 1..nlayer:
original_k = nlayer + 1 - k
d_u(:,original_k) = ptimestep * pdudt(:,k)
d_v(:,original_k) = ptimestep * pdvdt(:,k)
d_t(:,original_k) = ptimestep * pdtdt(:,k)
pustr(:) += g * pdudt(:,k) * (inv_pplev(:,k+1)-inv_pplev(:,k))
pvstr(:) += g * pdvdt(:,k) * (inv_pplev(:,k+1)-inv_pplev(:,k))
参与的主题流程
| 主题 |
参与方式 |
主物理时间步 physiq |
physiq_mod.F 在 calllott 为真时调用 calldrag_noro,后者再调用本例程;本例程返回的增量最终被除以 ptimestep 后累加到 pdu/pdv/pdt。 |
| 地形重力波 / 次网格地形拖曳 |
本例程是 ORODRAG 的输入适配层,负责层序、位势量和单位转换。 |
| 子域并行/分块 |
数组形状来自 ndomainsz,但只循环 ngrid 个当前子域有效点。 |
写法特点
.F90 自由格式模块,局部自动数组统一按 ndomainsz 和 nlayer 声明。
- 垂直层序翻转是硬性接口约定;
ORODRAG 的输入数组、返回 tendency 和 stress 积分都使用翻转后的层序。
- 源码将
t 注释为 m/s 是注释错误;接口语义和下游公式显示它是全层温度,单位 K。
ptimestep 在本文件中参与 tendency 到 increment 的转换;上游 calldrag_noro 随后再除回 tendency。
复现要点
- 复现
drag_noro 时必须保留垂直翻转和翻回映射;直接把原始层序送入 ORODRAG 会改变地形 GW 廓线计算。
zgeom 的公式是 r*T*log(p ratio) 累加;不要在未检查 ORODRAG 期望单位前把它改写成几何高度米。
d_t/d_u/d_v 是每步增量,不是 tendency;调用方 calldrag_noro 会除以 ptimestep。
pvar/psig/pgam/pthe 必须由上游按子域起点预切片,并与 kdx/ktest 的局部编号对齐。
ngrid 是当前子域有效点数,不一定等于 ndomainsz;最后一个子域尤其需要按 ngrid 限制循环。
待确认
pthe 的角度单位需从地形预处理或 surfdat_h 填充路径继续确认;本文件只透传。
zgeom 在注释中称为 geopotential height,但公式没有除以 g;本页按源码公式记录为位势相关量,未推断下游物理单位。
pgam 被声明为 intent(inout),但是否会被 ORODRAG/OROSETUP 修改需在 orodrag_mod.F90 和 orosetup.F90 专页中继续核验。
相关页面