caldyn 动力 tendency 分段

输入范围

dyn3d\caldyn.F
dyn3dpar\caldyn_p.F

Mars 运行参与度:条件经过。串行动力主循环调用 caldyn,并行动力主循环调用 caldyn_p;Mars 是否走 COMMON 版本取决于构建入口和并行配置。#ifdef NODYN 编译选项会将全部 tendency 置零并跳过。

页面定位

本页深入 caldyn/caldyn_p 的内部调用管线,按功能段拆解每个算子的角色、数据依赖和输出写入点。caldyn 串并行对照 提供高层比较;本页补充每个段的算子链路、并行 SAVE 语义、convmas 拆分原因和 advect 命名差异。

签名

串行和并行签名完全一致:

SUBROUTINE caldyn[_p]
 $ (itau, ucov, vcov, teta, ps, masse, pk, pkf, tsurpk, phis,
 $  phi, conser, du, dv, dteta, dp, w, pbaru, pbarv, time)
参数 INTENT 维度 说明
itau IN scalar 时间步索引
ucov IN (ip1jmp1,llm) 协变纬向风
vcov IN (ip1jm,llm) 协变经向风
teta IN (ip1jmp1,llm) 位温
ps IN (ip1jmp1) 地表压力
pk IN (ip1jmp1,llm) Exner 函数中层值
pkf IN (ip1jmp1,llm) 滤波后 Exner
tsurpk IN (ip1jmp1,llm) cpp*temp/pk
phis IN (ip1jmp1) 地表位势
phi IN (ip1jmp1,llm) 中层位势(由 geopot 预计算)
conser IN logical 触发 sortvarc 守恒诊断输出
masse OUT (ip1jmp1,llm) 每层空气质量
du OUT (ip1jmp1,llm) ucov tendency
dv OUT (ip1jm,llm) vcov tendency
dteta OUT (ip1jmp1,llm) 位温 tendency
dp OUT (ip1jmp1) 地表压力 tendency
w OUT (ip1jmp1,llm) 垂直速度
pbaru OUT (ip1jmp1,llm) 纬向质量通量
pbarv OUT (ip1jm,llm) 经向质量通量
time IN scalar 当前时间

注意 phi 是 IN 参数——它在 leapfrog 调用 caldyn 之前由 geopot 预计算传入。

管线总览

caldyn 内部按 5 段顺序执行,每段依赖前段输出:

A. 风场转换和压力:   covcont + pression [+ psextbar]
         ↓
B. 质量初始化:       massdair → massbar → massbarxy → flumass
         ↓
C. 位温通量和 dp:    dteta1 → convmas → dp 计算 → vitvert
         ↓
D. 涡度和能量:       tourpot → dudv1 → enercin → bernoui → dudv2
         ↓
E. 垂直平流:         ang 构造 → advect/advect_new_p → 周期性修正

段 A:风场转换和压力

CALL covcont[_p]  (llm, ucov, vcov, ucont, vcont)
CALL pression[_p] (ip1jmp1, ap, bp, ps, p)

covcont 把协变风转为逆变风,供后续 flumass 使用。pressionap/bp/ps 构造层界压力 p

串行额外调用 psextbar(ps, psexbarxy) 计算地表压力 XY 面积加权平均。并行版本此调用被注释掉(L84 cym),因为 psexbarxy 在并行 caldyn_p 中未被后续使用。

Include 依赖:dimensions.h, paramet.h, comgeom.hairesurg 等在后续段使用)。USE 依赖:comvert_modap, bp)。

详细签名和公式参见 压力与质量算子 family风场转换与质量通量算子组

段 B:质量初始化

CALL massdair[_p]  (p, masse)
CALL massbar[_p]   (masse, massebx, masseby)
CALL massbarxy[_p] (masse, massebxy)
CALL flumass[_p]   (massebx, masseby, vcont, ucont, pbaru, pbarv)

四步从层界压力 p 构造出每层空气质量 masse、U/V/Z 点质量平均 massebx/masseby/massebxy,再与逆变风相乘得到质量通量 pbaru/pbarv

massebxy 在 Z 点(角点)上计算,被段 D 的 tourpot 使用。pbaru/pbarv 同时被段 C 和段 D 使用。

段 C:位温通量和 dp

