Compare commits
44 Commits
postreleas
...
feature-po
| Author | SHA1 | Date | |
|---|---|---|---|
| a4aa16b509 | |||
| 343126df7b | |||
| c5e6c70cfa | |||
| 89e1de29a1 | |||
| 268851c5e2 | |||
| e0cf4209a8 | |||
| 1426191fa2 | |||
| ec3bca90fc | |||
| 8b85e5c932 | |||
| 506802bbea | |||
| 0c20009587 | |||
| 5a0fba84b4 | |||
| 732c8b3330 | |||
| ff567dbe71 | |||
| e3b7c2e6ee | |||
| 84a1fc9b4f | |||
| 47c44a5783 | |||
| 91a1eaa01b | |||
| fcf090410a | |||
| 19a6241e08 | |||
| 52f5a6d039 | |||
| fe1d7e01d6 | |||
| cb416fb3ec | |||
| 4ae4f0928d | |||
| 6dadd3d33e | |||
| 3a43aae7c0 | |||
| 9ad3754ed7 | |||
| d6781b91fe | |||
| d9c5a5d1a9 | |||
| fc9820b08a | |||
| f9bbd06e57 | |||
| 182afc27ba | |||
| 0bf39691ff | |||
| 312c7a1c32 | |||
| 0ae3da8560 | |||
| 44c594dbff | |||
| a889e5eba6 | |||
| 3d0cb79be3 | |||
| ebe49d4cbd | |||
| 62524b140c | |||
| a46b310fa4 | |||
| 1dc216eb1f | |||
| c4328296b0 | |||
| 52ab1fc06f |
@ -9,6 +9,7 @@ It is likely incomplete...
|
||||
- Yu Ankun
|
||||
- Tetsuo Aoyagi
|
||||
- Akira Azami
|
||||
- Pete Bachant
|
||||
- William Bainbridge
|
||||
- Gabriel Barajas
|
||||
- Kutalmis Bercin
|
||||
|
||||
@ -135,14 +135,14 @@ public:
|
||||
virtual volScalarField& he()
|
||||
{
|
||||
NotImplemented;
|
||||
return thermo1_->he();
|
||||
return const_cast<volScalarField&>(volScalarField::null());
|
||||
}
|
||||
|
||||
//- Enthalpy/Internal energy [J/kg]
|
||||
virtual const volScalarField& he() const
|
||||
{
|
||||
NotImplemented;
|
||||
return thermo1_->he();
|
||||
return volScalarField::null();
|
||||
}
|
||||
|
||||
//- Enthalpy/Internal energy
|
||||
@ -213,7 +213,7 @@ public:
|
||||
) const
|
||||
{
|
||||
NotImplemented;
|
||||
return tmp<scalarField>::New(p);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//- Heat capacity at constant volume [J/kg/K]
|
||||
@ -236,7 +236,7 @@ public:
|
||||
) const
|
||||
{
|
||||
NotImplemented;
|
||||
return tmp<scalarField>::New(p);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//- Gamma = Cp/Cv []
|
||||
|
||||
@ -243,14 +243,14 @@ public:
|
||||
virtual volScalarField& he()
|
||||
{
|
||||
NotImplemented;
|
||||
return phases_[0].thermo().he();
|
||||
return const_cast<volScalarField&>(volScalarField::null());
|
||||
}
|
||||
|
||||
//- Enthalpy/Internal energy [J/kg]
|
||||
virtual const volScalarField& he() const
|
||||
{
|
||||
NotImplemented;
|
||||
return phases_[0].thermo().he();
|
||||
return volScalarField::null();
|
||||
}
|
||||
|
||||
//- Enthalpy/Internal energy
|
||||
@ -327,7 +327,7 @@ public:
|
||||
) const
|
||||
{
|
||||
NotImplemented;
|
||||
return tmp<scalarField>::New(p);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//- Heat capacity at constant volume [J/kg/K]
|
||||
@ -350,7 +350,7 @@ public:
|
||||
) const
|
||||
{
|
||||
NotImplemented;
|
||||
return tmp<scalarField>::New(p);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//- Gamma = Cp/Cv []
|
||||
|
||||
@ -86,14 +86,14 @@ public:
|
||||
virtual volScalarField& he()
|
||||
{
|
||||
NotImplemented;
|
||||
return p();
|
||||
return const_cast<volScalarField&>(volScalarField::null());
|
||||
}
|
||||
|
||||
//- Return access to the internal energy field [J/Kg]
|
||||
virtual const volScalarField& he() const
|
||||
{
|
||||
NotImplemented;
|
||||
return p();
|
||||
return volScalarField::null();
|
||||
}
|
||||
|
||||
//- Enthalpy/Internal energy
|
||||
@ -182,7 +182,7 @@ public:
|
||||
) const
|
||||
{
|
||||
NotImplemented;
|
||||
return tmp<scalarField>::New(p);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//- Return Cv of the mixture
|
||||
@ -205,7 +205,7 @@ public:
|
||||
) const
|
||||
{
|
||||
NotImplemented;
|
||||
return tmp<scalarField>::New(p);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//- Gamma = Cp/Cv []
|
||||
|
||||
@ -412,7 +412,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
{
|
||||
Info<< "range-for of list (" << list1.count() << '/'
|
||||
Info<< "range-for of list (" << list1.count_nonnull() << '/'
|
||||
<< list1.size() << ") non-null entries" << nl
|
||||
<< "(" << nl;
|
||||
for (const auto& item : list1)
|
||||
|
||||
@ -64,6 +64,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
// Add some more entries
|
||||
{
|
||||
label idx = 0;
|
||||
dictionary subdict;
|
||||
|
||||
subdict.add("key", 100);
|
||||
@ -72,23 +73,30 @@ int main(int argc, char *argv[])
|
||||
|
||||
subdict.add
|
||||
(
|
||||
new formattingEntry(10, "// comment - without newline.")
|
||||
new formattingEntry(++idx, "// comment - without newline.")
|
||||
);
|
||||
|
||||
subdict.add
|
||||
(
|
||||
// NB newline must be part of the content!
|
||||
new formattingEntry(11, "// some comment - with newline?\n")
|
||||
new formattingEntry(++idx, "// some comment - with newline?\n")
|
||||
);
|
||||
|
||||
subdict.add
|
||||
(
|
||||
// NB newline must be part of the content!
|
||||
new formattingEntry(12, "/* other comment */\n")
|
||||
new formattingEntry(++idx, "/* other comment */\n")
|
||||
);
|
||||
|
||||
// Other - invisible
|
||||
subdict.add(new formattingEntry(++idx, token(123), false));
|
||||
|
||||
// Other - visible (probably not what anyone wants!)
|
||||
subdict.add(new formattingEntry(++idx, token(456)));
|
||||
|
||||
subdict.add("val", 42);
|
||||
|
||||
Info<< "subdict keys:" << flatOutput(subdict.toc()) << nl;
|
||||
dict.add("subdict", std::move(subdict));
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
Test-gatherValues1.C
|
||||
Test-gatherValues1.cxx
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-gatherValues1
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2021-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2021-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -52,7 +52,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
const labelList localValues
|
||||
(
|
||||
identity(2 *(Pstream::myProcNo()+1), -5*Pstream::myProcNo())
|
||||
identity(2 *(UPstream::myProcNo()+1), -5*UPstream::myProcNo())
|
||||
);
|
||||
|
||||
// Test resize
|
||||
@ -76,8 +76,8 @@ int main(int argc, char *argv[])
|
||||
// One-sided sizing! master only
|
||||
const globalIndex allProcAddr
|
||||
(
|
||||
sendData.size(),
|
||||
globalIndex::gatherOnly{}
|
||||
globalIndex::gatherOnly{},
|
||||
sendData.size()
|
||||
);
|
||||
|
||||
Pout<< "listGather sizes: " << flatOutput(allProcAddr.sizes()) << nl;
|
||||
@ -98,8 +98,8 @@ int main(int argc, char *argv[])
|
||||
// One-sided sizing! master only
|
||||
const globalIndex allProcAddr
|
||||
(
|
||||
sendData.size(),
|
||||
globalIndex::gatherOnly{}
|
||||
globalIndex::gatherOnly{},
|
||||
sendData.size()
|
||||
);
|
||||
|
||||
Pout<< "listGather sizes: " << flatOutput(allProcAddr.sizes()) << nl;
|
||||
@ -116,7 +116,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
const labelList::subList& sendData =
|
||||
(
|
||||
Pstream::master()
|
||||
UPstream::master()
|
||||
? SubList<label>(localValues, 0) // exclude
|
||||
: SubList<label>(localValues)
|
||||
);
|
||||
@ -147,11 +147,11 @@ int main(int argc, char *argv[])
|
||||
<< UPstream::listScatterValues(subProcAddr.offsets()) << nl;
|
||||
|
||||
|
||||
Pout<< endl << "local list [" << Pstream::myProcNo() << "] "
|
||||
Pout<< endl << "local list [" << UPstream::myProcNo() << "] "
|
||||
<< flatOutput(localValues) << nl;
|
||||
|
||||
|
||||
Pout<< endl << "local send [" << Pstream::myProcNo() << "] "
|
||||
Pout<< endl << "local send [" << UPstream::myProcNo() << "] "
|
||||
<< sendSize << nl;
|
||||
|
||||
|
||||
@ -163,7 +163,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
Pout<< "off-proc: " << allValues << endl;
|
||||
|
||||
if (Pstream::master())
|
||||
if (UPstream::master())
|
||||
{
|
||||
Info<< "master: " << flatOutput(localValues) << nl;
|
||||
|
||||
@ -196,7 +196,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
globalIndex glob
|
||||
(
|
||||
globalIndex:gatherNone{},
|
||||
globalIndex::gatherNone{},
|
||||
labelList(Foam::one{}, 0)
|
||||
);
|
||||
Info<< "single:" << nl;
|
||||
@ -208,35 +208,37 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
// This will likely fail - not declared as is_contiguous
|
||||
// Cannot even catch since it triggers an abort()
|
||||
|
||||
#if 0
|
||||
// Non-contiguous gather - use Pstream, not UPstream!
|
||||
{
|
||||
std::pair<label,vector> sendData(Pstream::myProcNo(), vector::one);
|
||||
typedef std::pair<label,vector> valueType;
|
||||
|
||||
const bool oldThrowingError = FatalError.throwing(true);
|
||||
valueType sendData(UPstream::myProcNo(), vector::one);
|
||||
|
||||
try
|
||||
{
|
||||
List<std::pair<label,vector>> countValues
|
||||
(
|
||||
UPstream::listGatherValues<std::pair<label, vector>>
|
||||
(
|
||||
sendData
|
||||
)
|
||||
);
|
||||
List<valueType> countValues
|
||||
(
|
||||
Pstream::listGatherValues(sendData)
|
||||
);
|
||||
|
||||
Pout<< "listGather: " << flatOutput(countValues) << nl;
|
||||
}
|
||||
catch (const Foam::error& err)
|
||||
{
|
||||
Info<< err.message().c_str() << nl;
|
||||
}
|
||||
|
||||
FatalError.throwing(oldThrowingError);
|
||||
Pout<< "listGather: " << flatOutput(countValues) << nl;
|
||||
}
|
||||
|
||||
// Non-contiguous scatter - use Pstream, not UPstream!
|
||||
{
|
||||
List<fileName> allValues;
|
||||
|
||||
if (UPstream::master())
|
||||
{
|
||||
allValues.resize(UPstream::nProcs());
|
||||
forAll(allValues, proci)
|
||||
{
|
||||
allValues[proci] = "processor" + Foam::name(proci);
|
||||
}
|
||||
}
|
||||
|
||||
fileName procName = Pstream::listScatterValues(allValues);
|
||||
|
||||
Pout<< "listScatter: " << procName << nl;
|
||||
}
|
||||
#endif
|
||||
|
||||
Info<< "\nEnd\n" << endl;
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2014 OpenFOAM Foundation
|
||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||
Copyright (C) 2019-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -48,7 +48,7 @@ class SimpleClass
|
||||
public:
|
||||
|
||||
//- Default construct
|
||||
SimpleClass() {}
|
||||
SimpleClass() = default;
|
||||
};
|
||||
|
||||
|
||||
@ -73,9 +73,8 @@ void printInfo(const UList<T>& list)
|
||||
int main()
|
||||
{
|
||||
// Test pointer and reference to a class
|
||||
|
||||
SimpleClass* ptrToClass = new SimpleClass;
|
||||
SimpleClass& refToClass(*ptrToClass);
|
||||
auto ptrToClass = autoPtr<SimpleClass>::New();
|
||||
auto& refToClass = ptrToClass.ref();
|
||||
|
||||
std::cout
|
||||
<< "nullObject addr=" << name(&(nullObjectPtr)) << nl
|
||||
@ -89,13 +88,13 @@ int main()
|
||||
<< " pointer:" << name(nullObjectPtr->pointer()) << nl
|
||||
<< " value:" << nullObjectPtr->value() << nl << nl;
|
||||
|
||||
if (notNull(ptrToClass))
|
||||
if (notNull(ptrToClass.get()))
|
||||
{
|
||||
Info<< "Pass: ptrToClass is not null" << nl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "FAIL: refToClass is null" << nl;
|
||||
Info<< "FAIL: ptrToClass is null" << nl;
|
||||
}
|
||||
|
||||
if (notNull(refToClass))
|
||||
@ -110,8 +109,8 @@ int main()
|
||||
|
||||
// Test pointer and reference to the nullObject
|
||||
|
||||
const SimpleClass* ptrToNull(NullObjectPtr<SimpleClass>());
|
||||
const SimpleClass& refToNull(*ptrToNull);
|
||||
const SimpleClass* ptrToNull = NullObjectPtr<SimpleClass>();
|
||||
const SimpleClass& refToNull = (*ptrToNull);
|
||||
|
||||
if (isNull(ptrToNull))
|
||||
{
|
||||
@ -131,9 +130,6 @@ int main()
|
||||
Info<< "FAIL: refToNull is not null" << nl;
|
||||
}
|
||||
|
||||
// Clean-up
|
||||
delete ptrToClass;
|
||||
|
||||
|
||||
// Test List casting
|
||||
{
|
||||
@ -152,7 +148,7 @@ int main()
|
||||
// Looks pretty ugly though!
|
||||
|
||||
NullObject::nullObject = "hello world";
|
||||
NullObject::nullObject = labelList({1, 2, 3});
|
||||
NullObject::nullObject = Foam::identity(5);
|
||||
|
||||
Info<< nl;
|
||||
|
||||
|
||||
@ -50,37 +50,37 @@ scalar sumReduce
|
||||
)
|
||||
{
|
||||
scalar sum = 0;
|
||||
if (Pstream::parRun())
|
||||
if (UPstream::parRun())
|
||||
{
|
||||
if (UPstream::master(comm))
|
||||
{
|
||||
// Add master value and all slaves
|
||||
// Add master value and all sub-procs
|
||||
sum = localValue;
|
||||
|
||||
for (const int slave : UPstream::subProcs(comm))
|
||||
for (const int proci : UPstream::subProcs(comm))
|
||||
{
|
||||
scalar slaveValue;
|
||||
scalar procValue;
|
||||
UIPstream::read
|
||||
(
|
||||
Pstream::commsTypes::blocking,
|
||||
slave,
|
||||
reinterpret_cast<char*>(&slaveValue),
|
||||
UPstream::commsTypes::blocking,
|
||||
proci,
|
||||
reinterpret_cast<char*>(&procValue),
|
||||
sizeof(scalar),
|
||||
UPstream::msgType(), // tag
|
||||
comm // communicator
|
||||
);
|
||||
|
||||
sum += slaveValue;
|
||||
sum += procValue;
|
||||
}
|
||||
|
||||
// Send back to slaves
|
||||
// Send back
|
||||
|
||||
for (const int slave : UPstream::subProcs(comm))
|
||||
for (const int proci : UPstream::subProcs(comm))
|
||||
{
|
||||
UOPstream::write
|
||||
(
|
||||
UPstream::commsTypes::blocking,
|
||||
slave,
|
||||
proci,
|
||||
reinterpret_cast<const char*>(&sum),
|
||||
sizeof(scalar),
|
||||
UPstream::msgType(), // tag
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2020 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -52,27 +52,27 @@ void testMapDistribute()
|
||||
|
||||
// Generate random data.
|
||||
List<Tuple2<label, List<scalar>>> complexData(100);
|
||||
forAll(complexData, i)
|
||||
for (auto& data : complexData)
|
||||
{
|
||||
complexData[i].first() = rndGen.position(0, Pstream::nProcs()-1);
|
||||
complexData[i].second().setSize(3);
|
||||
complexData[i].second()[0] = 1;
|
||||
complexData[i].second()[1] = 2;
|
||||
complexData[i].second()[2] = 3;
|
||||
data.first() = rndGen.position(0, UPstream::nProcs()-1);
|
||||
data.second().resize(3);
|
||||
data.second()[0] = 1;
|
||||
data.second()[1] = 2;
|
||||
data.second()[2] = 3;
|
||||
}
|
||||
|
||||
// Send all ones to processor indicated by .first()
|
||||
|
||||
// Count how many to send
|
||||
labelList nSend(Pstream::nProcs(), Zero);
|
||||
forAll(complexData, i)
|
||||
labelList nSend(UPstream::nProcs(), Foam::zero{});
|
||||
for (const auto& data : complexData)
|
||||
{
|
||||
const label proci = complexData[i].first();
|
||||
const label proci = data.first();
|
||||
nSend[proci]++;
|
||||
}
|
||||
|
||||
// Collect items to be sent
|
||||
labelListList sendMap(Pstream::nProcs());
|
||||
labelListList sendMap(UPstream::nProcs());
|
||||
forAll(sendMap, proci)
|
||||
{
|
||||
sendMap[proci].resize_nocopy(nSend[proci]);
|
||||
@ -116,40 +116,31 @@ void testTransfer(const T& input)
|
||||
{
|
||||
T data = input;
|
||||
|
||||
if (Pstream::master())
|
||||
if (UPstream::master())
|
||||
{
|
||||
Perr<<"test transfer (" << (typeid(T).name()) << "): ";
|
||||
perrInfo(data) << nl << endl;
|
||||
}
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
for (const int slave : Pstream::subProcs())
|
||||
for (const int proci : UPstream::subProcs())
|
||||
{
|
||||
Perr<< "master receiving from slave " << slave << endl;
|
||||
IPstream fromSlave(Pstream::commsTypes::blocking, slave);
|
||||
fromSlave >> data;
|
||||
Perr<< "master receiving from proc:" << proci << endl;
|
||||
IPstream::recv(data, proci);
|
||||
perrInfo(data) << endl;
|
||||
}
|
||||
|
||||
for (const int slave : Pstream::subProcs())
|
||||
for (const int proci : UPstream::subProcs())
|
||||
{
|
||||
Perr<< "master sending to slave " << slave << endl;
|
||||
OPstream toSlave(Pstream::commsTypes::blocking, slave);
|
||||
toSlave << data;
|
||||
Perr<< "master sending to proc:" << proci << endl;
|
||||
OPstream::bsend(data, proci);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
Perr<< "slave sending to master " << Pstream::masterNo() << endl;
|
||||
OPstream toMaster(Pstream::commsTypes::blocking, Pstream::masterNo());
|
||||
toMaster << data;
|
||||
}
|
||||
Perr<< "proc sending to master" << endl;
|
||||
OPstream::bsend(data, UPstream::masterNo());
|
||||
|
||||
Perr<< "slave receiving from master " << Pstream::masterNo() << endl;
|
||||
IPstream fromMaster(Pstream::commsTypes::blocking, Pstream::masterNo());
|
||||
fromMaster >> data;
|
||||
Perr<< "proc receiving from master" << endl;
|
||||
IPstream::recv(data, UPstream::masterNo());
|
||||
perrInfo(data) << endl;
|
||||
}
|
||||
}
|
||||
@ -160,49 +151,31 @@ void testTokenized(const T& data)
|
||||
{
|
||||
token tok;
|
||||
|
||||
if (Pstream::master())
|
||||
if (UPstream::master())
|
||||
{
|
||||
Perr<<"test tokenized \"" << data << "\"" << nl << endl;
|
||||
}
|
||||
Perr<< "test tokenized \"" << data << "\"" << nl << endl;
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
for (const int slave : Pstream::subProcs())
|
||||
for (const int proci : UPstream::subProcs())
|
||||
{
|
||||
Perr<< "master receiving from slave " << slave << endl;
|
||||
IPstream fromSlave(Pstream::commsTypes::blocking, slave);
|
||||
fromSlave >> tok;
|
||||
Perr<< "master receiving from proc:" << proci << endl;
|
||||
IPstream::recv(tok, proci);
|
||||
Perr<< tok.info() << endl;
|
||||
}
|
||||
|
||||
for (const int slave : Pstream::subProcs())
|
||||
for (const int proci : UPstream::subProcs())
|
||||
{
|
||||
Perr<< "master sending to slave " << slave << endl;
|
||||
OPstream toSlave(Pstream::commsTypes::blocking, slave);
|
||||
toSlave << data;
|
||||
Perr<< "master sending to proc:" << proci << endl;
|
||||
OPstream::bsend(tok, proci);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
Perr<< "slave sending to master " << Pstream::masterNo() << endl;
|
||||
OPstream toMaster
|
||||
(
|
||||
Pstream::commsTypes::blocking,
|
||||
Pstream::masterNo()
|
||||
);
|
||||
Perr<< "proc sending to master" << endl;
|
||||
OPstream::bsend(tok, UPstream::masterNo());
|
||||
|
||||
toMaster << data;
|
||||
}
|
||||
Perr<< "proc receiving from master" << endl;
|
||||
IPstream::recv(tok, UPstream::masterNo());
|
||||
|
||||
Perr<< "slave receiving from master " << Pstream::masterNo() << endl;
|
||||
IPstream fromMaster
|
||||
(
|
||||
Pstream::commsTypes::blocking,
|
||||
Pstream::masterNo()
|
||||
);
|
||||
|
||||
fromMaster >> tok;
|
||||
Perr<< tok.info() << endl;
|
||||
}
|
||||
}
|
||||
@ -212,12 +185,14 @@ void testTokenized(const T& data)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
argList::noCheckProcessorDirectories();
|
||||
|
||||
#include "setRootCase.H"
|
||||
#include "createTime.H"
|
||||
|
||||
testMapDistribute();
|
||||
|
||||
if (!Pstream::parRun())
|
||||
if (!UPstream::parRun())
|
||||
{
|
||||
Info<< "\nWarning: not parallel - skipping further tests\n" << endl;
|
||||
return 0;
|
||||
|
||||
11
applications/test/syncTools/missing_cell/Allclean
Executable file
11
applications/test/syncTools/missing_cell/Allclean
Executable file
@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
cd "${0%/*}" || exit # Run from this directory
|
||||
. ${WM_PROJECT_DIR:?}/bin/tools/CleanFunctions # Tutorial clean functions
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
cleanCase
|
||||
|
||||
# Remove surface and features
|
||||
rm -rf constant/triSurface
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
27
applications/test/syncTools/missing_cell/Allrun
Executable file
27
applications/test/syncTools/missing_cell/Allrun
Executable file
@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
cd "${0%/*}" || exit # Run from this directory
|
||||
. ${WM_PROJECT_DIR:?}/bin/tools/RunFunctions # Tutorial run functions
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
#- Generate 2x2x1 cells
|
||||
runApplication blockMesh
|
||||
|
||||
#- Remove cell0
|
||||
runApplication topoSet
|
||||
runApplication subsetMesh c0 -patch exposed0 -overwrite
|
||||
|
||||
#- Put exposed faces (2) into separate patches
|
||||
runApplication -s face topoSet
|
||||
runApplication createPatch -overwrite
|
||||
|
||||
#- Decompose - creates one processor without any faces in patches
|
||||
runApplication decomposePar
|
||||
|
||||
#- Extract inter-patch points. Should include processor that does not
|
||||
#- have faces on patch ...
|
||||
mkdir -p constant/triSurface
|
||||
runParallel surfaceMeshExtract \
|
||||
-patches '(exposed0 exposed1)' -featureAngle 180 \
|
||||
constant/triSurface/blockMesh.obj
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
7
applications/test/syncTools/missing_cell/README.txt
Normal file
7
applications/test/syncTools/missing_cell/README.txt
Normal file
@ -0,0 +1,7 @@
|
||||
- 2x2x1 mesh
|
||||
- remove one cell, exposing two faces
|
||||
- move exposed faces into two patches
|
||||
- decompose onto 3
|
||||
- run surfaceMeshExtract -featureAngle 180
|
||||
- should also mark points on the processor that has no
|
||||
faces but is coupled
|
||||
@ -0,0 +1,21 @@
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: v2312 |
|
||||
| \\ / A nd | Website: www.openfoam.com |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
FoamFile
|
||||
{
|
||||
version 2.0;
|
||||
format ascii;
|
||||
class dictionary;
|
||||
location "constant";
|
||||
object transportProperties;
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
nu 0.01;
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,88 @@
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: v2312 |
|
||||
| \\ / A nd | Website: www.openfoam.com |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
FoamFile
|
||||
{
|
||||
version 2.0;
|
||||
format ascii;
|
||||
class dictionary;
|
||||
object blockMeshDict;
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
scale 1;
|
||||
|
||||
vertices
|
||||
(
|
||||
//- Single block
|
||||
(0 0 0)
|
||||
(2 0 0)
|
||||
(2 2 0)
|
||||
(0 2 0)
|
||||
(0 0 2)
|
||||
(2 0 2)
|
||||
(2 2 2)
|
||||
(0 2 2)
|
||||
);
|
||||
|
||||
blocks
|
||||
(
|
||||
hex (0 1 2 3 4 5 6 7) (2 2 1) simpleGrading (1 1 1)
|
||||
);
|
||||
|
||||
edges
|
||||
(
|
||||
);
|
||||
|
||||
boundary
|
||||
(
|
||||
topWall
|
||||
{
|
||||
type wall;
|
||||
faces
|
||||
(
|
||||
(3 7 6 2)
|
||||
);
|
||||
}
|
||||
bottomWall
|
||||
{
|
||||
type wall;
|
||||
faces
|
||||
(
|
||||
(1 5 4 0)
|
||||
);
|
||||
}
|
||||
fixedWalls
|
||||
{
|
||||
type wall;
|
||||
faces
|
||||
(
|
||||
(0 4 7 3)
|
||||
(2 6 5 1)
|
||||
);
|
||||
}
|
||||
frontAndBack
|
||||
{
|
||||
type patch;
|
||||
faces
|
||||
(
|
||||
(0 3 2 1)
|
||||
(4 5 6 7)
|
||||
);
|
||||
}
|
||||
exposed0
|
||||
{
|
||||
type patch;
|
||||
faces ();
|
||||
}
|
||||
);
|
||||
|
||||
mergePatchPairs
|
||||
(
|
||||
);
|
||||
|
||||
// ************************************************************************* //
|
||||
48
applications/test/syncTools/missing_cell/system/controlDict
Normal file
48
applications/test/syncTools/missing_cell/system/controlDict
Normal file
@ -0,0 +1,48 @@
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: v2312 |
|
||||
| \\ / A nd | Website: www.openfoam.com |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
FoamFile
|
||||
{
|
||||
version 2.0;
|
||||
format ascii;
|
||||
class dictionary;
|
||||
location "system";
|
||||
object controlDict;
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
application icoFoam;
|
||||
|
||||
startFrom startTime;
|
||||
|
||||
startTime 0;
|
||||
|
||||
stopAt endTime;
|
||||
|
||||
endTime 0.5;
|
||||
|
||||
deltaT 0.005;
|
||||
|
||||
writeControl timeStep;
|
||||
|
||||
writeInterval 20;
|
||||
|
||||
purgeWrite 0;
|
||||
|
||||
writeFormat ascii;
|
||||
|
||||
writePrecision 16;
|
||||
|
||||
writeCompression off;
|
||||
|
||||
timeFormat general;
|
||||
|
||||
timePrecision 6;
|
||||
|
||||
runTimeModifiable true;
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,44 @@
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: v2312 |
|
||||
| \\ / A nd | Website: www.openfoam.com |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
FoamFile
|
||||
{
|
||||
version 2.0;
|
||||
format ascii;
|
||||
class dictionary;
|
||||
object createPatchDict;
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
pointSync false;
|
||||
|
||||
// Patches to create.
|
||||
patches
|
||||
(
|
||||
// Example of creating mapped patches using geometric matching
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
{
|
||||
// Name of new patch
|
||||
name exposed1;
|
||||
|
||||
// Dictionary to construct new patch from
|
||||
patchInfo
|
||||
{
|
||||
type patch;
|
||||
}
|
||||
|
||||
// How to select the faces:
|
||||
// - set : specify faceSet in 'set'
|
||||
// - patches : specify names in 'patches'
|
||||
// - autoPatch : attempts automatic patching of the specified
|
||||
// candidates in 'patches'.
|
||||
constructFrom set;
|
||||
set exposed0;
|
||||
}
|
||||
);
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,24 @@
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: v2312 |
|
||||
| \\ / A nd | Website: www.openfoam.com |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
FoamFile
|
||||
{
|
||||
version 2.0;
|
||||
format ascii;
|
||||
class dictionary;
|
||||
note "mesh decomposition control dictionary";
|
||||
object decomposeParDict;
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
//- The total number of domains (mandatory)
|
||||
numberOfSubdomains 3;
|
||||
|
||||
//- The decomposition method (mandatory)
|
||||
method scotch;
|
||||
|
||||
// ************************************************************************* //
|
||||
51
applications/test/syncTools/missing_cell/system/fvSchemes
Normal file
51
applications/test/syncTools/missing_cell/system/fvSchemes
Normal file
@ -0,0 +1,51 @@
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: v2312 |
|
||||
| \\ / A nd | Website: www.openfoam.com |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
FoamFile
|
||||
{
|
||||
version 2.0;
|
||||
format ascii;
|
||||
class dictionary;
|
||||
location "system";
|
||||
object fvSchemes;
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
ddtSchemes
|
||||
{
|
||||
default Euler;
|
||||
}
|
||||
|
||||
gradSchemes
|
||||
{
|
||||
default Gauss linear;
|
||||
grad(p) Gauss linear;
|
||||
}
|
||||
|
||||
divSchemes
|
||||
{
|
||||
default none;
|
||||
div(phi,U) Gauss linear;
|
||||
}
|
||||
|
||||
laplacianSchemes
|
||||
{
|
||||
default Gauss linear orthogonal;
|
||||
}
|
||||
|
||||
interpolationSchemes
|
||||
{
|
||||
default linear;
|
||||
}
|
||||
|
||||
snGradSchemes
|
||||
{
|
||||
default orthogonal;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
52
applications/test/syncTools/missing_cell/system/fvSolution
Normal file
52
applications/test/syncTools/missing_cell/system/fvSolution
Normal file
@ -0,0 +1,52 @@
|
||||
/*--------------------------------*- C++ -*----------------------------------*\
|
||||
| ========= | |
|
||||
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||
| \\ / O peration | Version: v2312 |
|
||||
| \\ / A nd | Website: www.openfoam.com |
|
||||
| \\/ M anipulation | |
|
||||
\*---------------------------------------------------------------------------*/
|
||||
FoamFile
|
||||
{
|
||||
version 2.0;
|
||||
format ascii;
|
||||
class dictionary;
|
||||
location "system";
|
||||
object fvSolution;
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
solvers
|
||||
{
|
||||
p
|
||||
{
|
||||
solver PCG;
|
||||
preconditioner DIC;
|
||||
tolerance 1e-06;
|
||||
relTol 0.05;
|
||||
}
|
||||
|
||||
pFinal
|
||||
{
|
||||
$p;
|
||||
relTol 0;
|
||||
}
|
||||
|
||||
U
|
||||
{
|
||||
solver smoothSolver;
|
||||
smoother symGaussSeidel;
|
||||
tolerance 1e-05;
|
||||
relTol 0;
|
||||
}
|
||||
}
|
||||
|
||||
PISO
|
||||
{
|
||||
nCorrectors 2;
|
||||
nNonOrthogonalCorrectors 0;
|
||||
pRefCell 0;
|
||||
pRefValue 0;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -8,53 +8,41 @@
|
||||
FoamFile
|
||||
{
|
||||
version 2.0;
|
||||
format binary;
|
||||
class volScalarField;
|
||||
object mut;
|
||||
format ascii;
|
||||
class dictionary;
|
||||
object topoSetDict;
|
||||
}
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
dimensions [1 -1 -1 0 0 0 0];
|
||||
|
||||
internalField uniform 0;
|
||||
|
||||
boundaryField
|
||||
{
|
||||
inlet
|
||||
actions
|
||||
(
|
||||
{
|
||||
type calculated;
|
||||
value uniform 0;
|
||||
name c0;
|
||||
type cellSet;
|
||||
action new;
|
||||
source labelToCell;
|
||||
value (0);
|
||||
}
|
||||
{
|
||||
name c0;
|
||||
type cellSet;
|
||||
action invert;
|
||||
}
|
||||
|
||||
outlet
|
||||
{
|
||||
type calculated;
|
||||
value uniform 0;
|
||||
name exposed0;
|
||||
type faceSet;
|
||||
action new;
|
||||
source patchToFace;
|
||||
patch exposed0;
|
||||
}
|
||||
|
||||
symmetry
|
||||
{
|
||||
type symmetryPlane;
|
||||
name exposed0;
|
||||
type faceSet;
|
||||
action subset;
|
||||
source boxToFace;
|
||||
box (-100 1 -100)(100 100 100);
|
||||
}
|
||||
|
||||
walls
|
||||
{
|
||||
type mutkWallFunction;
|
||||
Cmu 0.09;
|
||||
kappa 0.41;
|
||||
E 9.8;
|
||||
value uniform 0;
|
||||
}
|
||||
|
||||
cabin_to_ice
|
||||
{
|
||||
type mutkWallFunction;
|
||||
Cmu 0.09;
|
||||
kappa 0.41;
|
||||
E 9.8;
|
||||
value uniform 0;
|
||||
}
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -51,7 +51,7 @@ void printConnection(Ostream& os, const label proci, const labelUList& below)
|
||||
// The number of receives - as per gatherList (v2112)
|
||||
void printRecvCount_gatherList
|
||||
(
|
||||
const List<UPstream::commsStruct>& comms,
|
||||
const UList<UPstream::commsStruct>& comms,
|
||||
const label comm = UPstream::worldComm
|
||||
)
|
||||
{
|
||||
@ -91,7 +91,7 @@ void printRecvCount_gatherList
|
||||
// The number of sends - as per scatterList (v2112)
|
||||
void printSendCount_scatterList
|
||||
(
|
||||
const List<UPstream::commsStruct>& comms,
|
||||
const UList<UPstream::commsStruct>& comms,
|
||||
const label comm = UPstream::worldComm
|
||||
)
|
||||
{
|
||||
@ -131,7 +131,7 @@ void printSendCount_scatterList
|
||||
// Transmission widths (contiguous data)
|
||||
void printWidths
|
||||
(
|
||||
const List<UPstream::commsStruct>& comms,
|
||||
const UList<UPstream::commsStruct>& comms,
|
||||
const label comm = UPstream::worldComm
|
||||
)
|
||||
{
|
||||
|
||||
@ -579,8 +579,8 @@ inline bool CGAL::indexedCell<Gt, Cb>::potentialCoplanarCell() const
|
||||
|
||||
if (nMasters == 2 && nSlaves == 2)
|
||||
{
|
||||
Foam::vector vp0(Foam::Zero);
|
||||
Foam::vector vp1(Foam::Zero);
|
||||
Foam::vector vp0(Foam::zero{});
|
||||
Foam::vector vp1(Foam::zero{});
|
||||
|
||||
if
|
||||
(
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -220,7 +220,7 @@ PtrList<FieldType> subsetFields
|
||||
const pointMesh& pMesh
|
||||
)
|
||||
{
|
||||
const fvMesh& baseMesh = subsetter.baseMesh();
|
||||
//const fvMesh& baseMesh = subsetter.baseMesh();
|
||||
|
||||
const UPtrList<const IOobject> fieldObjects
|
||||
(
|
||||
@ -247,8 +247,8 @@ PtrList<FieldType> subsetFields
|
||||
IOobject
|
||||
(
|
||||
io.name(),
|
||||
baseMesh.time().timeName(),
|
||||
baseMesh,
|
||||
pMesh.thisDb().time().timeName(),
|
||||
pMesh.thisDb(),
|
||||
IOobjectOption::MUST_READ,
|
||||
IOobjectOption::NO_WRITE,
|
||||
IOobjectOption::NO_REGISTER
|
||||
@ -382,6 +382,8 @@ int main(int argc, char *argv[])
|
||||
#include "createTime.H"
|
||||
|
||||
#include "createNamedMesh.H"
|
||||
// Make sure pointMesh gets constructed/read as well
|
||||
(void)pointMesh::New(mesh, IOobject::READ_IF_PRESENT);
|
||||
|
||||
// arg[1] = word (cellSet) or wordRes (cellZone)
|
||||
// const word selectionName = args[1];
|
||||
@ -583,7 +585,7 @@ int main(int argc, char *argv[])
|
||||
// Read point fields and subset
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
const pointMesh& pMesh = pointMesh::New(mesh);
|
||||
const pointMesh& pMesh = pointMesh::New(mesh, IOobject::READ_IF_PRESENT);
|
||||
|
||||
#undef createSubsetFields
|
||||
#define createSubsetFields(FieldType, Variable) \
|
||||
@ -663,6 +665,18 @@ int main(int argc, char *argv[])
|
||||
subsetter.subMesh().write();
|
||||
processorMeshes::removeFiles(subsetter.subMesh());
|
||||
|
||||
auto* subPointMeshPtr =
|
||||
subsetter.subMesh().thisDb().findObject<pointMesh>
|
||||
(
|
||||
pointMesh::typeName
|
||||
);
|
||||
if (subPointMeshPtr)
|
||||
{
|
||||
pointMesh& subPointMesh = const_cast<pointMesh&>(*subPointMeshPtr);
|
||||
subPointMesh.setInstance(subsetter.subMesh().facesInstance());
|
||||
subPointMesh.write();
|
||||
}
|
||||
|
||||
|
||||
// Volume fields
|
||||
for (const auto& fld : vScalarFlds) { fld.write(); }
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2022,2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -661,6 +661,9 @@ int main(int argc, char *argv[])
|
||||
),
|
||||
decompDictFile
|
||||
);
|
||||
// Make sure pointMesh gets read as well
|
||||
(void)pointMesh::New(mesh, IOobject::READ_IF_PRESENT);
|
||||
|
||||
|
||||
// Decompose the mesh
|
||||
if (!decomposeFieldsOnly)
|
||||
@ -780,6 +783,7 @@ int main(int argc, char *argv[])
|
||||
PtrList<labelIOList> cellProcAddressingList(mesh.nProcs());
|
||||
PtrList<labelIOList> boundaryProcAddressingList(mesh.nProcs());
|
||||
PtrList<labelIOList> pointProcAddressingList(mesh.nProcs());
|
||||
PtrList<labelIOList> pointBoundaryProcAddressingList(mesh.nProcs());
|
||||
|
||||
PtrList<fvFieldDecomposer> fieldDecomposerList(mesh.nProcs());
|
||||
PtrList<pointFieldDecomposer> pointFieldDecomposerList
|
||||
@ -850,7 +854,10 @@ int main(int argc, char *argv[])
|
||||
|
||||
// Point fields
|
||||
// ~~~~~~~~~~~~
|
||||
const pointMesh& pMesh = pointMesh::New(mesh);
|
||||
|
||||
// Read decomposed pointMesh
|
||||
const pointMesh& pMesh =
|
||||
pointMesh::New(mesh, IOobject::READ_IF_PRESENT);
|
||||
|
||||
pointFieldDecomposer::fieldsCache pointFieldCache;
|
||||
|
||||
@ -1119,7 +1126,34 @@ int main(int argc, char *argv[])
|
||||
pointProcAddressingList
|
||||
);
|
||||
|
||||
const pointMesh& procPMesh = pointMesh::New(procMesh);
|
||||
const pointMesh& procPMesh =
|
||||
pointMesh::New(procMesh, IOobject::READ_IF_PRESENT);
|
||||
|
||||
if (!pointBoundaryProcAddressingList.set(proci))
|
||||
{
|
||||
pointBoundaryProcAddressingList.set
|
||||
(
|
||||
proci,
|
||||
autoPtr<labelIOList>::New
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"boundaryProcAddressing",
|
||||
procMesh.facesInstance(),
|
||||
polyMesh::meshSubDir
|
||||
/pointMesh::meshSubDir,
|
||||
procPMesh.thisDb(),
|
||||
IOobject::READ_IF_PRESENT,
|
||||
IOobject::NO_WRITE,
|
||||
IOobject::NO_REGISTER
|
||||
),
|
||||
boundaryProcAddressing
|
||||
)
|
||||
);
|
||||
}
|
||||
const auto& pointBoundaryProcAddressing =
|
||||
pointBoundaryProcAddressingList[proci];
|
||||
|
||||
|
||||
if (!pointFieldDecomposerList.set(proci))
|
||||
{
|
||||
@ -1131,7 +1165,7 @@ int main(int argc, char *argv[])
|
||||
pMesh,
|
||||
procPMesh,
|
||||
pointProcAddressing,
|
||||
boundaryProcAddressing
|
||||
pointBoundaryProcAddressing
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -1143,6 +1177,12 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (times.size() == 1)
|
||||
{
|
||||
// Early deletion
|
||||
pointBoundaryProcAddressingList.set
|
||||
(
|
||||
proci,
|
||||
nullptr
|
||||
);
|
||||
pointProcAddressingList.set(proci, nullptr);
|
||||
pointFieldDecomposerList.set(proci, nullptr);
|
||||
}
|
||||
|
||||
@ -44,6 +44,12 @@ License
|
||||
#include "decompositionModel.H"
|
||||
#include "hexRef8Data.H"
|
||||
|
||||
// For handling pointMeshes with additional patches
|
||||
#include "pointMesh.H"
|
||||
#include "meshPointPatch.H"
|
||||
#include "processorPointPatch.H"
|
||||
#include "DynamicField.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::domainDecomposition::mark
|
||||
@ -740,6 +746,101 @@ bool Foam::domainDecomposition::writeDecomposition(const bool decomposeSets)
|
||||
|
||||
procMesh.write();
|
||||
|
||||
// Add pointMesh if it was available
|
||||
const auto* pMeshPtr =
|
||||
thisDb().cfindObject<pointMesh>(pointMesh::typeName);
|
||||
if (pMeshPtr)
|
||||
{
|
||||
const auto& pMesh = *pMeshPtr;
|
||||
const auto& pMeshBoundary = pMesh.boundary();
|
||||
|
||||
|
||||
// 1. Generate pointBoundaryMesh from polyBoundaryMesh (so ignoring
|
||||
// any additional patches
|
||||
const auto& procPointMesh = pointMesh::New(procMesh);
|
||||
|
||||
pointBoundaryMesh& procBoundary =
|
||||
const_cast<pointBoundaryMesh&>(procPointMesh.boundary());
|
||||
|
||||
|
||||
// 2. Explicitly add subsetted meshPointPatches
|
||||
forAll(pMeshBoundary, patchi)
|
||||
{
|
||||
const auto* mppPtr = isA<meshPointPatch>(pMeshBoundary[patchi]);
|
||||
if (mppPtr && (procBoundary.findPatchID(mppPtr->name()) == -1))
|
||||
{
|
||||
const auto& mpp = *mppPtr;
|
||||
|
||||
DynamicList<label> procMeshPoints(mpp.size());
|
||||
DynamicField<vector> procNormals(mpp.size());
|
||||
forAll(mpp.meshPoints(), i)
|
||||
{
|
||||
const label pointi = mpp.meshPoints()[i];
|
||||
const label procPointi = pointLookup[pointi];
|
||||
if (procPointi != -1)
|
||||
{
|
||||
procMeshPoints.append(procPointi);
|
||||
procNormals.append(mpp.pointNormals()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
procBoundary.push_back
|
||||
(
|
||||
new meshPointPatch
|
||||
(
|
||||
mpp.name(),
|
||||
procMeshPoints,
|
||||
procNormals,
|
||||
procBoundary.size(),
|
||||
procBoundary,
|
||||
meshPointPatch::typeName
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Shuffle new patches before any processor patches
|
||||
labelList oldToNew(procBoundary.size());
|
||||
label newPatchi = 0;
|
||||
forAll(procBoundary, patchi)
|
||||
{
|
||||
if (!isA<processorPointPatch>(procBoundary[patchi]))
|
||||
{
|
||||
oldToNew[patchi] = newPatchi;
|
||||
newPatchi++;
|
||||
}
|
||||
}
|
||||
|
||||
// decomposed-to-undecomposed patch numbering
|
||||
labelList boundaryProcAddressing(identity(newPatchi));
|
||||
boundaryProcAddressing.setSize(procBoundary.size(), -1);
|
||||
|
||||
forAll(procBoundary, patchi)
|
||||
{
|
||||
if (isA<processorPointPatch>(procBoundary[patchi]))
|
||||
{
|
||||
oldToNew[patchi] = newPatchi++;
|
||||
}
|
||||
}
|
||||
procBoundary.reorder(oldToNew, true);
|
||||
|
||||
// Write pointMesh/boundary
|
||||
procBoundary.write();
|
||||
|
||||
// Write pointMesh/boundaryProcAddressing
|
||||
IOobject ioAddr
|
||||
(
|
||||
"boundaryProcAddressing",
|
||||
procMesh.facesInstance(),
|
||||
polyMesh::meshSubDir/pointMesh::meshSubDir,
|
||||
procPointMesh.thisDb(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
IOobject::NO_REGISTER
|
||||
);
|
||||
IOListRef<label>(ioAddr, boundaryProcAddressing).write();
|
||||
}
|
||||
|
||||
// Write points if pointsInstance differing from facesInstance
|
||||
if (facesInstancePointsPtr_)
|
||||
{
|
||||
|
||||
@ -411,24 +411,18 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
Info<< "Reconstructing point fields" << nl << endl;
|
||||
|
||||
const pointMesh& pMesh = pointMesh::New(mesh);
|
||||
PtrList<pointMesh> pMeshes(procMeshes.meshes().size());
|
||||
|
||||
forAll(pMeshes, proci)
|
||||
{
|
||||
pMeshes.set
|
||||
(
|
||||
proci,
|
||||
new pointMesh(procMeshes.meshes()[proci])
|
||||
);
|
||||
}
|
||||
const pointMesh& pMesh = pointMesh::New
|
||||
(
|
||||
mesh,
|
||||
IOobject::READ_IF_PRESENT
|
||||
);
|
||||
|
||||
pointFieldReconstructor reconstructor
|
||||
(
|
||||
pMesh,
|
||||
pMeshes,
|
||||
procMeshes.pointMeshes(),
|
||||
procMeshes.pointProcAddressing(),
|
||||
procMeshes.boundaryProcAddressing()
|
||||
procMeshes.pointMeshBoundaryProcAddressing()
|
||||
);
|
||||
|
||||
reconstructor.reconstructAllFields(objects, selectedFields);
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2017-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -34,10 +34,13 @@ Description
|
||||
Extract patch or faceZone surfaces from a polyMesh.
|
||||
Depending on output surface format triangulates faces.
|
||||
|
||||
Region numbers on faces no guaranteed to be the same as the patch indices.
|
||||
Region numbers on faces not guaranteed to be the same as the patch indices.
|
||||
|
||||
Optionally only extracts named patches.
|
||||
|
||||
Optionally filters out points on feature-edges and generates pointPatches
|
||||
for these - written to pointMesh/boundary.
|
||||
|
||||
If run in parallel, processor patches get filtered out by default and
|
||||
the mesh is merged (based on topology).
|
||||
|
||||
@ -48,6 +51,7 @@ Description
|
||||
#include "argList.H"
|
||||
#include "Time.H"
|
||||
#include "polyMesh.H"
|
||||
#include "pointMesh.H"
|
||||
#include "emptyPolyPatch.H"
|
||||
#include "processorPolyPatch.H"
|
||||
#include "ListListOps.H"
|
||||
@ -55,6 +59,11 @@ Description
|
||||
#include "globalMeshData.H"
|
||||
#include "globalIndex.H"
|
||||
#include "timeSelector.H"
|
||||
#include "meshPointPatch.H"
|
||||
#include "unitConversion.H"
|
||||
#include "dummyTransform.H"
|
||||
#include "syncTools.H"
|
||||
#include "processorPointPatch.H"
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
@ -106,6 +115,551 @@ labelList getSelectedPatches
|
||||
}
|
||||
|
||||
|
||||
label addMeshPointPatches
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const pointMesh& pMesh,
|
||||
|
||||
const uindirectPrimitivePatch& allBoundary,
|
||||
const labelUList& faceToZone,
|
||||
const surfZoneIdentifierList& surfZones,
|
||||
|
||||
const scalar edgeFeatureAngle,
|
||||
const scalar pointFeatureAngle,
|
||||
const bool verbose = true
|
||||
)
|
||||
{
|
||||
const pointBoundaryMesh& pointBm = pMesh.boundary();
|
||||
const label nPointPatches = pointBm.size();
|
||||
|
||||
const globalMeshData& globalData = mesh.globalData();
|
||||
const indirectPrimitivePatch& cpp = globalData.coupledPatch();
|
||||
const mapDistribute& map = globalData.globalEdgeSlavesMap();
|
||||
const auto& mp = allBoundary.meshPoints();
|
||||
|
||||
|
||||
const vector nullVector(vector::uniform(0));
|
||||
const auto assignNonNull = [&](vector& x, const vector& y)
|
||||
{
|
||||
if (x == nullVector && y != nullVector)
|
||||
{
|
||||
x = y;
|
||||
}
|
||||
};
|
||||
|
||||
// Calculate parallel-consistent point normals (as unweighted average
|
||||
// of faceNormals). Note: only valid on patch points, not on mesh points
|
||||
// that are coupled to these.
|
||||
const pointField pointNormals
|
||||
(
|
||||
PatchTools::pointNormals
|
||||
(
|
||||
mesh,
|
||||
allBoundary
|
||||
)
|
||||
);
|
||||
// Expand to all coupled points
|
||||
pointField meshPointNormals(mesh.nPoints(), nullVector);
|
||||
UIndirectList<vector>(meshPointNormals, mp) = pointNormals;
|
||||
syncTools::syncPointList
|
||||
(
|
||||
mesh,
|
||||
meshPointNormals,
|
||||
assignNonNull,
|
||||
nullVector
|
||||
);
|
||||
|
||||
|
||||
// Find correspondence between allBoundary and coupled edges
|
||||
labelList allEdges;
|
||||
labelList coupledEdges;
|
||||
bitSet sameEdgeOrientation;
|
||||
PatchTools::matchEdges
|
||||
(
|
||||
allBoundary,
|
||||
cpp,
|
||||
allEdges,
|
||||
coupledEdges,
|
||||
sameEdgeOrientation
|
||||
);
|
||||
|
||||
|
||||
|
||||
// To construct the patches we need to know per edge
|
||||
// - patch on either side (if topological feature edge)
|
||||
// - faceNormal on either side (if feature angle)
|
||||
// We need to know per point
|
||||
// - patches on all connected faces
|
||||
// - faceNormals on all connected faces? And compare to average?
|
||||
// or edge normals on all connected edges
|
||||
|
||||
|
||||
typedef Tuple2<label, vector> PN;
|
||||
const PN nullPN(-1, nullVector);
|
||||
|
||||
|
||||
|
||||
// Point-based analysis
|
||||
// ~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
// Collect per (mesh)point the zones (1, 2 or >2). Note: per mesh to
|
||||
// make it easier to sync. See edge-based code below where we explicitly
|
||||
// have to transfer from patch-edge to mesh-point etc. Note sure which one
|
||||
// fits better....
|
||||
labelPairList pointToZones(mesh.nPoints(), labelPair(-1, -1));
|
||||
{
|
||||
// Combine zones.
|
||||
const auto combineZones = [&](labelPair& x, const labelPair& y)
|
||||
{
|
||||
if (x == labelPair(-2, -2))
|
||||
{
|
||||
// Already marked
|
||||
}
|
||||
else if (y == labelPair(-2, -2))
|
||||
{
|
||||
x = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find first free slot
|
||||
if (x[0] == -1)
|
||||
{
|
||||
if (y[0] != -1)
|
||||
{
|
||||
x[0] = y[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
x[0] = y[1];
|
||||
}
|
||||
}
|
||||
else if (x[1] == -1)
|
||||
{
|
||||
if (y[0] != -1 && y[0] != x[0])
|
||||
{
|
||||
x[1] = y[0];
|
||||
}
|
||||
else if (y[1] != -1 && y[1] != x[1])
|
||||
{
|
||||
x[1] = y[1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Both x slots filled. See if y adds a 3rd element
|
||||
if (y[0] != -1 && y[0] != x[0] && y[0] != x[1])
|
||||
{
|
||||
x = labelPair(-2, -2);
|
||||
}
|
||||
else if (y[1] != -1 && y[1] != x[0] && y[1] != x[1])
|
||||
{
|
||||
x = labelPair(-2, -2);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
forAll(allBoundary, facei)
|
||||
{
|
||||
const auto& f = allBoundary[facei];
|
||||
const label zonei = faceToZone[facei];
|
||||
for (const label pointi : f)
|
||||
{
|
||||
auto& pZones = pointToZones[pointi];
|
||||
|
||||
if (pZones != labelPair(-2, -2) && !pZones.contains(zonei))
|
||||
{
|
||||
if (pZones.first() == -1)
|
||||
{
|
||||
pZones.first() = zonei;
|
||||
}
|
||||
else if (pZones.second() == -1)
|
||||
{
|
||||
pZones.second() = zonei;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mark as >2 zones
|
||||
pZones = labelPair(-2, -2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
syncTools::syncPointList
|
||||
(
|
||||
mesh,
|
||||
pointToZones,
|
||||
combineZones,
|
||||
labelPair(-1, -1),
|
||||
dummyTransform()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Edge-based analysis
|
||||
// ~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
// 1. Local analysis
|
||||
|
||||
List<Pair<PN>> allEdgeToFaces
|
||||
(
|
||||
allBoundary.nEdges(),
|
||||
Pair<PN>(nullPN, nullPN)
|
||||
);
|
||||
{
|
||||
const auto& edgeFaces = allBoundary.edgeFaces();
|
||||
const auto& faceNormals = allBoundary.faceNormals();
|
||||
|
||||
forAll(edgeFaces, edgei)
|
||||
{
|
||||
const auto& eFaces = edgeFaces[edgei];
|
||||
const vector& n0 = faceNormals[eFaces[0]];
|
||||
const label zone0 = faceToZone[eFaces[0]];
|
||||
if (eFaces.size() == 1)
|
||||
{
|
||||
allEdgeToFaces[edgei] = Pair<PN>(PN(zone0, n0), nullPN);
|
||||
}
|
||||
else
|
||||
{
|
||||
const vector& n1 = faceNormals[eFaces[1]];
|
||||
const label zone1 = faceToZone[eFaces[1]];
|
||||
allEdgeToFaces[edgei] = Pair<PN>
|
||||
(
|
||||
PN(zone0, n0),
|
||||
PN(zone1, n1)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 2. Sync across coupled patches
|
||||
|
||||
{
|
||||
// Combine pair of normals
|
||||
const auto vectorPairMax = [&](Pair<PN>& x, const Pair<PN>& y)
|
||||
{
|
||||
if (x[0] == nullPN)
|
||||
{
|
||||
if (y[0] != nullPN)
|
||||
{
|
||||
x[0] = y[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
x[0] = y[1];
|
||||
}
|
||||
}
|
||||
else if (x[1] == nullPN)
|
||||
{
|
||||
if (y[0] != nullPN && y[0] != x[0])
|
||||
{
|
||||
x[1] = y[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
x[1] = y[1];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
List<Pair<PN>> cppEdgeData
|
||||
(
|
||||
map.constructSize(),
|
||||
Pair<PN>(nullPN, nullPN)
|
||||
);
|
||||
UIndirectList<Pair<PN>>(cppEdgeData, coupledEdges) =
|
||||
UIndirectList<Pair<PN>>(allEdgeToFaces, allEdges);
|
||||
|
||||
globalData.syncData
|
||||
(
|
||||
cppEdgeData,
|
||||
globalData.globalEdgeSlaves(),
|
||||
globalData.globalEdgeTransformedSlaves(),
|
||||
map,
|
||||
globalData.globalTransforms(),
|
||||
vectorPairMax,
|
||||
dummyTransform()
|
||||
);
|
||||
|
||||
UIndirectList<Pair<PN>>(allEdgeToFaces, allEdges) =
|
||||
UIndirectList<Pair<PN>>(cppEdgeData, coupledEdges);
|
||||
}
|
||||
|
||||
|
||||
// Now we have all the per-patch edge information
|
||||
// - do inter-patch edges
|
||||
// - do feature-angle edges
|
||||
// Store on mesh points
|
||||
|
||||
const auto assignNonNullPN = [&](PN& x, const PN& y)
|
||||
{
|
||||
if (x.second() == nullVector && y.second() != nullVector)
|
||||
{
|
||||
x = y;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Storing the normal for points that are on inter-patch edges
|
||||
vectorField patchEdgeNormal(mesh.nPoints(), nullVector);
|
||||
// Storing the normal for points that are on patch-internal feat edges
|
||||
List<PN> featEdgeNormal(mesh.nPoints(), nullPN);
|
||||
forAll(allEdgeToFaces, edgei)
|
||||
{
|
||||
const edge& e = allBoundary.edges()[edgei];
|
||||
const label mp0 = mp[e[0]];
|
||||
const label mp1 = mp[e[1]];
|
||||
|
||||
const Pair<PN>& facesInfo = allEdgeToFaces[edgei];
|
||||
|
||||
if (facesInfo[1] == nullPN)
|
||||
{
|
||||
// Boundary edge
|
||||
patchEdgeNormal[mp0] = pointNormals[e[0]];
|
||||
patchEdgeNormal[mp1] = pointNormals[e[1]];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (facesInfo[0].first() != facesInfo[1].first())
|
||||
{
|
||||
// Inter-patch
|
||||
patchEdgeNormal[mp0] = pointNormals[e[0]];
|
||||
patchEdgeNormal[mp1] = pointNormals[e[1]];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Same patch - check for feature angle
|
||||
|
||||
const vector& n0 = facesInfo[0].second();
|
||||
const vector& n1 = facesInfo[1].second();
|
||||
|
||||
if ((n0 & n1) < Foam::cos(degToRad(edgeFeatureAngle)))
|
||||
{
|
||||
if (patchEdgeNormal[mp0] == nullVector)
|
||||
{
|
||||
featEdgeNormal[mp0] = PN
|
||||
(
|
||||
facesInfo[0].first(), // zone
|
||||
pointNormals[e[0]]
|
||||
);
|
||||
}
|
||||
if (patchEdgeNormal[mp1] == nullVector)
|
||||
{
|
||||
featEdgeNormal[mp1] = PN
|
||||
(
|
||||
facesInfo[0].first(), // zone
|
||||
pointNormals[e[1]]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
syncTools::syncPointList
|
||||
(
|
||||
mesh,
|
||||
patchEdgeNormal,
|
||||
assignNonNull,
|
||||
nullVector
|
||||
);
|
||||
syncTools::syncPointList
|
||||
(
|
||||
mesh,
|
||||
featEdgeNormal,
|
||||
assignNonNullPN,
|
||||
nullPN,
|
||||
dummyTransform()
|
||||
);
|
||||
|
||||
// Make sure that inter-patch points are not also in feature-edge
|
||||
// points. Note: not absolutely nessecary since all inter-patch points
|
||||
// will also be in the 'normal' facePointPatches.
|
||||
|
||||
DynamicList<label> multiZoneMeshPoints(allBoundary.nPoints());
|
||||
forAll(pointToZones, pointi)
|
||||
{
|
||||
if (pointToZones[pointi] == labelPair(-2, -2))
|
||||
{
|
||||
multiZoneMeshPoints.append(pointi);
|
||||
// Unmark as feature angle point
|
||||
patchEdgeNormal[pointi] = nullVector;
|
||||
featEdgeNormal[pointi] = nullPN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DynamicList<label> twoZoneMeshPoints(allBoundary.nPoints());
|
||||
forAll(patchEdgeNormal, pointi)
|
||||
{
|
||||
if (patchEdgeNormal[pointi] != nullVector)
|
||||
{
|
||||
twoZoneMeshPoints.append(pointi);
|
||||
// Unmark as feature angle point
|
||||
featEdgeNormal[pointi] = nullPN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Sort featEdgeNormal according to zone
|
||||
List<List<label>> zoneToMeshPoints(surfZones.size());
|
||||
List<vectorField> zoneToNormal(surfZones.size());
|
||||
{
|
||||
labelList sizes(surfZones.size(), 0);
|
||||
forAll(featEdgeNormal, pointi)
|
||||
{
|
||||
const auto& pInfo = featEdgeNormal[pointi];
|
||||
if (pInfo != nullPN)
|
||||
{
|
||||
const label zonei = pInfo.first();
|
||||
sizes[zonei]++;
|
||||
}
|
||||
}
|
||||
forAll(zoneToMeshPoints, zonei)
|
||||
{
|
||||
zoneToMeshPoints[zonei].setSize(sizes[zonei]);
|
||||
zoneToNormal[zonei].setSize(sizes[zonei]);
|
||||
}
|
||||
sizes = 0;
|
||||
forAll(featEdgeNormal, pointi)
|
||||
{
|
||||
const auto& pInfo = featEdgeNormal[pointi];
|
||||
if (pInfo != nullPN)
|
||||
{
|
||||
const label zonei = pInfo.first();
|
||||
const label index = sizes[zonei]++;
|
||||
zoneToMeshPoints[zonei][index] = pointi;
|
||||
zoneToNormal[zonei][index] = pInfo.second();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add patches
|
||||
forAll(zoneToMeshPoints, zonei)
|
||||
{
|
||||
const label nPoints =
|
||||
returnReduce(zoneToMeshPoints[zonei].size(), sumOp<label>());
|
||||
|
||||
const word patchName(surfZones[zonei].name() + "Edges");
|
||||
|
||||
if (nPoints && (pointBm.findPatchID(patchName) == -1))
|
||||
{
|
||||
const_cast<pointBoundaryMesh&>(pointBm).push_back
|
||||
(
|
||||
new meshPointPatch
|
||||
(
|
||||
patchName,
|
||||
zoneToMeshPoints[zonei],
|
||||
zoneToNormal[zonei],
|
||||
pointBm.size(),
|
||||
pointBm,
|
||||
meshPointPatch::typeName
|
||||
)
|
||||
);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
const auto& ppp = pointBm.last();
|
||||
Info<< "Added feature-edges pointPatch " << ppp.name()
|
||||
<< " with " << nPoints << " points" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add inter-patch points
|
||||
|
||||
const word allEdgePatchName("boundaryEdges");
|
||||
const label nPatchEdgePoints =
|
||||
returnReduce(twoZoneMeshPoints.size(), sumOp<label>());
|
||||
if (nPatchEdgePoints && (pointBm.findPatchID(allEdgePatchName) == -1))
|
||||
{
|
||||
const_cast<pointBoundaryMesh&>(pointBm).push_back
|
||||
(
|
||||
new meshPointPatch
|
||||
(
|
||||
allEdgePatchName,
|
||||
twoZoneMeshPoints,
|
||||
vectorField
|
||||
(
|
||||
patchEdgeNormal, // is pointNormal expanded to all mesh
|
||||
twoZoneMeshPoints
|
||||
),
|
||||
pointBm.size(),
|
||||
pointBm,
|
||||
meshPointPatch::typeName
|
||||
)
|
||||
);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
const auto& ppp = pointBm.last();
|
||||
Info<< "Added inter-patch pointPatch " << ppp.name()
|
||||
<< " with " << nPatchEdgePoints << " points" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const word allPointPatchName("boundaryPoints");
|
||||
const label nMultiPoints =
|
||||
returnReduce(multiZoneMeshPoints.size(), sumOp<label>());
|
||||
if (nMultiPoints && (pointBm.findPatchID(allPointPatchName) == -1))
|
||||
{
|
||||
const_cast<pointBoundaryMesh&>(pointBm).push_back
|
||||
(
|
||||
new meshPointPatch
|
||||
(
|
||||
allPointPatchName,
|
||||
multiZoneMeshPoints,
|
||||
vectorField
|
||||
(
|
||||
meshPointNormals, // is pointNormal expanded to all mesh
|
||||
multiZoneMeshPoints
|
||||
),
|
||||
pointBm.size(),
|
||||
pointBm,
|
||||
meshPointPatch::typeName
|
||||
)
|
||||
);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
const auto& ppp = pointBm.last();
|
||||
Info<< "Added multi-patch pointPatch " << ppp.name()
|
||||
<< " with " << nMultiPoints << " points" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Shuffle into order
|
||||
labelList oldToNew(pointBm.size());
|
||||
label newPatchi = 0;
|
||||
forAll(pointBm, patchi)
|
||||
{
|
||||
if (!isA<processorPointPatch>(pointBm[patchi]))
|
||||
{
|
||||
oldToNew[patchi] = newPatchi++;
|
||||
}
|
||||
}
|
||||
forAll(pointBm, patchi)
|
||||
{
|
||||
if (isA<processorPointPatch>(pointBm[patchi]))
|
||||
{
|
||||
oldToNew[patchi] = newPatchi++;
|
||||
}
|
||||
}
|
||||
const_cast<pointBoundaryMesh&>(pointBm).reorder(oldToNew, true);
|
||||
|
||||
return pointBm.size() - nPointPatches;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@ -152,6 +706,12 @@ int main(int argc, char *argv[])
|
||||
true // mark as an advanced option
|
||||
);
|
||||
argList::addOptionCompat("exclude-patches", {"excludePatches", 2306});
|
||||
argList::addOption
|
||||
(
|
||||
"featureAngle",
|
||||
"angle",
|
||||
"Auto-extract feature edges/points and put into separate point-patches"
|
||||
);
|
||||
|
||||
#include "setRootCase.H"
|
||||
#include "createTime.H"
|
||||
@ -199,9 +759,28 @@ int main(int argc, char *argv[])
|
||||
<< nl << endl;
|
||||
}
|
||||
|
||||
scalar featureAngle = 180.0;
|
||||
const bool specifiedFeature = args.readIfPresent
|
||||
(
|
||||
"featureAngle",
|
||||
featureAngle
|
||||
);
|
||||
|
||||
Info<< "Reading mesh from time " << runTime.value() << endl;
|
||||
|
||||
#include "createNamedPolyMesh.H"
|
||||
if (specifiedFeature)
|
||||
{
|
||||
Info<< "Detecting all sharp (>" << featureAngle
|
||||
<< " degrees) patch edges." << nl << endl;
|
||||
|
||||
//#include "createNamedPointMesh.H"
|
||||
// Do not read constant/pointMesh - construct from polyMesh only
|
||||
Info<< "Create pointMesh for time = "
|
||||
<< runTime.timeName() << Foam::nl << Foam::endl;
|
||||
(void)pointMesh::New(mesh);
|
||||
}
|
||||
|
||||
|
||||
// User specified times
|
||||
instantList timeDirs = timeSelector::select0(runTime, args);
|
||||
@ -275,6 +854,8 @@ int main(int argc, char *argv[])
|
||||
// Mesh face and compact zone indx
|
||||
DynamicList<label> faceLabels;
|
||||
DynamicList<label> compactZones;
|
||||
// Per compact 'zone' index the name and location
|
||||
surfZoneIdentifierList surfZones;
|
||||
|
||||
{
|
||||
// Collect sizes. Hash on names to handle local-only patches (e.g.
|
||||
@ -316,6 +897,17 @@ int main(int argc, char *argv[])
|
||||
Pstream::broadcast(compactZoneID);
|
||||
|
||||
|
||||
// Zones
|
||||
surfZones.resize_nocopy(compactZoneID.size());
|
||||
forAllConstIters(compactZoneID, iter)
|
||||
{
|
||||
surfZones[*iter] = surfZoneIdentifier(iter.key(), *iter);
|
||||
Info<< "surfZone " << *iter
|
||||
<< " : " << surfZones[*iter].name()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
|
||||
// Rework HashTable into labelList just for speed of conversion
|
||||
labelList patchToCompactZone(bMesh.size(), -1);
|
||||
labelList faceZoneToCompactZone(bMesh.size(), -1);
|
||||
@ -361,7 +953,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
|
||||
// Addressing engine for all faces
|
||||
uindirectPrimitivePatch allBoundary
|
||||
const uindirectPrimitivePatch allBoundary
|
||||
(
|
||||
UIndirectList<face>(mesh.faces(), faceLabels),
|
||||
mesh.points()
|
||||
@ -399,7 +991,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
// Gather all ZoneIDs
|
||||
List<labelList> gatheredZones(Pstream::nProcs());
|
||||
gatheredZones[Pstream::myProcNo()].transfer(compactZones);
|
||||
gatheredZones[Pstream::myProcNo()] = compactZones;
|
||||
Pstream::gatherList(gatheredZones);
|
||||
|
||||
// On master combine all points, faces, zones
|
||||
@ -427,16 +1019,6 @@ int main(int argc, char *argv[])
|
||||
gatheredZones.clear();
|
||||
|
||||
|
||||
// Zones
|
||||
surfZoneIdentifierList surfZones(compactZoneID.size());
|
||||
forAllConstIters(compactZoneID, iter)
|
||||
{
|
||||
surfZones[*iter] = surfZoneIdentifier(iter.key(), *iter);
|
||||
Info<< "surfZone " << *iter
|
||||
<< " : " << surfZones[*iter].name()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
UnsortedMeshedSurface<face> unsortedFace
|
||||
(
|
||||
std::move(allPoints),
|
||||
@ -463,6 +1045,31 @@ int main(int argc, char *argv[])
|
||||
|
||||
sortedFace.write(globalCasePath);
|
||||
}
|
||||
|
||||
|
||||
if (specifiedFeature)
|
||||
{
|
||||
// Add edge patches
|
||||
const auto& pMesh = pointMesh::New(mesh);
|
||||
|
||||
const label nAdded = addMeshPointPatches
|
||||
(
|
||||
mesh,
|
||||
pMesh,
|
||||
|
||||
allBoundary, // all patches together
|
||||
compactZones, // originating compactZone
|
||||
surfZones, // per compactZone the index
|
||||
|
||||
featureAngle,
|
||||
featureAngle
|
||||
);
|
||||
|
||||
if (nAdded)
|
||||
{
|
||||
pMesh.boundary().write();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Info<< "End\n" << endl;
|
||||
|
||||
@ -440,6 +440,15 @@ pointSet_doc
|
||||
}
|
||||
|
||||
|
||||
//- All points of pointpatch
|
||||
{
|
||||
source patchToPoint;
|
||||
patches ("patch.*");
|
||||
// or
|
||||
patch somePatch;
|
||||
}
|
||||
|
||||
|
||||
//- Copy elements from pointSet
|
||||
{
|
||||
source pointToPoint;
|
||||
|
||||
@ -38,8 +38,8 @@ SourceFiles
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef ODESolver_H
|
||||
#define ODESolver_H
|
||||
#ifndef Foam_ODESolver_H
|
||||
#define Foam_ODESolver_H
|
||||
|
||||
#include "ODESystem.H"
|
||||
#include "typeInfo.H"
|
||||
@ -56,10 +56,9 @@ namespace Foam
|
||||
|
||||
class ODESolver
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
// Protected data
|
||||
// Protected Data
|
||||
|
||||
//- Reference to ODESystem
|
||||
const ODESystem& odes_;
|
||||
@ -106,7 +105,7 @@ public:
|
||||
|
||||
class stepState
|
||||
{
|
||||
public:
|
||||
public:
|
||||
|
||||
const bool forward;
|
||||
scalar dxTry;
|
||||
@ -171,14 +170,14 @@ public:
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Return the number of equations to solve
|
||||
inline label nEqns() const;
|
||||
//- The number of equations to solve
|
||||
label nEqns() const noexcept { return n_; }
|
||||
|
||||
//- Return access to the absolute tolerance field
|
||||
inline scalarField& absTol();
|
||||
//- Access to the absolute tolerance field
|
||||
scalarField& absTol() noexcept { return absTol_; }
|
||||
|
||||
//- Return access to the relative tolerance field
|
||||
inline scalarField& relTol();
|
||||
//- Access to the relative tolerance field
|
||||
scalarField& relTol() noexcept { return relTol_; }
|
||||
|
||||
//- Resize the ODE solver
|
||||
virtual bool resize() = 0;
|
||||
|
||||
@ -27,36 +27,19 @@ License
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
inline Foam::label Foam::ODESolver::nEqns() const
|
||||
{
|
||||
return n_;
|
||||
}
|
||||
|
||||
|
||||
inline Foam::scalarField& Foam::ODESolver::absTol()
|
||||
{
|
||||
return absTol_;
|
||||
}
|
||||
|
||||
|
||||
inline Foam::scalarField& Foam::ODESolver::relTol()
|
||||
{
|
||||
return relTol_;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
inline void Foam::ODESolver::resizeField(UList<Type>& f, const label n)
|
||||
{
|
||||
f.shallowCopy(UList<Type>(f.begin(), n));
|
||||
// shallowResize
|
||||
f.shallowCopy(f.data(), n);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
inline void Foam::ODESolver::resizeField(UList<Type>& f) const
|
||||
{
|
||||
resizeField(f, n_);
|
||||
// shallowResize
|
||||
f.shallowCopy(f.data(), n_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -716,8 +716,10 @@ $(pointMeshMapper)/pointPatchMapper.C
|
||||
|
||||
pointPatches = $(pointMesh)/pointPatches
|
||||
$(pointPatches)/pointPatch/pointPatch.C
|
||||
$(pointPatches)/pointPatch/pointPatchNew.C
|
||||
$(pointPatches)/facePointPatch/facePointPatch.C
|
||||
$(pointPatches)/facePointPatch/facePointPatchNew.C
|
||||
$(pointPatches)/meshPointPatch/meshPointPatch.C
|
||||
|
||||
basicPointPatches = $(pointPatches)/basic
|
||||
$(basicPointPatches)/coupled/coupledPointPatch.C
|
||||
|
||||
@ -120,8 +120,11 @@ public:
|
||||
|
||||
// Static Member Functions
|
||||
|
||||
//- Return a null bitSet reference
|
||||
inline static const bitSet& null();
|
||||
//- Return a null bitSet (reference to a nullObject).
|
||||
static const bitSet& null() noexcept
|
||||
{
|
||||
return NullObjectRef<bitSet>();
|
||||
}
|
||||
|
||||
|
||||
//- Declare type-name (with debug switch)
|
||||
|
||||
@ -405,12 +405,6 @@ inline Foam::label Foam::bitSet::find_next(label pos) const
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
inline const Foam::bitSet& Foam::bitSet::null()
|
||||
{
|
||||
return NullObjectRef<bitSet>();
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::bitSet::all() const
|
||||
{
|
||||
if (empty()) return true; // SIC. boost convention
|
||||
|
||||
@ -81,7 +81,7 @@ Foam::CompactListList<T> Foam::CompactListList<T>::pack_impl
|
||||
|
||||
if (len)
|
||||
{
|
||||
newOffsets.resize(len+1, Zero);
|
||||
newOffsets.resize(len+1, Foam::zero{});
|
||||
|
||||
for (label i = 0; i < len; ++i)
|
||||
{
|
||||
|
||||
@ -138,8 +138,11 @@ public:
|
||||
|
||||
// Static Member Functions
|
||||
|
||||
//- Return a CompactListList reference to a nullObject
|
||||
inline static const CompactListList<T>& null();
|
||||
//- Return a null CompactListList (reference to a nullObject).
|
||||
static const CompactListList<T>& null() noexcept
|
||||
{
|
||||
return NullObjectRef<CompactListList<T>>();
|
||||
}
|
||||
|
||||
//- Construct by packing together the list of lists
|
||||
template<class SubListType = List<T>>
|
||||
|
||||
@ -29,15 +29,6 @@ License
|
||||
#include "ListOps.H"
|
||||
#include "SubList.H"
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
inline const Foam::CompactListList<T>& Foam::CompactListList<T>::null()
|
||||
{
|
||||
return NullObjectRef<CompactListList<T>>();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
@ -98,7 +89,7 @@ inline Foam::CompactListList<T>::CompactListList
|
||||
const label nVals
|
||||
)
|
||||
:
|
||||
offsets_(mRows+1, Zero),
|
||||
offsets_(mRows+1, Foam::zero{}),
|
||||
values_(nVals)
|
||||
{
|
||||
// Optionally: enforceSizeSanity();
|
||||
@ -113,8 +104,8 @@ inline Foam::CompactListList<T>::CompactListList
|
||||
const Foam::zero
|
||||
)
|
||||
:
|
||||
offsets_(mRows+1, Zero),
|
||||
values_(nVals, Zero)
|
||||
offsets_(mRows+1, Foam::zero{}),
|
||||
values_(nVals, Foam::zero{})
|
||||
{
|
||||
// Optionally: enforceSizeSanity();
|
||||
}
|
||||
@ -128,7 +119,7 @@ inline Foam::CompactListList<T>::CompactListList
|
||||
const T& val
|
||||
)
|
||||
:
|
||||
offsets_(mRows+1, Zero),
|
||||
offsets_(mRows+1, Foam::zero{}),
|
||||
values_(nVals, val)
|
||||
{
|
||||
// Optionally: enforceSizeSanity();
|
||||
@ -387,7 +378,7 @@ inline void Foam::CompactListList<T>::resize
|
||||
}
|
||||
else
|
||||
{
|
||||
offsets_.resize(mRows+1, Zero);
|
||||
offsets_.resize(mRows+1, Foam::zero{});
|
||||
values_.resize(nVals);
|
||||
}
|
||||
}
|
||||
@ -408,7 +399,7 @@ inline void Foam::CompactListList<T>::resize_nocopy
|
||||
}
|
||||
else
|
||||
{
|
||||
offsets_.resize(mRows+1, Zero);
|
||||
offsets_.resize(mRows+1, Foam::zero{});
|
||||
values_.resize_nocopy(nVals);
|
||||
}
|
||||
}
|
||||
@ -430,7 +421,7 @@ inline void Foam::CompactListList<T>::resize
|
||||
}
|
||||
else
|
||||
{
|
||||
offsets_.resize(mRows+1, Zero);
|
||||
offsets_.resize(mRows+1, Foam::zero{});
|
||||
values_.resize(nVals, val);
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,9 +46,10 @@ SourceFiles
|
||||
#include "zero.H"
|
||||
#include "contiguous.H"
|
||||
#include "stdFoam.H"
|
||||
#include "autoPtr.H"
|
||||
#include "nullObject.H"
|
||||
#include "Hash.H"
|
||||
#include "ListPolicy.H"
|
||||
#include "autoPtr.H"
|
||||
|
||||
// <algorithm> already included by stdFoam.H
|
||||
#include <iterator>
|
||||
@ -139,8 +140,12 @@ public:
|
||||
|
||||
// Static Functions
|
||||
|
||||
//- Return a null FixedList
|
||||
inline static const FixedList<T, N>& null();
|
||||
//- Return a null FixedList (reference to a nullObject).
|
||||
//- Read/write access is questionable
|
||||
static const FixedList<T, N>& null() noexcept
|
||||
{
|
||||
return NullObjectRef<FixedList<T, N>>();
|
||||
}
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
@ -28,15 +28,6 @@ License
|
||||
|
||||
#include "UList.H"
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
template<class T, unsigned N>
|
||||
inline const Foam::FixedList<T, N>& Foam::FixedList<T, N>::null()
|
||||
{
|
||||
return NullObjectRef<FixedList<T, N>>();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, unsigned N>
|
||||
|
||||
@ -129,8 +129,12 @@ public:
|
||||
|
||||
// Static Member Functions
|
||||
|
||||
//- Return a null List
|
||||
inline static const List<T>& null();
|
||||
//- Return a null List (reference to a nullObject).
|
||||
//- Behaves like an empty List.
|
||||
static const List<T>& null() noexcept
|
||||
{
|
||||
return NullObjectRef<List<T>>();
|
||||
}
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
@ -133,13 +133,6 @@ inline Foam::autoPtr<Foam::List<T>> Foam::List<T>::clone() const
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
inline const Foam::List<T>& Foam::List<T>::null()
|
||||
{
|
||||
return NullObjectRef<List<T>>();
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
inline void Foam::List<T>::clear()
|
||||
{
|
||||
|
||||
@ -73,8 +73,12 @@ public:
|
||||
|
||||
// Static Functions
|
||||
|
||||
//- Return a null SubList
|
||||
inline static const SubList<T>& null();
|
||||
//- Return a null SubList (reference to a nullObject).
|
||||
//- Behaves like an empty SubList.
|
||||
static const SubList<T>& null() noexcept
|
||||
{
|
||||
return NullObjectRef<SubList<T>>();
|
||||
}
|
||||
|
||||
|
||||
// Generated Methods
|
||||
|
||||
@ -28,15 +28,6 @@ License
|
||||
|
||||
#include "FixedList.H"
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
inline const Foam::SubList<T>& Foam::SubList<T>::null()
|
||||
{
|
||||
return NullObjectRef<SubList<T>>();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
@ -124,7 +115,7 @@ inline Foam::SubList<T>::SubList
|
||||
template<class T>
|
||||
inline Foam::UList<T>& Foam::SubList<T>::reset(std::nullptr_t) noexcept
|
||||
{
|
||||
UList<T>::shallowCopy(nullptr, 0);
|
||||
UList<T>::shallowCopy(nullptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@ -183,8 +183,12 @@ public:
|
||||
|
||||
// Static Functions
|
||||
|
||||
//- Return a UList reference to a nullObject
|
||||
inline static const UList<T>& null();
|
||||
//- Return a null UList (reference to a nullObject).
|
||||
//- Behaves like an empty UList.
|
||||
static const UList<T>& null() noexcept
|
||||
{
|
||||
return NullObjectRef<UList<T>>();
|
||||
}
|
||||
|
||||
|
||||
// Public Classes
|
||||
@ -367,6 +371,9 @@ public:
|
||||
//- Copy the pointer and size
|
||||
inline void shallowCopy(T* __restrict__ ptr, const label len) noexcept;
|
||||
|
||||
//- Copy nullptr and zero size
|
||||
inline void shallowCopy(std::nullptr_t) noexcept;
|
||||
|
||||
//- Copy the pointer and size held by the given UList
|
||||
inline void shallowCopy(const UList<T>& list) noexcept;
|
||||
|
||||
|
||||
@ -93,13 +93,6 @@ inline void Foam::UList<T>::fill_uniform(const Foam::zero)
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
inline const Foam::UList<T>& Foam::UList<T>::null()
|
||||
{
|
||||
return NullObjectRef<UList<T>>();
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
inline Foam::label Foam::UList<T>::fcIndex(const label i) const noexcept
|
||||
{
|
||||
@ -330,6 +323,14 @@ inline void Foam::UList<T>::shallowCopy
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
inline void Foam::UList<T>::shallowCopy(std::nullptr_t) noexcept
|
||||
{
|
||||
size_ = 0;
|
||||
v_ = nullptr;
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
inline void Foam::UList<T>::shallowCopy(const UList<T>& list) noexcept
|
||||
{
|
||||
|
||||
@ -116,7 +116,7 @@ Foam::labelListList Foam::invertOneToMany
|
||||
const labelUList& map
|
||||
)
|
||||
{
|
||||
labelList sizes(len, Zero);
|
||||
labelList sizes(len, Foam::zero{});
|
||||
|
||||
for (const label newIdx : map)
|
||||
{
|
||||
|
||||
@ -707,7 +707,7 @@ void Foam::invertManyToMany
|
||||
)
|
||||
{
|
||||
// The output list sizes
|
||||
labelList sizes(len, Zero);
|
||||
labelList sizes(len, Foam::zero{});
|
||||
|
||||
for (const InputIntListType& sublist : input)
|
||||
{
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2018-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2018-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -30,7 +30,7 @@ License
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
Foam::label Foam::Detail::PtrListDetail<T>::count() const noexcept
|
||||
Foam::label Foam::Detail::PtrListDetail<T>::count_nonnull() const noexcept
|
||||
{
|
||||
label n = 0;
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2018-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2018-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -95,8 +95,8 @@ public:
|
||||
//- Return pointer to element or nullptr for out-of-range access.
|
||||
inline T* get(const label i);
|
||||
|
||||
//- Return the number of non-null entries
|
||||
label count() const noexcept;
|
||||
//- The number of non-nullptr entries in the list
|
||||
label count_nonnull() const noexcept;
|
||||
|
||||
//- FatalError if any null exists in the list
|
||||
inline void checkNonNull() const;
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2018-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2018-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -40,8 +40,8 @@ Foam::Ostream& Foam::Detail::PtrListDetail<T>::write
|
||||
{
|
||||
const label len = this->size();
|
||||
|
||||
// The net length (after trimming any nullptr)
|
||||
const label netLen = (trimNull ? this->count() : len);
|
||||
// The net length, optionally after trimming any nullptr
|
||||
const label netLen = (trimNull ? this->count_nonnull() : len);
|
||||
|
||||
if (!netLen)
|
||||
{
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2018-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2018-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -257,8 +257,8 @@ public:
|
||||
//- Size of the underlying storage.
|
||||
inline label capacity() const noexcept;
|
||||
|
||||
//- The number of non-null entries in the list
|
||||
inline label count() const noexcept;
|
||||
//- The number of non-nullptr entries in the list
|
||||
inline label count_nonnull() const noexcept;
|
||||
|
||||
//- Reference to the first element of the list
|
||||
inline T& front();
|
||||
@ -648,6 +648,10 @@ public:
|
||||
//- Move append another list to the end of this list.
|
||||
//FOAM_DEPRECATED_FOR(2022-10, "push_back()")
|
||||
void append(UPtrList<T>&& other) { this->push_back(std::move(other)); }
|
||||
|
||||
//- The number of non-nullptr entries in the list
|
||||
FOAM_DEPRECATED_FOR(2024-01, "count_nonnull()")
|
||||
label count() const noexcept { return count_nonnull(); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2018-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2018-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -124,9 +124,9 @@ inline Foam::label Foam::UPtrList<T>::capacity() const noexcept
|
||||
|
||||
|
||||
template<class T>
|
||||
inline Foam::label Foam::UPtrList<T>::count() const noexcept
|
||||
inline Foam::label Foam::UPtrList<T>::count_nonnull() const noexcept
|
||||
{
|
||||
return ptrs_.count();
|
||||
return ptrs_.count_nonnull();
|
||||
}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -135,15 +135,23 @@ protected:
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Read data (on master) and transmit.
|
||||
//- Helper: determine number of processors whose recvSizes fits
|
||||
//- into maxBufferSize
|
||||
static label calcNumProcs
|
||||
(
|
||||
const label comm,
|
||||
const off_t maxBufferSize,
|
||||
const labelUList& recvSizes,
|
||||
const label startProci
|
||||
);
|
||||
|
||||
//- Read data into *this. ISstream is only valid on master.
|
||||
static bool readBlocks
|
||||
(
|
||||
const label comm,
|
||||
// [in] The input stream (only valid on master)
|
||||
autoPtr<ISstream>& isPtr,
|
||||
// [out] The processor local data
|
||||
List<char>& localData,
|
||||
const UPstream::commsTypes commsType /* unused */
|
||||
List<char>& contentChars,
|
||||
const UPstream::commsTypes commsType
|
||||
);
|
||||
|
||||
//- Helper: skip a block of (binary) character data
|
||||
@ -269,19 +277,6 @@ public:
|
||||
}
|
||||
|
||||
//- Helper: write block of (binary) character content
|
||||
// Housekeeping
|
||||
static std::streamoff writeBlockEntry
|
||||
(
|
||||
OSstream& os,
|
||||
const label blocki,
|
||||
const stdFoam::span<char>& s
|
||||
)
|
||||
{
|
||||
return writeBlockEntry(os, blocki, s.data(), s.size());
|
||||
}
|
||||
|
||||
//- Helper: write block of (binary) character content
|
||||
// Housekeeping
|
||||
static std::streamoff writeBlockEntry
|
||||
(
|
||||
OSstream& os,
|
||||
@ -312,136 +307,61 @@ public:
|
||||
);
|
||||
|
||||
//- Read master header information (into headerIO) and return
|
||||
//- data in stream.
|
||||
//- data in stream. Note: isPtr is only valid on master.
|
||||
static autoPtr<ISstream> readBlocks
|
||||
(
|
||||
const label comm,
|
||||
const fileName& fName,
|
||||
//! [in] The input stream (only valid on master)
|
||||
autoPtr<ISstream>& isPtr,
|
||||
//! [out] header information
|
||||
IOobject& headerIO,
|
||||
const UPstream::commsTypes commsType /* unused */
|
||||
);
|
||||
|
||||
//- Helper: gather data from (subset of) sub-ranks.
|
||||
// In non-blocking mode it sets up send/recv for non-empty content.
|
||||
// In blocking/scheduled mode it uses MPI_Gatherv to collect data.
|
||||
//
|
||||
// Returns:
|
||||
// - recvData : the received data
|
||||
// - recvOffsets : offset in data. recvOffsets is nProcs+1
|
||||
static void gatherProcData
|
||||
(
|
||||
const label comm,
|
||||
const UList<char>& localData, //!< [in] required on all procs
|
||||
const labelUList& recvSizes, //!< [in] only required on master
|
||||
|
||||
const labelRange& whichProcs, //!< [in] required on all procs
|
||||
|
||||
List<int>& recvOffsets, //!< [out] only relevant on master
|
||||
DynamicList<char>& recvData, //!< [out] only relevant on master
|
||||
|
||||
const UPstream::commsTypes commsType
|
||||
);
|
||||
|
||||
//- Helper: gather single label. Note: using native Pstream.
|
||||
// datas sized with num procs but undefined contents on
|
||||
// slaves
|
||||
static void gather
|
||||
(
|
||||
const label comm,
|
||||
const label data,
|
||||
labelList& datas
|
||||
);
|
||||
|
||||
//- Helper: gather data from (subset of) slaves.
|
||||
//
|
||||
// Returns:
|
||||
// - recvData : received data
|
||||
// - recvOffsets : offset in data. recvOffsets is nProcs+1
|
||||
static void gatherSlaveData
|
||||
(
|
||||
const label comm,
|
||||
const UList<char>& data,
|
||||
const labelUList& recvSizes,
|
||||
|
||||
const labelRange& fromProcs,
|
||||
|
||||
List<int>& recvOffsets,
|
||||
DynamicList<char>& recvData
|
||||
);
|
||||
|
||||
//- Write *this. Ostream only valid on master.
|
||||
// Returns offsets of processor blocks in blockOffset
|
||||
static bool writeBlocks
|
||||
(
|
||||
const label comm,
|
||||
|
||||
//! [in] output stream (relevant on master)
|
||||
autoPtr<OSstream>& osPtr,
|
||||
//! [out] start offsets to each block (relevant on master),
|
||||
//! ignored if List::null() type
|
||||
List<std::streamoff>& blockOffset,
|
||||
|
||||
const UList<char>& localData, //!< [in] required on all procs
|
||||
const labelUList& recvSizes, //!< [in] only required on master
|
||||
const UList<char>& masterData,
|
||||
|
||||
//! Optional proc data (only written on master)
|
||||
//! but \b must also be symmetrically defined (empty/non-empty)
|
||||
//! on all ranks
|
||||
const UList<stdFoam::span<char>>& procData,
|
||||
const labelUList& recvSizes,
|
||||
|
||||
// Optional slave data (on master)
|
||||
const UPtrList<SubList<char>>& slaveData,
|
||||
|
||||
const UPstream::commsTypes commsType,
|
||||
const bool syncReturnState = true
|
||||
);
|
||||
|
||||
|
||||
// Housekeeping
|
||||
|
||||
//- Write *this. Ostream only valid on master.
|
||||
// Returns offsets of processor blocks in blockOffset
|
||||
FOAM_DEPRECATED_FOR(2023-09, "write with char span instead")
|
||||
static bool writeBlocks
|
||||
(
|
||||
const label comm,
|
||||
autoPtr<OSstream>& osPtr,
|
||||
List<std::streamoff>& blockOffset,
|
||||
|
||||
const UList<char>& localData, // [in] required on all procs
|
||||
const labelUList& recvSizes, // [in] only required on master
|
||||
|
||||
// Optional proc data (only written on master)
|
||||
// but \b must also be symmetrically defined (empty/non-empty)
|
||||
// on all ranks
|
||||
const UPtrList<SubList<char>>& procData,
|
||||
|
||||
const UPstream::commsTypes commsType,
|
||||
const bool syncReturnState = true
|
||||
)
|
||||
{
|
||||
// Transcribe to span<char>
|
||||
List<stdFoam::span<char>> spans(procData.size());
|
||||
forAll(procData, proci)
|
||||
{
|
||||
if (procData.test(proci))
|
||||
{
|
||||
spans[proci] = stdFoam::span<char>
|
||||
(
|
||||
const_cast<char*>(procData[proci].cdata()),
|
||||
procData[proci].size()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return decomposedBlockData::writeBlocks
|
||||
(
|
||||
comm,
|
||||
osPtr,
|
||||
blockOffset,
|
||||
localData,
|
||||
recvSizes,
|
||||
spans,
|
||||
commsType,
|
||||
syncReturnState
|
||||
);
|
||||
}
|
||||
|
||||
//- Deprecated(2023-09) - consider UPstream::listGatherValue
|
||||
// The only difference is that this gather also resizes the output
|
||||
// on the non-master procs
|
||||
// \deprecated(2023-09) - consider UPstream::listGatherValue
|
||||
FOAM_DEPRECATED_FOR(2023-09, "consider UPstream::listGatherValue()")
|
||||
static void gather
|
||||
(
|
||||
const label comm,
|
||||
const label localValue,
|
||||
labelList& allValues
|
||||
)
|
||||
{
|
||||
allValues.resize_nocopy(UPstream::nProcs(comm));
|
||||
|
||||
UPstream::mpiGather
|
||||
(
|
||||
reinterpret_cast<const char*>(&localValue),
|
||||
allValues.data_bytes(),
|
||||
sizeof(label), // The send/recv size per rank
|
||||
comm
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2020-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2020-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -132,7 +132,7 @@ public:
|
||||
// Member Functions
|
||||
|
||||
//- True if compiled with libz support
|
||||
static bool supports_gz();
|
||||
static bool supports_gz() noexcept;
|
||||
|
||||
|
||||
// Access
|
||||
@ -276,7 +276,7 @@ public:
|
||||
// Member Functions
|
||||
|
||||
//- True if compiled with libz support
|
||||
static bool supports_gz();
|
||||
static bool supports_gz() noexcept;
|
||||
|
||||
|
||||
// Access
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011 OpenFOAM Foundation
|
||||
Copyright (C) 2018-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2018-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -40,7 +40,7 @@ License
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::ifstreamPointer::supports_gz()
|
||||
bool Foam::ifstreamPointer::supports_gz() noexcept
|
||||
{
|
||||
#ifdef HAVE_LIBZ
|
||||
return true;
|
||||
@ -50,7 +50,7 @@ bool Foam::ifstreamPointer::supports_gz()
|
||||
}
|
||||
|
||||
|
||||
bool Foam::ofstreamPointer::supports_gz()
|
||||
bool Foam::ofstreamPointer::supports_gz() noexcept
|
||||
{
|
||||
#ifdef HAVE_LIBZ
|
||||
return true;
|
||||
@ -71,7 +71,7 @@ Foam::ifstreamPointer::ifstreamPointer
|
||||
IOstreamOption streamOpt // Currently unused
|
||||
)
|
||||
:
|
||||
ptr_(nullptr)
|
||||
ptr_()
|
||||
{
|
||||
open(pathname, streamOpt);
|
||||
}
|
||||
@ -82,7 +82,7 @@ Foam::ifstreamPointer::ifstreamPointer
|
||||
const fileName& pathname
|
||||
)
|
||||
:
|
||||
ptr_(nullptr)
|
||||
ptr_()
|
||||
{
|
||||
open(pathname);
|
||||
}
|
||||
@ -110,7 +110,7 @@ Foam::ofstreamPointer::ofstreamPointer
|
||||
const bool atomic
|
||||
)
|
||||
:
|
||||
ptr_(nullptr),
|
||||
ptr_(),
|
||||
atomic_(atomic)
|
||||
{
|
||||
std::ios_base::openmode mode
|
||||
|
||||
@ -29,7 +29,7 @@ License
|
||||
#include "masterOFstream.H"
|
||||
#include "OFstream.H"
|
||||
#include "OSspecific.H"
|
||||
#include "Pstream.H"
|
||||
#include "PstreamBuffers.H"
|
||||
#include "masterUncollatedFileOperation.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
@ -38,10 +38,10 @@ void Foam::masterOFstream::checkWrite
|
||||
(
|
||||
const fileName& fName,
|
||||
const char* str,
|
||||
const std::streamsize len
|
||||
std::streamsize len
|
||||
)
|
||||
{
|
||||
if (!str || !len)
|
||||
if (!len)
|
||||
{
|
||||
// Can probably skip all of this if there is nothing to write
|
||||
return;
|
||||
@ -63,7 +63,9 @@ void Foam::masterOFstream::checkWrite
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
// Write characters directly to std::ostream
|
||||
// Use writeRaw() instead of writeQuoted(string,false) to output
|
||||
// characters directly.
|
||||
|
||||
os.writeRaw(str, len);
|
||||
|
||||
if (!os.good())
|
||||
@ -75,159 +77,97 @@ void Foam::masterOFstream::checkWrite
|
||||
}
|
||||
|
||||
|
||||
void Foam::masterOFstream::checkWrite
|
||||
(
|
||||
const fileName& fName,
|
||||
const std::string& s
|
||||
)
|
||||
{
|
||||
checkWrite(fName, s.data(), s.length());
|
||||
}
|
||||
|
||||
|
||||
void Foam::masterOFstream::commit()
|
||||
{
|
||||
// Take ownership of serialized content, without copying or reallocation
|
||||
DynamicList<char> charData(OCharStream::release());
|
||||
|
||||
if (UPstream::parRun())
|
||||
{
|
||||
// Ignore content if not writing (reduces communication)
|
||||
if (!writeOnProc_)
|
||||
{
|
||||
charData.clear();
|
||||
}
|
||||
|
||||
List<fileName> filePaths(UPstream::nProcs(comm_));
|
||||
filePaths[UPstream::myProcNo(comm_)] = pathName_;
|
||||
Pstream::gatherList(filePaths, UPstream::msgType(), comm_);
|
||||
|
||||
// Test for identical output paths
|
||||
bool uniform =
|
||||
(
|
||||
UPstream::master(comm_)
|
||||
? fileOperation::uniformFile(filePaths)
|
||||
: true
|
||||
&& fileOperation::uniformFile(filePaths)
|
||||
);
|
||||
|
||||
Pstream::broadcast(uniform, comm_);
|
||||
|
||||
if (uniform)
|
||||
{
|
||||
// Identical file paths - write on master
|
||||
if (UPstream::master(comm_) && writeOnProc_)
|
||||
{
|
||||
checkWrite(pathName_, charData);
|
||||
checkWrite(pathName_, this->str());
|
||||
}
|
||||
|
||||
this->reset();
|
||||
return;
|
||||
}
|
||||
|
||||
// Different files
|
||||
// ---------------
|
||||
// Current strategy is to setup all non-blocking send/recv
|
||||
// using the probed message size to establish the recv size
|
||||
// (to avoid an additional communication of the sizes).
|
||||
//
|
||||
// For ranks with writeOnProc=false, the message size is 0.
|
||||
PstreamBuffers pBufs(comm_, UPstream::commsTypes::nonBlocking);
|
||||
|
||||
// An alternative approach would be to gather recv sizes
|
||||
// to avoid zero-sized messages and/or use double buffering
|
||||
// to recv into a buffer and write.
|
||||
//
|
||||
// const labelList recvSizes
|
||||
// (
|
||||
// UPstream::listGatherValues<label>
|
||||
// (
|
||||
// (UPstream::is_subrank(comm_) ? charData.size() : label(0)),
|
||||
// comm_
|
||||
// )
|
||||
// );
|
||||
|
||||
const label startOfRequests = UPstream::nRequests();
|
||||
|
||||
// Some unique tag for this read/write/probe grouping
|
||||
const int messageTag = UPstream::msgType() + 256;
|
||||
|
||||
if (UPstream::is_subrank(comm_))
|
||||
if (!UPstream::master(comm_))
|
||||
{
|
||||
// Send to master. When (!writeOnProc_) it is zero-sized.
|
||||
UOPstream::write
|
||||
(
|
||||
UPstream::commsTypes::nonBlocking,
|
||||
UPstream::masterNo(),
|
||||
charData.cdata_bytes(),
|
||||
charData.size_bytes(),
|
||||
messageTag,
|
||||
comm_
|
||||
);
|
||||
}
|
||||
else if (UPstream::master(comm_))
|
||||
{
|
||||
// The receive slots
|
||||
List<List<char>> procBuffers(UPstream::nProcs(comm_));
|
||||
|
||||
const auto recvProcs = UPstream::subProcs(comm_);
|
||||
|
||||
for (const int proci : recvProcs)
|
||||
{
|
||||
auto& procSlice = procBuffers[proci];
|
||||
|
||||
// Probe the message size
|
||||
std::pair<int, int> probed =
|
||||
UPstream::probeMessage
|
||||
(
|
||||
UPstream::commsTypes::blocking,
|
||||
proci,
|
||||
messageTag,
|
||||
comm_
|
||||
);
|
||||
|
||||
procSlice.resize_nocopy(probed.second);
|
||||
|
||||
// Receive content (can also be zero-sized)
|
||||
UIPstream::read
|
||||
(
|
||||
UPstream::commsTypes::nonBlocking,
|
||||
proci,
|
||||
procSlice.data_bytes(),
|
||||
procSlice.size_bytes(),
|
||||
messageTag,
|
||||
comm_
|
||||
);
|
||||
}
|
||||
|
||||
if (writeOnProc_)
|
||||
{
|
||||
// Write non-empty master data
|
||||
checkWrite(pathName_, charData);
|
||||
// Send buffer to master
|
||||
string s(this->str());
|
||||
|
||||
UOPstream os(UPstream::masterNo(), pBufs);
|
||||
os.write(s.data(), s.length());
|
||||
}
|
||||
this->reset(); // Done with contents
|
||||
}
|
||||
|
||||
// Poll for completed receive requests and dispatch
|
||||
DynamicList<int> indices(recvProcs.size());
|
||||
while
|
||||
(
|
||||
UPstream::waitSomeRequests
|
||||
(
|
||||
startOfRequests,
|
||||
recvProcs.size(),
|
||||
&indices
|
||||
)
|
||||
)
|
||||
pBufs.finishedGathers();
|
||||
|
||||
|
||||
if (UPstream::master(comm_))
|
||||
{
|
||||
if (writeOnProc_)
|
||||
{
|
||||
for (const int idx : indices)
|
||||
// Write master data
|
||||
checkWrite(filePaths[UPstream::masterNo()], this->str());
|
||||
}
|
||||
this->reset(); // Done with contents
|
||||
|
||||
|
||||
// Allocate large enough to read without resizing
|
||||
List<char> buf(pBufs.maxRecvCount());
|
||||
|
||||
for (const int proci : UPstream::subProcs(comm_))
|
||||
{
|
||||
const std::streamsize count(pBufs.recvDataCount(proci));
|
||||
|
||||
if (count)
|
||||
{
|
||||
const int proci = recvProcs[idx];
|
||||
auto& procSlice = procBuffers[proci];
|
||||
UIPstream is(proci, pBufs);
|
||||
|
||||
if (!procSlice.empty())
|
||||
{
|
||||
// Write non-empty sub-proc data
|
||||
checkWrite(filePaths[proci], procSlice);
|
||||
}
|
||||
|
||||
// Eager cleanup?
|
||||
// TBD: procSlice.clear();
|
||||
is.read(buf.data(), count);
|
||||
checkWrite(filePaths[proci], buf.cdata(), count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UPstream::waitRequests(startOfRequests);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write (non-empty) data
|
||||
checkWrite(pathName_, charData);
|
||||
checkWrite(pathName_, this->str());
|
||||
this->reset();
|
||||
}
|
||||
|
||||
// This method is only called once (internally)
|
||||
// so no need to clear/flush old buffered data
|
||||
}
|
||||
|
||||
|
||||
@ -243,7 +183,7 @@ Foam::masterOFstream::masterOFstream
|
||||
const bool writeOnProc
|
||||
)
|
||||
:
|
||||
OCharStream(streamOpt),
|
||||
OStringStream(streamOpt),
|
||||
pathName_(pathName),
|
||||
atomic_(atomic),
|
||||
compression_(streamOpt.compression()),
|
||||
|
||||
@ -41,7 +41,7 @@ SourceFiles
|
||||
#ifndef Foam_masterOFstream_H
|
||||
#define Foam_masterOFstream_H
|
||||
|
||||
#include "SpanStream.H"
|
||||
#include "StringStream.H"
|
||||
#include "UPstream.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
@ -55,7 +55,7 @@ namespace Foam
|
||||
|
||||
class masterOFstream
|
||||
:
|
||||
public OCharStream
|
||||
public OStringStream
|
||||
{
|
||||
// Private Data
|
||||
|
||||
@ -85,20 +85,13 @@ class masterOFstream
|
||||
(
|
||||
const fileName& fName,
|
||||
const char* str,
|
||||
const std::streamsize len
|
||||
std::streamsize len
|
||||
);
|
||||
|
||||
//- Open file with checking and write append contents
|
||||
void checkWrite
|
||||
(
|
||||
const fileName& fName,
|
||||
const UList<char>& charData
|
||||
)
|
||||
{
|
||||
checkWrite(fName, charData.cdata(), charData.size_bytes());
|
||||
}
|
||||
void checkWrite(const fileName& fName, const std::string& s);
|
||||
|
||||
//- Commit buffered information, including communication as required
|
||||
//- Commit buffered information, including parallel gather as required
|
||||
void commit();
|
||||
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2015 OpenFOAM Foundation
|
||||
Copyright (C) 2018-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2018-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -468,6 +468,41 @@ inline IOstream& scientific(IOstream& io)
|
||||
namespace Detail
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class Detail::StreamAllocator Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
//- A wrapper to hold a std::stream type for OpenFOAM wrapped streams.
|
||||
//- This is necessary since the OpenFOAM streams hold a reference to
|
||||
//- the normal std::stream
|
||||
template<class StreamType>
|
||||
class StreamAllocator
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- The std::stream
|
||||
StreamType stream_;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct (empty)
|
||||
StreamAllocator() = default;
|
||||
};
|
||||
|
||||
|
||||
} // End namespace Detail
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Functions/Algorithms
|
||||
|
||||
namespace Detail
|
||||
{
|
||||
|
||||
//- Termination for input looping (no-op)
|
||||
template<class IS> inline void inputLoop(IS&) {}
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2013 OpenFOAM Foundation
|
||||
Copyright (C) 2021-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2021-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -71,6 +71,33 @@ public:
|
||||
const label comm = UPstream::worldComm,
|
||||
IOstreamOption::streamFormat fmt = IOstreamOption::BINARY
|
||||
);
|
||||
|
||||
|
||||
// Static Functions
|
||||
|
||||
//- Receive and deserialize a value.
|
||||
//- Uses \c operator>> for de-serialization
|
||||
template<class Type>
|
||||
static void recv
|
||||
(
|
||||
Type& value,
|
||||
const int fromProcNo,
|
||||
const int tag = UPstream::msgType(),
|
||||
const label comm = UPstream::worldComm,
|
||||
IOstreamOption::streamFormat fmt = IOstreamOption::BINARY
|
||||
)
|
||||
{
|
||||
IPstream is
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
fromProcNo,
|
||||
0, // bufSize
|
||||
tag,
|
||||
comm,
|
||||
fmt
|
||||
);
|
||||
is >> value;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2013 OpenFOAM Foundation
|
||||
Copyright (C) 2021-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2021-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -71,6 +71,73 @@ public:
|
||||
const label comm = UPstream::worldComm,
|
||||
IOstreamOption::streamFormat fmt = IOstreamOption::BINARY
|
||||
);
|
||||
|
||||
|
||||
// Static Functions
|
||||
|
||||
//- Serialize a value and send (buffered/blocking or standard mode).
|
||||
//- Uses \c operator<< for serialization
|
||||
template<class Type>
|
||||
static void send
|
||||
(
|
||||
const Type& value,
|
||||
//! blocking or scheduled only!
|
||||
const UPstream::commsTypes commsType,
|
||||
const int toProcNo,
|
||||
const int tag = UPstream::msgType(),
|
||||
const label comm = UPstream::worldComm,
|
||||
IOstreamOption::streamFormat fmt = IOstreamOption::BINARY
|
||||
)
|
||||
{
|
||||
OPstream os(commsType, toProcNo, 0, tag, comm, fmt);
|
||||
os << value;
|
||||
}
|
||||
|
||||
//- Serialize a value and send (buffered/blocking mode).
|
||||
//- Uses \c operator<< for serialization
|
||||
template<class Type>
|
||||
static void bsend
|
||||
(
|
||||
const Type& value,
|
||||
const int toProcNo,
|
||||
const int tag = UPstream::msgType(),
|
||||
const label comm = UPstream::worldComm,
|
||||
IOstreamOption::streamFormat fmt = IOstreamOption::BINARY
|
||||
)
|
||||
{
|
||||
OPstream::send
|
||||
(
|
||||
value,
|
||||
UPstream::commsTypes::blocking,
|
||||
toProcNo,
|
||||
tag,
|
||||
comm,
|
||||
fmt
|
||||
);
|
||||
}
|
||||
|
||||
//- Serialize a value and send (standard mode).
|
||||
//- Uses \c operator<< for serialization
|
||||
template<class Type>
|
||||
static void send
|
||||
(
|
||||
const Type& value,
|
||||
const int toProcNo,
|
||||
const int tag = UPstream::msgType(),
|
||||
const label comm = UPstream::worldComm,
|
||||
IOstreamOption::streamFormat fmt = IOstreamOption::BINARY
|
||||
)
|
||||
{
|
||||
OPstream::send
|
||||
(
|
||||
value,
|
||||
UPstream::commsTypes::scheduled,
|
||||
toProcNo,
|
||||
tag,
|
||||
comm,
|
||||
fmt
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -47,9 +47,6 @@ SourceFiles
|
||||
#include "UPstream.H"
|
||||
#include "DynamicList.H"
|
||||
|
||||
// Legacy
|
||||
// #define Foam_Pstream_scatter_nobroadcast
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
@ -130,22 +127,9 @@ public:
|
||||
|
||||
// Gather
|
||||
|
||||
//- Gather (reduce) data, appyling \c bop to combine \c value
|
||||
//- from different processors. The basis for Foam::reduce().
|
||||
// Uses the specified communication schedule.
|
||||
template<class T, class BinaryOp>
|
||||
static void gather
|
||||
(
|
||||
const List<commsStruct>& comms,
|
||||
T& value,
|
||||
const BinaryOp& bop,
|
||||
const int tag,
|
||||
const label comm
|
||||
);
|
||||
|
||||
//- Gather (reduce) data, applying \c bop to combine \c value
|
||||
//- from different processors. The basis for Foam::reduce().
|
||||
// Uses linear/tree communication.
|
||||
// Uses linear/tree communication (with parallel guard).
|
||||
template<class T, class BinaryOp>
|
||||
static void gather
|
||||
(
|
||||
@ -155,46 +139,46 @@ public:
|
||||
const label comm = UPstream::worldComm
|
||||
);
|
||||
|
||||
//- Gather individual values into list locations.
|
||||
// On master list length == nProcs, otherwise zero length.
|
||||
// \n
|
||||
// For \b non-parallel :
|
||||
// the returned list length is 1 with localValue.
|
||||
template<class T>
|
||||
static List<T> listGatherValues
|
||||
(
|
||||
const T& localValue,
|
||||
const label comm = UPstream::worldComm,
|
||||
//! Only used for non-contiguous types
|
||||
const int tag = UPstream::msgType()
|
||||
);
|
||||
|
||||
//- Scatter individual values from list locations.
|
||||
// On master input list length == nProcs, ignored on other procs.
|
||||
// \n
|
||||
// For \b non-parallel :
|
||||
// returns the first list element (or default initialized).
|
||||
template<class T>
|
||||
static T listScatterValues
|
||||
(
|
||||
const UList<T>& allValues,
|
||||
const label comm = UPstream::worldComm,
|
||||
//! Only used for non-contiguous types
|
||||
const int tag = UPstream::msgType()
|
||||
);
|
||||
|
||||
|
||||
// Gather/combine data
|
||||
// Inplace combine values from processors.
|
||||
// (Uses construct from Istream instead of <<)
|
||||
// (Uses construct from Istream instead of \c << operator)
|
||||
|
||||
//- Gather data, applying \c cop to inplace combine \c value
|
||||
//- from different processors.
|
||||
// Uses the specified communication schedule.
|
||||
// Uses linear/tree communication (with parallel guard).
|
||||
template<class T, class CombineOp>
|
||||
static void combineGather
|
||||
(
|
||||
const List<commsStruct>& comms,
|
||||
T& value,
|
||||
const CombineOp& cop,
|
||||
const int tag,
|
||||
const label comm
|
||||
);
|
||||
|
||||
//- Gather data, applying \c cop to inplace combine \c value
|
||||
//- from different processors.
|
||||
// Uses linear/tree communication.
|
||||
template<class T, class CombineOp>
|
||||
static void combineGather
|
||||
(
|
||||
T& value,
|
||||
const CombineOp& cop,
|
||||
const int tag = UPstream::msgType(),
|
||||
const label comm = UPstream::worldComm
|
||||
);
|
||||
|
||||
//- Reduce inplace (cf. MPI Allreduce)
|
||||
//- applying \c cop to inplace combine \c value
|
||||
//- from different processors.
|
||||
//- After completion all processors have the same data.
|
||||
// Uses the specified communication schedule.
|
||||
// Wraps combineGather/broadcast (may change in the future).
|
||||
template<class T, class CombineOp>
|
||||
static void combineReduce
|
||||
(
|
||||
const List<commsStruct>& comms,
|
||||
//! [in,out]
|
||||
T& value,
|
||||
const CombineOp& cop,
|
||||
const int tag = UPstream::msgType(),
|
||||
@ -210,6 +194,7 @@ public:
|
||||
template<class T, class CombineOp>
|
||||
static void combineReduce
|
||||
(
|
||||
//! [in,out]
|
||||
T& value,
|
||||
const CombineOp& cop,
|
||||
const int tag = UPstream::msgType(),
|
||||
@ -232,30 +217,25 @@ public:
|
||||
|
||||
// Combine variants working on whole List at a time.
|
||||
|
||||
//- Combines List elements.
|
||||
// Uses linear/tree communication (with parallel guard).
|
||||
template<class T, class CombineOp>
|
||||
static void listCombineGather
|
||||
(
|
||||
const List<commsStruct>& comms,
|
||||
List<T>& values,
|
||||
const CombineOp& cop,
|
||||
const int tag,
|
||||
const label comm
|
||||
);
|
||||
|
||||
//- Like above but switches between linear/tree communication
|
||||
template<class T, class CombineOp>
|
||||
static void listCombineGather
|
||||
(
|
||||
List<T>& values,
|
||||
//! [in,out]
|
||||
UList<T>& values,
|
||||
const CombineOp& cop,
|
||||
const int tag = UPstream::msgType(),
|
||||
const label comm = UPstream::worldComm
|
||||
);
|
||||
|
||||
//- Combines List elements.
|
||||
//- After completion all processors have the same data.
|
||||
// Uses linear/tree communication (with parallel guard).
|
||||
template<class T, class CombineOp>
|
||||
static void listCombineReduce
|
||||
(
|
||||
//! [in,out] - List (not UList) due to broadcast()
|
||||
List<T>& values,
|
||||
const CombineOp& cop,
|
||||
const int tag = UPstream::msgType(),
|
||||
@ -266,6 +246,7 @@ public:
|
||||
template<class T, class CombineOp>
|
||||
static void listCombineAllGather
|
||||
(
|
||||
//! [in,out] - List (not UList) due to broadcast()
|
||||
List<T>& values,
|
||||
const CombineOp& cop,
|
||||
const int tag = UPstream::msgType(),
|
||||
@ -279,17 +260,8 @@ public:
|
||||
// Combine variants working on whole map at a time.
|
||||
// Container needs iterators, find() and insert methods defined.
|
||||
|
||||
template<class Container, class CombineOp>
|
||||
static void mapCombineGather
|
||||
(
|
||||
const List<commsStruct>& comms,
|
||||
Container& values,
|
||||
const CombineOp& cop,
|
||||
const int tag,
|
||||
const label comm
|
||||
);
|
||||
|
||||
//- Like above but switches between linear/tree communication
|
||||
//- Combine Map elements.
|
||||
// Uses linear/tree communication (with parallel guard).
|
||||
template<class Container, class CombineOp>
|
||||
static void mapCombineGather
|
||||
(
|
||||
@ -338,8 +310,9 @@ public:
|
||||
template<class T>
|
||||
static void gatherList
|
||||
(
|
||||
const List<commsStruct>& comms,
|
||||
List<T>& values,
|
||||
const UList<commsStruct>& comms,
|
||||
//! [in,out]
|
||||
UList<T>& values,
|
||||
const int tag,
|
||||
const label comm
|
||||
);
|
||||
@ -349,133 +322,48 @@ public:
|
||||
template<class T>
|
||||
static void gatherList
|
||||
(
|
||||
List<T>& values,
|
||||
//! [in,out]
|
||||
UList<T>& values,
|
||||
const int tag = UPstream::msgType(),
|
||||
const label comm = UPstream::worldComm
|
||||
);
|
||||
|
||||
//- Gather data, but keep individual values separate.
|
||||
//- Uses linear/tree communication.
|
||||
//- Uses MPI_Allgather or manual linear/tree communication.
|
||||
// After completion all processors have the same data.
|
||||
// Wraps gatherList/scatterList (may change in the future).
|
||||
template<class T>
|
||||
static void allGatherList
|
||||
(
|
||||
List<T>& values,
|
||||
//! [in,out]
|
||||
UList<T>& values,
|
||||
const int tag = UPstream::msgType(),
|
||||
const label comm = UPstream::worldComm
|
||||
);
|
||||
|
||||
|
||||
// Scatter
|
||||
// Scatter
|
||||
|
||||
//- Broadcast data: Distribute without modification.
|
||||
// \note comms and tag parameters only used when
|
||||
// Foam_Pstream_scatter_nobroadcast is defined
|
||||
template<class T>
|
||||
static void scatter
|
||||
(
|
||||
const List<commsStruct>& comms,
|
||||
T& value,
|
||||
const int tag,
|
||||
const label comm
|
||||
);
|
||||
//- Inverse of gatherList.
|
||||
//- Uses the specified communication schedule.
|
||||
template<class T>
|
||||
static void scatterList
|
||||
(
|
||||
const UList<commsStruct>& comms,
|
||||
UList<T>& values,
|
||||
const int tag,
|
||||
const label comm
|
||||
);
|
||||
|
||||
//- Broadcast data: Distribute without modification.
|
||||
// \note tag parameter only used when
|
||||
// Foam_Pstream_scatter_nobroadcast is defined
|
||||
template<class T>
|
||||
static void scatter
|
||||
(
|
||||
T& value,
|
||||
const int tag = UPstream::msgType(),
|
||||
const label comm = UPstream::worldComm
|
||||
);
|
||||
|
||||
//- Broadcast data: Distribute without modification.
|
||||
// \note tag parameter only used when
|
||||
// Foam_Pstream_scatter_nobroadcast is defined
|
||||
template<class T>
|
||||
static void combineScatter
|
||||
(
|
||||
const List<commsStruct>& comms,
|
||||
T& value,
|
||||
const int tag,
|
||||
const label comm
|
||||
);
|
||||
|
||||
//- Broadcast data: Distribute without modification.
|
||||
// \note tag parameter only used when
|
||||
// Foam_Pstream_scatter_nobroadcast is defined
|
||||
template<class T>
|
||||
static void combineScatter
|
||||
(
|
||||
T& value,
|
||||
const int tag = UPstream::msgType(),
|
||||
const label comm = UPstream::worldComm
|
||||
);
|
||||
|
||||
//- Broadcast data: Distribute without modification.
|
||||
// \note comms and tag parameters only used when
|
||||
// Foam_Pstream_scatter_nobroadcast is defined
|
||||
template<class T>
|
||||
static void listCombineScatter
|
||||
(
|
||||
const List<commsStruct>& comms,
|
||||
List<T>& value,
|
||||
const int tag,
|
||||
const label comm
|
||||
);
|
||||
|
||||
//- Broadcast data: Distribute without modification.
|
||||
// \note comms and tag parameters only used when
|
||||
// Foam_Pstream_scatter_nobroadcast is defined
|
||||
template<class T>
|
||||
static void listCombineScatter
|
||||
(
|
||||
List<T>& value,
|
||||
const int tag = UPstream::msgType(),
|
||||
const label comm = UPstream::worldComm
|
||||
);
|
||||
|
||||
//- Broadcast data: Distribute without modification.
|
||||
template<class Container>
|
||||
static void mapCombineScatter
|
||||
(
|
||||
const List<commsStruct>& comms,
|
||||
Container& values,
|
||||
const int tag,
|
||||
const label comm
|
||||
);
|
||||
|
||||
//- Like above but switches between linear/tree communication
|
||||
template<class Container>
|
||||
static void mapCombineScatter
|
||||
(
|
||||
Container& values,
|
||||
const int tag = UPstream::msgType(),
|
||||
const label comm = UPstream::worldComm
|
||||
);
|
||||
|
||||
|
||||
//- Scatter data. Reverse of gatherList
|
||||
template<class T>
|
||||
static void scatterList
|
||||
(
|
||||
const List<commsStruct>& comms,
|
||||
List<T>& values,
|
||||
const int tag,
|
||||
const label comm
|
||||
);
|
||||
|
||||
//- Like above but switches between linear/tree communication
|
||||
template<class T>
|
||||
static void scatterList
|
||||
(
|
||||
List<T>& values,
|
||||
const int tag = UPstream::msgType(),
|
||||
const label comm = UPstream::worldComm
|
||||
);
|
||||
//- Inverse of gatherList.
|
||||
//- Uses linear/tree communication.
|
||||
template<class T>
|
||||
static void scatterList
|
||||
(
|
||||
UList<T>& values,
|
||||
const int tag = UPstream::msgType(),
|
||||
const label comm = UPstream::worldComm
|
||||
);
|
||||
|
||||
|
||||
// Exchange
|
||||
@ -654,6 +542,61 @@ public:
|
||||
const label comm,
|
||||
const bool wait = true //!< (ignored)
|
||||
);
|
||||
|
||||
|
||||
// Housekeeping
|
||||
|
||||
//- \deprecated(2024-01) Broadcast data
|
||||
template<class T>
|
||||
FOAM_DEPRECATED_FOR(2024-01, "Pstream::broadcast()")
|
||||
static void scatter
|
||||
(
|
||||
T& value,
|
||||
const int tag = UPstream::msgType(), //!< ignored
|
||||
const label comm = UPstream::worldComm
|
||||
)
|
||||
{
|
||||
Pstream::broadcast(value, comm);
|
||||
}
|
||||
|
||||
//- \deprecated(2024-01) Broadcast data
|
||||
template<class T>
|
||||
FOAM_DEPRECATED_FOR(2024-01, "Pstream::broadcast()")
|
||||
static void combineScatter
|
||||
(
|
||||
T& value,
|
||||
const int tag = UPstream::msgType(), //!< ignored
|
||||
const label comm = UPstream::worldComm
|
||||
)
|
||||
{
|
||||
Pstream::broadcast(value, comm);
|
||||
}
|
||||
|
||||
//- \deprecated(2024-01) Broadcast data
|
||||
template<class T>
|
||||
FOAM_DEPRECATED_FOR(2024-01, "Pstream::broadcast()")
|
||||
static void listCombineScatter
|
||||
(
|
||||
List<T>& value,
|
||||
const int tag = UPstream::msgType(), //!< ignored
|
||||
const label comm = UPstream::worldComm
|
||||
)
|
||||
{
|
||||
Pstream::broadcast(value, comm);
|
||||
}
|
||||
|
||||
//- \deprecated(2024-01) Broadcast data
|
||||
template<class Container>
|
||||
FOAM_DEPRECATED_FOR(2024-01, "Pstream::broadcast()")
|
||||
static void mapCombineScatter
|
||||
(
|
||||
Container& values,
|
||||
const int tag = UPstream::msgType(), //!< ignored
|
||||
const label comm = UPstream::worldComm
|
||||
)
|
||||
{
|
||||
Pstream::broadcast(values, comm);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2022-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -137,4 +137,32 @@ void Foam::Pstream::broadcastList(ListType& list, const label comm)
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Convenience wrappers - defined after all specialisations are known
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
//- Return a broadcasted value (uses a copy internally)
|
||||
template<class Type>
|
||||
Type returnBroadcast
|
||||
(
|
||||
const Type& value,
|
||||
const label comm = UPstream::worldComm
|
||||
)
|
||||
{
|
||||
Type work(value);
|
||||
Pstream::broadcast(work, comm);
|
||||
return work;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2019-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2019-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -25,7 +25,7 @@ License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Description
|
||||
Variant of gather, scatter.
|
||||
Variant of gather.
|
||||
Normal gather uses:
|
||||
- default construct and read (>>) from Istream
|
||||
- binary operator and assignment operator to combine values
|
||||
@ -46,7 +46,6 @@ Description
|
||||
template<class T, class CombineOp>
|
||||
void Foam::Pstream::combineGather
|
||||
(
|
||||
const List<UPstream::commsStruct>& comms,
|
||||
T& value,
|
||||
const CombineOp& cop,
|
||||
const int tag,
|
||||
@ -55,8 +54,10 @@ void Foam::Pstream::combineGather
|
||||
{
|
||||
if (UPstream::is_parallel(comm))
|
||||
{
|
||||
// My communication order
|
||||
const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
|
||||
// Communication order
|
||||
const auto& comms = UPstream::whichCommunication(comm);
|
||||
// if (comms.empty()) return; // extra safety?
|
||||
const auto& myComm = comms[UPstream::myProcNo(comm)];
|
||||
|
||||
// Receive from my downstairs neighbours
|
||||
for (const label belowID : myComm.below())
|
||||
@ -89,7 +90,7 @@ void Foam::Pstream::combineGather
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
belowID,
|
||||
0,
|
||||
0, // bufsize
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
@ -106,7 +107,7 @@ void Foam::Pstream::combineGather
|
||||
}
|
||||
|
||||
// Send up value
|
||||
if (myComm.above() != -1)
|
||||
if (myComm.above() >= 0)
|
||||
{
|
||||
if (debug & 2)
|
||||
{
|
||||
@ -132,7 +133,7 @@ void Foam::Pstream::combineGather
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
myComm.above(),
|
||||
0,
|
||||
0, // bufsize
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
@ -143,144 +144,6 @@ void Foam::Pstream::combineGather
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void Foam::Pstream::combineScatter
|
||||
(
|
||||
const List<UPstream::commsStruct>& comms,
|
||||
T& value,
|
||||
const int tag,
|
||||
const label comm
|
||||
)
|
||||
{
|
||||
#ifndef Foam_Pstream_scatter_nobroadcast
|
||||
Pstream::broadcast(value, comm);
|
||||
#else
|
||||
if (UPstream::is_parallel(comm))
|
||||
{
|
||||
// My communication order
|
||||
const UPstream::commsStruct& myComm = comms[UPstream::myProcNo(comm)];
|
||||
|
||||
// Receive from up
|
||||
if (myComm.above() != -1)
|
||||
{
|
||||
if (is_contiguous<T>::value)
|
||||
{
|
||||
UIPstream::read
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
myComm.above(),
|
||||
reinterpret_cast<char*>(&value),
|
||||
sizeof(T),
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
IPstream fromAbove
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
myComm.above(),
|
||||
0,
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
value = T(fromAbove);
|
||||
}
|
||||
}
|
||||
|
||||
// Send to my downstairs neighbours
|
||||
forAllReverse(myComm.below(), belowI)
|
||||
{
|
||||
const label belowID = myComm.below()[belowI];
|
||||
|
||||
if (is_contiguous<T>::value)
|
||||
{
|
||||
UOPstream::write
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
belowID,
|
||||
reinterpret_cast<const char*>(&value),
|
||||
sizeof(T),
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
OPstream toBelow
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
belowID,
|
||||
0,
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
toBelow << value;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template<class T, class CombineOp>
|
||||
void Foam::Pstream::combineGather
|
||||
(
|
||||
T& value,
|
||||
const CombineOp& cop,
|
||||
const int tag,
|
||||
const label comm
|
||||
)
|
||||
{
|
||||
Pstream::combineGather
|
||||
(
|
||||
UPstream::whichCommunication(comm),
|
||||
value,
|
||||
cop,
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void Foam::Pstream::combineScatter
|
||||
(
|
||||
T& value,
|
||||
const int tag,
|
||||
const label comm
|
||||
)
|
||||
{
|
||||
#ifndef Foam_Pstream_scatter_nobroadcast
|
||||
Pstream::broadcast(value, comm);
|
||||
#else
|
||||
Pstream::combineScatter
|
||||
(
|
||||
UPstream::whichCommunication(comm),
|
||||
value,
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template<class T, class CombineOp>
|
||||
void Foam::Pstream::combineReduce
|
||||
(
|
||||
const List<UPstream::commsStruct>& comms,
|
||||
T& value,
|
||||
const CombineOp& cop,
|
||||
const int tag,
|
||||
const label comm
|
||||
)
|
||||
{
|
||||
Pstream::combineGather(comms, value, cop, tag, comm);
|
||||
Pstream::broadcast(value, comm);
|
||||
}
|
||||
|
||||
|
||||
template<class T, class CombineOp>
|
||||
void Foam::Pstream::combineReduce
|
||||
(
|
||||
@ -292,9 +155,7 @@ void Foam::Pstream::combineReduce
|
||||
{
|
||||
if (UPstream::is_parallel(comm))
|
||||
{
|
||||
const auto& comms = UPstream::whichCommunication(comm);
|
||||
|
||||
Pstream::combineGather(comms, value, cop, tag, comm);
|
||||
Pstream::combineGather(value, cop, tag, comm);
|
||||
Pstream::broadcast(value, comm);
|
||||
}
|
||||
}
|
||||
@ -305,8 +166,7 @@ void Foam::Pstream::combineReduce
|
||||
template<class T, class CombineOp>
|
||||
void Foam::Pstream::listCombineGather
|
||||
(
|
||||
const List<UPstream::commsStruct>& comms,
|
||||
List<T>& values,
|
||||
UList<T>& values,
|
||||
const CombineOp& cop,
|
||||
const int tag,
|
||||
const label comm
|
||||
@ -314,8 +174,10 @@ void Foam::Pstream::listCombineGather
|
||||
{
|
||||
if (UPstream::is_parallel(comm))
|
||||
{
|
||||
// My communication order
|
||||
const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
|
||||
// Communication order
|
||||
const auto& comms = UPstream::whichCommunication(comm);
|
||||
// if (comms.empty()) return; // extra safety?
|
||||
const auto& myComm = comms[UPstream::myProcNo(comm)];
|
||||
|
||||
// Receive from my downstairs neighbours
|
||||
for (const label belowID : myComm.below())
|
||||
@ -351,7 +213,7 @@ void Foam::Pstream::listCombineGather
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
belowID,
|
||||
0,
|
||||
0, // bufsize
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
@ -371,7 +233,7 @@ void Foam::Pstream::listCombineGather
|
||||
}
|
||||
|
||||
// Send up values
|
||||
if (myComm.above() != -1)
|
||||
if (myComm.above() >= 0)
|
||||
{
|
||||
if (debug & 2)
|
||||
{
|
||||
@ -397,7 +259,7 @@ void Foam::Pstream::listCombineGather
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
myComm.above(),
|
||||
0,
|
||||
0, // bufsize
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
@ -408,129 +270,6 @@ void Foam::Pstream::listCombineGather
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void Foam::Pstream::listCombineScatter
|
||||
(
|
||||
const List<UPstream::commsStruct>& comms,
|
||||
List<T>& values,
|
||||
const int tag,
|
||||
const label comm
|
||||
)
|
||||
{
|
||||
#ifndef Foam_Pstream_scatter_nobroadcast
|
||||
Pstream::broadcast(values, comm);
|
||||
#else
|
||||
if (UPstream::is_parallel(comm))
|
||||
{
|
||||
// My communication order
|
||||
const UPstream::commsStruct& myComm = comms[UPstream::myProcNo(comm)];
|
||||
|
||||
// Receive from up
|
||||
if (myComm.above() != -1)
|
||||
{
|
||||
if (is_contiguous<T>::value)
|
||||
{
|
||||
UIPstream::read
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
myComm.above(),
|
||||
values.data_bytes(),
|
||||
values.size_bytes(),
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
IPstream fromAbove
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
myComm.above(),
|
||||
0,
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
fromAbove >> values;
|
||||
}
|
||||
}
|
||||
|
||||
// Send to my downstairs neighbours
|
||||
forAllReverse(myComm.below(), belowI)
|
||||
{
|
||||
const label belowID = myComm.below()[belowI];
|
||||
|
||||
if (is_contiguous<T>::value)
|
||||
{
|
||||
UOPstream::write
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
belowID,
|
||||
values.cdata_bytes(),
|
||||
values.size_bytes(),
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
OPstream toBelow
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
belowID,
|
||||
0,
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
toBelow << values;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template<class T, class CombineOp>
|
||||
void Foam::Pstream::listCombineGather
|
||||
(
|
||||
List<T>& values,
|
||||
const CombineOp& cop,
|
||||
const int tag,
|
||||
const label comm
|
||||
)
|
||||
{
|
||||
Pstream::listCombineGather
|
||||
(
|
||||
UPstream::whichCommunication(comm),
|
||||
values,
|
||||
cop,
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void Foam::Pstream::listCombineScatter
|
||||
(
|
||||
List<T>& values,
|
||||
const int tag,
|
||||
const label comm
|
||||
)
|
||||
{
|
||||
#ifndef Foam_Pstream_scatter_nobroadcast
|
||||
Pstream::broadcast(values, comm);
|
||||
#else
|
||||
Pstream::listCombineScatter
|
||||
(
|
||||
UPstream::whichCommunication(comm),
|
||||
values,
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template<class T, class CombineOp>
|
||||
void Foam::Pstream::listCombineReduce
|
||||
(
|
||||
@ -542,9 +281,7 @@ void Foam::Pstream::listCombineReduce
|
||||
{
|
||||
if (UPstream::is_parallel(comm))
|
||||
{
|
||||
const auto& comms = UPstream::whichCommunication(comm);
|
||||
|
||||
Pstream::listCombineGather(comms, values, cop, tag, comm);
|
||||
Pstream::listCombineGather(values, cop, tag, comm);
|
||||
Pstream::broadcast(values, comm);
|
||||
}
|
||||
}
|
||||
@ -555,7 +292,6 @@ void Foam::Pstream::listCombineReduce
|
||||
template<class Container, class CombineOp>
|
||||
void Foam::Pstream::mapCombineGather
|
||||
(
|
||||
const List<UPstream::commsStruct>& comms,
|
||||
Container& values,
|
||||
const CombineOp& cop,
|
||||
const int tag,
|
||||
@ -564,8 +300,10 @@ void Foam::Pstream::mapCombineGather
|
||||
{
|
||||
if (UPstream::is_parallel(comm))
|
||||
{
|
||||
// My communication order
|
||||
const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
|
||||
// Communication order
|
||||
const auto& comms = UPstream::whichCommunication(comm);
|
||||
// if (comms.empty()) return; // extra safety?
|
||||
const auto& myComm = comms[UPstream::myProcNo(comm)];
|
||||
|
||||
// Receive from my downstairs neighbours
|
||||
for (const label belowID : myComm.below())
|
||||
@ -576,7 +314,7 @@ void Foam::Pstream::mapCombineGather
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
belowID,
|
||||
0,
|
||||
0, // bufsize
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
@ -611,7 +349,7 @@ void Foam::Pstream::mapCombineGather
|
||||
}
|
||||
|
||||
// Send up values
|
||||
if (myComm.above() != -1)
|
||||
if (myComm.above() >= 0)
|
||||
{
|
||||
if (debug & 2)
|
||||
{
|
||||
@ -623,7 +361,7 @@ void Foam::Pstream::mapCombineGather
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
myComm.above(),
|
||||
0,
|
||||
0, // bufsize
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
@ -633,110 +371,6 @@ void Foam::Pstream::mapCombineGather
|
||||
}
|
||||
|
||||
|
||||
template<class Container>
|
||||
void Foam::Pstream::mapCombineScatter
|
||||
(
|
||||
const List<UPstream::commsStruct>& comms,
|
||||
Container& values,
|
||||
const int tag,
|
||||
const label comm
|
||||
)
|
||||
{
|
||||
#ifndef Foam_Pstream_scatter_nobroadcast
|
||||
Pstream::broadcast(values, comm);
|
||||
#else
|
||||
if (UPstream::is_parallel(comm))
|
||||
{
|
||||
// My communication order
|
||||
const UPstream::commsStruct& myComm = comms[UPstream::myProcNo(comm)];
|
||||
|
||||
// Receive from up
|
||||
if (myComm.above() != -1)
|
||||
{
|
||||
IPstream fromAbove
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
myComm.above(),
|
||||
0,
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
fromAbove >> values;
|
||||
|
||||
if (debug & 2)
|
||||
{
|
||||
Pout<< " received from "
|
||||
<< myComm.above() << " data:" << values << endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Send to my downstairs neighbours
|
||||
forAllReverse(myComm.below(), belowI)
|
||||
{
|
||||
const label belowID = myComm.below()[belowI];
|
||||
|
||||
if (debug & 2)
|
||||
{
|
||||
Pout<< " sending to " << belowID << " data:" << values << endl;
|
||||
}
|
||||
|
||||
OPstream toBelow
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
belowID,
|
||||
0,
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
toBelow << values;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template<class Container, class CombineOp>
|
||||
void Foam::Pstream::mapCombineGather
|
||||
(
|
||||
Container& values,
|
||||
const CombineOp& cop,
|
||||
const int tag,
|
||||
const label comm
|
||||
)
|
||||
{
|
||||
Pstream::mapCombineGather
|
||||
(
|
||||
UPstream::whichCommunication(comm),
|
||||
values,
|
||||
cop,
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class Container>
|
||||
void Foam::Pstream::mapCombineScatter
|
||||
(
|
||||
Container& values,
|
||||
const int tag,
|
||||
const label comm
|
||||
)
|
||||
{
|
||||
#ifndef Foam_Pstream_scatter_nobroadcast
|
||||
Pstream::broadcast(values, comm);
|
||||
#else
|
||||
Pstream::mapCombineScatter
|
||||
(
|
||||
UPstream::whichCommunication(comm),
|
||||
values,
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template<class Container, class CombineOp>
|
||||
void Foam::Pstream::mapCombineReduce
|
||||
(
|
||||
@ -748,9 +382,7 @@ void Foam::Pstream::mapCombineReduce
|
||||
{
|
||||
if (UPstream::is_parallel(comm))
|
||||
{
|
||||
const auto& comms = UPstream::whichCommunication(comm);
|
||||
|
||||
Pstream::mapCombineGather(comms, values, cop, tag, comm);
|
||||
Pstream::mapCombineGather(values, cop, tag, comm);
|
||||
Pstream::broadcast(values, comm);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2019-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2019-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -26,7 +26,7 @@ License
|
||||
|
||||
Description
|
||||
Gather data from all processors onto single processor according to some
|
||||
communication schedule (usually linear-to-master or tree-to-master).
|
||||
communication schedule (usually tree-to-master).
|
||||
The gathered data will be a single value constructed from the values
|
||||
on individual processors using a user-specified operator.
|
||||
|
||||
@ -41,7 +41,6 @@ Description
|
||||
template<class T, class BinaryOp>
|
||||
void Foam::Pstream::gather
|
||||
(
|
||||
const List<UPstream::commsStruct>& comms,
|
||||
T& value,
|
||||
const BinaryOp& bop,
|
||||
const int tag,
|
||||
@ -50,8 +49,10 @@ void Foam::Pstream::gather
|
||||
{
|
||||
if (UPstream::is_parallel(comm))
|
||||
{
|
||||
// My communication order
|
||||
const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
|
||||
// Communication order
|
||||
const auto& comms = UPstream::whichCommunication(comm);
|
||||
// if (comms.empty()) return; // extra safety?
|
||||
const auto& myComm = comms[UPstream::myProcNo(comm)];
|
||||
|
||||
// Receive from my downstairs neighbours
|
||||
for (const label belowID : myComm.below())
|
||||
@ -76,7 +77,7 @@ void Foam::Pstream::gather
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
belowID,
|
||||
0,
|
||||
0, // bufsize
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
@ -87,7 +88,7 @@ void Foam::Pstream::gather
|
||||
}
|
||||
|
||||
// Send up value
|
||||
if (myComm.above() != -1)
|
||||
if (myComm.above() >= 0)
|
||||
{
|
||||
if (is_contiguous<T>::value)
|
||||
{
|
||||
@ -107,7 +108,7 @@ void Foam::Pstream::gather
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
myComm.above(),
|
||||
0,
|
||||
0, // bufsize
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
@ -119,110 +120,181 @@ void Foam::Pstream::gather
|
||||
|
||||
|
||||
template<class T>
|
||||
void Foam::Pstream::scatter
|
||||
Foam::List<T> Foam::Pstream::listGatherValues
|
||||
(
|
||||
const List<UPstream::commsStruct>& comms,
|
||||
T& value,
|
||||
const int tag,
|
||||
const label comm
|
||||
const T& localValue,
|
||||
const label comm,
|
||||
const int tag
|
||||
)
|
||||
{
|
||||
#ifndef Foam_Pstream_scatter_nobroadcast
|
||||
Pstream::broadcast(value, comm);
|
||||
#else
|
||||
// OR
|
||||
// if (is_contiguous<T>::value)
|
||||
// {
|
||||
// return UPstream::listGatherValues(localValue, comm);
|
||||
// }
|
||||
|
||||
List<T> allValues;
|
||||
|
||||
if (UPstream::is_parallel(comm))
|
||||
{
|
||||
// My communication order
|
||||
const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
|
||||
const label numProc = UPstream::nProcs(comm);
|
||||
|
||||
// Receive from up
|
||||
if (myComm.above() != -1)
|
||||
if (UPstream::master(comm))
|
||||
{
|
||||
if (is_contiguous<T>::value)
|
||||
{
|
||||
UIPstream::read
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
myComm.above(),
|
||||
reinterpret_cast<char*>(&value),
|
||||
sizeof(T),
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
IPstream fromAbove
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
myComm.above(),
|
||||
0,
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
fromAbove >> value;
|
||||
}
|
||||
allValues.resize(numProc);
|
||||
}
|
||||
|
||||
// Send to my downstairs neighbours. Note reverse order (compared to
|
||||
// receiving). This is to make sure to send to the critical path
|
||||
// (only when using a tree schedule!) first.
|
||||
forAllReverse(myComm.below(), belowI)
|
||||
if (is_contiguous<T>::value)
|
||||
{
|
||||
const label belowID = myComm.below()[belowI];
|
||||
UPstream::mpiGather
|
||||
(
|
||||
reinterpret_cast<const char*>(&localValue),
|
||||
allValues.data_bytes(),
|
||||
sizeof(T), // The send/recv size per rank
|
||||
comm
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (UPstream::master(comm))
|
||||
{
|
||||
// Non-trivial to manage non-blocking gather without a
|
||||
// PEX/NBX approach (eg, PstreamBuffers) but leave with
|
||||
// with simple exchange for now
|
||||
|
||||
if (is_contiguous<T>::value)
|
||||
{
|
||||
UOPstream::write
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
belowID,
|
||||
reinterpret_cast<const char*>(&value),
|
||||
sizeof(T),
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
allValues[0] = localValue;
|
||||
|
||||
for (int proci = 1; proci < numProc; ++proci)
|
||||
{
|
||||
IPstream fromProc
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
proci,
|
||||
0, // bufsize
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
fromProc >> allValues[proci];
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (UPstream::is_rank(comm))
|
||||
{
|
||||
OPstream toBelow
|
||||
OPstream toProc
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
belowID,
|
||||
0,
|
||||
UPstream::masterNo(),
|
||||
0, // bufsize
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
toBelow << value;
|
||||
toProc << localValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// non-parallel: return own value
|
||||
// TBD: only when UPstream::is_rank(comm) as well?
|
||||
allValues.resize(1);
|
||||
allValues[0] = localValue;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class BinaryOp>
|
||||
void Foam::Pstream::gather
|
||||
(
|
||||
T& value,
|
||||
const BinaryOp& bop,
|
||||
const int tag,
|
||||
const label comm
|
||||
)
|
||||
{
|
||||
Pstream::gather(UPstream::whichCommunication(comm), value, bop, tag, comm);
|
||||
return allValues;
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void Foam::Pstream::scatter(T& value, const int tag, const label comm)
|
||||
T Foam::Pstream::listScatterValues
|
||||
(
|
||||
const UList<T>& allValues,
|
||||
const label comm,
|
||||
const int tag
|
||||
)
|
||||
{
|
||||
#ifndef Foam_Pstream_scatter_nobroadcast
|
||||
Pstream::broadcast(value, comm);
|
||||
#else
|
||||
Pstream::scatter(UPstream::whichCommunication(comm), value, tag, comm);
|
||||
#endif
|
||||
// OR
|
||||
// if (is_contiguous<T>::value)
|
||||
// {
|
||||
// return UPstream::listScatterValues(allValues, comm);
|
||||
// }
|
||||
|
||||
T localValue{};
|
||||
|
||||
if (UPstream::is_parallel(comm))
|
||||
{
|
||||
const label numProc = UPstream::nProcs(comm);
|
||||
|
||||
if (UPstream::master(comm) && allValues.size() < numProc)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Attempting to send " << allValues.size()
|
||||
<< " values to " << numProc << " processors" << endl
|
||||
<< Foam::abort(FatalError);
|
||||
}
|
||||
|
||||
if (is_contiguous<T>::value)
|
||||
{
|
||||
UPstream::mpiScatter
|
||||
(
|
||||
allValues.cdata_bytes(),
|
||||
reinterpret_cast<char*>(&localValue),
|
||||
sizeof(T), // The send/recv size per rank
|
||||
comm
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (UPstream::master(comm))
|
||||
{
|
||||
const label startOfRequests = UPstream::nRequests();
|
||||
|
||||
List<DynamicList<char>> sendBuffers(numProc);
|
||||
|
||||
for (int proci = 1; proci < numProc; ++proci)
|
||||
{
|
||||
UOPstream toProc
|
||||
(
|
||||
UPstream::commsTypes::nonBlocking,
|
||||
proci,
|
||||
sendBuffers[proci],
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
toProc << allValues[proci];
|
||||
}
|
||||
|
||||
// Wait for outstanding requests
|
||||
UPstream::waitRequests(startOfRequests);
|
||||
|
||||
return allValues[0];
|
||||
}
|
||||
else if (UPstream::is_rank(comm))
|
||||
{
|
||||
IPstream fromProc
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
UPstream::masterNo(),
|
||||
0, // bufsize
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
fromProc >> localValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// non-parallel: return first value
|
||||
// TBD: only when UPstream::is_rank(comm) as well?
|
||||
|
||||
if (!allValues.empty())
|
||||
{
|
||||
return allValues[0];
|
||||
}
|
||||
}
|
||||
|
||||
return localValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2015-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -26,7 +26,7 @@ License
|
||||
|
||||
Description
|
||||
Gather data from all processors onto single processor according to some
|
||||
communication schedule (usually linear-to-master or tree-to-master).
|
||||
communication schedule (usually tree-to-master).
|
||||
The gathered data will be a list with element procID the data from processor
|
||||
procID. Before calling every processor should insert its value into
|
||||
values[UPstream::myProcNo(comm)].
|
||||
@ -45,24 +45,27 @@ Description
|
||||
template<class T>
|
||||
void Foam::Pstream::gatherList
|
||||
(
|
||||
const List<UPstream::commsStruct>& comms,
|
||||
List<T>& values,
|
||||
const UList<UPstream::commsStruct>& comms,
|
||||
UList<T>& values,
|
||||
const int tag,
|
||||
const label comm
|
||||
)
|
||||
{
|
||||
if (UPstream::is_parallel(comm))
|
||||
if (!comms.empty() && UPstream::is_parallel(comm))
|
||||
{
|
||||
if (values.size() < UPstream::nProcs(comm))
|
||||
const label myProci = UPstream::myProcNo(comm);
|
||||
const label numProc = UPstream::nProcs(comm);
|
||||
|
||||
if (values.size() < numProc)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "List of values is too small:" << values.size()
|
||||
<< " vs numProcs:" << UPstream::nProcs(comm) << nl
|
||||
<< "List of values:" << values.size()
|
||||
<< " < numProcs:" << numProc << nl
|
||||
<< Foam::abort(FatalError);
|
||||
}
|
||||
|
||||
// My communication order
|
||||
const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
|
||||
const auto& myComm = comms[myProci];
|
||||
|
||||
// Receive from my downstairs neighbours
|
||||
for (const label belowID : myComm.below())
|
||||
@ -127,21 +130,21 @@ void Foam::Pstream::gatherList
|
||||
// Send up from values:
|
||||
// - my own value first
|
||||
// - all belowLeaves next
|
||||
if (myComm.above() != -1)
|
||||
if (myComm.above() >= 0)
|
||||
{
|
||||
const labelList& belowLeaves = myComm.allBelow();
|
||||
|
||||
if (debug & 2)
|
||||
{
|
||||
Pout<< " sending to " << myComm.above()
|
||||
<< " data from me:" << UPstream::myProcNo(comm)
|
||||
<< " data:" << values[UPstream::myProcNo(comm)] << endl;
|
||||
<< " data from me:" << myProci
|
||||
<< " data:" << values[myProci] << endl;
|
||||
}
|
||||
|
||||
if (is_contiguous<T>::value)
|
||||
{
|
||||
List<T> sending(belowLeaves.size() + 1);
|
||||
sending[0] = values[UPstream::myProcNo(comm)];
|
||||
sending[0] = values[myProci];
|
||||
|
||||
forAll(belowLeaves, leafI)
|
||||
{
|
||||
@ -168,7 +171,7 @@ void Foam::Pstream::gatherList
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
toAbove << values[UPstream::myProcNo(comm)];
|
||||
toAbove << values[myProci];
|
||||
|
||||
for (const label leafID : belowLeaves)
|
||||
{
|
||||
@ -189,8 +192,8 @@ void Foam::Pstream::gatherList
|
||||
template<class T>
|
||||
void Foam::Pstream::scatterList
|
||||
(
|
||||
const List<UPstream::commsStruct>& comms,
|
||||
List<T>& values,
|
||||
const UList<UPstream::commsStruct>& comms,
|
||||
UList<T>& values,
|
||||
const int tag,
|
||||
const label comm
|
||||
)
|
||||
@ -199,21 +202,24 @@ void Foam::Pstream::scatterList
|
||||
// between scatterList() and using broadcast(List<T>&) or a regular
|
||||
// scatter(List<T>&) is that processor-local data is skipped.
|
||||
|
||||
if (UPstream::is_parallel(comm))
|
||||
if (!comms.empty() && UPstream::is_parallel(comm))
|
||||
{
|
||||
if (values.size() < UPstream::nProcs(comm))
|
||||
const label myProci = UPstream::myProcNo(comm);
|
||||
const label numProc = UPstream::nProcs(comm);
|
||||
|
||||
if (values.size() < numProc)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "List of values is too small:" << values.size()
|
||||
<< " vs numProcs:" << UPstream::nProcs(comm) << nl
|
||||
<< "List of values:" << values.size()
|
||||
<< " < numProcs:" << numProc << nl
|
||||
<< Foam::abort(FatalError);
|
||||
}
|
||||
|
||||
// My communication order
|
||||
const commsStruct& myComm = comms[UPstream::myProcNo(comm)];
|
||||
const auto& myComm = comms[myProci];
|
||||
|
||||
// Receive from up
|
||||
if (myComm.above() != -1)
|
||||
if (myComm.above() >= 0)
|
||||
{
|
||||
const labelList& notBelowLeaves = myComm.allNotBelow();
|
||||
|
||||
@ -318,12 +324,18 @@ void Foam::Pstream::scatterList
|
||||
template<class T>
|
||||
void Foam::Pstream::gatherList
|
||||
(
|
||||
List<T>& values,
|
||||
UList<T>& values,
|
||||
const int tag,
|
||||
const label comm
|
||||
)
|
||||
{
|
||||
Pstream::gatherList(UPstream::whichCommunication(comm), values, tag, comm);
|
||||
Pstream::gatherList
|
||||
(
|
||||
UPstream::whichCommunication(comm),
|
||||
values,
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -331,19 +343,25 @@ void Foam::Pstream::gatherList
|
||||
template<class T>
|
||||
void Foam::Pstream::scatterList
|
||||
(
|
||||
List<T>& values,
|
||||
UList<T>& values,
|
||||
const int tag,
|
||||
const label comm
|
||||
)
|
||||
{
|
||||
Pstream::scatterList(UPstream::whichCommunication(comm), values, tag, comm);
|
||||
Pstream::scatterList
|
||||
(
|
||||
UPstream::whichCommunication(comm),
|
||||
values,
|
||||
tag,
|
||||
comm
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void Foam::Pstream::allGatherList
|
||||
(
|
||||
List<T>& values,
|
||||
UList<T>& values,
|
||||
const int tag,
|
||||
const label comm
|
||||
)
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -46,28 +46,6 @@ namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
//- Reduce inplace (cf. MPI Allreduce)
|
||||
//- using specified communication schedule.
|
||||
template<class T, class BinaryOp>
|
||||
void reduce
|
||||
(
|
||||
const List<UPstream::commsStruct>& comms,
|
||||
T& value,
|
||||
const BinaryOp& bop,
|
||||
const int tag,
|
||||
const label comm
|
||||
)
|
||||
{
|
||||
if (UPstream::warnComm >= 0 && comm != UPstream::warnComm)
|
||||
{
|
||||
Pout<< "** reducing:" << value << " with comm:" << comm << endl;
|
||||
error::printStack(Pout);
|
||||
}
|
||||
Pstream::gather(comms, value, bop, tag, comm);
|
||||
Pstream::broadcast(value, comm);
|
||||
}
|
||||
|
||||
|
||||
//- Reduce inplace (cf. MPI Allreduce)
|
||||
//- using linear/tree communication schedule
|
||||
template<class T, class BinaryOp>
|
||||
@ -81,7 +59,13 @@ void reduce
|
||||
{
|
||||
if (UPstream::is_parallel(comm))
|
||||
{
|
||||
Foam::reduce(UPstream::whichCommunication(comm), value, bop, tag, comm);
|
||||
if (UPstream::warnComm >= 0 && comm != UPstream::warnComm)
|
||||
{
|
||||
Pout<< "** reducing:" << value << " with comm:" << comm << endl;
|
||||
error::printStack(Pout);
|
||||
}
|
||||
Pstream::gather(value, bop, tag, comm);
|
||||
Pstream::broadcast(value, comm);
|
||||
}
|
||||
}
|
||||
|
||||
@ -436,8 +420,7 @@ Pstream_SumReduce(double);
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Convenience wrappers for some reduction operations
|
||||
// - defined after all specialisations are known
|
||||
// Convenience wrappers - defined after all specialisations are known
|
||||
|
||||
//- Perform reduction on a copy, using specified binary operation
|
||||
// \return the resulting value
|
||||
|
||||
@ -52,6 +52,7 @@ Foam::UPstream::commsTypeNames
|
||||
({
|
||||
{ commsTypes::blocking, "blocking" },
|
||||
{ commsTypes::scheduled, "scheduled" },
|
||||
// { commsTypes::nonBlocking, "non-blocking" },
|
||||
{ commsTypes::nonBlocking, "nonBlocking" },
|
||||
});
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2015-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -895,21 +895,32 @@ public:
|
||||
);
|
||||
|
||||
//- Communication schedule for tree all-to-master (proc 0)
|
||||
static const List<commsStruct>& treeCommunication
|
||||
static const List<commsStruct>&
|
||||
treeCommunication
|
||||
(
|
||||
const label communicator = worldComm
|
||||
);
|
||||
|
||||
//- Communication schedule for linear/tree all-to-master (proc 0).
|
||||
//- Chooses based on the value of UPstream::nProcsSimpleSum
|
||||
//- Communication schedule for all-to-master (proc 0) as
|
||||
//- linear/tree/none with switching based on UPstream::nProcsSimpleSum
|
||||
//- and the is_parallel() state
|
||||
static const List<commsStruct>& whichCommunication
|
||||
(
|
||||
const label communicator = worldComm
|
||||
)
|
||||
{
|
||||
const label np
|
||||
(
|
||||
parRun_ && is_rank(communicator) // cf. is_parallel()
|
||||
? nProcs(communicator)
|
||||
: 0
|
||||
);
|
||||
|
||||
return
|
||||
(
|
||||
nProcs(communicator) < nProcsSimpleSum
|
||||
np <= 1
|
||||
? List<commsStruct>::null()
|
||||
: np < nProcsSimpleSum
|
||||
? linearCommunication(communicator)
|
||||
: treeCommunication(communicator)
|
||||
);
|
||||
@ -1138,7 +1149,7 @@ public:
|
||||
// On master input list length == nProcs, ignored on other procs.
|
||||
// \n
|
||||
// For \b non-parallel :
|
||||
// returns the first list element (or zero).
|
||||
// returns the first list element (or default initialized).
|
||||
template<class T>
|
||||
static T listScatterValues
|
||||
(
|
||||
@ -1191,6 +1202,7 @@ public:
|
||||
|
||||
//- Process index of first sub-process
|
||||
// \deprecated(2020-09) use subProcs() method instead
|
||||
FOAM_DEPRECATED_FOR(2020-09, "subProcs() method")
|
||||
static constexpr int firstSlave() noexcept
|
||||
{
|
||||
return 1;
|
||||
@ -1198,6 +1210,7 @@ public:
|
||||
|
||||
//- Process index of last sub-process
|
||||
// \deprecated(2020-09) use subProcs() method instead
|
||||
FOAM_DEPRECATED_FOR(2020-09, "subProcs() or allProcs() method")
|
||||
static int lastSlave(const label communicator = worldComm)
|
||||
{
|
||||
return nProcs(communicator) - 1;
|
||||
|
||||
@ -34,14 +34,6 @@ Foam::List<T> Foam::UPstream::allGatherValues
|
||||
const label comm
|
||||
)
|
||||
{
|
||||
if (!is_contiguous<T>::value)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot all-gather values for non-contiguous types" << endl
|
||||
<< Foam::abort(FatalError);
|
||||
}
|
||||
|
||||
|
||||
List<T> allValues;
|
||||
|
||||
if (UPstream::is_parallel(comm))
|
||||
@ -49,7 +41,17 @@ Foam::List<T> Foam::UPstream::allGatherValues
|
||||
allValues.resize(UPstream::nProcs(comm));
|
||||
allValues[UPstream::myProcNo(comm)] = localValue;
|
||||
|
||||
UPstream::mpiAllGather(allValues.data_bytes(), sizeof(T), comm);
|
||||
if (is_contiguous<T>::value)
|
||||
{
|
||||
UPstream::mpiAllGather(allValues.data_bytes(), sizeof(T), comm);
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot all-gather values for non-contiguous types"
|
||||
" - consider Pstream variant instead" << endl
|
||||
<< Foam::abort(FatalError);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -70,14 +72,6 @@ Foam::List<T> Foam::UPstream::listGatherValues
|
||||
const label comm
|
||||
)
|
||||
{
|
||||
if (!is_contiguous<T>::value)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot gather values for non-contiguous types" << endl
|
||||
<< Foam::abort(FatalError);
|
||||
}
|
||||
|
||||
|
||||
List<T> allValues;
|
||||
|
||||
if (UPstream::is_parallel(comm))
|
||||
@ -87,13 +81,23 @@ Foam::List<T> Foam::UPstream::listGatherValues
|
||||
allValues.resize(UPstream::nProcs(comm));
|
||||
}
|
||||
|
||||
UPstream::mpiGather
|
||||
(
|
||||
reinterpret_cast<const char*>(&localValue),
|
||||
allValues.data_bytes(),
|
||||
sizeof(T), // The send/recv size per rank
|
||||
comm
|
||||
);
|
||||
if (is_contiguous<T>::value)
|
||||
{
|
||||
UPstream::mpiGather
|
||||
(
|
||||
reinterpret_cast<const char*>(&localValue),
|
||||
allValues.data_bytes(),
|
||||
sizeof(T), // The send/recv size per rank
|
||||
comm
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot gather values for non-contiguous types"
|
||||
" - consider Pstream variant instead" << endl
|
||||
<< Foam::abort(FatalError);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -114,47 +118,46 @@ T Foam::UPstream::listScatterValues
|
||||
const label comm
|
||||
)
|
||||
{
|
||||
if (!is_contiguous<T>::value)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot scatter values for non-contiguous types" << endl
|
||||
<< Foam::abort(FatalError);
|
||||
}
|
||||
|
||||
|
||||
T localValue;
|
||||
T localValue{};
|
||||
|
||||
if (UPstream::is_parallel(comm))
|
||||
{
|
||||
const label nproc = UPstream::nProcs(comm);
|
||||
const label numProc = UPstream::nProcs(comm);
|
||||
|
||||
if (UPstream::master(comm) && allValues.size() < nproc)
|
||||
if (UPstream::master(comm) && allValues.size() < numProc)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Attempting to send " << allValues.size()
|
||||
<< " values to " << nproc << " processors" << endl
|
||||
<< " values to " << numProc << " processors" << endl
|
||||
<< Foam::abort(FatalError);
|
||||
}
|
||||
|
||||
UPstream::mpiScatter
|
||||
(
|
||||
allValues.cdata_bytes(),
|
||||
reinterpret_cast<char*>(&localValue),
|
||||
sizeof(T), // The send/recv size per rank
|
||||
comm
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// non-parallel: return local value
|
||||
|
||||
if (UPstream::is_rank(comm) && !allValues.empty())
|
||||
if (is_contiguous<T>::value)
|
||||
{
|
||||
localValue = allValues[0];
|
||||
UPstream::mpiScatter
|
||||
(
|
||||
allValues.cdata_bytes(),
|
||||
reinterpret_cast<char*>(&localValue),
|
||||
sizeof(T), // The send/recv size per rank
|
||||
comm
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
localValue = Zero;
|
||||
FatalErrorInFunction
|
||||
<< "Cannot scatter values for non-contiguous types"
|
||||
" - consider Pstream variant instead" << endl
|
||||
<< Foam::abort(FatalError);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// non-parallel: return first value
|
||||
// TBD: only when UPstream::is_rank(comm) as well?
|
||||
|
||||
if (!allValues.empty())
|
||||
{
|
||||
return allValues[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2017-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -46,60 +46,6 @@ SourceFiles
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
namespace Detail
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class Detail::StringStreamAllocator Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
//- Allocator for variants of a std stringstream
|
||||
template<class StreamType>
|
||||
class StringStreamAllocator
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Member Data
|
||||
|
||||
//- The stream type
|
||||
typedef StreamType stream_type;
|
||||
|
||||
//- The input/output stream.
|
||||
stream_type stream_;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
StringStreamAllocator() = default;
|
||||
|
||||
//- Copy construct from string
|
||||
StringStreamAllocator(const std::string& s)
|
||||
:
|
||||
stream_(s)
|
||||
{}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Get the string - as Foam::string rather than std::string
|
||||
Foam::string str() const
|
||||
{
|
||||
return Foam::string(stream_.str());
|
||||
}
|
||||
|
||||
//- Set the string
|
||||
void str(const std::string& s)
|
||||
{
|
||||
stream_.str(s);
|
||||
}
|
||||
};
|
||||
|
||||
} // End namespace Detail
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class IStringStream Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
@ -107,10 +53,12 @@ public:
|
||||
//- Input from string buffer, using a ISstream. Always UNCOMPRESSED.
|
||||
class IStringStream
|
||||
:
|
||||
public Detail::StringStreamAllocator<std::istringstream>,
|
||||
public ISstream
|
||||
public Foam::Detail::StreamAllocator<std::istringstream>,
|
||||
public Foam::ISstream
|
||||
{
|
||||
typedef Detail::StringStreamAllocator<std::istringstream> allocator_type;
|
||||
typedef
|
||||
Foam::Detail::StreamAllocator<std::istringstream>
|
||||
allocator_type;
|
||||
|
||||
public:
|
||||
|
||||
@ -133,9 +81,11 @@ public:
|
||||
IOstreamOption streamOpt = IOstreamOption()
|
||||
)
|
||||
:
|
||||
allocator_type(s),
|
||||
allocator_type(),
|
||||
ISstream(stream_, "input", streamOpt.format(), streamOpt.version())
|
||||
{}
|
||||
{
|
||||
stream_.str(s);
|
||||
}
|
||||
|
||||
//- Construct from char*
|
||||
explicit IStringStream
|
||||
@ -144,20 +94,32 @@ public:
|
||||
IOstreamOption streamOpt = IOstreamOption()
|
||||
)
|
||||
:
|
||||
allocator_type(s),
|
||||
allocator_type(),
|
||||
ISstream(stream_, "input", streamOpt.format(), streamOpt.version())
|
||||
{}
|
||||
{
|
||||
stream_.str(s);
|
||||
}
|
||||
|
||||
//- Copy construct, copies content and format
|
||||
IStringStream(const IStringStream& str)
|
||||
:
|
||||
allocator_type(str.str()),
|
||||
allocator_type(),
|
||||
ISstream(stream_, str.name(), static_cast<IOstreamOption>(str))
|
||||
{}
|
||||
{
|
||||
stream_.str(str.str());
|
||||
}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Get the string.
|
||||
//- As Foam::string instead of std::string (may change in future)
|
||||
Foam::string str() const { return Foam::string(stream_.str()); }
|
||||
|
||||
//- Set the string
|
||||
void str(const std::string& s) { stream_.str(s); }
|
||||
|
||||
|
||||
//- Reset the input buffer and rewind the stream
|
||||
virtual void reset(const std::string& s)
|
||||
{
|
||||
@ -220,10 +182,12 @@ public:
|
||||
//- Output to string buffer, using a OSstream. Always UNCOMPRESSED.
|
||||
class OStringStream
|
||||
:
|
||||
public Detail::StringStreamAllocator<std::ostringstream>,
|
||||
public OSstream
|
||||
public Foam::Detail::StreamAllocator<std::ostringstream>,
|
||||
public Foam::OSstream
|
||||
{
|
||||
typedef Detail::StringStreamAllocator<std::ostringstream> allocator_type;
|
||||
typedef
|
||||
Foam::Detail::StreamAllocator<std::ostringstream>
|
||||
allocator_type;
|
||||
|
||||
public:
|
||||
|
||||
@ -242,13 +206,23 @@ public:
|
||||
//- Copy construct, copies content and format
|
||||
OStringStream(const OStringStream& str)
|
||||
:
|
||||
allocator_type(str.str()),
|
||||
allocator_type(),
|
||||
OSstream(stream_, str.name(), static_cast<IOstreamOption>(str))
|
||||
{}
|
||||
{
|
||||
stream_.str(str.str());
|
||||
}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Get the string.
|
||||
//- As Foam::string instead of std::string (may change in future)
|
||||
Foam::string str() const { return Foam::string(stream_.str()); }
|
||||
|
||||
//- Set the string
|
||||
void str(const std::string& s) { stream_.str(s); }
|
||||
|
||||
|
||||
//- Reset the output buffer and rewind the stream
|
||||
void reset()
|
||||
{
|
||||
|
||||
@ -91,13 +91,14 @@ Foam::ITstream& Foam::ITstream::empty_stream()
|
||||
}
|
||||
|
||||
|
||||
Foam::tokenList Foam::ITstream::parse
|
||||
Foam::tokenList Foam::ITstream::parse_chars
|
||||
(
|
||||
const UList<char>& input,
|
||||
const char* s,
|
||||
size_t nbytes,
|
||||
IOstreamOption streamOpt
|
||||
)
|
||||
{
|
||||
ISpanStream is(input, streamOpt);
|
||||
ISpanStream is(s, nbytes, streamOpt);
|
||||
|
||||
tokenList tokens;
|
||||
parseStream(is, tokens);
|
||||
@ -105,31 +106,14 @@ Foam::tokenList Foam::ITstream::parse
|
||||
}
|
||||
|
||||
|
||||
Foam::tokenList Foam::ITstream::parse
|
||||
(
|
||||
const std::string& input,
|
||||
IOstreamOption streamOpt
|
||||
)
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::ITstream::reset(const char* input, size_t nbytes)
|
||||
{
|
||||
ISpanStream is(input, streamOpt);
|
||||
ISpanStream is(input, nbytes, static_cast<IOstreamOption>(*this));
|
||||
|
||||
tokenList tokens;
|
||||
parseStream(is, tokens);
|
||||
return tokens;
|
||||
}
|
||||
|
||||
|
||||
Foam::tokenList Foam::ITstream::parse
|
||||
(
|
||||
const char* input,
|
||||
IOstreamOption streamOpt
|
||||
)
|
||||
{
|
||||
ISpanStream is(input, strlen(input), streamOpt);
|
||||
|
||||
tokenList tokens;
|
||||
parseStream(is, tokens);
|
||||
return tokens;
|
||||
parseStream(is, static_cast<tokenList&>(*this));
|
||||
ITstream::seek(0); // rewind(), but bypasss virtual
|
||||
}
|
||||
|
||||
|
||||
@ -254,10 +238,7 @@ Foam::ITstream::ITstream
|
||||
:
|
||||
ITstream(streamOpt, name)
|
||||
{
|
||||
ISpanStream is(input, streamOpt);
|
||||
|
||||
parseStream(is, static_cast<tokenList&>(*this));
|
||||
ITstream::seek(0); // rewind(), but bypasss virtual
|
||||
reset(input.cdata(), input.size_bytes());
|
||||
}
|
||||
|
||||
|
||||
@ -270,10 +251,7 @@ Foam::ITstream::ITstream
|
||||
:
|
||||
ITstream(streamOpt, name)
|
||||
{
|
||||
ISpanStream is(input, streamOpt);
|
||||
|
||||
parseStream(is, static_cast<tokenList&>(*this));
|
||||
ITstream::seek(0); // rewind(), but bypasss virtual
|
||||
reset(input.data(), input.size());
|
||||
}
|
||||
|
||||
|
||||
@ -286,10 +264,7 @@ Foam::ITstream::ITstream
|
||||
:
|
||||
ITstream(streamOpt, name)
|
||||
{
|
||||
ISpanStream is(input, strlen(input), streamOpt);
|
||||
|
||||
parseStream(is, static_cast<tokenList&>(*this));
|
||||
ITstream::seek(0); // rewind(), but bypasss virtual
|
||||
reset(input, strlen(input));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -77,6 +77,18 @@ class ITstream
|
||||
// but leave any excess capacity (ie, like reserve).
|
||||
void reserveCapacity(const label newCapacity);
|
||||
|
||||
//- Convert input sequence into a list of tokens,
|
||||
static tokenList parse_chars
|
||||
(
|
||||
const char* s,
|
||||
size_t nbytes,
|
||||
IOstreamOption streamOpt
|
||||
);
|
||||
|
||||
//- Convert input sequence into a list of tokens,
|
||||
//- using the existing stream format. Rewinds the stream
|
||||
void reset(const char* input, size_t nbytes);
|
||||
|
||||
//- Failsafe read-access to token at specified location
|
||||
//- or undefinedToken
|
||||
inline const token& peekNoFail(const label i) const
|
||||
@ -158,6 +170,47 @@ public:
|
||||
const string& name = "input"
|
||||
);
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
//- Construct token list by parsing the input character sequence
|
||||
// Uses static parse function internally.
|
||||
explicit ITstream
|
||||
(
|
||||
std::string_view s,
|
||||
IOstreamOption streamOpt = IOstreamOption()
|
||||
)
|
||||
:
|
||||
ITstream(streamOpt)
|
||||
{
|
||||
reset(s.data(), s.size());
|
||||
}
|
||||
#endif
|
||||
|
||||
//- Construct token list by parsing the input character sequence
|
||||
// Uses static parse function internally.
|
||||
explicit ITstream
|
||||
(
|
||||
stdFoam::span<char> s,
|
||||
IOstreamOption streamOpt = IOstreamOption()
|
||||
)
|
||||
:
|
||||
ITstream(streamOpt)
|
||||
{
|
||||
reset(s.data(), s.size());
|
||||
}
|
||||
|
||||
//- Construct token list by parsing the input character sequence
|
||||
// Uses static parse function internally.
|
||||
explicit ITstream
|
||||
(
|
||||
stdFoam::span<const char> s,
|
||||
IOstreamOption streamOpt = IOstreamOption()
|
||||
)
|
||||
:
|
||||
ITstream(streamOpt)
|
||||
{
|
||||
reset(s.data(), s.size());
|
||||
}
|
||||
|
||||
|
||||
// Additional constructors
|
||||
|
||||
@ -207,7 +260,10 @@ public:
|
||||
(
|
||||
const UList<char>& input,
|
||||
IOstreamOption streamOpt = IOstreamOption()
|
||||
);
|
||||
)
|
||||
{
|
||||
return parse_chars(input.cdata(), input.size(), streamOpt);
|
||||
}
|
||||
|
||||
//- Create token list by parsing the input string
|
||||
//- until no good tokens remain.
|
||||
@ -215,7 +271,10 @@ public:
|
||||
(
|
||||
const std::string& input,
|
||||
IOstreamOption streamOpt = IOstreamOption()
|
||||
);
|
||||
)
|
||||
{
|
||||
return parse_chars(input.data(), input.size(), streamOpt);
|
||||
}
|
||||
|
||||
//- Create token list by parsing the input character sequence
|
||||
//- until no good tokens remain.
|
||||
@ -223,7 +282,45 @@ public:
|
||||
(
|
||||
const char* input,
|
||||
IOstreamOption streamOpt = IOstreamOption()
|
||||
);
|
||||
)
|
||||
{
|
||||
return parse_chars(input, strlen(input), streamOpt);
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
//- Create token list by parsing the input character sequence
|
||||
//- until no good tokens remain.
|
||||
static tokenList parse
|
||||
(
|
||||
std::string_view s,
|
||||
IOstreamOption streamOpt = IOstreamOption()
|
||||
)
|
||||
{
|
||||
return parse_chars(s.data(), s.size(), streamOpt);
|
||||
}
|
||||
#endif
|
||||
|
||||
//- Create token list by parsing the input character sequence
|
||||
//- until no good tokens remain.
|
||||
static tokenList parse
|
||||
(
|
||||
stdFoam::span<char> s,
|
||||
IOstreamOption streamOpt = IOstreamOption()
|
||||
)
|
||||
{
|
||||
return parse_chars(s.data(), s.size(), streamOpt);
|
||||
}
|
||||
|
||||
//- Create token list by parsing the input character sequence
|
||||
//- until no good tokens remain.
|
||||
static tokenList parse
|
||||
(
|
||||
stdFoam::span<const char> s,
|
||||
IOstreamOption streamOpt = IOstreamOption()
|
||||
)
|
||||
{
|
||||
return parse_chars(s.data(), s.size(), streamOpt);
|
||||
}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011 OpenFOAM Foundation
|
||||
Copyright (C) 2019-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2019-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -35,8 +35,8 @@ Description
|
||||
#ifndef Foam_OSHA1stream_H
|
||||
#define Foam_OSHA1stream_H
|
||||
|
||||
#include "OSstream.H"
|
||||
#include "SHA1.H"
|
||||
#include "OSstream.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -114,33 +114,6 @@ public:
|
||||
};
|
||||
|
||||
|
||||
namespace Detail
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class Detail::OSHA1streamAllocator Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
//- An allocator for holding Foam::osha1stream
|
||||
class OSHA1streamAllocator
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- The output stream
|
||||
Foam::osha1stream stream_;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
OSHA1streamAllocator() = default;
|
||||
};
|
||||
|
||||
} // End namespace Detail
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class OSHA1stream Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
@ -148,10 +121,12 @@ protected:
|
||||
//- The output stream for calculating SHA1 digests
|
||||
class OSHA1stream
|
||||
:
|
||||
public Detail::OSHA1streamAllocator,
|
||||
public OSstream
|
||||
public Foam::Detail::StreamAllocator<Foam::osha1stream>,
|
||||
public Foam::OSstream
|
||||
{
|
||||
typedef Detail::OSHA1streamAllocator allocator_type;
|
||||
typedef
|
||||
Foam::Detail::StreamAllocator<Foam::osha1stream>
|
||||
allocator_type;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2017-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -42,8 +42,6 @@ See Also
|
||||
#define Foam_ICharStream_H
|
||||
|
||||
#include "ISpanStream.H"
|
||||
#include "List.H"
|
||||
#include "DynamicList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -205,33 +203,6 @@ public:
|
||||
};
|
||||
|
||||
|
||||
namespace Detail
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class Detail::ICharStreamAllocator Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
//- An allocator for holding Foam::icharstream
|
||||
class ICharStreamAllocator
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- The stream
|
||||
Foam::icharstream stream_;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
ICharStreamAllocator() = default;
|
||||
};
|
||||
|
||||
} // End namespace Detail
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class ICharStream Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
@ -239,10 +210,12 @@ protected:
|
||||
//- An ISstream with internal List storage. Always UNCOMPRESSED.
|
||||
class ICharStream
|
||||
:
|
||||
public Detail::ICharStreamAllocator,
|
||||
public Foam::Detail::StreamAllocator<Foam::icharstream>,
|
||||
public Foam::ISstream
|
||||
{
|
||||
typedef Detail::ICharStreamAllocator allocator_type;
|
||||
typedef
|
||||
Foam::Detail::StreamAllocator<Foam::icharstream>
|
||||
allocator_type;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2016-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -65,7 +65,6 @@ See Also
|
||||
#define Foam_ISpanStream_H
|
||||
|
||||
#include "memoryStreamBuffer.H"
|
||||
#include "UList.H"
|
||||
#include "ISstream.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
@ -213,49 +212,23 @@ public:
|
||||
//- Some information about the input buffer position/capacity
|
||||
void debug_info(Ostream& os) const
|
||||
{
|
||||
os << "get="
|
||||
<< input_pos() << '/' << capacity();
|
||||
os << "get=" << input_pos() << '/' << capacity();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
namespace Detail
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class Detail::ISpanStreamAllocator Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
//- An allocator for holding Foam::ispanstream
|
||||
class ISpanStreamAllocator
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- The stream
|
||||
Foam::ispanstream stream_;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct (empty)
|
||||
ISpanStreamAllocator() = default;
|
||||
};
|
||||
|
||||
} // End namespace Detail
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class ISpanStream Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class ISpanStream
|
||||
:
|
||||
public Detail::ISpanStreamAllocator,
|
||||
public Foam::Detail::StreamAllocator<Foam::ispanstream>,
|
||||
public Foam::ISstream
|
||||
{
|
||||
typedef Detail::ISpanStreamAllocator allocator_type;
|
||||
typedef
|
||||
Foam::Detail::StreamAllocator<Foam::ispanstream>
|
||||
allocator_type;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2017-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -109,7 +109,13 @@ public:
|
||||
//- The current output position within the buffer (tellp)
|
||||
std::streampos output_pos() const
|
||||
{
|
||||
return (buffer_type::span_tellp());
|
||||
return buffer_type::span_tellp();
|
||||
}
|
||||
|
||||
//- The number of bytes outputted
|
||||
std::streamsize count() const
|
||||
{
|
||||
return buffer_type::size_bytes();
|
||||
}
|
||||
|
||||
//- The put buffer capacity
|
||||
@ -189,33 +195,6 @@ public:
|
||||
};
|
||||
|
||||
|
||||
namespace Detail
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class Detail::OCharStreamAllocator Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
//- An allocator for holding Foam::ocharstream
|
||||
class OCharStreamAllocator
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- The stream
|
||||
Foam::ocharstream stream_;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct - empty
|
||||
OCharStreamAllocator() = default;
|
||||
};
|
||||
|
||||
} // End namespace Detail
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class OCharStream Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
@ -223,10 +202,12 @@ protected:
|
||||
//- An OSstream with internal List storage
|
||||
class OCharStream
|
||||
:
|
||||
public Detail::OCharStreamAllocator,
|
||||
public Foam::Detail::StreamAllocator<Foam::ocharstream>,
|
||||
public Foam::OSstream
|
||||
{
|
||||
typedef Detail::OCharStreamAllocator allocator_type;
|
||||
typedef
|
||||
Foam::Detail::StreamAllocator<Foam::ocharstream>
|
||||
allocator_type;
|
||||
|
||||
public:
|
||||
|
||||
@ -277,8 +258,11 @@ public:
|
||||
//- The current output position within the buffer (tellp)
|
||||
std::streampos output_pos() const { return stream_.output_pos(); }
|
||||
|
||||
//- The current output size. Same as tellp(), output_pos()
|
||||
label size() const { return label(stream_.output_pos()); }
|
||||
//- The number of bytes outputted
|
||||
std::streamsize count() const { return stream_.count(); }
|
||||
|
||||
//- The current output size. Same as count(), output_pos(), tellp().
|
||||
label size() const { return label(stream_.count()); }
|
||||
|
||||
//- The put buffer capacity
|
||||
std::streamsize capacity() const { return stream_.capacity(); }
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2016-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -35,7 +35,6 @@ Description
|
||||
#define Foam_OScountStream_H
|
||||
|
||||
#include "OSstream.H"
|
||||
#include <iostream>
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -126,7 +125,7 @@ class ocountstream
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- The number of bytes counted.
|
||||
//- The number of bytes counted
|
||||
std::streamsize count() const noexcept { return size_; }
|
||||
|
||||
//- Reset the count
|
||||
@ -155,7 +154,7 @@ public:
|
||||
//- This hides both signatures of std::basic_ios::rdbuf()
|
||||
countbuf* rdbuf() { return &buf_; }
|
||||
|
||||
//- \return The number of bytes counted
|
||||
//- The number of bytes counted
|
||||
std::streamsize count() const noexcept { return buf_.count(); }
|
||||
|
||||
//- Reset the count
|
||||
@ -173,33 +172,6 @@ public:
|
||||
};
|
||||
|
||||
|
||||
namespace Detail
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class Detail::OCountStreamAllocator Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
//- An allocator for holding Foam::ocountstream
|
||||
class OCountStreamAllocator
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- The output stream
|
||||
Foam::ocountstream stream_;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
OCountStreamAllocator() = default;
|
||||
};
|
||||
|
||||
} // End namespace Detail
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class OCountStream Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
@ -207,10 +179,12 @@ protected:
|
||||
//- An output stream for calculating byte counts
|
||||
class OCountStream
|
||||
:
|
||||
public Detail::OCountStreamAllocator,
|
||||
public OSstream
|
||||
public Foam::Detail::StreamAllocator<Foam::ocountstream>,
|
||||
public Foam::OSstream
|
||||
{
|
||||
typedef Detail::OCountStreamAllocator allocator_type;
|
||||
typedef
|
||||
Foam::Detail::StreamAllocator<Foam::ocountstream>
|
||||
allocator_type;
|
||||
|
||||
public:
|
||||
|
||||
@ -238,10 +212,10 @@ public:
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- \return The number of bytes counted
|
||||
//- The number of bytes counted
|
||||
std::streamsize count() const noexcept { return stream_.count(); }
|
||||
|
||||
//- \return The number of bytes counted
|
||||
//- The number of bytes counted
|
||||
std::streamsize size() const noexcept { return stream_.count(); }
|
||||
|
||||
//- Reset the count
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2016-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -83,7 +83,6 @@ See Also
|
||||
#define Foam_OSpanStream_H
|
||||
|
||||
#include "memoryStreamBuffer.H"
|
||||
#include "DynamicList.H"
|
||||
#include "OSstream.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
@ -141,6 +140,12 @@ public:
|
||||
return buffer_type::span_tellp();
|
||||
}
|
||||
|
||||
//- The number of bytes outputted
|
||||
std::streamsize count() const
|
||||
{
|
||||
return buffer_type::size_bytes();
|
||||
}
|
||||
|
||||
//- The put buffer capacity
|
||||
std::streamsize capacity() const
|
||||
{
|
||||
@ -199,49 +204,23 @@ public:
|
||||
//- Some information about the output buffer position/capacity
|
||||
void debug_info(Ostream& os) const
|
||||
{
|
||||
os << "put="
|
||||
<< output_pos() << '/' << capacity();
|
||||
os << "put=" << output_pos() << '/' << capacity();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
namespace Detail
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class Detail::OSpanStreamAllocator Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
//- An allocator for holding Foam::ospanstream
|
||||
class OSpanStreamAllocator
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- The stream
|
||||
Foam::ospanstream stream_;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct (empty)
|
||||
OSpanStreamAllocator() = default;
|
||||
};
|
||||
|
||||
} // End namespace Detail
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class OSpanStream Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class OSpanStream
|
||||
:
|
||||
public Detail::OSpanStreamAllocator,
|
||||
public Foam::Detail::StreamAllocator<Foam::ospanstream>,
|
||||
public Foam::OSstream
|
||||
{
|
||||
typedef Detail::OSpanStreamAllocator allocator_type;
|
||||
typedef
|
||||
Foam::Detail::StreamAllocator<Foam::ospanstream>
|
||||
allocator_type;
|
||||
|
||||
public:
|
||||
|
||||
@ -314,8 +293,11 @@ public:
|
||||
//- The current output position within the buffer (tellp)
|
||||
std::streampos output_pos() const { return stream_.output_pos(); }
|
||||
|
||||
//- The current output size. Same as tellp(), output_pos()
|
||||
label size() const { return label(stream_.output_pos()); }
|
||||
//- The number of bytes outputted
|
||||
std::streamsize count() const { return stream_.count(); }
|
||||
|
||||
//- The current output size. Same as count(), output_pos(), tellp().
|
||||
label size() const { return label(stream_.count()); }
|
||||
|
||||
//- The put buffer capacity
|
||||
std::streamsize capacity() const { return stream_.capacity(); }
|
||||
|
||||
@ -541,7 +541,7 @@ public:
|
||||
// No character stripping
|
||||
inline explicit token(tokenType typ, const std::string&, label line=0);
|
||||
|
||||
//- Copy construct word/string token with the specified variant.
|
||||
//- Move construct word/string token with the specified variant.
|
||||
// A invalid word/string variant type is silently treated as STRING.
|
||||
// No character stripping
|
||||
inline explicit token(tokenType typ, std::string&&, label line=0);
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023 Sergey Lesnik
|
||||
Copyright (C) 2023 OpenCFD Ltd.
|
||||
Copyright (C) 2023-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -35,7 +35,7 @@ namespace Foam
|
||||
{
|
||||
|
||||
// Write tokens without keyword, suppress/ignore bad tokens.
|
||||
// Mostly like primitiveEntry::write(os, false);
|
||||
// Mostly like primitiveEntry::write(os, true);
|
||||
|
||||
static void writeTokens(Ostream& os, const tokenList& toks)
|
||||
{
|
||||
@ -56,11 +56,11 @@ static void writeTokens(Ostream& os, const tokenList& toks)
|
||||
started = true;
|
||||
}
|
||||
|
||||
// Output token with direct handling in Ostream(s),
|
||||
// or use normal '<<' output operator
|
||||
// Token output via direct handling in Ostream(s),
|
||||
// or normal '<<' output operator
|
||||
if (!os.write(tok))
|
||||
{
|
||||
os << tok;
|
||||
os << tok;
|
||||
}
|
||||
|
||||
if (tok.isCharData())
|
||||
@ -73,18 +73,10 @@ static void writeTokens(Ostream& os, const tokenList& toks)
|
||||
if (s.starts_with("//") && !s.ends_with('\n'))
|
||||
{
|
||||
os << '\n';
|
||||
started = false; // already have newline as separator
|
||||
started = false; // Does not need further space separator
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Always finish up with a newline?
|
||||
// eg,
|
||||
//
|
||||
// if (started)
|
||||
// {
|
||||
// os << nl;
|
||||
// }
|
||||
}
|
||||
|
||||
} // End namespace Foam
|
||||
@ -141,7 +133,10 @@ Foam::formattingEntry::formattingEntry
|
||||
|
||||
void Foam::formattingEntry::write(Ostream& os) const
|
||||
{
|
||||
writeTokens(os, *this);
|
||||
if (active_)
|
||||
{
|
||||
writeTokens(os, *this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023 Sergey Lesnik
|
||||
Copyright (C) 2023 OpenCFD Ltd.
|
||||
Copyright (C) 2023-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -51,12 +51,17 @@ class formattingEntry
|
||||
:
|
||||
public primitiveEntry
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- The output visibility
|
||||
bool active_ = true;
|
||||
|
||||
public:
|
||||
|
||||
// Static Member Functions
|
||||
|
||||
//- Generate a default entry keyword: "__format-entry__NNN"
|
||||
// The generated names are unlikely to collide with user dictionaries
|
||||
//- Generate an entry keyword: "__format-entry__NNN".
|
||||
//- The generated names are unlikely to collide with user dictionaries
|
||||
static keyType defaultName(label n)
|
||||
{
|
||||
return keyType
|
||||
@ -99,6 +104,12 @@ public:
|
||||
formattingEntry(defaultName(n), std::move(content))
|
||||
{}
|
||||
|
||||
//- Construct with token data, using a generated keyword
|
||||
formattingEntry(const label n, token&& tok, bool visible=true)
|
||||
:
|
||||
primitiveEntry(defaultName(n), std::move(tok)),
|
||||
active_(visible)
|
||||
{}
|
||||
|
||||
//- Clone the entry
|
||||
virtual autoPtr<entry> clone(const dictionary&) const
|
||||
@ -112,6 +123,21 @@ public:
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Set output visibility on/off.
|
||||
// \return the previous value
|
||||
bool active(bool on) noexcept
|
||||
{
|
||||
bool old(active_);
|
||||
active_ = on;
|
||||
return old;
|
||||
}
|
||||
|
||||
//- Get the output visibility
|
||||
bool active() const noexcept
|
||||
{
|
||||
return active_;
|
||||
}
|
||||
|
||||
//- Write content without the keyword.
|
||||
// Special properties:
|
||||
// - ignores any bad tokens on output.
|
||||
|
||||
@ -115,7 +115,7 @@ Type Foam::Function1Types::Function1Expression<Type>::integrate
|
||||
) const
|
||||
{
|
||||
NotImplemented;
|
||||
return Zero;
|
||||
return Type();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2021 OpenCFD Ltd.
|
||||
Copyright (C) 2019-2024 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -163,7 +163,7 @@ operator_precedence()
|
||||
|
||||
svalue (lhs) ::= NUMBER (tok) . { lhs = (tok).scalarValue; } // scanToken
|
||||
|
||||
svalue (lhs) ::= ZERO . { lhs = Foam::Zero; }
|
||||
svalue (lhs) ::= ZERO . { lhs = Foam::zero{}; }
|
||||
svalue (lhs) ::= PI LPAREN RPAREN . { lhs = Foam::constant::mathematical::pi; }
|
||||
svalue (lhs) ::= DEG_TO_RAD LPAREN RPAREN . { lhs = Foam::degToRad(); }
|
||||
svalue (lhs) ::= RAD_TO_DEG LPAREN RPAREN . { lhs = Foam::radToDeg(); }
|
||||
|
||||
@ -137,8 +137,11 @@ public:
|
||||
|
||||
// Static Member Functions
|
||||
|
||||
//- Return a NullObjectRef DimensionedField
|
||||
inline static const DimensionedField<Type, GeoMesh>& null();
|
||||
//- Return a null DimensionedField (reference to a nullObject).
|
||||
static const DimensionedField<Type, GeoMesh>& null() noexcept
|
||||
{
|
||||
return NullObjectRef<DimensionedField<Type, GeoMesh>>();
|
||||
}
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
@ -28,14 +28,6 @@ License
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type, class GeoMesh>
|
||||
inline const Foam::DimensionedField<Type, GeoMesh>&
|
||||
Foam::DimensionedField<Type, GeoMesh>::null()
|
||||
{
|
||||
return NullObjectRef<DimensionedField<Type, GeoMesh>>();
|
||||
}
|
||||
|
||||
|
||||
template<class Type, class GeoMesh>
|
||||
inline const typename GeoMesh::Mesh&
|
||||
Foam::DimensionedField<Type, GeoMesh>::mesh() const noexcept
|
||||
|
||||
@ -85,7 +85,7 @@ public:
|
||||
~SlicedDimensionedField()
|
||||
{
|
||||
// Set internalField to nullptr to avoid deletion of underlying field
|
||||
UList<Type>::shallowCopy(UList<Type>());
|
||||
UList<Type>::shallowCopy(nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -97,8 +97,8 @@ public:
|
||||
|
||||
// Static Member Functions
|
||||
|
||||
//- Return a null field
|
||||
inline static const DynamicField<T, SizeMin>& null()
|
||||
//- Return a null DynamicField (reference to a nullObject).
|
||||
static const DynamicField<T, SizeMin>& null() noexcept
|
||||
{
|
||||
return NullObjectRef<DynamicField<T, SizeMin>>();
|
||||
}
|
||||
|
||||
@ -122,8 +122,12 @@ public:
|
||||
|
||||
// Static Member Functions
|
||||
|
||||
//- Return nullObject reference Field
|
||||
inline static const Field<Type>& null();
|
||||
//- Return a null Field (reference to a nullObject).
|
||||
//- Behaves like an empty Field.
|
||||
static const Field<Type>& null() noexcept
|
||||
{
|
||||
return NullObjectRef<Field<Type>>();
|
||||
}
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
@ -25,15 +25,6 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
inline const Foam::Field<Type>& Foam::Field<Type>::null()
|
||||
{
|
||||
return NullObjectRef<Field<Type>>();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
|
||||
@ -69,8 +69,12 @@ public:
|
||||
|
||||
// Static Member Functions
|
||||
|
||||
//- Return nullObject reference SubField
|
||||
inline static const SubField<Type>& null();
|
||||
//- Return a null SubField (reference to a nullObject).
|
||||
//- Behaves like an empty SubField.
|
||||
static const SubField<Type>& null() noexcept
|
||||
{
|
||||
return NullObjectRef<SubField<Type>>();
|
||||
}
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
@ -26,15 +26,6 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
inline const Foam::SubField<Type>& Foam::SubField<Type>::null()
|
||||
{
|
||||
return NullObjectRef<SubField<Type>>();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
|
||||
@ -154,8 +154,11 @@ public:
|
||||
|
||||
// Static Member Functions
|
||||
|
||||
//- Return a null geometric field
|
||||
inline static const GeometricField<Type, PatchField, GeoMesh>& null();
|
||||
//- Return a null GeometricField (reference to a nullObject).
|
||||
static const GeometricField<Type, PatchField, GeoMesh>& null() noexcept
|
||||
{
|
||||
return NullObjectRef<GeometricField<Type, PatchField, GeoMesh>>();
|
||||
}
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
@ -28,14 +28,6 @@ License
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
inline const Foam::GeometricField<Type, PatchField, GeoMesh>&
|
||||
Foam::GeometricField<Type, PatchField, GeoMesh>::null()
|
||||
{
|
||||
return NullObjectRef<GeometricField<Type, PatchField, GeoMesh>>();
|
||||
}
|
||||
|
||||
|
||||
template<class Type, template<class> class PatchField, class GeoMesh>
|
||||
inline const typename
|
||||
Foam::GeometricField<Type, PatchField, GeoMesh>::Internal&
|
||||
|
||||
@ -176,10 +176,11 @@ makeBoundary
|
||||
new SlicedPatchField<Type>
|
||||
(
|
||||
p,
|
||||
DimensionedField<Type, GeoMesh>::null(),
|
||||
bField[patchi]
|
||||
DimensionedField<Type, GeoMesh>::null()
|
||||
)
|
||||
);
|
||||
|
||||
bf[patchi].UList<Type>::shallowCopy(bField[patchi]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -368,7 +369,7 @@ Foam::SlicedGeometricField<Type, PatchField, SlicedPatchField, GeoMesh>::
|
||||
~SlicedGeometricField()
|
||||
{
|
||||
// Set internalField to nullptr to avoid deletion of underlying field
|
||||
UList<Type>::shallowCopy(UList<Type>());
|
||||
UList<Type>::shallowCopy(nullptr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -47,9 +47,9 @@ bool Foam::OFstreamCollator::writeFile
|
||||
const label comm,
|
||||
const word& objectType,
|
||||
const fileName& fName,
|
||||
const UList<char>& localData,
|
||||
const string& masterData,
|
||||
const labelUList& recvSizes,
|
||||
const UList<stdFoam::span<char>>& procData, // optional proc data
|
||||
const UPtrList<SubList<char>>& slaveData, // optional slave data
|
||||
IOstreamOption streamOpt,
|
||||
IOstreamOption::atomicType atomic,
|
||||
IOstreamOption::appendType append,
|
||||
@ -58,14 +58,18 @@ bool Foam::OFstreamCollator::writeFile
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "OFstreamCollator : Writing local " << localData.size()
|
||||
Pout<< "OFstreamCollator : Writing master " << label(masterData.size())
|
||||
<< " bytes to " << fName << " using comm " << comm
|
||||
<< " and " << procData.size() << " sub-ranks" << endl;
|
||||
<< " and " << slaveData.size() << " sub-ranks" << endl;
|
||||
|
||||
forAll(procData, proci)
|
||||
forAll(slaveData, proci)
|
||||
{
|
||||
Pout<< " " << proci << " size:"
|
||||
<< label(procData[proci].size()) << nl;
|
||||
if (slaveData.set(proci))
|
||||
{
|
||||
Pout<< " " << proci
|
||||
<< " size:" << slaveData[proci].size()
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,27 +104,32 @@ bool Foam::OFstreamCollator::writeFile
|
||||
// for some mpi so default is non-blocking.
|
||||
const UPstream::commsTypes myCommsType
|
||||
(
|
||||
mag
|
||||
(
|
||||
fileOperations::masterUncollatedFileOperation::
|
||||
maxMasterFileBufferSize
|
||||
) < 1
|
||||
maxMasterFileBufferSize == 0
|
||||
)
|
||||
? UPstream::commsTypes::scheduled
|
||||
: UPstream::commsTypes::nonBlocking
|
||||
);
|
||||
|
||||
|
||||
List<std::streamoff> blockOffsets; // Optional
|
||||
UList<char> slice
|
||||
(
|
||||
const_cast<char*>(masterData.data()),
|
||||
label(masterData.size())
|
||||
);
|
||||
|
||||
List<std::streamoff> blockOffset;
|
||||
decomposedBlockData::writeBlocks
|
||||
(
|
||||
comm,
|
||||
osPtr,
|
||||
blockOffsets, // or List<std::streamoff>::null()
|
||||
localData,
|
||||
blockOffset,
|
||||
slice,
|
||||
recvSizes,
|
||||
procData,
|
||||
slaveData,
|
||||
myCommsType,
|
||||
false // do not sync return state
|
||||
false // do not reduce return state
|
||||
);
|
||||
|
||||
if (osPtr && !osPtr->good())
|
||||
@ -131,18 +140,17 @@ bool Foam::OFstreamCollator::writeFile
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "OFstreamCollator : Finished writing "
|
||||
<< localData.size() << " bytes";
|
||||
|
||||
Pout<< "OFstreamCollator : Finished writing " << masterData.size()
|
||||
<< " bytes";
|
||||
if (UPstream::master(comm))
|
||||
{
|
||||
off_t total = 0;
|
||||
off_t sum = 0;
|
||||
for (const label recv : recvSizes)
|
||||
{
|
||||
total += recv;
|
||||
sum += recv;
|
||||
}
|
||||
// Use std::to_string to display long int
|
||||
Pout<< " (overall " << std::to_string(total) << ')';
|
||||
Pout<< " (overall " << std::to_string(sum) << ')';
|
||||
}
|
||||
Pout<< " to " << fName
|
||||
<< " using comm " << comm << endl;
|
||||
@ -159,16 +167,13 @@ void* Foam::OFstreamCollator::writeAll(void *threadarg)
|
||||
// Consume stack
|
||||
while (true)
|
||||
{
|
||||
std::unique_ptr<writeData> ptr;
|
||||
writeData* ptr = nullptr;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handler.mutex_);
|
||||
|
||||
if (handler.objects_.size())
|
||||
{
|
||||
// FIFO
|
||||
ptr.reset(handler.objects_.front());
|
||||
handler.objects_.pop_front();
|
||||
ptr = handler.objects_.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,39 +181,51 @@ void* Foam::OFstreamCollator::writeAll(void *threadarg)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
writeData& obj = *ptr;
|
||||
|
||||
// Obtain spans from storage
|
||||
List<stdFoam::span<char>> procData(obj.procData_.size());
|
||||
forAll(procData, proci)
|
||||
else
|
||||
{
|
||||
procData[proci] = stdFoam::span<char>
|
||||
// Convert storage to pointers
|
||||
PtrList<SubList<char>> slaveData;
|
||||
if (ptr->slaveData_.size())
|
||||
{
|
||||
slaveData.resize(ptr->slaveData_.size());
|
||||
forAll(slaveData, proci)
|
||||
{
|
||||
if (ptr->slaveData_.set(proci))
|
||||
{
|
||||
slaveData.set
|
||||
(
|
||||
proci,
|
||||
new SubList<char>
|
||||
(
|
||||
ptr->slaveData_[proci],
|
||||
ptr->sizes_[proci]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ok = writeFile
|
||||
(
|
||||
const_cast<char*>(obj.procData_[proci].cdata()),
|
||||
obj.procData_[proci].size()
|
||||
ptr->comm_,
|
||||
ptr->objectType_,
|
||||
ptr->pathName_,
|
||||
ptr->data_,
|
||||
ptr->sizes_,
|
||||
slaveData,
|
||||
ptr->streamOpt_,
|
||||
ptr->atomic_,
|
||||
ptr->append_,
|
||||
ptr->headerEntries_
|
||||
);
|
||||
}
|
||||
if (!ok)
|
||||
{
|
||||
FatalIOErrorInFunction(ptr->pathName_)
|
||||
<< "Failed writing " << ptr->pathName_
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
bool ok = writeFile
|
||||
(
|
||||
obj.comm_,
|
||||
obj.objectType_,
|
||||
obj.pathName_,
|
||||
obj.localData_,
|
||||
obj.sizes_,
|
||||
procData,
|
||||
obj.streamOpt_,
|
||||
obj.atomic_,
|
||||
obj.append_,
|
||||
obj.headerEntries_
|
||||
);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
FatalIOErrorInFunction(obj.pathName_)
|
||||
<< "Failed writing " << obj.pathName_
|
||||
<< exit(FatalIOError);
|
||||
delete ptr;
|
||||
}
|
||||
//sleep(1);
|
||||
}
|
||||
@ -231,14 +248,14 @@ void Foam::OFstreamCollator::waitForBufferSpace(const off_t wantedSize) const
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
// The pending output size(s)
|
||||
// Count files to be written
|
||||
off_t totalSize = 0;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
for (const writeData* ptr : objects_)
|
||||
forAllConstIters(objects_, iter)
|
||||
{
|
||||
if (ptr) totalSize += ptr->size();
|
||||
totalSize += iter()->size();
|
||||
}
|
||||
}
|
||||
|
||||
@ -270,7 +287,17 @@ void Foam::OFstreamCollator::waitForBufferSpace(const off_t wantedSize) const
|
||||
|
||||
Foam::OFstreamCollator::OFstreamCollator(const off_t maxBufferSize)
|
||||
:
|
||||
OFstreamCollator(maxBufferSize, UPstream::worldComm)
|
||||
maxBufferSize_(maxBufferSize),
|
||||
threadRunning_(false),
|
||||
localComm_(UPstream::worldComm),
|
||||
threadComm_
|
||||
(
|
||||
UPstream::allocateCommunicator
|
||||
(
|
||||
localComm_,
|
||||
labelRange(UPstream::nProcs(localComm_))
|
||||
)
|
||||
)
|
||||
{}
|
||||
|
||||
|
||||
@ -285,7 +312,6 @@ Foam::OFstreamCollator::OFstreamCollator
|
||||
localComm_(comm),
|
||||
threadComm_
|
||||
(
|
||||
// dupComm
|
||||
UPstream::allocateCommunicator
|
||||
(
|
||||
localComm_,
|
||||
@ -319,7 +345,7 @@ bool Foam::OFstreamCollator::write
|
||||
(
|
||||
const word& objectType,
|
||||
const fileName& fName,
|
||||
DynamicList<char>&& localData,
|
||||
const string& data,
|
||||
IOstreamOption streamOpt,
|
||||
IOstreamOption::atomicType atomic,
|
||||
IOstreamOption::appendType append,
|
||||
@ -329,109 +355,78 @@ bool Foam::OFstreamCollator::write
|
||||
{
|
||||
// Determine (on master) sizes to receive. Note: do NOT use thread
|
||||
// communicator
|
||||
const labelList recvSizes
|
||||
(
|
||||
UPstream::listGatherValues<label>(localData.size(), localComm_)
|
||||
);
|
||||
labelList recvSizes;
|
||||
decomposedBlockData::gather(localComm_, label(data.size()), recvSizes);
|
||||
|
||||
off_t totalSize = 0;
|
||||
label maxLocalSize = 0;
|
||||
|
||||
if (UPstream::master(localComm_))
|
||||
{
|
||||
for (const label recvSize : recvSizes)
|
||||
if (UPstream::master(localComm_))
|
||||
{
|
||||
totalSize += recvSize;
|
||||
maxLocalSize = max(maxLocalSize, recvSize);
|
||||
for (const label recvSize : recvSizes)
|
||||
{
|
||||
totalSize += recvSize;
|
||||
maxLocalSize = max(maxLocalSize, recvSize);
|
||||
}
|
||||
}
|
||||
Pstream::broadcasts(localComm_, totalSize, maxLocalSize);
|
||||
}
|
||||
Pstream::broadcasts(localComm_, totalSize, maxLocalSize);
|
||||
|
||||
|
||||
// Determine how things will be gathered and written...
|
||||
|
||||
enum class dispatchModes { GATHER_WRITE, PREFETCH_THREADED, FULL_THREADED };
|
||||
|
||||
dispatchModes dispatch(dispatchModes::GATHER_WRITE);
|
||||
|
||||
if (!useThread || maxBufferSize_ == 0 || maxLocalSize > maxBufferSize_)
|
||||
{
|
||||
dispatch = dispatchModes::GATHER_WRITE;
|
||||
}
|
||||
else if (totalSize <= maxBufferSize_)
|
||||
{
|
||||
// Total size can be stored locally
|
||||
// - gather all data now and only do the writing in the thread
|
||||
|
||||
dispatch = dispatchModes::PREFETCH_THREADED;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Gather data and write in the thread
|
||||
|
||||
dispatch = dispatchModes::FULL_THREADED;
|
||||
|
||||
if (!UPstream::haveThreads())
|
||||
{
|
||||
WarningInFunction
|
||||
<< "MPI not initialized with thread support." << nl
|
||||
<< " maxThreadFileBufferSize = 0 to disable threading" << nl
|
||||
<< " or maxThreadFileBufferSize > " << totalSize
|
||||
<< " to collate before threaded writing." << nl << nl;
|
||||
|
||||
dispatch = dispatchModes::GATHER_WRITE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -----------
|
||||
// Dispatching
|
||||
// -----------
|
||||
|
||||
if (dispatch == dispatchModes::GATHER_WRITE)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "OFstreamCollator : non-thread gather/write "
|
||||
<< "(local comm: " << localComm_ << ") of "
|
||||
<< fName << endl;
|
||||
Pout<< "OFstreamCollator : non-thread gather and write of " << fName
|
||||
<< " using local comm " << localComm_ << endl;
|
||||
}
|
||||
|
||||
// Direct collating and writing (so master blocks until all written!)
|
||||
const PtrList<SubList<char>> dummySlaveData;
|
||||
return writeFile
|
||||
(
|
||||
localComm_,
|
||||
objectType,
|
||||
fName,
|
||||
localData,
|
||||
data,
|
||||
recvSizes,
|
||||
UList<stdFoam::span<char>>(), // dummy proc data
|
||||
dummySlaveData,
|
||||
streamOpt,
|
||||
atomic,
|
||||
append,
|
||||
headerEntries
|
||||
);
|
||||
}
|
||||
else if (dispatch == dispatchModes::PREFETCH_THREADED)
|
||||
else if (totalSize <= maxBufferSize_)
|
||||
{
|
||||
// Total size can be stored locally so receive all data now and only
|
||||
// do the writing in the thread
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "OFstreamCollator : non-thread gather; thread write of "
|
||||
<< fName << endl;
|
||||
}
|
||||
|
||||
if (UPstream::master(localComm_))
|
||||
if (Pstream::master(localComm_))
|
||||
{
|
||||
waitForBufferSpace(totalSize);
|
||||
}
|
||||
|
||||
std::unique_ptr<writeData> fileAndDataPtr
|
||||
|
||||
// Receive in chunks of labelMax (2^31-1) since this is the maximum
|
||||
// size that a List can be
|
||||
|
||||
autoPtr<writeData> fileAndDataPtr
|
||||
(
|
||||
new writeData
|
||||
(
|
||||
threadComm_, // Note: comm not actually used anymore
|
||||
objectType,
|
||||
fName,
|
||||
(
|
||||
Pstream::master(localComm_)
|
||||
? data // Only used on master
|
||||
: string::null
|
||||
),
|
||||
recvSizes,
|
||||
streamOpt,
|
||||
atomic,
|
||||
@ -439,81 +434,63 @@ bool Foam::OFstreamCollator::write
|
||||
headerEntries
|
||||
)
|
||||
);
|
||||
auto& fileAndData = *fileAndDataPtr;
|
||||
writeData& fileAndData = fileAndDataPtr();
|
||||
|
||||
List<List<char>>& procData = fileAndData.procData_;
|
||||
if (UPstream::master(localComm_))
|
||||
{
|
||||
// Move in local data (master only!)
|
||||
fileAndData.transfer(localData);
|
||||
PtrList<List<char>>& slaveData = fileAndData.slaveData_;
|
||||
|
||||
// Storage for receive data
|
||||
procData.resize(UPstream::nProcs(localComm_));
|
||||
|
||||
for (const int proci : UPstream::subProcs(localComm_))
|
||||
{
|
||||
procData[proci].resize(recvSizes[proci]);
|
||||
}
|
||||
}
|
||||
else if (UPstream::is_subrank(localComm_))
|
||||
{
|
||||
// Requires a size for decomposedBlockData::writeBlocks() logic
|
||||
procData.resize(UPstream::nProcs(localComm_));
|
||||
}
|
||||
UList<char> slice(const_cast<char*>(data.data()), label(data.size()));
|
||||
|
||||
slaveData.setSize(recvSizes.size());
|
||||
|
||||
// Gather all data onto master. Is done in local communicator since
|
||||
// not in write thread.
|
||||
// not in write thread. Note that we do not store in contiguous
|
||||
// buffer since that would limit to 2G chars.
|
||||
const label startOfRequests = UPstream::nRequests();
|
||||
if (UPstream::master(localComm_))
|
||||
if (Pstream::master(localComm_))
|
||||
{
|
||||
for (const int proci : UPstream::subProcs(localComm_))
|
||||
for (label proci = 1; proci < slaveData.size(); proci++)
|
||||
{
|
||||
List<char>& procSlice = procData[proci];
|
||||
if (procSlice.empty()) continue;
|
||||
|
||||
slaveData.set(proci, new List<char>(recvSizes[proci]));
|
||||
UIPstream::read
|
||||
(
|
||||
UPstream::commsTypes::nonBlocking,
|
||||
proci,
|
||||
procSlice.data_bytes(),
|
||||
procSlice.size_bytes(),
|
||||
UPstream::msgType(),
|
||||
slaveData[proci].data(),
|
||||
slaveData[proci].size_bytes(),
|
||||
Pstream::msgType(),
|
||||
localComm_
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (UPstream::is_subrank(localComm_) && !localData.empty())
|
||||
else
|
||||
{
|
||||
if
|
||||
(
|
||||
!UOPstream::write
|
||||
(
|
||||
UPstream::commsTypes::nonBlocking,
|
||||
UPstream::masterNo(),
|
||||
localData.cdata_bytes(),
|
||||
localData.size_bytes(),
|
||||
UPstream::msgType(),
|
||||
0,
|
||||
slice.cdata(),
|
||||
slice.size_bytes(),
|
||||
Pstream::msgType(),
|
||||
localComm_
|
||||
)
|
||||
)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot send outgoing message (size: "
|
||||
<< localData.size() << ") to master" << nl
|
||||
<< "Cannot send outgoing message. "
|
||||
<< "to:" << 0 << " nBytes:"
|
||||
<< label(slice.size_bytes())
|
||||
<< Foam::abort(FatalError);
|
||||
}
|
||||
}
|
||||
UPstream::waitRequests(startOfRequests);
|
||||
|
||||
// The localData has been moved (master) or communicated
|
||||
localData.clearStorage();
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
|
||||
// Append to thread buffer (as FIFO), take ownership
|
||||
objects_.push_back(fileAndDataPtr.release());
|
||||
// Append to thread buffer
|
||||
objects_.push(fileAndDataPtr.ptr());
|
||||
|
||||
// Start thread if not running
|
||||
if (!threadRunning_)
|
||||
@ -540,46 +517,49 @@ bool Foam::OFstreamCollator::write
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (dispatch == dispatchModes::FULL_THREADED)
|
||||
else
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "OFstreamCollator : thread gather and write "
|
||||
<< "(thread comm: " << threadComm_
|
||||
<< ") of " << fName << endl;
|
||||
Pout<< "OFstreamCollator : thread gather and write of " << fName
|
||||
<< " using communicator " << threadComm_ << endl;
|
||||
}
|
||||
|
||||
if (UPstream::master(localComm_))
|
||||
if (!UPstream::haveThreads())
|
||||
{
|
||||
waitForBufferSpace(localData.size());
|
||||
FatalErrorInFunction
|
||||
<< "mpi does not seem to have thread support."
|
||||
<< " Make sure to set buffer size 'maxThreadFileBufferSize'"
|
||||
<< " to at least " << totalSize
|
||||
<< " to be able to do the collating before threading."
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
std::unique_ptr<writeData> fileAndDataPtr
|
||||
(
|
||||
new writeData
|
||||
(
|
||||
threadComm_,
|
||||
objectType,
|
||||
fName,
|
||||
recvSizes,
|
||||
streamOpt,
|
||||
atomic,
|
||||
append,
|
||||
headerEntries
|
||||
)
|
||||
);
|
||||
|
||||
// Move in local data (all procs)
|
||||
fileAndDataPtr->transfer(localData);
|
||||
if (Pstream::master(localComm_))
|
||||
{
|
||||
waitForBufferSpace(data.size());
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
|
||||
// Append to thread buffer (as FIFO), take ownership
|
||||
objects_.push_back(fileAndDataPtr.release());
|
||||
|
||||
// Note: no proc data provided
|
||||
// Push all file info on buffer. Note that no slave data provided
|
||||
// so it will trigger communication inside the thread
|
||||
objects_.push
|
||||
(
|
||||
new writeData
|
||||
(
|
||||
threadComm_,
|
||||
objectType,
|
||||
fName,
|
||||
data,
|
||||
recvSizes,
|
||||
streamOpt,
|
||||
atomic,
|
||||
append,
|
||||
headerEntries
|
||||
)
|
||||
);
|
||||
|
||||
if (!threadRunning_)
|
||||
{
|
||||
@ -604,12 +584,6 @@ bool Foam::OFstreamCollator::write
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FatalErrorInFunction
|
||||
<< "Unknown dispatch mode: " << int(dispatch)
|
||||
<< " - programming error?" << abort(FatalError);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -617,7 +591,7 @@ void Foam::OFstreamCollator::waitAll()
|
||||
{
|
||||
// Wait for all buffer space to be available i.e. wait for all jobs
|
||||
// to finish
|
||||
if (UPstream::master(localComm_))
|
||||
if (Pstream::master(localComm_))
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2017-2018 OpenFOAM Foundation
|
||||
Copyright (C) 2019-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2021-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -51,13 +51,13 @@ SourceFiles
|
||||
#ifndef Foam_OFstreamCollator_H
|
||||
#define Foam_OFstreamCollator_H
|
||||
|
||||
#include "IOstream.H"
|
||||
#include "List.H"
|
||||
#include "CircularBuffer.H" // As FIFO
|
||||
#include "dictionary.H"
|
||||
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include "IOstream.H"
|
||||
#include "labelList.H"
|
||||
#include "FIFOStack.H"
|
||||
#include "SubList.H"
|
||||
#include "dictionary.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -72,33 +72,26 @@ class OFstreamCollator
|
||||
{
|
||||
// Private Class
|
||||
|
||||
//- Holds data to be written
|
||||
struct writeData
|
||||
{
|
||||
const label comm_;
|
||||
const word objectType_;
|
||||
const fileName pathName_;
|
||||
DynamicList<char> localData_;
|
||||
const string data_;
|
||||
const labelList sizes_;
|
||||
List<List<char>> procData_;
|
||||
PtrList<List<char>> slaveData_;
|
||||
const IOstreamOption streamOpt_;
|
||||
IOstreamOption::atomicType atomic_;
|
||||
IOstreamOption::appendType append_;
|
||||
const dictionary headerEntries_;
|
||||
|
||||
writeData() = delete; // No default construct
|
||||
writeData(const writeData&) = delete; // No copy construct
|
||||
writeData(writeData&&) = delete; // No move construct
|
||||
void operator=(const writeData&) = delete; // No copy assign
|
||||
void operator=(writeData&&) = delete; // No move assign
|
||||
|
||||
//- Construct without local data
|
||||
writeData
|
||||
(
|
||||
const label comm,
|
||||
const word& objectType,
|
||||
const fileName& pathName,
|
||||
const labelUList& sizes,
|
||||
const string& data,
|
||||
const labelList& sizes,
|
||||
IOstreamOption streamOpt,
|
||||
IOstreamOption::atomicType atomic,
|
||||
IOstreamOption::appendType append,
|
||||
@ -108,30 +101,27 @@ class OFstreamCollator
|
||||
comm_(comm),
|
||||
objectType_(objectType),
|
||||
pathName_(pathName),
|
||||
localData_(),
|
||||
data_(data),
|
||||
sizes_(sizes),
|
||||
procData_(),
|
||||
slaveData_(),
|
||||
streamOpt_(streamOpt),
|
||||
atomic_(atomic),
|
||||
append_(append),
|
||||
headerEntries_(headerEntries)
|
||||
{}
|
||||
|
||||
//- Move reset local data
|
||||
void transfer(DynamicList<char>& localData)
|
||||
{
|
||||
localData_.transfer(localData);
|
||||
}
|
||||
|
||||
//- The (approximate) size of local + any optional proc data
|
||||
//- The (approximate) size of master + any optional slave data
|
||||
off_t size() const
|
||||
{
|
||||
off_t total = localData_.size();
|
||||
for (const auto& data : procData_)
|
||||
off_t totalSize = data_.size();
|
||||
forAll(slaveData_, i)
|
||||
{
|
||||
total += data.size();
|
||||
if (slaveData_.set(i))
|
||||
{
|
||||
totalSize += slaveData_[i].size();
|
||||
}
|
||||
}
|
||||
return total;
|
||||
return totalSize;
|
||||
}
|
||||
};
|
||||
|
||||
@ -145,8 +135,8 @@ class OFstreamCollator
|
||||
|
||||
std::unique_ptr<std::thread> thread_;
|
||||
|
||||
//- FIFO of files to write and their contents
|
||||
CircularBuffer<writeData*> objects_;
|
||||
//- Stack of files to write + contents
|
||||
FIFOStack<writeData*> objects_;
|
||||
|
||||
//- Whether thread is running (and not exited)
|
||||
bool threadRunning_;
|
||||
@ -166,9 +156,9 @@ class OFstreamCollator
|
||||
const label comm,
|
||||
const word& objectType,
|
||||
const fileName& fName,
|
||||
const UList<char>& localData,
|
||||
const string& masterData,
|
||||
const labelUList& recvSizes,
|
||||
const UList<stdFoam::span<char>>& procData,
|
||||
const UPtrList<SubList<char>>& slaveData,
|
||||
IOstreamOption streamOpt,
|
||||
IOstreamOption::atomicType atomic,
|
||||
IOstreamOption::appendType append,
|
||||
@ -191,8 +181,7 @@ public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from buffer size (0 = do not use thread)
|
||||
//- and with worldComm
|
||||
//- Construct from buffer size. 0 = do not use thread
|
||||
explicit OFstreamCollator(const off_t maxBufferSize);
|
||||
|
||||
//- Construct from buffer size (0 = do not use thread)
|
||||
@ -206,15 +195,14 @@ public:
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Write file with contents, possibly taking ownership of the
|
||||
//- content.
|
||||
// Blocks until write-thread has space available
|
||||
//- Write file with contents.
|
||||
// Blocks until writethread has space available
|
||||
// (total file sizes < maxBufferSize)
|
||||
bool write
|
||||
(
|
||||
const word& objectType,
|
||||
const fileName& fName,
|
||||
DynamicList<char>&& localData,
|
||||
const fileName&,
|
||||
const string& data,
|
||||
IOstreamOption streamOpt,
|
||||
IOstreamOption::atomicType atomic,
|
||||
IOstreamOption::appendType append,
|
||||
@ -222,37 +210,6 @@ public:
|
||||
const dictionary& headerEntries = dictionary::null
|
||||
);
|
||||
|
||||
//- Write file with contents.
|
||||
FOAM_DEPRECATED_FOR(2023-09, "use write with movable content")
|
||||
bool write
|
||||
(
|
||||
const word& objectType,
|
||||
const fileName& fName,
|
||||
const std::string& s,
|
||||
IOstreamOption streamOpt,
|
||||
IOstreamOption::atomicType atomic,
|
||||
IOstreamOption::appendType append,
|
||||
const bool useThread = true,
|
||||
const dictionary& headerEntries = dictionary::null
|
||||
)
|
||||
{
|
||||
DynamicList<char> charData;
|
||||
charData.setCapacity(s.size());
|
||||
std::copy(s.begin(), s.end(), charData.begin());
|
||||
|
||||
return write
|
||||
(
|
||||
objectType,
|
||||
fName,
|
||||
std::move(charData),
|
||||
streamOpt,
|
||||
atomic,
|
||||
append,
|
||||
useThread,
|
||||
headerEntries
|
||||
);
|
||||
}
|
||||
|
||||
//- Wait for all thread actions to have finished
|
||||
void waitAll();
|
||||
};
|
||||
|
||||
@ -116,7 +116,7 @@ void Foam::fileOperations::collatedFileOperation::printBanner
|
||||
{
|
||||
DetailInfo
|
||||
<< " With non-blocking transfer,"
|
||||
" buffer-size = " << maxMasterFileBufferSize << nl;
|
||||
" buffer-size = " << maxMasterFileBufferSize << nl;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2017-2018 OpenFOAM Foundation
|
||||
Copyright (C) 2020-2023 OpenCFD Ltd.
|
||||
Copyright (C) 2020-2022 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -41,7 +41,7 @@ Foam::threadedCollatedOFstream::threadedCollatedOFstream
|
||||
const bool useThread
|
||||
)
|
||||
:
|
||||
OCharStream(streamOpt),
|
||||
OStringStream(streamOpt),
|
||||
writer_(writer),
|
||||
pathName_(pathName),
|
||||
atomic_(atomic),
|
||||
@ -74,22 +74,11 @@ Foam::threadedCollatedOFstream::threadedCollatedOFstream
|
||||
|
||||
Foam::threadedCollatedOFstream::~threadedCollatedOFstream()
|
||||
{
|
||||
commit();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::threadedCollatedOFstream::commit()
|
||||
{
|
||||
// Take ownership of serialized content, without copying or reallocation
|
||||
DynamicList<char> charData(OCharStream::release());
|
||||
|
||||
writer_.write
|
||||
(
|
||||
decomposedBlockData::typeName,
|
||||
pathName_,
|
||||
std::move(charData),
|
||||
str(),
|
||||
IOstreamOption(IOstreamOption::BINARY, version(), compression_),
|
||||
atomic_,
|
||||
IOstreamOption::NON_APPEND,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user