watercloud_mod.F
路径
LMDZ.MARS\libf\phymars\watercloud_mod.F
所属目录/模块
libf/phymars
文件定位
水冰云形成的主调度模块。根据 microphys 开关选择简化云方案 (simpleclouds) 或完整微物理方案 (improvedclouds),包含时间子循环、次网格云覆盖分数计算、冰粒半径更新、非负保护、HDO 分馏和尘埃清除等逻辑。被 physiq 在每个物理时间步调用。
定义的符号
| 符号 |
类型 |
行号 |
作用 |
watercloud_mod |
module |
1 |
水冰云主调度模块 |
watercloud |
subroutine |
12 |
水冰云形成主例程:时间子循环、方案分派、倾向汇总、半径更新、非负保护 |
zdqcloud |
module variable (REAL, SAVE, ALLOCATABLE) |
5 |
H2O 凝结对 tracer 的倾向 (kg/kg/s),3D |
zdqscloud |
module variable (REAL, SAVE, ALLOCATABLE) |
6 |
H2O 凝结对地表倾向(仅 calchim 使用),2D |
ini_watercloud_mod |
subroutine |
715 |
分配 zdqcloud、zdqscloud |
end_watercloud_mod |
subroutine |
730 |
释放 zdqcloud、zdqscloud |
依赖的模块
| use 模块 |
only 列表 |
用途 |
待确认 |
ioipsl_getin_p_mod |
getin_p |
从 run.def 读取 imicro 参数 |
|
updaterad |
updaterdust, updaterice_micro, updaterice_typ |
更新尘埃/冰粒有效半径和云密度 |
|
simpleclouds_mod |
simpleclouds |
简化云方案(非微物理路径) |
|
improvedclouds_mod |
improvedclouds |
完整微物理云方案 |
|
watersat_mod |
watersat |
计算水饱和混合比(supersat=false 时用) |
|
tcondwater_mod |
tcondwater |
计算水凝结温度(CLFvarying 次网格方案用) |
|
tracer_mod |
nqmx, igcm_h2o_vap, igcm_h2o_ice, igcm_hdo_vap, igcm_hdo_ice, igcm_dust_mass, igcm_dust_number, igcm_ccn_mass, igcm_ccn_number, rho_dust, nuice_sed, nuice_ref, qparentmin |
tracer 索引和物理常数 |
|
dimradmars_mod |
naerkind |
气溶胶种类数 |
|
conc_mod |
mmean |
未直接使用(推断:improvedclouds 内部需要) |
待确认:watercloud 本体未调用 mmean |
write_output_mod |
write_output |
诊断输出(当前代码中相关调用已注释) |
|
callkeys_mod |
activice, microphys, supersat, hdo, scavenging, CLFvarying |
运行时物理开关 |
|
调用的关键例程
| 被调用例程 |
所在模块/文件 |
调用位置 |
作用 |
getin_p("imicro",imicro) |
ioipsl_getin_p_mod |
行 182 |
读取时间子循环步数 |
simpleclouds |
simpleclouds_mod |
行 349 |
简化云方案,在 microphys=false 时每个 microstep 调用 |
improvedclouds |
improvedclouds_mod |
行 316 |
完整微物理方案,在 microphys=true 时单次调用 |
tcondwater |
tcondwater_mod |
行 248 |
计算凝结温度,用于 CLFvarying 次网格云覆盖 |
watersat |
watersat_mod |
行 564 |
计算饱和混合比,supersat=false 时强制不超饱和 |
updaterice_micro |
updaterad |
行 618 |
微物理路径下更新冰粒半径和云密度 |
updaterice_typ |
updaterad |
行 638 |
简化路径下更新冰粒半径 |
updaterdust |
updaterad |
行 543 |
更新尘埃有效半径(scavenging 路径) |
abort_physic |
(GCM 内部) |
行 170 |
nq > nqmx 时终止运行 |
输入
| 输入 |
来源 |
类型/维度 |
单位 |
含义 |
ngrid |
physiq |
INT, scalar |
- |
大气格点数 |
nlay |
physiq |
INT, scalar |
- |
大气层数 |
ptimestep |
physiq |
REAL, scalar |
s |
物理时间步长 |
pplev |
physiq |
REAL (ngrid,nlay+1) |
Pa |
层界面气压 |
pplay |
physiq |
REAL (ngrid,nlay) |
Pa |
层中气压 |
pdpsrf |
physiq |
REAL (ngrid) |
Pa/s |
地面气压倾向 |
pzlay |
physiq |
REAL (ngrid,nlay) |
m |
层中高度 |
pt |
physiq |
REAL (ngrid,nlay) |
K |
温度 |
pdt |
physiq |
REAL (ngrid,nlay) |
K/s |
温度倾向(其他过程) |
pq |
physiq |
REAL (ngrid,nlay,nq) |
kg/kg |
tracer 混合比 |
pdq |
physiq |
REAL (ngrid,nlay,nq) |
kg/kg/s |
tracer 倾向(其他过程) |
nq |
physiq |
INT, scalar |
- |
tracer 数量 |
tau |
physiq |
REAL (ngrid,naerkind) |
- |
柱尘埃光学厚度 |
tauscaling |
physiq |
REAL (ngrid) |
- |
尘埃量转换因子 |
rdust |
physiq |
REAL (ngrid,nlay) |
m |
尘埃几何平均半径(INOUT) |
输出
| 输出 |
去向 |
类型/维度 |
单位 |
含义 |
pdqcloud |
physiq |
REAL (ngrid,nlay,nq) |
kg/kg/s |
水冰云凝结产生的 tracer 倾向 |
pdtcloud |
physiq |
REAL (ngrid,nlay) |
K/s |
水冰云潜热释放温度倾向 |
rice |
physiq |
REAL (ngrid,nlay) |
m |
冰粒质量平均半径(INOUT) |
nuice |
physiq |
REAL (ngrid,nlay) |
- |
尺度分布有效方差(设为 nuice_ref) |
rsedcloud |
physiq |
REAL (ngrid,nlay) |
m |
云沉降半径 |
rhocloud |
physiq |
REAL (ngrid,nlay) |
kg/m³ |
云密度 |
totcloudfrac |
physiq |
REAL (ngrid) |
- |
柱总云覆盖分数(INOUT) |
共享状态与副作用
- module 变量:
zdqcloud(3D)、zdqscloud(2D)为 SAVE+ALLOCATABLE,带 OMP THREADPRIVATE,在 ini_watercloud_mod 分配、end_watercloud_mod 释放。
- SAVE 变量:
imicro(子循环步数)、microtimestep、microtimestep_prev、firstcall、flagcloud 均为 SAVE+THREADPRIVATE。
- firstcall:首次调用时检查 nq <= nqmx,读取
imicro 参数。
- 标准输出:firstcall 打印 tracer 索引和 imicro 值;microtimestep 变化时打印新值;CLFvarying 首次打印 spant 和 mincloud。
- 诊断输出:代码中 write_output 调用已被注释掉(行 293-300、698-710)。
核心逻辑
- firstcall 初始化(行 165-186):验证 nq <= nqmx;根据是否 MESOSCALE 编译宏设 imicro 默认值(2 或 30),通过
getin_p 允许用户覆盖。
- 计算 microtimestep(行 190-196):
microtimestep = ptimestep / real(imicro);变化时打印通知。
- 初始化倾向累积器和默认值(行 199-203):
sum_subpdq=0, sum_subpdt=0, rhocloud=rho_dust。
- CLFvarying 次网格云覆盖计算(行 206-301):
- 用
pdt*ptimestep 和 pdq*ptimestep 更新有效温度 pteff 和有效 tracer pqeff。
- 调用
tcondwater 计算凝结温度 tcond。
- 根据
tcond 与 ztclf ± spant 的关系计算网格内云覆盖分数 cloudfrac,mincloud=0.1 为下限。
- 按冰含量加权求柱总覆盖
totcloudfrac。
- 将 CCN 和 h2o_ice tracer 除以 cloudfrac 得到云内有效值。
- 主方案分派(行 315-387):
microphys=true:单次调用 improvedclouds,传入原始网格平均量 pt/pq(不受 CLFvarying 影响),自适应时间步在 improvedclouds 内部处理。
microphys=false:imicro 步子循环调用 simpleclouds,传入 CLFvarying 修改后的云内有效值 pteff/pqeff(行 349-351);每步累加 pdt/pdq 作为阶梯输入,simpleclouds 返回的倾向也累加回 sum_subpdq/sum_subpdt;循环结束后从 zt_micro/zq_micro 中恢复最终状态。
- 关键分支差异:CLFvarying 方案中
pteff/pqeff 经过云覆盖分数调整(pqeff(ccn,h2o_ice) /= cloudfrac),但 improvedclouds 接收的是未经 cloudfrac 调整的 pt/pq——两个方案对次网格云的处理方式完全不同。最终 CLFvarying 均值化(行 677-695 将倾向乘以 cloudfrac)在两种路径之后统一执行。
- 计算最终倾向(行 393-453):从 zt_micro/zq_micro 减去初始状态和输入倾向,得到纯云过程倾向 pdtcloud/pdqcloud;涉及 h2o_vap, h2o_ice, hdo_vap, hdo_ice, ccn_mass, ccn_number, dust_mass, dust_number(后者受 microphys/scavenging 开关控制)。
- 非负保护(行 457-534):
- CCN:若
pq + ptimestep*(pdq+pdqcloud) <= 1. 或质量阈值 1.e-20,强制归零并反推 dust 倾向。
- dust(scavenging 路径):同理。
- h2o_ice/h2o_vap:若最终值 <= qparentmin,强制归零并保持质量守恒(vap↔︎ice 互反)。
- HDO:跟随 H2O 的非负保护同步处理。
- 更新粒子半径(行 536-674):
- scavenging 路径:调用
updaterdust 更新尘埃半径。
- microphys=true 且 supersat=false 时:调用
watersat 检查饱和,强制凝结过量水汽,同时计算 HDO 分馏系数 α(Lamb et al. 2017 公式 exp(13525/T² - 0.0559))。
- microphys=true:调用
updaterice_micro 更新 ice 半径和 rhocloud。
- microphys=false:调用
updaterice_typ 更新 ice 半径。
- CO2 升华修正(行 651-660):若第一层气压变化接近层厚,用上层 rice 覆盖。
- 计算
rsedcloud = max(rice*(1+nuice_sed)³, rdust)。
- 设
nuice = nuice_ref(常数,对数正态分布假设)。
- CLFvarying 倾向缩放(行 677-695):所有倾向乘以 cloudfrac,将云内值映射回网格平均。
- 清理:返回 pdqcloud、pdtcloud、rice、nuice、rsedcloud、rhocloud、totcloudfrac。
伪代码
watercloud(ngrid, nlay, ptimestep, ...):
if firstcall:
assert nq <= nqmx
imicro = getin_p("imicro") // default: 30 (global), 2 (MESOSCALE)
firstcall = false
microtimestep = ptimestep / imicro
sum_subpdq = 0, sum_subpdt = 0
rhocloud = rho_dust
// --- CLFvarying 次网格方案 ---
if CLFvarying:
pteff = pt + pdt*ptimestep // 有效温度
pqeff = pq + pdq*ptimestep // 有效 tracer
tcond = tcondwater(pplay, h2o_vap + h2o_ice)
// cloudfrac ∈ [mincloud, 1] 由 tcond 与温度分布宽度决定
totcloudfrac = 按冰含量加权的 cloudfrac 柱平均
pqeff(ccn, h2o_ice) /= cloudfrac // 转为云内值
// --- 主方案分派 ---
if microphys:
// improvedclouds 接收原始 pt/pq(网格平均量),不用 pteff/pqeff
zt_micro, zq_micro = improvedclouds(pt, pq, ...) // 自适应时间步
else:
// simpleclouds 接收 CLFvarying 修改后的 pteff/pqeff(云内有效值)
for microstep = 1..imicro:
累加 pdt, pdq 为阶梯输入
subpdqcloud, subpdtcloud = simpleclouds(pteff, pqeff, sum_subpdq, ...)
累加 subpdqcloud, subpdtcloud 回 sum
zt_micro = pt + ptimestep * sum_subpdt / imicro
zq_micro = pq + ptimestep * sum_subpdq / imicro
// --- 最终倾向 ---
pdtcloud = (zt_micro - pt)/ptimestep - pdt
pdqcloud[tracer] = (zq_micro[tracer] - pq[tracer])/ptimestep - pdq[tracer]
// --- 非负保护 (CCN → dust → h2o_ice/h2o_vap → HDO) ---
enforce_positive(pq, pdq, pdqcloud, qparentmin/thresholds)
// --- 粒子半径更新 ---
if scavenging: rdust = updaterdust(dust updated)
if microphys:
if not supersat: enforce_no_supersaturation(watersat)
rice, rhocloud = updaterice_micro(ice, ccn)
else:
rice = updaterice_typ(ice, tau, pzlay)
CO2 升华第一层修正
rsedcloud = max(rice*(1+nuice_sed)³, rdust)
nuice = nuice_ref
// --- CLFvarying 均值化 ---
if CLFvarying:
pdqcloud *= cloudfrac
pdtcloud *= cloudfrac
参与的主题流程
| 主题 |
参与方式 |
| 水循环 (water-cycle) |
主调度:驱动水汽凝结/冰升华、更新冰粒半径、计算云倾向 |
| 尘埃循环 (dust-cycle) |
清除路径:scavenging 时尘埃被 CCN 捕获,更新尘埃半径 |
| 辐射 (radiation) |
提供 rice、nuice、rhocloud 用于辐射计算 |
写法特点
- 固定格式 Fortran 77(.F 后缀,续行用第 6 列
& 或 c 注释)。
- SAVE + THREADPRIVATE:
imicro、microtimestep、microtimestep_prev、firstcall、flagcloud,保证 OpenMP 线程安全。
- firstcall 模式:首次调用时读取参数和打印诊断,之后
firstcall=.false.。
- 阶梯输入法:simpleclouds 路径中,每个 microstep 将 pdt/pdq 累加为阶梯式输入(而非简单平分),这可能导致其他过程倾向累积到负值,因此需要后续非负保护。
- 非负保护逻辑:先处理 CCN(阈值 1.0 和 1.e-20),再处理 dust,最后处理 h2o_ice/h2o_vap(阈值 qparentmin),每层保证质量守恒(vap↔︎ice 互反、ccn↔︎dust 互反)。
- HDO 分馏(行 577-608):仅在
microphys=true + supersat=false + hdo=true + 凝结时激活,使用 Lamb et al. 2017 公式 α = exp(13525/T² - 0.0559);升华时按 HDO/H2O 比例分配。
- 编译宏:
MESOSCALE 影响 imicro 默认值;#ifndef MESOSCALE 保护诊断输出代码。
- 硬编码常数:
spant=3.0(K)、mincloud=0.1、CCN 阈值 1./1.e-20、CO2 升华修正系数 0.9。
复现要点
imicro 默认值依赖编译宏 MESOSCALE(2 vs 30),可通过 run.def 的 imicro 覆盖。
supersat=false 时的额外饱和检查会修改 pdqcloud,改变 H2O/HDO 倾向分配。
- CLFvarying 方案中
spant=3.0 K 和 mincloud=0.1 为硬编码,无法通过配置修改。
- 非负保护的执行顺序(CCN → dust → h2o → HDO)影响最终倾向值,不同顺序可能导致不同结果。
- CO2 升华第一层修正(行 654-660)在 pdpsrfptimestep > 0.9(pplev层差) 时触发,仅影响第 1-2 层 rice。
- simpleclouds 路径中最终 zt_micro/zq_micro 的除以
real(imicro) 平均化(行 383-385)意味着子循环内所有 microstep 的累积倾向被均摊。
待确认
conc_mod 的 mmean 在 watercloud 本体中未被直接调用,但在 use 列表中——推断是为了让 improvedclouds 内部可见,但 Fortran module 的 use 不自动传递,需确认是否多余或 improvedclouds 自行 use。
zdqcloud 和 zdqscloud 声明为 module 变量但在 watercloud 子程序中使用的是参数 pdqcloud,module 变量可能由外部(如 calchim)直接读写——待确认。
相关页面