Compare commits
6 Commits
develop.me
...
wip-update
| Author | SHA1 | Date | |
|---|---|---|---|
| 88477b66f0 | |||
| aaf921ba73 | |||
| 4918161d0c | |||
| f26b9c5a9f | |||
| 6582002ccc | |||
| 9bcef219a8 |
@ -92,21 +92,20 @@ void Foam::masterOFstream::commit()
|
|||||||
{
|
{
|
||||||
if (Pstream::parRun())
|
if (Pstream::parRun())
|
||||||
{
|
{
|
||||||
List<fileName> filePaths(Pstream::nProcs());
|
List<fileName> filePaths(Pstream::nProcs(comm_));
|
||||||
filePaths[Pstream::myProcNo()] = pathName_;
|
filePaths[Pstream::myProcNo(comm_)] = pathName_;
|
||||||
Pstream::gatherList(filePaths);
|
Pstream::gatherList(filePaths, UPstream::msgType(), comm_);
|
||||||
|
|
||||||
bool uniform =
|
bool uniform =
|
||||||
fileOperations::masterUncollatedFileOperation::uniformFile
|
(
|
||||||
(
|
Pstream::master(comm_) && fileOperation::uniformFile(filePaths)
|
||||||
filePaths
|
);
|
||||||
);
|
|
||||||
|
|
||||||
Pstream::broadcast(uniform);
|
Pstream::broadcast(uniform, comm_);
|
||||||
|
|
||||||
if (uniform)
|
if (uniform)
|
||||||
{
|
{
|
||||||
if (Pstream::master() && valid_)
|
if (Pstream::master(comm_) && valid_)
|
||||||
{
|
{
|
||||||
checkWrite(pathName_, this->str());
|
checkWrite(pathName_, this->str());
|
||||||
}
|
}
|
||||||
@ -115,13 +114,13 @@ void Foam::masterOFstream::commit()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolList procValid(UPstream::listGatherValues<bool>(valid_));
|
boolList procValid(UPstream::listGatherValues<bool>(valid_, comm_));
|
||||||
|
|
||||||
// Different files
|
// Different files
|
||||||
PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
|
PstreamBuffers pBufs(comm_, Pstream::commsTypes::nonBlocking);
|
||||||
|
|
||||||
// Send my buffer to master
|
// Send my buffer to master
|
||||||
if (!Pstream::master())
|
if (!Pstream::master(comm_))
|
||||||
{
|
{
|
||||||
UOPstream os(Pstream::masterNo(), pBufs);
|
UOPstream os(Pstream::masterNo(), pBufs);
|
||||||
string s(this->str());
|
string s(this->str());
|
||||||
@ -133,7 +132,7 @@ void Foam::masterOFstream::commit()
|
|||||||
labelList recvSizes;
|
labelList recvSizes;
|
||||||
pBufs.finishedGathers(recvSizes);
|
pBufs.finishedGathers(recvSizes);
|
||||||
|
|
||||||
if (Pstream::master())
|
if (Pstream::master(comm_))
|
||||||
{
|
{
|
||||||
// Write master data
|
// Write master data
|
||||||
if (procValid[Pstream::masterNo()])
|
if (procValid[Pstream::masterNo()])
|
||||||
@ -149,7 +148,7 @@ void Foam::masterOFstream::commit()
|
|||||||
*std::max_element(recvSizes.cbegin(), recvSizes.cend())
|
*std::max_element(recvSizes.cbegin(), recvSizes.cend())
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const int proci : Pstream::subProcs())
|
for (const int proci : Pstream::subProcs(comm_))
|
||||||
{
|
{
|
||||||
UIPstream is(proci, pBufs);
|
UIPstream is(proci, pBufs);
|
||||||
|
|
||||||
@ -179,6 +178,7 @@ void Foam::masterOFstream::commit()
|
|||||||
Foam::masterOFstream::masterOFstream
|
Foam::masterOFstream::masterOFstream
|
||||||
(
|
(
|
||||||
IOstreamOption::atomicType atomic,
|
IOstreamOption::atomicType atomic,
|
||||||
|
const label comm,
|
||||||
const fileName& pathName,
|
const fileName& pathName,
|
||||||
IOstreamOption streamOpt,
|
IOstreamOption streamOpt,
|
||||||
IOstreamOption::appendType append,
|
IOstreamOption::appendType append,
|
||||||
@ -190,7 +190,8 @@ Foam::masterOFstream::masterOFstream
|
|||||||
atomic_(atomic),
|
atomic_(atomic),
|
||||||
compression_(streamOpt.compression()),
|
compression_(streamOpt.compression()),
|
||||||
append_(append),
|
append_(append),
|
||||||
valid_(valid)
|
valid_(valid),
|
||||||
|
comm_(comm)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -30,6 +30,9 @@ Class
|
|||||||
Description
|
Description
|
||||||
Master-only drop-in replacement for OFstream.
|
Master-only drop-in replacement for OFstream.
|
||||||
|
|
||||||
|
Called on all processors (of the provided communicator). Sends files to
|
||||||
|
the master and writes them there.
|
||||||
|
|
||||||
SourceFiles
|
SourceFiles
|
||||||
masterOFstream.C
|
masterOFstream.C
|
||||||
|
|
||||||
@ -39,6 +42,7 @@ SourceFiles
|
|||||||
#define Foam_masterOFstream_H
|
#define Foam_masterOFstream_H
|
||||||
|
|
||||||
#include "StringStream.H"
|
#include "StringStream.H"
|
||||||
|
#include "UPstream.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -70,6 +74,9 @@ class masterOFstream
|
|||||||
//- Should file be written (on this processor)
|
//- Should file be written (on this processor)
|
||||||
const bool valid_;
|
const bool valid_;
|
||||||
|
|
||||||
|
//- Communicator
|
||||||
|
const label comm_;
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
@ -92,6 +99,40 @@ public:
|
|||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct with specified atomic behaviour and communicator
|
||||||
|
//- from pathname, stream option, optional append
|
||||||
|
masterOFstream
|
||||||
|
(
|
||||||
|
IOstreamOption::atomicType atomic,
|
||||||
|
const label comm,
|
||||||
|
const fileName& pathname,
|
||||||
|
IOstreamOption streamOpt = IOstreamOption(),
|
||||||
|
IOstreamOption::appendType append = IOstreamOption::NON_APPEND,
|
||||||
|
const bool valid = true
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct with specified communicator
|
||||||
|
//- from pathname, stream option, optional append
|
||||||
|
masterOFstream
|
||||||
|
(
|
||||||
|
const label comm,
|
||||||
|
const fileName& pathname,
|
||||||
|
IOstreamOption streamOpt = IOstreamOption(),
|
||||||
|
IOstreamOption::appendType append = IOstreamOption::NON_APPEND,
|
||||||
|
const bool valid = true
|
||||||
|
)
|
||||||
|
:
|
||||||
|
masterOFstream
|
||||||
|
(
|
||||||
|
IOstreamOption::NON_ATOMIC,
|
||||||
|
comm,
|
||||||
|
pathname,
|
||||||
|
streamOpt,
|
||||||
|
append,
|
||||||
|
valid
|
||||||
|
)
|
||||||
|
{}
|
||||||
|
|
||||||
//- Construct with specified atomic behaviour (with worldComm)
|
//- Construct with specified atomic behaviour (with worldComm)
|
||||||
//- from pathname, stream option, optional append
|
//- from pathname, stream option, optional append
|
||||||
masterOFstream
|
masterOFstream
|
||||||
@ -101,7 +142,18 @@ public:
|
|||||||
IOstreamOption streamOpt = IOstreamOption(),
|
IOstreamOption streamOpt = IOstreamOption(),
|
||||||
IOstreamOption::appendType append = IOstreamOption::NON_APPEND,
|
IOstreamOption::appendType append = IOstreamOption::NON_APPEND,
|
||||||
const bool valid = true
|
const bool valid = true
|
||||||
);
|
)
|
||||||
|
:
|
||||||
|
masterOFstream
|
||||||
|
(
|
||||||
|
atomic,
|
||||||
|
UPstream::worldComm,
|
||||||
|
pathname,
|
||||||
|
streamOpt,
|
||||||
|
append,
|
||||||
|
valid
|
||||||
|
)
|
||||||
|
{}
|
||||||
|
|
||||||
//- Construct (with worldComm)
|
//- Construct (with worldComm)
|
||||||
//- from pathname, stream option, optional append
|
//- from pathname, stream option, optional append
|
||||||
@ -116,6 +168,7 @@ public:
|
|||||||
masterOFstream
|
masterOFstream
|
||||||
(
|
(
|
||||||
IOstreamOption::NON_ATOMIC,
|
IOstreamOption::NON_ATOMIC,
|
||||||
|
UPstream::worldComm,
|
||||||
pathname,
|
pathname,
|
||||||
streamOpt,
|
streamOpt,
|
||||||
append,
|
append,
|
||||||
|
|||||||
@ -397,7 +397,15 @@ void Foam::Time::setMonitoring(const bool forceProfiling)
|
|||||||
if (runTimeModifiable_)
|
if (runTimeModifiable_)
|
||||||
{
|
{
|
||||||
// Monitor all files that controlDict depends on
|
// Monitor all files that controlDict depends on
|
||||||
fileHandler().addWatches(controlDict_, controlDict_.files());
|
auto& watchFiles = controlDict_.files();
|
||||||
|
|
||||||
|
// Files might have been set during token reading so only on master
|
||||||
|
// processor. Make sure we add them to all processors (though they
|
||||||
|
// are checked only on master - we just need to keep the state
|
||||||
|
// synchronised)
|
||||||
|
Pstream::broadcast(watchFiles, UPstream::worldComm);
|
||||||
|
|
||||||
|
fileHandler().addWatches(controlDict_, watchFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear dependent files - not needed now
|
// Clear dependent files - not needed now
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||||
Copyright (C) 2018-2021 OpenCFD Ltd.
|
Copyright (C) 2018-2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -133,6 +133,15 @@ bool Foam::functionEntries::includeEntry::execute
|
|||||||
Istream& is
|
Istream& is
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
const dictionary& top = parentDict.topDict();
|
||||||
|
const auto* rioPtr = dynamic_cast<const regIOobject*>(&top);
|
||||||
|
const label oldComm
|
||||||
|
(
|
||||||
|
rioPtr && rioPtr->global()
|
||||||
|
? fileHandler().comm(UPstream::worldComm)
|
||||||
|
: fileHandler().comm()
|
||||||
|
);
|
||||||
|
|
||||||
const fileName rawName(is);
|
const fileName rawName(is);
|
||||||
const fileName fName(resolveFile(is.name().path(), rawName, parentDict));
|
const fileName fName(resolveFile(is.name().path(), rawName, parentDict));
|
||||||
|
|
||||||
@ -148,20 +157,19 @@ bool Foam::functionEntries::includeEntry::execute
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add watch on included file
|
// Add watch on included file
|
||||||
const dictionary& top = parentDict.topDict();
|
if (rioPtr)
|
||||||
if (isA<regIOobject>(top))
|
|
||||||
{
|
{
|
||||||
regIOobject& rio = const_cast<regIOobject&>
|
const_cast<regIOobject&>(*rioPtr).addWatch(fName);
|
||||||
(
|
|
||||||
dynamic_cast<const regIOobject&>(top)
|
|
||||||
);
|
|
||||||
rio.addWatch(fName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parentDict.read(ifs);
|
parentDict.read(ifs);
|
||||||
|
|
||||||
|
fileHandler().comm(oldComm);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileHandler().comm(oldComm);
|
||||||
|
|
||||||
if (!mandatory)
|
if (!mandatory)
|
||||||
{
|
{
|
||||||
return true; // Never fails if optional
|
return true; // Never fails if optional
|
||||||
@ -185,6 +193,15 @@ bool Foam::functionEntries::includeEntry::execute
|
|||||||
Istream& is
|
Istream& is
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
const dictionary& top = parentDict.topDict();
|
||||||
|
const auto* rioPtr = dynamic_cast<const regIOobject*>(&top);
|
||||||
|
const label oldComm
|
||||||
|
(
|
||||||
|
rioPtr && rioPtr->global()
|
||||||
|
? fileHandler().comm(UPstream::worldComm)
|
||||||
|
: fileHandler().comm()
|
||||||
|
);
|
||||||
|
|
||||||
const fileName rawName(is);
|
const fileName rawName(is);
|
||||||
const fileName fName(resolveFile(is.name().path(), rawName, parentDict));
|
const fileName fName(resolveFile(is.name().path(), rawName, parentDict));
|
||||||
|
|
||||||
@ -200,20 +217,19 @@ bool Foam::functionEntries::includeEntry::execute
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add watch on included file
|
// Add watch on included file
|
||||||
const dictionary& top = parentDict.topDict();
|
if (rioPtr)
|
||||||
if (isA<regIOobject>(top))
|
|
||||||
{
|
{
|
||||||
regIOobject& rio = const_cast<regIOobject&>
|
const_cast<regIOobject&>(*rioPtr).addWatch(fName);
|
||||||
(
|
|
||||||
dynamic_cast<const regIOobject&>(top)
|
|
||||||
);
|
|
||||||
rio.addWatch(fName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
entry.read(parentDict, ifs);
|
entry.read(parentDict, ifs);
|
||||||
|
|
||||||
|
fileHandler().comm(oldComm);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileHandler().comm(oldComm);
|
||||||
|
|
||||||
if (!mandatory)
|
if (!mandatory)
|
||||||
{
|
{
|
||||||
return true; // Never fails if optional
|
return true; // Never fails if optional
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2015-2017 OpenFOAM Foundation
|
Copyright (C) 2015-2017 OpenFOAM Foundation
|
||||||
Copyright (C) 2019-2021 OpenCFD Ltd.
|
Copyright (C) 2019-2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -33,6 +33,8 @@ License
|
|||||||
#include "IFstream.H"
|
#include "IFstream.H"
|
||||||
#include "IOstreams.H"
|
#include "IOstreams.H"
|
||||||
#include "fileOperation.H"
|
#include "fileOperation.H"
|
||||||
|
#include "regIOobject.H"
|
||||||
|
#include "UPstream.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -113,6 +115,16 @@ bool Foam::functionEntries::includeEtcEntry::execute
|
|||||||
Istream& is
|
Istream& is
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
const dictionary& top = parentDict.topDict();
|
||||||
|
const regIOobject* rioPtr = dynamic_cast<const regIOobject*>(&top);
|
||||||
|
|
||||||
|
const label oldComm
|
||||||
|
(
|
||||||
|
rioPtr && rioPtr->global()
|
||||||
|
? fileHandler().comm(UPstream::worldComm)
|
||||||
|
: fileHandler().comm()
|
||||||
|
);
|
||||||
|
|
||||||
const fileName rawName(is);
|
const fileName rawName(is);
|
||||||
const fileName fName(resolveEtcFile(rawName, parentDict));
|
const fileName fName(resolveEtcFile(rawName, parentDict));
|
||||||
|
|
||||||
@ -127,9 +139,13 @@ bool Foam::functionEntries::includeEtcEntry::execute
|
|||||||
Info<< fName << nl;
|
Info<< fName << nl;
|
||||||
}
|
}
|
||||||
parentDict.read(ifs);
|
parentDict.read(ifs);
|
||||||
|
|
||||||
|
fileHandler().comm(oldComm);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileHandler().comm(oldComm);
|
||||||
|
|
||||||
if (!mandatory)
|
if (!mandatory)
|
||||||
{
|
{
|
||||||
return true; // Never fails if optional
|
return true; // Never fails if optional
|
||||||
@ -153,6 +169,15 @@ bool Foam::functionEntries::includeEtcEntry::execute
|
|||||||
Istream& is
|
Istream& is
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
const dictionary& top = parentDict.topDict();
|
||||||
|
const regIOobject* rioPtr = dynamic_cast<const regIOobject*>(&top);
|
||||||
|
const label oldComm
|
||||||
|
(
|
||||||
|
rioPtr && rioPtr->global()
|
||||||
|
? fileHandler().comm(UPstream::worldComm)
|
||||||
|
: fileHandler().comm()
|
||||||
|
);
|
||||||
|
|
||||||
const fileName rawName(is);
|
const fileName rawName(is);
|
||||||
const fileName fName(resolveEtcFile(rawName, parentDict));
|
const fileName fName(resolveEtcFile(rawName, parentDict));
|
||||||
|
|
||||||
@ -167,9 +192,13 @@ bool Foam::functionEntries::includeEtcEntry::execute
|
|||||||
Info<< fName << nl;
|
Info<< fName << nl;
|
||||||
}
|
}
|
||||||
entry.read(parentDict, ifs);
|
entry.read(parentDict, ifs);
|
||||||
|
|
||||||
|
fileHandler().comm(oldComm);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileHandler().comm(oldComm);
|
||||||
|
|
||||||
if (!mandatory)
|
if (!mandatory)
|
||||||
{
|
{
|
||||||
return true; // Never fails if optional
|
return true; // Never fails if optional
|
||||||
|
|||||||
@ -1815,7 +1815,7 @@ Foam::argList::~argList()
|
|||||||
jobInfo.stop(); // Normal job termination
|
jobInfo.stop(); // Normal job termination
|
||||||
|
|
||||||
// Delete file handler to flush any remaining IO
|
// Delete file handler to flush any remaining IO
|
||||||
Foam::fileHandler(nullptr);
|
(void)Foam::fileHandler(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -50,6 +50,12 @@ namespace fileOperations
|
|||||||
collatedFileOperation,
|
collatedFileOperation,
|
||||||
word
|
word
|
||||||
);
|
);
|
||||||
|
addToRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
fileOperation,
|
||||||
|
collatedFileOperation,
|
||||||
|
comm
|
||||||
|
);
|
||||||
|
|
||||||
float collatedFileOperation::maxThreadFileBufferSize
|
float collatedFileOperation::maxThreadFileBufferSize
|
||||||
(
|
(
|
||||||
@ -107,45 +113,10 @@ void Foam::fileOperations::collatedFileOperation::printBanner
|
|||||||
|
|
||||||
if (printRanks)
|
if (printRanks)
|
||||||
{
|
{
|
||||||
// Information about the ranks
|
masterUncollatedFileOperation::printRanks();
|
||||||
stringList hosts(Pstream::nProcs());
|
|
||||||
if (Pstream::master(comm_))
|
|
||||||
{
|
|
||||||
hosts[Pstream::myProcNo()] = hostName();
|
|
||||||
}
|
|
||||||
Pstream::gatherList(hosts);
|
|
||||||
|
|
||||||
DynamicList<label> offsetMaster(Pstream::nProcs());
|
|
||||||
|
|
||||||
forAll(hosts, ranki)
|
|
||||||
{
|
|
||||||
if (!hosts[ranki].empty())
|
|
||||||
{
|
|
||||||
offsetMaster.append(ranki);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offsetMaster.size() > 1)
|
|
||||||
{
|
|
||||||
DetailInfo
|
|
||||||
<< "IO nodes:" << nl << '(' << nl;
|
|
||||||
|
|
||||||
offsetMaster.append(Pstream::nProcs());
|
|
||||||
|
|
||||||
for (label group = 1; group < offsetMaster.size(); ++group)
|
|
||||||
{
|
|
||||||
const label beg = offsetMaster[group-1];
|
|
||||||
const label end = offsetMaster[group];
|
|
||||||
|
|
||||||
DetailInfo
|
|
||||||
<< " (" << hosts[beg].c_str() << ' '
|
|
||||||
<< (end-beg) << ')' << nl;
|
|
||||||
}
|
|
||||||
DetailInfo
|
|
||||||
<< ')' << nl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- fileModificationChecking already set by base class (masterUncollated)
|
||||||
// if (IOobject::fileModificationChecking == IOobject::timeStampMaster)
|
// if (IOobject::fileModificationChecking == IOobject::timeStampMaster)
|
||||||
// {
|
// {
|
||||||
// WarningInFunction
|
// WarningInFunction
|
||||||
@ -169,10 +140,10 @@ const
|
|||||||
{
|
{
|
||||||
return Pstream::master(comm_);
|
return Pstream::master(comm_);
|
||||||
}
|
}
|
||||||
else if (ioRanks_.size())
|
else if (ioRanks().size())
|
||||||
{
|
{
|
||||||
// Found myself in IO rank
|
// Found myself in IO rank
|
||||||
return ioRanks_.found(proci);
|
return ioRanks().found(proci);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -256,6 +227,38 @@ bool Foam::fileOperations::collatedFileOperation::appendObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Construction helper
|
||||||
|
static Tuple2<label, labelList> getCommPattern()
|
||||||
|
{
|
||||||
|
// With useHost == false
|
||||||
|
|
||||||
|
Tuple2<label, labelList> commAndIORanks;
|
||||||
|
|
||||||
|
commAndIORanks.first() = UPstream::worldComm;
|
||||||
|
commAndIORanks.second() = fileOperation::getGlobalIORanks(false);
|
||||||
|
|
||||||
|
if (!commAndIORanks.second().empty())
|
||||||
|
{
|
||||||
|
// Needs its own communicator
|
||||||
|
commAndIORanks.first() =
|
||||||
|
UPstream::allocateCommunicator
|
||||||
|
(
|
||||||
|
UPstream::worldComm,
|
||||||
|
fileOperation::getGlobalSubRanks(false)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return commAndIORanks;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
void Foam::fileOperations::collatedFileOperation::init(bool verbose)
|
void Foam::fileOperations::collatedFileOperation::init(bool verbose)
|
||||||
@ -276,21 +279,32 @@ Foam::fileOperations::collatedFileOperation::collatedFileOperation
|
|||||||
:
|
:
|
||||||
masterUncollatedFileOperation
|
masterUncollatedFileOperation
|
||||||
(
|
(
|
||||||
(
|
getCommPattern(),
|
||||||
ioRanks().size()
|
false, // distributedRoots
|
||||||
? UPstream::allocateCommunicator
|
false // verbose
|
||||||
(
|
|
||||||
UPstream::worldComm,
|
|
||||||
subRanks(Pstream::nProcs())
|
|
||||||
)
|
|
||||||
: UPstream::worldComm
|
|
||||||
),
|
|
||||||
false
|
|
||||||
),
|
),
|
||||||
myComm_(comm_),
|
managedComm_(comm_), // [sic] Managed here, or is worldComm
|
||||||
writer_(mag(maxThreadFileBufferSize), comm_),
|
writer_(mag(maxThreadFileBufferSize), comm_)
|
||||||
nProcs_(Pstream::nProcs()),
|
{
|
||||||
ioRanks_(ioRanks())
|
init(verbose);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::fileOperations::collatedFileOperation::collatedFileOperation
|
||||||
|
(
|
||||||
|
const Tuple2<label, labelList>& commAndIORanks,
|
||||||
|
const bool distributedRoots,
|
||||||
|
bool verbose
|
||||||
|
)
|
||||||
|
:
|
||||||
|
masterUncollatedFileOperation
|
||||||
|
(
|
||||||
|
commAndIORanks,
|
||||||
|
distributedRoots,
|
||||||
|
false // verbose
|
||||||
|
),
|
||||||
|
managedComm_(-1), // Externally managed
|
||||||
|
writer_(mag(maxThreadFileBufferSize), comm_)
|
||||||
{
|
{
|
||||||
init(verbose);
|
init(verbose);
|
||||||
}
|
}
|
||||||
@ -299,16 +313,20 @@ Foam::fileOperations::collatedFileOperation::collatedFileOperation
|
|||||||
Foam::fileOperations::collatedFileOperation::collatedFileOperation
|
Foam::fileOperations::collatedFileOperation::collatedFileOperation
|
||||||
(
|
(
|
||||||
const label comm,
|
const label comm,
|
||||||
const labelList& ioRanks,
|
const labelUList& ioRanks,
|
||||||
const word& typeName,
|
const bool distributedRoots,
|
||||||
bool verbose
|
bool verbose
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
masterUncollatedFileOperation(comm, false),
|
masterUncollatedFileOperation
|
||||||
myComm_(-1),
|
(
|
||||||
writer_(mag(maxThreadFileBufferSize), comm),
|
comm,
|
||||||
nProcs_(Pstream::nProcs()),
|
ioRanks,
|
||||||
ioRanks_(ioRanks)
|
distributedRoots,
|
||||||
|
false // verbose
|
||||||
|
),
|
||||||
|
managedComm_(-1), // Externally managed
|
||||||
|
writer_(mag(maxThreadFileBufferSize), comm_)
|
||||||
{
|
{
|
||||||
init(verbose);
|
init(verbose);
|
||||||
}
|
}
|
||||||
@ -321,9 +339,9 @@ Foam::fileOperations::collatedFileOperation::~collatedFileOperation()
|
|||||||
// Wait for any outstanding file operations
|
// Wait for any outstanding file operations
|
||||||
flush();
|
flush();
|
||||||
|
|
||||||
if (myComm_ != -1 && myComm_ != UPstream::worldComm)
|
if (managedComm_ >= 0 && managedComm_ != UPstream::worldComm)
|
||||||
{
|
{
|
||||||
UPstream::freeCommunicator(myComm_);
|
UPstream::freeCommunicator(managedComm_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,6 +407,7 @@ bool Foam::fileOperations::collatedFileOperation::writeObject
|
|||||||
// Note: currently still NON_ATOMIC (Dec-2022)
|
// Note: currently still NON_ATOMIC (Dec-2022)
|
||||||
masterOFstream os
|
masterOFstream os
|
||||||
(
|
(
|
||||||
|
comm_,
|
||||||
pathName,
|
pathName,
|
||||||
streamOpt,
|
streamOpt,
|
||||||
IOstreamOption::NON_APPEND,
|
IOstreamOption::NON_APPEND,
|
||||||
@ -420,7 +439,7 @@ bool Foam::fileOperations::collatedFileOperation::writeObject
|
|||||||
mkDir(path);
|
mkDir(path);
|
||||||
fileName pathName(path/io.name());
|
fileName pathName(path/io.name());
|
||||||
|
|
||||||
if (io.global())
|
if (io.global() || io.globalObject())
|
||||||
{
|
{
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
@ -433,6 +452,7 @@ bool Foam::fileOperations::collatedFileOperation::writeObject
|
|||||||
// Note: currently still NON_ATOMIC (Dec-2022)
|
// Note: currently still NON_ATOMIC (Dec-2022)
|
||||||
masterOFstream os
|
masterOFstream os
|
||||||
(
|
(
|
||||||
|
comm_,
|
||||||
pathName,
|
pathName,
|
||||||
streamOpt,
|
streamOpt,
|
||||||
IOstreamOption::NON_APPEND,
|
IOstreamOption::NON_APPEND,
|
||||||
@ -549,9 +569,10 @@ Foam::word Foam::fileOperations::collatedFileOperation::processorsDir
|
|||||||
{
|
{
|
||||||
const List<int>& procs(UPstream::procID(comm_));
|
const List<int>& procs(UPstream::procID(comm_));
|
||||||
|
|
||||||
word procDir(processorsBaseDir+Foam::name(Pstream::nProcs()));
|
//word procDir(processorsBaseDir+Foam::name(Pstream::nProcs()));
|
||||||
|
word procDir(processorsBaseDir+Foam::name(nProcs_));
|
||||||
|
|
||||||
if (procs.size() != Pstream::nProcs())
|
if (procs.size() != nProcs_)
|
||||||
{
|
{
|
||||||
procDir +=
|
procDir +=
|
||||||
+ "_"
|
+ "_"
|
||||||
@ -565,7 +586,7 @@ Foam::word Foam::fileOperations::collatedFileOperation::processorsDir
|
|||||||
{
|
{
|
||||||
word procDir(processorsBaseDir+Foam::name(nProcs_));
|
word procDir(processorsBaseDir+Foam::name(nProcs_));
|
||||||
|
|
||||||
if (ioRanks_.size())
|
if (ioRanks().size())
|
||||||
{
|
{
|
||||||
// Detect current processor number
|
// Detect current processor number
|
||||||
label proci = detectProcessorPath(fName);
|
label proci = detectProcessorPath(fName);
|
||||||
@ -575,7 +596,7 @@ Foam::word Foam::fileOperations::collatedFileOperation::processorsDir
|
|||||||
// Find lowest io rank
|
// Find lowest io rank
|
||||||
label minProc = 0;
|
label minProc = 0;
|
||||||
label maxProc = nProcs_-1;
|
label maxProc = nProcs_-1;
|
||||||
for (const label ranki : ioRanks_)
|
for (const label ranki : ioRanks())
|
||||||
{
|
{
|
||||||
if (ranki >= nProcs_)
|
if (ranki >= nProcs_)
|
||||||
{
|
{
|
||||||
@ -613,16 +634,4 @@ Foam::word Foam::fileOperations::collatedFileOperation::processorsDir
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::fileOperations::collatedFileOperation::setNProcs(const label nProcs)
|
|
||||||
{
|
|
||||||
nProcs_ = nProcs;
|
|
||||||
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Pout<< "collatedFileOperation::setNProcs :"
|
|
||||||
<< " Setting number of processors to " << nProcs_ << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2017 OpenFOAM Foundation
|
Copyright (C) 2017 OpenFOAM Foundation
|
||||||
Copyright (C) 2019-2021 OpenCFD Ltd.
|
Copyright (C) 2019-2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -46,8 +46,8 @@ SourceFiles
|
|||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef fileOperations_collatedFileOperation_H
|
#ifndef Foam_fileOperations_collatedFileOperation_H
|
||||||
#define fileOperations_collatedFileOperation_H
|
#define Foam_fileOperations_collatedFileOperation_H
|
||||||
|
|
||||||
#include "masterUncollatedFileOperation.H"
|
#include "masterUncollatedFileOperation.H"
|
||||||
#include "OFstreamCollator.H"
|
#include "OFstreamCollator.H"
|
||||||
@ -67,6 +67,12 @@ class collatedFileOperation
|
|||||||
:
|
:
|
||||||
public masterUncollatedFileOperation
|
public masterUncollatedFileOperation
|
||||||
{
|
{
|
||||||
|
// Private Data
|
||||||
|
|
||||||
|
//- Communicator allocated/managed by us
|
||||||
|
label managedComm_;
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Any initialisation steps after constructing
|
//- Any initialisation steps after constructing
|
||||||
@ -76,20 +82,9 @@ protected:
|
|||||||
|
|
||||||
// Protected Data
|
// Protected Data
|
||||||
|
|
||||||
//- Any communicator allocated by me
|
|
||||||
const label myComm_;
|
|
||||||
|
|
||||||
//- Threaded writer
|
//- Threaded writer
|
||||||
mutable OFstreamCollator writer_;
|
mutable OFstreamCollator writer_;
|
||||||
|
|
||||||
// For non-parallel operation
|
|
||||||
|
|
||||||
//- Number of processors (overall)
|
|
||||||
label nProcs_;
|
|
||||||
|
|
||||||
//- Ranks of IO handlers
|
|
||||||
const labelList ioRanks_;
|
|
||||||
|
|
||||||
|
|
||||||
// Protected Member Functions
|
// Protected Member Functions
|
||||||
|
|
||||||
@ -111,8 +106,8 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//- Runtime type information
|
//- Runtime type information
|
||||||
TypeName("collated");
|
TypeName("collated");
|
||||||
|
|
||||||
|
|
||||||
// Static Data
|
// Static Data
|
||||||
@ -128,12 +123,20 @@ public:
|
|||||||
//- Default construct
|
//- Default construct
|
||||||
explicit collatedFileOperation(bool verbose);
|
explicit collatedFileOperation(bool verbose);
|
||||||
|
|
||||||
//- Construct from user communicator
|
//- Construct from communicator with specified io-ranks
|
||||||
|
collatedFileOperation
|
||||||
|
(
|
||||||
|
const Tuple2<label, labelList>& commAndIORanks,
|
||||||
|
const bool distributedRoots,
|
||||||
|
bool verbose
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct from communicator with specified io-ranks
|
||||||
collatedFileOperation
|
collatedFileOperation
|
||||||
(
|
(
|
||||||
const label comm,
|
const label comm,
|
||||||
const labelList& ioRanks,
|
const labelUList& ioRanks,
|
||||||
const word& typeName,
|
const bool distributedRoots,
|
||||||
bool verbose
|
bool verbose
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -162,6 +165,7 @@ public:
|
|||||||
const bool valid = true
|
const bool valid = true
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
|
|
||||||
//- Forcibly wait until all output done. Flush any cached data
|
//- Forcibly wait until all output done. Flush any cached data
|
||||||
@ -172,10 +176,6 @@ public:
|
|||||||
|
|
||||||
//- Actual name of processors dir
|
//- Actual name of processors dir
|
||||||
virtual word processorsDir(const fileName&) const;
|
virtual word processorsDir(const fileName&) const;
|
||||||
|
|
||||||
//- Set number of processor directories/results.
|
|
||||||
//- Only used in decomposePar
|
|
||||||
virtual void setNProcs(const label nProcs);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -28,7 +28,6 @@ License
|
|||||||
|
|
||||||
#include "hostCollatedFileOperation.H"
|
#include "hostCollatedFileOperation.H"
|
||||||
#include "addToRunTimeSelectionTable.H"
|
#include "addToRunTimeSelectionTable.H"
|
||||||
#include "bitSet.H"
|
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
|
/* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
|
||||||
|
|
||||||
@ -43,6 +42,12 @@ namespace fileOperations
|
|||||||
hostCollatedFileOperation,
|
hostCollatedFileOperation,
|
||||||
word
|
word
|
||||||
);
|
);
|
||||||
|
addToRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
fileOperation,
|
||||||
|
hostCollatedFileOperation,
|
||||||
|
comm
|
||||||
|
);
|
||||||
|
|
||||||
// Register initialisation routine. Signals need for threaded mpi and
|
// Register initialisation routine. Signals need for threaded mpi and
|
||||||
// handles command line arguments
|
// handles command line arguments
|
||||||
@ -57,70 +62,6 @@ namespace fileOperations
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
|
||||||
|
|
||||||
Foam::labelList Foam::fileOperations::hostCollatedFileOperation::subRanks
|
|
||||||
(
|
|
||||||
const label n
|
|
||||||
)
|
|
||||||
{
|
|
||||||
DynamicList<label> subRanks(64);
|
|
||||||
|
|
||||||
labelList mainRanks(fileOperation::ioRanks());
|
|
||||||
if (!mainRanks.empty())
|
|
||||||
{
|
|
||||||
if (!mainRanks.found(0))
|
|
||||||
{
|
|
||||||
FatalErrorInFunction
|
|
||||||
<< "Rank 0 (master) should be in the IO ranks. Currently "
|
|
||||||
<< mainRanks << nl
|
|
||||||
<< exit(FatalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The lowest numbered rank is the IO rank
|
|
||||||
const bitSet isIOrank(n, mainRanks);
|
|
||||||
|
|
||||||
for (label proci = Pstream::myProcNo(); proci >= 0; --proci)
|
|
||||||
{
|
|
||||||
if (isIOrank[proci])
|
|
||||||
{
|
|
||||||
// Found my master. Collect all processors with same master
|
|
||||||
subRanks.append(proci);
|
|
||||||
for
|
|
||||||
(
|
|
||||||
label rank = proci+1;
|
|
||||||
rank < n && !isIOrank[rank];
|
|
||||||
++rank
|
|
||||||
)
|
|
||||||
{
|
|
||||||
subRanks.append(rank);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Normal operation: one lowest rank per hostname is the writer
|
|
||||||
const string myHostName(hostName());
|
|
||||||
|
|
||||||
stringList hosts(Pstream::nProcs());
|
|
||||||
hosts[Pstream::myProcNo()] = myHostName;
|
|
||||||
Pstream::allGatherList(hosts);
|
|
||||||
|
|
||||||
// Collect procs with same hostname
|
|
||||||
forAll(hosts, proci)
|
|
||||||
{
|
|
||||||
if (hosts[proci] == myHostName)
|
|
||||||
{
|
|
||||||
subRanks.append(proci);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return subRanks;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
void Foam::fileOperations::hostCollatedFileOperation::init(bool verbose)
|
void Foam::fileOperations::hostCollatedFileOperation::init(bool verbose)
|
||||||
@ -144,24 +85,71 @@ Foam::fileOperations::hostCollatedFileOperation::hostCollatedFileOperation
|
|||||||
UPstream::allocateCommunicator
|
UPstream::allocateCommunicator
|
||||||
(
|
(
|
||||||
UPstream::worldComm,
|
UPstream::worldComm,
|
||||||
subRanks(Pstream::nProcs())
|
fileOperation::getGlobalSubRanks(true) // Host
|
||||||
),
|
),
|
||||||
(Pstream::parRun() ? labelList() : ioRanks()), // processor dirs
|
fileOperation::getGlobalIORanks(true), // Host
|
||||||
typeName,
|
false, // distributedRoots
|
||||||
false // verbose
|
false // verbose
|
||||||
)
|
),
|
||||||
|
managedComm_(comm_)
|
||||||
{
|
{
|
||||||
init(verbose);
|
init(verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::fileOperations::hostCollatedFileOperation::hostCollatedFileOperation
|
||||||
|
(
|
||||||
|
const Tuple2<label, labelList>& commAndIORanks,
|
||||||
|
const bool distributedRoots,
|
||||||
|
bool verbose
|
||||||
|
)
|
||||||
|
:
|
||||||
|
collatedFileOperation
|
||||||
|
(
|
||||||
|
commAndIORanks,
|
||||||
|
distributedRoots,
|
||||||
|
false // verbose
|
||||||
|
),
|
||||||
|
managedComm_(-1) // Externally managed
|
||||||
|
{
|
||||||
|
if (verbose && Foam::infoDetailLevel > 0)
|
||||||
|
{
|
||||||
|
this->printBanner(ioRanks_.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::fileOperations::hostCollatedFileOperation::hostCollatedFileOperation
|
||||||
|
(
|
||||||
|
const label comm,
|
||||||
|
const labelUList& ioRanks,
|
||||||
|
const bool distributedRoots,
|
||||||
|
bool verbose
|
||||||
|
)
|
||||||
|
:
|
||||||
|
collatedFileOperation
|
||||||
|
(
|
||||||
|
comm,
|
||||||
|
ioRanks,
|
||||||
|
distributedRoots,
|
||||||
|
false // verbose
|
||||||
|
),
|
||||||
|
managedComm_(-1) // Externally managed
|
||||||
|
{
|
||||||
|
if (verbose && Foam::infoDetailLevel > 0)
|
||||||
|
{
|
||||||
|
this->printBanner(ioRanks_.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::fileOperations::hostCollatedFileOperation::~hostCollatedFileOperation()
|
Foam::fileOperations::hostCollatedFileOperation::~hostCollatedFileOperation()
|
||||||
{
|
{
|
||||||
if (comm_ != -1 && comm_ != UPstream::worldComm)
|
if (managedComm_ >= 0 && managedComm_ != UPstream::worldComm)
|
||||||
{
|
{
|
||||||
UPstream::freeCommunicator(comm_);
|
UPstream::freeCommunicator(managedComm_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2017-2018 OpenFOAM Foundation
|
Copyright (C) 2017-2018 OpenFOAM Foundation
|
||||||
Copyright (C) 2021 OpenCFD Ltd.
|
Copyright (C) 2021-2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -77,14 +77,17 @@ class hostCollatedFileOperation
|
|||||||
:
|
:
|
||||||
public collatedFileOperation
|
public collatedFileOperation
|
||||||
{
|
{
|
||||||
|
// Private Data
|
||||||
|
|
||||||
|
//- Communicator allocated/managed by us
|
||||||
|
label managedComm_;
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Any initialisation steps after constructing
|
//- Any initialisation steps after constructing
|
||||||
void init(bool verbose);
|
void init(bool verbose);
|
||||||
|
|
||||||
//- Get the list of processors part of this set
|
|
||||||
static labelList subRanks(const label n);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//- Runtime type information
|
//- Runtime type information
|
||||||
@ -96,6 +99,23 @@ public:
|
|||||||
//- Default construct
|
//- Default construct
|
||||||
explicit hostCollatedFileOperation(const bool verbose);
|
explicit hostCollatedFileOperation(const bool verbose);
|
||||||
|
|
||||||
|
//- Construct from communicator with specified io-ranks
|
||||||
|
hostCollatedFileOperation
|
||||||
|
(
|
||||||
|
const Tuple2<label, labelList>& commAndIORanks,
|
||||||
|
const bool distributedRoots,
|
||||||
|
bool verbose
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct from communicator with specified io-ranks
|
||||||
|
hostCollatedFileOperation
|
||||||
|
(
|
||||||
|
const label comm,
|
||||||
|
const labelUList& ioRanks,
|
||||||
|
const bool distributedRoots,
|
||||||
|
bool verbose
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
//- Destructor
|
//- Destructor
|
||||||
virtual ~hostCollatedFileOperation();
|
virtual ~hostCollatedFileOperation();
|
||||||
|
|||||||
@ -37,6 +37,7 @@ License
|
|||||||
#include "registerSwitch.H"
|
#include "registerSwitch.H"
|
||||||
#include "Time.H"
|
#include "Time.H"
|
||||||
#include "ITstream.H"
|
#include "ITstream.H"
|
||||||
|
#include <algorithm>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
|
|
||||||
@ -46,6 +47,7 @@ namespace Foam
|
|||||||
{
|
{
|
||||||
defineTypeNameAndDebug(fileOperation, 0);
|
defineTypeNameAndDebug(fileOperation, 0);
|
||||||
defineRunTimeSelectionTable(fileOperation, word);
|
defineRunTimeSelectionTable(fileOperation, word);
|
||||||
|
defineRunTimeSelectionTable(fileOperation, comm);
|
||||||
|
|
||||||
word fileOperation::defaultFileHandler
|
word fileOperation::defaultFileHandler
|
||||||
(
|
(
|
||||||
@ -83,6 +85,9 @@ Foam::word Foam::fileOperation::processorsBaseDir = "processors";
|
|||||||
|
|
||||||
Foam::autoPtr<Foam::fileOperation> Foam::fileOperation::fileHandlerPtr_;
|
Foam::autoPtr<Foam::fileOperation> Foam::fileOperation::fileHandlerPtr_;
|
||||||
|
|
||||||
|
//- Caching (e.g. of time directories) - enabled by default
|
||||||
|
int Foam::fileOperation::cacheLevel_(1);
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -221,7 +226,11 @@ void sortProcessorDirs(Foam::UList<Foam::fileOperation::dirIndex>& dirs)
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::labelList Foam::fileOperation::ioRanks()
|
Foam::labelList Foam::fileOperation::getGlobalIORanks
|
||||||
|
(
|
||||||
|
const bitSet& useProc,
|
||||||
|
const bool useHost
|
||||||
|
)
|
||||||
{
|
{
|
||||||
labelList ranks;
|
labelList ranks;
|
||||||
|
|
||||||
@ -231,6 +240,278 @@ Foam::labelList Foam::fileOperation::ioRanks()
|
|||||||
is >> ranks;
|
is >> ranks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const label np = Pstream::nProcs(UPstream::worldComm);
|
||||||
|
|
||||||
|
bool needFilter = false;
|
||||||
|
|
||||||
|
if (ranks.size())
|
||||||
|
{
|
||||||
|
if (!ranks.found(0))
|
||||||
|
{
|
||||||
|
// Could also add silently, using append
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Rank 0 (master) should be in the IO ranks. Currently:" << nl
|
||||||
|
<< " " << flatOutput(ranks) << nl
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cannot trust in user input.
|
||||||
|
// Sort and eliminate any duplicates
|
||||||
|
|
||||||
|
std::sort(ranks.begin(), ranks.end());
|
||||||
|
|
||||||
|
auto last = std::unique(ranks.begin(), ranks.end());
|
||||||
|
|
||||||
|
ranks.resize(static_cast<label>(last - ranks.begin()));
|
||||||
|
|
||||||
|
needFilter =
|
||||||
|
(
|
||||||
|
!useProc.empty()
|
||||||
|
&& (useProc.size() != np || !useProc.all())
|
||||||
|
);
|
||||||
|
|
||||||
|
// Could also test everything first in the hope of
|
||||||
|
// avoiding unneeded work
|
||||||
|
//
|
||||||
|
/// if
|
||||||
|
/// (
|
||||||
|
/// !useProc.empty()
|
||||||
|
/// && (useProc.size() != np || !useProc.all())
|
||||||
|
/// )
|
||||||
|
/// {
|
||||||
|
/// needFilter = false;
|
||||||
|
/// for (const label ranki : ranks)
|
||||||
|
/// {
|
||||||
|
/// if (!useProc.test(ranki))
|
||||||
|
/// {
|
||||||
|
/// needFilter = true;
|
||||||
|
/// break
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
}
|
||||||
|
else if (useHost)
|
||||||
|
{
|
||||||
|
// Use hostname
|
||||||
|
// Lowest rank per hostname is the IO rank
|
||||||
|
|
||||||
|
const label myProci = Pstream::myProcNo(UPstream::worldComm);
|
||||||
|
|
||||||
|
stringList hostNames(np);
|
||||||
|
|
||||||
|
// Most efficient to apply subset filter now,
|
||||||
|
// by simply not populating that hostName
|
||||||
|
if
|
||||||
|
(
|
||||||
|
// Always include master
|
||||||
|
Pstream::master(UPstream::worldComm)
|
||||||
|
|
||||||
|
// No filtering, or is included in subset
|
||||||
|
|| (useProc.empty() || useProc.test(myProci))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
hostNames[myProci] = hostName();
|
||||||
|
}
|
||||||
|
|
||||||
|
Pstream::gatherList
|
||||||
|
(
|
||||||
|
hostNames,
|
||||||
|
UPstream::msgType(),
|
||||||
|
UPstream::worldComm
|
||||||
|
);
|
||||||
|
|
||||||
|
if (Pstream::master(UPstream::worldComm))
|
||||||
|
{
|
||||||
|
DynamicList<label> hostRanks(np);
|
||||||
|
|
||||||
|
hostRanks.append(0); // Always include master
|
||||||
|
label previ = 0;
|
||||||
|
|
||||||
|
for (label proci = 1; proci < hostNames.size(); ++proci)
|
||||||
|
{
|
||||||
|
if
|
||||||
|
(
|
||||||
|
hostNames[proci].size()
|
||||||
|
&& hostNames[proci] != hostNames[previ]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
hostRanks.append(proci);
|
||||||
|
previ = proci;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ranks.transfer(hostRanks);
|
||||||
|
}
|
||||||
|
|
||||||
|
Pstream::broadcast(ranks, UPstream::worldComm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (needFilter && ranks.size())
|
||||||
|
{
|
||||||
|
// The ranks are already sorted, no duplicate values
|
||||||
|
bitSet newRanks(ranks.last());
|
||||||
|
|
||||||
|
const label nRanks = ranks.size();
|
||||||
|
|
||||||
|
// Always include proc0
|
||||||
|
newRanks.set(0);
|
||||||
|
|
||||||
|
for
|
||||||
|
(
|
||||||
|
label idx = (ranks[0] == 0 ? 1 : 0);
|
||||||
|
idx < nRanks;
|
||||||
|
++idx
|
||||||
|
)
|
||||||
|
{
|
||||||
|
label ranki = ranks[idx];
|
||||||
|
|
||||||
|
if (useProc.test(ranki))
|
||||||
|
{
|
||||||
|
// IO rank is also in processor subset
|
||||||
|
newRanks.set(ranki);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// IO rank not in processor subset.
|
||||||
|
// Find the next rank of this range that is
|
||||||
|
|
||||||
|
ranki = useProc.find_next(ranki);
|
||||||
|
|
||||||
|
if (ranki == -1)
|
||||||
|
{
|
||||||
|
// No more processors for this IO group
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of search, or in range
|
||||||
|
if ((idx == nRanks-1) || (ranki < ranks[idx+1]))
|
||||||
|
{
|
||||||
|
newRanks.set(ranki);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ranks = newRanks.sortedToc();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ranks;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::labelList Foam::fileOperation::getGlobalSubRanks
|
||||||
|
(
|
||||||
|
const bitSet& useProc,
|
||||||
|
const bool useHost
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Get IO ranks first
|
||||||
|
labelList ranks(fileOperation::getGlobalIORanks(useProc, useHost));
|
||||||
|
|
||||||
|
const label np = Pstream::nProcs(UPstream::worldComm);
|
||||||
|
|
||||||
|
const bool needFilter =
|
||||||
|
(
|
||||||
|
!useProc.empty()
|
||||||
|
&& (useProc.size() != np || !useProc.all())
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Fast path - no IO ranks.
|
||||||
|
if (ranks.empty())
|
||||||
|
{
|
||||||
|
if (needFilter)
|
||||||
|
{
|
||||||
|
// Subset of ranks involved
|
||||||
|
return useProc.sortedToc();
|
||||||
|
}
|
||||||
|
|
||||||
|
// All ranks are involved
|
||||||
|
return identity(np);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Build sub-ranks: the lowest numbered rank is the IO rank
|
||||||
|
|
||||||
|
// Note: the IO ranks have already been filtered/adjusted
|
||||||
|
// to only include ranks that are also in useProc
|
||||||
|
|
||||||
|
const label myProci = Pstream::myProcNo(UPstream::worldComm);
|
||||||
|
|
||||||
|
if (needFilter && !useProc.test(myProci))
|
||||||
|
{
|
||||||
|
// I am not involved with any IO
|
||||||
|
return labelList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
labelRange subRange(0, np);
|
||||||
|
|
||||||
|
// Linear search for enclosing range
|
||||||
|
{
|
||||||
|
const label nIOranks = ranks.size();
|
||||||
|
|
||||||
|
// Starting with proc = 0, silently adds master (0) into IO ranks
|
||||||
|
label begIdx = 0;
|
||||||
|
|
||||||
|
for (label i = 0; i < nIOranks && (ranks[i] <= myProci); ++i)
|
||||||
|
{
|
||||||
|
begIdx = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// One-beyond end of our range (ie, where the next IO range begins)
|
||||||
|
const label begProc = ranks[begIdx];
|
||||||
|
const label endProc = (begIdx+1 < nIOranks) ? ranks[begIdx+1] : np;
|
||||||
|
|
||||||
|
subRange.reset(begProc, (endProc-begProc));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// Use bitSet during search
|
||||||
|
{
|
||||||
|
// IO ranks are sorted, so last element is a good sizing estimate
|
||||||
|
const bitSet isIOrank(ranks.last(), ranks);
|
||||||
|
|
||||||
|
// Build sub-ranks: the lowest numbered rank is the IO rank
|
||||||
|
label begProc = 0;
|
||||||
|
|
||||||
|
for (label proci = myProci; proci >= 0; --proci)
|
||||||
|
{
|
||||||
|
if (isIOrank.test(proci))
|
||||||
|
{
|
||||||
|
// Found the lower rank used for IO
|
||||||
|
begProc = proci;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find one-beyond end of our range (ie, where the next IO range begins)
|
||||||
|
label endProc = isIOrank.find_next(begProc);
|
||||||
|
if (endProc == -1) endProc = np;
|
||||||
|
|
||||||
|
subRange.reset(begProc, (endProc-begProc));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (needFilter)
|
||||||
|
{
|
||||||
|
DynamicList<label> subRanks(subRange.size());
|
||||||
|
|
||||||
|
for (label proci : subRange)
|
||||||
|
{
|
||||||
|
if (useProc.test(proci))
|
||||||
|
{
|
||||||
|
subRanks.append(proci);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ranks.transfer(subRanks);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ranks = identity(subRange);
|
||||||
|
}
|
||||||
|
|
||||||
return ranks;
|
return ranks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,6 +576,42 @@ Foam::fileOperation::sortTimes
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::fileOperation::uniformFile(const fileNameList& names)
|
||||||
|
{
|
||||||
|
if (names.empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& object0 = names[0];
|
||||||
|
|
||||||
|
for (label i = 1; i < names.size(); ++i)
|
||||||
|
{
|
||||||
|
if (object0 != names[i])
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::fileOperation::uniformFile(const label comm, const fileName& name)
|
||||||
|
{
|
||||||
|
if (!Pstream::parRun())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fileName masterName(name);
|
||||||
|
|
||||||
|
Pstream::broadcast(masterName, comm);
|
||||||
|
|
||||||
|
return returnReduceAnd((masterName == name), comm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::fileMonitor& Foam::fileOperation::monitor() const
|
Foam::fileMonitor& Foam::fileOperation::monitor() const
|
||||||
@ -415,11 +732,14 @@ Foam::fileOperation::lookupAndCacheProcessorsPath
|
|||||||
{
|
{
|
||||||
const fileName procPath(path/pDir);
|
const fileName procPath(path/pDir);
|
||||||
|
|
||||||
const auto iter = procsDirs_.cfind(procPath);
|
if (cacheLevel() > 0)
|
||||||
|
|
||||||
if (iter.found())
|
|
||||||
{
|
{
|
||||||
return iter.val();
|
const auto iter = procsDirs_.cfind(procPath);
|
||||||
|
|
||||||
|
if (iter.found())
|
||||||
|
{
|
||||||
|
return iter.val();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicList<dirIndex> procDirs;
|
DynamicList<dirIndex> procDirs;
|
||||||
@ -449,7 +769,7 @@ Foam::fileOperation::lookupAndCacheProcessorsPath
|
|||||||
// Parallel and non-distributed
|
// Parallel and non-distributed
|
||||||
// Read on master only and send to subProcs
|
// Read on master only and send to subProcs
|
||||||
|
|
||||||
if (Pstream::master(comm_))
|
if (Pstream::master(UPstream::worldComm))
|
||||||
{
|
{
|
||||||
dirEntries = Foam::readDir(path, fileName::Type::DIRECTORY);
|
dirEntries = Foam::readDir(path, fileName::Type::DIRECTORY);
|
||||||
|
|
||||||
@ -458,7 +778,7 @@ Foam::fileOperation::lookupAndCacheProcessorsPath
|
|||||||
<< " names to sub-processes" << endl;
|
<< " names to sub-processes" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pstream::broadcast(dirEntries, comm_);
|
Pstream::broadcast(dirEntries, UPstream::worldComm);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -619,7 +939,7 @@ Foam::fileOperation::lookupAndCacheProcessorsPath
|
|||||||
// Serial: use the number of decompositions (if found)
|
// Serial: use the number of decompositions (if found)
|
||||||
if (nProcs)
|
if (nProcs)
|
||||||
{
|
{
|
||||||
const_cast<fileOperation&>(*this).setNProcs(nProcs);
|
const_cast<fileOperation&>(*this).nProcs(nProcs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -628,10 +948,17 @@ Foam::fileOperation::lookupAndCacheProcessorsPath
|
|||||||
|
|
||||||
if (procDirsStatus & 2u)
|
if (procDirsStatus & 2u)
|
||||||
{
|
{
|
||||||
procsDirs_.insert(procPath, procDirs);
|
if (cacheLevel() > 0)
|
||||||
|
{
|
||||||
|
procsDirs_.insert(procPath, procDirs);
|
||||||
|
|
||||||
// Make sure to return a reference
|
// Make sure to return a reference
|
||||||
return procsDirs_[procPath];
|
return procsDirs_[procPath];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return refPtr<dirIndexList>::New(procDirs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -692,14 +1019,30 @@ bool Foam::fileOperation::exists(IOobject& io) const
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::fileOperation::fileOperation
|
||||||
|
(
|
||||||
|
const Tuple2<label, labelList>& commAndIORanks,
|
||||||
|
const bool distributedRoots
|
||||||
|
)
|
||||||
|
:
|
||||||
|
comm_(commAndIORanks.first()),
|
||||||
|
nProcs_(Pstream::nProcs(UPstream::worldComm)),
|
||||||
|
distributed_(distributedRoots),
|
||||||
|
ioRanks_(commAndIORanks.second())
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
Foam::fileOperation::fileOperation
|
Foam::fileOperation::fileOperation
|
||||||
(
|
(
|
||||||
const label comm,
|
const label comm,
|
||||||
|
const labelUList& ioRanks,
|
||||||
const bool distributedRoots
|
const bool distributedRoots
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
comm_(comm),
|
comm_(comm),
|
||||||
distributed_(distributedRoots)
|
nProcs_(Pstream::nProcs(UPstream::worldComm)),
|
||||||
|
distributed_(distributedRoots),
|
||||||
|
ioRanks_(ioRanks)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
@ -710,6 +1053,18 @@ Foam::fileOperation::New
|
|||||||
bool verbose
|
bool verbose
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
if (handlerType.empty())
|
||||||
|
{
|
||||||
|
if (fileOperation::defaultFileHandler.empty())
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "defaultFileHandler name is undefined" << nl
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileOperation::New(fileOperation::defaultFileHandler, verbose);
|
||||||
|
}
|
||||||
|
|
||||||
DebugInFunction
|
DebugInFunction
|
||||||
<< "Constructing fileHandler" << endl;
|
<< "Constructing fileHandler" << endl;
|
||||||
|
|
||||||
@ -729,16 +1084,65 @@ Foam::fileOperation::New
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
Foam::autoPtr<Foam::fileOperation>
|
||||||
|
Foam::fileOperation::New
|
||||||
bool Foam::fileOperation::distributed(bool on) const noexcept
|
(
|
||||||
|
const word& handlerType,
|
||||||
|
const label comm,
|
||||||
|
const labelUList& ioRanks,
|
||||||
|
const bool distributedRoots,
|
||||||
|
bool verbose
|
||||||
|
)
|
||||||
{
|
{
|
||||||
bool old(distributed_);
|
if (handlerType.empty())
|
||||||
distributed_ = on;
|
{
|
||||||
return old;
|
if (fileOperation::defaultFileHandler.empty())
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "defaultFileHandler name is undefined" << nl
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileOperation::New
|
||||||
|
(
|
||||||
|
fileOperation::defaultFileHandler,
|
||||||
|
comm,
|
||||||
|
ioRanks,
|
||||||
|
distributedRoots,
|
||||||
|
verbose
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugInFunction
|
||||||
|
<< "Constructing fileHandler" << endl;
|
||||||
|
|
||||||
|
auto* ctorPtr = commConstructorTable(handlerType);
|
||||||
|
|
||||||
|
if (!ctorPtr)
|
||||||
|
{
|
||||||
|
FatalErrorInLookup
|
||||||
|
(
|
||||||
|
"fileHandler",
|
||||||
|
handlerType,
|
||||||
|
*commConstructorTablePtr_
|
||||||
|
) << abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
return autoPtr<fileOperation>
|
||||||
|
(
|
||||||
|
ctorPtr
|
||||||
|
(
|
||||||
|
comm,
|
||||||
|
ioRanks,
|
||||||
|
distributedRoots,
|
||||||
|
verbose
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::fileName Foam::fileOperation::objectPath
|
Foam::fileName Foam::fileOperation::objectPath
|
||||||
(
|
(
|
||||||
const IOobject& io,
|
const IOobject& io,
|
||||||
@ -1209,8 +1613,18 @@ Foam::fileNameList Foam::fileOperation::readObjects
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::fileOperation::setNProcs(const label nProcs)
|
Foam::label Foam::fileOperation::nProcs(const label numProcs)
|
||||||
{}
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Pout<< "fileOperation::nProcs :"
|
||||||
|
<< " Setting number of processors to " << numProcs << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
label old(nProcs_);
|
||||||
|
nProcs_ = numProcs;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::label Foam::fileOperation::nProcs
|
Foam::label Foam::fileOperation::nProcs
|
||||||
@ -1273,6 +1687,23 @@ void Foam::fileOperation::flush() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::fileOperation::sync()
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Pout<< "fileOperation::sync : parallel synchronisation"
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pstream::broadcasts
|
||||||
|
(
|
||||||
|
UPstream::worldComm,
|
||||||
|
nProcs_,
|
||||||
|
procsDirs_
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::fileName Foam::fileOperation::processorsCasePath
|
Foam::fileName Foam::fileOperation::processorsCasePath
|
||||||
(
|
(
|
||||||
const IOobject& io,
|
const IOobject& io,
|
||||||
@ -1511,37 +1942,56 @@ const Foam::fileOperation& Foam::fileHandler()
|
|||||||
{
|
{
|
||||||
if (!fileOperation::fileHandlerPtr_)
|
if (!fileOperation::fileHandlerPtr_)
|
||||||
{
|
{
|
||||||
word handler(Foam::getEnv("FOAM_FILEHANDLER"));
|
word handlerType(Foam::getEnv("FOAM_FILEHANDLER"));
|
||||||
|
|
||||||
if (handler.empty())
|
if (handlerType.empty())
|
||||||
{
|
{
|
||||||
handler = fileOperation::defaultFileHandler;
|
handlerType = fileOperation::defaultFileHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileOperation::fileHandlerPtr_ = fileOperation::New(handler, true);
|
fileOperation::fileHandlerPtr_ = fileOperation::New(handlerType, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return *fileOperation::fileHandlerPtr_;
|
return *fileOperation::fileHandlerPtr_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::autoPtr<Foam::fileOperation>
|
||||||
|
Foam::fileHandler(std::nullptr_t)
|
||||||
|
{
|
||||||
|
return autoPtr<fileOperation>(fileOperation::fileHandlerPtr_.release());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::autoPtr<Foam::fileOperation>
|
Foam::autoPtr<Foam::fileOperation>
|
||||||
Foam::fileHandler(autoPtr<fileOperation>&& newHandler)
|
Foam::fileHandler(autoPtr<fileOperation>&& newHandler)
|
||||||
{
|
{
|
||||||
|
// - do nothing if newHandler is empty. Does not delete current
|
||||||
|
// - do nothing if newHandler is identical to current handler
|
||||||
|
|
||||||
|
// Change ownership as atomic operations
|
||||||
|
|
||||||
|
// If newHandler and current handler are actually identical, we
|
||||||
|
// have a bit problem somewhere else since this means that the pointer
|
||||||
|
// is managed is done in two places!
|
||||||
|
// Should flag as a FatalError (in the future), but there may still be
|
||||||
|
// some place where we would like to fake shared pointers?
|
||||||
|
|
||||||
|
// TBD: add a flush() operation on the old handler first,
|
||||||
|
// instead of waiting for it to be run on destruction?
|
||||||
|
|
||||||
|
autoPtr<fileOperation> old;
|
||||||
|
|
||||||
if
|
if
|
||||||
(
|
(
|
||||||
newHandler
|
newHandler.get() != nullptr
|
||||||
&& fileOperation::fileHandlerPtr_
|
&& newHandler.get() != fileOperation::fileHandlerPtr_.get()
|
||||||
&& newHandler->type() == fileOperation::fileHandlerPtr_->type()
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return nullptr; // No change
|
old.reset(newHandler.release());
|
||||||
|
old.swap(fileOperation::fileHandlerPtr_);
|
||||||
}
|
}
|
||||||
|
|
||||||
autoPtr<fileOperation> old(std::move(fileOperation::fileHandlerPtr_));
|
|
||||||
|
|
||||||
fileOperation::fileHandlerPtr_ = std::move(newHandler);
|
|
||||||
|
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -43,11 +43,12 @@ Description
|
|||||||
|
|
||||||
#include "ISstream.H"
|
#include "ISstream.H"
|
||||||
#include "Ostream.H"
|
#include "Ostream.H"
|
||||||
#include "autoPtr.H"
|
#include "fileMonitor.H"
|
||||||
#include "fileNameList.H"
|
#include "fileNameList.H"
|
||||||
#include "instantList.H"
|
#include "instantList.H"
|
||||||
#include "fileMonitor.H"
|
#include "autoPtr.H"
|
||||||
#include "refPtr.H"
|
#include "refPtr.H"
|
||||||
|
#include "bitSet.H"
|
||||||
#include "Enum.H"
|
#include "Enum.H"
|
||||||
#include "Tuple2.H"
|
#include "Tuple2.H"
|
||||||
|
|
||||||
@ -108,14 +109,29 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
// Protected Static Data
|
||||||
|
|
||||||
|
//- Cache level (eg, for caching time directories). Default: 1
|
||||||
|
static int cacheLevel_;
|
||||||
|
|
||||||
|
|
||||||
// Protected Data
|
// Protected Data
|
||||||
|
|
||||||
//- Communicator to use
|
//- Communicator to use
|
||||||
const label comm_;
|
mutable label comm_;
|
||||||
|
|
||||||
|
//- Overall number of processors.
|
||||||
|
// Used to synthesise processor directory naming:
|
||||||
|
// - parallel: Pstream::nProcs()
|
||||||
|
// - non-parallel: detected from processor dir naming ('processorsNN')
|
||||||
|
label nProcs_;
|
||||||
|
|
||||||
//- Distributed roots (parallel run)
|
//- Distributed roots (parallel run)
|
||||||
mutable bool distributed_;
|
mutable bool distributed_;
|
||||||
|
|
||||||
|
//- Ranks (in comm_) of IO handlers
|
||||||
|
const labelList ioRanks_;
|
||||||
|
|
||||||
//- Detected processors directories
|
//- Detected processors directories
|
||||||
mutable HashTable<dirIndexList> procsDirs_;
|
mutable HashTable<dirIndexList> procsDirs_;
|
||||||
|
|
||||||
@ -128,9 +144,6 @@ protected:
|
|||||||
//- Get or create fileMonitor singleton
|
//- Get or create fileMonitor singleton
|
||||||
fileMonitor& monitor() const;
|
fileMonitor& monitor() const;
|
||||||
|
|
||||||
//- Retrieve list of IO ranks from FOAM_IORANKS env variable
|
|
||||||
static labelList ioRanks();
|
|
||||||
|
|
||||||
//- Merge two times
|
//- Merge two times
|
||||||
static void mergeTimes
|
static void mergeTimes
|
||||||
(
|
(
|
||||||
@ -189,13 +202,26 @@ public:
|
|||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
//- Construct from communicator, optionally with distributed roots
|
//- Construct from communicator,
|
||||||
|
//- optionally with specified io-ranks and/or distributed roots
|
||||||
explicit fileOperation
|
explicit fileOperation
|
||||||
(
|
(
|
||||||
const label comm,
|
const label comm,
|
||||||
|
const labelUList& ioRanks = labelUList::null(),
|
||||||
const bool distributedRoots = false
|
const bool distributedRoots = false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//- Construct from communicator with specified io-ranks
|
||||||
|
explicit fileOperation
|
||||||
|
(
|
||||||
|
const Tuple2<label, labelList>& commAndIORanks,
|
||||||
|
const bool distributedRoots = false
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//- Clone fileHandler
|
||||||
|
/// virtual autoPtr<fileOperation> clone() const = 0;
|
||||||
|
|
||||||
|
|
||||||
// Declare run-time constructor selection table
|
// Declare run-time constructor selection table
|
||||||
|
|
||||||
@ -210,16 +236,42 @@ public:
|
|||||||
(verbose)
|
(verbose)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
declareRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
autoPtr,
|
||||||
|
fileOperation,
|
||||||
|
comm,
|
||||||
|
(
|
||||||
|
const label comm,
|
||||||
|
const labelUList& ioRanks,
|
||||||
|
const bool distributedRoots,
|
||||||
|
bool verbose
|
||||||
|
),
|
||||||
|
(comm, ioRanks, distributedRoots, verbose)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
// Selectors
|
// Selectors
|
||||||
|
|
||||||
//- Select fileHandler-type
|
//- Select fileHandler-type.
|
||||||
|
//- Uses defaultFileHandler if the handlerType is empty.
|
||||||
static autoPtr<fileOperation> New
|
static autoPtr<fileOperation> New
|
||||||
(
|
(
|
||||||
const word& handlerType,
|
const word& handlerType,
|
||||||
bool verbose = false
|
bool verbose = false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//- Select fileHandler-type.
|
||||||
|
//- Uses defaultFileHandler if the handlerType is empty.
|
||||||
|
static autoPtr<fileOperation> New
|
||||||
|
(
|
||||||
|
const word& handlerType,
|
||||||
|
const label comm,
|
||||||
|
const labelUList& ioRanks,
|
||||||
|
const bool distributedRoots,
|
||||||
|
bool verbose
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
//- Destructor
|
//- Destructor
|
||||||
virtual ~fileOperation() = default;
|
virtual ~fileOperation() = default;
|
||||||
@ -227,6 +279,20 @@ public:
|
|||||||
|
|
||||||
// Static Functions
|
// Static Functions
|
||||||
|
|
||||||
|
//- Return cache level
|
||||||
|
static int cacheLevel() noexcept
|
||||||
|
{
|
||||||
|
return cacheLevel_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Set cache level (0 = off). \return the previous value
|
||||||
|
static int cacheLevel(int level) noexcept
|
||||||
|
{
|
||||||
|
int old(cacheLevel_);
|
||||||
|
cacheLevel_ = level;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
//- Sort directory entries according to time value,
|
//- Sort directory entries according to time value,
|
||||||
// with "constant" appearing first (if it exists)
|
// with "constant" appearing first (if it exists)
|
||||||
static instantList sortTimes
|
static instantList sortTimes
|
||||||
@ -235,19 +301,55 @@ public:
|
|||||||
const word& constantName = "constant"
|
const word& constantName = "constant"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//- True if the file names are identical. False on an empty list
|
||||||
|
static bool uniformFile(const fileNameList& names);
|
||||||
|
|
||||||
|
//- True if the file name is identical on all ranks
|
||||||
|
static bool uniformFile(const label comm, const fileName& name);
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
|
// Characteristics
|
||||||
|
|
||||||
|
//- Communicator to use
|
||||||
|
label comm() const noexcept
|
||||||
|
{
|
||||||
|
return comm_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Set communicator to use [mutable]. Negative values are a no-op.
|
||||||
|
// \return old value
|
||||||
|
label comm(label communicator) const noexcept
|
||||||
|
{
|
||||||
|
label old(comm_);
|
||||||
|
if (communicator > 0) comm_ = communicator;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
//- Distributed roots (parallel run)
|
//- Distributed roots (parallel run)
|
||||||
bool distributed() const noexcept
|
bool distributed() const noexcept
|
||||||
{
|
{
|
||||||
return distributed_;
|
return distributed_;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Set distributed roots on/off (mutable)
|
//- Set distributed roots on/off [mutable]
|
||||||
// \return old value
|
// \return old value
|
||||||
bool distributed(bool on) const noexcept;
|
bool distributed(bool on) const noexcept
|
||||||
|
{
|
||||||
|
bool old(distributed_);
|
||||||
|
distributed_ = on;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Retrieve list of IO ranks (in the local communicator)
|
||||||
|
virtual const labelList& ioRanks() const
|
||||||
|
{
|
||||||
|
return ioRanks_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
// OSSpecific equivalents
|
// OSSpecific equivalents
|
||||||
|
|
||||||
@ -531,12 +633,28 @@ public:
|
|||||||
return processorsBaseDir;
|
return processorsBaseDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Set number of processor directories/results. Only used in
|
//- Overall number of processors,
|
||||||
// decomposePar
|
//- eg, detected from directories/results.
|
||||||
virtual void setNProcs(const label nProcs);
|
virtual label nProcs() const
|
||||||
|
{
|
||||||
|
return nProcs_;
|
||||||
|
}
|
||||||
|
|
||||||
//- Get number of processor directories/results. Used for e.g.
|
//- Set number of processor directories/results.
|
||||||
// reconstructPar, argList checking
|
// Used to cache format of e.g. processorsDDD.
|
||||||
|
// Returns old number of processors.
|
||||||
|
// Only used in decomposePar
|
||||||
|
virtual label nProcs(const label numProcs);
|
||||||
|
|
||||||
|
//- Set number of processor directories/results.
|
||||||
|
// Only used in decomposePar
|
||||||
|
virtual label setNProcs(const label numProcs)
|
||||||
|
{
|
||||||
|
return nProcs(numProcs);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Get number of processor directories/results.
|
||||||
|
// Used for e.g. reconstructPar, argList checking
|
||||||
virtual label nProcs
|
virtual label nProcs
|
||||||
(
|
(
|
||||||
const fileName& dir,
|
const fileName& dir,
|
||||||
@ -564,6 +682,9 @@ public:
|
|||||||
//- Forcibly wait until all output done. Flush any cached data
|
//- Forcibly wait until all output done. Flush any cached data
|
||||||
virtual void flush() const;
|
virtual void flush() const;
|
||||||
|
|
||||||
|
//- Forcibly parallel sync
|
||||||
|
virtual void sync();
|
||||||
|
|
||||||
//- Generate path (like io.path) from root+casename with any
|
//- Generate path (like io.path) from root+casename with any
|
||||||
// 'processorXXX' replaced by procDir (usually 'processsors')
|
// 'processorXXX' replaced by procDir (usually 'processsors')
|
||||||
fileName processorsCasePath
|
fileName processorsCasePath
|
||||||
@ -603,6 +724,40 @@ public:
|
|||||||
|
|
||||||
//- Detect processor number from '/aa/bb/processorDDD/cc'
|
//- Detect processor number from '/aa/bb/processorDDD/cc'
|
||||||
static label detectProcessorPath(const fileName& objPath);
|
static label detectProcessorPath(const fileName& objPath);
|
||||||
|
|
||||||
|
|
||||||
|
// Rank selection/sub-selection
|
||||||
|
|
||||||
|
//- Get the list of global IO ranks from FOAM_IORANKS env variable,
|
||||||
|
//- subsetted by a list of processor ranks,
|
||||||
|
//- with optional fallback by hostname
|
||||||
|
static labelList getGlobalIORanks
|
||||||
|
(
|
||||||
|
const bitSet& useProc = bitSet::null(),
|
||||||
|
const bool useHost = false
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Get the list of global IO ranks from FOAM_IORANKS env variable,
|
||||||
|
//- no subsetting, with optional fallback by hostname
|
||||||
|
static labelList getGlobalIORanks(const bool useHost)
|
||||||
|
{
|
||||||
|
return fileOperation::getGlobalIORanks(bitSet::null(), useHost);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Get the list of global ranks that share the same IO rank
|
||||||
|
//- as myProcNo, subjected to subsetting by a list of processor ranks
|
||||||
|
static labelList getGlobalSubRanks
|
||||||
|
(
|
||||||
|
const bitSet& useProc = bitSet::null(),
|
||||||
|
const bool useHost = false
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Get the list of global ranks that share the same IO rank.
|
||||||
|
//- as myProcNo. Uses getGlobalIORanks
|
||||||
|
static labelList getGlobalSubRanks(const bool useHost)
|
||||||
|
{
|
||||||
|
return fileOperation::getGlobalSubRanks(bitSet::null(), useHost);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -628,11 +783,21 @@ inline Ostream& operator<<(Ostream& os, const fileOperation::pathType b)
|
|||||||
|
|
||||||
// Note: defined in fileOperation.C
|
// Note: defined in fileOperation.C
|
||||||
|
|
||||||
//- Get current file handler
|
//- Return the current file handler.
|
||||||
|
//- Will create the default file handler if necessary.
|
||||||
const fileOperation& fileHandler();
|
const fileOperation& fileHandler();
|
||||||
|
|
||||||
//- Replace, reset file handler.
|
//- Delete current file handler.
|
||||||
// \return old handler on change, null otherwise
|
// \returns the old handler
|
||||||
|
autoPtr<fileOperation> fileHandler(std::nullptr_t);
|
||||||
|
|
||||||
|
//- Replace the current file handler.
|
||||||
|
// The following are considered no-ops:
|
||||||
|
// - an empty/invalid newHandler does \b not delete,
|
||||||
|
// use fileHandler(std::nullptr_t) - ie, a literal \c nullptr for that
|
||||||
|
// - if new handler and current handler are identical (same pointer).
|
||||||
|
// .
|
||||||
|
// \returns the old handler (on change), nullptr otherwise
|
||||||
autoPtr<fileOperation> fileHandler(autoPtr<fileOperation>&& newHandler);
|
autoPtr<fileOperation> fileHandler(autoPtr<fileOperation>&& newHandler);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -88,6 +88,12 @@ class masterUncollatedFileOperation
|
|||||||
:
|
:
|
||||||
public fileOperation
|
public fileOperation
|
||||||
{
|
{
|
||||||
|
// Private Data
|
||||||
|
|
||||||
|
//- Communicator allocated/managed by us
|
||||||
|
label managedComm_;
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Any initialisation steps after constructing
|
//- Any initialisation steps after constructing
|
||||||
@ -97,9 +103,6 @@ protected:
|
|||||||
|
|
||||||
// Protected Data
|
// Protected Data
|
||||||
|
|
||||||
//- Any communicator allocated by me
|
|
||||||
const label myComm_;
|
|
||||||
|
|
||||||
//- Cached times for a given directory
|
//- Cached times for a given directory
|
||||||
mutable HashPtrTable<DynamicList<instant>> times_;
|
mutable HashPtrTable<DynamicList<instant>> times_;
|
||||||
|
|
||||||
@ -388,9 +391,6 @@ protected:
|
|||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Get the list of processors that are part of this communicator
|
|
||||||
static labelList subRanks(const label n);
|
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
Type scatterList(const UList<Type>&, const int, const label comm) const;
|
Type scatterList(const UList<Type>&, const int, const label comm) const;
|
||||||
|
|
||||||
@ -432,6 +432,7 @@ protected:
|
|||||||
const bool checkGlobal,
|
const bool checkGlobal,
|
||||||
const bool isFile,
|
const bool isFile,
|
||||||
const IOobject& io,
|
const IOobject& io,
|
||||||
|
const dirIndexList& pDirs,
|
||||||
const bool search,
|
const bool search,
|
||||||
pathType& searchType,
|
pathType& searchType,
|
||||||
word& processorsDir,
|
word& processorsDir,
|
||||||
@ -470,6 +471,8 @@ protected:
|
|||||||
// without parent searchign and instance searching
|
// without parent searchign and instance searching
|
||||||
bool exists(const dirIndexList&, IOobject& io) const;
|
bool exists(const dirIndexList&, IOobject& io) const;
|
||||||
|
|
||||||
|
//- Helper: output which ranks are IO
|
||||||
|
void printRanks() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -490,8 +493,22 @@ public:
|
|||||||
//- Default construct
|
//- Default construct
|
||||||
explicit masterUncollatedFileOperation(bool verbose);
|
explicit masterUncollatedFileOperation(bool verbose);
|
||||||
|
|
||||||
//- Construct from communicator
|
//- Construct from communicator with specified io-ranks
|
||||||
masterUncollatedFileOperation(const label comm, bool verbose);
|
masterUncollatedFileOperation
|
||||||
|
(
|
||||||
|
const Tuple2<label, labelList>& commAndIORanks,
|
||||||
|
const bool distributedRoots,
|
||||||
|
bool verbose
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct from communicator with specified io-ranks
|
||||||
|
masterUncollatedFileOperation
|
||||||
|
(
|
||||||
|
const label comm,
|
||||||
|
const labelUList& ioRanks,
|
||||||
|
const bool distributedRoots,
|
||||||
|
bool verbose
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
//- Destructor
|
//- Destructor
|
||||||
@ -744,9 +761,6 @@ public:
|
|||||||
|
|
||||||
// Other
|
// Other
|
||||||
|
|
||||||
//- Same file?
|
|
||||||
static bool uniformFile(const fileNameList&);
|
|
||||||
|
|
||||||
//- Get sorted list of times
|
//- Get sorted list of times
|
||||||
virtual instantList findTimes(const fileName&, const word&) const;
|
virtual instantList findTimes(const fileName&, const word&) const;
|
||||||
|
|
||||||
@ -767,6 +781,9 @@ public:
|
|||||||
//- Forcibly wait until all output done. Flush any cached data
|
//- Forcibly wait until all output done. Flush any cached data
|
||||||
virtual void flush() const;
|
virtual void flush() const;
|
||||||
|
|
||||||
|
//- Forcibly parallel sync
|
||||||
|
virtual void sync();
|
||||||
|
|
||||||
//- Return cached times
|
//- Return cached times
|
||||||
const HashPtrTable<DynamicList<instant>>& times() const noexcept
|
const HashPtrTable<DynamicList<instant>>& times() const noexcept
|
||||||
{
|
{
|
||||||
|
|||||||
@ -0,0 +1,155 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2022 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/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "hostUncollatedFileOperation.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
namespace fileOperations
|
||||||
|
{
|
||||||
|
defineTypeNameAndDebug(hostUncollatedFileOperation, 0);
|
||||||
|
addToRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
fileOperation,
|
||||||
|
hostUncollatedFileOperation,
|
||||||
|
word
|
||||||
|
);
|
||||||
|
addToRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
fileOperation,
|
||||||
|
hostUncollatedFileOperation,
|
||||||
|
comm
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register initialisation routine. Signals need for threaded mpi and
|
||||||
|
// handles command line arguments
|
||||||
|
addNamedToRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
fileOperationInitialise,
|
||||||
|
hostUncollatedFileOperationInitialise,
|
||||||
|
word,
|
||||||
|
hostUncollated
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::fileOperations::hostUncollatedFileOperation::init(bool verbose)
|
||||||
|
{
|
||||||
|
verbose = (verbose && Foam::infoDetailLevel > 0);
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
{
|
||||||
|
DetailInfo
|
||||||
|
<< "I/O : " << this->type() << nl;
|
||||||
|
|
||||||
|
if (ioRanks().size())
|
||||||
|
{
|
||||||
|
masterUncollatedFileOperation::printRanks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::fileOperations::hostUncollatedFileOperation::hostUncollatedFileOperation
|
||||||
|
(
|
||||||
|
bool verbose
|
||||||
|
)
|
||||||
|
:
|
||||||
|
masterUncollatedFileOperation
|
||||||
|
(
|
||||||
|
UPstream::allocateCommunicator
|
||||||
|
(
|
||||||
|
UPstream::worldComm,
|
||||||
|
fileOperation::getGlobalSubRanks(true) // Host
|
||||||
|
),
|
||||||
|
fileOperation::getGlobalIORanks(true), // Host
|
||||||
|
false, // distributedRoots
|
||||||
|
false // verbose
|
||||||
|
),
|
||||||
|
managedComm_(comm_)
|
||||||
|
{
|
||||||
|
init(verbose);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::fileOperations::hostUncollatedFileOperation::hostUncollatedFileOperation
|
||||||
|
(
|
||||||
|
const Tuple2<label, labelList>& commAndIORanks,
|
||||||
|
const bool distributedRoots,
|
||||||
|
bool verbose
|
||||||
|
)
|
||||||
|
:
|
||||||
|
masterUncollatedFileOperation
|
||||||
|
(
|
||||||
|
commAndIORanks,
|
||||||
|
distributedRoots,
|
||||||
|
false // verbose
|
||||||
|
),
|
||||||
|
managedComm_(-1) // Externally managed
|
||||||
|
{
|
||||||
|
init(verbose);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::fileOperations::hostUncollatedFileOperation::
|
||||||
|
hostUncollatedFileOperation
|
||||||
|
(
|
||||||
|
const label comm,
|
||||||
|
const labelUList& ioRanks,
|
||||||
|
const bool distributedRoots,
|
||||||
|
bool verbose
|
||||||
|
)
|
||||||
|
:
|
||||||
|
masterUncollatedFileOperation(comm, ioRanks, distributedRoots, false),
|
||||||
|
managedComm_(comm_)
|
||||||
|
{
|
||||||
|
init(verbose);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::fileOperations::hostUncollatedFileOperation::
|
||||||
|
~hostUncollatedFileOperation()
|
||||||
|
{
|
||||||
|
// Wait for any outstanding file operations
|
||||||
|
flush();
|
||||||
|
|
||||||
|
if (myComm_ != -1 && myComm_ != UPstream::worldComm)
|
||||||
|
{
|
||||||
|
UPstream::freeCommunicator(comm_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,132 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2022 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/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::fileOperations::hostUncollatedFileOperation
|
||||||
|
|
||||||
|
Description
|
||||||
|
Version of masterUncollated with host-based IO ranks
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef Foam_fileOperations_hostUncollatedFileOperation_H
|
||||||
|
#define Foam_fileOperations_hostUncollatedFileOperation_H
|
||||||
|
|
||||||
|
#include "masterUncollatedFileOperation.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
namespace fileOperations
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class hostUncollatedFileOperation Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class hostUncollatedFileOperation
|
||||||
|
:
|
||||||
|
public masterUncollatedFileOperation
|
||||||
|
{
|
||||||
|
// Private Data
|
||||||
|
|
||||||
|
//- Communicator allocated/managed by us
|
||||||
|
label managedComm_;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Any initialisation steps after constructing
|
||||||
|
void init(bool verbose);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("hostUncollated");
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Default construct
|
||||||
|
explicit hostUncollatedFileOperation(bool verbose);
|
||||||
|
|
||||||
|
//- Construct from communicator with specified io-ranks
|
||||||
|
hostUncollatedFileOperation
|
||||||
|
(
|
||||||
|
const Tuple2<label, labelList>& commAndIORanks,
|
||||||
|
const bool distributedRoots,
|
||||||
|
bool verbose
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct from communicator with specified io-ranks
|
||||||
|
hostUncollatedFileOperation
|
||||||
|
(
|
||||||
|
const label comm,
|
||||||
|
const labelUList& ioRanks,
|
||||||
|
const bool distributedRoots,
|
||||||
|
bool verbose
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~hostUncollatedFileOperation();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class hostUncollatedFileOperationInitialise Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class hostUncollatedFileOperationInitialise
|
||||||
|
:
|
||||||
|
public masterUncollatedFileOperationInitialise
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from components
|
||||||
|
hostUncollatedFileOperationInitialise(int& argc, char**& argv)
|
||||||
|
:
|
||||||
|
masterUncollatedFileOperationInitialise(argc, argv)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~hostUncollatedFileOperationInitialise() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace fileOperations
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -42,6 +42,12 @@ namespace fileOperations
|
|||||||
{
|
{
|
||||||
defineTypeNameAndDebug(uncollatedFileOperation, 0);
|
defineTypeNameAndDebug(uncollatedFileOperation, 0);
|
||||||
addToRunTimeSelectionTable(fileOperation, uncollatedFileOperation, word);
|
addToRunTimeSelectionTable(fileOperation, uncollatedFileOperation, word);
|
||||||
|
addToRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
fileOperation,
|
||||||
|
uncollatedFileOperation,
|
||||||
|
comm
|
||||||
|
);
|
||||||
|
|
||||||
// Mark as not needing threaded mpi
|
// Mark as not needing threaded mpi
|
||||||
addNamedToRunTimeSelectionTable
|
addNamedToRunTimeSelectionTable
|
||||||
@ -159,7 +165,7 @@ Foam::fileName Foam::fileOperations::uncollatedFileOperation::filePathInfo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fileName::null;
|
return fileName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -174,6 +180,46 @@ Foam::fileOperations::uncollatedFileOperation::lookupProcessorsPath
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Construction helper
|
||||||
|
static Tuple2<label, labelList> getCommPattern()
|
||||||
|
{
|
||||||
|
// With useHost == false
|
||||||
|
|
||||||
|
Tuple2<label, labelList> commAndIORanks;
|
||||||
|
|
||||||
|
if (fileOperation::getGlobalIORanks(false).empty())
|
||||||
|
{
|
||||||
|
// No specified IO ranks
|
||||||
|
// Master of communicator is the one that writes
|
||||||
|
commAndIORanks.first() =
|
||||||
|
UPstream::allocateCommunicator
|
||||||
|
(
|
||||||
|
UPstream::worldComm,
|
||||||
|
labelList(Foam::one{}, Pstream::myProcNo(UPstream::worldComm))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Group by IO ranks
|
||||||
|
commAndIORanks.first() =
|
||||||
|
UPstream::allocateCommunicator
|
||||||
|
(
|
||||||
|
UPstream::worldComm,
|
||||||
|
fileOperation::getGlobalSubRanks(false)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return commAndIORanks;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
void Foam::fileOperations::uncollatedFileOperation::init(bool verbose)
|
void Foam::fileOperations::uncollatedFileOperation::init(bool verbose)
|
||||||
@ -193,12 +239,59 @@ Foam::fileOperations::uncollatedFileOperation::uncollatedFileOperation
|
|||||||
bool verbose
|
bool verbose
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
fileOperation(Pstream::worldComm)
|
fileOperation
|
||||||
|
(
|
||||||
|
getCommPattern()
|
||||||
|
),
|
||||||
|
managedComm_(comm_)
|
||||||
{
|
{
|
||||||
init(verbose);
|
init(verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::fileOperations::uncollatedFileOperation::uncollatedFileOperation
|
||||||
|
(
|
||||||
|
const Tuple2<label, labelList>& commAndIORanks,
|
||||||
|
const bool distributedRoots,
|
||||||
|
bool verbose
|
||||||
|
)
|
||||||
|
:
|
||||||
|
fileOperation(commAndIORanks, distributedRoots),
|
||||||
|
managedComm_(-1) // Externally managed
|
||||||
|
{
|
||||||
|
init(verbose);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::fileOperations::uncollatedFileOperation::uncollatedFileOperation
|
||||||
|
(
|
||||||
|
const label comm,
|
||||||
|
const labelUList& ioRanks,
|
||||||
|
const bool distributedRoots,
|
||||||
|
bool verbose
|
||||||
|
)
|
||||||
|
:
|
||||||
|
fileOperation(comm, ioRanks, distributedRoots),
|
||||||
|
managedComm_(-1) // Externally managed
|
||||||
|
{
|
||||||
|
init(verbose);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::fileOperations::uncollatedFileOperation::~uncollatedFileOperation()
|
||||||
|
{
|
||||||
|
// Wait for any outstanding file operations
|
||||||
|
flush();
|
||||||
|
|
||||||
|
if (managedComm_ >= 0 && managedComm_ != UPstream::worldComm)
|
||||||
|
{
|
||||||
|
UPstream::freeCommunicator(managedComm_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Filesystem Operations * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Filesystem Operations * * * * * * * * * * * * * //
|
||||||
|
|
||||||
bool Foam::fileOperations::uncollatedFileOperation::mkDir
|
bool Foam::fileOperations::uncollatedFileOperation::mkDir
|
||||||
|
|||||||
@ -53,6 +53,12 @@ class uncollatedFileOperation
|
|||||||
:
|
:
|
||||||
public fileOperation
|
public fileOperation
|
||||||
{
|
{
|
||||||
|
// Private Data
|
||||||
|
|
||||||
|
//- Communicator allocated/managed by us
|
||||||
|
label managedComm_;
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Any initialisation steps after constructing
|
//- Any initialisation steps after constructing
|
||||||
@ -84,8 +90,8 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//- Runtime type information
|
//- Runtime type information
|
||||||
TypeName("uncollated");
|
TypeName("uncollated");
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
@ -93,9 +99,26 @@ public:
|
|||||||
//- Default construct
|
//- Default construct
|
||||||
explicit uncollatedFileOperation(bool verbose);
|
explicit uncollatedFileOperation(bool verbose);
|
||||||
|
|
||||||
|
//- Construct from communicator with specified io-ranks
|
||||||
|
uncollatedFileOperation
|
||||||
|
(
|
||||||
|
const Tuple2<label, labelList>& commAndIORanks,
|
||||||
|
const bool distributedRoots,
|
||||||
|
bool verbose
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct from communicator with specified io-ranks
|
||||||
|
uncollatedFileOperation
|
||||||
|
(
|
||||||
|
const label comm,
|
||||||
|
const labelUList& ioRanks,
|
||||||
|
const bool distributedRoots,
|
||||||
|
bool verbose
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
//- Destructor
|
//- Destructor
|
||||||
virtual ~uncollatedFileOperation() = default;
|
virtual ~uncollatedFileOperation();
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
# \\ / A nd | www.openfoam.com
|
# \\ / A nd | www.openfoam.com
|
||||||
# \\/ M anipulation |
|
# \\/ M anipulation |
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# Copyright (C) 2018-2020 OpenCFD Ltd.
|
# Copyright (C) 2018-2022 OpenCFD Ltd.
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# License
|
# License
|
||||||
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
||||||
@ -212,7 +212,7 @@ then
|
|||||||
findLibrary()
|
findLibrary()
|
||||||
{
|
{
|
||||||
local prefixDir localDir searchDir searchName
|
local prefixDir localDir searchDir searchName
|
||||||
local file ext
|
local file found ext zshsplit
|
||||||
|
|
||||||
searchDir=true
|
searchDir=true
|
||||||
|
|
||||||
@ -264,6 +264,13 @@ then
|
|||||||
|
|
||||||
## echo "search: $# $@" 1>&2
|
## echo "search: $# $@" 1>&2
|
||||||
|
|
||||||
|
# Split extLibraries on space, but zsh does not like that
|
||||||
|
if [ -n "$ZSH_VERSION" ]
|
||||||
|
then
|
||||||
|
case "$-" in (*y*) zshsplit=y;; esac
|
||||||
|
setopt shwordsplit
|
||||||
|
fi
|
||||||
|
|
||||||
for searchDir in "$@"
|
for searchDir in "$@"
|
||||||
do
|
do
|
||||||
[ -n "$searchDir" ] || continue
|
[ -n "$searchDir" ] || continue
|
||||||
@ -272,8 +279,8 @@ then
|
|||||||
file="$prefixDir/$searchDir/$searchName$ext"
|
file="$prefixDir/$searchDir/$searchName$ext"
|
||||||
if [ -f "$file" ] && [ -r "$file" ]
|
if [ -f "$file" ] && [ -r "$file" ]
|
||||||
then
|
then
|
||||||
echo "$file" # Found
|
found="$file" # Found
|
||||||
return 0
|
break 2
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
@ -281,6 +288,13 @@ then
|
|||||||
else
|
else
|
||||||
# Directed search
|
# Directed search
|
||||||
|
|
||||||
|
# Split extLibraries on space, but zsh does not like that
|
||||||
|
if [ -n "$ZSH_VERSION" ]
|
||||||
|
then
|
||||||
|
case "$-" in (*y*) zshsplit=y;; esac
|
||||||
|
setopt shwordsplit
|
||||||
|
fi
|
||||||
|
|
||||||
for file
|
for file
|
||||||
do
|
do
|
||||||
[ -n "$file" ] || continue
|
[ -n "$file" ] || continue
|
||||||
@ -288,13 +302,27 @@ then
|
|||||||
do
|
do
|
||||||
if [ -f "$file$ext" ] && [ -r "$file$ext" ]
|
if [ -f "$file$ext" ] && [ -r "$file$ext" ]
|
||||||
then
|
then
|
||||||
echo "$file$ext" # Found
|
found="$file$ext" # Found
|
||||||
return 0
|
break 2
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Restore word splitting (zsh)
|
||||||
|
|
||||||
|
# Restore case "$-" in (*y*) zshsplit=y;; esac
|
||||||
|
if [ -n "$ZSH_VERSION" ] && [ -z "$zshsplit" ]
|
||||||
|
then
|
||||||
|
unsetopt shwordsplit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$found" ]
|
||||||
|
then
|
||||||
|
echo "$found"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user