/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2013-2017 OpenFOAM Foundation
Copyright (C) 2021-2023 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 "GAMGProcAgglomeration.H"
#include "GAMGAgglomeration.H"
#include "lduMesh.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(GAMGProcAgglomeration, 0);
defineRunTimeSelectionTable(GAMGProcAgglomeration, GAMGAgglomeration);
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::GAMGProcAgglomeration::printStats
(
Ostream& os,
GAMGAgglomeration& agglom
) const
{
for (label levelI = 0; levelI <= agglom.size(); levelI++)
{
if (agglom.hasMeshLevel(levelI))
{
os << "Level " << levelI << " mesh:"
<< agglom.meshLevel(levelI).info() << endl;
}
else
{
os << "Level " << levelI << " has no fine mesh:" << endl;
}
if
(
levelI < agglom.restrictAddressing_.size()
&& agglom.restrictAddressing_.set(levelI)
)
{
const labelList& cellRestrict =
agglom.restrictAddressing(levelI);
const labelList& faceRestrict =
agglom.faceRestrictAddressing(levelI);
os << "Level " << levelI << " agglomeration:" << nl
<< " nCoarseCells:" << agglom.nCells(levelI) << nl
<< " nCoarseFaces:" << agglom.nFaces(levelI) << nl
<< " cellRestriction:"
<< " size:" << cellRestrict.size()
<< " max:" << max(cellRestrict)
<< nl
<< " faceRestriction:"
<< " size:" << faceRestrict.size()
<< " max:" << max(faceRestrict)
<< nl;
const labelListList& patchFaceRestrict =
agglom.patchFaceRestrictAddressing(levelI);
forAll(patchFaceRestrict, i)
{
if (patchFaceRestrict[i].size())
{
const labelList& faceRestrict =
patchFaceRestrict[i];
os << " " << i
<< " size:" << faceRestrict.size()
<< " max:" << max(faceRestrict)
<< nl;
}
}
}
if
(
levelI < agglom.procCellOffsets_.size()
&& agglom.procCellOffsets_.set(levelI)
)
{
os << " procCellOffsets:" << agglom.procCellOffsets_[levelI]
<< nl
<< " procAgglomMap:" << agglom.procAgglomMap_[levelI]
<< nl
<< " procIDs:" << agglom.agglomProcIDs_[levelI]
<< nl
<< " comm:" << agglom.procCommunicator_[levelI]
<< endl;
}
os << endl;
}
os << endl;
}
Foam::labelListList Foam::GAMGProcAgglomeration::globalCellCells
(
const lduMesh& mesh
)
{
const lduAddressing& addr = mesh.lduAddr();
lduInterfacePtrsList interfaces = mesh.interfaces();
const label myProci = UPstream::myProcNo(mesh.comm());
const globalIndex globalNumbering
(
addr.size(),
mesh.comm(),
UPstream::parRun()
);
const labelList globalIndices
(
Foam::identity(globalNumbering.range(myProci))
);
// Get the interface cells
PtrList nbrGlobalCells(interfaces.size());
{
const label startOfRequests = UPstream::nRequests();
// Initialise transfer of restrict addressing on the interface
forAll(interfaces, inti)
{
if (interfaces.set(inti))
{
interfaces[inti].initInternalFieldTransfer
(
Pstream::commsTypes::nonBlocking,
globalIndices
);
}
}
UPstream::waitRequests(startOfRequests);
forAll(interfaces, inti)
{
if (interfaces.set(inti))
{
nbrGlobalCells.set
(
inti,
new labelList
(
interfaces[inti].internalFieldTransfer
(
Pstream::commsTypes::nonBlocking,
globalIndices
)
)
);
}
}
}
// Scan the neighbour list to find out how many times the cell
// appears as a neighbour of the face. Done this way to avoid guessing
// and resizing list
labelList nNbrs(addr.size(), 1);
const labelUList& nbr = addr.upperAddr();
const labelUList& own = addr.lowerAddr();
{
forAll(nbr, facei)
{
nNbrs[nbr[facei]]++;
nNbrs[own[facei]]++;
}
forAll(interfaces, inti)
{
if (interfaces.set(inti))
{
const labelUList& faceCells = interfaces[inti].faceCells();
forAll(faceCells, i)
{
nNbrs[faceCells[i]]++;
}
}
}
}
// Create cell-cells addressing
labelListList cellCells(addr.size());
forAll(cellCells, celli)
{
cellCells[celli].setSize(nNbrs[celli], -1);
}
// Reset the list of number of neighbours to zero
nNbrs = 0;
// Scatter the neighbour faces
forAll(nbr, facei)
{
label c0 = own[facei];
label c1 = nbr[facei];
cellCells[c0][nNbrs[c0]++] = globalIndices[c1];
cellCells[c1][nNbrs[c1]++] = globalIndices[c0];
}
forAll(interfaces, inti)
{
if (interfaces.set(inti))
{
const labelUList& faceCells = interfaces[inti].faceCells();
forAll(faceCells, i)
{
label c0 = faceCells[i];
cellCells[c0][nNbrs[c0]++] = nbrGlobalCells[inti][i];
}
}
}
forAll(cellCells, celli)
{
Foam::stableSort(cellCells[celli]);
}
// Replace the initial element (always -1) with the local cell
forAll(cellCells, celli)
{
cellCells[celli][0] = globalIndices[celli];
}
return cellCells;
}
bool Foam::GAMGProcAgglomeration::agglomerate
(
const label fineLevelIndex,
const labelList& procAgglomMap,
const labelList& masterProcs,
const List