-
henry authoredac37ed45
Pstream.C 6.56 KiB
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "Pstream.H"
#include "debug.H"
#include "dictionary.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
defineTypeNameAndDebug(Foam::Pstream, 0);
template<>
const char* Foam::NamedEnum<Foam::Pstream::commsTypes, 3>::names[] =
{
"blocking",
"scheduled",
"nonBlocking"
};
const Foam::NamedEnum<Foam::Pstream::commsTypes, 3>
Foam::Pstream::commsTypeNames;
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::Pstream::setParRun()
{
parRun_ = true;
Pout.prefix() = '[' + name(myProcNo()) + "] ";
Perr.prefix() = '[' + name(myProcNo()) + "] ";
}
void Foam::Pstream::calcLinearComm(const label nProcs)
{
linearCommunication_.setSize(nProcs);
// Master
labelList belowIDs(nProcs - 1);
forAll(belowIDs, i)
{
belowIDs[i] = i + 1;
}
linearCommunication_[0] = commsStruct
(
nProcs,
0,
-1,
belowIDs,
labelList(0)
);
// Slaves. Have no below processors, only communicate up to master
for (label procID = 1; procID < nProcs; procID++)
{
linearCommunication_[procID] = commsStruct
(
nProcs,
procID,
0,
labelList(0),
labelList(0)
);
}
}
// Append my children (and my children children etc.) to allReceives.
void Foam::Pstream::collectReceives
(
const label procID,
const List<DynamicList<label> >& receives,
DynamicList<label>& allReceives
)
{
const DynamicList<label>& myChildren = receives[procID];
forAll(myChildren, childI)
{
allReceives.append(myChildren[childI]);
collectReceives(myChildren[childI], receives, allReceives);
}
}
// Tree like schedule. For 8 procs:
// (level 0)
// 0 receives from 1
// 2 receives from 3
// 4 receives from 5
// 6 receives from 7
// (level 1)
// 0 receives from 2
// 4 receives from 6
// (level 2)
// 0 receives from 4
//
// The sends/receives for all levels are collected per processor (one send per
// processor; multiple receives possible) creating a table:
//
// So per processor:
// proc receives from sends to
// ---- ------------- --------
// 0 1,2,4 -
// 1 - 0
// 2 3 0
// 3 - 2
// 4 5 0
// 5 - 4
// 6 7 4
// 7 - 6
void Foam::Pstream::calcTreeComm(label nProcs)
{
label nLevels = 1;
while ((1 << nLevels) < nProcs)
{
nLevels++;
}
List<DynamicList<label> > receives(nProcs);
labelList sends(nProcs, -1);
// Info<< "Using " << nLevels << " communication levels" << endl;
label offset = 2;
label childOffset = offset/2;
for (label level = 0; level < nLevels; level++)
{
label receiveID = 0;
while (receiveID < nProcs)
{
// Determine processor that sends and we receive from
label sendID = receiveID + childOffset;
if (sendID < nProcs)
{
receives[receiveID].append(sendID);
sends[sendID] = receiveID;
}
receiveID += offset;
}
offset <<= 1;
childOffset <<= 1;
}
// For all processors find the processors it receives data from
// (and the processors they receive data from etc.)
List<DynamicList<label> > allReceives(nProcs);
for (label procID = 0; procID < nProcs; procID++)
{
collectReceives(procID, receives, allReceives[procID]);
}
treeCommunication_.setSize(nProcs);
for (label procID = 0; procID < nProcs; procID++)
{
treeCommunication_[procID] = commsStruct
(
nProcs,
procID,
sends[procID],
receives[procID].shrink(),
allReceives[procID].shrink()
);
}
}
// Callback from Pstream::init() : initialize linear and tree communication
// schedules now that nProcs is known.
void Foam::Pstream::initCommunicationSchedule()
{
calcLinearComm(nProcs());
calcTreeComm(nProcs());
}
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
// Initialise my process number to 0 (the master)
int Foam::Pstream::myProcNo_(0);
// By default this is not a parallel run
bool Foam::Pstream::parRun_(false);
// List of process IDs
Foam::List<int> Foam::Pstream::procIDs_(1, 0);
// Standard transfer message type
const int Foam::Pstream::msgType_(1);
// Linear communication schedule
Foam::List<Foam::Pstream::commsStruct> Foam::Pstream::linearCommunication_(0);
// Multi level communication schedule
Foam::List<Foam::Pstream::commsStruct> Foam::Pstream::treeCommunication_(0);
// Should compact transfer be used in which floats replace doubles
// reducing the bandwidth requirement at the expense of some loss
// in accuracy
bool Foam::Pstream::floatTransfer
(
debug::optimisationSwitch("floatTransfer", 0)
);
// Number of processors at which the reduce algorithm changes from linear to
// tree
int Foam::Pstream::nProcsSimpleSum
(
debug::optimisationSwitch("nProcsSimpleSum", 16)
);
// Default commsType
Foam::Pstream::commsTypes Foam::Pstream::defaultCommsType
(
commsTypeNames.read(debug::optimisationSwitches().lookup("commsType"))
);
// ************************************************************************* //