对于数值仿真而言,无论是商软或者开源软件,并行计算都是非常重要的,
作为一名仿真工程师,如果想把自身数值仿真能力提升一个层次,需要对并行计算有很好的理解与应用
openfoam并行通信主要通过Pstream类完成
Pstream类,类如其名,parallel_stream,并行计算时使用的信息流
Openfoam对其的介绍是:
Inter-processor communications stream.
处理器间交换信息流
类似的命名方法我们在c++文件读取时说过,std有fstream类读取写入文件/二进制文件,比如说我们要读取文件,会把读取内容放入缓存区内进行操作
#include <iostream>
#include <fstream> // ifstream类需要包含的头文件。
#include <string> // getline()函数需要包含的头文件。
using namespace std;
int main()
{
string filename = R"(./test.txt)";
//ifstream fin(filename, ios::in);
ifstream fin;
fin.open(filename , ios::in);
// 判断打开文件是否成功。
// 失败的原因主要有:1)目录不存在;2)文件不存在;3)没有权限,Linux平台下很常见。
if (fin.is_open() == false)
{
cout << "打开文件" << filename << "失败。\n"; return 0;
}
string buffer;
while (fin >> buffer)
{
cout << buffer << endl;
}
fin.close(); // 关闭文件,fin对象失效前会自动调用close()。
cout << "操作文件完成。\n";
}
类似的openfoam也有PstreamBuffers类进行并行通信缓冲
可以这样使用:
PstreamBuffers pBuffers(Pstream::commsTypes::nonBlocking);
for (label proci = 0; proci < Pstream::nProcs(); proci++)
{
if (proci != Pstream::myProcNo())
{
someObject vals;
UOPstream str(proci, pBuffers);
str << vals;
}
}
pBuffers.finishedSends(); // no-op for blocking
for (label proci = 0; proci < Pstream::nProcs(); proci++)
{
if (proci != Pstream::myProcNo())
{
UIPstream str(proci, pBuffers);
someObject vals(str);
}
}
上面这个程序可以看到,先后使用UOPstream与UIPstream进行缓冲区的文件输出与读取,这就很像ofstream类与ifstream类,甚至命名方式上都有几分相似,我们打开相应的继承关系图
二者分别服务于IPstream类与OPstream类,我们再打开今天文章的主角,Pstream类继承关系图
发现IPstream类与OPstream类是Pstream类的衍生类,Pstream类是其基础
打开Pstream类的源码:
点击查看代码
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class Pstream Declaration
\*---------------------------------------------------------------------------*/
class Pstream
:
public UPstream
{
protected:
// Protected data
//- Transfer buffer
DynamicList<char> buf_;
public:
// Declare name of the class and its debug switch
ClassName("Pstream");
// Constructors
//- Construct given optional buffer size
Pstream
(
const commsTypes commsType,
const label bufSize = 0
)
:
UPstream(commsType),
buf_(0)
{
if (bufSize)
{
buf_.setCapacity(bufSize + 2*sizeof(scalar) + 1);
}
}
// Gather and scatter
//- Gather data. Apply bop to combine Value
// from different processors
template<class T, class BinaryOp>
static void gather
(
const List<commsStruct>& comms,
T& Value,
const BinaryOp& bop,
const int tag,
const label comm
);
//- Like above but switches between linear/tree communication
template<class T, class BinaryOp>
static void gather
(
T& Value,
const BinaryOp& bop,
const int tag = Pstream::msgType(),
const label comm = Pstream::worldComm
);
//- Scatter data. Distribute without modification. Reverse of gather
template<class T>
static void scatter
(
const List<commsStruct>& comms,
T& Value,
const int tag,
const label comm
);
//- Like above but switches between linear/tree communication
template<class T>
static void scatter
(
T& Value,
const int tag = Pstream::msgType(),
const label comm = Pstream::worldComm
);
// Combine va