orosetup.F90
快速理解
它做什么: Lott/Miller 地形重力波拖曳链的预处理层,被 ORODRAG 调用。
基本过程: 把翻转后的压力/温度/风/位势/地形统计量转换成后续 GWSTRESS/GWPROFIL 所需工作量。
关键结果: 地形高度层索引、低层风、Brunt-Väisälä 频率、Richardson 数、投影风速和阻塞层参数。
路径
LMDZ.MARS\libf\phymars\orosetup.F90
所属目录 / 模块
libf\phymars
文件定位
orosetup.F90 定义 orosetup_mod 和 OROSETUP,是 Lott/Miller 地形重力波拖曳链中的预处理层。它不直接输出风温 tendency,而是在 orodrag_mod.F90 的 ORODRAG 内被调用,负责把已经由 drag_noro_mod 翻转到地形拖曳层序的压力、温度、风场、位势高度和次网格地形统计量转换成后续 GWSTRESS/GWPROFIL 与阻塞层 wake drag 所需的工作量。
核心输出包括地形高度层索引 IKNU/IKNU2/IKENVH/IKCRITH/ICRIT、低层平均风 PULOW/PVLOW、半层密度 ZRHO、Brunt-Vaisala 频率平方 BV、Richardson 数 PRI、投影风速 ZVPH、地形方向角 ZPSI、阻塞层 leakiness ZZDEP 以及各向异性组合量 ZD1/ZD2/ZDMOD。下游 ORODRAG 随后用这些量初始化应力、重算应力廓线,并把应力差分或阻塞层拖曳换算成 pdudt/pdvdt/pdtdt。
定义的符号
| 符号 | 类型 | 行号 | 作用 |
|---|---|---|---|
orosetup_mod |
module | 1 | 封装地形重力波拖曳预处理例程。 |
OROSETUP |
subroutine | 7 | 计算地形 GW 所需的层索引、低层风、稳定度、密度、方向投影和阻塞层参数。 |
依赖的模块
| use 模块 | only 列表 | 用途 | 待确认 |
|---|---|---|---|
dimradmars_mod |
ndomainsz |
固定本例程接口数组第一维。 | - |
comcstfi_h |
cpp, g, r, pi |
r 用于密度,g 用于位势高度和压力厚度积分,cpp 用于稳定度项,pi 用于地形主轴角角度到弧度换算。 |
- |
yoegwd_h |
gfrcrit, grcrit, gsigcr, gssec, gtsec, gvsec |
地形 GW 经验阈值:低层压力范围、Richardson 数下限、稳定度下限、地形各向异性下限和风速下限。 | - |
yoegwd_h |
nktopg |
限制地形高度索引搜索结果,避免越过方案允许的顶部地形层。 | - |
调用的关键例程
| 被调用例程 | 所在模块 / 文件 | 调用位置 | 作用 |
|---|---|---|---|
| - | - | - | 本文件没有调用其他 Fortran 子程序。 |
OROSETUP 在 IKNUL=IKNUB 的保护分支中有一次 WRITE(*,*) 诊断输出,提示低层平均区间退化并用相邻层的 BV/ZRHO 兜底。
输入
| 输入 | 来源 | 类型 / 维度 | 单位 | 含义 |
|---|---|---|---|---|
ngrid, nlayer |
ORODRAG |
integer scalar | - | 当前子域水平点数和垂直层数。 |
ktest |
calldrag_noro -> drag_noro -> ORODRAG |
integer (ndomainsz) |
- | 当前局地点是否进入地形 GW 计算的开关图。 |
pplev |
drag_noro 翻转后的半层压力 |
real (ndomainsz,nlayer+1) |
Pa | 用于压力厚度、低层平均风和地形高度层积分。 |
pplay |
drag_noro 翻转后的全层压力 |
real (ndomainsz,nlayer) |
Pa | 用于稳定度、密度和半层插值。 |
pu, pv |
drag_noro 翻转后的全层风 |
real (ndomainsz,nlayer) |
m/s | 计算低层平均风、沿低层应力方向的投影风和临界层。 |
pt |
drag_noro 翻转后的全层温度 |
real (ndomainsz,nlayer) |
K | 计算密度和 Brunt-Vaisala 频率平方。 |
zgeom |
drag_noro 用静力关系构造 |
real (ndomainsz,nlayer) |
位势相关量 | 源码用 zgeom/g 与 pvar 倍数比较,判定 1/2/3/4 倍地形标准差高度层,并用于 ZZDEP。 |
pvar |
surfdat_h:zstd 子域切片 |
real (ndomainsz) |
m | 次网格地形标准差;决定 IKNU* 搜索高度和 ZZDEP 尺度。 |
pthe |
surfdat_h:zthe 子域切片 |
real (ndomainsz) |
degree | 地形主轴角;源码用 pthe*pi/180. 与流向角相减得到 ZPSI。 |
pgam |
surfdat_h:zgam 子域切片 |
real (ndomainsz), intent(inout) |
- | 地形各向异性;本例程会用 gtsec 做下限保护。 |
输出
| 输出 | 去向 | 类型 / 维度 | 单位 | 含义 |
|---|---|---|---|---|
IKCRIT |
ORODRAG -> GWPROFIL |
integer (ndomainsz) |
层索引 | 低层流顶部压力阈值对应层。 |
IKCRITH |
ORODRAG -> GWPROFIL |
integer (ndomainsz) |
层索引 | 重力波破碎的动力混合高度,上限再受 IKNU 限制。 |
ICRIT |
ORODRAG -> GWPROFIL |
integer (ndomainsz) |
层索引 | 沿低层应力方向投影风速低于 gvsec 时记录的临界层。 |
IKENVH |
ORODRAG/GWPROFIL 和阻塞层 wake drag |
integer (ndomainsz) |
层索引 | 阻塞层顶部;ORODRAG 用 JK >= IKENVH 判断阻塞层分支。 |
IKNU |
ORODRAG -> GWPROFIL |
integer (ndomainsz) |
层索引 | 4*pvar 地形高度阈值层。 |
IKNU2 |
ORODRAG -> GWPROFIL |
integer (ndomainsz) |
层索引 | 3*pvar 地形高度阈值层。 |
ZRHO |
ORODRAG/GWSTRESS/GWPROFIL |
real (ndomainsz,nlayer+1) |
kg/m3 量纲 | 半层密度;底部半层为 1-2 倍 pvar 区间压力加权平均。 |
PRI |
ORODRAG -> GWPROFIL |
real (ndomainsz,nlayer+1) |
- | 半层 Richardson 数,下限为 grcrit。 |
BV |
ORODRAG/GWSTRESS/GWPROFIL |
real (ndomainsz,nlayer+1) |
s^-2 量纲 | Brunt-Vaisala 频率平方,下限为 gssec。 |
ZTAU |
ORODRAG -> GWSTRESS/GWPROFIL |
real (ndomainsz,nlayer+1) |
stress 相关量 | 本例程把工作数组初始化为 0;后续 GWSTRESS/GWPROFIL 改写。 |
ZVPH |
ORODRAG/GWSTRESS/GWPROFIL |
real (ndomainsz,nlayer+1) |
m/s | 沿低层应力方向的投影风速;底部半层为低层平均风速。 |
ZPSI |
ORODRAG 阻塞层分支 |
real (ndomainsz,nlayer+1) |
rad | 入射流方向与地形法线方向的夹角。 |
ZZDEP |
ORODRAG 阻塞层分支 |
real (ndomainsz,nlayer) |
- | 阻塞层 wake drag 使用的垂直 leakiness 因子。 |
ZNU |
ORODRAG -> GWPROFIL |
real (ndomainsz) |
- | 方程 9 形式的积分量,用于定位阻塞层顶部。 |
ZD1, ZD2, ZDMOD |
ORODRAG/GWSTRESS |
real (ndomainsz) |
- | 椭圆山各向异性公式的方向组合量,用于应力方向投影。 |
PULOW, PVLOW |
ORODRAG |
real (ndomainsz) |
m/s | 1-2 倍地形标准差之间压力加权的低层平均纬向/经向风。 |
共享状态与副作用
- 本文件没有
SAVE变量、THREADPRIVATE、文件 I/O 或配置读取。 pgam是intent(inout);行 144 将其改为max(pgam,gtsec),因此调用方传入的局部地形各向异性数组会被本例程下限保护。ZTAU是输出工作数组,但本例程只在全层循环中初始化ZTAU(:,1:nlayer)=0.0;底部半层ZTAU(:,nlayer+1)由后续GWSTRESS初始化。- 当
IKNUL=IKNUB时,行 362 会向标准输出写诊断信息,并把BV(:,nlayer+1)、ZRHO(:,nlayer+1)设为相邻全层值。这是唯一运行时输出副作用。 - 只有
ktest(JL)==1的分支会计算密度、稳定度、投影风、Richardson 数和阻塞层积分;但部分初始化循环仍覆盖kidia:kfdia全部局地点。
核心逻辑
- 初始化局部范围和常数:
kidia=1、kfdia=ngrid,ILEVH=nlayer/3,并构造1/r、g**2/cpp和1.5*pi。 - 初始化地形高度索引。
IKNU/IKNU2/IKNUb/IKNUl先设为nlayer,pgam用gtsec下限保护,然后从近地层向上搜索zgeom/g何时越过4*pvar、3*pvar、2*pvar和1*pvar。 - 用
nktopg修正IKNU/IKNUb,并在IKNUb到达顶部限制或IKNUl <= IKNUb时调整IKNUl,避免 1-2 倍pvar平均区间退化。 - 初始化半层边界和输出数组:
BV/PRI/ZPSI/ZVPH/PULOW/PVLOW/IKCRITH/IKENVH/ICRIT等被设置为表面或顶部默认值。 - 从近地层向上计算全层之间的半层密度
ZRHO和BV。密度使用rho=p/(r*T)的两层平均形式,BV使用源码中的压力差表达式并用gssec下限保护。 - 在
IKNUb..IKNUl之间做压力加权平均,得到低层风PULOW/PVLOW,并用gvsec给低层风速范数ZNORM下限。 - 根据低层风向和地形主轴角得到底部半层
ZPSI(:,nlayer+1),再由pgam计算B=1-0.18*pgam-0.04*pgam^2、C=0.48*pgam+0.3*pgam^2,得到ZD1/ZD2/ZDMOD。 - 对每层把实际风投影到低层应力方向,形成
ZVPF;随后把ZVPF插值到半层得到ZVPH。若半层投影风速低于gvsec,则强制为gvsec并记录ICRIT=JK。 - 在 1-2 倍
pvar区间累加底部半层BV(:,nlayer+1)和ZRHO(:,nlayer+1),再按压力厚度平均;退化区间走WRITE诊断和相邻层兜底。 - 用
BV、ZRHO、沿应力方向风切变和压力差计算PRI,并用grcrit下限保护。 - 从
IKNU2以下积分方程 9 的ZNU,当它跨过gfrcrit且IKENVH仍为表面默认值时,记录阻塞层顶部。 - 在阻塞层以上继续积分
ZNUP,当它跨过1.5且IKCRITH仍为默认值时,记录重力波破碎动力混合高度;最后IKCRITH=min(IKCRITH,IKNU)。 - 对
JK >= IKENVH的阻塞层重新计算层内ZPSI,并用zgeom(IKENVH)、当前层zgeom和pvar*g计算ZZDEP。
伪代码
OROSETUP(pressure, wind, temperature, zgeom, subgrid-orography):
set constants and vertical search limits
for each local column:
initialize IKNU*, IKENVH, IKCRITH, ICRIT and work arrays
pgam = max(pgam, gtsec)
for thresholds 4*pvar, 3*pvar, 2*pvar, 1*pvar:
scan from surface upward
compare zgeom/g against threshold
record the layer where the logical test changes
constrain terrain-height indices with nktopg
for active columns and half-levels:
compute density and BV from pressure, temperature and constants
apply gssec lower bound to BV
average pu/pv between 1*pvar and 2*pvar levels:
PULOW/PVLOW = pressure-weighted low-level wind
ZVPH(:,nlayer+1) = max(low-level wind speed, gvsec)
compute terrain orientation terms:
ZPSI = terrain-axis angle - low-level flow angle
ZD1/ZD2/ZDMOD = anisotropic mountain coefficients from pgam and ZPSI
project each layer wind into the low-level stress plane:
ZVPF -> half-level ZVPH
if ZVPH < gvsec:
set ZVPH = gvsec
record ICRIT
average bottom half-level BV/ZRHO between 1*pvar and 2*pvar:
if interval is degenerate:
print diagnostic and copy adjacent layer values
compute PRI with a grcrit lower bound
integrate ZNU below 3*pvar:
first crossing of gfrcrit defines IKENVH
integrate ZNUP above blocked layer:
first crossing of 1.5 defines IKCRITH
IKCRITH = min(IKCRITH, IKNU)
for blocked-layer levels:
recompute ZPSI from local layer wind
compute ZZDEP leakiness from envelope height and current height
参与的主题流程
| 主题 | 参与方式 |
|---|---|
| 地形重力波 / 次网格地形拖曳 | 预处理层:为 ORODRAG 提供应力初始化、应力廓线重算和阻塞层 wake drag 所需的层索引、风投影、稳定度和地形方向组合量。 |
主物理时间步 physiq |
间接参与 physiq_mod.F 的 calllott 分支;调用链为 calldrag_noro -> drag_noro -> ORODRAG -> OROSETUP。 |
| 垂直层序适配 | 本例程假定 pplev/pplay/pu/pv/pt 已由 drag_noro 翻转,源码注释也把 nlayer 侧视作近地表。 |
写法特点
.F90自由格式模块,但保留 ECMWF/IFS 和 Lott/Miller 方案的历史注释。- 本例程大量使用
nlayer侧作为表面、从nlayer向小层号扫描的层序约定;这依赖上游drag_noro的翻转。 BV注释说是 Brunt-Vaisala frequency,但表达式和下限变量按N^2使用;页面按源码计算量记录为频率平方。kentp、ncount、zulow、zvlow等局部变量只初始化或声明,未参与后续计算。- 注释中保留多处开发者疑问,例如
ILEVH=nlayer/3“maybe not enough for Mars”、BV公式待替换、PRI中dp是否应为dp^2。
复现要点
- 必须先按
drag_noro的层序翻转输入;直接用原始物理层序调用会改变所有JK >= IKENVH、IKNU*和 pressure-thickness 逻辑。 pgam会被原地改写为不小于gtsec,复现实验若比较原始地形统计量,需要在调用前后区分。IKNUb..IKNUl的压力平均区间决定PULOW/PVLOW、底部BV/ZRHO和后续应力尺度;nktopg、pvar和zgeom/g的一致性会直接影响拖曳强度。ZVPH和风切变用gvsec下限保护,BV用gssec下限保护,PRI用grcrit下限保护;这些yoegwd_h参数必须与运行配置一致。- 源码只对底部
BV/ZRHO平均的IKNUL=IKNUB情况显式兜底;低层风平均和其他分母仍依赖前置索引修正与输入范围。 ZZDEP只在JK >= IKENVH的阻塞层写入,其他层保持 0;下游 wake drag 分支不能把 0 当作已计算 leakiness。
待确认
- 源码注释称
ILEVH=nlayer/3“maybe not enough for Mars”,本页只记录字面行为,未判断该上限对不同垂直分辨率是否充分。 BV公式旁注释说 “Use N^2=g/T[1/(cpp*T)+dT/dz] to replace in the future”;是否应替换属于方案演进问题,非本页结论。PRI公式旁注释说 “Here dp maybe dp^2 ? Need ask Francois lott later”;本页按源码记录,未确认理论公式。zgeom在上游页面中按位势相关量记录;本页按源码zgeom/g和pvar*g用法说明,不重新定义其单位来源。
相关页面
- orodrag_mod:直接调用本例程,并消费
IK*、BV/ZRHO/ZVPH/ZPSI/ZZDEP/ZD*输出。 - drag_noro_mod:上游包装层,翻转垂直层序并构造
zgeom。 - calldrag_noro_mod:读取地形 GW 开关并筛选进入拖曳计算的格点。
- gwstress_mod:使用本例程输出的低层风、稳定度、密度和地形方向量初始化底部应力。
- gwprofil_mod:使用本例程输出的临界层、阻塞层和稳定度信息重算垂直应力廓线。
- phymars 目录:本模块所属目录。
- sugwd:记录
gfrcrit/grcrit/gssec/gvsec/nktopg等 GWD 调参常量初始化来源。 - yoegwd_h:记录这些共享变量的定义位置和
THREADPRIVATE属性。