水平微分/耗散 stencil family 深度
输入范围
dyn3d_common: grad.F, gradiv.F, gradiv2.F,
diverg.F, divergf.F, divergst.F, diverg_gam.F,
rotat.F, rotatf.F, rotatst.F, rotat_nfil.F,
laplacien.F, laplacien_gam.F, laplacien_rot.F, laplacien_rotgam.F,
nxgrad.F, nxgradst.F, nxgrad_gam.F,
nxgraro2.F, nxgrarot.F
dyn3dpar: 对应 17 个 _p 变体
Mars 运行参与度:条件经过。所有复合算子由 dissip/dissip_p 和 inidissip 调用,仅在 apdiss 为真时执行。叶子算子由复合算子内部调用,不直接从外部入口调用。
页面定位
本页提供 dyn3d_common 中水平微分/耗散 stencil 算子族的深度签名、公式、变体关系和串并行对照。它承接 差分算子总览 的分类框架,补充每个算子的精确签名、网格位置、Include 依赖和内部调用链。耗散链路的端到端数据流由 Mars 水平耗散链路 覆盖;inidissip 的配置和特征值估算由 inidissip 文件页 覆盖。gradsdef.h(GrADS I/O header)不属于差分算子,本页不覆盖。
文件总览
叶子算子(基础微分)
| 算子 | 串行文件 | 并行文件 | 行数 (串/并) | 输入格点 | 输出格点 | Include |
|---|---|---|---|---|---|---|
grad |
grad.F |
grad_p.F |
45/54 | P | U, V | dimensions.h, paramet.h |
diverg |
diverg.F |
diverg_p.F |
86/107 | U, V | P | + comgeom.h |
divergf |
divergf.F |
divergf_p.F |
86/116 | U, V | P | + comgeom.h |
diverg_gam |
diverg_gam.F |
diverg_gam_p.F |
81/98 | U, V | P | + comgeom.h |
rotat |
rotat.F |
rotat_p.F |
59/64 | U, V | Z | + comgeom.h |
rotatf |
rotatf.F |
rotatf_p.F |
59/68 | U, V | Z | + comgeom.h |
rotat_nfil |
rotat_nfil.F |
rotat_nfil_p.F |
50/53 | U, V | Z | + comgeom.h |
nxgrad |
nxgrad.F |
nxgrad_p.F |
49/68 | Z | U, V | + comgeom.h |
nxgrad_gam |
nxgrad_gam.F |
nxgrad_gam_p.F |
48/68 | Z | U, V | + comgeom.h |
Laplacian 复合算子
| 算子 | 串行文件 | 并行文件 | 行数 (串/并) | 内部调用 | Include |
|---|---|---|---|---|---|
laplacien |
laplacien.F |
laplacien_p.F |
41/57 | filtreg → grad → divergf |
+ comgeom.h |
laplacien_gam |
laplacien_gam.F |
laplacien_gam_p.F |
54/66 | grad → diverg_gam |
+ comgeom.h |
laplacien_rot |
laplacien_rot.F |
laplacien_rot_p.F |
40/46 | filtreg → nxgrad → rotatf |
+ comgeom.h |
laplacien_rotgam |
laplacien_rotgam.F |
laplacien_rotgam_p.F |
45/49 | nxgrad_gam → rotat_nfil → × unsairz_gam |
+ comgeom.h |
耗散复合算子
| 算子 | 串行文件 | 并行文件 | 行数 (串/并) | 内部调用链 | Include |
|---|---|---|---|---|---|
gradiv |
gradiv.F |
gradiv_p.F |
57/109 | 迭代 ld 次:diverg → filtreg → grad × -cdivu |
+ comdissipn.h |
gradiv2 |
gradiv2.F |
gradiv2_p.F |
80/148 | divergf → laplacien → (ld-2)× laplacien_gam → filtreg → grad × cdivu |
+ comgeom.h, comdissipn.h |
nxgrarot |
nxgrarot.F |
nxgrarot_p.F |
55/101 | 迭代 lr 次:rotat → filtreg → nxgrad × -crot |
+ comdissipn.h |
nxgraro2 |
nxgraro2.F |
nxgraro2_p.F |
69/142 | rotatf → laplacien_rot → (lr-2)× laplacien_rotgam → filtreg → nxgrad × crot |
+ comdissipn.h |
死代码
divergst.F(63 行)、rotatst.F(44 行)和 nxgradst.F(48 行)在整个代码库中无任何调用方,也不存在对应的 _p 并行变体。它们是 staggered-grid 简化版本,可能用于早期开发或已废弃的诊断路径。
grad — 标量梯度
SUBROUTINE grad(klevel, pg, pgx, pgy)
INTEGER klevel
REAL pg(ip1jmp1, klevel) ! 输入:P 点标量场
REAL pgx(ip1jmp1, klevel) ! 输出:U 点 x-梯度
REAL pgy(ip1jm, klevel) ! 输出:V 点 y-梯度有限差分:pgx(ij) = pg(ij+1) - pg(ij)(前向差),pgy(ij) = pg(ij) - pg(ij+iip1)(南向北差)。周期性修正 pgx(ij+iim) = pgx(ij)。无滤波、无度量权重。
散度族
diverg — 协变向量散度(无滤波)
SUBROUTINE diverg(klevel, x, y, div)
REAL x(ip1jmp1, klevel), y(ip1jm, klevel) ! 输入:U/V 点协变分量
REAL div(ip1jmp1, klevel) ! 输出:P 点散度公式:div(ij) = (x(ij)*cvusurcv(ij) - x(ij-1)*cvusurcv(ij-1)) + (y(ij)*cuvscu(ij) - y(ij-iip1)*cuvscu(ij-iip1)),再乘以 unaire(ij)(逆格点面积)。极点用面积加权求和除以 apoln/apols。
divergf — 滤波散度
与 diverg 相同公式,但在面积乘法前调用 filtreg(div, jjp1, klevel, 2, 1, .TRUE., 1) 施加正则滤波。用于 gradiv2 和 laplacien 内部。
diverg_gam — gamma 权重散度
SUBROUTINE diverg_gam(klevel, cuvscvgam, cvuscugam, unsairegam,
unsapolnga, unsapolsga, x, y, div)使用 gamma-耗散度量比(cvuscugam/cuvscvgam)和 gamma 逆面积(unsairegam)替代标准度量。由 comdissipn.h 中 inidissip 初始化的 gamma 权重数组驱动。用于 laplacien_gam 内部。
旋度族
rotat — 协变向量旋度(无滤波)
SUBROUTINE rotat(klevel, x, y, rot)
REAL x(ip1jmp1, klevel), y(ip1jm, klevel) ! 输入:U/V 点协变分量
REAL rot(ip1jm, klevel) ! 输出:Z 点旋度公式:rot(ij) = y(ij+1) - y(ij) + x(ij) - x(ij+iip1)(离散旋度),再乘以 unairez(ij)(Z 点逆面积)。
rotatf — 滤波旋度
与 rotat 相同公式,在面积乘法前调用 filtreg。用于 nxgraro2 和 laplacien_rot 内部。
rotat_nfil — 无滤波无面积归一化旋度
与 rotat 相同差分公式,但不调用 filtreg 且不乘以 unairez。返回原始环量。用于 laplacien_rotgam 内部,gamma 面积归一化在外部完成。
nxgrad — 旋转梯度族
nxgrad — π/2 旋转梯度
SUBROUTINE nxgrad(klevel, rot, x, y)
REAL rot(ip1jm, klevel) ! 输入:Z 点旋度场
REAL x(ip1jmp1, klevel) ! 输出:U 点旋转梯度 x
REAL y(ip1jm, klevel) ! 输出:V 点旋转梯度 y公式:y(ij) = (rot(ij) - rot(ij-1)) * cvsurcuv(ij),x(ij) = (rot(ij) - rot(ij-iip1)) * cusurcvu(ij)。极点置零,周期性修正。
nxgrad_gam — gamma 权重旋转梯度
使用 gamma 度量比 cvscuvgam/cuscvugam 替代标准 cvsurcuv/cusurcvu。用于 laplacien_rotgam 内部。
Laplacian 复合算子
laplacien — 标准标量 Laplacian
SUBROUTINE laplacien(klevel, teta, divgra)内部链:teta → divgra(复制)→ filtreg → grad → divergf。即 div_f(grad(teta)):先滤波再取梯度的滤波散度。
laplacien_gam — gamma 权重 Laplacian
SUBROUTINE laplacien_gam(klevel, cuvsga, cvusga, unsaigam,
unsapolnga, unsapolsga, teta, divgra)内部链:teta → divgra(复制)→ grad → diverg_gam。无滤波。gamma 度量数组由 comdissipn.h 提供。
laplacien_rot — 旋转 Laplacian
SUBROUTINE laplacien_rot(klevel, rotin, rotout, ghx, ghy)内部链:rotin → filtreg → nxgrad → rotatf。即 rot_f(nxgrad(rotin)):先滤波再取旋转梯度的滤波旋度。
laplacien_rotgam — gamma 旋转 Laplacian
SUBROUTINE laplacien_rotgam(klevel, rotin, rotout)内部链:rotin → nxgrad_gam → rotat_nfil → × unsairz_gam。无滤波。gamma 面积归一化在最后一步完成。
耗散复合算子
gradiv — 迭代 grad(div)(标准版)
SUBROUTINE gradiv(klevel, xcov, ycov, ld, gdx, gdy)
REAL xcov(ip1jmp1, klevel), ycov(ip1jm, klevel) ! 输入:协变风场
INTEGER ld ! 迭代次数
REAL gdx(ip1jmp1, klevel), gdy(ip1jm, klevel) ! 输出:耗散增量迭代 ld 次,每次:diverg(gdx,gdy) → filtreg(div) → grad(div) → × -cdivu。cdivu 来自 comdissipn.h,由 inidissip 初始化。当 lstardis=.false. 时使用。
gradiv2 — gamma 高阶 grad(div)(star 版)
SUBROUTINE gradiv2(klevel, xcov, ycov, ld, gdx, gdy)单次 divergf → laplacien → (ld-2) 次 laplacien_gam → filtreg → grad → × cdivu(符号由 ld 决定)。gamma 度量数组 cuvscvgam1/cvuscugam1/unsair_gam1 来自 comdissipn.h。当 lstardis=.true. 时使用。
nxgrarot — 迭代 n×grad(rot)(标准版)
SUBROUTINE nxgrarot(klevel, xcov, ycov, lr, grx, gry)迭代 lr 次,每次:rotat(grx,gry) → filtreg(rot) → nxgrad(rot) → × -crot。crot 来自 comdissipn.h。当 lstardis=.false. 时使用。
nxgraro2 — gamma 高阶 n×grad(rot)(star 版)
SUBROUTINE nxgraro2(klevel, xcov, ycov, lr, grx, gry)单次 rotatf → laplacien_rot → (lr-2) 次 laplacien_rotgam → filtreg → nxgrad → × crot。当 lstardis=.true. 时使用。
内部调用图
gradiv (ld 迭代) gradiv2 (gamma star)
├─ diverg ├─ divergf
├─ filtreg ├─ laplacien (filtreg→grad→divergf)
└─ grad ├─ (ld-2)× laplacien_gam (grad→diverg_gam)
├─ filtreg
└─ grad
nxgrarot (lr 迭代) nxgraro2 (gamma star)
├─ rotat ├─ rotatf
├─ filtreg ├─ laplacien_rot (filtreg→nxgrad→rotatf)
└─ nxgrad ├─ (lr-2)× laplacien_rotgam (nxgrad_gam→rotat_nfil→×unsairz_gam)
├─ filtreg
└─ nxgrad
外部调用方:
dissip/dissip_p: gradiv2/gradiv (lstardis 分支)
nxgraro2/nxgrarot (lstardis 分支)
divgrad2/divgrad (第三路)
inidissip: 同上 (特征值估算, klevel=1)
串并行差异
叶子算子并行模式
所有 9 个叶子算子的并行化模式一致:USE parallel_lmdz,c$OMP DO SCHEDULE(STATIC,OMP_CHUNK) 在 klevel 外层循环,子域范围 ijb=ij_begin, ije=ij_end 加极点条件调整(pole_nord 跳过北极行,pole_sud 跳过南极行),filtreg → filtreg_p 带 jjb/jje 子域。无 halo 交换——叶子算子依赖调用者保证 halo 已同步。
复合算子并行模式
四个 Laplacian 复合算子内部调用 _p 叶子算子,自身不增加额外 halo 交换(halo 由上层保证)。
四个耗散复合算子有两种并行 halo 策略:
| 算子 | halo 策略 | 额外模块 |
|---|---|---|
gradiv_p |
阻塞 exchange_Hallo (MASTER/BARRIER) |
parallel_lmdz, times |
gradiv2_p |
异步 Register_Hallo/SendRequest/WaitRequest |
parallel_lmdz, times, mod_hallo |
nxgrarot_p |
阻塞 exchange_Hallo (MASTER/BARRIER) |
parallel_lmdz, times |
nxgraro2_p |
异步 Register_Hallo/SendRequest/WaitRequest |
parallel_lmdz, times, mod_hallo |
标准版(gradiv_p/nxgrarot_p)用阻塞 halo 交换,每次迭代在 OMP MASTER 块中同步。Star 版(gradiv2_p/nxgraro2_p)用异步非阻塞 halo,在 OMP BARRIER 之间注册和等待,允许计算/通信重叠。
输出数组分离
串行耗散复合算子直接在 gdx/gdy 或 grx/gry 中就地迭代。并行版使用 SAVE 内部数组做迭代,最终用 OMP DO 把子域结果复制到独立的 gdx_out/gdy_out(或 grx_out/gry_out)输出数组。
已知异常
gradiv2_p.F L104 调用串行 laplacien_gam(不是 laplacien_gam_p)。对比 divgrad2_p.F L88 正确调用 laplacien_gam_p。这可能是一个遗留 bug 或有意为之(laplacien_gam 内部只调叶子算子,可能不需要额外 halo),但需确认。
调用方总览
所有 20 个活跃算子的外部调用方仅限于 dissip.F/dissip_p.F(耗散施加)和 inidissip.F90(特征值估算)。叶子算子和 Laplacian 复合算子没有外部直接调用方——它们只被其他 stencil 算子内部调用。
| 外部调用方 | 调用的算子 | 说明 |
|---|---|---|
dissip.F L81-108 |
gradiv2/gradiv, nxgraro2/nxgrarot |
按 lstardis 分支选择 |
dissip_p.F L104-147 |
gradiv2_p/gradiv_p, nxgraro2_p/nxgrarot_p |
同上 |
dissip.F L137-139 |
divgrad2/divgrad |
第三路温度耗散 |
dissip_p.F L195-197 |
divgrad2_p/divgrad_p |
同上 |
inidissip.F90 L129-177 |
全部 6 个复合算子 | 特征值估算 (klevel=1) |
caldyn.F/caldyn_p.F、COMMON leapfrog.F/leapfrog_p.F 和 MARS phymars/leapfrog_nogcm.F 不直接调用任何 stencil 算子。
复现要点
lstardis决定走标准路径(gradiv/nxgrarot)还是 star 路径(gradiv2/nxgraro2),由inidissip从run.def读取。- gamma 度量数组(
cuvscvgam1/cvuscugam1/unsair_gam1等)来自comdissipn.h,由inidissip在初始化时计算。 - 叶子算子之间不可互换:
diverg(无滤波)和divergf(有滤波)在耗散迭代中的选择影响数值稳定性。 - 并行版的 halo 交换是正确性前提:遗漏会导致子域边界处差分结果错误。
divergst/rotatst/nxgradst是死代码,不参与 Mars 运行路径。
待确认
gradiv2_p中调用串行laplacien_gam而非laplacien_gam_p是否为已知 bug 或有意设计。- gamma 度量数组的具体数值来源(
inidissip幂迭代过程中的生成方式)需在inidissip页面补充。 divergst/rotatst/nxgradst是否在任何 Earth/Venus 构建路径中被使用(当前搜索仅限 Mars COMMON)。- 阻塞 vs 异步 halo 策略的选择标准(标准版 vs star 版的性能差异)需在并行性能页面覆盖。