写在最前面:作为一个有点菜的学生(一把年纪,真是颇为羞愧),计算机基础也好,水文模型软件也好,这篇里面确实可能会有点理解的各种不到位,也许确是走了不少大佬们看起来的弯路,甚至有很多不知道原理但是莫名其妙就跑起来了的状况,也腆着脸写上去了(轻拍勿笑,欢迎评论区提出改善的意见和建议XD)。
不过作为一个小白,这几天摸索中的磕磕碰碰以及同样搜寻到很多大佬的经验贴把我从泥潭中拉出来的救急救命,也让我觉得,分享自己的一点拙见和经验(主要是整合其他大佬的相关经验贴),也许是一种攒人品(希望能早日毕业!)的薪火相传,也许能像大佬们帮助我一样,为同方向的同学们带来一些并非孤身一人的伴随感。而且还是怕自己下次再用这个又忘了,所以也给自己各备份hh。
毕竟相关的中文经验贴不多,虽然这篇里很多浅显错漏,也****希望会对大家的研究有点帮助吧~
这一篇先写到运行成功example.m吧,后续一段时间还会继续上自己的数据进行摸索研究
欸,希望后续也能成功吧,不过万一到时候发现失败了怎么办…希望大家帮我祈祷成功
( ˇωˇ)人
到时候再把新的心路历程分享给大家~
0. MatSWMM是什么?有什么用处?
如果你眼馋别人的SWMM参数自动率定,疲惫于玄学的手工调参,但自己编程苦手计算机基础薄弱,只浅显了解过matlab。
那么MatSWMM就是可以实现用matlab(!)修改SWMM的input文件里的参数,用matlab(!)提取output文件的结果,那么由此可推,也就是后续有可能进一步编程批量修改和提取,从而进一步进行各种研究,实现批量处理SWMM输入输出,默默节省你手工的你的田螺姑娘。
具体介绍的原文和原模型,参考以下链接:
对MatSWMM模型论文的中文简介
英文论文原文
经常容易断线的github上的MatSWMM程序及说明
MatSWMM除可以使用Matlab调用SWMM外,还可以使用python、LabView等其他方式调用,笔者不太懂,就对其他方法不深入分析了。
根据笔者的肤浅简易理解,大概就是Matlab有可以调用其他软件的接口方式,SWMM也有开放的接口代码,于是通过C++编程,可以生成.dll脚本文件及.h头文件,使得matlab可以调用SWMM的功能。这就是MatSWMM的基本原理。参考以下链接:
大概可以看这个理解一下什么是dll,不过看不懂也不影响我们使用
关于matlab调用dll?
那么,在大概的理解了MatSWMM的使用目的和基本原理之后,让我们来开始看看怎么能让MatSWMM跑起来吧。
1. 搞到和安装MatSWMM?
对于swmm原来的本体,原模型好像没有说要不要安装,但是保险起见,既然找到MatSWMM了,SWMM想必各位也都早已安装了罢。毕竟主要还得靠swmm生成inp文件什么的。
MatSWMM不是一个商业化的程序,(当然也是免费的)所以没有常见的setup.exe傻瓜一键安装程序,第一次接触可能有是点懵的,
总之第一步是去下载好全部代码(我也也不清楚是否可以只下载需要的那部分,但是保险起见,全下载下来好了)。链接如下:
经常容易断线的github官方作者上传的代码
github可能会经常刷不出来,解决方法如下:
一个体验后感觉有点玄学的解决总断线下载难的方法
点击 Download ZIP那里进行打包下载
或者我也上传了一份,以备大家急用。不过还是推荐去github上支持原作者哈。MatSWMM代码包,利用该程序可使用Matlab调用SWMM(也包含python、Labview调用部分)-数据集文档类资源-CSDN文库
对于matlab部分,本人使用的是学校正版软件平台上的Matlab R2022a和学校那边的授权,旧版本或者其他版本可行性未知,参考原作者发文日期是2016年,可能使用2016年以后发布的版本会比较稳妥。
2.下载完的这些代码文件怎么处理?
参考README.md里面的说明
009和012的区别不是很懂,总之是从009的文件夹下面的SWMM matlab文件夹中,找到swmm5.dll和swmm5.h,
把swmm5.dll 和swmm5.h都复制好放在matlab当前工作目录里。
当前工作目录是什么?如果不太会设置,可以直接输入代码,查询工作目录
pwd
会输出蹦出来一个文件夹,那么就直接放在这个文件夹下面,如图。
(右边查询出来的文件夹正是左边的这个,那么就把它俩直接这样塞进去就好)
其他的文件,不是确定是否必须也放在当前工作目录里,但是保险起见,我是也放在这个目录下面了,反正也不大嘛。
放好了之后,我决定使用文件里的example.m 测试一下是否安装成功,于是用记事本打开,看一下代码的含义,决定先测前面的两个命令。
%% INITIALIZE SWMM(应该是初始化SWMM的意思)
inp = 'swmm_files/redchicosur_gates.INP'; %命名测试文件路径为inp
swmm = SWMM; %大概是载入SWMM这个脚本?
%% RETRIEVING VARIABLE IDs FROM THE .INP(从INP类型的文件里,提取link和node的ID)
links = swmm.get_all(inp, swmm.LINK, swmm.NONE); %提取link
nodes = swmm.get_all(inp, swmm.NODE, swmm.NONE); %提取node
果不其然,第一次的时候,各种bug会纷纷出现。
3. 错误使用loadlibrary?
如果之前没有C++什么编译基础,也是头一次使用调用函数什么的,应该一运行就会报错,matlab会提示下载MinGW64编译器
这时候需要打开 附加功能,搜索MinGW
就是下载这个。点击进去,会有很明确的下载键,点击就ok啦。但是——
注意1!关键的来了,点击下载之前,各位还在大学里挣扎的朋友们!先断开你的校园网,把网络切换成热点或者别的什么wifi,否则它就会速度极慢地根本下不下来!(不知道为什么……但是感谢Dinephy这位大佬的这一拯救方法,确实好使。
(31条消息) MATLAB附件功能模块下载安装失败解决方案_Dinephy的博客-CSDN博客_matlab附加功能安装程序出现了异常情况
#注意2,下载好后好像还得重启一遍才不会再报这个错误。
4. 无法找到文件/没有权限
可能性1.:输入了错误的文件夹地址和名称
MatSWMM里的example.m,引用位置是固定的
但是这可能不是你实际放置这个文件的真正位置,因此在使用时,注意检查这个文件真实的文件名称和存放地址。存放地址从当前工作目录的下一级开始写,且存放地址不能是工作目录以外的文件夹。
如,现在工作目录为'C:\Users\Patricia Feng\Documents\MATLAB',
笔者为了方便测试,直接将这一文件放在了当前工作目录里。
则文件实际地址为'C:\Users\Patricia Feng\Documents\MATLAB\RedChicoSur_Gates.INP'
那么奔着从当前工作目录下一级开始写的原则,直接写
inp='RedChicoSur_Gates.INP'
即可成功。
如果不确定地址否输入正确,可以用exist函数查询文件是否存在。
exist('RedChicoSur_Gates.INP', 'file')
括号里的第一项为文件地址(笔者是因为直接放在工作目录下所以看起来只有文件名,实际这里要写地址\文件名格式),第二项写’file‘这个单词就可以。
如果返回值为0,则说明这一文件夹地址没有这一名称的文件,注意检查拼写或者实际地址。
如果返回值为2,则说明地址和文件名都没有问题,那么考虑第二种可能。
可能性2:没有权限
反复检查确认没有问题后,如果还是这样报错,应该就是权限的问题。笔者不太了解这一部分如何设置权限,但是最稳妥的方式重开Matlab,直接使用“**以管理员身份打开**”这一选择,基本会规避掉这个问题。
4.2. 好久没用,再用的时候突然报错,错误使用callib,参数不能转换成字符向量
试图自动生成批量的inp文件,轮流跑进SWMM运行,结果出了这个问题……
那么是为什么呢?
答案就是利用strcat生成的连接文件夹名和文件名的字符向量,是string型,也就是用双引号包起来的字符向量。!但是MatSWMM的文件名需要是单引号引起来的!是char型。
所以需要用char函数把它转换一下哦
5. 基本上bug都被处理完了,可以成功运行了!
现在让我们再来尝试一下运行:
可以看到工作区已经成功地提取到了link和node的id,点开这两个cell,可以看到
基本上就是比较成功啦。
那么继续运行后续的部分
%% RUNNING A SWMM SIMULATION %调用SWMM进行模拟
[e, d] = swmm.run_simulation(inp); %使用inp这个路径的文件inp进行模拟(上一段代码中一定赋值为'RedChicoSur_Gates.INP'
%% RETRIEVING INFORMATION %获取信息
fprintf('Total flooding = %.3f m3\n', swmm.total_flooding); %计算总flooding,以立方米为单位输出
[time, fn5] = swmm.read_results(links, swmm.LINK, swmm.VOLUME);
plot(time, fn5); %画了图
disp('MatSWMM is awesome! isn it?'); %嗯,原模型作者决定皮一下(笑)
可以看到总flooding可以显示出来了,同时,
6. 来看看我们得到了什么!
matswmm里可以调用的函数及其意义和用法,在原模型页面的functionalities这个链接里可以查看
[e, d] = swmm.run_simulation(inp);
% p: path to the input file % e: vector of errors % e(1) run-off | e(2) flow rounting | e(3) water quality % d: duration in seconds of the simulation
%输出向量e,储存了误差(也许是连续性误差?),一共有三个值,依次是地表径流、流量演算和水质的误差
%(这里应该是inp中没有模拟水质,因此为0了)
%%输出向量d,储存了模拟时间
可以在工作区看到这些值都不大,模拟的还是可以接受的。
fprintf('Total flooding = %.3f m3\n', swmm.total_flooding);
%f: total flooding [m^3/s]
%这个应该就是出口的总流量
%fprintf是控制输出格式的函数,
% "%.3f" 控制输出格式为float(浮点,用f表示),并保留3位小数
% "\n" 控制新起一行
这一段完全就是输出flooding了。
[time, fn5] = swmm.read_results(links, swmm.LINK, swmm.VOLUME);
plot(time, fn5);
% swmm.read_results 用来读取生成的results的具体参数,node和link等的控制有所不同
% 右侧括号中第一个参数为id: IDs of the objects,在上一段获取id中,已经为link这个变量赋值为含有所有link id的cell数组了
% 右侧括号中第二个参数为type,这里选link
% 右侧括号中第三个参数为 attr: constant related to the attribute of the requested object,跟第二个参数相关,表明想要获取对应type的什么参数,这里选择link的VOLUME(流速)
% 左侧中括号第一个输出为t: vector with time in hours ,即时间
% 左侧中括号第一二输出为val: vector with the requested data,即t时间对应的所选参数值,VOLUME流速。
%最后使用plot,画出所有link中,流速与时间的对应关系
那么可以看到,通过这样简短的代码,我们可以很快地且简单地仅控制输入matlab代码,获取指定管道/节点的流量、流速等信息,并直接在matlab里作图。
而且通过查阅functionalities,我们发现这个程序里的关键函数
可以看到MatSwmm是存在批量改变参数的可能的。
很有胜利的曙光啊!
未来可期~
版权归原作者 叶不伤 所有, 如有侵权,请联系我们删除。