/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 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 .
\*---------------------------------------------------------------------------*/
#include "regionSplit.H"
#include "cyclicPolyPatch.H"
#include "processorPolyPatch.H"
#include "globalIndex.H"
#include "syncTools.H"
#include "FaceCellWave.H"
#include "minData.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(regionSplit, 0);
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::regionSplit::calcNonCompactRegionSplit
(
const globalIndex& globalFaces,
const boolList& blockedFace,
const List& explicitConnections,
labelList& cellRegion
) const
{
// Field on cells and faces.
List cellData(mesh().nCells());
List faceData(mesh().nFaces());
// Take over blockedFaces by seeding a negative number
// (so is always less than the decomposition)
label nUnblocked = 0;
forAll(faceData, faceI)
{
if (blockedFace.size() && blockedFace[faceI])
{
faceData[faceI] = minData(-2);
}
else
{
nUnblocked++;
}
}
// Seed unblocked faces
labelList seedFaces(nUnblocked);
List seedData(nUnblocked);
nUnblocked = 0;
forAll(faceData, faceI)
{
if (blockedFace.empty() || !blockedFace[faceI])
{
seedFaces[nUnblocked] = faceI;
// Seed face with globally unique number
seedData[nUnblocked] = minData(globalFaces.toGlobal(faceI));
nUnblocked++;
}
}
// Propagate information inwards
FaceCellWave deltaCalc
(
mesh(),
explicitConnections,
false, // disable walking through cyclicAMI for backwards compatibility
seedFaces,
seedData,
faceData,
cellData,
mesh().globalData().nTotalCells()+1
);
// And extract
cellRegion.setSize(mesh().nCells());
forAll(cellRegion, cellI)
{
if (cellData[cellI].valid(deltaCalc.data()))
{
cellRegion[cellI] = cellData[cellI].data();
}
else
{
// Unvisited cell -> only possible if surrounded by blocked faces.
// If so make up region from any of the faces
const cell& cFaces = mesh().cells()[cellI];
label faceI = cFaces[0];
if (blockedFace.size() && !blockedFace[faceI])
{
FatalErrorInFunction
<< "Problem: unblocked face " << faceI
<< " at " << mesh().faceCentres()[faceI]
<< " on unassigned cell " << cellI
<< mesh().cellCentres()[faceI]
<< exit(FatalError);
}
cellRegion[cellI] = globalFaces.toGlobal(faceI);
}
}
}
Foam::autoPtr Foam::regionSplit::calcRegionSplit
(
const bool doGlobalRegions,
const boolList& blockedFace,
const List& explicitConnections,
labelList& cellRegion
) const
{
// See header in regionSplit.H
if (!doGlobalRegions)
{
// Block all parallel faces to avoid comms across
boolList coupledOrBlockedFace(blockedFace);
const polyBoundaryMesh& pbm = mesh().boundaryMesh();
if (coupledOrBlockedFace.size())
{
forAll(pbm, patchI)
{
const polyPatch& pp = pbm[patchI];
if (isA(pp))
{
label faceI = pp.start();
forAll(pp, i)
{
coupledOrBlockedFace[faceI++] = true;
}
}
}
}
// Create dummy (local only) globalIndex
labelList offsets(Pstream::nProcs()+1, 0);
for (label i = Pstream::myProcNo()+1; i < offsets.size(); i++)
{
offsets[i] = mesh().nFaces();
}
const globalIndex globalRegions(offsets.xfer());
// Minimise regions across connected cells
// Note: still uses global decisions so all processors are running
// in lock-step, i.e. slowest determines overall time.
// To avoid this we could switch off Pstream::parRun.
calcNonCompactRegionSplit
(
globalRegions,
coupledOrBlockedFace,
explicitConnections,
cellRegion
);
// Compact
Map