ENH: consolidate processorTopology handling for volume and area meshes

- relocate templating to factory method 'New'.
  Adds provisions for more general re-use.

- expose processor topology in globalMesh as topology()

- wrap proc->patch lookup as processorTopology::procPatchLookup method
  (failsafe). May consider using Map<label> for its storage in the
  future.
This commit is contained in:
Mark Olesen 2022-04-26 23:10:05 +02:00
parent dea2f23afd
commit 42de624344
29 changed files with 618 additions and 640 deletions

View File

@ -44,7 +44,7 @@ int main(int argc, char *argv[])
argList::noFunctionObjects();
argList::addNote
(
"Create a metis graph file representation for an OpenFOAM mesh"
"Create graph of OpenFOAM mesh connections"
);
#include "setRootCase.H"
@ -59,9 +59,9 @@ int main(int argc, char *argv[])
#include "createTime.H"
#include "createPolyMesh.H"
const globalMeshData& globData = mesh.globalData();
const labelListList& connectivity = globData;
// Adjacency table
const labelListList& connectivity =
mesh.globalData().topology().procNeighbours();
if (Pstream::master())
{

View File

@ -60,6 +60,7 @@ Description
#include "wedgePolyPatch.H"
#include "planeExtrusion.H"
#include "emptyPolyPatch.H"
#include "processorPolyPatch.H"
#include "processorMeshes.H"
#include "hexRef8Data.H"

View File

@ -57,6 +57,7 @@ Description
#include "fvMeshTools.H"
#include "topoSet.H"
#include "processorPolyPatch.H"
#include "processorMeshes.H"
using namespace Foam;

View File

@ -32,8 +32,8 @@ Description
\*---------------------------------------------------------------------------*/
#ifndef lduSchedule_H
#define lduSchedule_H
#ifndef Foam_lduSchedule_H
#define Foam_lduSchedule_H
#include "List.H"
@ -42,14 +42,17 @@ Description
namespace Foam
{
// Forward declaration of friend functions and operators
// Forward Declarations
struct lduScheduleEntry;
Ostream& operator<<(Ostream& os, const lduScheduleEntry& lb);
//- A List of lduSchedule entries.
typedef List<lduScheduleEntry> lduSchedule;
/*---------------------------------------------------------------------------*\
Class lduSchedule Declaration
Class lduScheduleEntry Declaration
\*---------------------------------------------------------------------------*/
struct lduScheduleEntry
@ -57,11 +60,22 @@ struct lduScheduleEntry
label patch;
bool init;
friend bool operator!=
(
const lduScheduleEntry& lb1,
const lduScheduleEntry& lb2
)
//- Define patch for initEvaluate()
void setInitEvaluate(const label patchi) noexcept
{
patch = patchi;
init = true;
}
//- Define patch for evaluate()
void setEvaluate(const label patchi) noexcept
{
patch = patchi;
init = false;
}
//- Always unequal: each entry is supposed to be unique!
friend bool operator!=(const lduScheduleEntry&, const lduScheduleEntry&)
{
return true;
}
@ -74,9 +88,6 @@ struct lduScheduleEntry
};
typedef List<lduScheduleEntry> lduSchedule;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam

View File

@ -1,273 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "ProcessorTopology.H"
#include "ListOps.H"
#include "Pstream.H"
#include "commSchedule.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class Container, class ProcPatch>
Foam::labelList Foam::ProcessorTopology<Container, ProcPatch>::procNeighbours
(
const label nProcs,
const Container& patches
)
{
// Determine number of processor neighbours and max neighbour id.
label nNeighbours = 0;
label maxNb = 0;
boolList isNeighbourProc(nProcs, false);
forAll(patches, patchi)
{
const auto* cpp = isA<ProcPatch>(patches[patchi]);
if (cpp)
{
const label nbrProci = cpp->neighbProcNo();
if (!isNeighbourProc[nbrProci])
{
isNeighbourProc[nbrProci] = true;
maxNb = max(maxNb, nbrProci);
++nNeighbours;
}
}
}
labelList neighbours(nNeighbours, -1);
nNeighbours = 0;
forAll(isNeighbourProc, proci)
{
if (isNeighbourProc[proci])
{
neighbours[nNeighbours++] = proci;
}
}
procPatchMap_.setSize(maxNb + 1);
procPatchMap_ = -1;
forAll(patches, patchi)
{
const auto* cpp = isA<ProcPatch>(patches[patchi]);
if (cpp)
{
const label nbrProci = cpp->neighbProcNo();
// Reverse map
procPatchMap_[nbrProci] = patchi;
}
}
return neighbours;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Container, class ProcPatch>
Foam::ProcessorTopology<Container, ProcPatch>::ProcessorTopology
(
const Container& patches,
const label comm
)
:
labelListList(Pstream::nProcs(comm)),
patchSchedule_()
{
if (Pstream::parRun())
{
// Fill my 'slot' with my neighbours
operator[](Pstream::myProcNo(comm)) =
procNeighbours(this->size(), patches);
// Distribute to all processors
Pstream::allGatherList(*this, Pstream::msgType(), comm);
}
if
(
Pstream::parRun()
&& Pstream::defaultCommsType == Pstream::commsTypes::scheduled
)
{
patchSchedule_.resize(2*patches.size());
label patchEvali = 0;
// 1. All non-processor patches
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
forAll(patches, patchi)
{
if (!isA<ProcPatch>(patches[patchi]))
{
patchSchedule_[patchEvali].patch = patchi;
patchSchedule_[patchEvali++].init = true;
patchSchedule_[patchEvali].patch = patchi;
patchSchedule_[patchEvali++].init = false;
}
}
// 2. All processor patches
// ~~~~~~~~~~~~~~~~~~~~~~~~
// Determine the schedule for all. Insert processor pair once
// to determine the schedule. Each processor pair stands for both
// send and receive.
label nComms = 0;
for (const labelList& neighbours : *this)
{
nComms += neighbours.size();
}
DynamicList<labelPair> comms(nComms);
forAll(*this, proci)
{
const labelList& neighbours = operator[](proci);
for (const label nbrProci : neighbours)
{
if (proci < nbrProci)
{
comms.append(labelPair(proci, nbrProci));
}
}
}
comms.shrink();
// Determine a schedule.
labelList mySchedule
(
commSchedule
(
Pstream::nProcs(comm),
comms
).procSchedule()[Pstream::myProcNo(comm)]
);
for (const label commI : mySchedule)
{
// Get the other processor
label nb = comms[commI][0];
if (nb == Pstream::myProcNo(comm))
{
nb = comms[commI][1];
}
label patchi = procPatchMap_[nb];
if (Pstream::myProcNo(comm) > nb)
{
patchSchedule_[patchEvali].patch = patchi;
patchSchedule_[patchEvali++].init = true;
patchSchedule_[patchEvali].patch = patchi;
patchSchedule_[patchEvali++].init = false;
}
else
{
patchSchedule_[patchEvali].patch = patchi;
patchSchedule_[patchEvali++].init = false;
patchSchedule_[patchEvali].patch = patchi;
patchSchedule_[patchEvali++].init = true;
}
}
}
else
{
patchSchedule_ = nonBlockingSchedule(patches);
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Container, class ProcPatch>
Foam::lduSchedule
Foam::ProcessorTopology<Container, ProcPatch>::nonBlockingSchedule
(
const Container& patches
)
{
lduSchedule patchSchedule(2*patches.size());
label patchEvali = 0;
// 1. All non-processor patches
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Have evaluate directly after initEvaluate. Could have them separated
// as long as they're not intermingled with processor patches since
// then e.g. any reduce parallel traffic would interfere with the
// processor swaps.
forAll(patches, patchi)
{
if (!isA<ProcPatch>(patches[patchi]))
{
patchSchedule[patchEvali].patch = patchi;
patchSchedule[patchEvali++].init = true;
patchSchedule[patchEvali].patch = patchi;
patchSchedule[patchEvali++].init = false;
}
}
// 2. All processor patches
// ~~~~~~~~~~~~~~~~~~~~~~~~
// 2a. initEvaluate
forAll(patches, patchi)
{
if (isA<ProcPatch>(patches[patchi]))
{
patchSchedule[patchEvali].patch = patchi;
patchSchedule[patchEvali++].init = true;
}
}
// 2b. evaluate
forAll(patches, patchi)
{
if (isA<ProcPatch>(patches[patchi]))
{
patchSchedule[patchEvali].patch = patchi;
patchSchedule[patchEvali++].init = false;
}
}
return patchSchedule;
}
// ************************************************************************* //

View File

@ -1,126 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::ProcessorTopology
Description
Determines processor-processor connection. After instantiation contains
on all processors the processor-processor connection table.
*this[proci] gives the list of neighbouring processors.
TODO: This does not currently correctly support multiple processor
patches connecting two processors.
SourceFiles
ProcessorTopology.C
\*---------------------------------------------------------------------------*/
#ifndef Foam_ProcessorTopology_H
#define Foam_ProcessorTopology_H
#include "labelList.H"
#include "lduSchedule.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class ProcessorTopology Declaration
\*---------------------------------------------------------------------------*/
template<class Container, class ProcPatch>
class ProcessorTopology
:
public labelListList
{
// Private Data
//- Local map from neighbour proc to patchi. Different per processor!
// -1 or patchi for connection to procID
labelList procPatchMap_;
//- Order in which the patches should be initialised/evaluated
// corresponding to the schedule
lduSchedule patchSchedule_;
// Private Member Functions
//- Return all neighbouring processors of this processor.
// Sets procPatchMap_.
labelList procNeighbours(const label nProcs, const Container&);
public:
// Constructors
//- Construct from boundaryMesh
ProcessorTopology(const Container& patches, const label comm);
// Static Functions
//- Calculate non-blocking (i.e. unscheduled) schedule
static lduSchedule nonBlockingSchedule(const Container& patches);
// Member Functions
//- From neighbour processor to index in boundaryMesh.
// Local information (so not same over all processors)
const labelList& procPatchMap() const noexcept
{
return procPatchMap_;
}
//- Order in which the patches should be initialised/evaluated
//- corresponding to the schedule
const lduSchedule& patchSchedule() const noexcept
{
return patchSchedule_;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "ProcessorTopology.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2013 OpenFOAM Foundation
Copyright (C) 2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -36,38 +37,37 @@ Foam::lduSchedule Foam::lduPrimitiveMesh::nonBlockingSchedule
)
{
lduSchedule schedule(2*interfaces.size());
label slotI = 0;
forAll(interfaces, i)
// 1. All non-processor patches
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
label patchEvali = 0;
forAll(interfaces, patchi)
{
if (interfaces.set(i) && !isA<ProcPatch>(interfaces[i]))
if (interfaces.set(patchi) && !isA<ProcPatch>(interfaces[patchi]))
{
schedule[slotI].patch = i;
schedule[slotI].init = true;
slotI++;
schedule[slotI].patch = i;
schedule[slotI].init = false;
slotI++;
schedule[patchEvali++].setInitEvaluate(patchi);
schedule[patchEvali++].setEvaluate(patchi);
}
}
forAll(interfaces, i)
// 2. All processor patches
// ~~~~~~~~~~~~~~~~~~~~~~~~
forAll(interfaces, patchi)
{
if (interfaces.set(i) && isA<ProcPatch>(interfaces[i]))
if (interfaces.set(patchi) && isA<ProcPatch>(interfaces[patchi]))
{
schedule[slotI].patch = i;
schedule[slotI].init = true;
slotI++;
schedule[patchEvali++].setInitEvaluate(patchi);
}
}
forAll(interfaces, i)
forAll(interfaces, patchi)
{
if (interfaces.set(i) && isA<ProcPatch>(interfaces[i]))
if (interfaces.set(patchi) && isA<ProcPatch>(interfaces[patchi]))
{
schedule[slotI].patch = i;
schedule[slotI].init = false;
slotI++;
schedule[patchEvali++].setEvaluate(patchi);
}
}

View File

@ -27,14 +27,15 @@ License
\*---------------------------------------------------------------------------*/
#include "globalMeshData.H"
#include "Pstream.H"
#include "processorPolyPatch.H"
#include "globalPoints.H"
#include "polyMesh.H"
#include "mapDistribute.H"
#include "labelIOList.H"
#include "mergePoints.H"
#include "processorPolyPatch.H"
#include "processorTopologyNew.H"
#include "globalIndexAndTransform.H"
#include "Pstream.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -61,15 +62,15 @@ public:
void Foam::globalMeshData::initProcAddr()
{
processorPatchIndices_.setSize(mesh_.boundaryMesh().size());
processorPatchIndices_.resize_nocopy(mesh_.boundaryMesh().size());
processorPatchIndices_ = -1;
processorPatchNeighbours_.setSize(mesh_.boundaryMesh().size());
processorPatchNeighbours_.resize_nocopy(mesh_.boundaryMesh().size());
processorPatchNeighbours_ = -1;
// Construct processor patch indexing. processorPatchNeighbours_ only
// set if running in parallel!
processorPatches_.setSize(mesh_.boundaryMesh().size());
processorPatches_.resize_nocopy(mesh_.boundaryMesh().size());
label nNeighbours = 0;
@ -81,7 +82,7 @@ void Foam::globalMeshData::initProcAddr()
processorPatchIndices_[patchi] = nNeighbours++;
}
}
processorPatches_.setSize(nNeighbours);
processorPatches_.resize(nNeighbours);
if (Pstream::parRun())
@ -1728,14 +1729,21 @@ void Foam::globalMeshData::calcGlobalCoPointSlaves() const
Foam::globalMeshData::globalMeshData(const polyMesh& mesh)
:
processorTopology(mesh.boundaryMesh(), UPstream::worldComm),
mesh_(mesh),
nTotalPoints_(-1),
nTotalFaces_(-1),
nTotalCells_(-1),
processorPatches_(0),
processorPatchIndices_(0),
processorPatchNeighbours_(0),
processorTopology_
(
processorTopology::New<processorPolyPatch>
(
mesh.boundaryMesh(),
UPstream::worldComm
)
),
processorPatches_(),
processorPatchIndices_(),
processorPatchNeighbours_(),
nGlobalPoints_(-1),
sharedPointLabelsPtr_(nullptr),
sharedPointAddrPtr_(nullptr),
@ -1750,10 +1758,9 @@ Foam::globalMeshData::globalMeshData(const polyMesh& mesh)
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
// A non-default destructor since we had incomplete types in the header
Foam::globalMeshData::~globalMeshData()
{
clearOut();
}
{}
void Foam::globalMeshData::clearOut()
@ -1780,6 +1787,7 @@ void Foam::globalMeshData::clearOut()
globalPointSlavesPtr_.clear();
globalPointTransformedSlavesPtr_.clear();
globalPointSlavesMapPtr_.clear();
// Edge
globalEdgeNumberingPtr_.clear();
globalEdgeSlavesPtr_.clear();
@ -2728,7 +2736,7 @@ void Foam::globalMeshData::updateMesh()
if (debug)
{
Pout<< "globalMeshData : nTotalFaces_:" << nTotalFaces_ << endl;
Pout<< "globalMeshData : nTotalFaces:" << nTotalFaces_ << endl;
}
nTotalCells_ = returnReduce
@ -2741,7 +2749,7 @@ void Foam::globalMeshData::updateMesh()
if (debug)
{
Pout<< "globalMeshData : nTotalCells_:" << nTotalCells_ << endl;
Pout<< "globalMeshData : nTotalCells:" << nTotalCells_ << endl;
}
nTotalPoints_ = returnReduce
@ -2757,7 +2765,7 @@ void Foam::globalMeshData::updateMesh()
if (debug)
{
Pout<< "globalMeshData : nTotalPoints_:" << nTotalPoints_ << endl;
Pout<< "globalMeshData : nTotalPoints:" << nTotalPoints_ << endl;
}
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2021 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -81,8 +81,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/
#ifndef globalMeshData_H
#define globalMeshData_H
#ifndef Foam_globalMeshData_H
#define Foam_globalMeshData_H
#include "processorTopology.H"
#include "labelPair.H"
@ -106,8 +106,6 @@ class bitSet;
\*---------------------------------------------------------------------------*/
class globalMeshData
:
public processorTopology
{
// Private Data
@ -129,6 +127,9 @@ class globalMeshData
// Processor patch addressing (be careful if not running in parallel!)
//- The processor/processor topology
processorTopology processorTopology_;
//- List of processor patch labels
// (size of list = number of processor patches)
labelList processorPatches_;
@ -377,6 +378,19 @@ public:
// Processor patch addressing (be careful when not running in parallel)
//- The processor to processor topology.
const processorTopology& topology() const noexcept
{
return processorTopology_;
}
//- Order in which the patches should be initialised/evaluated
//- corresponding to the schedule
const lduSchedule& patchSchedule() const noexcept
{
return processorTopology_.patchSchedule();
}
//- Return list of processor patch labels
// (size of list = number of processor patches)
const labelList& processorPatches() const noexcept
@ -393,7 +407,7 @@ public:
}
//- Return processorPatchIndices of the neighbours
// processor patches. -1 if not running parallel.
//- processor patches. -1 if not running parallel.
const labelList& processorPatchNeighbours() const noexcept
{
return processorPatchNeighbours_;

View File

@ -1,51 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2013 OpenFOAM Foundation
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#ifndef processorTopology_H
#define processorTopology_H
#include "ProcessorTopology.H"
#include "processorPolyPatch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
typedef ProcessorTopology<polyPatchList, processorPolyPatch> processorTopology;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -90,7 +90,8 @@ Foam::commSchedule::commSchedule
if (proc0 < 0 || proc0 >= nProcs || proc1 < 0 || proc1 >= nProcs)
{
FatalErrorInFunction
<< "Illegal processor " << comms[commI] << abort(FatalError);
<< "Illegal processor(s): "
<< comms[commI] << abort(FatalError);
}
procToComms[proc0].append(commI);

View File

@ -42,8 +42,8 @@ Description
- procSchedule()[proci] gives per proci
Does not care whether 'talking' is first send, second receive or maybe
full swap. This is all responsibility of caller. See ProcessorTopology
class for use in scheduling processor boundary swaps.
full swap. This is all responsibility of caller.
See Foam::rocessorTopology for use in scheduling processor boundary swaps.
SourceFiles
commSchedule.C
@ -78,13 +78,17 @@ class commSchedule
public:
//- Runtime type information
ClassName("commSchedule");
// Constructors
//- Construct from wanted communication. Wanted communication is between
// two processors. Can be a one-way communication or
// two-way communication, that is up to the caller. This class just
//- two processors. Can be a one-way communication or
//- two-way communication, that is up to the caller.
//
// This class just
// determines an order for it such that any processor is only talking
// to one other at a time. After construction:
// - schedule is the order in which comms is done.

View File

@ -0,0 +1,176 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::processorTopology
Description
Determines/represents processor-processor connection.
After instantiation contains the processor-processor connection table
(globally synchronized on all processors).
Note
A processorTopology is usually generated by using the \c New
factory method, which has been wrapped into a separate header to
minimize dependencies.
Warning
Does not currently correctly support multiple processor
patches connecting two processors.
SourceFiles
processorTopologyNew.H
\*---------------------------------------------------------------------------*/
#ifndef Foam_processorTopology_H
#define Foam_processorTopology_H
#include "labelList.H"
#include "lduSchedule.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class processorTopology Declaration
\*---------------------------------------------------------------------------*/
class processorTopology
{
// Private Data
//- The processor to processor connection (adjacency) table
labelListList procNeighbours_;
//- Order in which the patches should be initialised/evaluated
//- corresponding to the schedule
lduSchedule patchSchedule_;
//- Local map from neighbour proc to patchi. Different per processor!
// -1 or patchi for connection to procID
labelList procPatchMap_;
// Private Member Functions
//- From neighbour processor to index in our local boundary.
// Local information (so not same over all processors)
///const labelList& procPatchMap() const noexcept
///{
/// return procPatchMap_;
///}
//- Which \em local boundary is attached to specified processor
// Local information (so not same over all processors)
// \return -1 if not currently connected to specified processor.
label procToLocalPatch(const label proci) const
{
return
(
proci >= 0 && proci < procPatchMap_.size()
? procPatchMap_[proci]
: static_cast<label>(-1)
);
}
public:
// Generated Methods
//- Default construct (empty)
processorTopology() = default;
//- Copy construct
processorTopology(const processorTopology&) = default;
//- Move construct
processorTopology(processorTopology&&) = default;
//- Copy assignment
processorTopology& operator=(const processorTopology&) = default;
//- Move assignment
processorTopology& operator=(processorTopology&&) = default;
// Static Functions
//- Factory method to create topology, schedule and proc/patch maps.
// Scans the list of patches for processor connections corresponding
// to the ProcPatch type.
template<class ProcPatch, class PatchListType>
static processorTopology New
(
const PatchListType& patches,
const label comm
);
// Member Functions
//- The number of processors used by the topology
label nProcs() const noexcept
{
return procNeighbours_.size();
}
//- The processor to processor connection topology
//- (like an adjacency list). Globally synchronized information
const labelListList& procNeighbours() const noexcept
{
return procNeighbours_;
}
//- Order in which the patches should be initialised/evaluated
//- corresponding to the schedule
const lduSchedule& patchSchedule() const noexcept
{
return patchSchedule_;
}
//- Which \em local boundary is attached to specified processor
// Local information (so not same over all processors)
// \return -1 if not currently connected to specified processor.
label procPatchLookup(const label proci) const
{
return procToLocalPatch(proci);
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,229 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
InClass
Foam::processorTopology
Description
Define the processor-processor connection table by walking a list of
patches and detecting the processor ones.
This has been split off as a separate include from processorTopology
to minimize dependencies.
Warning
Does not currently correctly support multiple processor
patches connecting two processors.
\*---------------------------------------------------------------------------*/
#ifndef Foam_processorTopologyNew_H
#define Foam_processorTopologyNew_H
#include "processorTopology.H"
#include "bitSet.H"
#include "commSchedule.H"
#include "DynamicList.H"
#include "Pstream.H"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
template<class ProcPatch, class PatchListType>
Foam::processorTopology Foam::processorTopology::New
(
const PatchListType& patches,
const label comm
)
{
const label myProci = Pstream::myProcNo(comm);
const label nProcs = Pstream::nProcs(comm);
processorTopology procTopo;
auto& procToProcs = procTopo.procNeighbours_;
auto& procToPatch = procTopo.procPatchMap_;
auto& schedule = procTopo.patchSchedule_;
procToProcs.resize(nProcs);
schedule.resize(2*patches.size());
if (Pstream::parRun())
{
// Fill my 'slot' with my neighbours
auto& procSlot = procToProcs[myProci];
bitSet isNeighbour(procToProcs.size());
forAll(patches, patchi)
{
const auto* cpp = isA<ProcPatch>(patches[patchi]);
if (cpp)
{
const label nbrProci = cpp->neighbProcNo();
isNeighbour.set(nbrProci);
}
}
// The neighbouring procs in sorted (ascending) order
procSlot = isNeighbour.sortedToc();
const label maxNbrProci = procSlot.empty() ? -1 : procSlot.last();
// Note could also use Map<label> if desired
procToPatch.resize_nocopy(maxNbrProci + 1);
procToPatch = -1;
forAll(patches, patchi)
{
const auto* cpp = isA<ProcPatch>(patches[patchi]);
if (cpp)
{
const label nbrProci = cpp->neighbProcNo();
// Reverse map
procToPatch[nbrProci] = patchi;
}
}
// Synchronize on all processors
Pstream::allGatherList(procToProcs, UPstream::msgType(), comm);
}
// Define the schedule
label patchEvali = 0;
// 1. All non-processor patches
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
forAll(patches, patchi)
{
if (!isA<ProcPatch>(patches[patchi]))
{
schedule[patchEvali++].setInitEvaluate(patchi);
schedule[patchEvali++].setEvaluate(patchi);
}
}
// 2. All processor patches
// ~~~~~~~~~~~~~~~~~~~~~~~~
if
(
Pstream::parRun()
&& Pstream::defaultCommsType == Pstream::commsTypes::scheduled
)
{
// Determine the schedule for all processor patches.
// Insert processor pair once to determine the schedule.
// Each processor pair stands for both send and receive.
label nComms = 0;
for (const labelList& nbrProcs : procToProcs)
{
nComms += nbrProcs.size();
}
DynamicList<labelPair> comms(nComms/2);
forAll(procToProcs, proci)
{
for (const label nbrProci : procToProcs[proci])
{
if (proci < nbrProci)
{
comms.append(labelPair(proci, nbrProci));
}
}
}
// Determine a schedule.
labelList mySchedule
(
commSchedule
(
nProcs,
comms
).procSchedule()[myProci]
);
for (const label scheduleIndex : mySchedule)
{
// Get the other processor
label nbrProci = comms[scheduleIndex][0];
if (nbrProci == myProci)
{
nbrProci = comms[scheduleIndex][1];
}
const label patchi = procToPatch[nbrProci];
if (myProci > nbrProci)
{
schedule[patchEvali++].setInitEvaluate(patchi);
schedule[patchEvali++].setEvaluate(patchi);
}
else
{
schedule[patchEvali++].setEvaluate(patchi);
schedule[patchEvali++].setInitEvaluate(patchi);
}
}
}
else
{
// Non-blocking schedule for processor patches
// initEvaluate
forAll(patches, patchi)
{
if (isA<ProcPatch>(patches[patchi]))
{
schedule[patchEvali++].setInitEvaluate(patchi);
}
}
// evaluate
forAll(patches, patchi)
{
if (isA<ProcPatch>(patches[patchi]))
{
schedule[patchEvali++].setEvaluate(patchi);
}
}
}
return procTopo;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -28,6 +28,7 @@ License
#include "interfaceTrackingFvMesh.H"
#include "primitivePatchInterpolation.H"
#include "emptyFaPatch.H"
#include "processorFaPatch.H"
#include "wedgeFaPatch.H"
#include "wallFvPatch.H"
#include "coordinateSystem.H"

View File

@ -30,6 +30,7 @@ License
#include "addToRunTimeSelectionTable.H"
#include "motionSolver.H"
#include "volFields.H"
#include "processorFaPatch.H"
#include "wedgeFaPatch.H"
#include "wedgeFaPatchFields.H"
#include "slipFaPatchFields.H"

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2015-2017,2020-2021 OpenCFD Ltd.
Copyright (C) 2015-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -1201,30 +1201,30 @@ void Foam::addPatchCellLayer::calcExtrudeInfo
if (otherProci != -1)
{
if (gd[Pstream::myProcNo()].found(otherProci))
// Use existing processorPolyPatch to otherProci?
label procPatchi =
gd.topology().procPatchLookup(otherProci);
if (procPatchi < 0)
{
// There is already a processorPolyPatch to otherProci.
// Use it. Note that we can only index procPatchMap
// if the processor actually is a neighbour processor
// so that is why we first check.
edgePatchID[edgei] = gd.procPatchMap()[otherProci];
}
else
{
// Cannot find a patch to processor. See if already
// marked for addition
if (nbrProcToPatch.found(otherProci))
// No existing processorPolyPatch to otherProci.
// See if already marked for addition
procPatchi = nbrProcToPatch.lookup(otherProci, -1);
if (procPatchi < 0)
{
edgePatchID[edgei] = nbrProcToPatch[otherProci];
}
else
{
edgePatchID[edgei] = nPatches;
nbrProcToPatch.insert(otherProci, nPatches);
patchToNbrProc.insert(nPatches, otherProci);
nPatches++;
// Add new proc-patch, mark for addition.
procPatchi = nPatches;
++nPatches;
nbrProcToPatch.insert(otherProci, procPatchi);
patchToNbrProc.insert(procPatchi, otherProci);
}
}
edgePatchID[edgei] = procPatchi;
}
}
}

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -23,8 +24,6 @@ License
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Description
Author
Hrvoje Jasak
@ -33,16 +32,25 @@ Author
#include "faGlobalMeshData.H"
#include "faMesh.H"
#include "globalMeshData.H"
#include "processorFaPatch.H"
#include "processorTopologyNew.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::faGlobalMeshData::faGlobalMeshData(const faMesh& mesh)
:
faProcessorTopology(mesh.boundary(), UPstream::worldComm),
mesh_(mesh),
processorTopology_
(
processorTopology::New<processorFaPatch>
(
mesh.boundary(),
UPstream::worldComm
)
),
nGlobalPoints_(-1),
sharedPointLabels_(0),
sharedPointAddr_(0)
sharedPointLabels_(),
sharedPointAddr_()
{
updateMesh();
}
@ -50,13 +58,14 @@ Foam::faGlobalMeshData::faGlobalMeshData(const faMesh& mesh)
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
// A non-default destructor since we had incomplete types in the header
Foam::faGlobalMeshData::~faGlobalMeshData()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::faMesh& Foam::faGlobalMeshData::mesh() const
const Foam::faMesh& Foam::faGlobalMeshData::mesh() const noexcept
{
return mesh_;
}

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd
Copyright (C) 2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -35,17 +36,17 @@ Author
\*---------------------------------------------------------------------------*/
#ifndef faGlobalMeshData_H
#define faGlobalMeshData_H
#ifndef Foam_faGlobalMeshData_H
#define Foam_faGlobalMeshData_H
#include "faProcessorTopology.H"
#include "processorTopology.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Class forward declarations
// Class Declarations
class faMesh;
/*---------------------------------------------------------------------------*\
@ -53,25 +54,28 @@ class faMesh;
\*---------------------------------------------------------------------------*/
class faGlobalMeshData
:
public faProcessorTopology
{
// Private data
// Private Data
//- Reference to mesh
const faMesh& mesh_;
// Globally shared point addressing
//- The processor/processor topology
processorTopology processorTopology_;
//- Total number of global points
label nGlobalPoints_;
//- Indices of local points that are globally shared
labelList sharedPointLabels_;
// Globally shared point addressing
//- Total number of global points
label nGlobalPoints_;
//- Indices of local points that are globally shared
labelList sharedPointLabels_;
//- Indices of globally shared points in the master list
// This list contains all the shared points in the mesh
labelList sharedPointAddr_;
//- Indices of globally shared points in the master list
// This list contains all the shared points in the mesh
labelList sharedPointAddr_;
// Private Member Functions
@ -87,8 +91,12 @@ public:
//- Runtime type information
ClassName("faGlobalMeshData");
//- Construct from mesh
faGlobalMeshData(const faMesh& mesh);
// Constructors
//- Construct from mesh
explicit faGlobalMeshData(const faMesh& mesh);
//- Destructor
~faGlobalMeshData();
@ -96,34 +104,50 @@ public:
// Member Functions
// Access
// Access
//- Return mesh reference
const faMesh& mesh() const;
//- Return mesh reference
const faMesh& mesh() const noexcept;
// Globally shared point addressing
//- Return number of globally shared points
label nGlobalPoints() const
{
return nGlobalPoints_;
}
// Processor-Topology
//- Return indices of local points that are globally shared
const labelList& sharedPointLabels() const
{
return sharedPointLabels_;
}
//- The processor to processor topology.
const processorTopology& topology() const noexcept
{
return processorTopology_;
}
//- Return addressing into the complete globally shared points
// list
const labelList& sharedPointAddr() const
{
return sharedPointAddr_;
}
//- Order in which the patches should be initialised/evaluated
//- corresponding to the schedule
const lduSchedule& patchSchedule() const noexcept
{
return processorTopology_.patchSchedule();
}
//- Change global mesh data given a topological change.
void updateMesh();
// Globally shared point addressing
//- Return number of globally shared points
label nGlobalPoints() const noexcept
{
return nGlobalPoints_;
}
//- Return indices of local points that are globally shared
const labelList& sharedPointLabels() const noexcept
{
return sharedPointLabels_;
}
//- Return addressing into the complete globally shared points list
const labelList& sharedPointAddr() const noexcept
{
return sharedPointAddr_;
}
//- Change global mesh data given a topological change.
void updateMesh();
};

View File

@ -1,60 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2017 Wikki Ltd
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Typedef
Foam::faProcessorTopology
Description
Author
Zeljko Tukovic, FMENA
Hrvoje Jasak, Wikki Ltd.
\*---------------------------------------------------------------------------*/
#ifndef Foam_faProcessorTopology_H
#define Foam_faProcessorTopology_H
#include "ProcessorTopology.H"
#include "processorFaPatch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
typedef ProcessorTopology<faPatchList, processorFaPatch> faProcessorTopology;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -27,6 +27,7 @@ License
\*---------------------------------------------------------------------------*/
#include "processorFaPatch.H"
#include "processorPolyPatch.H" // For newName()
#include "addToRunTimeSelectionTable.H"
#include "transformField.H"
#include "faBoundaryMesh.H"

View File

@ -31,6 +31,7 @@ License
#include "Pstream.H"
#include "cyclicPolyPatch.H"
#include "emptyPolyPatch.H"
#include "processorPolyPatch.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

View File

@ -26,6 +26,7 @@ License
\*---------------------------------------------------------------------------*/
#include "fieldExtents.H"
#include "processorPolyPatch.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

View File

@ -28,6 +28,7 @@ License
#include "vtkWrite.H"
#include "cellBitSet.H"
#include "topoSetCellSource.H"
#include "processorPolyPatch.H"
// * * * * * * * * * * * * * * Local Data Members * * * * * * * * * * * * * //

View File

@ -29,6 +29,7 @@ License
#include "surfaceAlignedSBRStressFvMotionSolver.H"
#include "addToRunTimeSelectionTable.H"
#include "pointIndexHit.H"
#include "processorPolyPatch.H"
#include "fvmLaplacian.H"
#include "fvcDiv.H"
#include "surfaceInterpolate.H"

View File

@ -161,7 +161,8 @@ void Foam::Cloud<ParticleType>::move
const labelList& procPatchNeighbours = pData.processorPatchNeighbours();
// Which processors this processor is connected to
const labelList& neighbourProcs = pData[Pstream::myProcNo()];
const labelList& neighbourProcs =
pData.topology().procNeighbours()[Pstream::myProcNo()];
// Initialise the stepFraction moved for the particles
for (ParticleType& p : *this)

View File

@ -27,11 +27,11 @@ License
#include "voxelMeshSearch.H"
#include "polyMesh.H"
#include "processorPolyPatch.H"
#include "IOobject.H"
#include "fvMesh.H"
#include "block.H"
#include "emptyPolyPatch.H"
#include "processorPolyPatch.H"
#include "fvMeshTools.H"
/* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */

View File

@ -31,6 +31,7 @@ License
#include "globalIndex.H"
#include "meshToMeshMethod.H"
#include "nearestFaceAMI.H"
#include "processorPolyPatch.H"
#include "faceAreaWeightAMI.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

View File

@ -29,6 +29,7 @@ License
#include "dictionary.H"
#include "polyMesh.H"
#include "polyPatch.H"
#include "processorPolyPatch.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "volPointInterpolation.H"