concatnc.F90
路径
LMDZ.MARS\util\concatnc.F90
所属目录/模块
util
文件定位
concatnc.F90 是 LMD Mars GCM 输出的 NetCDF 时间拼接工具。它读取多个 diagfi.nc、concat.nc、stats.nc 类文件,把用户选择的时间相关变量沿输出 Time unlimited 维追加到固定输出文件 concat.nc,并复制首个输入文件中的经纬度、高度、垂直坐标、网格面积和地表位势等辅助变量。
本文件是独立命令行 program concatnc,不是 GCM 运行时模块。程序通过 stdin 交互式读取输入文件列表、起始 sol 策略、输出时间轴类型和变量列表;典型用法是 concatnc.e < concatnc.def。它通常位于 util 后处理链第一步,后续结果可交给 zrecast、localtime.F90、lslin.F90 或 extract.F90。
定义的符号
| 符号 |
类型 |
行号 |
作用 |
concatnc |
program |
1 |
主程序:读取输入文件和变量选择,创建 concat.nc,沿时间轴追加 1D/3D/4D 变量。 |
initiate |
subroutine |
729 |
创建输出 NetCDF,定义 latitude/longitude/altitude/Time/GCM_layers 维度并写坐标变量。 |
init2 |
subroutine |
885 |
从首个输入文件复制 aps/bps、ap/bp、sigma、aire/area、phisinit/phisfi 等静态辅助变量。 |
def_var |
subroutine |
1234 |
在打开的 NetCDF 中定义 float 变量并写 long_name、units 属性。 |
change_time_axis |
subroutine |
1283 |
将输出 Time 从 sol 转为 Ls;adls 模式下新增 Ls 一维变量。 |
sol2ls |
subroutine |
1385 |
用火星轨道近似和 Newton 迭代把 sol 转成太阳经度 Ls。 |
missing_value |
subroutine |
1478 |
将输入变量的 valid_range 和 missing_value 属性复制到输出变量。 |
依赖的模块
| use/include |
用途 |
include "netcdf.inc" |
主程序和所有内部例程使用旧式 NetCDF Fortran NF_* 接口。 |
无 LMDZ 物理模块依赖。程序只操作 NetCDF 文件和 stdin/stdout。
调用的关键例程
| 被调用例程 |
所在位置 |
作用 |
NF_OPEN / NF_CREATE / NF_CLOSE |
NetCDF 库 |
打开输入文件,创建 concat.nc,关闭文件。 |
NF_INQ_DIMID / NF_INQ_VARID / NF_INQ_DIMLEN |
NetCDF 库 |
查找 latitude/longitude/altitude/Time/controle 等维度和变量。 |
NF_GET_VAR_REAL / NF_PUT_VARA_REAL |
NetCDF 库 |
读取整块输入变量,并按时间片写入输出变量。 |
initiate |
本文件 |
首个输入文件确定输出坐标和维度后创建输出文件。 |
init2 |
本文件 |
首个输入文件复制垂直坐标、面积和地形辅助量。 |
def_var |
本文件 |
定义输出变量及属性。 |
missing_value |
本文件 |
复制缺测和值域属性。 |
change_time_axis / sol2ls |
本文件 |
在 ls 或 adls 输出模式下转换或新增 Ls 轴。 |
输入
| 输入 |
来源 |
类型/维度 |
单位 |
含义 |
| 输入文件列表 |
stdin |
文件名列表,空行结束 |
- |
要拼接的 diagfi/concat/stats 类 NetCDF 文件。 |
| 起始时间 |
stdin |
数值或非数值输入 |
sol |
数值输入时用于设置输出起始 sol;非数值输入时保留第一文件的季节/起点逻辑。源码变量名 firstsol 的注释与提示文字有歧义,见待确认。 |
axis |
stdin |
sol / ls / adls |
- |
输出时间轴类型:sol、Ls,或保留 sol 并额外写 Ls。 |
| 变量列表 |
stdin |
all 或逐行变量名,空行结束 |
- |
要拼接的时间相关变量;坐标/静态变量由 notconcat 排除。 |
latitude/lat |
输入 NetCDF |
1D |
degrees_north |
纬度坐标;各输入文件长度必须一致。 |
longitude/lon |
输入 NetCDF |
1D |
degrees_east |
经度坐标;各输入文件长度必须一致。 |
altitude |
输入 NetCDF |
1D |
随文件 |
垂直坐标;各输入文件长度必须一致,属性复制到输出。 |
Time/time_counter |
输入 NetCDF |
1D |
sol 或文件约定 |
拼接维;输出 Time 为 unlimited。 |
controle |
输入 NetCDF |
index 或 controle_axe 维 |
混合 |
可选;存在时用 ctl(4) 和 ctl(27) 计算输出 sol,并在输出中写入重置后的 controle。 |
aps/bps、ap/bp、sigma、aire/area、phisinit/phisfi |
输入 NetCDF |
静态坐标/辅助量 |
随变量 |
首个输入文件复制到输出。 |
输出
| 输出 |
去向 |
类型/维度 |
单位 |
含义 |
concat.nc |
磁盘 |
NetCDF |
- |
固定输出文件名,NF_CLOBBER 覆盖已有文件。 |
Time |
concat.nc |
unlimited 1D |
days 或 degrees |
追加后的时间轴;ls 模式最终写成 Ls,sol/adls 保持 sol。 |
Ls |
concat.nc |
unlimited 1D |
degrees |
仅 adls 模式新增;源码通过 change_time_axis 写入。 |
| 用户选择变量 |
concat.nc |
1D(Time)、3D(lon,lat,Time) 或 4D(lon,lat,alt,Time) |
随变量 |
从每个输入文件整块读取并按 reptime 追加。 |
| 坐标和静态辅助变量 |
concat.nc |
1D/2D |
随变量 |
latitude、longitude、altitude、controle、aps/bps、ap/bp 或 sigma、aire、phisinit 等。 |
共享状态与副作用
- 固定输出文件名:
filename="concat.nc",initiate 用 NF_CLOBBER 创建,当前目录中同名文件会被覆盖。
- stdin 交互:输入文件列表、时间策略、
axis 和变量列表都通过 read(*,...) 获取;.def 文件必须严格匹配读取顺序。
- stdout 进度与错误提示:程序打印文件打开、时间轴、变量名、Sol 和 NetCDF 错误。
- 硬停止:缺少输入文件、必要坐标、Time 维、请求变量或 NetCDF 写入失败时直接
stop。
- 输出时间状态:
reptime 记录已写入时间长度;previous_last_output_time 用来处理跨年或文件时间倒退。
- 无线程安全要求:本程序为单进程命令行工具,内部没有 SAVE 缓存或并行状态。
核心逻辑
- 读取输入参数:stdin 读入多个输入文件名;读取起始 sol 策略;打开第一文件,读取变量总数;读取
axis,仅接受 sol、ls、adls。
- 筛选候选变量:
notconcat(1:24) 排除坐标、控制和静态辅助量,包括 Time、controle、latitude/longitude/altitude、aps/bps、ap/bp、aire/area、phisinit/phisfi 和 XIOS 时间/边界变量。用户可输入 all 或逐项变量名。
- 逐输入文件循环:
- 打开文件,读取
latitude/lat、longitude/lon、altitude、可选 GCM_layers。
- 查找
index 或 controle_axe,可用时读取 controle 并取 ctlsol=ctl(4)。
- 查找
Time 或 time_counter 并读取时间数组。
- 首个文件初始化输出:
- 保存经纬高和
controle 长度,用于后续文件兼容性检查。
- 计算
starttimeoffset 和 previous_last_output_time;有 controle 时还把输出 ctl(4)、ctl(27) 置零。
- 调
initiate 定义输出维度和坐标;调 init2 复制垂直坐标与静态辅助量。
- 后续文件兼容性检查:纬度、经度、高度和
controle 长度必须与首文件一致,否则停止。
- 追加 Time:对当前文件每个时间样本计算
output_time。有 controle 时使用 time(rep)+ctlsol-starttimeoffset,若小于上一输出时间则加 year_day=669 直到连续;无 controle 时按当前文件时间间隔顺推。
- 追加变量:对每个用户变量查找变量 ID,只接受 1D、3D、4D;按维度构造
dim/corner/edges,首文件定义输出变量并复制 long_name/title 与 units,随后用 NF_PUT_VARA_REAL 追加数据块。
- 复制缺测属性:若输入变量有
missing_value,调用 missing_value 复制 valid_range 和 missing_value 属性。
- 后处理时间轴:所有文件处理后,如果
axis=="ls" 或 axis=="adls",调用 change_time_axis。sol2ls 对每个 sol 做 Ls 转换,并修正相邻 Ls 跨 0/360 度导致的大跳变。
伪代码
program concatnc:
read input file list until blank
read optional startsol; read axis in {sol, ls, adls}
open first file; list variables except notconcat
read variable selection: all or names
filename = "concat.nc"; reptime = 0
for each input file:
open file if not first
read lat/lon/alt, optional GCM_layers
read optional controle from index/controle_axe
read Time or time_counter
if first file:
store reference dimension lengths
compute starttimeoffset and previous_last_output_time
initiate(concat.nc, coordinates, controle, axis)
init2(copy vertical coordinate, area, phisinit)
else:
require lat/lon/alt/controle lengths match first file
for rep in current file Time:
output_time = controle-aware sol, else sequential time
while output_time < previous_last_output_time:
output_time += 669
append output_time at Time(reptime+rep)
for each selected variable:
require ndim in {1,3,4}
build output dimensions and write corner/edges
if first file: define output variable and attributes
read full input variable into var3d
append var3d block to output
copy missing_value/valid_range if present
reptime += timelen
close input file
if axis is ls or adls:
change_time_axis(output)
close output file
参与的主题流程
| 主题 |
参与方式 |
| util 后处理链 |
常作为第一步把多段 GCM 输出合成单个 concat.nc,再交给 zrecast、localtime.F90、lslin.F90 或 extract.F90。 |
| GCM 输出整理 |
保留经纬高、垂直坐标、面积、地形和缺测属性,保证后续 NetCDF 工具仍能识别坐标契约。 |
| 时间轴标准化 |
支持 sol、Ls 和 sol+Ls (adls) 三种输出策略,并处理跨火星年拼接时的时间倒退。 |
写法特点
- 旧式 NetCDF API:全文件使用
include "netcdf.inc" 和 NF_* 接口。
- 固定静态变量排除表:
notconcat(1:24) 既跳过经典 diagfi 坐标,也跳过 XIOS 的 lat/lon/time_counter/time_instant_bounds/area/phisfi。
- 维度只支持 1D/3D/4D:非这三类变量会被跳过,不能拼接 2D 静态变量;静态量由
init2 单独复制。
GCM_layers 与 altitude 分离:若输入来自 zrecast,GCM_layers 可不同于 altlen,用于复制原始 hybrid/sigma 层。
adls 模式意图:保留 Time 为 sol,并额外写 Ls 变量;待确认处见下。
复现要点
.def 输入顺序必须是:文件名列表(空行结束)、起始 sol 策略、axis、变量列表(all 或逐行变量名,空行结束)。
- 所有输入文件的 latitude、longitude、altitude 长度必须一致;
controle 有无和长度也必须一致。
- 若输入含
controle,输出 controle(4) 和 controle(27) 会被置零,输出 Time 由 time + ctl(4) - starttimeoffset 计算。
- 若输入没有
controle,程序使用第一个文件的时间间隔顺推,依赖 time(2)-time(1);单时间样本文件可能触碰数组边界,见待确认。
- 输出文件固定为当前目录
concat.nc,批处理前应移动或删除旧文件以避免覆盖。
ls/adls 模式下 Ls 换算使用 year_day=669、peri_day=485.0、timeperi=1.9082314、e_elips=0.093358。
待确认
- 源码第 167-172 行的
firstsol 逻辑与注释/提示文字相反:ierr.eq.0 表示读到数值,但打印“使用第一输入文件起始日”;实际公式按数值 startsol 参与 starttimeoffset,页面按公式描述而未判断原意。
change_time_axis 在 adls 分支调用 def_var(nout,...) 和 timedimout,但子程序参数只有 nid,ierr,axis;这些名称来自主程序宿主作用域的内部过程 host association。此写法可读性差,移植时需确认编译器接受。
init2 中 phisinit 查找失败后尝试 phisfi,若两者都失败,源码仍在失败分支后设置 phis=.true.;这可能导致未初始化 phisinit 被写出。需用实际文件和编译器行为确认。
- 无
controle 分支使用 time(2)-time(1) 推算首个文件前一时间;当 timelen=1 时是否越界取决于运行时检查设置。
复现风险
NF_CLOBBER 会覆盖已有 concat.nc。
stop 式错误处理会让批处理链在缺坐标、缺变量或维度不匹配时直接终止。
- 请求变量必须存在于每个输入文件;任一文件缺变量会停止,不能自动跳过单个文件。
all 模式依赖第一输入文件变量清单,后续文件变量集合不同会失败。
ls 模式把 Time 内容改为 Ls,部分工具若期待 sol 轴应使用 adls 或保持 sol。
相关页面