Commit c6d4035c authored by mattijs's avatar mattijs

Added master-slave addressing for coupled points.

- Rewrote globalPoints to use globalIndex class so now only transfers
single label instead of labelPair
- Added addressing in globalMeshData
    - from coupled master points to slave points
    -         ,,          edges     ,,    edges
    - from coupled points (master or slave) to uncoupled boundary faces
    -               ,,                    ,,                      cells
- See test/globalMeshData for simple test
parent 0e0ffa40
globalMeshDataTest.C
EXE = $(FOAM_USER_APPBIN)/globalMeshDataTest
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Application
globalMeshDataTest
Description
Test global point communication
\*---------------------------------------------------------------------------*/
#include "globalMeshData.H"
#include "argList.H"
#include "polyMesh.H"
#include "Time.H"
#include "mapDistribute.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
# include "setRootCase.H"
# include "createTime.H"
# include "createPolyMesh.H"
const globalMeshData& globalData = mesh.globalData();
const indirectPrimitivePatch& coupledPatch = globalData.coupledPatch();
// Test:print shared points
{
const labelListList& globalPointSlaves =
globalData.globalPointSlaves();
const mapDistribute& globalPointSlavesMap =
globalData.globalPointSlavesMap();
pointField coords(globalPointSlavesMap.constructSize());
SubList<point>(coords, coupledPatch.nPoints()).assign
(
coupledPatch.localPoints()
);
// Exchange data
globalPointSlavesMap.distribute(coords);
// Print
forAll(globalPointSlaves, pointI)
{
const labelList& slavePoints = globalPointSlaves[pointI];
if (slavePoints.size() > 0)
{
Pout<< "Master point:" << pointI
<< " coord:" << coords[pointI]
<< " connected to slave points:" << endl;
forAll(slavePoints, i)
{
Pout<< " " << coords[slavePoints[i]] << endl;
}
}
}
}
// Test: point to faces addressing
{
const labelListList& globalPointBoundaryFaces =
globalData.globalPointBoundaryFaces();
const mapDistribute& globalPointBoundaryFacesMap =
globalData.globalPointBoundaryFacesMap();
label nBnd = mesh.nFaces()-mesh.nInternalFaces();
pointField fc(globalPointBoundaryFacesMap.constructSize());
SubList<point>(fc, nBnd).assign
(
primitivePatch
(
SubList<face>
(
mesh.faces(),
nBnd,
mesh.nInternalFaces()
),
mesh.points()
).faceCentres()
);
// Exchange data
globalPointBoundaryFacesMap.distribute(fc);
// Print
forAll(globalPointBoundaryFaces, pointI)
{
const labelList& bFaces = globalPointBoundaryFaces[pointI];
Pout<< "Point:" << pointI
<< " at:" << coupledPatch.localPoints()[pointI]
<< " connected to faces:" << endl;
forAll(bFaces, i)
{
Pout<< " " << fc[bFaces[i]] << endl;
}
}
}
// Test:point to cells addressing
{
const labelList& boundaryCells = globalData.boundaryCells();
const labelListList& globalPointBoundaryCells =
globalData.globalPointBoundaryCells();
const mapDistribute& globalPointBoundaryCellsMap =
globalData.globalPointBoundaryCellsMap();
pointField cc(globalPointBoundaryCellsMap.constructSize());
forAll(boundaryCells, i)
{
cc[i] = mesh.cellCentres()[boundaryCells[i]];
}
// Exchange data
globalPointBoundaryCellsMap.distribute(cc);
// Print
forAll(globalPointBoundaryCells, pointI)
{
const labelList& bCells = globalPointBoundaryCells[pointI];
Pout<< "Point:" << pointI
<< " at:" << coupledPatch.localPoints()[pointI]
<< " connected to cells:" << endl;
forAll(bCells, i)
{
Pout<< " " << cc[bCells[i]] << endl;
}
}
}
// Test:print shared edges
{
const labelListList& globalEdgeSlaves =
globalData.globalEdgeSlaves();
const mapDistribute& globalEdgeSlavesMap =
globalData.globalEdgeSlavesMap();
// Test: distribute edge centres
pointField ec(globalEdgeSlavesMap.constructSize());
forAll(coupledPatch.edges(), edgeI)
{
ec[edgeI] = coupledPatch.edges()[edgeI].centre
(
coupledPatch.localPoints()
);
}
// Exchange data
globalEdgeSlavesMap.distribute(ec);
// Print
forAll(globalEdgeSlaves, edgeI)
{
const labelList& slaveEdges = globalEdgeSlaves[edgeI];
if (slaveEdges.size() > 0)
{
Pout<< "Master edge:" << edgeI
<< " centre:" << ec[edgeI]
<< " connected to slave edges:" << endl;
forAll(slaveEdges, i)
{
Pout<< " " << ec[slaveEdges[i]] << endl;
}
}
}
}
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //
......@@ -32,6 +32,8 @@ License
#include "demandDrivenData.H"
#include "globalPoints.H"
//#include "geomGlobalPoints.H"
#include "polyMesh.H"
#include "mapDistribute.H"
#include "labelIOList.H"
#include "PackedList.H"
#include "mergePoints.H"
......@@ -115,24 +117,17 @@ void Foam::globalMeshData::initProcAddr()
// Given information about locally used edges allocate global shared edges.
void Foam::globalMeshData::countSharedEdges
(
const HashTable<labelList, edge, Hash<edge> >& procSharedEdges,
HashTable<label, edge, Hash<edge> >& globalShared,
const EdgeMap<labelList>& procSharedEdges,
EdgeMap<label>& globalShared,
label& sharedEdgeI
)
{
// Count occurrences of procSharedEdges in global shared edges table.
for
(
HashTable<labelList, edge, Hash<edge> >::const_iterator iter =
procSharedEdges.begin();
iter != procSharedEdges.end();
++iter
)
forAllConstIter(EdgeMap<labelList>, procSharedEdges, iter)
{
const edge& e = iter.key();
HashTable<label, edge, Hash<edge> >::iterator globalFnd =
globalShared.find(e);
EdgeMap<label>::iterator globalFnd = globalShared.find(e);
if (globalFnd == globalShared.end())
{
......@@ -189,10 +184,7 @@ void Foam::globalMeshData::calcSharedEdges() const
// Find edges using shared points. Store correspondence to local edge
// numbering. Note that multiple local edges can have the same shared
// points! (for cyclics or separated processor patches)
HashTable<labelList, edge, Hash<edge> > localShared
(
2*sharedPtAddr.size()
);
EdgeMap<labelList> localShared(2*sharedPtAddr.size());
const edgeList& edges = mesh_.edges();
......@@ -218,7 +210,7 @@ void Foam::globalMeshData::calcSharedEdges() const
sharedPtAddr[e1Fnd()]
);
HashTable<labelList, edge, Hash<edge> >::iterator iter =
EdgeMap<labelList>::iterator iter =
localShared.find(sharedEdge);
if (iter == localShared.end())
......@@ -249,7 +241,7 @@ void Foam::globalMeshData::calcSharedEdges() const
// used). But then this only gets done once so not too bothered about the
// extra global communication.
HashTable<label, edge, Hash<edge> > globalShared(nGlobalPoints());
EdgeMap<label> globalShared(nGlobalPoints());
if (Pstream::master())
{
......@@ -275,10 +267,7 @@ void Foam::globalMeshData::calcSharedEdges() const
{
// Receive the edges using shared points from the slave.
IPstream fromSlave(Pstream::blocking, slave);
HashTable<labelList, edge, Hash<edge> > procSharedEdges
(
fromSlave
);
EdgeMap<labelList> procSharedEdges(fromSlave);
if (debug)
{
......@@ -295,17 +284,11 @@ void Foam::globalMeshData::calcSharedEdges() const
// These were only used once so are not proper shared edges.
// Remove them.
{
HashTable<label, edge, Hash<edge> > oldSharedEdges(globalShared);
EdgeMap<label> oldSharedEdges(globalShared);
globalShared.clear();
for
(
HashTable<label, edge, Hash<edge> >::const_iterator iter =
oldSharedEdges.begin();
iter != oldSharedEdges.end();
++iter
)
forAllConstIter(EdgeMap<label>, oldSharedEdges, iter)
{
if (iter() != -1)
{
......@@ -361,18 +344,11 @@ void Foam::globalMeshData::calcSharedEdges() const
DynamicList<label> dynSharedEdgeLabels(globalShared.size());
DynamicList<label> dynSharedEdgeAddr(globalShared.size());
for
(
HashTable<labelList, edge, Hash<edge> >::const_iterator iter =
localShared.begin();
iter != localShared.end();
++iter
)
forAllConstIter(EdgeMap<labelList>, localShared, iter)
{
const edge& e = iter.key();
HashTable<label, edge, Hash<edge> >::const_iterator edgeFnd =
globalShared.find(e);
EdgeMap<label>::const_iterator edgeFnd = globalShared.find(e);
if (edgeFnd != globalShared.end())
{
......@@ -434,6 +410,557 @@ Foam::label Foam::globalMeshData::countCoincidentFaces
}
void Foam::globalMeshData::calcGlobalPointSlaves() const
{
if (debug)
{
Pout<< "globalMeshData::calcGlobalPointSlaves() :"
<< " calculating coupled master to slave point addressing."
<< endl;
}
// Calculate connected points for master points
globalPoints globalData(mesh_, coupledPatch(), true);
const Map<label>& meshToProcPoint = globalData.meshToProcPoint();
// Create global numbering for coupled points
globalPointNumberingPtr_.reset
(
new globalIndex(globalData.globalIndices())
);
const globalIndex& globalIndices = globalPointNumberingPtr_();
// Create master to slave addressing. Empty for slave points.
globalPointSlavesPtr_.reset
(
new labelListList(coupledPatch().nPoints())
);
labelListList& globalPointSlaves = globalPointSlavesPtr_();
forAllConstIter(Map<label>, meshToProcPoint, iter)
{
label localPointI = iter.key();
const labelList& pPoints = globalData.procPoints()[iter()];
// Am I master?
if
(
globalIndices.isLocal(pPoints[0])
&& globalIndices.toLocal(pPoints[0]) == localPointI
)
{
labelList& slaves = globalPointSlaves[localPointI];
slaves.setSize(pPoints.size()-1);
for (label i = 1; i < pPoints.size(); i++)
{
slaves[i-1] = pPoints[i];
}
}
}
// Create schedule to get information from slaves onto master
// Construct compact numbering and distribution map.
// Changes globalPointSlaves to be indices into compact data
List<Map<label> > compactMap(Pstream::nProcs());
globalPointSlavesMapPtr_.reset
(
new mapDistribute
(
globalIndices,
globalPointSlaves,
compactMap
)
);
if (debug)
{
Pout<< "globalMeshData::calcGlobalPointSlaves() :"
<< " coupled points:" << coupledPatch().nPoints()
<< " additional remote points:"
<< globalPointSlavesMapPtr_().constructSize()
- coupledPatch().nPoints()
<< endl;
}
}
void Foam::globalMeshData::calcGlobalEdgeSlaves() const
{
if (debug)
{
Pout<< "globalMeshData::calcGlobalEdgeSlaves() :"
<< " calculating coupled master to slave edge addressing."
<< endl;
}
const labelListList& globalPointSlaves = this->globalPointSlaves();
const mapDistribute& globalPointSlavesMap = this->globalPointSlavesMap();
// - Send across connected edges (in global edge addressing)
// - Check on receiving side whether edge has same slave edge
// on both endpoints.
// Create global numbering for coupled edges
globalEdgeNumberingPtr_.reset
(
new globalIndex(coupledPatch().nEdges())
);
const globalIndex& globalIndices = globalEdgeNumberingPtr_();
// Coupled point to global coupled edges.
labelListList globalPointEdges(globalPointSlavesMap.constructSize());
// Create local version
const labelListList& pointEdges = coupledPatch().pointEdges();
forAll(pointEdges, pointI)
{
const labelList& pEdges = pointEdges[pointI];
labelList& globalPEdges = globalPointEdges[pointI];
globalPEdges.setSize(pEdges.size());
forAll(pEdges, i)
{
globalPEdges[i] = globalIndices.toGlobal(pEdges[i]);
}
}
// Pull slave data to master
globalPointSlavesMap.distribute(globalPointEdges);
// Now check on master if any of my edges are also on slave.
// This assumes that if slaves have a coupled edge it is also on
// the master (otherwise the mesh would be illegal anyway)
labelHashSet pointEdgeSet;
const edgeList& edges = coupledPatch().edges();
// Create master to slave addressing. Empty for slave edges.
globalEdgeSlavesPtr_.reset(new labelListList(edges.size()));
labelListList& globalEdgeSlaves = globalEdgeSlavesPtr_();
forAll(edges, edgeI)
{
const edge& e = edges[edgeI];
const labelList& slaves0 = globalPointSlaves[e[0]];
const labelList& slaves1 = globalPointSlaves[e[1]];
// Check for edges that are in both slaves0 and slaves1.
pointEdgeSet.clear();
forAll(slaves0, i)
{
const labelList& connectedEdges = globalPointEdges[slaves0[i]];
pointEdgeSet.insert(connectedEdges);
}
forAll(slaves1, i)
{
const labelList& connectedEdges = globalPointEdges[slaves1[i]];
forAll(connectedEdges, j)
{
label globalEdgeI = connectedEdges[j];
if (pointEdgeSet.found(globalEdgeI))
{
// Found slave edge.
label sz = globalEdgeSlaves[edgeI].size();
globalEdgeSlaves[edgeI].setSize(sz+1);
globalEdgeSlaves[edgeI][sz] = globalEdgeI;
}
}
}
}
// Construct map
List<Map<label> > compactMap(Pstream::nProcs());
globalEdgeSlavesMapPtr_.reset
(
new mapDistribute
(
globalIndices,
globalEdgeSlaves,
compactMap
)
);
if (debug)
{
Pout<< "globalMeshData::calcGlobalEdgeSlaves() :"
<< " coupled edge:" << edges.size()
<< " additional remote edges:"
<< globalEdgeSlavesMapPtr_().constructSize() - edges.size()
<< endl;
}
}
// Calculate uncoupled boundary faces (without calculating
// primitiveMesh::pointFaces())
void Foam::globalMeshData::calcPointBoundaryFaces
(
labelListList& pointBoundaryFaces
) const
{
const polyBoundaryMesh& bMesh = mesh_.boundaryMesh();
const Map<label>& meshPointMap = coupledPatch().meshPointMap();
// 1. Count
labelList nPointFaces(coupledPatch().nPoints(), 0);
forAll(bMesh, patchI)
{
const polyPatch& pp = bMesh[patchI];
if (!pp.coupled())
{
forAll(pp, i)
{
const face& f = pp[i];
forAll(f, fp)
{
Map<label>::const_iterator iter = meshPointMap.find(f[fp]);
if (iter != meshPointMap.end())
{
nPointFaces[iter()]++;
}
}
}
}
}
// 2. Size
pointBoundaryFaces.setSize(coupledPatch().nPoints());
forAll(nPointFaces, pointI)
{
pointBoundaryFaces[pointI].setSize(nPointFaces[pointI]);
}
nPointFaces = 0;
// 3. Fill
forAll(bMesh, patchI)
{
const polyPatch& pp = bMesh[patchI];
if (!pp.coupled())
{
forAll(pp, i)
{
const face& f = pp[i];
forAll(f, fp)
{
Map<label>::const_iterator iter = meshPointMap.find(f[fp]);
if (iter != meshPointMap.end())
{
label bFaceI = pp.start() + i - mesh_.nInternalFaces();
pointBoundaryFaces[iter()][nPointFaces[iter()]++] =