mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: add parallel sync checks for finite-area
- reduce the amount of communication when checking zones and patches by performing the synchonization check on the gathered strings (master only) and reduce or broadcast the result. STYLE: simplify coupled() checks depending only on parRun
This commit is contained in:
@ -138,14 +138,7 @@ public:
|
|||||||
//- Return true if running parallel
|
//- Return true if running parallel
|
||||||
virtual bool coupled() const
|
virtual bool coupled() const
|
||||||
{
|
{
|
||||||
if (Pstream::parRun())
|
return Pstream::parRun();
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Does the patch field perform the transformation
|
//- Does the patch field perform the transformation
|
||||||
|
|||||||
@ -142,14 +142,7 @@ public:
|
|||||||
//- Return true if running parallel
|
//- Return true if running parallel
|
||||||
virtual bool coupled() const
|
virtual bool coupled() const
|
||||||
{
|
{
|
||||||
if (Pstream::parRun())
|
return Pstream::parRun();
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Does the patch field perform the transformation
|
//- Does the patch field perform the transformation
|
||||||
|
|||||||
@ -959,8 +959,8 @@ bool Foam::polyBoundaryMesh::checkParallelSync(const bool report) const
|
|||||||
bool hasError = false;
|
bool hasError = false;
|
||||||
|
|
||||||
// Collect non-proc patches and check proc patches are last.
|
// Collect non-proc patches and check proc patches are last.
|
||||||
wordList names(bm.size());
|
wordList localNames(bm.size());
|
||||||
wordList types(bm.size());
|
wordList localTypes(bm.size());
|
||||||
|
|
||||||
label nonProci = 0;
|
label nonProci = 0;
|
||||||
|
|
||||||
@ -970,65 +970,67 @@ bool Foam::polyBoundaryMesh::checkParallelSync(const bool report) const
|
|||||||
{
|
{
|
||||||
if (nonProci != patchi)
|
if (nonProci != patchi)
|
||||||
{
|
{
|
||||||
// There is processor patch in between normal patches.
|
// A processor patch in between normal patches!
|
||||||
hasError = true;
|
hasError = true;
|
||||||
|
|
||||||
if (debug || report)
|
if (debug || report)
|
||||||
{
|
{
|
||||||
Pout<< " ***Problem with boundary patch " << patchi
|
Pout<< " ***Problem with boundary patch " << patchi
|
||||||
<< " named " << bm[patchi].name()
|
<< " name:" << bm[patchi].name()
|
||||||
<< " of type " << bm[patchi].type()
|
<< " type:" << bm[patchi].type()
|
||||||
<< ". The patch seems to be preceeded by processor"
|
<< " - seems to be preceeded by processor patches."
|
||||||
<< " patches. This is can give problems."
|
<< " This is usually a problem." << endl;
|
||||||
<< endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
names[nonProci] = bm[patchi].name();
|
localNames[nonProci] = bm[patchi].name();
|
||||||
types[nonProci] = bm[patchi].type();
|
localTypes[nonProci] = bm[patchi].type();
|
||||||
nonProci++;
|
++nonProci;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
names.setSize(nonProci);
|
localNames.resize(nonProci);
|
||||||
types.setSize(nonProci);
|
localTypes.resize(nonProci);
|
||||||
|
|
||||||
List<wordList> allNames(Pstream::nProcs());
|
// Check and report error(s) on master
|
||||||
allNames[Pstream::myProcNo()] = names;
|
|
||||||
Pstream::allGatherList(allNames);
|
|
||||||
|
|
||||||
List<wordList> allTypes(Pstream::nProcs());
|
const globalIndex procAddr
|
||||||
allTypes[Pstream::myProcNo()] = types;
|
|
||||||
Pstream::allGatherList(allTypes);
|
|
||||||
|
|
||||||
// Have every processor check but print error on master
|
|
||||||
// (in processor sequence).
|
|
||||||
|
|
||||||
for (const int proci : Pstream::subProcs())
|
|
||||||
{
|
|
||||||
if
|
|
||||||
(
|
(
|
||||||
(allNames[proci] != allNames.first())
|
// Don't need to collect master itself
|
||||||
|| (allTypes[proci] != allTypes.first())
|
(Pstream::master() ? 0 : nonProci),
|
||||||
)
|
globalIndex::gatherOnly{}
|
||||||
|
);
|
||||||
|
|
||||||
|
const wordList allNames(procAddr.gather(localNames));
|
||||||
|
const wordList allTypes(procAddr.gather(localTypes));
|
||||||
|
|
||||||
|
// Automatically restricted to master
|
||||||
|
for (const int proci : procAddr.subProcs())
|
||||||
|
{
|
||||||
|
const auto procNames(allNames.slice(procAddr.range(proci)));
|
||||||
|
const auto procTypes(allTypes.slice(procAddr.range(proci)));
|
||||||
|
|
||||||
|
if (procNames != localNames || procTypes != localTypes)
|
||||||
{
|
{
|
||||||
hasError = true;
|
hasError = true;
|
||||||
|
|
||||||
if (debug || (report && Pstream::master()))
|
if (debug || report)
|
||||||
{
|
{
|
||||||
Info<< " ***Inconsistent patches across processors, "
|
Info<< " ***Inconsistent patches across processors, "
|
||||||
"processor 0 has patch names:"
|
"processor0 has patch names:" << localNames
|
||||||
<< allNames.first()
|
<< " patch types:" << localTypes
|
||||||
<< " patch types:" << allTypes.first()
|
<< " processor" << proci
|
||||||
<< " processor " << proci
|
<< " has patch names:" << procNames
|
||||||
<< " has patch names:" << allNames[proci]
|
<< " patch types:" << procTypes
|
||||||
<< " patch types:" << allTypes[proci]
|
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reduce (not broadcast) to respect local out-of-order errors (first loop)
|
||||||
|
reduce(hasError, orOp<bool>());
|
||||||
|
|
||||||
return hasError;
|
return hasError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -274,11 +274,12 @@ public:
|
|||||||
labelHashSet& nonGroupPatches
|
labelHashSet& nonGroupPatches
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Check whether all procs have all patches and in same order. Return
|
//- Check whether all procs have all patches and in same order.
|
||||||
// true if in error.
|
// \return True if in error.
|
||||||
bool checkParallelSync(const bool report = false) const;
|
bool checkParallelSync(const bool report = false) const;
|
||||||
|
|
||||||
//- Check boundary definition. Return true if in error.
|
//- Check boundary definition.
|
||||||
|
// \return True if in error.
|
||||||
bool checkDefinition(const bool report = false) const;
|
bool checkDefinition(const bool report = false) const;
|
||||||
|
|
||||||
//- Correct polyBoundaryMesh after moving points
|
//- Correct polyBoundaryMesh after moving points
|
||||||
|
|||||||
@ -255,14 +255,7 @@ public:
|
|||||||
//- Return true only if this is a parallel run
|
//- Return true only if this is a parallel run
|
||||||
virtual bool coupled() const
|
virtual bool coupled() const
|
||||||
{
|
{
|
||||||
if (Pstream::parRun())
|
return Pstream::parRun();
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Return processor number
|
//- Return processor number
|
||||||
|
|||||||
@ -31,6 +31,7 @@ License
|
|||||||
#include "DynamicList.H"
|
#include "DynamicList.H"
|
||||||
#include "Pstream.H"
|
#include "Pstream.H"
|
||||||
#include "PtrListOps.H"
|
#include "PtrListOps.H"
|
||||||
|
#include "globalIndex.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -760,41 +761,47 @@ bool Foam::ZoneMesh<ZoneType, MeshType>::checkParallelSync
|
|||||||
|
|
||||||
bool hasError = false;
|
bool hasError = false;
|
||||||
|
|
||||||
// Collect all names
|
const wordList localNames(this->names());
|
||||||
List<wordList> allNames(Pstream::nProcs());
|
const wordList localTypes(this->types());
|
||||||
allNames[Pstream::myProcNo()] = this->names();
|
|
||||||
Pstream::allGatherList(allNames);
|
|
||||||
|
|
||||||
List<wordList> allTypes(Pstream::nProcs());
|
// Check and report error(s) on master
|
||||||
allTypes[Pstream::myProcNo()] = this->types();
|
|
||||||
Pstream::allGatherList(allTypes);
|
|
||||||
|
|
||||||
// Have every processor check but only master print error.
|
const globalIndex procAddr
|
||||||
|
|
||||||
for (label proci = 1; proci < allNames.size(); ++proci)
|
|
||||||
{
|
|
||||||
if
|
|
||||||
(
|
(
|
||||||
(allNames[proci] != allNames[0])
|
// Don't need to collect master itself
|
||||||
|| (allTypes[proci] != allTypes[0])
|
(Pstream::master() ? 0 : localNames.size()),
|
||||||
)
|
globalIndex::gatherOnly{}
|
||||||
|
);
|
||||||
|
|
||||||
|
const wordList allNames(procAddr.gather(localNames));
|
||||||
|
const wordList allTypes(procAddr.gather(localTypes));
|
||||||
|
|
||||||
|
// Automatically restricted to master
|
||||||
|
for (const int proci : procAddr.subProcs())
|
||||||
|
{
|
||||||
|
const auto procNames(allNames.slice(procAddr.range(proci)));
|
||||||
|
const auto procTypes(allTypes.slice(procAddr.range(proci)));
|
||||||
|
|
||||||
|
if (procNames != localNames || procTypes != localTypes)
|
||||||
{
|
{
|
||||||
hasError = true;
|
hasError = true;
|
||||||
|
|
||||||
if (debug || (report && Pstream::master()))
|
if (debug || report)
|
||||||
{
|
{
|
||||||
Info<< " ***Inconsistent zones across processors, "
|
Info<< " ***Inconsistent zones across processors, "
|
||||||
"processor 0 has zone names:" << allNames[0]
|
"processor 0 has zone names:" << localNames
|
||||||
<< " zone types:" << allTypes[0]
|
<< " zone types:" << localTypes
|
||||||
<< " processor " << proci << " has zone names:"
|
<< " processor " << proci
|
||||||
<< allNames[proci]
|
<< " has zone names:" << procNames
|
||||||
<< " zone types:" << allTypes[proci]
|
<< " zone types:" << procTypes
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check contents
|
Pstream::broadcast(hasError);
|
||||||
|
|
||||||
|
// Check local contents
|
||||||
if (!hasError)
|
if (!hasError)
|
||||||
{
|
{
|
||||||
for (const ZoneType& zn : zones)
|
for (const ZoneType& zn : zones)
|
||||||
|
|||||||
@ -395,25 +395,35 @@ void Foam::fvMeshDistribute::getFieldNames
|
|||||||
|
|
||||||
|
|
||||||
// Check all procs have same names
|
// Check all procs have same names
|
||||||
if (syncPar)
|
if (syncPar && Pstream::parRun())
|
||||||
{
|
{
|
||||||
List<wordList> allNames(Pstream::nProcs());
|
// Check and report error(s) on master
|
||||||
allNames[Pstream::myProcNo()] = list;
|
|
||||||
Pstream::allGatherList(allNames);
|
|
||||||
|
|
||||||
for (const int proci : Pstream::subProcs())
|
const globalIndex procAddr
|
||||||
|
(
|
||||||
|
// Don't need to collect master itself
|
||||||
|
(Pstream::master() ? 0 : list.size()),
|
||||||
|
globalIndex::gatherOnly{}
|
||||||
|
);
|
||||||
|
|
||||||
|
const wordList allNames(procAddr.gather(list));
|
||||||
|
|
||||||
|
// Automatically restricted to master
|
||||||
|
for (const int proci : procAddr.subProcs())
|
||||||
{
|
{
|
||||||
if (allNames[proci] != allNames[0])
|
const auto procNames(allNames.slice(procAddr.range(proci)));
|
||||||
|
|
||||||
|
if (procNames != list)
|
||||||
{
|
{
|
||||||
FatalErrorInFunction
|
FatalErrorInFunction
|
||||||
<< "When checking for equal "
|
<< "When checking for equal " << GeoField::typeName
|
||||||
<< GeoField::typeName
|
|
||||||
<< " :" << nl
|
<< " :" << nl
|
||||||
<< "processor0 has:" << allNames[0] << endl
|
<< "processor0 has:" << list << nl
|
||||||
<< "processor" << proci << " has:" << allNames[proci] << nl
|
<< "processor" << proci << " has:" << procNames << nl
|
||||||
<< GeoField::typeName
|
<< GeoField::typeName
|
||||||
<< " need to be synchronised on all processors."
|
<< " need to be synchronised on all processors."
|
||||||
<< exit(FatalError);
|
<< exit(FatalError);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,9 @@ License
|
|||||||
|
|
||||||
#include "faBoundaryMesh.H"
|
#include "faBoundaryMesh.H"
|
||||||
#include "faMesh.H"
|
#include "faMesh.H"
|
||||||
|
#include "globalIndex.H"
|
||||||
#include "primitiveMesh.H"
|
#include "primitiveMesh.H"
|
||||||
|
#include "processorFaPatch.H"
|
||||||
#include "PtrListOps.H"
|
#include "PtrListOps.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
@ -625,6 +627,94 @@ Foam::label Foam::faBoundaryMesh::whichPatch(const label edgeIndex) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::faBoundaryMesh::checkParallelSync(const bool report) const
|
||||||
|
{
|
||||||
|
if (!Pstream::parRun())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const faBoundaryMesh& bm = *this;
|
||||||
|
|
||||||
|
bool hasError = false;
|
||||||
|
|
||||||
|
// Collect non-proc patches and check proc patches are last.
|
||||||
|
wordList localNames(bm.size());
|
||||||
|
wordList localTypes(bm.size());
|
||||||
|
|
||||||
|
label nonProci = 0;
|
||||||
|
|
||||||
|
forAll(bm, patchi)
|
||||||
|
{
|
||||||
|
if (!isA<processorFaPatch>(bm[patchi]))
|
||||||
|
{
|
||||||
|
if (nonProci != patchi)
|
||||||
|
{
|
||||||
|
// A processor patch in between normal patches!
|
||||||
|
hasError = true;
|
||||||
|
|
||||||
|
if (debug || report)
|
||||||
|
{
|
||||||
|
Pout<< " ***Problem with boundary patch " << patchi
|
||||||
|
<< " name:" << bm[patchi].name()
|
||||||
|
<< " type:" << bm[patchi].type()
|
||||||
|
<< " - seems to be preceeded by processor patches."
|
||||||
|
<< " This is usually a problem." << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
localNames[nonProci] = bm[patchi].name();
|
||||||
|
localTypes[nonProci] = bm[patchi].type();
|
||||||
|
++nonProci;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
localNames.resize(nonProci);
|
||||||
|
localTypes.resize(nonProci);
|
||||||
|
|
||||||
|
// Check and report error(s) on master
|
||||||
|
|
||||||
|
const globalIndex procAddr
|
||||||
|
(
|
||||||
|
// Don't need to collect master itself
|
||||||
|
(Pstream::master() ? 0 : nonProci),
|
||||||
|
globalIndex::gatherOnly{}
|
||||||
|
);
|
||||||
|
|
||||||
|
const wordList allNames(procAddr.gather(localNames));
|
||||||
|
const wordList allTypes(procAddr.gather(localTypes));
|
||||||
|
|
||||||
|
// Automatically restricted to master
|
||||||
|
for (const int proci : procAddr.subProcs())
|
||||||
|
{
|
||||||
|
const auto procNames(allNames.slice(procAddr.range(proci)));
|
||||||
|
const auto procTypes(allTypes.slice(procAddr.range(proci)));
|
||||||
|
|
||||||
|
if (procNames != localNames || procTypes != localTypes)
|
||||||
|
{
|
||||||
|
hasError = true;
|
||||||
|
|
||||||
|
if (debug || report)
|
||||||
|
{
|
||||||
|
Info<< " ***Inconsistent patches across processors, "
|
||||||
|
"processor0 has patch names:" << localNames
|
||||||
|
<< " patch types:" << localTypes
|
||||||
|
<< " processor" << proci
|
||||||
|
<< " has patch names:" << procNames
|
||||||
|
<< " patch types:" << procTypes
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reduce (not broadcast) to respect local out-of-order errors (first loop)
|
||||||
|
reduce(hasError, orOp<bool>());
|
||||||
|
|
||||||
|
return hasError;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Foam::faBoundaryMesh::checkDefinition(const bool report) const
|
bool Foam::faBoundaryMesh::checkDefinition(const bool report) const
|
||||||
{
|
{
|
||||||
label nextPatchStart = mesh().nInternalEdges();
|
label nextPatchStart = mesh().nInternalEdges();
|
||||||
|
|||||||
@ -210,8 +210,13 @@ public:
|
|||||||
void setGroup(const word& groupName, const labelUList& patchIDs);
|
void setGroup(const word& groupName, const labelUList& patchIDs);
|
||||||
|
|
||||||
//- Check boundary definition
|
//- Check boundary definition
|
||||||
|
// \return True if in error.
|
||||||
bool checkDefinition(const bool report = false) const;
|
bool checkDefinition(const bool report = false) const;
|
||||||
|
|
||||||
|
//- Check whether all procs have all patches and in same order.
|
||||||
|
// \return True if in error.
|
||||||
|
bool checkParallelSync(const bool report = false) const;
|
||||||
|
|
||||||
|
|
||||||
// Edit
|
// Edit
|
||||||
|
|
||||||
|
|||||||
@ -151,14 +151,7 @@ public:
|
|||||||
//- Return true if running parallel
|
//- Return true if running parallel
|
||||||
virtual bool coupled() const
|
virtual bool coupled() const
|
||||||
{
|
{
|
||||||
if (Pstream::parRun())
|
return Pstream::parRun();
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Return neighbour field given internal field
|
//- Return neighbour field given internal field
|
||||||
|
|||||||
@ -139,21 +139,12 @@ public:
|
|||||||
virtual ~processorFaePatchField();
|
virtual ~processorFaePatchField();
|
||||||
|
|
||||||
|
|
||||||
// Member functions
|
// Member Functions
|
||||||
|
|
||||||
// Access
|
|
||||||
|
|
||||||
//- Return true if running parallel
|
//- Return true if running parallel
|
||||||
virtual bool coupled() const
|
virtual bool coupled() const
|
||||||
{
|
{
|
||||||
if (Pstream::parRun())
|
return Pstream::parRun();
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -171,21 +171,14 @@ public:
|
|||||||
~processorFvPatchField() = default;
|
~processorFvPatchField() = default;
|
||||||
|
|
||||||
|
|
||||||
// Member functions
|
// Member Functions
|
||||||
|
|
||||||
// Access
|
// Access
|
||||||
|
|
||||||
//- Return true if running parallel
|
//- Return true if running parallel
|
||||||
virtual bool coupled() const
|
virtual bool coupled() const
|
||||||
{
|
{
|
||||||
if (Pstream::parRun())
|
return Pstream::parRun();
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Return neighbour field given internal field
|
//- Return neighbour field given internal field
|
||||||
|
|||||||
@ -136,21 +136,12 @@ public:
|
|||||||
virtual ~processorFvsPatchField();
|
virtual ~processorFvsPatchField();
|
||||||
|
|
||||||
|
|
||||||
// Member functions
|
// Member Functions
|
||||||
|
|
||||||
// Access
|
|
||||||
|
|
||||||
//- Return true if running parallel
|
//- Return true if running parallel
|
||||||
virtual bool coupled() const
|
virtual bool coupled() const
|
||||||
{
|
{
|
||||||
if (Pstream::parRun())
|
return Pstream::parRun();
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -137,21 +137,12 @@ public:
|
|||||||
virtual ~processorCyclicFvsPatchField();
|
virtual ~processorCyclicFvsPatchField();
|
||||||
|
|
||||||
|
|
||||||
// Member functions
|
// Member Functions
|
||||||
|
|
||||||
// Access
|
|
||||||
|
|
||||||
//- Return true if running parallel
|
//- Return true if running parallel
|
||||||
virtual bool coupled() const
|
virtual bool coupled() const
|
||||||
{
|
{
|
||||||
if (Pstream::parRun())
|
return Pstream::parRun();
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user