writediagmicrofi.F
路径
LMDZ.MARS\libf\phymars\writediagmicrofi.F
所属目录 / 模块
libf/phymars
文件定位
writediagmicrofi.F 定义传统微物理子步诊断文件 diagmicrofi.nc 的写入后端。它沿用 writediagfi 的按变量逐次调用模式,但额外定义有限长度 microtime 维度,用来在一个物理输出时刻内保存 coupled water microphysics / sedimentation 的每个微物理子步。源码历史注释明确说明 2020 年加入该文件,目标维度顺序为 (time,microtime,alt,lat,lon)。
例程在第一次进入时读取可选 diagmicrofi.def,未列出的变量直接返回;第一次有效变量调用时创建 diagmicrofi.nc、定义 Time 和 microtime,并调用 iniwrite 写经纬度、垂直层、地表位势和网格面积等固定头信息。后续写入由 firstnom、microstep 和 steps_per_sol/outputs_per_sol 共同控制:只有每个物理时刻的首个微物理子步会推进主时间索引,所有同名首变量调用会推进 microtime 坐标。
定义的符号
| 符号 |
类型 |
行号 |
作用 |
writediagmicrofi |
subroutine |
1 |
向 diagmicrofi.nc 创建并追加微物理子步诊断变量。 |
firstcall |
saved logical |
107 |
第一次进入时读取 diagmicrofi.def 并计算采样间隔。 |
firstnom / zitau |
saved state |
87-89 |
识别每个物理时刻的首变量,并推进主输出步计数。 |
ntime |
saved integer |
92 |
NetCDF unlimited Time 维的当前写入索引。 |
subdate |
saved real*4 |
77 |
当前主时间内的微物理子步累计时间,写入 microtime。 |
依赖的模块
| use 模块 |
only 列表 |
用途 |
待确认 |
surfdat_h |
phisfi |
首次创建文件时写地表位势。 |
- |
geometry_mod |
cell_area |
首次创建文件时写网格面积。 |
- |
time_phylmdz_mod |
steps_per_sol, outputs_per_sol |
计算输出采样间隔 isample。 |
- |
time_phylmdz_mod |
day_ini |
传给 iniwrite 作为文件头时间起点。 |
- |
mod_phys_lmdz_para |
is_parallel, is_mpi_root, is_master, gather |
并行路径中收集字段,并限制 NetCDF 由 master/root 写。 |
- |
mod_grid_phy_lmdz |
klon_glo, Grid1Dto2D_glo, nbp_lon, nbp_lat, nbp_lev |
提供全局网格维度,并把 1D 物理网格重排到经纬网格。 |
- |
调用的关键例程
| 被调用例程 |
所在模块 / 文件 |
调用位置 |
作用 |
iniwrite |
iniwrite.F |
首次有效变量调用 |
向 diagmicrofi.nc 写固定坐标、控制参数、面积和地表位势。 |
def_var |
def_var.F90 |
每个新诊断变量首次写入 |
在 NetCDF define mode 中创建变量并写 title/units 属性。 |
abort_physic |
外部错误处理 |
多处错误分支 |
变量名过长、变量重复、并行 dim=1 或写入失败时中止。 |
NetCDF NF_* |
NetCDF F77 接口 |
多处 |
创建、打开、关闭文件,定义维度/变量,追加坐标和诊断字段。 |
gather, Grid1Dto2D_glo |
并行/网格模块 |
并行 dim=2/3 路径 |
收集物理网格字段并重排到全局经纬网格。 |
输入
| 输入 |
来源 |
类型 / 维度 |
单位 |
含义 |
ngrid |
调用方 |
integer |
- |
当前物理网格点数。 |
imicro |
调用方 |
integer |
step count |
一个物理输出时刻内的微物理子步数量,也是 microtime 维长度。 |
microstep |
调用方 |
integer |
step index |
当前微物理子步索引,作为 microtime 写入位置。 |
microtimestep |
调用方 |
real |
timestep |
微物理子步长度,每次首变量调用时累加到 subdate。 |
nom, titre, unite |
调用方 |
character |
- |
变量名、标题和单位属性。 |
dim |
调用方 |
integer 0/1/2/3 |
- |
诊断变量维度码。 |
px(ngrid,nbp_lev) |
调用方 |
real array |
variable-dependent |
待写诊断场;低维变量也通过该二维实参承载。 |
diagmicrofi.def |
运行目录可选文件 |
text file |
- |
若存在,仅输出列在其中的变量名。 |
输出
| 输出 |
去向 |
类型 / 维度 |
单位 |
含义 |
diagmicrofi.nc |
当前运行目录 |
NetCDF file |
- |
微物理子步诊断文件。 |
Time |
diagmicrofi.nc |
unlimited coordinate |
days |
由 zitau 和 steps_per_sol 推得的主物理输出时间。 |
microtime |
diagmicrofi.nc |
finite coordinate, length imicro |
steps |
主输出时间内的微物理子步累计时间。 |
nom 变量 |
diagmicrofi.nc |
0D/1D/2D/3D + microtime + Time |
unite |
调用方指定的微物理诊断字段。 |
共享状态与副作用
- 例程使用多组
SAVE / THREADPRIVATE 状态:date/subdate、zitau/firstnom、ntime、firstcall。这些状态决定何时写主时间、微时间和变量。
diagmicrofi.def 只在第一次进入时由 OpenMP master 读取;若文件存在且当前变量名未列入,例程直接返回,不创建文件、不推进时间。
- 首次有效变量调用会以
NF_CLOBBER 创建 diagmicrofi.nc,因此同名文件会被覆盖。
- 每次满足采样条件时 master 打开
diagmicrofi.nc,写完当前变量后关闭文件。
- 并行路径只让 master/root 写 NetCDF;
dim=1 在并行模式下未实现,会调用 abort_physic。
核心逻辑
- 第一次进入时计算
isample=steps_per_sol/outputs_per_sol,尝试读取 diagmicrofi.def,保存允许输出的变量名列表。
- 若启用了
diagmicrofi.def 且 nom 不在列表中,立即返回。
- 第一次有效变量调用时设置
firstnom=nom,收集 phisfi/cell_area,创建 diagmicrofi.nc,定义 unlimited Time、有限 microtime 及对应坐标变量,并调用 iniwrite 写文件头。
- 只有
(nom == firstnom) .and. (microstep == 1) 时推进 zitau。
- 只有
MOD(zitau+1,isample)==0 时进入写文件分支。
- 在每个输出物理时刻的
firstnom 且 microstep==1 调用上,递增 ntime、写 Time,并把 subdate 归零。
- 在每个
firstnom 调用上,累加 subdate=subdate+microtimestep,并写 microtime(microstep)。
- 按
dim 将 px 转成 3D、2D、1D 或 0D 缓冲,必要时用 def_var 创建变量,再在 (microstep,ntime) 位置写入。
伪代码
writediagmicrofi(ngrid, imicro, microstep, microtimestep, nom, titre, unite, dim, px):
on first call:
isample = steps_per_sol / outputs_per_sol
read optional diagmicrofi.def
if diagmicrofi.def exists and nom is not listed:
return
on first valid variable:
firstnom = nom
create diagmicrofi.nc
define Time and microtime(imicro)
gather/copy phisfi and cell_area
call iniwrite(...)
close file
if nom == firstnom and microstep == 1:
zitau += 1
if MOD(zitau + 1, isample) == 0:
open diagmicrofi.nc
if nom == firstnom and microstep == 1:
ntime += 1
write Time(ntime)
subdate = 0
if nom == firstnom:
subdate += microtimestep
write microtime(microstep)
recast/gather px according to dim
create variable with def_var if needed
write variable slice at microstep, ntime
close diagmicrofi.nc
参与的主题流程
| 主题 |
参与方式 |
| 微物理诊断输出 |
为 coupled water microphysics / sedimentation 的每个子步提供传统 NetCDF 输出。 |
| 传统 NetCDF 文件初始化 |
首次有效变量调用时复用 iniwrite 和 def_var 写固定头信息与变量定义。 |
| 并行诊断输出 |
并行构建中先 gather 到全局物理网格,再由 root/master 重排并写文件。 |
写法特点
- 与
writediagfi 相比,本例程多了 microtime 维度和 microstep/microtimestep 控制,但主时间推进仍依赖 firstnom。
microtime 是固定长度维度,长度来自调用方传入的 imicro;源码内没有检查 microstep <= imicro。
- 3D 变量维度为
longitude, latitude, altitude, microtime, Time;2D 为 longitude, latitude, microtime, Time;1D 为 altitude, microtime, Time;0D 为 microtime, Time。
- 所有实际数据写入使用
NF_PUT_VARA_REAL,会以 real*4 形式输出。
复现要点
diagmicrofi.def 若存在,必须包含触发 firstnom 的变量名;否则文件可能不会创建或时间不会按预期推进。
- 调用顺序必须保证每个物理时刻、每个微物理子步都以同一个
firstnom 变量作为首个诊断变量,否则 zitau、ntime 和 microtime 的推进会错位。
microstep 必须落在 1:imicro 内;源码未做边界检查,越界会直接影响 NetCDF 写入位置。
- 并行模式不能写
dim=1 column 诊断。
待确认
diagmicrofi_def/n_nom_def/nom_def 只在 THREADPRIVATE(firstcall) 行尾注释中出现,未像 firstcall 一样明确放入 OpenMP THREADPRIVATE 指令;OpenMP 下筛选列表是否所有线程一致,需结合预处理和运行测试确认。
- 源码定义维度名为小写
"microtime",但 dim=2 和 dim=0 创建变量时查询的是 "Microtime"。NetCDF 维度名区分大小写时这两个分支可能无法创建变量;需运行复现确认。
isample=steps_per_sol/outputs_per_sol 未在本例程内检查整除性。
相关页面