dust_coagulation_main

所在文件

LMDZ.MARS\libf\phymars\dust_coagulation_mod.F90

SUBROUTINE dust_coagulation_main(源码第 93-400 行,共 308 行)。

例程类型

subroutine

职责

源码依据(第 4-7 行注释 "Dust coagulation scheme, Based on Bertrand et al., 2022"):在每个物理时间步中,对所有格点的所有层计算**尘埃凝并(coagulation)**倾向。

凝并的物理含义:两个尘埃粒子碰撞后粘连形成更大的粒子,改变尘埃粒径分布。本例程:

  1. 将 mass/number 双矩量展开为 nres_coag=10 个 bin 的对数正态分布;
  2. 用离散化的凝并方程(Smoluchowski 方程)计算每个 bin 的数浓度变化;
  3. 通过体积守恒归一化修正质量守恒;
  4. 将 bin 分布重新合并回 mass/number 的双矩量;
  5. 输出质量/数浓度的倾向 pdqcoag

涉及三种尘埃示踪物:duststormdusttopdust(各自含 mass/number 双矩量)。

参数

参数 方向 类型/维度 单位 含义
ngrid in integer 水平格点数
nlayer in integer 垂直层数
nq in integer 示踪物数
ptime in real s 当前时间(本例程未使用)
ptimestep in real s 物理时间步
pq in real(ngrid,nlayer,nq) kg/kg 示踪物混合比
pdqfi in real(ngrid,nlayer,nq) kg/kg/s 上游倾向
pt in real(ngrid,nlayer) K 层中点温度
pdtfi in real(ngrid,nlayer) K/s 上游温度倾向
pplay in real(ngrid,nlayer) Pa 层中点气压
pplev in real(ngrid,nlayer+1) Pa 层间界面气压(本例程未使用)
pdqcoag out real(ngrid,nlayer,nq) kg/kg/s 凝并倾向(仅尘埃类示踪物有非零值)

使用的 module 变量

