武理排水管网模拟分析系统应用专题5:模型克隆与并行计算

项目的实现类projectClass可以通过构造函数实现模型的深度拷贝(克隆),从而可以在内存中实现模型的复制、修改参数、并行计算。这个特点对于将SWMM模型纳入各种优化算法的计算过程十分有意义。

1 案例项目内容

本专题对应的开发案例为\software\tutorial\exp_swmmcpp_clone文件夹中的内容,其中SWMMCPP_clone子文件夹为VS2022 C++项目内容, swmm_network子文件夹为管网模型数据,即network.inp文件。建议按照本文内容自己新建项目,编写代码以便通过练习掌握"武理排水管网模拟分析系统"相关使用方法。按照专题1内容在\software\tutorial\exp_swmmcpp_clone文件夹中新建项目,并添加头文件及库文件。对于新建项目的:配置属性->常规->输出目录设置为:
"$(SolutionDir)$(Platform)\$(Configuration)\"

这样可执行文件会生成于\software\tutorial\x64\Debug文件夹下面,将\software\bin文件夹中内容全部拷贝至Debug文件夹,可以直接编译运行案例项目,方便统一进行调试运行。

2 路径处理相关函数

在main.cpp文件的最上面中添加路径处理相关函数,由于本案例会采用接口的实现类projectClass,所以需要添加projectClass.h

c 复制代码
#include <windows.h>
#include <filesystem>
#include <shlwapi.h>
#include <thread>
// TODO:  在此处引用程序需要的其他头文件
#include "swmm_cs.h"
#include "projectClass.h"
#pragma comment(lib, "Shlwapi.lib")
std::string GetExecutablePath()
{
	std::vector<char> buffer(MAX_PATH);
	DWORD len = GetModuleFileNameA(NULL, buffer.data(), MAX_PATH);
	if (len == 0 || len == MAX_PATH) {
		// 缓冲区不够,动态扩容
		while (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
			buffer.resize(buffer.size() * 2);
			len = GetModuleFileNameA(NULL, buffer.data(), buffer.size());
		}
	}
	return std::string(buffer.data(), len);
}
// 获取 exe 所在目录
std::string GetExecutableDirectory()
{
	std::string exePath = GetExecutablePath();
	char dir[MAX_PATH];
	lstrcpyA(dir, exePath.c_str());
	PathRemoveFileSpecA(dir);  // 去掉文件名,留下目录
	return std::string(dir);
}

3 projectClass实现模型克隆

本案例利用SwmmProjectClone函数实现projectClass的深度拷贝,并利用多线程对8个swmm模型进行同时计算,可以实现多个线程同时计算多个模型,可以使用projectClass相应的参数修改功能,实现不同模型参数设置情况下的多个模型的同时计算,本案例没有修改模型参数,仅仅实现了8个相同的模型同时计算。

c 复制代码
int SWMM_clone(std::string inpFilePath, std::string rptFilePath, std::string outFilePath)
{
	int i = 0;
	int ErrorCode = 0;
	int Nthread = 8;
	//线程初始化 
	std::vector<std::thread> trds;
	trds.reserve(Nthread);
	std::vector<projectClass*> pswmmMP = std::vector<projectClass*>(Nthread, nullptr);
	//std::thread** trds = new std::thread * [Nthread - 1];//这是新建线程,另外一个线程是主线程不需要新建
	//SWMMCPP::projectClass** pswmmMP = new SWMMCPP::projectClass * [Nthread];
	//初始化第一个元素,也可以使用 pswmmMP[0] = new projectClass();进行初始化
	if (GetSwmmSimulation((void**)&pswmmMP[0]) != 0)
	{
		printf("create projectClass instance failed!");
		return 1;
	}
	//对第一个pswmmMP数组元素进行赋值
	ErrorCode = pswmmMP[0]->swmm_open((char*)inpFilePath.data(),
		(char*)rptFilePath.data(), (char*)outFilePath.data());
	if (ErrorCode != 0)
	{
		ReleaseSwmmSimulation((void*&)pswmmMP[0]);
		printf("swmm_open failed");
		return 1;
	}
	//利用第一个元素初始化后面的元素
	for (i = 1; i < Nthread; ++i)
	{
		//对report,out文件进行重命名
		int strLen, insertPos;
		std::string rptFileName = pswmmMP[0]->Frpt.m_name;
		std::string outFileName = pswmmMP[0]->Fout.m_name;
		strLen = rptFileName.length();
		insertPos = strLen - 4;
		rptFileName.insert(insertPos, std::to_string(i));
		strLen = outFileName.length();
		insertPos = strLen - 4;
		outFileName.insert(insertPos, std::to_string(i));
		//通过深度拷贝为pswmmMP中的其他模型进行初始化
		if (SwmmProjectClone(pswmmMP[0], (void**)&pswmmMP[i], rptFileName.data(), outFileName.data()) == 0)
			printf("the %dth swmm project have been cloned successfully\n", i);
	}
	//对模型的参数进行更新后,可以对pswmmMP中的模型进行多线程,并行模拟,这里没有修改任何参数,只演示如何并行计算
		//新建线程计算
	for (i = 0; i < Nthread; ++i)
	{
		//新建线程,并启动计算,由于新建线程中调用的是projectClass类中的函数(第一个参数),
		//所以这里还需要传递一个类对象,因为类中的函数存在一个默认参数,就是对象本身this,
		//所以这里要将对象传递进去(第二个参数)
		//swmm_run2函数不会向硬盘写入结果
		trds.emplace_back(&SWMMCPP::projectClass::swmm_run2, pswmmMP[i]);
		printf("the %dth swmm project have started computation successfully\n", i);
	}
	printf("%d swmm projects are computing,wait please...\n", Nthread);

	// 等待所有线程结束
	for (auto& t : trds)
	{
		if (t.joinable())
		{
			t.join();
		}
	}
	//如果需要将计算结果写入硬盘需要调用end函数
	for (i = 0; i < Nthread; ++i)
	{
		pswmmMP[i]->swmm_end();
		pswmmMP[i]->swmm_close();
		ReleaseSwmmSimulation((void*&)pswmmMP[i]);
		printf("%d swmm project have released successfully\n", i);
	}
	return 0;
}

4 编译运行

编译后运行结果如下

相关推荐
cike_y2 小时前
Spring-Bean的作用域&Bean的自动装配
java·开发语言·数据库·spring
stella·2 小时前
mysql的时区问题
数据库·mysql·timezone·时区
谈笑也风生2 小时前
经典算法题型之排序算法(三)
java·算法·排序算法
OliverH-yishuihan3 小时前
在win10上借助WSL用VS2019开发跨平台项目实例
linux·c++·windows
汉克老师3 小时前
GESP2025年12月认证C++二级真题与解析(编程题1 (环保能量球))
c++·gesp二级·gesp2级
+VX:Fegn08953 小时前
计算机毕业设计|基于springboot + vueOA工程项目管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计
郝学胜-神的一滴3 小时前
Linux进程与线程控制原语对比:双刃出鞘,各显锋芒
linux·服务器·开发语言·数据结构·c++·程序人生
wang6021252184 小时前
阿里云存储的下载验证
数据库·阿里云·fastapi
大佬,救命!!!4 小时前
对算子shape相关的属性值自动化处理
python·算法·自动化·学习笔记·算子·用例脚本·算子形状