2. 作物生长模型驱动的产量预测

任务说明

本案例针对特定地块,利用历史气象数据(温度、降水、日照)与土壤数据(有机质、速效氮),通过简化的作物生长模型(基于积温与水分胁迫的干物质积累模型)预测该地块的作物产量。你需要完成数据准备、模型参数设定、产量计算与结果输出,并验证模型对输入变化的响应是否符合农学常识。

数据与模型定义

模型核心假设:作物产量与生育期内有效积温累积呈线性关系,但受水分供应(降水+土壤初始含水量)的胁迫限制。土壤肥力(有机质、速效氮)作为产量修正系数。

输入数据(以冬小麦为例,生育期150天):

  • 气象数据:逐日最高温、最低温、降水量(单位:℃、mm)
  • 土壤数据:土壤有效含水量(mm)、有机质含量(%)、速效氮含量(mg/kg)

模型公式:

有效积温 GDD = Σ max(0, (Tmax+Tmin)/2 - Tbase)  其中 Tbase=5℃
水分胁迫系数 W = min(1, (降水累计 + 初始土壤有效水) / 作物需水量)
作物需水量 ETc = 累计GDD × 0.25(mm/℃·d)
肥力修正 F = 0.8 + 0.1×有机质(%) + 0.002×速效氮(mg/kg)
产量 Y = 潜在产量系数 K × GDD × W × F   (K=0.8 kg/ha·℃)

代码实现

import json

def read_inputs(weather_file, soil_file):
    """读取气象与土壤JSON数据"""
    with open(weather_file, 'r', encoding='utf-8') as f:
        weather = json.load(f)
    with open(soil_file, 'r', encoding='utf-8') as f:
        soil = json.load(f)
    return weather, soil

def calculate_gdd(weather, tbase=5.0):
    """计算逐日有效积温并返回累计值"""
    total_gdd = 0.0
    for day in weather['daily']:
        tavg = (day['tmax'] + day['tmin']) / 2.0
        gdd = max(0.0, tavg - tbase)
        total_gdd += gdd
    return total_gdd

def water_stress_factor(weather, soil, total_gdd):
    """计算水分胁迫系数"""
    total_rain = sum(day['precip'] for day in weather['daily'])
    available_water = total_rain + soil['initial_soil_water']
    etc = total_gdd * 0.25  # 作物需水量
    w = min(1.0, available_water / etc) if etc > 0 else 1.0
    return w

def fertility_factor(soil):
    """计算土壤肥力修正系数"""
    return 0.8 + 0.1 * soil['organic_matter'] + 0.002 * soil['available_n']

def predict_yield(weather_file, soil_file, k=0.8):
    """主函数:预测产量(kg/ha)"""
    weather, soil = read_inputs(weather_file, soil_file)
    total_gdd = calculate_gdd(weather)
    w = water_stress_factor(weather, soil, total_gdd)
    f = fertility_factor(soil)
    yield_pred = k * total_gdd * w * f
    return {
        'total_gdd': round(total_gdd, 1),
        'water_stress': round(w, 3),
        'fertility_factor': round(f, 3),
        'yield_kg_per_ha': round(yield_pred, 1)
    }

# 示例数据文件:weather.json
weather_data = {
    "daily": [
        {"tmax": 12, "tmin": 4, "precip": 2},
        {"tmax": 15, "tmin": 6, "precip": 0},
        {"tmax": 18, "tmin": 8, "precip": 5},
        {"tmax": 20, "tmin": 10, "precip": 3},
        {"tmax": 22, "tmin": 12, "precip": 0}
    ]
}
with open('weather.json', 'w') as f:
    json.dump(weather_data, f)

# 示例数据文件:soil.json
soil_data = {
    "initial_soil_water": 40,
    "organic_matter": 2.5,
    "available_n": 80
}
with open('soil.json', 'w') as f:
    json.dump(soil_data, f)

# 执行预测
result = predict_yield('weather.json', 'soil.json')
print(json.dumps(result, ensure_ascii=False, indent=2))

运行与验证

运行方式:将上述代码保存为 yield_predict.py,在Python 3环境中执行 python yield_predict.py。代码会自动生成示例气象与土壤数据文件并运行预测。

验证方法:

  1. 检查输出结果中 total_gdd 是否等于逐日有效积温之和(示例数据中第1天(12+4)/2-5=3,第2天(15+6)/2-5=5.5,第3天(18+8)/2-5=8,第4天(20+10)/2-5=10,第5天(22+12)/2-5=12,合计38.5℃)。
  2. 验证水分胁迫:累计降水10mm + 初始土壤水40mm = 50mm,需水量=38.5×0.25=9.625mm,W=min(1, 50/9.625)=1.0,说明水分充足。
  3. 验证肥力修正:F=0.8+0.1×2.5+0.002×80=1.21。
  4. 预期产量:0.8×38.5×1.0×1.21=37.3 kg/ha(与代码输出一致)。
  5. 修改weather.json中降水为0,重新运行,观察产量是否下降(水分胁迫生效)。

判定标准:程序无报错运行,输出结果与上述手算一致;当降水减少时产量降低,证明模型对水分输入敏感。

作物生长模型产量预测流程 气象数据 逐日Tmax/Tmin 逐日降水量 (JSON格式) 土壤数据 初始有效含水量 有机质含量 速效氮含量 积温计算 GDD = Σmax(0,Tavg-5) 水分胁迫系数 W = min(1, 可用水/需水量) 肥力修正 F = 0.8+0.1×OM+0.002×N × 产量预测 Y = K×GDD×W×F 单位: kg/ha 验证观测点 ① 积温输出 = 手算逐日GDD之和 ② 水分充足时W=1.0;降水减少时W<1且产量下降 ③ 肥力修正系数 = 0.8+0.1×OM+0.002×N,与代码一致