简介:ITU-R P.676-11建议书给出氧气、水蒸气等大气气体在无线电传播中的吸收衰减推荐算法,本代码用Matlab将其曲线完整复现,目标是服务从事卫星通信、毫米波传输链路规划、大气衰减补偿和相关课题研究的学生、工程师与科研人员。资源包含6个文件,其中5个为带详细注释的.m函数脚本,分别对应主程序、气体吸收谱线计算与不同频段衰减函数等模块,另有1个txt说明文件帮助理解运行流程;整体7z压缩包仅3KB,结构轻量、便于逐行研读。用户在Matlab中直接运行main函数,即可输出ITU-R P.676-11建议的大气气体衰减参考曲线,并对照不同频率、仰角或气压条件的变化趋势。代码每行均有中文注释,既适合作为高频段电波传播课程或毕业设计的参考实现,也适合在现有衰减模型基础上扩展频段、修改参数、嵌入其他链路预算程序。该资源发布后已有417人学习下载,对希望快速得到标准衰减曲线并理解算法细节的读者来说,是一份可直接上手的实用模板。
1. 结论先给:为什么 P.676-11 建议书里的衰减曲线不是一条简单公式
很多做毫米波链路预算的人第一次翻开大气衰减数据时都会愣一下:同是晴空,1 GHz 的波跑一公里几乎无感,40 GHz 的波每公里却被吃掉约 0.3 dB,60 GHz 附近更是直接冲到每公里十几个 dB。更反直觉的是,这条大气损耗曲线长得不像一条平滑指数线,而是一堆陡峭的尖峰和起伏的尾巴。峰值位置恰好落在氧气和水蒸气的分子谐振频率上,这就是电磁波的大气衰减——准确说,是大气气体对微波和毫米波的吸收损耗。TU-R P.676-11 建议书就是把这种"随频率剧烈波动、随气象条件漂移"的物理过程,组织成一套可编程计算方法的权威依据。搞懂这条曲线为什么长这样、建议书又如何把它压缩成工程可用的公式,比拿到一段能跑的 MATLAB 代码更重要,因为所有毫米波通信、卫星地球站和雷达系统最终都要靠它校准链路余量。
2. 大气衰减的物理机制:谐振吸收与 P.676-11 的建模路线
2.1 分子谐振:氧气和水蒸气为什么会在特定频率"吃"信号
电磁波穿过大气时,能量不是均匀消耗的。大气中的氧分子和水分子拥有固定的转动能级,当电磁波频率恰好对应两组能级之间的能量差时,分子就会吸收一个光子,从低能态跃迁到高能态,随后通过分子间碰撞把这份能量转化为热能。在宏观上,这表现为信号的净衰减。氧气分子因为电子壳层未满,具有磁偶极矩,所以它的转动跃迁主要集中在一大簇靠近 60 GHz 的谱线群,外加一条 118 GHz 左右的独立谱线;水蒸气则是极性分子,电偶极矩可以与电场直接耦合,因此它的强吸收峰出现在 22.2 GHz、183.3 GHz、325.4 GHz 等位置。正是这些"分子指纹"决定了毫米波大气衰减的尖峰结构。
在地表大气压强和温度条件下,每条谱线都会被碰撞展宽成一条脚部很宽、中心很高的线形,通常用洛伦兹线形来描述。展宽后的谱线不再只在中心频率产生吸收,它的尾部会向两侧延伸很远。这就解释了为什么在完全没有降雨的情况下,甚至频率远离任何谐振峰时,大气仍然存在底噪式的吸收。10 GHz 以下频段的衰减里,就混着 22.2 GHz 水汽谱线的长尾巴和 60 GHz 氧气谱线群的拖尾。所谓"无降水也有大气吸收损耗",本质上是分子谐振尾巴在低频端的贡献。
2.2 谱线如何叠加成一条连续衰减曲线
理解了单条谱线的形态,大气衰减曲线的组装逻辑就很清晰:把大气中所有相关谱线在目标频点上的贡献逐一相加,再加上一个随频率缓慢变化的非谐振背景项。我们经常看到的比衰减 γ(f)(单位 dB/km),就是干空气谱线项、水汽谱线项和非谐振项三者的叠加结果。
非谐振项来自两个物理过程:一是氧气的德拜吸收,二是氮气的压力感生吸收。前者与分子在电磁场中的极化弛豫有关,频率比较低时贡献显著;后者是因为氮气分子本身没有永久偶极矩,但在高压下分子间碰撞会让它产生瞬时的感应极化和吸收。工程简化公式里往往把这两项合成一个平滑的低频背景项。如果复现代码时只累加谐振谱线而漏掉这个背景项,低频段算出来的衰减就会明显偏低。一个可验证的粗略准则是:在 5 GHz 附近,总比衰减通常应该在 0.01 dB/km 量级,偏差超过一个量级就要先怀疑非谐振项丢了。
2.3 逐线积分太贵:P.676-11 用两套精度做取舍
建议书文本里其实给了两种计算路径。第一种是逐线积分模型:把大气从地面到几十公里高度切成薄层,每一层用当地的气压、温度和水汽密度代入谱线公式,算出该层的比衰减,再沿射线实际路径做积分。这个方案最贴近物理,但需要探空数据或数值天气模型提供完整的大气剖面,对一般工程预算来说负担太重。
第二种是简化比衰减算法,也是大多数工程师实际使用的版本。它假设一组海平面平均气象条件,把所有谱线积分预先折成带温度修正的封闭表达式,用户只需要输入频率、气压、温度和绝对湿度,就能直接算出该频率下的比衰减。这样做的好处是把"复杂性"留在标准制定者和算法维护者那边,把"简单性"留给最终调用者。复现时必须先想清楚自己走的是哪条路径:拿简化法去校验证逐线法,或者反过来用逐线法检验简化法,都会得出"代码有 bug"的假象。
3. P.676-11 算法结构:参数、式子与倾斜路径
3.1 四个输入参数决定一个比衰减值
简化算法的输入参数并不多,但每个参数的单位和物理含义都容易踩坑。下面这张表列出最关键的四个量:
| 符号 | 含义 | 常用单位 | 典型地表值 |
|---|---|---|---|
| f | 工作频率 | GHz | 1 ~ 1000 |
| P | 大气压强 | hPa | 1013.25 |
| T | 温度 | K | 288.15(约 15°C) |
| ρ_w | 水汽绝对密度 | g/m³ | 7.5 |
注意 ρ_w 是绝对湿度,不是相对湿度百分比。很多工程脚本会把气象站给出的 50% RH 直接填进去,这是典型错误。正确做法是用饱和水汽压公式先做一次温湿度换算;如果手头没有实测湿度,取 7.5 g/m³ 作为地表默认值通常不会对链路预算造成灾难性误差,但在 183 GHz 水汽峰附近,默认值的不确定性会被放大。
3.2 干空气项、水汽项与总比衰减
在简化算法中,总比衰减写为:
γ = γ_o + γ_w
其中 γ_o 是干空气部分,主要来自氧气谱线群;γ_w 是水汽部分,来自水蒸气各条转动谱线。干空气部分的计算可以概括为对氧气谱线逐条循环:对每条谱线,先根据当前温度修正谱线强度,根据当前气压修正谱线宽度,然后代入洛伦兹线形公式。一条谱线在频点 f 处的贡献大致形如:
F(f) = Δf / ((f - f_i)² + Δf²) + Δf / ((f + f_i)² + Δf²)
这里 f_i 是谱线中心频率,Δf 是展宽后的半宽。第一项描述的是"入射波与谱线中心频率之差"产生的吸收,第二项是负频率镜像项,用来保证吸收谱在零频附近连续。把几十条氧气谱线全部累加,最后加上德拜非谐振项,就得到 γ_o。水汽部分逻辑相同,只是谱线表换成水汽的谱线表,并且整体近似正比于绝对湿度 ρ_w。
当频率远小于谱线中心频率时,每个洛伦兹项的尾部近似正比于 f²,所以低频段的总衰减大致按频率平方爬升。你可以用这个规律做快速自查:5 GHz 处的 γ 应该在 0.01 dB/km 量级,如果算出来是 0.1 dB/km,大概率是单位换算或谱线强度系数出了问题。
3.3 倾斜路径的等效高度法与低仰角修正
比衰减描述的是水平均匀大气中"每公里"的损耗。实际链路都是有仰角的,卫星地面站看卫星的仰角通常在 20° 到 50° 之间,射线穿过大气走过的路程大于垂直高度,而且大气越往上越稀薄,不能简单用海平面 γ 乘以整个路径长。
P.676-11 给了一个非常顺手的工程近似:把垂直方向上的大气积分等效成两个常数高度,即氧气等效高度 h_o 和水汽等效高度 h_w。对垂直射线,总衰减近似等于 γ_o h_o + γ_w h_w;对仰角 θ,路径长度大约按 1/sin(θ) 拉伸,所以总衰减近似为:
A ≈ γ_o h_o / sin(θ) + γ_w h_w / sin(θ)
这个近似在仰角大于 10° 时误差很小,因为大气层的等效积分对斜路径方向仍基本成立。但当仰角低到几度时,射线路径会在大气中弯曲,球面分层和折射效应开始占主导,直接除以 sin(θ) 会严重低估衰减。建议书针对低仰角给了专门的修正系数或要求改用球面分层积分。复现代码时我建议把角度分支单独写一个函数,让仰角大于 10° 和小于 10° 走完全不同的计算路径,而不是共用一个除法。
4. MATLAB 复现:参数表、核心函数与曲线绘制
4.1 把谱线参数表组织成 MATALB 结构体
建议书里最容易被忽略的是谱线参数表。我复现时第一件事不是写衰减函数,而是把氧气和水蒸气的谱线数据敲进一个结构体数组,因为后续所有计算都要反复引用这些系数。
% 每一行对应建议书中的一条气体吸收谱线 % 字段:center 线心频率 GHz;inten 强度系数;width 宽度系数;expn 温度指数 lines_o(1).center = 0.0; % 占位,实际从建议书复制 lines_o(1).inten = 0.0; lines_o(1).width = 0.0; lines_o(1).expn = 0.0; % 水汽谱线表结构相同,字段含义一致 lines_w(1).center = 22.235; % 示例:水汽第一条谱线 lines_w(1).inten = 0.0; lines_w(1).width = 0.0; lines_w(1).expn = 0.0;结构体数组的好处是循环内可读性好:lines_o(k).center 一眼就知道是线心频率。如果你更喜欢高效写法,也可以把四列拼成一个 N×4 矩阵。需要特别提醒的是,手敲参数极易出错,尤其是几十行的谱线表里一旦有一行频率错位,整个曲线的峰形就会变得奇奇怪怪。建议从建议书 PDF 里复制原始表格,再写一个 MATLAB 脚本检查频率序列是否严格递增、谱线总数是否与建议书一致。检查通过后再进入计算环节。
4.2 比衰减核心函数的骨架
下面是一个按简化算法骨架写的 MATLAB 函数,它接受频率、气压、温度和水汽密度,返回比衰减 γ:
function gamma = gas_gamma(f_GHz, P_hPa, T_K, rho_H2O) % 输入: % f_GHz 频率,单位 GHz,标量或向量 % P_hPa 地表气压,单位 hPa % T_K 温度,单位 K % rho_H2O 绝对湿度,单位 g/m3 % 输出: % gamma 比衰减,单位 dB/km % 参考条件,建议书中常用 P0 = 1013.25; T0 = 288.15; % 由温度产生的谱线强度修正:指数项来自建议书 % 这里用 exp 的形式,实际参数列表里每个谱线有自己的指数 gamma_o = zeros(size(f_GHz)); for k = 1:size(lines_o, 1) fi = lines_o(k).center; S = lines_o(k).inten * (T_K / T0)^lines_o(k).expn; df = lines_o(k).width * (P_hPa / P0) * (T0 / T_K)^0.9; % 洛伦兹线形,含负频率镜像项 F = df ./ ((f_GHz - fi).^2 + df.^2) + ... df ./ ((f_GHz + fi).^2 + df.^2); gamma_o = gamma_o + S .* F; end % 德拜非谐振项:频率越低越重要,系数按建议书公式填写 % 这里 F_MHz 只是占位,实际需要把 GHz 转换到公式要求的单位 F_dummy = f_GHz; % 提醒:真正的系数并不是 f 本身 gamma_o = gamma_o + F_dummy; % 占位,正式实现时替换 % 水汽谱线循环与氧气类似,最后整体乘以 rho_H2O gamma_w = zeros(size(f_GHz)); % for k = 1:size(lines_w, 1) % ... 同样的线形累加,最后乘 rho_H2O % end gamma = gamma_o + gamma_w; end这段代码只是展示结构,不是建议书完整实现。真正要强调的是几个机制性细节:谱线宽度与气压近似成正比,导致高海拔低压环境下谱线变窄、峰形变尖锐;谱线强度随温度按指数律变化,不同谱线指数不同;德拜非谐振项在低频端贡献很大,但它的频率依赖关系不是简单的一次方,必须查建议书具体公式,不能自己拍一个比例系数。另外注意代码中我把 f_GHz 同时用作 MHz 的占位,实际复现时最容易出 bug 的就是这里:有的公式用 GHz,有的用 MHz,一旦混用,60 GHz 的峰会被算到 600 GHz 去。
4.3 绘制复现曲线并与建议书交叉验证
比衰减函数写好后就到了最有价值的环节——画曲线。下面这段脚本生成 1 到 350 GHz 范围内的干空气、水汽和总衰减三条曲线:
% 典型地表气象条件 P = 1013.25; T = 288.15; rho = 7.5; % 频率采样:1 GHz 到 350 GHz,步进 0.05 GHz f = 1:0.05:350; % 分别计算三条曲线 gamma_o = gas_gamma_oxygen(f, P, T); % 干空气部分 gamma_w = gas_gamma_water(f, P, T, rho); % 水汽部分 gamma_t = gamma_o + gamma_w; % 总比衰减 % 半对数坐标绘图:横轴 GHz,纵轴 dB/km figure; semilogx(f, gamma_o, '--', f, gamma_w, ':', f, gamma_t, '-'); xlabel('频率 (GHz)'); ylabel('比衰减 (dB/km)'); legend('氧气', '水蒸气', '总衰减', 'Location', 'NorthWest'); xlim([1 350]); grid on;跑完这段脚本,你第一眼应该看到 60 GHz 附近一个尖锐的氧气吸收峰,以及 22.2 GHz 和 183 GHz 附近的水汽吸收峰。如果峰的位置不对,优先检查谱线中心频率表;如果峰高差很多,优先检查温度指数和气压展宽系数;如果低频端底噪偏高或偏低,优先检查德拜非谐振项。这种"先看曲线形状再怀疑实现细节"的顺序,能帮你快速定位大多数复现错误。
5. 常见问题与排查:从参数表到链路预算的五个坑
5.1 频率单位混用,峰值全部错位
现象:计算出的氧气吸收峰出现在 600 GHz,而不是 60 GHz。
原因:建议书不同子公式里频率单位不一致,有的用 GHz,有的用 MHz,还有的归一化到 THz。代码里一旦在某个环节把 GHz 当 MHz 使用,相当于所有频率坐标整体放大了 1000 倍。
解决:在函数入口处加一条单位断言,比如 assert(max(f_GHz) < 1000 && min(f_GHz) > 0)。每次调用前先算一个 60 GHz 单点值,确认 γ 落在 10 dB/km 量级再继续。
5.2 绝对湿度当相对湿度用,水汽衰减严重失真
现象:20 GHz 链路预算中水汽衰减算出来不足 0.001 dB/km,而经验参考值应该在 0.03 dB/km 左右。
原因:输入的是气象站给的相对湿度百分比(比如 50%),却被直接塞进需要绝对湿度(g/m³)的公式。这会让水汽谱线项的权重整体缩小几十倍。
解决:先用 Magnus 公式或其他经验饱和水汽压公式,把相对湿度换算成绝对湿度再传入。如果实在没有湿度数据,宁可固定默认 7.5 g/m³,也不要拿 50% 这种相对湿度数去凑单位。
5.3 低仰角时直线近似崩溃
现象:仰角从 5° 降到 1° 时,算出来的总衰减反而出现不正常的下降甚至负值。
原因:平坦大气近似中路径长度正比于 1/sin(θ),θ 趋近 0 时应该发散,不会下降。出现下降多半是修正函数里 sin/cos 写反,或者某个低仰角修正多项式被错误地外推到了定义域之外。
解决:代码里明确分支:仰角大于 10°,使用 1/sin(θ) 近似;仰角在 0 到 10°,查建议书的低仰角修正表并插值;仰角不允许为 0 以下。把这个分支写成独立函数,并在注释里写明适用边界。
5.4 漏掉非谐振项,低频段底噪失真
现象:1 GHz 和 5 GHz 处算出的干空气衰减比建议书参考值低 30% 以上。
原因:只累加了氧气谐振谱线,没有加上德拜吸收和氮气压力感生项。低频段谐振谱线的尾巴贡献很小,真正主导的是平滑的非谐振背景项。
解决:确认氧气比衰减计算的最后一步加上了低频平滑背景项。不要自己编一个系数,要从建议书复折射率模型或简化公式中反推这个项的表达式。
5.5 简化公式在频带边缘外推,误差突然放大
现象:在 350 GHz 以上计算值与逐线法差距越来越大,甚至出现非物理的负衰减。
原因:简化算法中的谱线截断和多项式拟合只覆盖了建议书确认的适用频段,超出这个范围后没有任何保证。
解决:把函数使用范围锁定在 1 ~ 350 GHz,并在 MATLAB 代码注释里明确"禁止外推"。如果业务真的需要更高的频率,就要切换到逐线积分版本,并准备完整的大气剖面数据,而不是试图用简化公式硬算。
6. 设计取舍与进阶:等效高度为什么是聪明的工程近似
看到这里你可能会问:既然计算机速度足够快,为什么 P.676-11 还要保留"等效高度"这种粗糙的近似,而不直接让用户对大气剖面做数值积分?答案是标准文本必须照顾最广泛的用户场景。一个做链路预算的工程师,手上可能只有站点的年均气压、年均温度和名义水汽密度,没有探空数据,也没有数值天气模式。等效高度把"未知的垂直剖面"压缩成两个可查常数,用户只需计算海平面的 γ,再乘以等效高度,就能得到垂直衰减。这个取舍牺牲的是对温度逆增、水汽边界层等特殊气象结构的刻画能力,但在绝大多数微波和毫米波通信场景里,这种误差远小于降雨衰减和云衰减带来的不确定性。
如果确实需要更高精度,进阶做法是把逐线模型从纸面搬进代码:利用数值天气预报输出的等压面数据,把大气分成数十层,每层直接用温度、气压和湿度计算比衰减,再沿射线路径做积分。此时要注意网格分辨率不均匀的问题——低层大气变化剧烈,必须用非均匀层高,高层可以适当放宽。每次计算完都与建议书参考点交叉验证,而不是只跑一次就对结果放心。
我在自己的毫米波链路预算工具里设置了一个自动化抽检脚本:固定一组地表气象条件,每晚对 1 ~ 350 GHz 全频段做一次比衰减扫描,自动提取 60 GHz 峰值的位置和高度,与建议书参考值比较。只要峰值位置偏移超过 0.1 GHz 或峰高偏差超过 0.5 dB,脚本就会告警提示参数表被动过了。从那以后,我每次改动谱线表,都强制先跑一遍 60 GHz 单点自检,再画曲线看峰形,最后才敢把结果接进链路预算。这套流程帮我拦下了不少低级错误,比如水汽密度换算错、dB/km 与 dB/100m 混用、频率单位漏转等,都是靠着曲线形状的先验知识一眼发现的。希望帮到你。
本文还有配套的精品资源,点击获取