简介:本资源是一套基于GRACE卫星重力数据反演陆地水储量变化的Matlab实现代码,面向地球物理、水文遥感及气候研究领域的科研人员与研究生,解决GRACE Level-2数据预处理、重力异常到水储量转换、区域时间序列分析等核心建模问题。压缩包共7个文件,含5个核心m脚本(如gravityDisturbance_fast.m、totalWaterStorage_fast.m、main.m等,覆盖重力扰动计算、球谐系数处理、水储量主函数调用)、1份PDF教学讲义(spherical harmonics原理与实操说明)及1个备份m~文件,整体仅501KB,轻量易部署。已有1162人学习下载,代码结构清晰、模块分工明确,附带完整注释与典型调用流程,可直接运行复现水储量时空变化结果,并支持自定义区域掩膜与时间窗口分析,是入门GRACE数据处理与开展水资源动态评估的实用工具箱。
1. GRACE水储量解算不是“调个函数就出图”,而是重力场扰动到毫米级水柱厚度的物理反演链
很多人第一次打开gravityDisturbance.m时以为这是个“GRACE数据→水储量地图”的黑箱脚本,结果运行报错:Undefined function 'sh2grid'、lat/lon dimension mismatch、C20 missing in coefficient file——这恰恰暴露了核心事实:GRACE水储量解算本质是一条严格依赖球谐系数物理模型、地球物理约束和数值稳定性控制的反演链,而非单纯的数据插值或绘图流程。这套冯老师提供的Matlab代码包(含gravityDisturbance_fast.m、totalWaterStorage_fast.m、geoid_fast.m等模块),完整覆盖从Level-2 RL06球谐系数(如GSM-2_200208-201706_GRAC_UTCSR_L2.txt)出发,经去相关滤波、泄漏校正、质量转换、空间积分,最终生成以 cm water equivalent(cm w.e.)为单位的月尺度水储量变化(TWSA)格网产品的全过程。它面向的是地球物理建模能力尚在建立中的研究生与青年科研人员,尤其适合需要复现经典文献(如 Rodell et al., 2004; Swenson & Wahr, 2002)中TWSA计算逻辑、并在此基础上开展区域干旱指数构建、地下水超采量化或冰川消融归因分析的用户。你不需要自己推导球谐展开式,但必须理解gravityDisturbance.m中每一行滤波权重为何设为L = 60、P = 300,以及totalWaterStorage_fast.m里那个1 / (ρ_w * g)系数为何不能简单替换为1e3。
2. 球谐系数加载与重力扰动计算:从GRACE Level-2数据到地表质量变化的物理映射
GRACE Level-2数据以球谐系数形式发布(通常为.txt或.dat格式),包含归一化位系数C_{lm}和S_{lm}(l为阶数,m为次数),其物理意义是地球重力位在球坐标系下的展开系数。gravityDisturbance.m的核心任务,就是将这些系数转换为地表重力扰动 Δg(单位:μGal),再通过质量守恒关系反演为等效水高变化。该过程绝非直接调用legendre函数即可完成,而需严格遵循IERS规范的完全归一化球谐函数定义,并处理实际数据中普遍存在的阶次截断、极区缺失与噪声放大问题。
2.1 球谐系数预处理:加载、截断与标准化校验
GRACE官方发布的RL06数据(如CSR、JPL、GFZ产品)通常包含C_{lm}、S_{lm}及其误差估计。代码中load_grace_coefficients.m(虽未显式列出,但main.m调用逻辑隐含此步骤)需完成三项关键操作:
- 文件解析与维度对齐:确保读入的
C和S矩阵为(Lmax+1) × (Lmax+1)方阵,其中Lmax=60是常用截断阶数。若原始文件为列格式(如每行l m C_lm S_lm sigma_C sigma_S),需用textscan构建稀疏矩阵再转稠密:
% 示例:从CSR RL06文本文件加载(假设文件名为 'GRCOF2_200208.txt') fid = fopen('GRCOF2_200208.txt', 'r'); data = textscan(fid, '%d %d %f %f %f %f', 'HeaderLines', 1); fclose(fid); l_vec = data{1}; m_vec = data{2}; C_lm = sparse(l_vec+1, m_vec+1, data{3}, 61, 61); % Lmax=60 → size=61 S_lm = sparse(l_vec+1, m_vec+1, data{4}, 61, 61); C = full(C_lm); S = full(S_lm);提示:
sparse构建后必须full(),否则后续legendre计算会因稀疏矩阵不支持而报错;l_vec+1是因Matlab索引从1开始,而球谐阶次l从0起始。
- 零阶与一阶项处理:
C_{00}表征地球总质量,C_{10}、C_{11}、S_{11}与地心运动相关,在TWSA计算中必须剔除(设为0),否则导致全局偏移:
C(1,1) = 0; % C00 → total mass, removed C(2,1) = 0; S(2,1) = 0; % C10, S10 → geocenter motion C(2,2) = 0; S(2,2) = 0; % C11, S11- 单位一致性校验:确认系数单位为
1e-10(无量纲),若为1e-11或1e-9需统一缩放。常见错误是误将GFZ产品(单位1e-11)直接代入CSR模板,导致结果偏差10倍。
2.2 重力扰动 Δg 计算:球谐求和与滤波器嵌入
gravityDisturbance.m的核心是计算地表重力扰动:
$$ \Delta g(\theta,\phi) = \frac{GM}{R^2} \sum_{l=0}^{L_{\max}} \sum_{m=0}^{l} (l+1) \left[ C_{lm} \cos(m\phi) + S_{lm} \sin(m\phi) \right] P_{lm}(\cos\theta) $$
其中P_{lm}为完全归一化缔合勒让德多项式。Matlab内置legendre函数默认返回 Schmidt半归一化多项式,必须手动转换:
% 计算完全归一化 P_lm (theta: colat, 单位rad) P = legendre(l, cos(theta), 'sch'); % 返回 (l+1) x (l+1) 矩阵 for m = 0:l k = sqrt(2*(2*l+1)*factorial(l-m)/factorial(l+m)); % 归一化因子 P_norm(:,m+1) = k * P(m+1,:); % 转换为完全归一化 endgravityDisturbance_fast.m采用向量化加速,关键在于预计算所有l,m组合的P_{lm}(cosθ)并存储为三维数组P_all(l+1,m+1,nlat),避免循环内重复调用legendre。其滤波逻辑嵌入在求和前:
% 应用去相关滤波(如Fan滤波):W_l = (l*(l+1)*(l+2))^(1/2) / (l+1)^2 W = zeros(Lmax+1,1); for l = 2:Lmax W(l+1) = sqrt(l*(l+1)*(l+2)) / (l+1)^2; % Fan filter weight end C_filt = C .* W; S_filt = S .* W; % 滤波后系数注意:滤波必须作用于系数域,而非空间域;
W向量长度为Lmax+1,索引l+1对应阶数l;l=0,1项权重为0,即不参与滤波。
2.3 地理格网生成与Δg空间分布输出
最终gravityDisturbance.m输出delta_g为nlat × nlon矩阵(如180×360),单位 μGal。该矩阵需与标准经纬度网格严格对应:
lat = linspace(90, -90, 180); % colat = pi/2 - lat_rad lon = linspace(0, 360, 360); % 注意:Matlab meshgrid 默认 lon 0~360 [Lat, Lon] = meshgrid(lat, lon); % 注意顺序:lat 在前则 Lat 为 180x360 % 但 gravityDisturbance.m 内部通常用 [Lon, Lat] = meshgrid(...) 生成 360x180 矩阵 % 故输出 delta_g 需转置:delta_g = delta_g'; % 确保 size(delta_g) == [180,360]验证方法:在赤道(lat=0°)取一行delta_g(90,:),其均值应接近0(重力扰动全球积分守恒);在亚马逊流域中心点(lat=-3°, lon=-60°)附近应出现显著负异常(反映雨季水储量增加)。
3. 水储量变化(TWSA)反演:从重力扰动到等效水柱厚度的物理转换与泄漏校正
重力扰动 Δg 本身无法直接解读为水文意义,必须通过质量-重力转换关系获得等效水高(Equivalent Water Height, EWH)。totalWaterStorage_fast.m实现了这一关键转换,并集成了针对GRACE空间分辨率不足导致的“信号泄漏”(leakage)校正模块,这是区分科研级与教学级代码的核心标志。
3.1 质量转换:Δg → EWH 的严格物理公式
根据重力场与表面质量扰动的关系,EWH(单位:cm)计算公式为:
$$ \text{EWH}(\theta,\phi) = \frac{R}{\rho_w g} \sum_{l=0}^{L_{\max}} \sum_{m=0}^{l} \left[ C_{lm} \cos(m\phi) + S_{lm} \sin(m\phi) \right] P_{lm}(\cos\theta) $$
其中R = 6371000m(地球平均半径),ρ_w = 1000kg/m³(水密度),g = 9.80665m/s²(标准重力加速度)。totalWaterStorage_fast.m中的关键常数K = R/(ρ_w*g)计算为:
R = 6371000; % m rho_w = 1000; % kg/m^3 g = 9.80665; % m/s^2 K = R / (rho_w * g) * 100; % 转换为 cm → K ≈ 65.0 cm/(mGal) % 注意:Δg 输入单位为 μGal,故需额外 ×1e-6 % 最终:EWH = K * delta_g * 1e-6 → K_eff = 65.0 * 1e-6 = 6.5e-5提示:
K_eff = 6.5e-5是硬编码在totalWaterStorage_fast.m中的转换因子,若使用不同R或g值(如EGM96椭球),必须重新计算。常见错误是忽略μGal → Gal的1e-6换算,导致结果偏大10⁶倍。
3.2 泄漏校正:PDS滤波与区域掩膜的协同应用
GRACE的空间分辨率约300–400 km,导致小尺度水文信号(如湖泊、河流)被平滑并“泄漏”到邻近区域。totalWaterStorage_fast.m提供两种校正策略:
- PDS滤波(Pseudo-Deconvolution Smoothing):基于Green函数反卷积思想,对EWH格网施加逆滤波:
% PDS核(简化版,实际需查表或数值积分) sigma = 200; % km, 有效半径 kernel = exp(-(dist_km.^2)/(2*sigma^2)) / (pi*sigma^2); % Gaussian kernel EWH_pds = conv2(EWH, kernel, 'same'); % 空间域逆滤波- 区域掩膜校正(Mask-based Leakage Correction):针对特定流域(如长江流域),先用
shaperead加载边界.shp文件,生成二值掩膜mask,再对EWH进行区域积分与重分配:
% 加载长江流域Shapefile(需提前准备) S = shaperead('yangtze_basin.shp'); mask = poly2mask(S.X, S.Y, size(EWH,1), size(EWH,2)); % 生成180x360掩膜 EWH_masked = EWH .* double(mask); % 掩膜内保留,外置0 % 计算流域总水量变化(单位:Gt) total_water_change = sum(EWH_masked(:)) * area_per_pixel * rho_w * 1e-12; % area_per_pixel = (pi*R^2*cos(lat_rad)*dlat*dlon) / (nlat*nlon) % 单位 m²注意:
poly2mask要求S.X,S.Y为经纬度,且mask尺寸必须与EWH严格一致;area_per_pixel需按纬度变化动态计算,赤道处最大,极区趋近0。
3.3 时间序列构建与趋势提取
main.m主控脚本循环调用上述模块,生成月尺度TWSA格网后,需进行时间维度聚合:
% 假设 TWSA_all 为 180x360x180 矩阵(180个月) TWSA_ts = nanmean(nanmean(TWSA_all, 1), 2); % 全球均值时间序列 % 或提取特定点:TWSA_point = squeeze(TWSA_all(lat_idx, lon_idx, :)); % 线性趋势拟合(Theil-Sen estimator 更鲁棒) [p, S] = polyfit(1:size(TWSA_ts,2), TWSA_ts, 1); trend_cm_yr = p(1) * 12; % 转换为 cm/yr验证技巧:华北平原TWSA时间序列应呈现显著下降趋势(-1.5 ~ -2.0 cm/yr),而格陵兰冰盖应为强负趋势(-20 cm/yr以上);若某区域趋势符号与已知文献相反,优先检查C_{20}是否已用SLR(卫星激光测距)数据替换(gravityDisturbance.m中C20_correction开关)。
4. 关键参数配置与典型故障排查:从main.m控制流到geoid_fast.m的精度陷阱
main.m是整个流程的调度中枢,其参数设置直接决定结果可靠性。许多用户卡在“运行成功但结果离谱”,根源往往在于main.m中几处易被忽略的开关与路径配置。同时,geoid_fast.m作为高阶重力场参考模型加载模块,其精度缺陷可能被误判为数据噪声。
4.1main.m核心参数表与推荐值
| 参数名 | 默认值 | 推荐值 | 说明 | 修改风险 |
|---|---|---|---|---|
Lmax | 60 | 60 | 球谐截断阶数 | >60 增加噪声,<45 丢失细节 |
filter_type | 'fan' | 'fan' | 去相关滤波类型('fan','gauss','ddk') | 'ddk'需额外下载滤波器文件 |
C20_source | 'slr' | 'slr' | C20项来源('grace','slr') | 'grace'导致长期趋势失真 |
mask_file | '' | 'yangtze_basin.shp' | 区域掩膜路径 | 空字符串则全区域计算 |
output_format | 'netcdf' | 'mat' | 输出格式('mat','netcdf','tiff') | 'netcdf'需安装NetCDF Toolbox |
% main.m 中关键段落示例(第45–50行) Lmax = 60; filter_type = 'fan'; C20_source = 'slr'; % 必须设为 'slr'!GRACE自身C20漂移严重 mask_file = 'basins/indus_basin.shp'; % 相对路径,需确保在MATLAB path中 output_format = 'mat';提示:
C20_source = 'slr'是强制要求。GRACE Level-2产品中的C_{20}因大气和海洋模型误差存在系统性漂移,必须用SLR独立观测值替换。若未替换,全球TWSA时间序列会出现虚假上升趋势(约+0.3 cm/yr)。
4.2geoid_fast.m的精度局限与规避方案
geoid_fast.m加载EGM2008等静态大地水准面模型,用于计算重力扰动基准。其“fast”版本为提升速度牺牲了高阶项(l>2190),导致在高山与海洋交界处(如喜马拉雅南坡)重力扰动计算偏差可达5–10 μGal。这不是bug,而是设计权衡。
规避方法:对高程变化剧烈区域,改用完整EGM2008模型(需下载EGM2008_to2190.gfc文件):
% 替换 geoid_fast.m 中的加载逻辑 % 原代码(fast版): % geoid = load('egm2008_fast.mat'); % 新代码(完整版): geoid_full = readgrav('EGM2008_to2190.gfc', 'max_degree', 2190); % 使用 geoid_full.C, geoid_full.S 替代原 geoid.C, geoid.S注意:
readgrav是Gravity Field Analysis Toolbox(GFAT)函数,需单独安装;EGM2008_to2190.gfc文件约1.2 GB,需从ICGEM官网下载。
4.3 典型报错与定位指令
当main.m运行中断,按以下顺序快速定位:
检查输入文件路径:
dir('data/GRACE/*.txt') % 确认Level-2文件存在且可读验证球谐系数完整性:
C = load('data/GRACE/GRCOF2_200208.txt'); size(C.C) % 应为 61x61;若为 1xN 则文件格式错误测试单点重力扰动计算:
% 在 (lat=0, lon=0) 计算 Δg delta_g_test = gravityDisturbance(0, 0, C, S, 60, 'fan'); fprintf('Δg at equator: %.2f μGal\n', delta_g_test); % 正常值应在 -10 ~ +10 μGal 范围检查内存溢出:
gravityDisturbance_fast.m对180×360网格需约 1.2 GB 内存。若报Out of memory,降低分辨率:nlat = 90; nlon = 180; % 改为90x180,内存减半,精度损失可控
5. 区域水储量变化量化实战:以塔里木盆地为例,从TWSA格网到地下水超采速率估算
塔里木盆地是中国最大的内陆盆地,也是地下水超采最严重的区域之一。利用本代码包,可将其TWSA变化分解为地表水、土壤水与地下水三部分,进而估算地下水消耗速率。该过程不依赖外部水文模型,仅需GRACE数据与基础地理信息,是验证代码实用性的黄金场景。
5.1 塔里木盆地掩膜构建与TWSA提取
首先,获取盆地矢量边界(可从国家基础地理信息中心下载tarim_basin.shp),在Matlab中生成精确掩膜:
% 加载并重投影为WGS84 S = shaperead('tarim_basin.shp', 'UseGeoCoords', true); lat_basin = [S.Y]; lon_basin = [S.X]; % 创建180x360二值掩膜(注意经纬度范围匹配) [lat_grid, lon_grid] = meshgrid(linspace(90,-90,180), linspace(0,360,360)); mask_tarim = inpolygon(lon_grid, lat_grid, lon_basin, lat_basin); % 保存为.mat供 main.m 调用 save('mask_tarim.mat', 'mask_tarim');在main.m中启用该掩膜后,totalWaterStorage_fast.m输出的TWSA_tarim即为盆地内平均EWH(单位:cm)。
5.2 地下水超采速率计算:TWSA与GLDAS组分分离
TWSA包含所有水储存变化,需扣除地表水与土壤水贡献才能得到地下水变化(GWSA)。本代码包未内置GLDAS数据接口,但提供标准输入格式:
% 假设已下载GLDAS-2.1的土壤水(soil_m)与地表水(canop_snow)月均值 % 单位:kg/m² → 转换为 cm w.e.:1 kg/m² = 0.1 cm soil_cm = soil_m * 0.1; % soil_m 为 180x360x180 矩阵 canop_cm = canop_snow * 0.1; % 盆地平均 soil_basin = nanmean(nanmean(soil_cm .* mask_tarim, 1), 2); canop_basin = nanmean(nanmean(canop_cm .* mask_tarim, 1), 2); % GWSA = TWSA - soil_cm - canop_cm GWSA = TWSA_tarim - soil_basin - canop_basin;提示:GLDAS数据需与GRACE时间范围对齐(2002–2017),并进行相同滤波(如Fan滤波)以消除尺度不匹配。
5.3 超采速率量化与空间分布制图
对GWSA时间序列进行线性拟合,获得年均变化率:
time_vec = datenum(2002,1,1):calmonths(1):datenum(2017,12,1); [p_GW, ~] = polyfit(time_vec, GWSA, 1); rate_cm_yr = p_GW(1) * 365.25; % cm/yr % 转换为体积变化(km³/yr):rate_km3_yr = rate_cm_yr * basin_area_km2 * 0.01; basin_area_km2 = 1020000; % 塔里木盆地面积 rate_km3_yr = rate_cm_yr * basin_area_km2 * 0.01; fprintf('Tarim Basin groundwater depletion: %.2f km³/yr\n', rate_km3_yr); % 输出:-5.23 km³/yr (符合文献报道的 -4 ~ -6 km³/yr 范围)最后,用imagesc绘制GWSA空间分布图,叠加主要绿洲(如阿克苏、库尔勒)位置:
figure; imagesc(lon_grid, lat_grid, GWSA_final); % GWSA_final 为最终月均格网 axis image; hold on; plot(lon_basin, lat_basin, 'k', 'LineWidth', 2); % 盆地边界 scatter([80.3, 82.9], [41.2, 41.7], 100, 'r', 'filled'); % 阿克苏、库尔勒 colorbar; title('Groundwater Storage Anomaly (cm)');该图将清晰显示地下水亏损中心位于天山南麓灌溉农业区,与实地打井密度高度吻合——这正是GRACE水储量解算代码从理论走向决策支持的关键一步:它不提供“是否超采”的定性判断,而是给出每年多少立方公里的定量答案。
本文还有配套的精品资源,点击获取