lwxn.F
路径
LMDZ.MARS\libf\phymars\lwxn.F
所属目录 / 模块
libf\phymars
文件定位
lwxn.F 定义 lwxn_mod 模块,提供长波 LTE 辐射中的相邻层交换系数例程 lwxn。它由 lwmain_mod.F 在 lwxd 远距离层间交换之后、lwxb 边界交换之前调用,输入来自 lwu 生成的 co2_u/co2_up/aer_t,输出写入 yomlw_h::xi 和 yomlw_h::xi_ground,供 lwflux 与 lwi 后续读取。
本例程覆盖 jk 与 jk+1 这类相邻真实大气层之间的交换。与 lwxd 的远距离四界面差分不同,lwxn 会把相邻两层分别拆成 lwxn_ncouche 个子层,在子层内部构造从下层到上层、从上层到下层的多条 CO2/气溶胶透过路径,再用加权积分得到整层相邻交换系数。底部相邻层还有一个额外的 xi_ground 修正项,用于 lwflux 对地面与第一层交换的处理。
定义的符号
| 符号 |
类型 |
行号 |
作用 |
lwxn_mod |
module |
1 |
封装相邻层长波交换系数构造例程和子层参数。 |
lwxn_linear |
module variable |
5 |
控制子层权重使用线性均分还是指数分布;OpenMP THREADPRIVATE。 |
lwxn_alphan |
module variable |
7 |
非线性子层分布的指数因子;OpenMP THREADPRIVATE。 |
lwxn_ncouche |
module variable |
9 |
每个物理层拆分的子层数;OpenMP THREADPRIVATE。 |
lwxn |
subroutine |
15 |
计算相邻层对 jk,jk+1 的净交换率,并写入 xi 与 xi_ground。 |
依赖的模块
| use 模块 |
only 列表 |
用途 |
待确认 |
dimradmars_mod |
ndlo2, nuco2, ndlon, nflev |
提供输入数组和局部工作数组的水平、谱带和垂直维度上限。 |
否 |
yomlw_h |
nlaylte, xi, xi_ground, xi_emis |
读取 LTE 长波有效层数,写入相邻层 xi 与底层修正 xi_ground,并读取 lwxd 保存的 xi_emis。 |
否 |
lwtt_mod |
lwtt |
用 CO2 子路径 zu/zup 计算每个 CO2 谱带透过率。 |
否 |
调用的关键例程
| 被调用例程 |
所在模块 / 文件 |
调用位置 |
作用 |
lwtt |
lwtt_mod / lwtt.F |
241 |
计算从下层子界面到两层公共界面的透过率。 |
lwtt |
lwtt_mod / lwtt.F |
258 |
计算从下层子界面穿过上层后的透过率。 |
lwtt |
lwtt_mod / lwtt.F |
285 |
计算从上层子界面到两层公共界面的透过率。 |
lwtt |
lwtt_mod / lwtt.F |
302 |
计算从上层子界面穿过下层后的透过率。 |
exit |
Fortran runtime |
180 |
当 lwxn_ncouche 大于本地硬上限 nmax=50 时终止运行。 |
输入
| 输入 |
来源 |
类型/维度 |
单位 |
含义 |
ig0 |
lwmain |
integer |
grid offset |
当前向量块在全局 xi / xi_ground 第一维中的偏移,写入时使用 ig0+jl。 |
kdlon |
lwmain |
integer |
column |
当前向量块内有效水平列数,循环范围为 1:kdlon。 |
kflev |
lwmain |
integer |
layer |
接口数组垂直层数参数;主要相邻层循环使用 yomlw_h::nlaylte。 |
dp |
lwmain |
real(ndlo2,kflev) |
Pa |
每层压力厚度;用于按两相邻层厚度加权合成相邻层交换率。 |
aer_t |
lwu |
real(ndlo2,nuco2,kflev+1) |
- |
CO2 谱带上的累计气溶胶吸收透过率。 |
co2_u |
lwu |
real(ndlo2,nuco2,kflev+1) |
吸收路径 |
自模型顶向下累计的 CO2 吸收量。 |
co2_up |
lwu |
real(ndlo2,nuco2,kflev+1) |
压力缩放吸收路径 |
带压力效应的累计 CO2 吸收量。 |
lwxn_linear |
conf_phys.F / radia.def |
module logical |
- |
默认 .true.;为真时每个子层 cn=1/lwxn_ncouche。 |
lwxn_ncouche |
conf_phys.F / radia.def |
module integer |
sublayer count |
默认 3;源码本地硬上限 nmax=50。 |
lwxn_alphan |
conf_phys.F / radia.def |
module real |
- |
默认 0.4;仅在 lwxn_linear=.false. 时用于指数分布子层权重。 |
输出
| 输出 |
去向 |
类型/维度 |
单位 |
含义 |
xi(ig0+jl,ja,jk,jk+1) 与互易项 |
yomlw_h,后续由 lwflux / lwi 读取 |
shared array |
- |
第 jk 层与第 jk+1 层之间的 CO2 带相邻层净交换系数。 |
xi_ground(ig0+jl,ja) |
yomlw_h,后续由 lwflux 读取 |
shared array |
- |
底层相邻交换的地面特殊修正系数,只在 jk=1 分支写入。 |
共享状态与副作用
lwxn 的持久副作用是写 yomlw_h::xi 的相邻层条目和 yomlw_h::xi_ground。它还读取 yomlw_h::xi_emis,把 lwxd 保存的邻近反射缓存加到相邻层 xi 中;按当前 lwxd.F 字面实现,该缓存通常为 0,因为相邻反射公式被注释。
模块变量 lwxn_linear/lwxn_alphan/lwxn_ncouche 是 SAVE 且 THREADPRIVATE,由 conf_phys.F 初始化和广播。默认值为 lwxn_linear=.true.、lwxn_ncouche=3、lwxn_alphan=0.4;如果运行目录存在 radia.def,conf_phys.F 会依序读取并覆盖这些值。若 lwxn_ncouche > 50,本例程打印错误并 call exit(1)。
核心逻辑
- 为第
lwxn_ncouche+1 个子界面初始化零 CO2 路径和单位气溶胶透过率,作为每层内部的公共边界。
- 根据
lwxn_linear 生成子层权重 cn 和几何/压力加权位置 cb。线性分布时 cn=1/lwxn_ncouche,cb=(lwxn_ncouche-nlmd+0.5)/lwxn_ncouche;非线性分布时使用 lwxn_alphan 的几何级数。
- 若
lwxn_ncouche 超过 nmax=50,立即终止,避免局部数组越界。
- 对每个相邻层对
jk=1:nlaylte-1,先从累计量差分得到下层 i 与上层 j 的整层 CO2 路径、压力缩放路径和气溶胶透过率。
- 按
cn 把两层各自拆成子层:CO2 路径线性分配,气溶胶透过率用整层透过率的 cn 次幂分配。
- 对下层每个子界面
ni,先构造从该界面到公共界面的路径并调用 lwtt,保存到 trans(ni,lwxn_ncouche+1);再加上整层上层路径,保存到 trans(ni,1)。
- 对上层每个子界面
nj,对称地构造从该界面到公共界面的路径 trans(lwxn_ncouche+1,nj),再加上整层下层路径得到 trans(1,nj)。
- 用两组子层透过率差分合成
ksi(jk)。下层贡献乘 cb(ni)*dp(jk)*2/(dp(jk)+dp(jk+1)),上层贡献乘 cb(nj)*dp(jk+1)*2/(dp(jk)+dp(jk+1))。
- 写入
xi(jk,jk+1)=ksi+xi_emis(jk),并显式写入互易项 xi(jk+1,jk)。
- 当
jk=1 时,额外累加 xi_ground:对下层子层的界面透过率差 trans(ni+1,common)-trans(ni,common) 乘 2*cb(ni)。
伪代码
if lwxn_linear:
for sublayer nlmd:
cn = 1 / lwxn_ncouche
cb = (lwxn_ncouche - nlmd + 0.5) / lwxn_ncouche
else:
for nlmd below last:
cn = (1 - lwxn_alphan) * lwxn_alphan**(nlmd-1)
cb = 0.5 * (1 + lwxn_alphan) * lwxn_alphan**(nlmd-1)
last cn = lwxn_alphan**(lwxn_ncouche-1)
last cb = 0.5 * lwxn_alphan**(lwxn_ncouche-1)
if lwxn_ncouche > 50:
stop with error
for jk = 1 to nlaylte-1:
layer_i = boundary jk to jk+1
layer_j = boundary jk+1 to jk+2
split layer_i and layer_j into lwxn_ncouche sublayers
for each lower-layer subinterface ni:
trans(ni,common) = lwtt(path from ni to common) * aerosol_path
trans(ni,top_of_j) = lwtt(path from ni through layer_j) * aerosol_path
for each upper-layer subinterface nj:
trans(common,nj) = lwtt(path from nj to common) * aerosol_path
trans(bottom_of_i,nj) = lwtt(path from nj through layer_i) * aerosol_path
ksi = weighted lower-side transmission differences
+ weighted upper-side transmission differences
xi(jk,jk+1) = ksi + xi_emis(jk)
xi(jk+1,jk) = xi(jk,jk+1)
if jk == 1:
xi_ground = weighted lower-layer-to-common transmission differences
参与的主题流程
写法特点
- 固定格式 Fortran 文件;模块变量与子例程在同一模块内,三个配置变量均为
SAVE + OpenMP THREADPRIVATE。
kflev 用于接口数组形状,实际相邻层循环由 yomlw_h::nlaylte 控制。
- 子层数有运行时配置入口,但本地数组硬上限固定为 50。
- 气溶胶透过率按
zt_aer_layer**cn 分配到子层,CO2 路径按 cn 线性分配。
xi_ground 只在 jk=1 分支清零并写入;其他相邻层不触碰该数组。
复现要点
conf_phys.F 必须先初始化并广播 lwxn_linear/lwxn_ncouche/lwxn_alphan;如果使用 radia.def 覆盖,文件顺序必须与源码读取顺序一致。
lwxn_ncouche 不能超过 50,否则源码会 call exit(1)。
lwxn_ncouche 也不能为 0;源码没有显式防护,线性分支会出现除零。
dp(jk)+dp(jk+1) 不能为 0 或异常小;相邻交换权重直接除以这个和。
- lwu 生成的
aer_t 必须保持正值,因为 lwxn 会做比值并取 **cn;当前上游 1e-30 下限保护是复现稳定性的前提。
xi_emis 的邻近反射缓存来自 lwxd。当前源码字面通常为 0;如果实验结果预期包含邻近层表面反射项,需要先核对 lwxd.F 中被注释的相邻反射公式。
待确认
lwxn_alphan 在默认 lwxn_linear=.true. 时不会参与计算;页面只记录源码行为,未确认非线性子层分布在当前标准运行中的使用频率。
xi_ground 的物理命名与后续 lwflux 地面第一层修正项一致,但本页未进一步推导该近似与原始辐射方案文献之间的对应关系。
相关页面