photochemistry_mod.F90
路径
LMDZ.MARS\libf\aeronomars\photochemistry_mod.F90
所属目录/模块
libf\aeronomars
文件定位
photochemistry_mod.F90 定义 photochemistry_mod,是 calchim_mod 逐列调用的主光化学积分器。它把 GCM tracer mole fraction zycol 映射到内部化学物种数组,计算在线或离线光解率、可选离子光电离率、气相/异相反应速率和反应索引矩阵,然后在 lswitch-1 以下逐层用自适应子时间步和 LAPACK dgesv 解隐式线性系统,最后把数密度结果写回 zycol。
该文件实现的是 ASIS 光化学求解框架的 Mars 反应网络,核心对象包括基础 C/O/H/N 光化学、可选氘化学、可选离子化学、冰/尘异相项以及 NO/O2 夜辉诊断。
定义的符号
| 符号 |
类型 |
行号 |
作用 |
photochemistry_mod |
module |
1(END MODULE 4345) |
光化学主模块 |
photochemistry |
subroutine |
21(END SUBROUTINE 4343) |
主积分器;更新 zycol,输出 jo3/jh2o/em_no/em_o2/iter |
define_dt |
internal subroutine |
531-646 |
按局部曲率误差准则迭代修正化学子时间步 |
reactionrates |
internal subroutine |
650-2296 |
计算光解、二体、三体、quench 和异相反应速率数组 |
fill_matrix |
internal subroutine |
2300-2419 |
用 indice_* 和速率数组填隐式求解的 Jacobian 矩阵、产生项和损失项 |
indice |
internal subroutine |
2423-3919 |
分配并填充 types_asis 中的 indice_phot/indice_3/indice_4 反应化学计量表 |
gcmtochim |
internal subroutine |
3923-4221 |
从 zycol 和 tracer_mod::igcm_* 构造内部 mole fraction rm 与数密度 c |
chimtogcm |
internal subroutine |
4225-4341 |
把 lswitch-1 以下内部数密度 c 写回 zycol 的 GCM tracer 槽位 |
依赖的模块
| use 模块 |
only 列表 |
用途 |
待确认 |
param_v4_h |
jion |
读取 phdisrate 写入的离子光电离率,映射到 v_phot(:,nphot+1:nphot+18) |
- |
jthermcalc_e107_mod |
jthermcalc_e107 |
在线光解且 ionchem 时计算 E107 光吸收/光电离输入 |
- |
paramfoto_compact_mod |
phdisrate |
把 jthermcalc_e107 结果转成 jion;本文件固定以 chemthermod=2 调用 |
- |
photolysis_module |
photolysis |
jonline=.false. 时使用离线查找表计算光解率 |
- |
photolysis_online_mod |
photolysis_online |
jonline=.true. 且白天时在线计算基础光解率 |
- |
comcstfi_h |
全模块 use |
reactionrates 中读取物理常数;具体常数使用需结合该子例程逐项反应确认 |
是 |
photolysis_mod |
nphot |
reactionrates 中确定基础光解项之后的 photoionization 计数起点 |
- |
types_asis |
全模块 use |
fill_matrix 和 indice 使用 z3spec/z4spec 类型与 indice_* 共享索引数组 |
- |
tracer_mod |
多个 igcm_* |
gcmtochim/chimtogcm 检查并映射 GCM tracer 索引 |
- |
调用的关键例程
| 被调用例程 |
所在模块/文件 |
调用位置 |
作用 |
indice |
本文件 |
257-264 |
firstcall 建立反应化学计量索引表并检查计数 |
gcmtochim |
本文件 |
272-280 |
把 zycol 映射为内部 rm/c |
photolysis_online |
photolysis_online.F |
290-295 |
在线计算基础光解率 |
jthermcalc_e107 |
jthermcalc_e107_mod.F |
299 |
离子化学路径下计算 E107 光吸收输入 |
phdisrate |
paramfoto_compact.F |
301 |
逐层生成 jion;调用参数固定 chemthermod=2 |
photolysis |
photolysis.F90 |
371-372 |
离线光解查找表路径 |
reactionrates |
本文件 |
392-398 |
填 v_phot/v_3/v_4 反应速率 |
fill_matrix |
本文件 |
435-437 |
构造隐式矩阵、产生项和损失项 |
define_dt |
本文件 |
441-442 |
计算本轮子时间步 |
dgesv |
LAPACK |
461;608 |
解线性系统;未定义 LAPACK 时中止 |
chimtogcm |
本文件 |
518-526 |
将更新后的内部数密度写回 zycol |
abort_physic |
LMDZ 物理工具(未显式 use) |
464、611、3916、3995 等 |
缺 LAPACK、反应数组维度不匹配或 tracer 缺失时中止 |
输入
| 输入 |
来源 |
类型/维度 |
单位 |
含义 |
nlayer,nq,nesp |
calchim_mod |
integer |
- |
层数、GCM tracer 数、内部化学物种数 |
nb_reaction_3_max,nb_reaction_4_max |
calchim_mod |
integer |
- |
三体/二体反应数组容量 |
nphot,nb_phot_max,nphotion |
calchim_mod / photolysis_mod |
integer |
- |
基础光解、总光解样反应、photoionization 数 |
ionchem,deutchem,jonline |
calchim_mod |
logical |
- |
是否启用离子化学、氘化学、在线光解 |
ig |
calchim_mod 列循环 |
integer |
- |
当前网格列,用于 E107 光化学和诊断 |
lswitch |
calchim_mod |
integer |
- |
低层光化学与热层化学分界;本文件只积分 1:lswitch-1 |
zycol |
calchim_mod |
real (nlayer,nq) |
mole fraction |
输入/输出化学 tracer 体积混合比 |
sza |
calchim_mod |
real |
degree |
太阳天顶角;在线路径 sza<=113 计算光解,否则清零 |
ptimestep |
calchim_mod |
real |
s |
物理时间步,作为化学积分总时长 |
press,alt,temp,temp_elect |
calchim_mod |
real (nlayer) |
hPa, km, K, K |
层压、高度、中性温度和电子温度 |
dens |
calchim_mod |
real (nlayer) |
cm^-3 |
总数密度,gcmtochim 用于 mole fraction 到数密度转换 |
zmmean |
calchim_mod |
real (nlayer) |
g/mol |
在线光解路径使用的平均摩尔质量 |
dist_sol,zday |
calchim_mod |
real |
AU, Mars day |
日火距离和季节日,供光解/E107 使用 |
surfdust1d,surfice1d |
calchim_mod |
real (nlayer) |
cm2/cm3 |
尘/冰表面积,异相反应速率使用 |
tau |
calchim_mod |
real |
- |
尘埃光学厚度;离线路径会按 tau*7/press(1) 重标定 |
输出
| 输出 |
去向 |
类型/维度 |
单位 |
含义 |
zycol |
calchim_mod |
real (nlayer,nq) |
mole fraction |
1:lswitch-1 的化学物种被更新后写回 GCM tracer 槽位 |
jo3 |
calchim_mod 诊断 |
real (nlayer) |
s^-1 |
v_phot(:,5),O3 -> O1D 光解率 |
jh2o |
calchim_mod 诊断 |
real (nlayer) |
s^-1 |
v_phot(:,7),H2O -> H + OH 光解率 |
em_no |
calchim_mod 诊断 |
real (nlayer) |
cm^-3 s^-1 |
O*N*v_4(ind_norec) 夜辉发射率 |
em_o2 |
calchim_mod 诊断 |
real (nlayer) |
cm^-3 s^-1 |
0.75*O*O*CO2*v_3(ind_orec) 夜辉发射率 |
iter |
calchim_mod 诊断 |
integer (nlayer) |
count |
每层化学积分内部子步次数 |
共享状态与副作用
photochemistry 和 gcmtochim 各有 firstcall,均为 SAVE/THREADPRIVATE;首次调用后缓存内部物种索引并不再重复分配/检查。
indice 会 allocate(indice_phot/indice_3/indice_4),这些数组来自 types_asis,用于后续矩阵填充;页面未发现释放路径。
indice 每次 firstcall 打印 nb_phot/nb_reaction_4/nb_reaction_3,并在计数不等于传入容量时中止。
- 在线离子路径写入并读取
param_v4_h::jion,依赖 jthermcalc_e107 和 phdisrate 的共享状态副作用。
- 未定义编译宏
LAPACK 时,主求解和 define_dt 的矩阵求解分支都会调用 abort_physic。
reactionrates 内部硬编码 hetero_dust=.false.、hetero_ice=.true.,因此冰异相反应活跃,尘异相反应默认关闭。
核心逻辑
- firstcall 设置内部物种索引:基础 17 个物种固定为 CO2、CO、O、O1D、O2、O3、H、H2、OH、HO2、H2O2、H2O、N、N2D、NO、NO2、N2;若
ionchem 为真追加 15 个离子/电子物种,若 deutchem 为真追加 6 个氘相关物种。随后调用 indice 建立反应化学计量表。
- GCM tracer 到内部数组:
gcmtochim 首次检查所有必需 tracer_mod::igcm_* 索引,之后把 zycol 的对应 tracer 拷贝到内部 rm,低于 1.e-30 的 mole fraction 清零,再乘 dens 得到数密度 c。
- 光解和光电离率:
jonline 时若 sza<=113 调 photolysis_online;夜间直接清零 v_phot。若 ionchem,再调 jthermcalc_e107 和逐层 phdisrate(ig,nlayer,2,sza,ilay),把 jion 的 CO2/O2/O/NO/CO/N2/N/H 光电离通道放入 v_phot(:,nphot+1:nphot+18)。jonline=.false. 时改调 photolysis,并先把 tau 按 7 hPa 查找表口径重标定。
- 保存诊断光解率:
jo3=v_phot(:,5),jh2o=v_phot(:,7)。
- 反应速率表:
reactionrates 先按 nphot+nphotion 初始化光解样反应数,再填 O、O(1D)、HOx、N/NOx、CO、氘、离子和异相反应。二体反应进 v_4,三体/同物种二次反应进 v_3,quench/异相项按光解样一阶反应进 v_phot。
- 逐层隐式积分:对
ilev=1:lswitch-1,在 time<ptimestep 循环中先用 fill_matrix 形成矩阵、产生项和损失项,再由 define_dt 按误差准则修正子步,最后解 (I + J*dt)*cnew = c_old。低于 1.e-30*dens 的数密度置零。
- 电荷中性修正:若
ionchem,每个子步后把电子数密度强制设为所有正离子数密度之和。
- 夜辉和写回:积分结束后计算
em_no/em_o2,再调用 chimtogcm 将 1:lswitch-1 的内部数密度除以 dens 写回 zycol。
伪代码
photochemistry(...):
if firstcall:
assign fixed species indices
append ion species if ionchem
append deuterium species if deutchem
call indice(...) to allocate/fill reaction stoichiometry tables
firstcall = false
call gcmtochim(...) # zycol -> rm -> c
if jonline:
if sza <= 113:
call photolysis_online(..., v_phot)
if ionchem:
call jthermcalc_e107(...)
for ilay = 1..lswitch-1: call phdisrate(..., chemthermod=2, ilay)
copy jion channels into v_phot after nphot
else:
v_phot = 0
else:
tau = tau * 7 / press(1)
call photolysis(..., v_phot)
jo3 = v_phot(:,5)
jh2o = v_phot(:,7)
hetero_dust = false
hetero_ice = true
call reactionrates(..., v_phot, v_3, v_4, ind_norec, ind_orec)
for ilev = 1..lswitch-1:
time = 0
dt_guess = ptimestep
while time < ptimestep:
call fill_matrix(ilev, mat1, prod, loss, c, ...)
call define_dt(..., dt_corrected, ...)
cap dt_corrected at remaining physical timestep
mat = identity + mat1*dt_corrected
solve mat*cnew = c(ilev,:) with dgesv
zero very small cnew
c(ilev,:) = cnew
if ionchem: electron = sum(positive ions)
time += dt_corrected
dt_guess = dt_corrected
em_no = O*N*NO_recombination_rate
em_o2 = 0.75*O*O*CO2*O_recombination_rate
call chimtogcm(...) # c -> zycol
参与的主题流程
| 主题 |
参与方式 |
| 光化学 / 光解 |
主低层光化学积分器,消费在线或离线光解率并更新化学 tracer |
| 离子化学 |
ionchem 开启时追加离子/电子物种,使用 E107/phdisrate 生成 18 个 photoionization 通道,并强制电子电荷中性 |
| 氘化学 |
deutchem 开启时追加 HDO/OD/D/HD/DO2/HDO2 并增加相关反应 |
| 异相化学 |
默认启用冰表面反应、关闭尘表面反应,按一阶光解样项进入矩阵 |
| 夜辉诊断 |
输出 NO 和 O2 体发射率,供 calchim_mod 写诊断/统计 |
写法特点
- 主例程包含 6 个内部子例程,
indice_* 类型来自 types_asis,反应化学计量和速率计算分离。
- 编译必须有
LAPACK 宏和 dgesv 链接,否则运行时会在求解处中止。
jionos 在主例程内硬编码为 .true.,没有外部配置输入。
hetero_ice 硬编码 .true.,hetero_dust 硬编码 .false.。
phychemrat=1,名义化学步长等于物理时间步;实际子步由 define_dt 自适应切分。
chimtogcm 只写回 1:lswitch-1,因此 .not.unichim 时 lswitch:nlayer 留给热层化学路径处理。
复现要点
nesp 必须与 ionchem/deutchem 对应的内部物种数一致:基础 17,离子化学加 15,氘化学加 6。
nb_phot_max/nb_reaction_3_max/nb_reaction_4_max 必须与 indice 实际填充计数一致,否则 indice 会中止。
- 在线光解夜间阈值是
sza>113,而 phdisrate 自身还有 zenit>140 夜间判断;本文件进入在线夜间分支时已经把全部 v_phot 清零。
- 离线路径会原地修改局部参数
tau=tau*7/press(1),这是查找表 7 hPa 口径换算。
- 若
ionchem 为真,param_read_e107/fill_data_thermos 等上游热层参数初始化必须已使 jthermcalc_e107 和 phdisrate 可用。
待确认
reactionrates 中 i027 和 i056 速率分别被连续写入两次(1894-1898、2148-2152),未见 i028 对应赋值;是否为编号遗漏或有意复用待确认。
phdisrate 在本文件中固定 chemthermod=2,因此不进入 chemthermod==3 的扩展通道;离子光化学是否需要这些通道需与物理设计确认。
indice 分配的 types_asis 共享索引数组未在本文件释放;是否由进程生命周期管理待确认。
comcstfi_h 在 reactionrates 中全模块 use,需进一步逐项反应确认具体使用的常数。
相关页面