xios_writefield.F90

源码路径:

LMDZ.COMMON-6.3\LMDZ.COMMON\libf\phy_common\xios_writefield.F90

Mars 运行参与度:条件经过/接口兼容。该文件只在 CPP_XIOS 下定义 xios_writefield generic;当前 COMMON 与本地 LMDZ.MARS 源码中未检出直接 USE xios_writefield_modxios_writefield(...) 调用点。它应按临时 XIOS field dump helper 维护,不应误读为 Mars diagfistats 或标准 physics XIOS 输出主链。

文件职责

xios_writefield_mod 为物理列局部数组提供一个按字段名懒创建的 XIOS 输出封装:

本文件不定义 Mars 输出频率、正式变量表或 physics 诊断内容。它只按调用方传入的 name_in 和 field shape 即时生成一个同名输出文件。

编译和公开接口

整个模块主体位于:

#ifdef CPP_XIOS
...
#endif

因此没有 CPP_XIOS 时,本文件不会提供 xios_writefield generic。启用 CPP_XIOS 后公开符号只有:

符号 类型 作用
xios_writefield generic interface 根据 rank 分派到 2D 或 3D 版本。
xios_writefield2d module procedure 输出 field(klon_omp)
xios_writefield3d module procedure 输出 field(klon_omp, nz),并创建一个简单垂直 axis。
NameId private function 在当前线程的 FieldName(1:NbField) 中查找字段名。

模块状态

状态 维度/类型 并行属性 含义
size_name parameter 255 常量 字段名缓存长度。
MaxWriteField parameter 100 常量 最多登记字段数;源码无越界保护。
FieldName(MaxWriteField) character save THREADPRIVATE 当前线程已经懒创建过的字段名。
FieldIt(MaxWriteField) integer save THREADPRIVATE 每个字段的 XIOS calendar step counter。
NbField integer save THREADPRIVATE 当前线程已登记字段数。
output_native_grid logical save THREADPRIVATE xios_writefield_nlon/nlat 缺失或为 0 时为真。
ni_glo, nj_glo integer save THREADPRIVATE 用户请求的 regular 输出网格大小。

这些状态都是线程私有。源码没有跨线程同步 FieldName/NbField/FieldIt,也没有清理 XIOS context 或重置缓存的入口。

输入、输出和依赖

输入参数

入口 输入 约束
xios_writefield2d field(:), name_in size(field,1) 必须等于 klon_omp
xios_writefield3d field(:,:), name_in 第一维必须等于 klon_omp;第二维作为临时 vertical axis 长度。

如果第一维不匹配,例程向 lunout 打印错误后直接 RETURN,不会 abort。

使用的 COMMON 状态

来源 符号 用途
dimphy klon_omp 校验调用方传入的是当前 OpenMP 线程的物理列字段。
mod_phys_lmdz_para is_master, is_omp_master, COMM_LMDZ_PHY, Gather_omp, bcast, grid1Dto2D_mpi, klon_mpi, jj_nb root 读取参数、广播输出网格、OMP gather、regular 2D 重排、XIOS context communicator。
mod_grid_phy_lmdz nbp_lon, nbp_lat, klon_glo, grid_type, regular_lonlat, unstructured 选择 domain 类型和发送数组 shape。
wxios wxios_domain_param, wxios_domain_param_unstructured, wxios_set_context 填写 XIOS domain 属性,并在发送后恢复默认 context。
ioipsl getin 读取 xios_writefield_nlonxios_writefield_nlat
print_control_mod lunout shape mismatch 消息输出。

运行配置键

默认/触发 作用
xios_writefield_nlon 初始为 0,root 用 getin 覆盖 unstructured grid 请求插值到 regular domain 时的 longitude 数。
xios_writefield_nlat 初始为 0,root 用 getin 覆盖 unstructured grid 请求插值到 regular domain 时的 latitude 数。

只要 ni_glo==0nj_glo==0,源码就设置 output_native_grid=.TRUE.,即 unstructured 输出保持 native domain。

首次字段定义流程

2D 和 3D 入口的结构基本相同:

检查第一维是否等于 klon_omp
name = trim(adjustl(name_in))
id = NameId(name)

if id != 0:
    OMP master 取回 context_lmdz_<name> 并设为 current context
