/*---------------------------------------------------------------------------*\ ========= | \\ / 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