mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
pairGAMGAgglomeration: Support reverse cell-scanning without reversing the order of the generated agglomeration
Gives better cache coherency
This commit is contained in:
@ -26,177 +26,7 @@ License
|
|||||||
#include "pairGAMGAgglomeration.H"
|
#include "pairGAMGAgglomeration.H"
|
||||||
#include "lduAddressing.H"
|
#include "lduAddressing.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::tmp<Foam::labelField> Foam::pairGAMGAgglomeration::agglomerate
|
|
||||||
(
|
|
||||||
label& nCoarseCells,
|
|
||||||
const lduAddressing& fineMatrixAddressing,
|
|
||||||
const scalarField& faceWeights
|
|
||||||
)
|
|
||||||
{
|
|
||||||
const label nFineCells = fineMatrixAddressing.size();
|
|
||||||
|
|
||||||
const labelUList& upperAddr = fineMatrixAddressing.upperAddr();
|
|
||||||
const labelUList& lowerAddr = fineMatrixAddressing.lowerAddr();
|
|
||||||
|
|
||||||
// For each cell calculate faces
|
|
||||||
labelList cellFaces(upperAddr.size() + lowerAddr.size());
|
|
||||||
labelList cellFaceOffsets(nFineCells + 1);
|
|
||||||
|
|
||||||
// memory management
|
|
||||||
{
|
|
||||||
labelList nNbrs(nFineCells, 0);
|
|
||||||
|
|
||||||
forAll(upperAddr, facei)
|
|
||||||
{
|
|
||||||
nNbrs[upperAddr[facei]]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
forAll(lowerAddr, facei)
|
|
||||||
{
|
|
||||||
nNbrs[lowerAddr[facei]]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
cellFaceOffsets[0] = 0;
|
|
||||||
forAll(nNbrs, celli)
|
|
||||||
{
|
|
||||||
cellFaceOffsets[celli+1] = cellFaceOffsets[celli] + nNbrs[celli];
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset the whole list to use as counter
|
|
||||||
nNbrs = 0;
|
|
||||||
|
|
||||||
forAll(upperAddr, facei)
|
|
||||||
{
|
|
||||||
cellFaces
|
|
||||||
[
|
|
||||||
cellFaceOffsets[upperAddr[facei]] + nNbrs[upperAddr[facei]]
|
|
||||||
] = facei;
|
|
||||||
|
|
||||||
nNbrs[upperAddr[facei]]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
forAll(lowerAddr, facei)
|
|
||||||
{
|
|
||||||
cellFaces
|
|
||||||
[
|
|
||||||
cellFaceOffsets[lowerAddr[facei]] + nNbrs[lowerAddr[facei]]
|
|
||||||
] = facei;
|
|
||||||
|
|
||||||
nNbrs[lowerAddr[facei]]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// go through the faces and create clusters
|
|
||||||
|
|
||||||
tmp<labelField> tcoarseCellMap(new labelField(nFineCells, -1));
|
|
||||||
labelField& coarseCellMap = tcoarseCellMap();
|
|
||||||
|
|
||||||
nCoarseCells = 0;
|
|
||||||
|
|
||||||
for (label celli=0; celli<nFineCells; celli++)
|
|
||||||
{
|
|
||||||
if (coarseCellMap[celli] < 0)
|
|
||||||
{
|
|
||||||
label matchFaceNo = -1;
|
|
||||||
scalar maxFaceWeight = -GREAT;
|
|
||||||
|
|
||||||
// check faces to find ungrouped neighbour with largest face weight
|
|
||||||
for
|
|
||||||
(
|
|
||||||
label faceOs=cellFaceOffsets[celli];
|
|
||||||
faceOs<cellFaceOffsets[celli+1];
|
|
||||||
faceOs++
|
|
||||||
)
|
|
||||||
{
|
|
||||||
label facei = cellFaces[faceOs];
|
|
||||||
|
|
||||||
// I don't know whether the current cell is owner or neighbour.
|
|
||||||
// Therefore I'll check both sides
|
|
||||||
if
|
|
||||||
(
|
|
||||||
coarseCellMap[upperAddr[facei]] < 0
|
|
||||||
&& coarseCellMap[lowerAddr[facei]] < 0
|
|
||||||
&& faceWeights[facei] > maxFaceWeight
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Match found. Pick up all the necessary data
|
|
||||||
matchFaceNo = facei;
|
|
||||||
maxFaceWeight = faceWeights[facei];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matchFaceNo >= 0)
|
|
||||||
{
|
|
||||||
// Make a new group
|
|
||||||
coarseCellMap[upperAddr[matchFaceNo]] = nCoarseCells;
|
|
||||||
coarseCellMap[lowerAddr[matchFaceNo]] = nCoarseCells;
|
|
||||||
nCoarseCells++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// No match. Find the best neighbouring cluster and
|
|
||||||
// put the cell there
|
|
||||||
label clusterMatchFaceNo = -1;
|
|
||||||
scalar clusterMaxFaceCoeff = -GREAT;
|
|
||||||
|
|
||||||
for
|
|
||||||
(
|
|
||||||
label faceOs=cellFaceOffsets[celli];
|
|
||||||
faceOs<cellFaceOffsets[celli+1];
|
|
||||||
faceOs++
|
|
||||||
)
|
|
||||||
{
|
|
||||||
label facei = cellFaces[faceOs];
|
|
||||||
|
|
||||||
if (faceWeights[facei] > clusterMaxFaceCoeff)
|
|
||||||
{
|
|
||||||
clusterMatchFaceNo = facei;
|
|
||||||
clusterMaxFaceCoeff = faceWeights[facei];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clusterMatchFaceNo >= 0)
|
|
||||||
{
|
|
||||||
// Add the cell to the best cluster
|
|
||||||
coarseCellMap[celli] = max
|
|
||||||
(
|
|
||||||
coarseCellMap[upperAddr[clusterMatchFaceNo]],
|
|
||||||
coarseCellMap[lowerAddr[clusterMatchFaceNo]]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Check that all cells are part of clusters,
|
|
||||||
// if not create single-cell "clusters" for each
|
|
||||||
for (label celli=0; celli<nFineCells; celli++)
|
|
||||||
{
|
|
||||||
if (coarseCellMap[celli] < 0)
|
|
||||||
{
|
|
||||||
coarseCellMap[celli] = nCoarseCells;
|
|
||||||
nCoarseCells++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reverse the map ordering to improve the next level of agglomeration
|
|
||||||
// (doesn't always help and is sometimes detrimental)
|
|
||||||
nCoarseCells--;
|
|
||||||
|
|
||||||
forAll(coarseCellMap, celli)
|
|
||||||
{
|
|
||||||
coarseCellMap[celli] = nCoarseCells - coarseCellMap[celli];
|
|
||||||
}
|
|
||||||
|
|
||||||
nCoarseCells++;
|
|
||||||
|
|
||||||
return tcoarseCellMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Foam::pairGAMGAgglomeration::agglomerate
|
void Foam::pairGAMGAgglomeration::agglomerate
|
||||||
(
|
(
|
||||||
@ -285,4 +115,187 @@ void Foam::pairGAMGAgglomeration::agglomerate
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::tmp<Foam::labelField> Foam::pairGAMGAgglomeration::agglomerate
|
||||||
|
(
|
||||||
|
label& nCoarseCells,
|
||||||
|
const lduAddressing& fineMatrixAddressing,
|
||||||
|
const scalarField& faceWeights
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const label nFineCells = fineMatrixAddressing.size();
|
||||||
|
|
||||||
|
const labelUList& upperAddr = fineMatrixAddressing.upperAddr();
|
||||||
|
const labelUList& lowerAddr = fineMatrixAddressing.lowerAddr();
|
||||||
|
|
||||||
|
// For each cell calculate faces
|
||||||
|
labelList cellFaces(upperAddr.size() + lowerAddr.size());
|
||||||
|
labelList cellFaceOffsets(nFineCells + 1);
|
||||||
|
|
||||||
|
// memory management
|
||||||
|
{
|
||||||
|
labelList nNbrs(nFineCells, 0);
|
||||||
|
|
||||||
|
forAll(upperAddr, facei)
|
||||||
|
{
|
||||||
|
nNbrs[upperAddr[facei]]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
forAll(lowerAddr, facei)
|
||||||
|
{
|
||||||
|
nNbrs[lowerAddr[facei]]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
cellFaceOffsets[0] = 0;
|
||||||
|
forAll(nNbrs, celli)
|
||||||
|
{
|
||||||
|
cellFaceOffsets[celli+1] = cellFaceOffsets[celli] + nNbrs[celli];
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset the whole list to use as counter
|
||||||
|
nNbrs = 0;
|
||||||
|
|
||||||
|
forAll(upperAddr, facei)
|
||||||
|
{
|
||||||
|
cellFaces
|
||||||
|
[
|
||||||
|
cellFaceOffsets[upperAddr[facei]] + nNbrs[upperAddr[facei]]
|
||||||
|
] = facei;
|
||||||
|
|
||||||
|
nNbrs[upperAddr[facei]]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
forAll(lowerAddr, facei)
|
||||||
|
{
|
||||||
|
cellFaces
|
||||||
|
[
|
||||||
|
cellFaceOffsets[lowerAddr[facei]] + nNbrs[lowerAddr[facei]]
|
||||||
|
] = facei;
|
||||||
|
|
||||||
|
nNbrs[lowerAddr[facei]]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// go through the faces and create clusters
|
||||||
|
|
||||||
|
tmp<labelField> tcoarseCellMap(new labelField(nFineCells, -1));
|
||||||
|
labelField& coarseCellMap = tcoarseCellMap();
|
||||||
|
|
||||||
|
nCoarseCells = 0;
|
||||||
|
label celli;
|
||||||
|
|
||||||
|
for (label cellfi=0; cellfi<nFineCells; cellfi++)
|
||||||
|
{
|
||||||
|
// Change cell ordering depending on direction for this level
|
||||||
|
celli = forward_ ? cellfi : nFineCells - cellfi - 1;
|
||||||
|
|
||||||
|
if (coarseCellMap[celli] < 0)
|
||||||
|
{
|
||||||
|
label matchFaceNo = -1;
|
||||||
|
scalar maxFaceWeight = -GREAT;
|
||||||
|
|
||||||
|
// check faces to find ungrouped neighbour with largest face weight
|
||||||
|
for
|
||||||
|
(
|
||||||
|
label faceOs=cellFaceOffsets[celli];
|
||||||
|
faceOs<cellFaceOffsets[celli+1];
|
||||||
|
faceOs++
|
||||||
|
)
|
||||||
|
{
|
||||||
|
label facei = cellFaces[faceOs];
|
||||||
|
|
||||||
|
// I don't know whether the current cell is owner or neighbour.
|
||||||
|
// Therefore I'll check both sides
|
||||||
|
if
|
||||||
|
(
|
||||||
|
coarseCellMap[upperAddr[facei]] < 0
|
||||||
|
&& coarseCellMap[lowerAddr[facei]] < 0
|
||||||
|
&& faceWeights[facei] > maxFaceWeight
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Match found. Pick up all the necessary data
|
||||||
|
matchFaceNo = facei;
|
||||||
|
maxFaceWeight = faceWeights[facei];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matchFaceNo >= 0)
|
||||||
|
{
|
||||||
|
// Make a new group
|
||||||
|
coarseCellMap[upperAddr[matchFaceNo]] = nCoarseCells;
|
||||||
|
coarseCellMap[lowerAddr[matchFaceNo]] = nCoarseCells;
|
||||||
|
nCoarseCells++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No match. Find the best neighbouring cluster and
|
||||||
|
// put the cell there
|
||||||
|
label clusterMatchFaceNo = -1;
|
||||||
|
scalar clusterMaxFaceCoeff = -GREAT;
|
||||||
|
|
||||||
|
for
|
||||||
|
(
|
||||||
|
label faceOs=cellFaceOffsets[celli];
|
||||||
|
faceOs<cellFaceOffsets[celli+1];
|
||||||
|
faceOs++
|
||||||
|
)
|
||||||
|
{
|
||||||
|
label facei = cellFaces[faceOs];
|
||||||
|
|
||||||
|
if (faceWeights[facei] > clusterMaxFaceCoeff)
|
||||||
|
{
|
||||||
|
clusterMatchFaceNo = facei;
|
||||||
|
clusterMaxFaceCoeff = faceWeights[facei];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clusterMatchFaceNo >= 0)
|
||||||
|
{
|
||||||
|
// Add the cell to the best cluster
|
||||||
|
coarseCellMap[celli] = max
|
||||||
|
(
|
||||||
|
coarseCellMap[upperAddr[clusterMatchFaceNo]],
|
||||||
|
coarseCellMap[lowerAddr[clusterMatchFaceNo]]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that all cells are part of clusters,
|
||||||
|
// if not create single-cell "clusters" for each
|
||||||
|
for (label cellfi=0; cellfi<nFineCells; cellfi++)
|
||||||
|
{
|
||||||
|
// Change cell ordering depending on direction for this level
|
||||||
|
celli = forward_ ? cellfi : nFineCells - cellfi - 1;
|
||||||
|
|
||||||
|
if (coarseCellMap[celli] < 0)
|
||||||
|
{
|
||||||
|
coarseCellMap[celli] = nCoarseCells;
|
||||||
|
nCoarseCells++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!forward_)
|
||||||
|
{
|
||||||
|
nCoarseCells--;
|
||||||
|
|
||||||
|
forAll(coarseCellMap, celli)
|
||||||
|
{
|
||||||
|
coarseCellMap[celli] = nCoarseCells - coarseCellMap[celli];
|
||||||
|
}
|
||||||
|
|
||||||
|
nCoarseCells++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reverse the map ordering for the next level
|
||||||
|
// to improve the next level of agglomeration
|
||||||
|
forward_ = !forward_;
|
||||||
|
|
||||||
|
return tcoarseCellMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
========= |
|
========= |
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
\\ / O peration |
|
\\ / O peration |
|
||||||
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
|
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -29,7 +29,8 @@ License
|
|||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
defineTypeNameAndDebug(pairGAMGAgglomeration, 0);
|
defineTypeNameAndDebug(pairGAMGAgglomeration, 0);
|
||||||
|
bool pairGAMGAgglomeration::forward_(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -56,6 +56,9 @@ class pairGAMGAgglomeration
|
|||||||
//- Number of levels to merge, 1 = don't merge, 2 = merge pairs etc.
|
//- Number of levels to merge, 1 = don't merge, 2 = merge pairs etc.
|
||||||
label mergeLevels_;
|
label mergeLevels_;
|
||||||
|
|
||||||
|
//- Direction of cell loop for the current level
|
||||||
|
static bool forward_;
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@ -97,7 +100,6 @@ public:
|
|||||||
const lduAddressing& fineMatrixAddressing,
|
const lduAddressing& fineMatrixAddressing,
|
||||||
const scalarField& faceWeights
|
const scalarField& faceWeights
|
||||||
);
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user