streamfunction.F90
快速理解
它做什么: 离线诊断程序,计算纬向平均的经向质量流函数、角动量和纬向平均风/温度/密度。
基本过程: 读输入(含 u/v/temp/rho/ps)→ 全时段平均 → 纬向平均/垂直积分 → 写 *_stream.nc。
关键结果: 单经度、单时间维度的流函数诊断文件。
路径
LMDZ.MARS\util\streamfunction.F90
所属目录/模块
util
文件定位
streamfunction.F90 是一个离线 NetCDF 诊断程序,用于从 diagfi.nc、concat.nc 或 stats.nc 类文件计算纬向平均的经向质量流函数、总角动量、纬向平均风、温度、密度、地表压力和初始地形势。
它不是逐时刻输出工具。源码先对输入的 u/v/temp/rho/ps 做全时段平均,再做纬向平均或垂直积分,输出文件固定为单经度、单时间维度的 *_stream.nc。
定义的符号
| 符号 | 类型 | 行号 | 作用 |
|---|---|---|---|
streamfunction |
program | 1 | 主程序:读取输入 NetCDF、计算流函数/角动量/纬向平均诊断并写出 *_stream.nc。 |
initiate |
internal subroutine | 860 | 创建输出 NetCDF 文件,定义 latitude、单点 longitude、altitude 和单点 Time。 |
init2 |
internal subroutine | 978 | 复制输入文件中的 aps/bps 到输出文件。 |
def_var |
internal subroutine | 1105 | 定义输出变量并写入 title、units 属性。 |
依赖
| 依赖 | 用途 |
|---|---|
include "netcdf.inc" |
使用旧式 NetCDF Fortran NF_* 接口。 |
预处理宏 MARS / JUPITER |
可覆盖 g0/a0/daysec/Rgas 行星常数;无宏时源码默认值已为 Mars。 |
预处理宏 NC_DOUBLE |
输出定义和坐标写入可切换为 NF_DOUBLE,否则为 NF_FLOAT。 |
输入
| 输入 | 来源 | 类型/维度 | 单位 | 含义 |
|---|---|---|---|---|
| 输入文件名 | stdin | NetCDF 文件名 | - | 程序提示为 diagfi.nc、concatnc.nc 或 stats.nc。 |
latitude / longitude / altitude / Time |
输入 NetCDF | 1D | 输入属性或约定 | 空间和时间坐标;四者均为必需。 |
aps / bps |
输入 NetCDF | altitude 长度 |
Pa / sigma | hybrid 中层坐标;源码要求二者都存在。 |
ps |
输入 NetCDF | (lon,lat,Time) |
Pa | 地表压力,用于时间平均、hybrid 压力和密度回退。 |
u / v |
输入 NetCDF | (lon,lat,alt,Time) |
m/s | 纬向风和经向风。 |
aire |
输入或回退文件 | (lon,lat) |
m2 | 网格框面积;输入缺失时依次尝试 diagfi.nc、diagfi1.nc。 |
phisinit |
输入或回退文件 | (lon,lat) |
m2/s2 | 地形势;输入缺失时依次尝试 diagfi.nc、diagfi1.nc。 |
cv |
输入或用户提供文件 | (lon,lat) |
- | 自然风到协变/逆变经向风的转换因子;输入缺失时要求用户输入另一文件名,再回退 start.nc。 |
temp |
输入 NetCDF | (lon,lat,alt,Time) |
K | 温度。 |
rho |
输入 NetCDF,可选 | (lon,lat,alt,Time) |
kg/m3 | 密度;缺失时用 (aps+bps*ps)/(Rgas*temp) 估算。 |
输出
| 输出 | 去向 | 类型/维度 | 单位 | 含义 |
|---|---|---|---|---|
*_stream.nc |
磁盘 NetCDF | 文件 | - | 输入文件名去掉 .nc 后追加 _stream.nc。 |
latitude / altitude |
输出 NetCDF | 1D | degrees_north / km | 原纬度和高度坐标。 |
longitude |
输出 NetCDF | 长度 1 | degrees_east | 固定写 0,表示纬向平均结果。 |
Time |
输出 NetCDF | 长度 1 | 属性为 calendar-like 字符串 | 固定写 0,表示全时段平均结果。 |
aps / bps |
输出 NetCDF | 1D | - | 从输入复制。 |
psi |
输出 NetCDF | (1,lat,alt,1) |
空字符串 | 经向质量流函数。 |
momave |
输出 NetCDF | (1,lat,alt,1) |
空字符串 | 纬向平均总角动量。 |
u / v |
输出 NetCDF | (1,lat,alt,1) |
m/s | 全时段、纬向平均的纬向风和经向风。 |
rho |
输出 NetCDF | (1,lat,alt,1) |
空字符串 | 全时段、纬向平均密度。 |
temp |
输出 NetCDF | (1,lat,alt,1) |
K | 全时段、纬向平均温度。 |
ps |
输出 NetCDF | (1,lat,1) |
Pa | 全时段、纬向平均地表压力。 |
phisinit |
输出 NetCDF | (1,lat) |
空字符串 | 纬向平均地形势。 |
副作用和错误处理
- 使用
NF_CLOBBER创建输出,同名*_stream.nc会被覆盖。 - 程序整块读取
u/v/temp/rho/ps,内存随lon*lat*alt*time增长。 - 必需变量或维度缺失时直接
stop。 aire和phisinit可从同目录diagfi.nc或diagfi1.nc回退读取;cv缺失时会额外交互读取一个文件名,再回退start.nc。- 源码行 852 使用
ierr=nf_close(nid)关闭输入,但主路径打开的是infid;nid未在主路径赋值。待确认:运行时是否因此出现 NetCDF close 错误或仅被忽略。
核心逻辑
- 读坐标和必需字段:读取
latitude/longitude/Time/altitude、aps/bps、ps、u/v、aire、phisinit、cv、temp和可选rho。 - 密度回退:若无
rho,用 hybrid 压力和理想气体近似:
rho(lon,lat,alt,time) = (aps(alt) + bps(alt) * ps(lon,lat,time)) / (Rgas * temp(lon,lat,alt,time))
- 时间平均:对每个
(lon,lat,alt)计算u/v/temp/rho的时间平均,对每个(lon,lat)计算ps的时间平均。 - 经向风转换:对
ilat=1..latlength-1,使用相邻纬度平均的经向风除以cv:
vcont(lon,lat,alt) = 0.5 * (vcum(lon,lat,alt) + vcum(lon,lat+1,alt)) / cv(lon,lat)
vcont(lon,latlength,alt) = 0
- hybrid 压力和层质量:
Plev = aps + bps * pscum
mass = aire * Plev / g0
dmass(alt) = mass(alt) - mass(alt+1)
dmass(top) = 0
- 流函数积分:从顶层向下积分,每层先继承上一层
psi,再减去所有经度上的vcont*(dmass(lat)+dmass(lat+1))。源码还计算vcontcum,但后续未写出。 - 角动量:先对每个经度计算:
mom = a0*cos(lat) * (omega*a0*cos(lat) + u_time_mean)
随后又用纬向平均风 uzm 重算 momave,因此最终输出的 momave 对应 zonal mean wind 路径。 8. 纬向平均诊断:对 u/v/temp/rho/ps/phisinit 沿经度平均。 9. 写输出:创建单经度、单时间输出文件,写 psi/momave/u/v/rho/temp/ps/phisinit。
伪代码
read infile from stdin
open infile
read lon, lat, alt, Time, aps, bps, ps, u, v
read aire and phisinit, falling back to diagfi.nc or diagfi1.nc
read cv, asking for a start-like file if missing
read temp
if rho exists:
read rho
else:
rho = hybrid_pressure / (Rgas * temp)
average u, v, temp, rho, ps over all input times
vcont = adjacent-lat average of v / cv
Plev = aps + bps * mean_ps
mass = aire * Plev / g0
dmass = vertical difference of mass
integrate psi downward from top using vcont and neighboring-lat dmass
compute zonal means of u, v, temp, rho, ps, phisinit
momave = a0*cos(lat) * (omega*a0*cos(lat) + zonal_mean_u)
create *_stream.nc with lon=0 and Time=0
write psi, momave, u, v, rho, temp, ps, phisinit
参与的主题流程
| 主题 | 参与方式 |
|---|---|
| util 后处理链 | 与 concatnc 产出的长时间文件配合,得到时间平均的纬向流函数和角动量诊断。 |
| 环流诊断 | 输出 psi、纬向平均风和角动量,用于纬度-高度剖面分析。 |
| 坐标/网格辅助 | 依赖 aire 和 cv,这些字段常来自 diagfi.nc 或 start 类文件。 |
复现要点
- 输入必须包含
u/v/temp/ps/aps/bps,否则程序停止;rho可以缺失但会用常数Rgas估算。 aire、phisinit和cv对结果不是可选物理量;若主文件没有,需要同目录有diagfi.nc、diagfi1.nc或用户提供的 start 类文件。- 输出纬度维和高度维保留输入坐标,但经度和时间均压缩为单点
0。 psi的单位属性为空;复现时应从mass/g0与vcont的源码公式推导实际量纲。dmass(top)=0、vcont(latlength)=0和psi(latlength,:)=0是源码边界条件。
待确认
cv的精确定义和单位需结合生成该字段的 start/archive 代码确认。psi是否缺少对经度宽度、纬向平均或传统流函数归一化因子的显式处理,需要和目标诊断定义比对。momave输出是否应乘层质量或层厚;源码当前输出的是每单位质量的绝对角动量形式。- 结尾
nf_close(nid)是否是infid拼写错误。 - 输出变量定义为 4D,但写入数组为 2D 或 1D 纬向平均数组;需用实际 NetCDF 库接口确认写入布局是否总是按预期。
复现风险
- 同名
_stream.nc会被覆盖。 - 大文件全量读入内存。
- 缺少
cv时会阻塞等待交互输入。 - 主路径没有复制输入文件的时间范围信息,输出
Time=0只表示平均诊断。 - 行星常数由编译宏控制;跨 Mars/Jupiter 编译时结果会不同。
相关页面
- util/index.md - util 后处理工具总览。
- concatnc.md - 常见上游时间拼接工具。
- localtime.md - 另一个时间相关后处理工具。
- lslin.md - Ls 线性化工具。