变量 来源模块 读/写 含义
pi comcstfi_h 圆周率
g comcstfi_h 重力加速度
r comcstfi_h 比气体常数
mugaz comcstfi_h 气体摩尔质量(推断)
igcm_dust_mass/number tracer_mod 尘埃 mass/number 索引
igcm_stormdust_mass/number tracer_mod stormdust 索引
igcm_topdust_mass/number tracer_mod topdust 索引
kbz microphys_h Boltzmann 常数
m0co2 microphys_h CO₂ 分子质量
rho_dust 本模块(第 54 行) 尘埃密度 2500 kg/m³(模块级 public
dev_dt 本模块(第 53 行) 对数正态分布标准差 0.63676
full_coag_equations 本模块(第 18 行) 是否使用完整方程(vs 查表)
coal_fac 本模块(第 31 行) 总体凝并效率因子(默认 1.0)
dust_coag_kernel_b/g/de/ti 本模块(第 19-22 行) 各 kernel 激活标志
coal_coeff_mode 本模块(第 24 行) 凝聚系数模式(0/1/2)
nres_coag 本模块(第 35 行) bin 分辨率 = 10(parameter
rads_coag 本模块(第 37 行) 各 bin 半径(由 dust_coagulation_init 填充)
vols_coag 本模块(第 37 行) 各 bin 体积
deltar_coag 本模块(第 37 行) 各 bin 直径宽度
table_b/g/de 本模块(第 49-51 行) 预计算的 kernel 查表(3D+2bin 维)
table_pt/pres/mfp 本模块(第 46-48 行) 查表轴(温度/气压/平均自由程)
table_numt/nump/numm 本模块(第 43-45 行) 查表维度大小(15/25/25)

调用的其他例程

例程 调用目的 是否影响主流程
mfp(pt,rho) 计算空气分子平均自由程(第 226、276 行) 是——决定 kernel 值
betab(pt,mfp,rad1,rad2) Brownian 凝并 kernel(第 236-237、249-250 行) 是——完整方程模式
betag(pt,mfp,rad1,rad2) 重力凝并 kernel(第 237、250 行)
betade(pt,mfp,rho,rad1,rad2) 扩散增强 kernel(第 238、251 行)
betati(pt,mfp,rho,rad1,rad2) 湍流 kernel(第 239、252 行,注释标注 "not implemented yet") 是(当前不激活)
boxinterp(...) 2D 双线性插值查表 kernel(第 300-340 行) 是——查表模式
findval(array,value) 在排序数组中找第一个 > value 的位置(第 279-290 行) 是——确定插值角点
frac(i,j,k) 计算两个 bin 凝并产物落入目标 bin k 的体积分数(第 240、316 行) 是——质量重新分配

控制流程

  1. 初始化(第 142-213 行):无条件执行
  2. 凝并分支(第 220 行 if (full_coag_equations)):
    • 完整方程模式(第 220-266 行):逐格点逐层逐 bin 直接计算 kernel 函数
    • 查表模式(第 268-357 行):先通过 findval 定位 (T, mfp) 或 (T, P) 角点,再用 boxinterp 双线性插值 kernel
  3. 凝并激活阈值(第 223、273 行):if (ntot(i,j) > 1000.) — 总粒子浓度 > 1000 nb/m³ 时才触发
  4. 质量守恒归一化(第 261-262、350-351 行):在每个格点层执行
  5. 新矩量计算(第 362-398 行):将 bin 分布重新合并为 mass/number 双矩量
  6. 非负保护(第 391-396 行 where 语句):防止混合比变负

核心计算步骤

阶段 1:初始化(第 142-213 行)

  1. 分布常数(第 145-147 行):

    dens = rho_dust         ! 2500 kg/m³
    sig0 = dev_dt           ! 0.63676
    cst  = 0.75 / (π*dens) * exp(-4.5*sig0²)
  2. 示踪物场推进(第 153-154 行):

    zq = pq + pdqfi * ptimestep
    zt = pt + pdtfi * ptimestep
  3. 大气密度(第 157-159 行):rho = pplay / (r * pt)

  4. 初始对数正态分布(第 173-193 行):对三种尘埃示踪物(mass, mass-1=number):

    mass_ini = max(zq(mass), 1e-15)
    numb_ini = max(zq(number), 1e-15)
    mtot += mass_ini                           ! 累积总质量用于守恒
    r0 = (0.75 * mass_ini / (π * numb_ini * dens))^(1/3) * exp(-1.5*sig0²)
    
    对每个 bin i:
      ndis_tab(i) = numb_ini * rho * deltar_coag(i) / (2*rad(i)*√(2π)*sig0)
                    * exp(-0.5*(ln(rad(i)/r0))² / sig0²)

    这是标准的对数正态分布 PDF,归一化为数浓度。

  5. 各模式数浓度比(第 196-208 行):

    rat_tab(iq) = ndis_tab(iq) / sum(ndis_tab(all_iq))
    rat_tab(iq) /= sum(rat_tab(all_iq))         ! 二次归一化确保 Σ=1

    此比值在凝并后用于将总分布重新拆分回各尘埃模式。

  6. 总初始分布(第 211-213 行):

    ndis = sum(ndis_tab(all_iq))     ! 所有模式合并
    ntot = sum(ndis(all_bins)) / rho ! nb/kg

阶段 2:凝并(第 215-357 行)

对每个格点层,若 ntot > 1000

  1. 环境参数(第 224-226 行):pt0=pt, rho0=rho, mfp0=mfp(pt0,rho0)

  2. 逐 bin 凝并方程(第 229-258 行):

    Term 1(增益项,第 231-243 行):所有 ii < k, jj ≤ k 的碰撞中,产物落入 bin k 的部分

    term1 = Σ_{jj=1..k} Σ_{ii=1..k-1} frac(ii,jj,k) * vol(ii) * kernel(ii,jj) * ndis_new(ii) * ndis(jj)
    term1 *= ptimestep / vol(k)

    Term 2(损耗项,第 246-255 行):bin k 与所有 bin 碰撞而消失

    term2 = Σ_{jj=1..nres_coag} (1 - frac(k,jj,k)) * kernel(k,jj) * ndis(jj)
    term2 *= ptimestep

    半隐式更新(第 257 行):

    ndis_new(k) = (ndis(k) + coal_fac * term1) / (1 + coal_fac * term2)

    这是经典的半隐式格式:增益项用部分更新值(ndis_new for ii<k),损耗项隐式处理。

  3. 体积守恒归一化(第 261-262 行):

    norm = Σ(ndis * vol) / Σ(ndis_new * vol)
    ndis_new *= norm

完整方程 vs 查表

阶段 3:新矩量计算(第 359-398 行)

  1. 按模式拆分(第 364-380 行):用初始比值分配

    ndis_tab_new(iq) = ndis_new * rat_tab(iq)
    numb_new(iq) = Σ(ndis_tab_new(iq)) / rho
    mass_new(iq) = Σ(ndis_tab_new(iq) * vol) * dens / rho
  2. 质量守恒(第 382-398 行):

    mass_new(iq) *= mtot / mtotnew     ! 按总量比缩放确保总质量守恒
    pdqcoag(mass)  = (mass_new - mass_ini) / ptimestep
    pdqcoag(number)= (numb_new - numb_ini_dis) / ptimestep
  3. 非负保护(第 391-396 行):

    where (zq(mass) + pdqcoag(mass)*ptimestep ≤ 0):
      pdqcoag(mass) = -zq(mass)/ptimestep + 1e-15
    where (zq(number) + pdqcoag(number)*ptimestep ≤ 0):
      pdqcoag(number) = -zq(number)/ptimestep + 1e-14

关键公式或算法

凝并方程(Smoluchowski 方程的离散化)

dn_k/dt = ½ Σ_{i+j→k} β(i,j) n_i n_j - Σ_{j} β(k,j) n_k n_j

本代码的半隐式离散形式:

n'_k = (n_k + Σ_{ii<k,jj≤k} frac(ii,jj,k)·vol(ii)·β(ii,jj)·n'_ii·n_jj · Δt/V_k)
       / (1 + Σ_j (1-frac(k,j,k))·β(k,j)·n_jj · Δt)

对数正态分布初始化

n(r) = N·ρ·ΔD / (2·r·√(2π)·σ₀) · exp(-0.5·(ln(r/r₀))²/σ₀²)

其中 r₀ = (0.75·Q/(π·N·ρ_d))^(1/3) · exp(-1.5·σ₀²) 是几何中值半径。

frac 函数(体积分数分配)

当 bin i 和 bin j 的粒子凝并,产物体积 v = vol(i) + vol(j)frac(i,j,k) 表示产物落入 bin k 的比例:

Kernel 函数

Kernel 物理机制 公式概要
betab Brownian 运动 4π(r₁+r₂)(D₁+D₂) / (den₁ + den₂),含 Fuchs 过渡区修正
betag 差速沉降碰并 `E·π(r₁+r₂)²·
betade 扩散增强 0.45·Re^(1/3 or 1/2)·Sc^(1/3)·β_Brownian
betati 湍流凝并 `ε^0.75·π/(g·ν^0.25)·(r₁+r₂)²·

边界条件与保护逻辑

输入数据来源

输出与副作用

伪代码

subroutine dust_coagulation_main(ngrid, nlayer, nq, ptimestep, pq, pdqfi, pt, pdtfi, pplay, pplev, pdqcoag):

  #--- 阶段 1: 初始化 ---
  sig0 = dev_dt; dens = rho_dust; cst = 0.75/(π*dens)*exp(-4.5*sig0²)
  zq = pq + pdqfi*ptimestep
  zt = pt + pdtfi*ptimestep
  rho = pplay / (r * pt)
  pdqcoag = 0

  for each dust mode iq in {dust_mass, stormdust_mass, topdust_mass}:
    mass_ini(iq) = max(zq(mass), 1e-15)
    numb_ini(iq) = max(zq(number), 1e-15)
    mtot += mass_ini(iq)
    r0 = (0.75*mass/(π*numb*dens))^(1/3) * exp(-1.5*sig0²)
    for each bin i:
      ndis_tab(i,iq) = numb*rho*deltar/(2*rad*√(2π)*sig0) * exp(-0.5*(ln(rad/r0))²/sig0²)
    numb_ini_dis(iq) = sum(ndis_tab(iq)) / rho

  rat_tab(iq) = normalize(ndis_tab(iq) / sum(ndis_tab))
  ndis = sum(ndis_tab(all_iq))
  ntot = sum(ndis) / rho

  #--- 阶段 2: 凝并(逐格点逐层)---
  for each (i,j):
    if ntot(i,j) > 1000:
      pt0 = pt(i,j); rho0 = rho(i,j); mfp0 = mfp(pt0, rho0)

      # 查表模式: findval + boxinterp 确定 kernel
      # 完整方程模式: 直接调 betab/betag/betade/betati

      for each bin k = 1..nres_coag:
        term1 = Σ_{ii<k, jj≤k} frac(ii,jj,k)*vol(ii)*K(ii,jj)*ndis_new(ii)*ndis(jj) * Δt/V_k
        term2 = Σ_j (1-frac(k,j,k))*K(k,j)*ndis(jj) * Δt
        ndis_new(k) = (ndis(k) + coal_fac*term1) / (1 + coal_fac*term2)

      # 体积守恒
      norm = Σ(ndis*vol) / Σ(ndis_new*vol)
      ndis_new *= norm

  #--- 阶段 3: 新矩量 ---
  for each dust mode iq:
    ndis_tab_new(iq) = ndis_new * rat_tab(iq)     # 按初始比值拆分
    numb_new(iq) = sum(ndis_tab_new(iq)) / rho
    mass_new(iq) = sum(ndis_tab_new(iq)*vol)*dens / rho
    mtotnew += mass_new(iq)

  for each dust mode iq:
    mass_new(iq) *= mtot / mtotnew                  # 质量守恒
    pdqcoag(mass, iq)   = (mass_new - mass_ini) / ptimestep
    pdqcoag(number, iq) = (numb_new - numb_ini_dis) / ptimestep
    where (zq + pdqcoag*ptimestep ≤ 0):             # 非负保护
      pdqcoag = -zq/ptimestep + small_value

复现注意事项

待确认