avg_horiz_mod.F
路径
LMDZ.MARS\libf\dynphy_lonlat\phymars\avg_horiz_mod.F
所属目录/模块
libf/dynphy_lonlat/phymars
文件定位
水平空间平均插值模块;将高分辨率地表数据(如 surface.nc 中的 summit、base 等字段)从源网格(imo×jmo)复合平均到目标 GCM 网格(imn+1 × jmn+1)。由 datareadnc.F 在读取地表数据时调用。
定义的符号
| 符号 |
类型 |
行号 |
作用 |
avg_horiz_mod |
module |
1 |
包装 avg_horiz 子例程 |
avg_horiz |
subroutine |
7 |
将源网格数据按空间搜索分箱平均到目标网格 |
依赖的模块
| use 模块 |
only 列表 |
用途 |
待确认 |
| 无 |
— |
本模块无外部 use 依赖 |
— |
调用的关键例程
| 被调用例程 |
所在模块/文件 |
调用位置 |
作用 |
| 无 |
— |
— |
本模块不调用任何外部例程 |
输入
| 输入 |
来源 |
类型/维度 |
单位 |
含义 |
imo |
datareadnc |
integer |
— |
源网格经度方向点数 |
jmo |
datareadnc |
integer |
— |
源网格纬度方向点数 |
imn |
datareadnc |
integer |
— |
目标网格经度方向点数(输出维度 imn+1) |
jmn |
datareadnc |
integer |
— |
目标网格纬度方向点数(输出维度 jmn+1) |
rlonuo |
datareadnc |
real (imo) |
rad |
源网格经度坐标 |
rlatvo |
datareadnc |
real (jmo) |
rad |
源网格纬度坐标 |
rlonv |
datareadnc |
real (imn+1) |
rad |
目标网格经度边界 |
rlatu |
datareadnc |
real (jmn+1) |
rad |
目标网格纬度边界 |
zdata |
datareadnc |
real (imo*jmo) |
— |
源网格数据(一维展开) |
输出
| 输出 |
去向 |
类型/维度 |
单位 |
含义 |
outdata |
datareadnc::pfield |
real (imn+1, jmn+1) |
同 zdata |
目标网格上的平均水平值 |
共享状态与副作用
- 无
save 变量、无 THREADPRIVATE、无文件 I/O。
- 纯计算模块,无副作用。
核心逻辑
构建目标网格中间坐标(行 43-53):tmplon(2..imn+1) 和 tmplat(2..jmn+1) 为相邻边界点的中点;边界值直接复制。这些中间点定义了目标网格单元的中心。
空间搜索(行 56-74):对每个源网格点 (i,j),遍历所有目标网格单元,找到满足经度在 [tmplon(m), tmplon(m+1)) 且纬度在 [tmplat(n+1), tmplat(n)) 范围内的目标单元 (m,n)。使用 goto 1000 在找到匹配后立即跳出内层循环。结果存储在 iik(i,j) 和 jjk(i,j) 中。
分箱平均(行 76-90):对每个目标单元 (m,n),累加所有映射到该单元的源数据值 zdata(i+imo*(j-1)),再除以落入该单元的源点数 nmesh,得到平均值写入 outdata(m,n)。
伪代码
! 构建目标网格中间坐标
tmplon(1) = rlonv(1)
for m = 2 to imn+1: tmplon(m) = (rlonv(m-1) + rlonv(m)) / 2
tmplon(imn+2) = rlonv(imn+1)
tmplat(1) = rlatu(1)
for n = 2 to jmn+1: tmplat(n) = (rlatu(n-1) + rlatu(n)) / 2
tmplat(jmn+2) = rlatu(jmn+1)
! 空间搜索:为每个源点找到对应的目标单元
for each source point (i, j):
for each target cell (m, n):
if rlonuo(i) in [tmplon(m), tmplon(m+1)):
if rlatvo(j) in [tmplat(n+1), tmplat(n)):
iik(i,j) = m; jjk(i,j) = n
break
! 分箱平均
for each target cell (m, n):
sum = 0; count = 0
for each source point (i, j):
if iik(i,j) == m and jjk(i,j) == n:
sum += zdata(i + imo*(j-1))
count += 1
outdata(m, n) = sum / count
参与的主题流程
| 主题 |
参与方式 |
| 初始场与地表数据 |
在 datareadnc 中将高分辨率地表数据插值到 GCM 网格 |
写法特点
- 固定格式 Fortran(
.F),续行符 .,使用 goto 跳出嵌套循环。
- 无外部依赖,纯算术实现。
- 计算
pi = 2*asin(1) 但实际未在后续代码中使用(遗留代码)。
- 四重嵌套循环(源点 × 目标单元)的时间复杂度为 O(imo×jmo×imn×jmn),适合小规模网格。
- 当目标单元内没有源点时
nmesh=0,存在除零风险(outdata 初始化为 0,但 0/0 仍为 NaN)。
复现要点
- 输入坐标
rlonuo/rlatvo 在调用前已由 datareadnc 从角度转换为弧度(× π/180)。
- 源数据
zdata 为一维展开格式(Fortran 列主序:zdata(i + imo*(j-1)))。
- 目标网格边界数组
rlonv/rlatu 维度为 +1(即网格边界数 = 网格单元数 + 1)。
- 调用后
datareadnc 会处理周期性边界(pfield(iimp1*j) = pfield(1+iimp1*(j-1)))。
待确认
- 纬度搜索条件
rlatvo(j) < tmplat(n) 且 rlatvo(j) >= tmplat(n+1) 暗示纬度从北极向南极递减排列,需确认。
- 目标网格为空单元时的除零行为是否在实际运行中触发。
pi 变量是否曾被使用或仅为遗留代码。
相关页面