else:
    root getin xios_writefield_nlon/nlat
    bcast ni_glo/nj_glo
    判断 output_native_grid
    OMP master 初始化 context_lmdz_<name>
    定义 D360 calendar、start date、time origin、timestep
    定义 domain / domaingroup
    如 unstructured 且非 native 输出,额外定义 regular_domain + generate_domain + interpolate_domain
    3D 入口额外定义 axis
    调用 wxios_domain_param 或 wxios_domain_param_unstructured 写 domain 属性
    OMP master 定义 file、field、field_ref
    如 unstructured 且非 native 输出,把 field domain_ref 改成 regular_domain
    close context definition
    登记 FieldName、FieldIt、NbField

Gather_omp 到 field_mpi
OMP master 更新 FieldIt(id) 和 XIOS calendar
按 grid_type 发送 regular 2D/3D block 或 unstructured physical-column block
wxios_set_context 恢复外层 context

grid 分支

grid_type domain 定义 发送数组 说明
regular_lonlat wxios_domain_param("domain") 2D: Field2d(nbp_lon,jj_nb);3D: Field2d(nbp_lon,jj_nb,nz) fieldGather_ompfield_mpi,再 grid1Dto2D_mpi 转为当前 MPI 纬向块。
unstructured, native 输出 wxios_domain_param_unstructured("domaingroup") 2D: field_mpi(klon_mpi);3D: field_mpi(klon_mpi,nz) XIOS domain 类型为 unstructured,global size 来自 klon_glo
unstructured, regular 输出 先定义 native domain,再加 regular_domain 同 unstructured 发送,field 的 domain_ref 改成 regular_domain regular_domain 设置 ni_glo/nj_glo/type="rectilinear",再加 generate_domaininterpolate_domain

mod_grid_phy_lmdzunstructured=0regular_lonlat=1init_grid_phy_lmdz 保存运行时 grid_type。本文件只处理这两个值;若出现其他值,源码没有 else 报错,发送分支会被跳过。

2D 与 3D 差异

项目 2D 3D
输入 field field(klon_omp) field(klon_omp,nz)
MPI local buffer field_mpi(klon_mpi) field_mpi(klon_mpi,nz)
regular send buffer Field2d(nbp_lon,jj_nb) Field2d(nbp_lon,jj_nb,nz)
XIOS field attr domain_ref="domain", operation="instant" domain_ref="domain", axis_ref="axis", operation="instant"
axis 创建 id 为 axis 的 axis,n_glo=nzvalue=1..nzunit="level"

3D 入口的 axis 只是整数层号,不读取 presnivspseudoalt 或真实垂直坐标。

XIOS 输出对象

首次调用字段 name 时,源码创建:

对象 id/name 属性
context context_lmdz_<name> communicator 为 COMM_LMDZ_PHY
calendar D360 start date 和 time origin 都是 2000-01-01 00:00:00,timestep 为 xios_second
file auto child,name=<name> output_freq=xios_timestep, sync_freq=xios_timestep, type="one_file"
field <name> operation="instant",写入同名 file。

每次发送前 FieldIt(id)=FieldIt(id)+1,然后 xios_update_calendar(FieldIt(id))。因此这个 helper 的时间轴是每个字段独立计数,而不是直接继承 GCM 主时间步。

与正式输出链的边界

复现要点

  1. 调用方必须在 CPP_XIOS 构建中使用本模块,否则 generic 不存在。
  2. 传入数组第一维必须是当前 OpenMP 线程的 klon_omp,不是 klon_mpiklon_glodimphy:klon 之外的任意网格长度。
  3. 字段名经 trim(adjustl(name_in)) 后作为 context、file 和 field 名的一部分;同名字段复用已有 context。
  4. regular lon-lat 输出会多一步 grid1Dto2D_mpi,shape 是当前 MPI 子域的 nbp_lon,jj_nb
  5. unstructured grid 若设置了非零 xios_writefield_nlon/nlat,field 的 domain_ref 会切到 regular_domain,由 XIOS 插值到 rectilinear 网格。
  6. MaxWriteField=100 没有源码级越界保护;长期调试时不要动态生成大量唯一字段名。
  7. shape mismatch 的错误消息拼接使用 FieldName 而不是 name_in,实际输出内容可能不直观;源码只 RETURN

待确认

相关页面