资讯动态

APSIM农业系统模拟全流程实战:从气象数据、碳氮平衡到NG迁移与R批量处理

发布时间:2026/9/11 22:22:53 来源:尧图企业网站定制
APSIM 农业系统模拟全流程实战从气象、土壤、碳氮平衡到 NG 版本迁移与 R 批量处理做农业模型的朋友应该都有体会APSIM 这套系统功能确实强但坑也确实多。早期我用它的时候光是搞懂气象文件格式、土壤剖面参数和碳氮循环模块怎么协同工作就花了不少时间。后来做批量模拟分析又发现命令行调用和结果汇总又是一堆细节。这篇东西基于我这些年跑 APSIM 的实际经验把全流程拆开讲讲顺便把常用的 R 批量处理代码整理出来希望对刚入门或者被某个环节卡住的朋友有帮助。这里说的“全流程”大概包含这几个环节理解 APSIM 的核心模拟逻辑、准备气象驱动文件、配置土壤参数、理解碳氮平衡模块、搞定经典版与 NextGenNG版本的衔接最后用 R 把批量模拟和结果处理串起来。这套流程打通之后做气候变化影响评估、不同播期或施肥管理的对比模拟、土壤有机碳变化研究都会顺手很多。1. APSIM 到底在模拟什么框架与整体逻辑刚开始用 APSIM 的时候很多人容易犯一个毛病——拿到模板就改参数也不管模块之间怎么交互。结果是模拟结果非常不靠谱又找不到问题出在哪。所以我觉得动模型之前必须先把它的架构逻辑搞清楚。1.1 模块化结构作物、土壤、气象、管理四件事APSIMAgricultural Production Systems sIMulator本质是一个模块化农业生态系统模拟平台。核心思路是把“作物生长”“土壤水氮变化”“气象驱动”“管理措施”四个维度拆成独立的模块然后在同一个模拟框架里互相交换数据。作物模块负责模拟作物生长发育、生物量积累、产量形成。具体包括玉米、小麦、水稻、棉花等不同作物的生理参数与物候模型。土壤模块包含土壤水分动态一维垂向水流、土壤温度、土壤氮素矿化/固定、硝化反硝化等过程输出不同深度土层的状态变量。气象模块提供逐日太阳辐射、最高最低温度、降水量等驱动数据。管理模块接收用户定义的播种日期、种植密度、施肥方案、灌溉制度、收获日期等管理操作。实际运行时气象数据先驱动作物和土壤模块作物从土壤中吸收水分和养分土壤反过来受到作物根系、残茬管理、耕作措施的影响。这个互相耦合的关系是理解和调试模拟结果的关键。我之前曾把碳氮模块开得太激进作物生物量就常年偏低最后发现是土壤初始矿质氮给得太低、固定作用太强作物无机氮供应不够了。1.2 时间步长与状态变量一切都按“天”推进APSIM 基本以日为时间步长。也就是说气象文件里提供逐日数据模型每天早上根据当天的辐射、温度、降水计算潜在蒸散、作物光合作用、土壤水分再分配、氮素转化等过程然后更新土壤和作物的状态变量。这种日步长机制的优点是运行效率高适合长时间序列模拟比如 30 年历史天气数据和大规模情景分析。但缺点也很明显——它对气象输入的“日值质量”极其敏感。如果哪天最高温度小于最低温度或者降水出现极端异常值模型轻则报错重则产出荒谬结果。所以后面讲气象数据处理时务必重视质量控制。1.3 模拟控制与配置文件从经典版到 NG 版的差异早期经典版APSIM Classic主要用 .apsim 文件存储模拟配置界面相对老旧但对部分老研究者来说比较顺手。而 APSIM NextGenNG用的是 .apsimx 文件格式底层架构完全重写也是目前官方主推的版本。NG 版本保留了经典版的模块思想但在模拟引擎、作物模型如小麦、玉米等采用新一代光合作用和物候计算方式、用户界面和文件格式上都做了大幅调整。也就是说如果你习惯了经典版刚到 NG 版本很有可能找不到参数在哪。但用熟之后NG 版本在批量模拟和 Python/R 集成上灵活得多这也是我推荐新手上手直接用 NG 的原因。不过我也得说实话NG 版本到现在仍有部分模块比如某些特殊管理操作、特定作物参数不如经典版灵活或者社区模板更新不够及时。所以实际项目里我经常会同时保留两套环境并针对具体任务做选择。这个后面单独说。2. 气象数据是模型的第一驱动格式规范与 R 预处理实战APSIM 模拟的源头是天气。没有可靠的气象数据后面做得再精细都是空中楼阁。这一节把天气文件的结构、单位和常见坑都梳理一遍然后用 R 写几段可以直接用的数据清洗与生成代码。2.1 天气驱动文件的字段定义与单位经典版 APSIM 和 NG 版本都用 .met 文件来存储天气数据。文件由两部分组成头部Header记录站点元信息和变量列表下面是一行一行的逐日数据。一个典型的 .met 文件大概是这样的以经典版格式为例! Weather file for Zhengzhou [weather.met.weather] ! station number 1 tav 15.2 amp 12.6 ! Latitude Latitude (degrees), North latitude 34.72 ! Longitude Longitude (degrees), East longitude 113.65 ! Average temperature (tav) and amplitude (amp) are used to calculate ! soil temperature at the start of simulation. [weather] ! radn maxt mint rain 12.5 30.2 18.4 0.0 13.1 31.0 18.9 0.0各字段的含义和单位非常关键radn太阳辐射单位 MJ/m²/day。如果原始数据不是这个单位比如是 W/m² 的瞬时值需要转换如果是日照时数则需要用 Angstrom 公式估算辐射。maxt最高气温单位 ℃一般指距地面 1.5-2m 的百叶箱温度。mint最低气温单位 ℃。rain降水量单位 mm/day。此外头部里还有 tav多年平均气温和 amp多年平均气温年较差用于模拟初始土壤温度剖面尤其是模拟开始阶段没有土壤温度观测数据时非常有用。latitude 和 longitude 用于计算日长、太阳高度角及潜在的辐射拆分对作物模型光周期和光合有效辐射的计算非常关键。2.2 气象数据质量检查与缺测填补我拿到原始气象数据后第一件事不是急着灌进模型而是先做一遍严格的质量检查。一些容易导致模拟失败的现象包括最高温低于最低温。这种情况在自动站数据里很常见尤其是有缺测或者异常记录时。处理办法是先剔除异常再用周边站点插值或时间序列平滑补齐。降水出现负值或极端值比如一日降水超过 500 mm。如果确定是错误数据直接改成缺测然后用相邻日期的均值或者历史同期数据填补。辐射为 0 或异常高。辐射为 0 通常意味着记录缺失或者夜间数据没处理异常高比如超过 35 MJ/m²/day可能是传感器故障需要结合日照时数和云量多方验证。时间序列不连续。如果某些日期缺失.met 文件无法正常运行因为 APSIM 要求逐日连续的数据。做缺测填补时我常采用的方法是根据长期月均值生成一个“气候基准值”再结合相邻年份同一天的波动范围随机扰动或者直接用线性插值。如果缺测比例超过 10%建议不要硬填而是考虑用再分析资料如 ERA5、NASA POWER替代或作为参考。2.3 用 R 实现气象数据格式化和 .met 文件生成下面这段代码是我处理气象数据时经常用的。它假设你有一份 CSV 原始数据包含 date、tmax、tmin、precip、srad 五列其中 srad 以 MJ/m²/day 为单位。代码会完成日期校验、异常值清洗、缺失值填补、单位检查最后生成标准的 .met 文件。library(tidyverse) library(lubridate) # 读取原始气象数据 raw_weather - read_csv(raw_weather.csv) # 日期校验确保连续逐日时间序列 raw_weather - raw_weather %% mutate(date as.Date(date, format %Y-%m-%d)) %% arrange(date) full_dates - data.frame(date seq(min(raw_weather$date), max(raw_weather$date), by day)) weather_daily - full_dates %% left_join(raw_weather, by date) # 异常值清洗去掉最高温 最低温、降水 0、辐射 40 的记录 weather_clean - weather_daily %% mutate( tmax ifelse(tmax tmin, NA, tmax), tmin ifelse(tmin tmax, NA, tmin), rain ifelse(rain 0 | rain 300, NA, rain), srad ifelse(srad 0 | srad 40, NA, srad) ) # 简单缺测填补用线性插值必要时用月度气候均值填充两端 weather_filled - weather_clean %% mutate( tmax zoo::na.approx(tmax, rule 2), tmin zoo::na.approx(tmin, rule 2), rain zoo::na.approx(rain, rule 2), srad zoo::na.approx(srad, rule 2) ) # 计算 tav 和 amp用于模型初始化 tav - mean(c(weather_filled$tmax, weather_filled$tmin), na.rm TRUE) monthly_means - weather_filled %% mutate(month month(date)) %% group_by(month) %% summarise(mean_temp mean((tmax tmin) / 2, na.rm TRUE)) amp - (max(monthly_means$mean_temp) - min(monthly_means$mean_temp)) / 2 # 写入 .met 文件 write_met - function(df, file_path, lat, lon, site_name Weather Station) { lines - c( paste0(! , site_name), [weather.met.weather], ! station number 1, paste0(tav , round(tav, 2)), paste0(amp , round(amp, 2)), paste0(latitude , lat), paste0(longitude , lon), paste0(! Met file generated from raw weather data at , Sys.Date()), [weather], ! radn maxt mint rain ) weather_str - df %% transmute( radn round(srad, 2), maxt round(tmax, 2), mint round(tmin, 2), rain round(rain, 2) ) %% mutate(line paste(radn, maxt, mint, rain, sep )) write_lines(c(lines, weather_str$line), file_path) } write_met(weather_filled, site.met, lat 34.72, lon 113.65, site_name Zhengzhou Station)这段代码里值得注意的几个细节zoo::na.approx默认用线性插值适合短期缺测如果缺测期太长建议先按月份生成气候均值再结合随机扰动否则会让模拟期内天气波动失真。异常值阈值比如 rain 300、srad 40需要根据你的站点实际气候条件调整不能照搬。tav 和 amp 计算用的是全部日值平均和月均温极差的一半这个做法在 APSIM 官方文档里也有体现目的是近似表示正弦年变化对应的温度振幅。2.4 NASA POWER 等再分析资料的快速获取如果实测气象数据不完整或者没有站点数据我通常会从 NASA POWER 或者 ERA5 这类再分析数据集获取逐日数据。NASA POWER 的好处是获取方便提供 API还能直接导出 CSV。需要注意的是这类数据的空间分辨率较粗POWER 大约是 0.5° x 0.5°在复杂地形区域与实测值可能有偏差最好用实测数据做一次偏差校正。R 中可以用nasapower包直接获取下面的代码可以拉取指定站点、指定时间段的逐日最高温、最低温、降水、太阳辐射library(nasapower) power_data - get_power( server power, temporal_average DAILY, lonlat c(113.65, 34.72), dates c(2015-01-01, 2020-12-31), vars c(T2M_MAX, T2M_MIN, PRECTOTCORR, ALLSKY_SFC_SW_DWN) )拿到 POWER 数据后再按前面的方法清洗、格式化成 .met 文件即可。ALLSKY_SFC_SW_DWN 的单位是 kWh/m²/day要转换成 MJ/m²/day 只需要乘以 3.6。3. 土壤参数配置与碳氮平衡模型准确性的“地基”气象是模型的驱动力土壤则是模型的“内存”——作物生长需要从土壤中吸水吸氮土壤碳氮循环又决定了养分的供应和损失。这一节讲土壤剖面文件的结构、核心参数含义以及碳氮平衡模块的初始化和调试思路。3.1 土壤剖面文件的物理参数APSIM 里面土壤剖面通常用不同深度的土层来离散化。每个土层的物理参数直接决定了水分的持水能力和运动特征。最常见的几个参数BD容重g/cm³影响总孔隙度和饱和含水量也影响根系穿透阻力。LL15萎蔫点cm³/cm³代表作物能够利用的下限含水量。低于这个值作物受到水分胁迫气孔关闭生长停滞。DUL田间持水量cm³/cm³代表在重力排水完成后土壤能保留的水量。SAT饱和含水量cm³/cm³所有孔隙都充满水时的含水量。KS饱和导水率mm/day代表土壤饱和时水分垂直下渗的快慢。AirDry风干含水量用于模拟表层土壤在干旱时的最低含水量对蒸发过程有直接影响。下面是一个简单的 APSIM 土壤文件示例经典版参数表我简化了字段SoilName: SiltLoam LayerDepth: 0-15, 15-30, 30-60, 60-100 BD: 1.30, 1.42, 1.50, 1.55 LL15: 0.10, 0.12, 0.15, 0.18 DUL: 0.28, 0.30, 0.32, 0.34 SAT: 0.42, 0.43, 0.44, 0.45 KS: 300, 150, 100, 50这里要特别提醒如果你用的是 NG 版本那么土壤水分特征参数比如 DUL、LL15、SAT和作物可用水量的概念都要更新成新一代的定义。NG 版本里面土壤水分特征曲线用的是 Campbell 模型参数比如AirDry、LL15、DUL、SAT、KS仍然保留但实际模块计算时对LL15的定义更加严格区分了“作物可利用水分下限”和“植物永久萎蔫点”。换句话说同一组参数在 Classic 和 NG 里模拟出来的水分胁迫程度可能不一样这点做模型对比时尤其要注意。3.2 土壤初始水分与初始氮量设定模拟开始之前土壤初始状态直接决定了模拟初期作物生长和氮素供应的水平。APSIM 要求用户设定初始含水量和初始无机氮NH4-N 和 NO3-N含量。初始含水量可以设成 DUL 的百分比比如 60%、80%也可以根据实测土壤墒情数据填写。如果做长期或多情景对比建议所有情景用同一初始条件否则不同情景的差异会被初始状态混淆。初始无机氮NO3-N 和 NH4-N单位是 kg N/ha。由于不同土层的厚度不同需要按土层逐层填写。如果数值太低作物容易前期缺氮太高则可能导致氮淋洗和反硝化损失偏高。在实际操作中我常用的做法是“预平衡”策略。先不种作物用常年气象数据跑 5-10 年“裸地”或“草地”模拟让土壤碳氮和水分达到相对平衡状态然后把模拟结束时的土壤状态作为正式模拟的初始条件。这样比拍脑袋设初始值更可靠尤其在研究长期土壤有机碳变化时预平衡几乎是必须的。3.3 碳氮平衡模块分池模型与调参心得APSIM 的土壤有机质模块采用分池Pool模型。简单说土壤有机质被拆成几个具有不同分解速率的池子。最常见的分法是作物残茬池Crop Residue / Surface Organic Matter留在土壤表面的秸秆、根系残体按 C:N 比和可分解性分成可分解metabolic和难分解structural两个池。土壤微生物生物量池Microbial Biomass / BIOM活跃的微生物和其代谢产物分解速度快周转快。腐殖质池Humic / HUM相对稳定的有机质分解速度慢是土壤碳库的主体。惰性有机质池Inert / IOM几乎不分解的部分。各池之间通过分解decomposition、合成synthesis、矿化mineralization和固定immobilization过程连接在一起。这些过程的速率受土壤温度、水分、质地和 C:N 比共同调节。调整碳氮模块参数时我的经验是“不要乱动默认参数先调输入条件”。很多时候模拟结果不合理不是模型参数的问题而是你给的初始 C:N 比、残茬数量和管理操作设置有问题。比如残茬管理秸秆还田量设定过高同时土壤初始氮不足会导致微生物固定大量无机氮作物前期缺氮。施肥方案如果施肥日期和作物需求高峰期错位即使总施肥量充足作物也会出现阶段性氮亏缺。有机肥投入投入 C:N 比很低的物料比如鸡粪矿化快容易出现氮过量投入 C:N 比高的物料比如麦秸前期固定氮后期释放氮。做碳氮平衡敏感性分析时我通常优先测这几个参数初始有机碳含量、各池分配比例、残茬 C:N 比、以及分解速率常数如果用的是经典版还要看potDecomp和fbiom。如果研究目标不是土壤碳动力学本身就少动分解速率常数多动初始条件和有机物料投入量。3.4 NG 版本里碳氮模块的变化如果你从 Classic 迁移到 NG最明显的变化是土壤氮模块从SoilN换成了SoilNitrogen部分参数命名和逻辑也有调整。NG 版本中土壤有机质的概念模型SoilOrganicMatter把有机质分成了几个 Pool并且新增了对 C、N、P 耦合的考虑取决于版本和模块。更重要的是NG 版本的分解速率计算方式和温度/水分响应函数与经典版并不完全一致。这意味着同一组土壤碳氮参数在 Classic 和 NG 下模拟出的有机碳变化速率可能差不少。所以如果项目里必须同时使用两套版本建议不要直接复用参数文件而是分别标定/验证。否则跨版本对比的结果很难解释。4. NG 版本迁移从 Classic 到 NextGen 的关键差异与实践如果你是新手建议直接学 NG。但如果你和老项目打交道或者有一些只能在 Classic 里跑的旧模型迁移时这些差异要搞清楚。4.1 版本差异与文件格式我整理了一个简要对照表方便快速理解对比维度APSIM ClassicAPSIM NextGen (NG)配置文件.apsim 文件.apsimx 文件JSON 格式界面较老的模拟控制台新版 APSIM UI支持实时预览模型引擎旧版 Fortran/C 模块全新 .NET 核心引擎作物模型经典 APSIM 作物模块新一代 APSIM 作物模块NG 版本土壤模块SoilN / SoilWaterSoilNitrogen / SoilWater重构扩展性相对封闭支持 R/Python 调用较易批量修改支持状态基本停止更新官方主推持续开发在实际使用中我发现 NG 版本的 UI 改进了很多比如土壤剖面参数可以在界面里直接以表格形式编辑气象文件可以拖拽导入而且运行结果的快速可视化也非常方便。但反过来说NG 版本对模型文件格式检查更严格稍微有点不匹配就报错早期的报错信息还不友好对新手是个挑战。4.2 NG 版本安装与基础配置NG 版本安装相对简单到官方渠道下载对应操作系统的安装包即可。安装完成后最好检查一下 APSIM 安装目录下的命令行工具例如Models.exe或ApsimNG.exe取决于版本和平台。使用命令行工具是后面用 R 批量模拟的基础。以我常用的环境为例Windows 下安装 NG 后可能需要自己确认命令行模型的路径。一些版本中命令行核心程序是Models.exe运行单个模拟文件的命令大概是cd /d C:\Program Files\APSIM Models.exe D:\my_simulations\test.apsimxLinux/macOS 环境下通常是通过命令行启动编译后的可执行文件。具体名称和路径可能随版本有所不同安装后建议先跑一个官方示例确认命令行能正确运行。成功运行之后通常会在模拟文件同目录下生成对应的.out文件或者用户指定的输出文件夹。4.3 Classic 模型迁移到 NG 的步骤如果你的手中有一套老模型.apsim 文件想迁移到 NG 版本可以按以下步骤操作在 APSIM NG 界面里尝试“打开”经典版文件。较新版本的 NG 支持直接打开和转换部分 .apsim 文件。转换后重点检查站点/气象文件路径是否仍然有效。因为经典版和 NG 版对相对路径的处理方式不同经常出现找不到气象文件的情况。检查土壤参数的字段名称和单位。尤其是碳氮模块字段更名后需要逐项核对。检查管理操作。比如播种、施肥、灌溉、收获等操作在 NG 里用的是新的“Manager”脚本框架部分老脚本逻辑可能需要重写。调试并对比输出。转换完成后用同一套气象数据跑一遍和经典版输出做对比。如果产量和相关变量的差异在可接受范围内迁移就基本成功了。我之前迁移一个老玉米模型的时候最常遇到的问题反而是来自“管理脚本”——经典版用 Fortran 写的老式管理操作逻辑在 NG 里可能需要用内置的Manager模块C# 脚本重新实现。这个过程并不简单但好在新版 UI 提供了一些现成的管理模板比如自动播种、自动施肥等直接套用再修改参数效率会高很多。4.4 NG 环境下跑通第一个模拟的路径建议如果你是第一次接触 NG不要一上来就自己建模型。建议先用官方自带的 Example比如 Wheat、Maize 的示例在 UI 里跑通一次看懂了输出文件列表和变量含义之后再尝试修改气象数据和土壤参数。修改气象文件时注意 NG 版本的 .met 文件头部里还需要提供一些额外的元数据字段具体看版本常见的有latitude和longitudetav和amp可选elevation可选year起始信息如果头部信息缺失或者格式不对NG 在加载时会报错或者使用默认值这可能导致模拟结果和预期不符。5. R 批量处理实战从单点模拟到大规模情景分析做研究或者实际项目很少只跑一次模拟。通常需要对多个站点、多个年份、多种管理方案做批量组合。这时候用 R 来做批处理和结果汇总能省下大量时间。5.1 准备工作R 中调用 APSIM 的几种方式R 调用 APSIM 主要有两种方式直接调用命令行。在 R 里用system2()函数运行 APSIM 的可执行文件传入 .apsimx 文件路径等运行结束后读取输出文件。用apsimx包如果支持当前版本。这个 R 包提供了一系列读取、修改、运行 APSIM NG 文件的接口使用体验更加友好。我个人的建议是如果只是批量运行预设好的 .apsimx 文件用system2()就够了简单直接如果你需要动态修改模型参数比如做参数敏感性分析那apsimx包能帮你省事不少。不过需要注意apsimx包的函数接口会随 APSIM 版本变化用之前务必检查包版本与 NG 版本的兼容性。5.2 批量修改模型参数的 R 代码以下是使用 R 批量修改一个 .apsimx 文件中的作物播期和施氮量并逐个运行的思路。由于 .apsimx 本质是 JSON 格式可以直接用字符串替换的方法但要小心别改错位置。我一般先复制原始文件为多个临时文件然后用简单的文本替换来实现参数修改。比如需要把作物播种日期从 10 月 1 日改成若干不同日期library(stringr) base_file - wheat_sim.apsimx param_grid - expand.grid( sowing_date c(10-01, 10-10, 10-20), nitrogen_rate c(80, 120, 160) ) run_apsim - function(file_path) { apsim_exe - C:/Program Files/APSIM/Models.exe system2(apsim_exe, args shQuote(file_path), wait TRUE) } for (i in seq_len(nrow(param_grid))) { # 为每个情景生成一个临时文件 temp_file - paste0(temp_sim_, i, .apsimx) file.copy(base_file, temp_file) # 替换播种日期和施氮量示例代码实际需要根据你的模型结构调整 sim_text - readLines(temp_file, warn FALSE) sim_text - str_replace_all(sim_text, pattern start_date.*?;, replacement paste0(start_date, param_grid$sowing_date[i], ;)) sim_text - str_replace_all(sim_text, pattern nitrogen.*?;, replacement paste0(nitrogen, param_grid$nitrogen_rate[i], ;)) writeLines(sim_text, temp_file) # 运行模拟 run_apsim(temp_file) # 运行结束后删掉临时文件或者保留以便排查 # file.remove(temp_file) }这种“文本替换”方法虽然土但好用。不过有个前提临时文件的模型结构必须一致只是某些参数值不同。如果不同情景需要完全不同的管理操作建议用apsimx包或者专门写一个模型生成模板。5.3 批量提取模拟结果out 文件分析与汇总APSIM 运行结束后会输出多个后缀为 .out 的文件。这些是制表符分隔的文本文件每列对应一个变量比如日期、作物产量、地上生物量、土壤含水量、氮淋洗量等。读入 R 并汇总的典型代码如下library(tidyverse) out_files - list.files(pattern *.out, full.names TRUE) # 读取所有 out 文件并保留文件名作为情景标签 all_results - out_files %% set_names(basename(.)) %% map_dfr(~ read.table(.x, header TRUE, sep \t, skip 1), .id file) # 假设需要提取每年产量并按情景汇总 summary_results - all_results %% filter(!is.na(yield)) %% group_by(file) %% summarise( avg_yield mean(yield, na.rm TRUE), sd_yield sd(yield, na.rm TRUE), avg_biomass mean(biomass, na.rm TRUE), avg_n_leach mean(n_leach, na.rm TRUE) )注意读取 .out 文件时APSIM 默认在列名之前可能有一行关于版本和单位的注释所以读取时要根据实际情况设置skip参数。否则会把表头读错提取变量名时很容易出错。还有一种更稳健的读取方式先readLines()探查文件的前几行再决定从第几行开始读表头。5.4 参数敏感性分析与情景对比参数敏感性分析是模型应用的重头戏。简单的方法是“一次一个参数”扫描One-At-a-Time, OAT。将某个参数从低到高设置若干个水平其他参数保持不变运行模拟观察目标变量的变化。以播种密度为例density_levels - c(5, 10, 15, 20, 25, 30) # 单位株/m² results_list - list() for (j in seq_along(density_levels)) { temp_file - paste0(density_, j, .apsimx) file.copy(base_file, temp_file) sim_text - readLines(temp_file, warn FALSE) sim_text - str_replace_all(sim_text, pattern sowing_density.*?;, replacement paste0(sowing_density, density_levels[j], ;)) writeLines(sim_text, temp_file) run_apsim(temp_file) out_file - sub(.apsimx, .out, temp_file) df_out - read.table(out_file, header TRUE, sep \t, skip 1) results_list[[j]] - tibble( density density_levels[j], yield mean(df_out$yield, na.rm TRUE), biomass mean(df_out$biomass, na.rm TRUE) ) } results_df - bind_rows(results_list)跑完之后可以直接画出产量对密度的响应曲线看看是否存在最优密度区间。这种分析在制定区域种植方案时非常实用也能帮你发现模型中参数之间潜在的交互效应。5.5 一个包含完整流程的实操案例这里给一个简化的完整案例把前面的内容串起来。假设我们要研究同一品种小麦在某个站点不同播期和不同施氮水平下的产量差异。流程分四步准备基础 .apsimx 模板 → 修改气象文件路径 → 批量生成情景文件 → 批量运行并汇总结果。基础模板可以直接用官方小麦示例然后将气象文件替换成我们自己生成的 site.met见第 2 节再把土壤剖面参数换成目标站点附近的参考值。之后就可以用前面提到的循环代码批量跑了。跑完 9 个情景3 个播期 x 3 个施氮量汇总结果后你就能画出类似“播期—施氮—产量”的等值线图或者分组柱状图。这种图拿到文章里或者给决策者看都很有说服力。6. 实操中踩过的坑常见问题与排查实录最后这部分把我这几年用 APSIM 遇到过的高频问题和解决方法整理成清单给各位做个参考。6.1 常见报错与解决方案现象可能原因解决办法模拟直接崩溃日志提示找不到 .met 文件相对路径不对或气象文件头部格式有误检查 .apsimx 中气象文件路径用绝对路径检查 .met 头部字段模拟直接崩溃提示日期格式错误气象数据时间不连续或播种日期超出模拟期用 R 做时间序列校验确保逐日连续检查模拟起止日期作物产量长期偏低初始土壤无机氮过低或残茬固定氮太强提高初始氮量调整残茬 C:N 比检查施肥时间和用量土壤水分模拟长期偏干土壤 DUL 和 LL15 参数不合理或 KS 太大对比实测墒情标定土壤物理参数NG 版本打开 .apsim 文件报错版本转换不完全或引用了经典版独有模块在 UI 中逐个模块核对必要时重建模型批量运行时部分 .out 文件没有生成单个模拟运行失败可能因为初始参数导致模型异常添加日志输出逐个排查运行后检查 .out 文件是否存在R 读 .out 文件时变量名对不上skip 参数设置不对或 APSIM 版本更新后表头结构变化先读几行内容查看实际结构再调整 skip6.2 气象数据质量坑再强调我在第 2 节说了一部分但这里还想再单独强调。气象数据是模型的第一道关卡很多人模拟结果乱飞最后发现其实是气象数据里有几个极端异常值没有清掉。比如一次降水记录写成 999.9这种错误如果不处理模型里模拟的径流和深层渗漏就会异常作物水分胁迫也会错乱。比较推荐的做法是在任何情景分析之前先做一次全模拟期的数据质量报告。用 R 把逐日气象数据的范围、均值、缺失比例、异常值数量都打出来。6.3 调试技巧与日志分析方法模拟失败时APSIM 一般会输出日志信息。NG 版本的日志比经典版详细一些会具体到某个模块、某个变量、甚至某个时间步长。遇到问题时我习惯先看三个方面报错信息发生在哪个模块。是气象读取还是作物模块还是土壤氮模块。模块不同排查方向完全不同。报错时模拟进行到了哪一天。这非常有用。比如如果模拟到第 50 天时报错可以回看气象文件第 50 天左右的数据十有八九就是异常值。输出文件里的关键变量是否出现极端跳变。如果微生物量碳一夜之间暴涨或者土壤含水量变成负数基本可以锁定是数值计算不稳定通常和初始条件或参数有关。6.4 批量模拟的稳健性设计批量跑几十上百个模拟时最怕的是有一个情景失败导致整个流程中断。我一般会在 R 里做两层防护第一层运行前用文件路径校验函数确认所有输入文件都存在参数替换后做一次简单的文本拼写检查。第二层运行时先把所有情景的文件生成好再逐个运行而不是生成一个运行一个这样即使中间出问题也能知道哪些尚未运行。另外批量运行会占用不少 CPU 时间如果你的机器支持并行可以用 R 的parallel或furrr包来加速。不过 APSIM 命令行本身可能不支持多线程共享同一个临时目录并行时要格外注意文件读写冲突。我通常把每个情景放在独立的工作目录里再并行调用这样可以避开大部分问题。最后再分享一个小技巧模拟做完之后强烈建议大家把模拟配置、输入文件、R 处理代码放到同一个项目目录并用脚本一次性重建整个模拟流程。这样以后要复现结果、改参数重新跑或者写方法学部分都不用翻箱倒柜找文件。我这两年做试验站模拟时几乎每个站都会建一个这样的 R 脚本里面从气象数据清洗、模型文件生成、批量运行到结果汇总全部一键跑完。一开始建脚本确实费点时间但后面每次更新气象数据、调整参数效率高得不是一点半点。这个思路也推荐给各位。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价