hrecast.F90
快速理解
它做什么: 水平重网格工具,把 GCM 输出按用户给定新经纬网格做面积权重映射。
基本过程: 读输入和新网格定义 → interp_horiz 计算格盒球面面积交叠 → 面积权重重分配 → 写 *_h.nc。
关键结果: 保持单位面积强度量总量一致的重网格文件(非点值双线性插值)。
路径
LMDZ.MARS\util\hrecast.F90
所属目录/模块
util
文件定位
hrecast.F90 是 LMD Mars GCM 输出的水平重网格工具。它读取 diagfi.nc、stats.nc、concat.nc 等 NetCDF 输出,按用户给定的新经纬度规则网格,把 3D (lon,lat,Time) 和 4D (lon,lat,alt,Time) 变量水平映射到新网格,输出文件名自动生成为 input_h.nc。
本工具不是点值双线性插值。核心例程 interp_horiz / iniinterp_h 计算旧网格格盒与新网格格盒的球面面积交叠,用 intersec/airen 面积权重把旧格点标量场重分配到新格点,源码注释说明目标是对单位面积强度量保持总量一致。
定义的符号
| 符号 | 类型 | 行号 | 作用 |
|---|---|---|---|
hrecast |
program | 3 | 主程序:读输入 NetCDF、变量列表和输出网格,创建 *_h.nc 并写入重网格结果。 |
interp_horiz |
subroutine | 1089 | 对一个 2D 或多层水平场执行面积交叠加权映射,并做极点平均。 |
iniinterp_h |
subroutine | 1291 | 预计算新旧网格格盒交集、交集面积 intersec 和新格盒面积 airen。 |
依赖的模块
| include | 用途 |
|---|---|
include "netcdf.inc" |
使用旧式 NetCDF Fortran NF_* 接口读写文件、维度、变量和属性。 |
调用的关键例程
| 被调用例程 | 所在位置 | 作用 |
|---|---|---|
NF_OPEN / NF_CREATE / NF_CLOSE |
NetCDF 库 | 打开输入文件、创建输出 *_h.nc、关闭输出。 |
NF_INQ_NVARS / NF_INQ_VARNAME / NF_INQ_VARNDIMS |
NetCDF 库 | 列出候选 3D/4D 变量并按用户选择确定处理列表。 |
NF_INQ_DIMID / NF_INQ_VARID / NF_GET_VAR_REAL |
NetCDF 库 | 读取坐标、sigma/hybrid 坐标、phisinit 和数据变量。 |
NF_DEF_DIM / NF_DEF_VAR / NF_PUT_VAR_REAL / NF_PUT_VARA_REAL |
NetCDF 库 | 定义输出维度/变量并写入坐标和重网格数据。 |
interp_horiz |
本文件 | 对 phisinit、3D 变量的每个 time、4D 变量的每个 time 和所有 altitude 执行水平映射。 |
iniinterp_h |
本文件 | 首次调用或网格尺寸变化时预计算面积交集表。 |
输入
| 输入 | 来源 | 类型/维度 | 单位 | 含义 |
|---|---|---|---|---|
| 输入文件名 | stdin / hrecast.def |
NetCDF 文件 | - | diagfi.nc、stats.nc、concat.nc 等。 |
| 变量列表 | stdin / hrecast.def |
all 或逐行变量名,空行结束 |
- | 要重网格的 3D/4D 变量;all 分支只自动选 4D 变量。 |
| 输出经度数和值 | stdin / hrecast.def |
lonlength + 逐行经度 |
degrees_east | 新网格经度,要求递增,约在 [-180,180]。 |
| 输出纬度数和值 | stdin / hrecast.def |
latlength + 逐行纬度 |
degrees_north | 新网格纬度,要求从北到南递减。 |
输入 longitude / latitude |
NetCDF | 1D | degrees | 输入网格必须包含 -180/180 经度端点和 90/-90 极点纬度。 |
输入 altitude / Time |
NetCDF | 1D | 随文件 | 垂直和时间坐标;原样复制到输出。 |
sigma 或 aps/bps |
NetCDF | 1D | - / Pa | 垂直坐标辅助量;输入缺 sigma 时要求有 hybrid 坐标。 |
phisinit |
NetCDF | 2D(lon,lat) | m2 s-2 | 可选地表位势;存在时一并水平重网格。 |
示例 hrecast.def 的顺序是:输入文件、变量名列表、输出经度数量和值、输出纬度数量和值。
输出
| 输出 | 去向 | 类型/维度 | 单位 | 含义 |
|---|---|---|---|---|
input_h.nc |
磁盘 NetCDF | 文件 | - | 以输入文件名去掉 .nc 后加 _h.nc 生成。 |
longitude / latitude |
输出 NetCDF | 1D | degrees | 用户指定的新水平网格。 |
altitude / Time |
输出 NetCDF | 1D | 随输入 | 从输入复制。 |
sigma 或 aps/bps |
输出 NetCDF | 1D | 随输入 | 从输入复制。 |
phisinit |
输出 NetCDF | 2D(lon,lat) | m2 s-2 | 若输入存在,则用面积权重重网格后输出。 |
| 用户选择变量 | 输出 NetCDF | 3D 或 4D | 随变量 | 水平重网格后的变量。 |
共享状态与副作用
- 固定输出命名:
outfile=infile(1:len_trim(infile)-3)//"_h.nc";NF_CLOBBER会覆盖同名输出。 - stdin 交互:变量列表和输出网格完全由 stdin 提供,
hrecast.def必须严格按源码读取顺序。 - 整变量读入内存:3D 和 4D 变量分别整块读入,长时间序列或大网格可能占用大量内存。
- 缓存插值权重:
interp_horiz用SAVE保存ktotal/iik/jjk/ik/jk/intersec/airen,网格尺寸未变时复用权重。 - 硬停止/exit:NetCDF 错误多为
stop;插值尺寸超过静态上限时调用exit(1)。
核心逻辑
- 读输入和变量列表:打开输入文件,列出 3D/4D 变量。用户可指定变量或输入
all;all分支只收集 4D 变量。 - 读取输入坐标:读取
latitude、longitude、altitude、Time。输入纬度必须首尾接近 90 和 -90,经度必须首尾接近 -180 和 180。 - 读取垂直辅助量:优先读取
sigma;若无,则读取aps和bps。可选读取phisinit。 - 构造输入格盒边界:输入经度边界用相邻经度中点,最后一个边界为第一个边界加 2π;输入纬度边界用相邻纬度中点。
- 读输出网格并构造工作网格:
- 若输出经度首尾已相差约 360,则视为周期网格;否则追加一个
lon(1)+360工作点。 - 若输出纬度不含 90/-90,则在工作网格中补极点,并把近极边界放到接近极点的位置。
- 若输出经度首尾已相差约 360,则视为周期网格;否则追加一个
- 创建输出文件:定义 longitude、latitude、altitude、Time 维度和坐标变量;复制 altitude 属性、Time units、sigma 或 aps/bps、变量 long_name/title、units、missing_value。
- 水平映射:
- 对
phisinit调interp_horiz,得到工作网格结果,再按是否补极点裁剪回用户网格。 - 对 3D 变量逐 time 调
interp_horiz。 - 对 4D 变量逐 time 调
interp_horiz,一次传入全部 altitude 层作为lm。
- 对
- 面积交叠权重:
iniinterp_h为每个新格盒找所有相交旧格盒,计算交集面积(bb-aa)*(sin(dd)-sin(cc));interp_horiz累加old_value*intersec/new_area,并对新网格南北极点做面积加权平均。
伪代码
program hrecast:
read infile; open NetCDF
list candidate variables with ndims 3 or 4
read selected variables
read input lon/lat/alt/Time, sigma or aps/bps, optional phisinit
require input lon starts -180 and ends 180; lat starts 90 and ends -90
build input lon/lat cell boundaries
read output lon/lat coordinate lists
build periodic/pole-complete work grid and boundaries
create infile_h.nc and define coords/variables
write coordinates and vertical metadata
if phisinit exists:
interp_horiz(phisinit) -> output phisinit
for each selected 3D variable:
for each time: interp_horiz(surface field)
write output variable
for each selected 4D variable:
for each time: interp_horiz(all altitude layers)
write output variable
subroutine interp_horiz:
if first call or dimensions changed: iniinterp_h(...)
zero output
for each old/new grid-box intersection:
new_cell += old_cell * intersection_area / new_cell_area
area-average north and south pole rows
参与的主题流程
| 主题 | 参与方式 |
|---|---|
| util 后处理链 | 在 concatnc 或 zrecast 后,把输出投到用户需要的规则经纬网格。 |
| 地图/比较前处理 | 适合把 GCM lon-lat 输出重分配到较粗或自定义经纬度网格,并保留 NetCDF 坐标和变量属性。 |
写法特点
- 面积交叠加权:
intersec/airen权重来自格盒边界交集,不是点值插值。 - 输入网格假设强:必须是包含 -180/180 和 90/-90 的 LMDZ GCM 标量网格。
- 输出网格可不含端点:程序会为内部计算补周期经度或极点,最后裁剪回用户指定网格。
- 静态数组上限:
interp_horiz/iniinterp_h对新旧网格维度和交集数有固定上限。 - 属性复制有限:只显式复制或转写
long_name/title、units、missing_value;其他属性会提示未转移。
复现要点
hrecast.def中变量列表后必须用空行结束;若输入all,源码只会处理 4D 变量,不会自动包含 3D surface+time 变量。- 输出经度必须递增;输出纬度必须从北到南递减。
- 输入文件需包含
sigma或同时包含aps/bps;否则创建输出垂直坐标会停止。 - 若目标变量没有
missing_value,输出会写默认-9.99e+33,但插值本身不显式跳过缺测角点。 - 大文件一次读完整变量,内存需求随 lonlatalt*time 增长。
待确认
all分支只收集 4D 变量,是否应包含 3D 变量需与使用者意图确认。miss_val只写属性,不参与interp_horiz缺测跳过;含缺测输入时面积平均可能把缺测值当普通数值传播。- 代码中多个错误信息把 longitude 写成 latitude,属诊断文本问题,不影响计算。
NF_DEF_DIMTime 失败时错误信息写成 latitude dimension,属诊断文本问题。
复现风险
- 输出
_h.nc会被NF_CLOBBER覆盖。 - 超过
imnmx2=360/jmnmx2=190、imomx=361/jmomx=180或kmax=360*179+200000会exit(1)。 - 输入经纬度若不是源码假设的 GCM 端点网格会直接停止。
- 对非单位面积强度量使用面积交叠平均时,物理意义需要按变量性质确认。
相关页面
- util/index.md - util 后处理工具总览。
- concatnc.md - 常见上游时间拼接工具。
- zrecast.md - 常见上游垂直坐标转换工具。
- extract.md - 下游点值/廓线抽取工具。