/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2013-2015 OpenFOAM Foundation
Copyright (C) 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 "manualGAMGProcAgglomeration.H"
#include "addToRunTimeSelectionTable.H"
#include "GAMGAgglomeration.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(manualGAMGProcAgglomeration, 0);
addToRunTimeSelectionTable
(
GAMGProcAgglomeration,
manualGAMGProcAgglomeration,
GAMGAgglomeration
);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::manualGAMGProcAgglomeration::manualGAMGProcAgglomeration
(
GAMGAgglomeration& agglom,
const dictionary& controlDict
)
:
GAMGProcAgglomeration(agglom, controlDict),
procAgglomMaps_(controlDict.lookup("processorAgglomeration"))
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::manualGAMGProcAgglomeration::~manualGAMGProcAgglomeration()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::manualGAMGProcAgglomeration::agglomerate()
{
if (debug)
{
Pout<< nl << "Starting mesh overview" << endl;
printStats(Pout, agglom_);
}
if (agglom_.size() >= 1)
{
forAll(procAgglomMaps_, i)
{
const label fineLevelIndex = procAgglomMaps_[i].first();
if (fineLevelIndex >= agglom_.size())
{
WarningInFunction
<< "Ignoring specification for level " << fineLevelIndex
<< " since outside agglomeration." << endl;
continue;
}
if (agglom_.hasMeshLevel(fineLevelIndex))
{
// Get the fine mesh
const lduMesh& levelMesh = agglom_.meshLevel(fineLevelIndex);
label nProcs = UPstream::nProcs(levelMesh.comm());
if (nProcs > 1)
{
// My processor id
const label myProcID = Pstream::myProcNo(levelMesh.comm());
const List& clusters =
procAgglomMaps_[i].second();
// Coarse to fine master processor
labelList coarseToMaster(clusters.size());
// Fine to coarse map
labelList procAgglomMap(nProcs, -1);
// Cluster for my processor (with master index first)
labelList agglomProcIDs;
forAll(clusters, coarseI)
{
const labelList& cluster = clusters[coarseI];
coarseToMaster[coarseI] = cluster[0];
forAll(cluster, i)
{
procAgglomMap[cluster[i]] = coarseI;
}
const label masterIndex =
cluster.find(coarseToMaster[coarseI]);
if (masterIndex == -1)
{
FatalErrorInFunction
<< "At level " << fineLevelIndex
<< " the master processor "
<< coarseToMaster[coarseI]
<< " is not in the cluster "
<< cluster
<< exit(FatalError);
}
if (cluster.found(myProcID))
{
// This is my cluster. Make sure master index is
// first
agglomProcIDs = cluster;
std::swap
(
agglomProcIDs[0],
agglomProcIDs[masterIndex]
);
}
}
// Check that we've done all processors
if (procAgglomMap.found(-1))
{
FatalErrorInFunction
<< "At level " << fineLevelIndex
<< " processor "
<< procAgglomMap.find(-1)
<< " is not in any cluster"
<< exit(FatalError);
}
// Communicator for the processor-agglomerated matrix
comms_.push_back
(
UPstream::newCommunicator
(
levelMesh.comm(),
coarseToMaster
)
);
// Use processor agglomeration maps to do the actual
// collecting
if (UPstream::myProcNo(levelMesh.comm()) != -1)
{
GAMGProcAgglomeration::agglomerate
(
fineLevelIndex,
procAgglomMap,
coarseToMaster,
agglomProcIDs,
comms_.back()
);
}
}
}
}
// Print a bit
if (debug)
{
Pout<< nl << "Agglomerated mesh overview" << endl;
printStats(Pout, agglom_);
}
}
return true;
}
// ************************************************************************* //