武理排水管网模拟分析系统应用专题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 编译运行

编译后运行结果如下

相关推荐
Bruce_kaizy18 小时前
c++ dfs搜索算法——剪枝
c++·深度优先·剪枝
源代码•宸18 小时前
Leetcode—3. 无重复字符的最长子串【中等】
经验分享·后端·算法·leetcode·面试·golang·string
汉堡go18 小时前
python_chapter6
前端·数据库·python
范纹杉想快点毕业18 小时前
嵌入式工程师一年制深度进阶学习计划(纯技术深耕版)
linux·运维·服务器·c语言·数据库·算法
-To be number.wan18 小时前
【数据结构真题解析】哈希表高级挑战:懒惰删除、探测链断裂与查找正确性陷阱
数据结构·算法·哈希算法
storyseek18 小时前
关于Milvus向量数据库的基础
数据库·milvus
CSDN_RTKLIB18 小时前
【std::string】find函数
c++·stl
历程里程碑18 小时前
哈希2:字母异位符分组
算法·leetcode·职场和发展
十五年专注C++开发18 小时前
浅谈CPU中的SIMD
c++·cpu·代码优化·simd
AI科技星18 小时前
统一场论理论下理解物体在不同运动状态的本质
人工智能·线性代数·算法·机器学习·概率论