conc_mod.F90
路径
LMDZ.MARS\libf\phymars\conc_mod.F90
所属目录/模块
libf\phymars
文件定位
conc_mod.F90 定义 conc_mod,是 phymars 中保存逐格点、逐层大气混合物热力学属性的共享模块。它维护四个二维数组:平均摩尔质量 mmean、热导率系数 Akknew、定压比热 cpnew 和比气体常数 rnew。
初始化时,phys_state_var_init_mod.F90 只负责分配这些数组;physiq_mod.F 首次调用 init_r_cp_mu 把 rnew/cpnew/mmean 填成 comcstfi_h 的常数值。每个物理步中,只有 photochem 或 callthermos 为真时,physiq 才调用 update_r_cp_mu_ak,用当前 tracer 混合比和 tracer 摩尔质量重算 mmean/rnew/cpnew/Akknew。下游 CO2 云、CO2 饱和、NLTE、热层/化学和若干诊断路径读取这些数组,把质量混合比换成体积混合比、更新气体常数或比热。
定义的符号
| 符号 |
类型 |
行号 |
作用 |
conc_mod |
module |
1 |
保存大气混合物热力学属性数组并提供初始化/更新例程 |
mmean |
protected allocatable module variable |
5 |
平均分子/摩尔质量数组,源码注释单位 amu,实际按 g/mol 与 tracer_mod:mmol 一起使用 |
Akknew |
protected allocatable module variable |
6 |
热导率系数数组,由各 tracer 的数密度权重和 aki 系数计算 |
cpnew |
protected allocatable module variable |
7 |
混合物定压比热数组,单位 J/kg/K |
rnew |
protected allocatable module variable |
8 |
混合物比气体常数数组,单位 J/kg/K |
ini_conc_mod |
subroutine |
14 |
按 ngrid,nlayer 分配四个二维数组 |
end_conc_mod |
subroutine |
28 |
释放已分配的四个二维数组 |
init_r_cp_mu |
subroutine |
39 |
用 comcstfi_h:r/cpp/mugaz 把 rnew/cpnew/mmean 填成常数背景值 |
update_r_cp_mu_ak |
subroutine |
65 |
按 tracer 混合比、摩尔质量、比热和热导率系数动态更新 mmean/rnew/cpnew/Akknew |
依赖的模块
| use 模块 |
only 列表 |
用途 |
待确认 |
comcstfi_h |
r, cpp, mugaz |
init_r_cp_mu 中给 rnew/cpnew/mmean 设置常数背景值 |
- |
tracer_mod |
igcm_* chemistry/aeronomy tracer 索引、mmol |
update_r_cp_mu_ak 中选择存在的 tracer,并用摩尔质量把质量混合比换成平均摩尔质量、体积分数和数密度 |
- |
调用的关键例程
| 被调用例程 |
所在模块/文件 |
调用位置 |
作用 |
| 无外部例程 |
- |
- |
本模块只分配/释放数组并执行局部公式计算 |
输入
| 输入 |
来源 |
类型/维度 |
单位 |
含义 |
ngrid, nlayer |
phys_state_var_init / physiq |
integer scalar |
- |
物理列数和垂直层数,用作数组维度 |
r, cpp, mugaz |
comcstfi_h |
real scalar |
J/kg/K, J/kg/K, g/mol |
常数背景气体属性,用于 init_r_cp_mu |
nq |
physiq |
integer scalar |
- |
tracer 数量,用于分配本例程内部保存的 aki/cpi/niq |
igcm_* tracer 索引 |
tracer_mod |
integer scalars |
- |
判断 CO2、CO、O、N2、Ar、H2O、离子和电子等 tracer 是否存在 |
mmol(:) |
tracer_mod |
real allocatable |
g/mol |
tracer 摩尔质量 |
pplay |
physiq |
real (ngrid,nlayer) |
Pa |
层中气压,用于数密度 ntot=p/(kT) |
pt, pdt, ptimestep |
physiq |
real arrays/scalar |
K, K/s, s |
当前温度、已累计温度倾向和物理时间步;组成更新后温度 zt |
pq, pdq |
physiq |
real (ngrid,nlayer,nq) |
kg/kg, kg/kg/s |
tracer 质量混合比和已累计 tracer tendency;组成更新后 tracer zq |
photochem, callthermos |
physiq 物理开关 |
logical |
- |
只有任一为真时,physiq 每步调用 update_r_cp_mu_ak |
输出
| 输出 |
去向 |
类型/维度 |
单位 |
含义 |
mmean |
CO2 饱和、CO2 云、水云、NLTE、诊断 |
real (ngrid,nlayer) |
g/mol |
混合物平均摩尔质量;用于把质量混合比换成体积混合比 |
rnew |
physiq 几何高度、密度、非地形重力波、CO2 云 |
real (ngrid,nlayer) |
J/kg/K |
更新后的比气体常数 |
cpnew |
非地形重力波、NLTE/热层相关路径 |
real (ngrid,nlayer) |
J/kg/K |
更新后的定压比热 |
Akknew |
热层/化学热传导相关路径 |
real (ngrid,nlayer) |
coefficient |
按 tracer 数密度加权的热导率系数 |
共享状态与副作用
mmean/Akknew/cpnew/rnew 是 SAVE, ALLOCATABLE, PROTECTED 模块变量;模块外可读取,但不能直接写入。
- 四个数组都用 OpenMP
THREADPRIVATE,并行复现时需要确认每个线程完成分配和初始化。
update_r_cp_mu_ak 内部的 nbq/niq/aki/cpi/firstcall 也是 SAVE + THREADPRIVATE;首次调用时按当前 tracer 索引构造参与计算的 tracer 列表。
- 首次调用
update_r_cp_mu_ak 会向标准输出打印 nbq、niq(1:nbq)、aki(1:nbq)、cpi(1:nbq)。
ini_conc_mod 只分配,不初始化数值;init_r_cp_mu 不写 Akknew。如果 photochem 和 callthermos 都为假,Akknew 可能未被本模块赋值,但通常也不会被需要动态热导率的路径读取。
核心逻辑
phys_state_var_init_mod.F90 在初始化共享物理状态时,先调用 end_conc_mod,再调用 ini_conc_mod(ngrid,nlayer),分配 mmean/Akknew/cpnew/rnew。
physiq_mod.F 的 firstcall 阶段调用 init_r_cp_mu(ngrid,nlayer),把 rnew(:,:)=r、cpnew(:,:)=cpp、mmean(:,:)=mugaz。
- 每个物理时间步先把
pdt/pdq 等 tendency 清零,再经过动力质量修正等前置步骤。
- 若
photochem.or.callthermos 为真,physiq 调用 update_r_cp_mu_ak(ngrid,nlayer,nq,zplay,pt,pdt,pq,pdq,ptimestep)。
update_r_cp_mu_ak 首次调用时,遍历 tracer_mod 中的化学/热层 tracer 索引,凡 igcm_* /= 0 的 tracer 都加入 niq(1:nbq),并为它们设置热导率系数 aki 和比热 cpi。源码中包含 30 类候选:CO2、CO、O、O(1D)、O2、O3、H、H2、OH、HO2、H2O2、N2、Ar、H2O vapor、N、NO、NO2、N2D、He、CO2+、O+、O2+、CO+、C+、N+、NO+、N2+、H+、HCO2+、electron。
- 每次更新时,先构造当前有效温度
zt=pt+pdt*ptimestep;再只对参与计算的 tracer 构造 zq=max(1.e-30, pq+pdq*ptimestep)。
- 对每个格点和层,按
mmean = 1 / sum(zq(iq)/mmol(iq)) 计算平均摩尔质量,再按 rnew = 8.314/mmean*1.e3 转成比气体常数。
- 继续按
ntot = pplay/(1.381e-23*zt)*1.e-6 计算总数密度(#/cm3),再按 ni = ntot*zq*mmean/mmol 得到各 tracer 数密度。
- 按质量混合比加权求
cpnew = sum(zq*cpi),按数密度加权求 Akknew = sum(ni*aki)/ntot。
- 下游立即可用更新后的
rnew 计算 zzlay/zzlev,并用 mmean 做 CO2/H2O/化学 tracer 体积混合比诊断。
伪代码
ini_conc_mod(ngrid, nlayer):
allocate mmean(ngrid,nlayer), Akknew(ngrid,nlayer)
allocate cpnew(ngrid,nlayer), rnew(ngrid,nlayer)
end_conc_mod:
deallocate each array if allocated
init_r_cp_mu(ngrid, nlayer):
rnew = comcstfi_h:r
cpnew = comcstfi_h:cpp
mmean = comcstfi_h:mugaz
update_r_cp_mu_ak(...):
if firstcall:
build compact tracer list niq(1:nbq) from nonzero igcm_* indices
assign aki/cpi coefficients for each selected tracer
print selected indices and coefficients
firstcall = false
zt = pt + pdt * ptimestep
for each selected tracer iq:
zq(:,:,iq) = max(1e-30, pq(:,:,iq) + pdq(:,:,iq) * ptimestep)
for each grid point and layer:
mmean = 1 / sum_over_selected_tracers(zq(iq) / mmol(iq))
rnew = 8.314 / mmean * 1000
ntot = pplay / (k_B * zt) converted from m-3 to cm-3
cpnew = sum_over_selected_tracers(zq(iq) * cpi(compact_index))
Akknew = sum_over_selected_tracers(
ntot * zq(iq) * mmean / mmol(iq) * aki(compact_index)
) / ntot
参与的主题流程
| 主题 |
参与方式 |
| 物理初始化 |
phys_state_var_init 分配数组;physiq firstcall 填常数背景值 |
| 光化学 / 热层 |
photochem 或 callthermos 开启时,每步用 tracer 组成动态更新气体常数、比热、平均摩尔质量和热导率 |
| 几何高度与密度 |
physiq 用 rnew 计算 zzlay/zzlev,并用 rho=p/(rnew*T) |
| CO2 云与 CO2 饱和 |
co2cloud_mod、improvedco2clouds_mod、tcondco2 用 mmean 把 CO2 质量混合比换成分压或饱和比 |
| 水云相关路径 |
improvedclouds_mod 和 watercloud_mod 读取 conc_mod::mmean 换算 H2O 分压或体积混合比;vdifc_mod.F 中同名 mmean 是局部数组 |
| NLTE 冷却 |
nltecool、nlte_tcool_mod 用 mmean/cpnew 做体积混合比和加热率换算 |
写法特点
- 自由格式
.F90 模块,使用 PROTECTED 防止模块外写共享数组。
ini_conc_mod 没有已分配保护;调用方通过先 end_conc_mod 再 ini_conc_mod 避免重复分配。
update_r_cp_mu_ak 的 tracer 系数表只在首次调用时构造,并受 THREADPRIVATE 影响。
- 多个
aki/cpi 值旁边带 !? 或 0,源码注释说明这些值是估计值;这在复现实验中属于参数不确定来源。
zq 只为被选入 niq(1:nbq) 的 tracer 写值,后续也只读取这些 tracer。
复现要点
- 必须先执行
ini_conc_mod 分配数组,再执行 init_r_cp_mu 或 update_r_cp_mu_ak 填数值。
- 如果
photochem 和 callthermos 都关闭,mmean/rnew/cpnew 保持常数背景;不要假定它们每步都会随 CO2/H2O tracer 改变。
mmean 使用 tracer_mod:mmol 的 g/mol 单位;rnew=8.314/mmean*1.e3 中的 1.e3 是从 g 转 kg 的换算。
update_r_cp_mu_ak 只纳入源码列出的化学/热层 tracer。若某个未列入的 tracer 在质量上不可忽略,它不会进入 mmean/cpnew/Akknew。
zq 对参与 tracer 设下限 1.e-30;极小或负 tracer tendency 不会让分子量求和变成零,但也可能掩盖非常小浓度下的符号问题。
cpnew=sum(zq*cpi) 未显式除以 sum(zq);复现时应确认参与 tracer 的质量混合比总和接近 1,或接受这是源码定义的质量加权形式。
待确认
Akknew 在 photochem/callthermos 关闭时是否有任何运行路径读取;本页只确认 init_r_cp_mu 不初始化它。
- 若 tracer 列表中没有任何
igcm_* 被选入,mmean=1/sum(...) 会发生除零;实际配置是否总保证 nbq>0 需由 tracer 初始化约束确认。
aki/cpi 中标注 !? 或设为 0 的物种参数是否仍代表当前推荐值,需要对照热层/化学方案文档。
相关页面