def_var.F90
路径
LMDZ.MARS\libf\phymars\def_var.F90
所属目录 / 模块
libf/phymars
文件定位
def_var.F90 提供一个外部子程序 def_var,用于在已经打开的 NetCDF 文件中定义一个新变量,并写入 title 与 units 两个文本属性。它不是 Fortran module,不保存共享状态,也不直接写变量数据;实际数据写入由 writediagfi.F、writediagmicrofi.F、writediagsoil.F90、write_archive.F、ini_archive.F 和 iniwrite.F 等调用者完成。
该例程封装了传统 NetCDF Fortran 接口的一段重复流程:切回 define mode,调用 NF_DEF_VAR 定义变量,写属性,再退出 define mode。2010 年注释说明输出被强制为 real*4;源码中 NC_DOUBLE 分支已经被注释掉,实际始终使用 NF_FLOAT 定义新变量。
定义的符号
| 符号 |
类型 |
行号 |
作用 |
def_var |
subroutine |
1 |
在已打开 NetCDF 文件中定义变量,写入 title 和 units 属性,并返回变量 ID 与错误码 |
依赖的模块
| use 模块 |
only 列表 |
用途 |
待确认 |
| 无 |
- |
源码没有 use 语句 |
否 |
netcdf.inc |
include file |
提供 NF_REDEF、NF_DEF_VAR、NF_PUT_ATT_TEXT、NF_ENDDEF、NF_NOERR、NF_FLOAT、NF_STRERROR 等 NetCDF 常量和接口 |
否 |
调用的关键例程
| 被调用例程 |
所在模块 / 文件 |
调用位置 |
作用 |
NF_REDEF |
NetCDF Fortran 接口 |
def_var.F90:28 |
把已打开文件切回 define mode |
NF_DEF_VAR |
NetCDF Fortran 接口 |
def_var.F90:34 |
用 NF_FLOAT、nbdim 和 dimids 定义变量 |
NF_PUT_ATT_TEXT |
NetCDF Fortran 接口 |
def_var.F90:43, def_var.F90:51 |
写入 title 和 units 文本属性 |
NF_ENDDEF |
NetCDF Fortran 接口 |
def_var.F90:60 |
退出 define mode,回到可写数据状态 |
NF_STRERROR |
NetCDF Fortran 接口 |
def_var.F90:38, def_var.F90:47, def_var.F90:55 |
把 NetCDF 错误码打印为文本 |
abort_physic |
外部错误终止例程 |
def_var.F90:39, def_var.F90:48, def_var.F90:56 |
变量定义或属性写入失败时中止物理流程 |
输入
| 输入 |
来源 |
类型 / 维度 |
单位 |
含义 |
nid |
调用者打开的 NetCDF 文件 |
integer |
- |
NetCDF file ID |
name |
调用者传入 |
character(len=*) |
- |
变量名;传给 NF_DEF_VAR 前使用 adjustl(name) |
title |
调用者传入 |
character(len=*) |
- |
写入变量属性 title 的文本 |
units |
调用者传入 |
character(len=*) |
- |
写入变量属性 units 的文本 |
nbdim |
调用者传入 |
integer |
- |
变量维度数 |
dimids |
调用者先通过 NF_INQ_DIMID 或维度定义取得 |
integer(nbdim) |
- |
变量各维度的 NetCDF dimension ID |
输出
| 输出 |
去向 |
类型 / 维度 |
单位 |
含义 |
nvarid |
调用者后续写变量数据时使用 |
integer |
- |
新定义变量的 NetCDF variable ID |
ierr |
调用者可继续检查 |
integer |
- |
最后一次 NetCDF 调用的状态码;成功路径结束时来自 NF_ENDDEF |
| NetCDF 变量定义 |
nid 指向的已打开文件 |
NF_FLOAT 变量 |
由 units 属性描述 |
在文件 schema 中新增变量及属性 |
共享状态与副作用
- 本文件没有 module 变量、common block、
SAVE 局部状态或 OpenMP 声明。
- 它会修改
nid 指向的 NetCDF 文件结构:新增变量、写入 title 与 units 属性,并在成功路径结束时退出 define mode。
- 三类失败会立即
abort_physic:NF_DEF_VAR 失败、写 title 属性失败、写 units 属性失败。
- 源码没有在
NF_REDEF 和最终 NF_ENDDEF 后检查 ierr;复现失败时需要结合调用者传入的文件状态和 NetCDF 返回码定位。
核心逻辑
- 调用
NF_REDEF(nid),把已打开的 NetCDF 文件切到定义模式。
- 调用
NF_DEF_VAR(nid, adjustl(name), NF_FLOAT, nbdim, dimids, nvarid) 定义新变量。
- 如果变量定义失败,打印变量名和
NF_STRERROR(ierr),再调用 abort_physic("def_var", "netcdf definition problem", 1)。
- 用
NF_PUT_ATT_TEXT 写 title 属性,长度为 len_trim(adjustl(title))。
- 如果
title 写入失败,打印诊断并以 netcdf title attribute problem 中止。
- 用
NF_PUT_ATT_TEXT 写 units 属性,长度为 len_trim(adjustl(units))。
- 如果
units 写入失败,打印诊断并以 netcdf units attribute problem 中止。
- 调用
NF_ENDDEF(nid) 退出定义模式。
伪代码
subroutine def_var(nid, name, title, units, nbdim, dimids, nvarid, ierr)
ierr = NF_REDEF(nid)
ierr = NF_DEF_VAR(nid, adjustl(name), NF_FLOAT, nbdim, dimids, nvarid)
if ierr is not NF_NOERR:
print variable-definition failure and NetCDF error text
abort physics
ierr = NF_PUT_ATT_TEXT(nid, nvarid, "title",
len_trim(adjustl(title)), adjustl(title))
if ierr is not NF_NOERR:
print title-attribute failure and NetCDF error text
abort physics
ierr = NF_PUT_ATT_TEXT(nid, nvarid, "units",
len_trim(adjustl(units)), adjustl(units))
if ierr is not NF_NOERR:
print units-attribute failure and NetCDF error text
abort physics
ierr = NF_ENDDEF(nid)
end
参与的主题流程
| 主题 |
参与方式 |
| 诊断输出 |
writediagfi.F 在 4D、3D、2D、1D 诊断变量首次出现时调用 def_var 创建变量 |
| 微物理诊断输出 |
writediagmicrofi.F 在 5D、4D、3D、2D 微物理诊断变量首次出现时调用 def_var |
| 土壤诊断输出 |
writediagsoil.F90 在 diagsoil.nc 中创建剖面、地表场和标量诊断变量时调用 def_var |
| 初始状态 / 归档输出 |
ini_archive.F、write_archive.F 和 iniwrite.F 用它创建时间、垂直坐标和归档变量 |
主要调用点
| 调用者 |
调用位置 |
维度数 |
说明 |
dynphy_lonlat/phymars/ini_archive.F |
180 |
1 |
定义 archive 文件中的 Time 变量 |
dynphy_lonlat/phymars/write_archive.F |
86, 151, 191, 240, 277, 323 |
1-5 |
根据变量形状创建 archive 输出变量 |
phymars/iniwrite.F |
244, 252, 260, 268 |
1 |
定义 aps/bps/ap/bp 垂直坐标变量 |
phymars/writediagfi.F |
380, 484, 555, 605 |
1-4 |
创建常规 diagfi 诊断变量 |
phymars/writediagmicrofi.F |
395, 502, 576, 629 |
2-5 |
创建微物理诊断变量 |
phymars/writediagsoil.F90 |
255, 339, 390 |
1, 3, 4 |
创建 diagsoil.nc 土壤诊断变量 |
写法特点
- 外部子程序而非 module:文件只有一个
subroutine def_var,没有 contains、module 或显式接口。
- 传统 NetCDF Fortran 77 风格接口:通过
include "netcdf.inc" 使用 NF_* 常量和函数。
- 强制单精度输出定义:虽然保留了
NC_DOUBLE 条件编译痕迹,但相关代码被注释掉,当前总是 NF_FLOAT。
- 属性名使用
title 而不是 long_name:源码注释明确说 long_name 更合适,但实现仍写 title。
- 调用者负责维度准备:本例程不创建维度,只消费
dimids;维度缺失通常会在调用者的 NF_INQ_DIMID 或后续定义阶段暴露。
复现要点
- 调用
def_var 前,nid 必须指向已创建并打开的 NetCDF 文件。
dimids 必须已经按变量维度顺序填好,且数组长度与 nbdim 一致。
- 新变量数据类型固定为
NF_FLOAT;即使编译时定义 NC_DOUBLE,当前源码也不会用 NF_DOUBLE 定义变量。
name、title、units 会先 adjustl,属性长度用 len_trim(adjustl(...)),因此左侧空格会被移除,右侧空格不写入属性。
- 如果变量已经存在,正常调用者通常不会调用
def_var,而是在 NF_INQ_VARID 成功后直接写数据或在初始时刻触发重复变量错误。
待确认
NF_REDEF 和最终 NF_ENDDEF 的返回码没有立即检查;在异常文件状态下错误会如何传播,需结合具体 NetCDF 库行为和调用者后续检查确认。
abort_physic 在本文件中未显式声明接口;编译链接依赖外部符号解析,具体来源需从全局构建系统确认。
相关页面