CALL dteta1[_p]  (teta, pbaru, pbarv, dteta)
CALL convmas[_p/1_p+2_p] (pbaru, pbarv, convm)

dteta1 计算位温水平通量散度:先构造 hbxu = pbaru * 0.5*(teta(ij) + teta(ij+1))hbyv = pbarv * 0.5*(teta(ij) + teta(ij+iip1)),再调用 convflu 求散度,最后 filtreg 滤波。输出 dteta 是位温的水平汇聚 tendency。

convmas 计算质量水平通量散度 convm。并行版本拆为两步:convmas1_p 计算水平散度部分,$OMP BARRIER 同步后 convmas2_p 执行垂直积分部分。拆分原因是两步之间存在数据依赖——垂直积分需要水平散度的完整结果。

dp 直接计算(串行 L94-96,并行 L120-128):

DO ij = ijb, ije
   dp(ij) = convm(ij, 1) / airesurg(ij)
ENDDO

地表压力 tendency 等于第一层质量散度除以地表面积。并行版本在 OMP MASTER 区内执行,用 ij_begin:ij_end 子域范围。

垂直速度

CALL vitvert[_p] (convm, w)

从质量散度垂直积分得到 sigma 坐标垂直速度 w,被段 E 的 advect 使用。

段 D:涡度和能量

CALL tourpot[_p]  (vcov, ucov, massebxy, vorpot)
CALL dudv1[_p]    (vorpot, pbaru, pbarv, du, dv)
CALL enercin[_p]  (vcov, ucov, vcont, ucont, ecin)
CALL bernoui[_p]  (ip1jmp1, llm, phi, ecin, bern)
CALL dudv2[_p]    (tsurpk, pkf, bern, du, dv)

这是动力 tendency 的核心组装段。数据管线:

  1. tourpot 在 Z 点计算位势涡度 vorpot = (filtreg(curl) + fext) / massebxy
  2. dudv1 用位涡和质量通量计算旋转对 du/dv 的贡献(Coriolis-like 项)。
  3. enercin 在 P 点计算 C-grid 动能 ecin,使用 covariant × contravariant 面积加权。
  4. bernoui 计算 Bernoulli 函数 bern = phi + ecin,再 filtreg 滤波。
  5. dudv2 把 Bernoulli 和压力梯度项加到 du/dv 上。

du/dv 在段 D 结束时已包含旋转、Bernoulli 和压力梯度三种贡献。段 E 再叠加垂直平流。

详细签名和公式参见 动能、Bernoulli、位势涡度与位势高度算子

段 E:垂直平流

DO l = 1, llm
   DO ij = ijb, ije
      ang(ij, l) = ucov(ij, l) + constang(ij)
   ENDDO
ENDDO
CALL advect[_new_p] (ang, vcov, teta, w, massebx, masseby, du, dv, dteta)

ang 是绝对角速度(ucov + constang),constang 来自 comgeom.h 的行星自转常量。

串行调用 advect(171 行),并行调用 advect_new_p(290 行),旧并行版 advect_p(217 行)不再被调用。advect_new_p 显式处理更多并行边界条件和 halo 交换。

advectang/vcov/tetaw/massebx/masseby 转交给 advx/advy/advz 底层内核,对 du/dv/dteta 叠加垂直平流贡献。

并行 ang 构造的循环范围:ijb = ij_begin - iip1ije = ij_end + iip1,向两侧各扩展一列 halo 宽度。极点条件:pole_nordijb = ij_begin(不向北扩展),pole_sudije = ij_end(不向南扩展)。使用 OMP DO SCHEDULE(STATIC, OMP_CHUNK)

详细对照参见 advect 文件组对照advxyz 串行内核

后处理:周期性修正和守恒诊断

周期性修正(串行 L124-133,并行 L186-202):

在每层的 ij = 1, ip1jm, iip1(即每行第一个格点)处,检查 dv(ij,l)dv(ij+iim,l) 是否相等,若不等则强制 dv(ij+iim,l) = dv(ij,l)。这是因为 V 点网格在东西边界处应满足周期性,但浮点精度差异可能导致不一致。

并行版本范围:ijb = ij_beginije = ij_endpole_sudije = ij_end - iip1(南极行不需修正,因为不存在对应的 wrap-around 行)。使用 OMP DO SCHEDULE(STATIC, OMP_CHUNK) + END DO NOWAIT

