跑WRF-Chem的人应该都有过这种经历:模式跑着跑着,突然发现近地面的CO₂浓度场出现一块莫名其妙的异常高值,或者O₃模拟结果对某个时次特别离谱,查来查去最后定位到植被排放输入上。VPRM(Vegetation Photosynthesis and Respiration Model)就是给WRF-Chem提供这类生物圈通量的常用工具,而pyVPRM_examples仓库里的vprm_predictions模块,是整套流程中最核心、也最容易让人卡壳的一环。
这篇我会直接把vprm_predictions从数据准备、单点预测、区域批量到接入WRF-Chem的完整链路拆开讲,包括每个环节为什么要这么做、哪些参数是可以根据自己研究区调整的、哪些是绝对不能乱动的。如果你正准备用pyVPRM跑自己的研究区,或者已经在跑但结果总是不对劲,这篇应该能帮你省下不少排查时间。
1. vprm_predictions是干什么的:先搞懂VPRM在WRF-Chem里扮演什么角色
1.1 WRF-Chem的植被排放缺口
WRF-Chem本身带有一些生物源排放方案,比如MEGAN,但很多人实际使用中会碰到一个问题:MEGAN的默认排放因子和植被分布数据比较老,对于特定区域、特定年份的模拟,不确定性很大。VPRM的优势在于它直接使用卫星反演的植被指数(EVI、LSWI)来动态刻画植被的光合活性和水分状态,而不是依赖静态排放因子表。这意味着它能捕捉到植被的季节变化、干旱胁迫、甚至火灾后的植被恢复过程——这些是传统排放清单很难体现的。
vprm_predictions就是这套VPRM流程里负责“预测”的模块。它读入气象驱动和遥感植被指数,计算出一组生物圈通量:总初级生产力GPP、生态系统呼吸ER、净生态系统交换NEE。这三个量是WRF-Chem生物圈CO₂反馈的核心输入。
1.2 VPRM的计算逻辑一句话版本
VPRM不是一个复杂的过程模型,它的核心思想可以用一个很简洁的框架概括:
NEE = ER + GPP
其中GPP由光能利用效率公式计算,ER由温度和呼吸基准速率决定。
GPP = FAPAR × LUE × PAR
PAR(光合有效辐射)来自气象驱动;FAPAR(光合有效辐射吸收比例)由EVI线性关系估算;LUE(光能利用效率)受温度和水分胁迫因子调节。ER则是基于一个与温度相关的指数函数计算,参考呼吸速率会根据不同植被功能型(PFT)取不同值。
所以vprm_predictions实际上就是把这个公式实现成可运行的代码,并且处理了各种输入数据的读入、时间对齐、空间匹配问题。
1.3 为什么叫“predictions”而不叫“emissions”
这一点值得先说明白。VPRM输出的GPP/ER/NEE在严格意义上说是“通量预测”,不是传统排放清单里的那种“排放量”。它反映的是生态系统和大气之间的CO₂交换速率,单位通常是μmol CO₂ m⁻² s⁻¹。WRF-Chem里面有一个专门的VPRM模块(wrfchemvprm)负责读取这些通量,然后耦合到传输和化学过程中。
很多初学者在这里会犯一个概念性错误:把VPRM输出的NEE直接当排放源项填进anthro_emiss,或者反过来把GPP单独当作排放源,导致碳通量重复计算或者正负号搞反。后面第5章我会专门讲接入WRF-Chem时要注意的单位和符号问题。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 运行vprm_predictions之前:文件结构、数据约定和准备工作
2.1 pyVPRM_examples仓库里你会看到什么
虽然仓库名叫“examples”,但它的结构其实比大多数人想象的要完整。以我拿到手的版本为例,典型目录大概是这样:
text复制pyVPRM_examples/
├── data/
│ ├── met_drivers/ # 气象驱动
│ ├── satellite/ # EVI/LSWI,如MOD09A1-derived
│ ├── landcover/ # 土地覆盖类型(PFT)
│ └── params/ # VPRM参数表(不同PFT参数)
├── scripts/
│ ├── vprm_core.py # VPRM核心计算函数
│ ├── vprm_predictions.py # 主程序,单点/栅格预测入口
│ ├── prep_inputs.py # 数据预处理,把原始数据转成统一格式
│ └── utils.py # 时间、坐标、单位换算辅助函数
├── config/
│ └── example_config.yaml # 配置文件模板
└── docs/
└── vprm_predictions.md # 使用说明
vprm_predictions在这套体系里是一个面向用户的入口,它的职责是:读配置、加载输入、调用vprm_core.py里的计算函数、输出NetCDF或文本结果。换句话说,你实际要改动的文件通常是配置文件,核心计算函数一般不用动。
2.2 输入数据格式约定
这个环节是很多人的第一个坑。VPRM需要的数据本身并不神秘,但格式要求很具体:
| 数据类别 | 典型来源 | 需要的变量 | 时间分辨率 | 空间分辨率 |
|---|---|---|---|---|
| 气象驱动 | ERA5、WRF输出、站点观测 | 2m气温(T2)、向下短波辐射(SWDOWN) | 小时或3小时 | 网格或站点 |
| 植被指数 | MOD09A1/MOD13A1 | EVI、LSWI | 8天合成 | 500m |
| 土地覆盖 | MOD12Q1、GLASS-GLC | PFT分类 | 年 | 500m/1km |
这里有个关键约定:VPRM计算时,EVI和LSWI通常是8天合成的。如果你准备用逐日或逐小时的EVI数据,需要确认来源是否做过时间插值,因为很多实践中的做法是把8天合成值在时间轴上线性插值到逐日,再在逐小时计算时保持当天值不变。
举例来说,读取气象驱动的典型代码:
python复制import xarray as xr
import numpy as np
def load_met(met_file):
ds = xr.open_dataset(met_file)
# 单位转换:K -> degC
temp_c = ds['T2'] - 273.15
# 短波辐射 W/m2,取正午附近时次用于光合计算
swdown = ds['SWDOWN']
return temp_c, swdown
