1. 从TxtInOut文件夹说起:SWAT跑起来之前的那道坎
很多人以为SWAT模型最难的环节在数据准备和参数率定,但真正让新手卡住动弹不得的,往往是点击"Run SWAT"之后那几秒——要么弹出一个看不懂的报错框,要么运行进度条走到一半直接闪退,要么看似跑完了但输出文件里全是零。我见过太多人在这里耗掉一整个下午,反复重装ArcSWAT、反复重建工程,最后发现只是一个路径里带了中文。
这一篇专门聊SWAT运行环节的实操细节和常见报错的排查思路。不涉及具体的率定调参方法,聚焦在"怎么让模型顺利跑完第一遍"这件事上。适合已经完成HRU划分、土地利用和土壤数据导入、气象数据加载,正准备点击运行按钮的读者。如果你连TxtInOut文件夹是什么都还没概念,建议先把前序步骤走完再来看这篇。
SWAT的运行机制本质上是一个"翻译加计算"的过程。ArcSWAT在ArcGIS界面里做的所有配置——划子流域、定义HRU、加载气象站——最终都会被翻译成一系列纯文本文件,统一存放在工程目录下的TxtInOut文件夹里。真正执行计算的是SWAT的可执行程序(swat.exe或swat_64.exe),它读取这些文本文件,按天或按小时逐步计算水文过程,最后把结果写到output.sub、output.hru、output.rch等文件中。理解这条链路,是排查所有运行报错的基础。
提示:每次点击Run SWAT之前,先打开TxtInOut文件夹看一眼文件是否齐全。正常情况下应该有file.cio、.sub、.hru、.sol、.mgt、.wgn等文件,数量与你的子流域和HRU数量对应。如果文件缺失,问题出在ArcSWAT写文件阶段,而不是SWAT计算阶段。
2. 运行前的环境自检:那些不检查就等着报错的项目
2.1 路径与文件名的"洁癖"要求
SWAT对文件路径的容忍度极低,这一点跟很多现代软件不一样。它底层用的是Fortran写的计算核心,对非ASCII字符的处理能力很有限。工程路径中如果出现中文字符、空格、特殊符号(如括号、井号、&),轻则报"file not found",重则直接崩溃且不给出任何提示。
我自己的习惯是在D盘或E盘根目录下建一个纯英文、无空格的文件夹,比如D:\SWAT_Projects\MyBasin,所有工程都放在这个目录下。不要放在桌面(路径里带Desktop没问题,但桌面路径通常很长且可能包含用户名中的中文),不要放在"我的文档"里(路径含中文),更不要放在OneDrive同步目录下(同步锁可能导致文件读写冲突)。
文件名同样有讲究。TxtInOut文件夹里的文件扩展名是SWAT约定的,不要手动改名。工程名(也就是.mdb文件的名字)也建议用英文,比如project.mdb,不要用项目.mdb。
2.2 气象数据文件的格式陷阱
气象数据是运行报错的高发区。SWAT要求气象数据以特定的文本格式提供,通常是通过ArcSWAT的"Write Input Tables"菜单下的"Weather Data Definition"工具导入的。导入时它会生成.pcp、.tmp、.slr、.hmd、.wnd等文件,存放在TxtInOut文件夹里。
常见的问题有三个。第一,气象站坐标与子流域不匹配。如果气象站的位置离你的流域太远,SWAT在插值时可能找不到有效的站点,导致降水为零。第二,数据缺测值处理不当。SWAT用-99表示缺测,如果你的原始数据里缺测值用的是-999或其他标记,导入后不会被识别,会被当成真实的负值参与计算,导致结果异常。第三,时间序列不连续。SWAT要求气象数据从模拟起始日期前一天开始提供,如果起始日期是1990年1月1日,气象数据必须从1989年12月31日开始。少这一天,SWAT会报"read error"。
2.3 时间步长与模拟周期的对齐
SWAT支持日尺度、月尺度和年尺度模拟,在file.cio中通过IPRINT和NBYR等参数控制。新手最容易犯的错误是模拟周期设置超出了气象数据的覆盖范围。比如气象数据只到2015年12月31日,但你在ArcSWAT里把模拟结束日期设成了2016年12月31日,SWAT跑到2016年1月1日就会发现没有气象数据可读,直接报错退出。
注意:在ArcSWAT的"Write SWAT Input Tables"对话框中设置模拟周期时,起始日期应该比气象数据的第一天晚至少一年(用于预热),结束日期不能超过气象数据的最后一天。预热期的概念后面会详细说。
3. 点击Run SWAT之后:常见报错逐条拆解
3.1 "forrtl: severe (29): file not found, unit 1, file ..."
这是SWAT运行中最常见的报错,没有之一。错误信息会告诉你具体是哪个文件找不到,比如file.cio、000010001.pcp之类的。排查思路分三步走。
第一步,确认报错中提到的文件名是否真的存在于TxtInOut文件夹中。如果不存在,说明ArcSWAT在写输入文件时出了问题。最常见的原因是HRU划分后没有重新写入输入表,或者工程路径变更后文件引用失效。解决办法是回到ArcSWAT界面,重新执行"Write Input Tables"下的所有写入操作,确保每一步都成功完成。
第二步,如果文件存在,检查文件名是否与file.cio中的引用一致。file.cio是SWAT的主控文件,里面列出了所有需要读取的输入文件及其路径。有时候ArcSWAT生成的file.cio中引用的文件名与实际文件名大小写不一致(比如引用了000010001.PCP但实际文件是000010001.pcp),在Windows下通常不区分大小写,但如果工程被拷贝到Linux服务器上运行就会出问题。
第三步,检查文件内容是否为空或格式错误。用文本编辑器打开报错的文件,看看是否有内容。如果文件是空的(0字节),说明写入过程被中断了,需要重新写入。
3.2 "forrtl: severe (64): input conversion error"
这个报错通常指向某个输入文件中的数值格式有问题。SWAT读取文本文件时对格式有一定要求,如果某个位置应该是数字但出现了字母或特殊符号,就会触发这个错误。
定位方法是看报错信息中提到的unit编号和文件名。比如unit 8, file 000010001.mgt,就去打开这个.mgt文件,检查里面的数值字段。常见的格式问题包括:数字中混入了逗号(如1,234应该写成1234)、科学计数法格式不被识别(如1.5E+03在某些版本中需要写成1.5e+03)、小数点后位数过多导致溢出。
我遇到过一次比较隐蔽的情况:土壤数据中的某个参数被Excel自动转换成了日期格式,导入后变成了####,SWAT读取时报input conversion error。解决办法是在Excel中把相关列预先设置为文本格式,再重新导入。
3.3 "forrtl: severe (24): end-of-file during read"
这个报错的意思是SWAT在读取某个文件时提前遇到了文件结尾,也就是说文件内容不完整。通常发生在气象数据文件上,比如.pcp文件中的降水数据行数少于模拟天数。
排查方法:打开报错涉及的.pcp文件,数一下数据行数是否等于模拟天数。如果模拟周期是1990年到2015年,共26年,按日尺度算应该有9497行数据(含闰年)。如果行数不够,说明气象数据导入时被截断了。可能的原因包括:原始数据文件中有空行、数据列数不一致、或者导入过程中程序崩溃。
解决办法是回到原始气象数据,检查数据完整性,确保每行都有完整的日期和数值,没有空行或注释行混在数据区。然后重新通过Weather Data Definition工具导入。
3.4 SWAT运行到一半闪退,没有任何报错信息
这种情况最让人头疼,因为没有任何线索。根据我的经验,闪退通常有以下几个原因。
内存不足。SWAT在处理大流域、多HRU时会消耗大量内存。如果你的流域有几千个HRU,模拟周期又很长,32位的swat.exe可能因为内存溢出而闪退。解决办法是换用64位版本(swat_64.exe),或者在ArcSWAT中减少HRU数量(通过调整土地利用和土壤的阈值)。
磁盘空间不足。SWAT运行过程中会生成大量输出文件,特别是如果设置了输出频率为日尺度,output.hru文件可能达到几个GB。检查一下TxtInOut所在磁盘的剩余空间。
杀毒软件拦截。某些杀毒软件会把swat.exe误判为可疑程序,在运行过程中强制终止。可以尝试把TxtInOut文件夹加入杀毒软件的白名单。
3.5 运行完成但输出全为零
这种情况比报错更隐蔽,因为程序确实跑完了,但结果没有意义。最常见的原因是气象数据没有被正确读取。SWAT在找不到有效气象数据时,会用默认值(通常是零)填充,导致整个水文过程为零。
排查方法:打开TxtInOut文件夹中的output.std文件(标准输出日志),查看里面的气象数据统计信息。如果看到"Precipitation: 0.00 mm"之类的记录,说明降水数据没有被读进去。回到气象数据定义环节,检查气象站坐标、数据文件路径、file.cio中的气象文件引用是否正确。
另一个可能的原因是模拟周期设置错误。如果模拟起始日期晚于结束日期,SWAT会直接跳过所有计算,输出全为零。检查file.cio中的NBYR、IYR、IDAF等参数。
4. 让SWAT稳定运行的几个实操习惯
4.1 分步运行,不要一步到位
ArcSWAT的界面设计是线性的:划子流域、定义HRU、写入输入表、运行SWAT。很多人习惯把所有步骤做完再点运行,一旦报错就不知道问题出在哪一步。我的建议是分步验证。
完成子流域划分后,先检查ArcSWAT生成的流域边界和河网是否合理。完成HRU定义后,打开TxtInOut文件夹看看.hru文件的数量和内容是否正常。完成气象数据导入后,检查.pcp文件的行数和数值范围。每一步都确认无误后再进入下一步,这样报错时排查范围会小很多。
4.2 保留一份"干净"的TxtInOut备份
SWAT运行过程中会修改TxtInOut文件夹里的某些文件(比如file.cio中的一些标志位),如果运行失败需要重新运行,最好从一份干净的备份开始。我的做法是在第一次成功写入所有输入文件后,把整个TxtInOut文件夹复制一份,命名为TxtInOut_backup。之后每次重新运行前,先把备份复制回去,覆盖被修改过的文件。
4.3 善用output.std和checker工具
SWAT运行结束后,TxtInOut文件夹里会生成一个output.std文件,里面记录了运行过程中的关键信息,包括读取了哪些文件、模拟了多少天、各水文要素的统计值等。这个文件是排查"运行完成但结果异常"类问题的第一手资料。
另外,SWAT官方提供了一个checker工具(swat_check.exe),可以在正式运行前检查输入文件的格式和一致性。虽然它不能发现所有问题,但能拦截大部分格式错误。建议在第一次运行新工程时先用checker跑一遍。
4.4 模拟周期的预热期设置
SWAT在模拟初期,土壤含水量、地下水储量等状态变量是从默认值开始的,需要一段时间才能达到平衡。如果直接从模拟第一年就开始分析结果,前几年的数据往往不可靠。通常的做法是在模拟周期中设置一段预热期(warm-up period),比如模拟1990年到2015年,但只用1995年之后的结果做分析。
预热期的长度取决于流域特性。一般来说,小流域(几百平方公里以内)预热3到5年就够了,大流域可能需要10年以上。在ArcSWAT中设置模拟周期时,把起始日期提前几年即可,不需要额外操作。
5. 几个容易被忽略的细节问题
5.1 土地利用和土壤数据的投影匹配
ArcSWAT在划分HRU时,会把土地利用图和土壤图与子流域边界进行叠加。如果这些图层的投影不一致,叠加结果会出现偏移,导致某些子流域内没有有效的土地利用或土壤类型,HRU划分失败或生成异常的HRU。
检查方法:在ArcGIS中把所有相关图层加载进来,看看它们是否对齐。如果不一致,用Project工具统一投影。SWAT通常要求使用投影坐标系(如UTM),不要用地理坐标系(经纬度)。
5.2 气象站数量与分布
SWAT支持多个气象站,通过泰森多边形或反距离权重法进行插值。如果流域内只有一个气象站,且该站位于流域边缘,插值结果可能不能代表整个流域。建议至少使用3个气象站,且分布相对均匀。
如果实在找不到足够的气象站,可以考虑使用SWAT内置的天气发生器(Weather Generator)。它可以根据长期统计参数生成日气象数据,虽然精度不如实测数据,但至少能让模型跑起来。
5.3 土壤数据库的完整性
SWAT需要土壤的物理和化学属性数据,包括土层厚度、容重、有效含水量、饱和导水率等。如果土壤数据库中某些字段缺失,SWAT会用默认值填充,可能导致水文过程模拟失真。
检查方法:打开TxtInOut文件夹中的.sol文件,看看每个土壤类型的参数是否完整。特别关注SOL_Z(土层深度)、SOL_AWC(有效含水量)、SOL_K(饱和导水率)这几个关键参数。如果发现大量零值或异常值,需要回到土壤数据库进行补充。
5.4 子流域划分的粒度选择
子流域划分的阈值直接影响HRU数量和模拟精度。阈值设得太小,子流域数量过多,HRU数量爆炸,运行速度极慢且容易内存不足。阈值设得太大,子流域数量太少,无法反映流域的空间异质性。
我的经验是:对于几百平方公里的小流域,子流域数量控制在20到50个之间比较合适。对于几千平方公里的大流域,可以放宽到100到200个。具体数值需要根据流域地形和研究目的调整,没有固定标准。
6. 当报错信息看不懂时怎么办
6.1 从output.std中找线索
SWAT的报错信息有时候很模糊,比如只告诉你"read error"但不说是哪个文件。这时候output.std文件就派上用场了。它记录了SWAT运行过程中的详细日志,包括每一步读取了哪个文件、读取了多少行、遇到了什么问题。打开output.std,从最后几行往前看,通常能找到报错发生前的最后一个成功操作,从而定位问题文件。
6.2 二分法排查
如果实在找不到问题所在,可以用二分法缩小范围。具体做法是:把模拟周期缩短到只有一年,看看是否能跑通。如果能跑通,说明问题出在某个特定时间段的数据上;如果还是报错,说明问题出在基础配置上。然后逐步增加模拟周期,直到报错出现,就能定位到具体是哪一年的数据有问题。
同样的思路也适用于HRU数量。先只保留一个子流域运行,如果能跑通,再逐步增加子流域数量。
6.3 社区和文档的力量
SWAT有一个非常活跃的用户社区,很多常见报错都能在论坛里找到答案。搜索时用报错信息中的关键词加上"SWAT"作为搜索词,通常能搜到相关的讨论帖。另外,SWAT官方文档(Theoretical Documentation和User Manual)虽然比较厚,但遇到问题时翻一翻相关章节,往往能找到参数设置的依据。
提示:在社区提问时,附上output.std文件的内容和报错截图,能大大提高获得有效回复的概率。不要只发一句"SWAT报错了怎么办",没有人能凭这句话帮你解决问题。
7. 跑通之后:结果文件的初步检查
模型跑通只是第一步,接下来要确认结果是否合理。TxtInOut文件夹里会生成几个关键输出文件:output.rch记录河道水文过程,output.sub记录子流域水文过程,output.hru记录HRU尺度的水文过程。用文本编辑器或Excel打开这些文件,重点看几个指标。
径流量是否在合理范围内。比如一个湿润地区的流域,年径流深可能在300到800毫米之间;干旱地区可能只有几十毫米。如果模拟出来的径流深是零或者几千毫米,说明有问题。
蒸散发与降水的比例是否合理。一般来说,蒸散发占降水的比例在40%到70%之间比较常见,具体取决于气候和植被。如果蒸散发接近零或超过降水,需要检查气象数据和植被参数。
泥沙输出是否合理。如果流域内有大量耕地,泥沙输出应该比较高;如果以林地为主,泥沙输出应该较低。如果泥沙输出为零或异常高,检查USLE方程相关参数。
这些初步检查不能替代正式的率定验证,但能帮你快速判断模型是否"跑对了方向"。如果初步检查就发现明显异常,就不用急着做率定了,先回去排查输入数据。
8. 一些个人踩坑记录
说几个我自己踩过的坑,希望能帮你省点时间。
有一次帮朋友跑一个南方小流域的SWAT模型,所有数据都准备好了,点击运行就闪退。折腾了两个小时,最后发现是他的工程路径里有一个空格——D:\SWAT Project\basin。把空格去掉改成D:\SWAT_Project\basin,问题解决。SWAT对空格的容忍度就是这么低。
还有一次,模型跑完了但径流量全是零。检查了气象数据、file.cio、HRU定义,都没问题。最后打开output.std一看,发现SWAT读取气象数据时报告"station out of basin"。原来是我在定义气象站时,坐标填的是经纬度,但流域的投影是UTM,导致气象站被判定在流域外。把气象站坐标转换成UTM后重新导入,问题解决。
最近一次比较有意思,一个学生跑模型时总是报"input conversion error",定位到.mgt文件。打开一看,里面有一行是1.5E+03,而SWAT这个版本只认小写的e。手动改成1.5e+03后正常运行。这种问题没有任何文档会写,只能靠经验积累。
SWAT这个模型就是这样,功能强大但脾气古怪。很多时候报错的原因跟水文本身无关,而是文件格式、路径命名、软件环境这些"非技术"因素。跑通第一遍之后,后面就顺了。