# 吉隆口岸 2026-08-26 冰岩崩灾害 · ERA5-Land 气象背景分析 ## 事件 2026 年 8 月 26 日北京时间 10:52,尼泊尔朗塘力宁(Langtang Lirung,7227 m)北坡海拔约 5200 至 5500 m 处发生高位冰岩崩塌。USGS 记录到 M5.2 地震信号,并判定该信号由崩塌本身产生, 而不是地震触发了崩塌。碎屑流沿东林藏布(Lhende Khola)高速下泄约 20 km, 在崩塌后约 7 分钟(10:59 前后)摧毁中尼边境吉隆口岸,随后沿吉隆藏布进入尼泊尔境内, 在特里苏里河约 72 km 河段造成连锁洪灾。 多方分析指向冻土退化与冰川减薄导致的坡体失稳,而非降雨或冰湖溃决触发,且事发当日无降水。 ## 本项目要回答的问题 1. **降水是否参与触发。** 事发前 1/3/7/30 天累计降水在近 10 年同期中处于什么水平, 能否从再分析资料的角度排除降雨触发。 2. **热力条件是否异常。** 事发前的气温距平、正积温(PDD)与 0 °C 等温线高度, 是否显示源区(约 5300 m)出现异常偏暖,为融水与冻土退化促发失稳的假说提供或排除背景证据。 **定位。** ERA5-Land 网格约 9 km,无法分辨实际失稳坡面。本分析提供的是区域尺度背景条件, 属于情景描述,不构成对触发机制的归因结论。 ## 目录 ``` Gyirong_2026_event/ ├── README.md ├── data/ │ ├── raw/ CDS 下载的原始 zip,按年一个文件 │ ├── processed/ daily_series.csv、event_hour_diagnostics.json 等分析结果 │ └── auxiliary/ 分析多边形、灾害路径、地点与时间线、界面字符串表(ui_strings.json) │ 以及用户提供的 reach path/ 实测河道 shapefile ├── notebooks/ 01 下载 · 02 处理与校验 · 03 生成网页 ├── src/ config / cds_download / climate_proc / webmap ├── web/ template.html 与内联用的 vendor/(Leaflet、ECharts) ├── docs/ 发布站点:index.html 与中英两版页面,GitHub Pages 服务此目录 ├── DEPLOY.md 发布到 GitHub Pages 的步骤 └── figures/ 静态诊断图 ``` ## 运行环境 conda 环境 `glof`(Python 3.11),已注册同名 Jupyter kernel。 除环境自带的 xarray、pandas、geopandas、shapely、matplotlib 外,需要 `cdsapi >= 0.7.2`: ``` D:/Anaconda/install/envs/glof/python.exe -m pip install "cdsapi>=0.7.2" ``` 网页图表用 CDN 引入 ECharts 与 Leaflet,不需要 plotly。 ## CDS 凭证 `C:\Users\<用户名>\.cdsapirc`,两行: ``` url: https://cds.climate.copernicus.eu/api key: ``` token 在 https://cds.climate.copernicus.eu/profile 获取。 另外必须在数据集页面底部接受 Copernicus 许可条款,否则 API 返回 403 而不会提示原因。 凭证只存放在用户主目录,不进入本项目任何文件。 ## 数据 范围 27.9 至 28.7°N、85.1 至 85.9°E,ERA5-Land 0.1° 网格上的 9 × 9 = 81 个格点, 时段自 2016-01-01 起。 ### 一个服务 用 `reanalysis-era5-land-timeseries`,按年各一次请求,把整个网格、气温与降水、 全部十余年的逐小时数据取回来,合计约 60 MB。 这个选择是实测比出来的。2026-08-30 当天三条路各自的表现: | 路径 | 结果 | |---|---| | `derived-era5-land-daily-statistics` 取降水 | 不可用,服务拒绝累积型变量 | | `reanalysis-era5-land` 逐小时 | 可用但极慢,单个六个月的请求排队 20 分钟以上,全部需六小时以上 | | `reanalysis-era5-land-timeseries` | 全部数据一次请求,64 秒 | 第三个由 ARCO(Analysis-Ready, Cloud-Optimised)存储直接提供,不走常规处理队列, 所以快了两个数量级。它同时接受 `area`、多个变量和跨年的日期区间。 日统计服务仍在 notebook 02 用到,但只用于一年的交叉校验,不用于批量取数。 ### 坑一:日统计服务不支持 ERA5-Land 的累积量 请求 `total_precipitation` 会返回 ``` Daily statistics of accumulated variables are not supported for this dataset, skipping: total_precipitation. ``` `daily_sum` 与 `daily_maximum` 都一样被拒。官方文档写明 "ERA5-Land daily accumulated parameters are not available from the catalogue entry", 而 ERA5 single levels 与 pressure levels 的同类服务是支持的,只有 ERA5-Land 被排除。 机制上的原因是,该服务是通用后处理器,底层对逐小时场套 mean/min/max/sum。 ERA5-Land 的 `tp` 是自 00 UTC 起的滚动累积量、每天归零,通用 reducer 套上去全错。 而这个服务的卖点恰恰是 `time_zone` 参数,一旦日界不是 UTC,累积窗口会在窗口中间归零, 没有任何一个简单 reducer 能给出正确的本地日总量。官方文档也承认这件事很麻烦, 并且在 2026-07-30 刚修过一个某些时区下累积量时间对齐差一小时的 bug。 月平均则完全不同:它是 ECMWF 核心产品线自己算的,定义明确(日总量的月平均,单位 m/day), 且日历月天然按 UTC,没有时区歧义,所以月尺度支持 `tp`。 ### 坑二:不同服务的降水含义不同 | 服务 | `tp` 的含义 | |---|---| | `reanalysis-era5-land` 逐小时 | 自 00 UTC 起的累积量,每天归零,必须解累积 | | `reanalysis-era5-land-timeseries` | 逐小时增量,直接求和即可 | 搞错方向会让日总量差约 12.5 倍。本项目用的是后者,因此代码里**不做解累积**。 notebook 02 每次运行都会与本地月尺度存档比对复核这一点。 ### 另外几条实测的限制 - 日统计服务单次请求最多一年。五年及以上返回 `Your request is too large`。 - `reanalysis-era5-land` 逐小时单次请求最多约六个月。整年返回 `cost limits exceeded`。 - 时间序列服务对裸边界框会丢掉最外一圈行列。`config.AREA_REQUEST` 因此比 `config.AREA_NWSE` 每边外扩半个格点,否则拿回来的是 8 × 8 而不是 9 × 9。 - 时间序列服务的 `end_datetime` 元数据是当年 12 月 31 日的占位值,不是真实档期末日。 `latest_available_date` 因此改用 `reanalysis-era5-land` 的值作为诚实下界, 而请求仍按今天发出,由服务返回它实际拥有的部分,真实末日从数据本身读取。 - **单账号同时活跃的作业数有上限(实测 4)。** 超出后新提交不会抛异常, 而是生成一个状态为 `rejected` 的作业。轮询代码若只识别 `successful` 与 `failed`, 这些作业会永远留在在途集合里,整个循环死锁。`cds_download.run` 显式处理 `rejected` 与 `dismissed`,自动降低并发并把请求放回队列。 - **不要用阻塞式 `client.retrieve`。** 它为每个请求维持一条长轮询连接, 在慢链路上会反复读超时,cdsapi 每次恢复要等 120 秒,实测几乎没有进展。 改为提交后用短请求轮询状态,问题消失。 - 被中断的运行会留下排队中的作业继续占用并发槽位,`cds_download.cleanup_orphans()` 在每次下载前清理。 ### 数据量 81 个格点 × 93,360 个小时 × 2 个变量约 60 MB。数据量取决于格点数乘时间步数, 而这个区域只有 81 个格点。作为对比,同样逐小时,若换成 HMA 全域约 8.6 万个格点则是 32 GB。 真正的成本是请求次数与排队时间,不是字节数。 ### 时效性 ERA5-Land 近实时版本 ERA5-Land-T 落后实时约 5 天。 - **2026-08-30 首次运行**:档期止于 2026-08-25,灾害当天尚未覆盖,诊断以档期末日为锚点。 - **2026-08-31 重跑**:逐小时档期已到 2026-08-27 23:00 UTC,**灾害当天 8 月 26 日已纳入**, 诊断锚点自动切换为事件当天,网页顶部的提示横幅自动消失。只重新下载了 2026 那一个文件。 日尺度序列止于 2026-08-26 而非 08-27,是因为档期最后一个 UTC 日在**空间上**尚未填满 (t2m 有 12 个格点、tp 有 69 个格点全天为 NaN),`_drop_partial_days` 的"完整 24 小时" 守卫把这个日子挡掉了。这是预期行为。 当月数据属 ERA5-Land-T 初始版本,约两个月后会被最终版 ERA5-Land 重算覆盖。 届时若需要最终版,删掉 `data/raw/` 中对应年份的文件重跑即可。 ## 方法 ### 降水:区域平均 分析多边形内格点按**与多边形的重叠面积**乘 cos(纬度) 加权平均。 多边形是实测运移路径两侧 4 km 的缓冲区。 不用中心点落入判断,是因为这个走廊在 0.1° 网格上只覆盖 2 个格点中心。 中心点判断会丢掉全部边缘格点,而且结果对多边形画在哪里极为敏感。 重叠面积权重让 8 个格点按比例参与,明显更稳健。 不做高程订正,因为递减率外推对降水没有物理依据,且 ERA5-Land 单点降水噪声大、 对高山降水存在系统性低估。 ### 气温:点提取加逐日反演的递减率 崩塌源区约 5300 m,吉隆口岸约 1850 m,高差约 3500 m。单一区域平均会把二者混在一起, 物理意义模糊,所以对两个目标高程分别做订正。 递减率不取固定的 6.5 K/km,而是**每天**用分析框内 81 个格点的 t2m 对格点高程做最小二乘回归: ``` t2m_i = a + b · h_i → T_target = t2m_cell + b · (h_target − h_cell) ``` 实测的递减率有明显季节循环:冬季约 −7 K/km,夏季约 −4.5 K/km, 因为季风期湿空气的实际递减率本来就比干绝热浅。**8 月中位数是 −4.41 K/km**, 比常用的固定值 6.5 浅了 2 K/km 以上。 这不是学术洁癖。在 8 月,若改用固定的 6.5 K/km,同样的格点温度订正到目标高程后 **源区会偏冷 2.34 K、口岸会偏暖 2.84 K**。而本项目的核心结论之一正是源区是否处于 融化条件之下,2.3 K 足以改变结论。 回归同时输出 R²,`b` 落在 −8 至 −4 K/km 之外或 R² < 0.7 的日期标记为低置信。 实测 R² 中位数 0.982,质控 100% 通过,没有日期被标记。 格点高程由本地已有的 `ERA5_Land data/era5_land_invariant_flat_HMA.nc` 中的位势场换算 (`z / 9.80665`),81 个格点全部覆盖,不需要额外下载。 回归的截距与斜率同时给出 **0 °C 等温线高度** `h₀ = −a / b`, 它直接回答源区当时是否处于融化条件之下,是本项目里针对性最强的一个诊断量。 ### 降水日聚合 时间序列服务给出的已经是逐小时增量,**不做解累积**。把时间戳整体加 8 小时后按本地日求和即可。 UTC+8 是整小时偏移,所以这一步是精确的。只保留有完整 24 小时支撑的本地日。 若改用 `reanalysis-era5-land` 逐小时,则必须先解累积: ``` inc(t) = acc(t) 若 hour(t) == 1 inc(t) = acc(t) - acc(t-1h) 其余情况(含 hour == 0,它闭合前一日的窗口) ``` 两条路的差别是约 12.5 倍,所以下面的校验一是必做项。 ## 校验 notebook 02 每次运行都会做三项交叉比对。 **校验一,降水量级。** 日降水汇总到月后,与本地 ERA5-Land 月尺度存档(重叠年份 2016 至 2024) 的比值应接近 1。若接近 12.5,说明把累积量当成了增量。实测中位数 **1.004**, 年降水约 2100 mm/yr。 **校验二,气温量级。** 日均气温汇总到月后与月尺度存档的差应在 0.5 K 以内。 实测平均差 **+0.015 K**,标准差 0.057 K。两者日界定义不同(本项目用 UTC+8,存档用 UTC), 存在小量偏差是正常的。 **校验三,日界口径。** 向官方 `derived-era5-land-daily-statistics` 要一年 `time_zone: utc+08:00` 的日均气温,与我们自己从逐小时聚合的结果逐格点比对。 实测差 **0.0002 K**,即 float32 的舍入量级。 同时作为对照,若改用 UTC 日界,与官方 UTC+8 结果的差是标准差 **0.68 K**、 最大 **6.56 K**。这说明日界选择对单日结果影响很大,值得较真,也说明本项目的处理是对的。 ### 递减率实测结果 中位数 **−5.80 K/km**,p5 −7.57,p95 −4.26,R² 中位数 0.982,质控 100% 通过。 明显偏离常用的固定值 6.5 K/km,这正是选择逐日反演的理由。 ## 结果 锚点 **2026-08-26**(灾害当天),百分位对照 2016 至 2026 共 11 年的同一日历窗口。 ### 降水:排除降雨触发 按小时锚定到崩塌时刻(截止 10:00,即排除包含 10:52 的那个小时,口径偏保守): | 窗口 | 累计降水 | 百分位 | |---|---|---| | **当日崩塌前(00:00 至 10:00)** | **0.16 mm** | 当日总量 6.73 mm | | 崩塌前 24 小时 | 6.2 mm | 18 | | 崩塌前 72 小时 | 20.8 mm | **9(11 年最干)** | | 崩塌前 168 小时 | 74.5 mm | 45 | **当天的雨几乎全部落在崩塌之后。** 逐小时序列显示 13:00 才开始下雨,15:00 至 17:00 达到峰值。 只报"当日降水 6.7 mm"会误导,因为崩塌发生时那一天的降水才 0.16 mm。 这是本项目里日尺度做不到、必须用逐小时才能给出的结论,也是选择逐小时取数的直接回报。 ### 热力条件:崩塌前 24 与 72 小时是 11 年同期最暖 0 °C 等温线高度同样按小时锚定,因此需要**逐小时**的递减率回归(与逐日回归同一套方法, 只是逐时步做)。0 °C 等温线有明显日变化,日均值会把这里最关心的细节抹掉。 | 指标 | 数值 | 相对源区 | 百分位 | |---|---|---|---| | 源区 5300 m 当日均气温 | 4.5 °C,距平 +1.0 °C | | | | 当日 0 °C 等温线高度(日历日均) | 6302 m | +1002 m | | | **崩塌前 24 小时等温线高度** | **6276 m** | +976 m | **100(11 年最高)** | | **崩塌前 72 小时等温线高度** | **6196 m** | +896 m | **100(11 年最高)** | | 崩塌前 168 小时等温线高度 | 6168 m | +868 m | 91 | | 前 10 天正积温 PDD | 43 °C·d | | 82 | | 前 30 天正积温 PDD | 131 °C·d | | 64 | 崩塌前 24 与 72 小时的 0 °C 等温线高度,在 2016 至 2026 的**同一时刻窗口中都是最高的一次** (百分位 100 即 11 年里排第 11)。整个源区在崩塌前几天持续处于融化条件之下约 900 至 1000 m。 PDD 的时间结构也一致:10 天窗口(第 82 百分位)比 30 天窗口(第 64 百分位)更靠前, 说明偏暖是集中在临近崩塌的那段时间,而不是整个月都异常。 值得注意的是,这个"11 年最暖"的结论是换用按小时锚定的窗口之后才出现的。 之前用日历日的"前 7 天"窗口得到的是第 91 百分位,已经偏高但不突出。 ### 怎么读这些结论 组合起来是**暖而干,且两者都集中在崩塌前的几十小时内**: - 季风季整体来水正常(前 168 小时第 45 百分位),不缺融水补给 - 但崩塌前 72 小时是 11 年同期最干,当天崩塌前几乎无雨 - 同时崩塌前 24 与 72 小时的 0 °C 等温线高度是 11 年同期最高,源区整层处于融化条件之下 从再分析资料的角度,这支持排除降雨触发,并为融水与冻土退化促发失稳的假说提供背景证据。 **但这不是归因结论**:ERA5-Land 网格约 9 km,分辨不出实际失稳坡面, 上述只是区域尺度的背景条件刻画。 ## 交付物 两个自包含的网页,双击用浏览器打开,也可直接发布上线(见 `DEPLOY.md`): - `docs/gyirong_2026_climate.html`(中文) - `docs/gyirong_2026_climate_en.html`(English) - `docs/index.html` 中英文入口页 Leaflet 与 ECharts 已内联进 HTML,每页约 1.4 MB, **唯一的外部请求是地图瓦片**。cdnjs 被拦或很慢时,图表与界面照常工作。 两者由**同一个模板** `web/template.html` 加**同一份字符串表** `data/auxiliary/ui_strings.json` 生成, 不是两份模板。这轮分析改动频繁,两份模板必然会漂移。地名、路径与图层说明的多语言字段 直接放在 `data/auxiliary/*.geojson` 与 `poi.json` 里,以 `_zh` / `_en` 后缀成对存放, `webmap._localize` 按语言拍平成无后缀键,模板只读无后缀键,未翻译的字段回落到中文。 页面右上角有语言切换链接。数值两版完全相同,不重算。 - 左侧地图:卫星影像与地形图可切换,标注冰岩崩源区、吉隆口岸、朗塘力宁主峰, 绘制灾害路径与气象分析区域,并可显示 81 个 ERA5-Land 格点(按高程着色, 点击查看该格点高程与区域平均权重)。 - 右侧两幅联动图表:日均气温(源区订正、口岸订正、区域平均、气候态参考线)与 日降水(柱状图加 7 日滑动累计)。支持滚轮缩放、拖拽平移、底部拖拽条, 并有近 1 周 / 近 1 月 / 近 1 年 / 近 10 年 / 全部五个预设范围。灾害当天以竖线高亮。 - 下方诊断面板 11 项,两组: **降水**(崩塌前当日、崩塌前 24/72/168 小时)与 **热力**(源区当日均气温、当日 0 °C 等温线高度、崩塌前 24/72/168 小时等温线高度、 前 10 天与前 30 天正积温 PDD)。 除当日气温与当日等温线高度按日历日外,其余均**按小时锚定到崩塌时刻 10:52**, 截止取 10:00 整点。按小时锚定的项只在灾害当天进入档期后出现; 尚未进入时面板自动退回日历日口径。所有项均附近 11 年同一窗口的百分位。 - 灾害当天尚未进入档期时,横轴会延伸到该日并显示数据缺口,顶部出现提示横幅, 诊断自动退回以档期末日为锚点。数据补齐后重跑 notebook 03 即自动切换。 **不发布为托管 artifact。** 托管环境的内容安全策略会拦截外部图片请求, 地图瓦片加载不出来,底图会是空白。本地文件没有这个限制。 网页需要联网加载地图瓦片与图表库,但所有数据序列已内联为 JSON,不依赖外部数据请求。 ## 已知局限 - ERA5-Land 0.1° 分辨率不能分辨实际失稳坡面。本页刻画区域尺度背景条件,不做触发机制归因。 - 运移路径的主体(16.9 km)取自 `data/auxiliary/reach path/source_to_port_path.shp` 的实测河道线, 不是人工勾绘。上游 4.8 km 因无河道数据以直线示意,下游洪水段仍为人工勾绘, 三段在网页上以线型区分,`segment` 属性分别为 `surveyed_channel`、`schematic`、`sketch`。 - 分析区域是沿该路径两侧 4 km 的缓冲区(约 200 km²),**不是 DEM 流向提取的真实汇水区**。 取 4 km 是因为面积与该集水区量级相当;实测 3 至 5 km 之间,事发前各时段累计降水 差异在 1% 以内,百分位除 30 天窗口外完全不变,说明结论对边界怎么画不敏感。 - 源区点位取自路径起点(28.27088°N, 85.51499°E)。公开报道给出的位置约为 28.29°N, 85.53°E,两者相距约 2.4 km,但落在同一个 ERA5-Land 格点(28.3°N, 85.5°E)内, 因此气温序列不受影响。待失稳区遥感解译发表后应予校正。 - 堰塞湖官方通报位于吉隆口岸上游约十几公里、海拔约 2950 m(比口岸高约 1000 m)的 错坚河与普热普强藏布交汇处,由泥石流过后旁侧的小滑坡堵塞河道形成。8 月 28 日 11:43 实测水面面积约 10.4 万 m²、蓄水量约 250 万 m³,尼方通报其后已溃决。 官方未公布坐标,故地图上不标点位,只在文字中说明。 - 递减率订正假设目标点与所在格点之间的温度差异由高程主导,忽略坡向、地形遮蔽与 局地环流的影响。在复杂地形中这是一个有实际误差的简化。 - 当月数据为 ERA5-Land-T 初始版本,数值会在最终版发布后变化。 ## 重跑 ``` cd notebooks # 在 glof kernel 下依次执行 01 → 02 → 03 ``` `01` 幂等,已下载的文件会跳过。想扩展档期(例如等灾害当天数据到位后),直接重跑 `01`, 它会重新查询档期末日并只补新增部分,然后重跑 `02` 与 `03`。