openfoam/applications/test/gatherValues1/Test-gatherValues1.cxx
Mark Olesen 9ad3754ed7 ENH: remove obsolete Pstream functions (#3087)
- the old Pstream::scatter routines (which were largely a misnomer)
  have been superseded by various broadcast routines, but were left in
  the code with #ifndef/#ifdef Foam_Pstream_scatter_nobroadcast
  guards. Now noisily deprecate them, and remove the old manual tree
  communication in favour of MPI broadcast and/or
  serialize/de-serialize with wrapped Pstream::broadcast

- consolidate various gather methods to include the communication
  structure directly. No functional change, but reduces the number of
  methods.

ENH: add parallel guard to UPstream::whichCommunication() method

- returns List::null() as the schedule for non-parallel instead
  of an inappropriate linear or tree schedule

ENH: Pstream::listGatherValues, Pstream::listScatterValues

- like the existing UPstream versions but supporting non-contiguous
2024-02-01 13:52:39 +00:00

250 lines
6.8 KiB
C++

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
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 3 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, see <http://www.gnu.org/licenses/>.
Application
Test-gatherValues1
Description
Test list gather functionality
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Time.H"
#include "IPstream.H"
#include "OPstream.H"
#include "vector.H"
#include "IOstreams.H"
#include "Pstream.H"
#include "globalIndex.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
argList::noCheckProcessorDirectories();
#include "setRootCase.H"
const labelList localValues
(
identity(2 *(UPstream::myProcNo()+1), -5*UPstream::myProcNo())
);
// Test resize
{
globalIndex globIdx(localValues.size());
Info<< "globIdx = " << flatOutput(globIdx.offsets()) << nl;
globIdx.setLocalSize(4, 0);
Info<< "globIdx = " << flatOutput(globIdx.offsets()) << nl;
globIdx.setLocalSize(3, 0);
Info<< "globIdx = " << flatOutput(globIdx.offsets()) << nl;
}
// This now compiles (and works)
// - reverts to normal gather for non-contiguous
{
const wordList sendData({"hello", "world"});
// One-sided sizing! master only
const globalIndex allProcAddr
(
globalIndex::gatherOnly{},
sendData.size()
);
Pout<< "listGather sizes: " << flatOutput(allProcAddr.sizes()) << nl;
// Collect all values
wordList allValues
(
allProcAddr.mpiGather(sendData)
);
Pout<< "all-data: " << allValues << endl;
}
// Gather all values
{
const auto& sendData = localValues;
// One-sided sizing! master only
const globalIndex allProcAddr
(
globalIndex::gatherOnly{},
sendData.size()
);
Pout<< "listGather sizes: " << flatOutput(allProcAddr.sizes()) << nl;
// Collect all values
labelList allValues
(
allProcAddr.mpiGather(sendData)
);
Pout<< "all-data: " << allValues << endl;
}
{
const labelList::subList& sendData =
(
UPstream::master()
? SubList<label>(localValues, 0) // exclude
: SubList<label>(localValues)
);
const labelList sendSizes
(
UPstream::listGatherValues<label>(sendData.size())
);
const label sendSize
(
UPstream::listScatterValues<label>(sendSizes)
);
const globalIndex subProcAddr(globalIndex::gatherNone{}, sendSizes);
Pout<< "listGather "
<< localValues.size() << " = " << flatOutput(sendSizes)
<< " offsets " << flatOutput(subProcAddr.offsets())
<< nl;
label newLocalValue = 5 + UPstream::listScatterValues(sendSizes);
Pout<< "listScattered: " << newLocalValue << nl;
// Can also scatter a longer list
Pout<< "listScatter off "
<< UPstream::listScatterValues(subProcAddr.offsets()) << nl;
Pout<< endl << "local list [" << UPstream::myProcNo() << "] "
<< flatOutput(localValues) << nl;
Pout<< endl << "local send [" << UPstream::myProcNo() << "] "
<< sendSize << nl;
// Collect all off-processor values
labelList allValues
(
subProcAddr.mpiGather(sendData)
);
Pout<< "off-proc: " << allValues << endl;
if (UPstream::master())
{
Info<< "master: " << flatOutput(localValues) << nl;
label proci = 0;
for (const labelRange& range : subProcAddr)
{
Info<< proci << ": " << flatOutput(allValues.slice(range))
<< nl;
++proci;
}
Info<< nl << "verify ranges" << nl;
{
globalIndex glob;
Info<< "empty:" << nl;
for (const labelRange& range : glob)
{
Info<< " range: " << range << endl;
}
}
{
globalIndex glob(labelList(Foam::one{}, 0));
Info<< "degenerate:" << nl;
for (const labelRange& range : glob)
{
Info<< " range: " << range << endl;
}
}
{
globalIndex glob
(
globalIndex::gatherNone{},
labelList(Foam::one{}, 0)
);
Info<< "single:" << nl;
for (const labelRange& range : glob)
{
Info<< " range: " << range << endl;
}
}
}
}
// Non-contiguous gather - use Pstream, not UPstream!
{
typedef std::pair<label,vector> valueType;
valueType sendData(UPstream::myProcNo(), vector::one);
List<valueType> countValues
(
Pstream::listGatherValues(sendData)
);
Pout<< "listGather: " << flatOutput(countValues) << nl;
}
// Non-contiguous scatter - use Pstream, not UPstream!
{
List<fileName> allValues;
if (UPstream::master())
{
allValues.resize(UPstream::nProcs());
forAll(allValues, proci)
{
allValues[proci] = "processor" + Foam::name(proci);
}
}
fileName procName = Pstream::listScatterValues(allValues);
Pout<< "listScatter: " << procName << nl;
}
Info<< "\nEnd\n" << endl;
return 0;
}
// ************************************************************************* //