solzenangle.F90
路径
LMDZ.MARS\util\solzenangle.F90
所属目录/模块
util
文件定位
solzenangle.F90 是一个离线 NetCDF 后处理程序,用于把 diagfi.nc、concat.nc 或 stats.nc 类输出中的 3D/4D 变量插值到指定太阳天顶角对应的本地真太阳时。它常用于抽取晨侧或昏侧的掩星/晨昏线条件,例如 sza=90 度时的地表终止线。
程序不改变经纬度网格或垂直坐标。核心流程是先按日期、经度、纬度和目标太阳天顶角反解本地时 LTsolzenangle(lon,lat,Time),再沿输入文件的时间维对用户选择的变量做一维线性插值,输出 *_MO.nc 或 *_EV.nc。
定义的符号
| 符号 | 类型 | 行号 | 作用 |
|---|---|---|---|
solzenangle |
program | 1 | 主程序:读取输入文件、变量列表、晨/昏侧和目标 SZA,创建输出 NetCDF 并插值变量。 |
initiate |
internal subroutine | 861 | 创建输出 NetCDF 文件,定义坐标、Time、GCM_layers 和可选 controle。 |
init2 |
internal subroutine | 1076 | 从输入复制可选 aps/bps hybrid 坐标和 phisinit。 |
def_var |
internal subroutine | 1252 | 定义输出变量并写入 long_name、units 属性。 |
missing_value |
internal subroutine | 1302 | 把 valid_range 和 missing_value 属性写到输出变量。 |
interpolf |
internal subroutine | 1381 | 一维线性插值;目标点不在坐标范围内或邻点缺测时返回 missing。 |
LTsolzenangle |
internal subroutine | 1428 | 由纬度、Ls、晨/昏侧和目标 SZA 反解本地真太阳时。 |
sol2ls |
internal subroutine | 1483 | 把 sol 日期转换为太阳经度 Ls,单位为度。 |
依赖
| 依赖 | 用途 |
|---|---|
include "netcdf.inc" |
使用旧式 NetCDF Fortran NF_* 接口读写输入和输出。 |
调用的关键例程
| 被调用例程 | 所在位置 | 作用 |
|---|---|---|
NF_OPEN / NF_CLOSE |
NetCDF 库 | 打开输入文件,关闭输入和输出文件。 |
NF_INQ_NVARS / NF_INQ_VARNAME / NF_INQ_VARNDIMS |
NetCDF 库 | 枚举变量、排除坐标/静态字段、确认 3D/4D 变量。 |
NF_INQ_DIMID / NF_INQ_VARID / NF_INQ_DIMLEN |
NetCDF 库 | 读取 latitude/longitude/altitude/Time/index/GCM_layers 维度和变量。 |
NF_GET_VAR_REAL / NF_PUT_VARA_REAL |
NetCDF 库 | 读取坐标、控制数组、输入变量,并写出插值后的变量。 |
NF_GET_ATT_TEXT / NF_GET_ATT_REAL / NF_PUT_ATT_* |
NetCDF 库 | 读取和写入 long_name/title、units、missing_value、valid_range 等属性。 |
LTsolzenangle |
本文件 | 反解目标 SZA 对应的本地真太阳时。 |
sol2ls |
本文件 | 非 stats 输入时把 sol 日期换算到 Ls,供太阳赤纬计算使用。 |
interpolf |
本文件 | 沿每个格点的时间序列做线性插值。 |
输入
| 输入 | 来源 | 类型/维度 | 单位 | 含义 |
|---|---|---|---|---|
| 输入文件名 | stdin / solzenangle.def |
NetCDF 文件名 | - | diagfi.nc、concat.nc、stats.nc 等。 |
| 变量列表 | stdin / solzenangle.def |
all 或逐行变量名,空行结束 |
- | 要插值到目标 SZA 本地时的变量;源码只处理 3D 或 4D 变量。 |
planetside |
stdin / solzenangle.def |
morning 或 evening |
- | 选择目标 SZA 位于当地正午之前还是之后。 |
sza |
stdin / solzenangle.def |
real scalar | degree | 目标太阳天顶角,源码要求 0 <= sza < 180。 |
| 参考时间 | stdin / solzenangle.def |
n、sol 值或 stats 平均 Ls |
sol 或 degree | 非 stats 文件可保留/覆盖起始 sol;stats 文件读取平均 Ls。 |
latitude / longitude / altitude |
输入 NetCDF | 1D | degrees / 输入属性 | 空间坐标;altitude 属性会复制到输出。 |
Time |
输入 NetCDF | 1D | sol 或 stats 小时 | 输入时间轴;若属性为 Solar longitude,程序停止。 |
controle |
输入 NetCDF | 1D,可选 | - | 用于推导 startsol,存在时也复制到输出并可能更新 ctl(4)。 |
GCM_layers |
输入 NetCDF | 维度,可选 | - | 供 aps/bps 长度使用;不存在时取 altlen。 |
aps/bps / phisinit |
输入 NetCDF | 可选 | - | init2 尝试复制到输出。 |
solzenangle.def 示例依次给出 diagfi.nc、tsurf/ps/temp、空行、morning、90 和 0。其中注释说明 90 度代表地表终止线,>90 度可代表高空终止线条件。
输出
| 输出 | 去向 | 类型/维度 | 单位 | 含义 |
|---|---|---|---|---|
*_MO.nc |
磁盘 NetCDF | 文件 | - | morning 分支输出,输入文件去掉 .nc 后追加 _MO.nc。 |
*_EV.nc |
磁盘 NetCDF | 文件 | - | evening 分支输出,输入文件去掉 .nc 后追加 _EV.nc。 |
latitude / longitude / altitude |
输出 NetCDF | 1D | 输入或固定属性 | 原坐标复制。 |
Time |
输出 NetCDF | unlimited | 源码属性写成 calendar-like 字符串 | 非 stats 分支写整数 sol;stats 分支写 intsol*24。 |
GCM_layers / aps / bps / phisinit |
输出 NetCDF | 可选 | - | 从输入复制的辅助坐标和地形字段。 |
| 用户选择变量 | 输出 NetCDF | 3D (lon,lat,Time) 或 4D (lon,lat,alt,Time) |
输入 units |
插值到目标 SZA 对应本地时后的变量。 |
LTsolzenangle |
输出 NetCDF | (lon,lat,Time) |
hours | 每个经纬度、sol 上目标 SZA 对应的本地真太阳时;无解时为 1E+20。 |
副作用
- 使用
NF_CLOBBER和NF_64BIT_OFFSET创建输出,同名_MO.nc或_EV.nc会被覆盖。 - 标准输入顺序严格依赖
solzenangle.def;交互输入与重定向输入必须保持同一顺序。 - 所选变量整块读入内存,再整块写出;大文件会按
lon*lat*alt*time放大内存压力。 - 缺少必要维度/变量、时间轴为
Solar longitude、planetside或sza非法、NetCDF 读写失败时会stop。 - 若目标 SZA 在极昼/极夜条件下无对应本地时,
LTsolzenangle和相应插值输出会写 missing。
核心逻辑
- 变量筛选:程序枚举输入文件中的所有变量,排除
Time/controle/rlonu/latitude/longitude/altitude/rlatv/aps/bps/ap/bp/soildepth/cu/cv/aire/phisinit这 16 个字段;用户输入all时取其余变量,否则逐行读取变量名。 - 坐标和时间读取:要求存在
latitude、longitude、altitude、Time;controle和GCM_layers可选。Time的long_name或title若等于Solar longitude,程序停止,因为后续插值需要 sol 类时间轴。 - SZA 参数检查:
planetside只能是morning或evening;sza必须在[0,180)度。 - 确定季节日期:
- 有
controle时用int(int(ctl(4))+int(time(1)+ctl(27)))推导startsol。 - 无
controle时用int(time(1))。 - 若
timelen==12、time(1)==2、time(last)==24,识别为stats文件,把时间小时除以 24,nsol=1,并从 stdin 读取平均Ls。 - 其他文件按
nsol=int(time(last))-int(time(first))生成每个输出 sol。
- 有
- 反解目标本地时:对每个输出 sol、经度和纬度:
- 晨侧先用
tmpsol=intsol+(6-lon/15)/24+startsol估计用于计算Ls的日期。 - 昏侧用
tmpsol=intsol+(18-lon/15)/24+startsol。 - 非
stats分支调用sol2ls(tmpsol,tmpLs)。 - 调用
LTsolzenangle(lat,tmpLs,planetside,sza,miss_lt,tmpLT)得到本地真太阳时小时。
- 晨侧先用
- 创建输出和复制辅助字段:
initiate写基本维度与坐标;init2在可用时复制aps/bps/phisinit。 - 逐变量时间插值:
- 只处理
ndim>=3的变量,ndim==3按(lon,lat,time),ndim==4按(lon,lat,alt,time)。 - 每个经度的输入本地时轴为
lt_gcm=time+lon/360。 - 目标
LTsolzenangle小时被换成lt_outc=intsol+LT/24。 - 单 sol 输入会在尾部追加周期点;多 sol 输入若目标点越界则把
lt_out和lt_outc置 missing。 interpolf对每条时间序列线性插值。
- 只处理
- 写输出变量和属性:变量保留输入
long_name/title与units;输入没有missing_value属性时,源码把 missing 设为1E+20并写回输出。 - 写
LTsolzenangle和全局注释:输出目标 SZA 对应的本地时变量,并在全局comment中说明可由LTsolzenangle、经度和Time组合推回经度 0 度的 sol。
太阳天顶角反解公式
LTsolzenangle 使用固定火星倾角 obliquity=25.1919 度,先计算太阳赤纬:
declin = asin(sin(Ls) * sin(obliquity))
然后由源码注释中的太阳天顶角方程反解时角:
cos(sza) = sin(lat)*sin(declin)
+ cos(lat)*cos(declin)*cos(2*pi*(localtime/24 - 0.5))
程序实际计算:
tmpcos = cos(sza)/(cos(lat)*cos(declin)) - tan(lat)*tan(declin)
若 tmpcos 超出 [-1,1],视为极昼/极夜下无对应本地时,返回 missing。否则晨侧使用:
lt = 24 * (0.5 - acos(tmpcos)/(2*pi))
昏侧使用:
lt = 24 * (0.5 + acos(tmpcos)/(2*pi))
伪代码
read input file
list variables not in the 16-field skip list
read selected variables
read latitude, longitude, altitude, optional controle, and Time
reject Solar longitude time axis
read planetside and sza
derive startsol and detect stats case
for each output sol, longitude, latitude:
estimate tmpsol at LT=6 or LT=18 for season
if not stats: tmpLs = sol2ls(tmpsol)
lt_out = LTsolzenangle(lat, tmpLs, planetside, sza)
create *_MO.nc or *_EV.nc
copy coords, optional controle, aps/bps, phisinit
for each selected 3D/4D variable:
read full variable
for each longitude:
lt_gcm = time + lon/360
convert lt_out hours to sol decimal lt_outc
wrap one-sol inputs or mark out-of-range multi-sol targets missing
interpolate each lat or lat-alt series with interpolf
write variable and missing/valid_range attributes
write LTsolzenangle(lon,lat,Time)
write global comment and close files
参与的主题流程
| 主题 | 参与方式 |
|---|---|
| util 后处理链 | 常接在 concatnc、zrecast 或 localtime 类工具附近,用于把模型输出抽样到晨/昏侧指定 SZA。 |
| 观测/掩星比较链 | sza=90 可模拟晨昏线或太阳掩星几何条件,输出的 LTsolzenangle 可检查每个格点实际抽样本地时。 |
| 太阳几何 | 与 solarlong 的主模式轨道换算不同,本文件内置 sol2ls 参数并直接用 SZA 几何公式反解本地时。 |
复现要点
- 输入时间轴必须是 sol 类时间,不可先把
Time轴替换为Solar longitude。 solzenangle.def中变量列表后必须保留空行,随后才是morning/evening、sza和参考时间。- 晨侧/昏侧只影响目标 SZA 的反解分支和输出后缀;
morning输出_MO.nc,evening输出_EV.nc。 - 非
stats输入的输出时间数由int(time(last))-int(time(first))决定;时间覆盖不足时会影响输出 sol 数。 - 单 sol 输入会把首个时间点复制为周期尾点参与插值;多 sol 输入不会周期补齐,越界目标点会写 missing。
- 目标 SZA 在高纬季节可能无晨侧或昏侧解,
LTsolzenangle会保留 missing,相关变量也会写 missing。
待确认
startsol = int(int(ctl(4))+int(time(1)+ctl(27)))中ctl(4)与ctl(27)的语义需结合具体输出文件控制表确认。stats分支把输出Time写为intsol*24,而Time属性仍使用 calendar-like 字符串;单位语义需按下游工具实际读取方式确认。all分支用Nnotprocessed+1:nbvarfile选择变量,隐含排除字段在变量表前部连续的假设;不同 NetCDF 变量顺序可能需要实测。LTsolzenangle在cos(lat)==0或cos(declin)==0时直接停止;极点和极端季节输入是否常见需结合实际网格确认。
复现风险
_MO.nc/_EV.nc会覆盖同名文件。- 大 4D 变量整块读写,内存占用可能很高。
- 文件名生成假定输入后缀为
.nc,通过file(1:len_trim(file)-3)截断。 - 内置
sol2ls常数与主模式planete_h/solarlong参数不完全共享,精确季节对齐需核验。
相关页面
- util/index.md - util 后处理工具总览。
- concatnc.md - 常见上游时间拼接工具。
- localtime.md - 固定本地时重排工具。
- lslin.md - Ls 线性化工具。
- zrecast.md - 常见上游垂直坐标重投影工具。
- solarlong - 主模式侧 sol 到太阳经度换算。