守恒诊断conser 触发):

IF (conser) THEN
   CALL sortvarc (itau, ucov, tsurpk, ps, masse, pk, phis, vorpot, phi, bern, dp, time, vcov)
ENDIF

sortvarc 输出守恒诊断变量,用于调试和质量监控。并行注释提到需要 collective communication(也在 advect 中出现)。

调用链上下文

caldyn/caldyn_pleapfrog 主循环中的位置:

leapfrog/leapfrog_p 主循环 (label 2):
  pression + exner_hyb/exner_milieu     ← 压力和 Exner 刷新
  tpot2t + geopot                        ← 温度→位势
  [NODYN: 全部 tendency 置零]
  ── caldyn/caldyn_p ──                  ← 本页
  [generic + ok_guide: du nudging]       ← 通用行星 guide 修正
  caladvtrac                             ← tracer advection
  addfi                                  ← 物理 tendency 加和
  integrd                                ← 状态积分写回

phicaldyn 之前由 geopot 计算并作为 IN 参数传入。caldyn 输出的 tendency 随后被 integrd 使用,更新 prognostic state ucov/vcov/teta/ps

串并行差异

串行 caldyn.F (145 行) 并行 caldyn_p.F (214 行)
USE 无并行模块 parallel_lmdz, Write_Field_p
局部数组 自动栈分配 SAVE 属性(线程持久存储)
psextbar 活跃调用 注释掉(cym
convmas 单步 convmas 拆为 convmas1_p + BARRIER + convmas2_p + BARRIER
dp 计算 普通 DO 全局 OMP MASTER 区,ij_begin:ij_end 子域
垂直平流 advect (171 行) advect_new_p (290 行)
ang 构造 普通 DO,全局范围 OMP DO SCHEDULE(STATIC,OMP_CHUNK),halo 扩展范围 ±iip1
周期性修正 全局 ij=1,ip1jm,iip1 子域范围 + pole_sud 缩减 + OMP END DO NOWAIT
调试输出 #ifdef DEBUG_IO 块,WriteField_p 多场 dump
BARRIER 段 B/C 之间多个 BARRIER 同步点

SAVE 语义

并行版本给 vcont, ucont, ang, p, massebx, masseby, psexbarxy, vorpot, ecin, bern, massebxy, convm 等局部数组加了 SAVE 属性。这是因为 OpenMP 并行区中线程的栈空间有限,大数组需要放到静态存储区。串行版本无此需求。

convmas 拆分原因

convmas 并行拆为 convmas1_p + convmas2_p 是因为内部存在两步数据依赖:第一步计算水平质量通量散度(纯水平操作,可并行),第二步做垂直积分(需要第一步的完整结果)。中间的 BARRIER 保证所有线程完成第一步后再进入第二步。

数据流图

                    ucov, vcov, teta, ps, pk, pkf, tsurpk, phi
                              │
段 A:  covcont(ucov,vcov) → ucont, vcont
       pression(ap,bp,ps) → p
       [psextbar(ps) → psexbarxy]   (仅串行)
                              │
段 B:  massdair(p) → masse
       massbar(masse) → massebx, masseby
       massbarxy(masse) → massebxy
       flumass(massebx,masseby,vcont,ucont) → pbaru, pbarv
                              │
段 C:  dteta1(teta,pbaru,pbarv) → dteta     (convflu + filtreg)
       convmas(pbaru,pbarv) → convm
       dp(ij) = convm(ij,1) / airesurg(ij)
       vitvert(convm) → w
                              │
段 D:  tourpot(vcov,ucov,massebxy) → vorpot
       dudv1(vorpot,pbaru,pbarv) → du, dv   (旋转贡献)
       enercin(vcov,ucov,vcont,ucont) → ecin
       bernoui(phi,ecin) → bern             (phi+ecin, filtreg)
       dudv2(tsurpk,pkf,bern) → du, dv      (叠加 Bernoulli+压力)
                              │
段 E:  ang = ucov + constang
       advect[_new_p](ang,vcov,teta,w,massebx,masseby) → du,dv,dteta
                              │
后处理: dv 周期性修正
        [conser: sortvarc 诊断输出]
                              │
                    du, dv, dteta, dp, w, pbaru, pbarv, masse

复现要点

待确认

相关页面