ENH: faceAgglomerate: more robust. Fixes #2741
- feature angle compared to real angle - stop agglomerating if number of marked edges does not change
This commit is contained in:
parent
5de59417f8
commit
d51967d728
@ -1,4 +1,5 @@
|
|||||||
EXE_INC = \
|
EXE_INC = \
|
||||||
|
-I$(LIB_SRC)/fileFormats/lnInclude \
|
||||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
-I$(LIB_SRC)/meshTools/lnInclude
|
-I$(LIB_SRC)/meshTools/lnInclude
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||||
Copyright (C) 2016-2022 OpenCFD Ltd.
|
Copyright (C) 2016-2023 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -30,6 +30,15 @@ License
|
|||||||
#include "meshTools.H"
|
#include "meshTools.H"
|
||||||
#include "edgeHashes.H"
|
#include "edgeHashes.H"
|
||||||
#include "unitConversion.H"
|
#include "unitConversion.H"
|
||||||
|
#include "OBJstream.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
defineTypeNameAndDebug(pairPatchAgglomeration, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -44,7 +53,8 @@ void Foam::pairPatchAgglomeration::compactLevels(const label nCreatedLevels)
|
|||||||
bool Foam::pairPatchAgglomeration::continueAgglomerating
|
bool Foam::pairPatchAgglomeration::continueAgglomerating
|
||||||
(
|
(
|
||||||
const label nLocal,
|
const label nLocal,
|
||||||
const label nLocalOld
|
const label nLocalOld,
|
||||||
|
const label nMarkedEdges
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Keep agglomerating
|
// Keep agglomerating
|
||||||
@ -54,65 +64,80 @@ bool Foam::pairPatchAgglomeration::continueAgglomerating
|
|||||||
|
|
||||||
label nGlobal = returnReduce(nLocal, sumOp<label>());
|
label nGlobal = returnReduce(nLocal, sumOp<label>());
|
||||||
label nGlobalOld = returnReduce(nLocalOld, sumOp<label>());
|
label nGlobalOld = returnReduce(nLocalOld, sumOp<label>());
|
||||||
|
label nGlobalMarked = returnReduce(nMarkedEdges, sumOp<label>());
|
||||||
|
|
||||||
return
|
return
|
||||||
(
|
(
|
||||||
returnReduceOr(nLocal > nFacesInCoarsestLevel_)
|
returnReduceOr(nLocal > nFacesInCoarsestLevel_)
|
||||||
|| nGlobal > nGlobalFacesInCoarsestLevel_
|
|| nGlobal > nGlobalFacesInCoarsestLevel_
|
||||||
)
|
)
|
||||||
&& nGlobal != nGlobalOld;
|
&& (nGlobal != nGlobalOld || nGlobalMarked > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::pairPatchAgglomeration::setLevel0EdgeWeights()
|
void Foam::pairPatchAgglomeration::setLevel0EdgeWeights()
|
||||||
{
|
{
|
||||||
const bPatch& coarsePatch = patchLevels_[0];
|
const bPatch& coarsePatch = patchLevels_[0];
|
||||||
forAll(coarsePatch.edges(), i)
|
const auto& coarseEdges = coarsePatch.edges();
|
||||||
|
|
||||||
|
// Statistics on edges
|
||||||
|
label nNonManif = 0;
|
||||||
|
label nFeat = 0;
|
||||||
|
|
||||||
|
for (label i = 0; i < coarsePatch.nInternalEdges(); i++)
|
||||||
{
|
{
|
||||||
if (coarsePatch.isInternalEdge(i))
|
scalar edgeLength = coarseEdges[i].mag(coarsePatch.localPoints());
|
||||||
|
|
||||||
|
const labelList& eFaces = coarsePatch.edgeFaces()[i];
|
||||||
|
|
||||||
|
if (eFaces.size() == 2)
|
||||||
{
|
{
|
||||||
scalar edgeLength =
|
scalar cosI =
|
||||||
coarsePatch.edges()[i].mag(coarsePatch.localPoints());
|
coarsePatch.faceNormals()[eFaces[0]]
|
||||||
|
& coarsePatch.faceNormals()[eFaces[1]];
|
||||||
|
|
||||||
const labelList& eFaces = coarsePatch.edgeFaces()[i];
|
const edge edgeCommon = edge(eFaces[0], eFaces[1]);
|
||||||
|
|
||||||
if (eFaces.size() == 2)
|
if (facePairWeight_.found(edgeCommon))
|
||||||
{
|
{
|
||||||
scalar cosI =
|
facePairWeight_[edgeCommon] += edgeLength;
|
||||||
coarsePatch.faceNormals()[eFaces[0]]
|
|
||||||
& coarsePatch.faceNormals()[eFaces[1]];
|
|
||||||
|
|
||||||
const edge edgeCommon = edge(eFaces[0], eFaces[1]);
|
|
||||||
|
|
||||||
if (facePairWeight_.found(edgeCommon))
|
|
||||||
{
|
|
||||||
facePairWeight_[edgeCommon] += edgeLength;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
facePairWeight_.insert(edgeCommon, edgeLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mag(cosI) < Foam::cos(degToRad(featureAngle_)))
|
|
||||||
{
|
|
||||||
facePairWeight_[edgeCommon] = -1.0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
forAll(eFaces, j)
|
facePairWeight_.insert(edgeCommon, edgeLength);
|
||||||
{
|
}
|
||||||
for (label k = j+1; k<eFaces.size(); k++)
|
|
||||||
{
|
if (cosI < Foam::cos(degToRad(featureAngle_)))
|
||||||
facePairWeight_.insert
|
{
|
||||||
(
|
facePairWeight_[edgeCommon] = -1.0;
|
||||||
edge(eFaces[j], eFaces[k]),
|
nFeat++;
|
||||||
-1.0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
forAll(eFaces, j)
|
||||||
|
{
|
||||||
|
for (label k = j+1; k<eFaces.size(); k++)
|
||||||
|
{
|
||||||
|
facePairWeight_.insert
|
||||||
|
(
|
||||||
|
edge(eFaces[j], eFaces[k]),
|
||||||
|
-1.0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nNonManif++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Pout<< "Level:" << 0
|
||||||
|
<< " nEdges:" << coarsePatch.nEdges() << " of which:" << nl
|
||||||
|
<< " boundary:" << coarsePatch.nBoundaryEdges() << nl
|
||||||
|
<< " non-manifold:" << nNonManif << nl
|
||||||
|
<< " feature (angle < " << featureAngle_ << "):" << nFeat << nl
|
||||||
|
<< endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,9 +148,8 @@ void Foam::pairPatchAgglomeration::setEdgeWeights
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
const bPatch& coarsePatch = patchLevels_[fineLevelIndex];
|
const bPatch& coarsePatch = patchLevels_[fineLevelIndex];
|
||||||
|
const auto& coarseEdges = coarsePatch.edges();
|
||||||
const labelList& fineToCoarse = restrictAddressing_[fineLevelIndex];
|
const labelList& fineToCoarse = restrictAddressing_[fineLevelIndex];
|
||||||
const label nCoarseI = max(fineToCoarse) + 1;
|
|
||||||
labelListList coarseToFine(invertOneToMany(nCoarseI, fineToCoarse));
|
|
||||||
|
|
||||||
edgeHashSet fineFeaturedFaces(coarsePatch.nEdges()/10);
|
edgeHashSet fineFeaturedFaces(coarsePatch.nEdges()/10);
|
||||||
|
|
||||||
@ -144,54 +168,173 @@ void Foam::pairPatchAgglomeration::setEdgeWeights
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Statistics on edges
|
||||||
|
label nNonManif = 0;
|
||||||
|
label nFeat = 0;
|
||||||
|
|
||||||
// Clean old weights
|
// Clean old weights
|
||||||
facePairWeight_.clear();
|
facePairWeight_.clear();
|
||||||
facePairWeight_.resize(coarsePatch.nEdges());
|
facePairWeight_.resize(coarsePatch.nEdges());
|
||||||
|
|
||||||
forAll(coarsePatch.edges(), i)
|
for (label i = 0; i < coarsePatch.nInternalEdges(); i++)
|
||||||
{
|
{
|
||||||
if (coarsePatch.isInternalEdge(i))
|
scalar edgeLength = coarseEdges[i].mag(coarsePatch.localPoints());
|
||||||
|
|
||||||
|
const labelList& eFaces = coarsePatch.edgeFaces()[i];
|
||||||
|
|
||||||
|
if (eFaces.size() == 2)
|
||||||
{
|
{
|
||||||
scalar edgeLength =
|
const edge edgeCommon(eFaces[0], eFaces[1]);
|
||||||
coarsePatch.edges()[i].mag(coarsePatch.localPoints());
|
// If the fine 'pair' faces was featured edge so it is
|
||||||
|
// the coarse 'pair'
|
||||||
const labelList& eFaces = coarsePatch.edgeFaces()[i];
|
if (fineFeaturedFaces.found(edgeCommon))
|
||||||
|
|
||||||
if (eFaces.size() == 2)
|
|
||||||
{
|
{
|
||||||
const edge edgeCommon = edge(eFaces[0], eFaces[1]);
|
auto w = facePairWeight_.find(edgeCommon);
|
||||||
if (facePairWeight_.found(edgeCommon))
|
if (!w.good())
|
||||||
{
|
{
|
||||||
facePairWeight_[edgeCommon] += edgeLength;
|
facePairWeight_.insert(edgeCommon, -1.0);
|
||||||
|
nFeat++;
|
||||||
|
}
|
||||||
|
else if (w() != -1.0)
|
||||||
|
{
|
||||||
|
// Mark as feature edge
|
||||||
|
w() = -1.0;
|
||||||
|
nFeat++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto w = facePairWeight_.find(edgeCommon);
|
||||||
|
if (w)
|
||||||
|
{
|
||||||
|
if (w() != -1.0)
|
||||||
|
{
|
||||||
|
w() += edgeLength;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
facePairWeight_.insert(edgeCommon, edgeLength);
|
facePairWeight_.insert(edgeCommon, edgeLength);
|
||||||
}
|
}
|
||||||
// If the fine 'pair' faces was featured edge so it is
|
}
|
||||||
// the coarse 'pair'
|
}
|
||||||
if (fineFeaturedFaces.found(edgeCommon))
|
else
|
||||||
|
{
|
||||||
|
// Set edge as barrier by setting weight to -1
|
||||||
|
forAll(eFaces, j)
|
||||||
|
{
|
||||||
|
for (label k = j+1; k<eFaces.size(); k++)
|
||||||
{
|
{
|
||||||
facePairWeight_[edgeCommon] = -1.0;
|
facePairWeight_.insert
|
||||||
|
(
|
||||||
|
edge(eFaces[j], eFaces[k]),
|
||||||
|
-1.0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
nNonManif++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Pout<< "Level:" << fineLevelIndex
|
||||||
|
<< " nEdges:" << coarsePatch.nEdges() << " of which:" << nl
|
||||||
|
<< " boundary:" << coarsePatch.nBoundaryEdges() << nl
|
||||||
|
<< " non-manifold:" << nNonManif << nl
|
||||||
|
<< " feature (angle < " << featureAngle_ << "):" << nFeat << nl
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::pairPatchAgglomeration::isSingleEdgeLoop
|
||||||
|
(
|
||||||
|
const bPatch& patch,
|
||||||
|
const labelList& faceIDs,
|
||||||
|
const label facei
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
// Does combining facei with faceIDs produce a valid single face?
|
||||||
|
|
||||||
|
labelList allFaces(faceIDs.size()+1);
|
||||||
|
SubList<label>(allFaces, faceIDs.size()) = faceIDs;
|
||||||
|
allFaces.last() = facei;
|
||||||
|
|
||||||
|
// Construct single face
|
||||||
|
const indirectPrimitivePatch upp
|
||||||
|
(
|
||||||
|
IndirectList<face>(patch, allFaces),
|
||||||
|
patch.points()
|
||||||
|
);
|
||||||
|
|
||||||
|
return (upp.edgeLoops().size() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::label Foam::pairPatchAgglomeration::maxValidNeighbour
|
||||||
|
(
|
||||||
|
const bool addToCluster,
|
||||||
|
const bPatch& patch,
|
||||||
|
const label facei,
|
||||||
|
const labelList& fineToCoarse
|
||||||
|
//const labelListList& coarseToFine
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
// Return index of neighbour face with max edge weight. Either looks
|
||||||
|
// at clustered faces (addToCluster=true) or at unclustered faces
|
||||||
|
|
||||||
|
const auto& fFaces = patch.faceFaces()[facei];
|
||||||
|
|
||||||
|
label matchFaceNeibNo = -1;
|
||||||
|
scalar maxFaceWeight = -0.5; // negative but larger than -1 (= feature)
|
||||||
|
|
||||||
|
if (addToCluster)
|
||||||
|
{
|
||||||
|
// Check faces to find grouped neighbour with largest face weight
|
||||||
|
// and that forms a single edge cut
|
||||||
|
for (const label faceNeig : fFaces)
|
||||||
|
{
|
||||||
|
const label coarsei = fineToCoarse[faceNeig];
|
||||||
|
|
||||||
|
if (coarsei >= 0)
|
||||||
{
|
{
|
||||||
// Set edge as barrier by setting weight to -1
|
const edge edgeCommon = edge(facei, faceNeig);
|
||||||
forAll(eFaces, j)
|
const auto& weight = facePairWeight_[edgeCommon];
|
||||||
|
if
|
||||||
|
(
|
||||||
|
(weight > maxFaceWeight)
|
||||||
|
//&& (isSingleEdgeLoop(patch, coarseToFine[coarsei], facei))
|
||||||
|
)
|
||||||
{
|
{
|
||||||
for (label k = j+1; k<eFaces.size(); k++)
|
maxFaceWeight = weight;
|
||||||
{
|
matchFaceNeibNo = faceNeig;
|
||||||
facePairWeight_.insert
|
|
||||||
(
|
|
||||||
edge(eFaces[j], eFaces[k]),
|
|
||||||
-1.0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Check faces to find ungrouped neighbour with largest face weight
|
||||||
|
for (const label faceNeig : fFaces)
|
||||||
|
{
|
||||||
|
const label coarsei = fineToCoarse[faceNeig];
|
||||||
|
|
||||||
|
if (coarsei < 0) // ungrouped
|
||||||
|
{
|
||||||
|
const edge edgeCommon = edge(facei, faceNeig);
|
||||||
|
const auto& weight = facePairWeight_[edgeCommon];
|
||||||
|
if (weight > maxFaceWeight)
|
||||||
|
{
|
||||||
|
maxFaceWeight = weight;
|
||||||
|
matchFaceNeibNo = faceNeig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return matchFaceNeibNo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -307,7 +450,8 @@ bool Foam::pairPatchAgglomeration::agglomeratePatch
|
|||||||
(
|
(
|
||||||
const bPatch& patch,
|
const bPatch& patch,
|
||||||
const labelList& fineToCoarse,
|
const labelList& fineToCoarse,
|
||||||
const label fineLevelIndex
|
const label fineLevelIndex,
|
||||||
|
label& nMarkedEdges
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (min(fineToCoarse) == -1)
|
if (min(fineToCoarse) == -1)
|
||||||
@ -333,10 +477,13 @@ bool Foam::pairPatchAgglomeration::agglomeratePatch
|
|||||||
const label nCoarseI = max(fineToCoarse) + 1;
|
const label nCoarseI = max(fineToCoarse) + 1;
|
||||||
List<face> patchFaces(nCoarseI);
|
List<face> patchFaces(nCoarseI);
|
||||||
|
|
||||||
|
|
||||||
// Patch faces per agglomeration
|
// Patch faces per agglomeration
|
||||||
labelListList coarseToFine(invertOneToMany(nCoarseI, fineToCoarse));
|
labelListList coarseToFine(invertOneToMany(nCoarseI, fineToCoarse));
|
||||||
|
|
||||||
|
// Additional feature edges created
|
||||||
|
nMarkedEdges = 0;
|
||||||
|
|
||||||
|
|
||||||
for (label coarseI = 0; coarseI < nCoarseI; coarseI++)
|
for (label coarseI = 0; coarseI < nCoarseI; coarseI++)
|
||||||
{
|
{
|
||||||
const labelList& fineFaces = coarseToFine[coarseI];
|
const labelList& fineFaces = coarseToFine[coarseI];
|
||||||
@ -350,23 +497,54 @@ bool Foam::pairPatchAgglomeration::agglomeratePatch
|
|||||||
|
|
||||||
if (upp.edgeLoops().size() != 1)
|
if (upp.edgeLoops().size() != 1)
|
||||||
{
|
{
|
||||||
if (fineFaces.size() == 2)
|
// More than one outside loop. Possible because pair-wise
|
||||||
|
// agglomeration has e.g. walked a path leaving a hole in the
|
||||||
|
// middle of a coarse face.
|
||||||
|
// - mark as feature edges to avoid locally further agglomeration
|
||||||
|
// - but further agglomeration might e.g. 'fill in the hole'
|
||||||
|
// - or immediately leave all agglomeration
|
||||||
|
// Currently we have no choice but to leave agglomeration since
|
||||||
|
// we cannot store a face-with-hole.
|
||||||
|
|
||||||
|
|
||||||
|
//{
|
||||||
|
// OBJstream os
|
||||||
|
// (
|
||||||
|
// "error_agglomeration_"+Foam::name(fineLevelIndex)+".obj"
|
||||||
|
// );
|
||||||
|
// Pout<< "Writing error patch at level:" << fineLevelIndex
|
||||||
|
// << " to:" << os.name() << endl;
|
||||||
|
// os.write(upp.localFaces(), upp.localPoints(), true);
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (fineFaces.size() >= 2)
|
||||||
{
|
{
|
||||||
const edge e(fineFaces[0], fineFaces[1]);
|
forAll(fineFaces, j)
|
||||||
facePairWeight_[e] = -1.0;
|
{
|
||||||
}
|
for (label k = j+1; k<fineFaces.size(); k++)
|
||||||
else if (fineFaces.size() == 3)
|
{
|
||||||
{
|
const edge e(fineFaces[j], fineFaces[k]);
|
||||||
const edge e(fineFaces[0], fineFaces[1]);
|
|
||||||
const edge e1(fineFaces[0], fineFaces[2]);
|
auto w = facePairWeight_.find(e);
|
||||||
const edge e2(fineFaces[2], fineFaces[1]);
|
if (!w.good())
|
||||||
facePairWeight_[e] = -1.0;
|
{
|
||||||
facePairWeight_[e1] = -1.0;
|
facePairWeight_.insert(e, -1.0);
|
||||||
facePairWeight_[e2] = -1.0;
|
nMarkedEdges++;
|
||||||
|
}
|
||||||
|
else if (w() != -1.0)
|
||||||
|
{
|
||||||
|
// Mark as feature edge
|
||||||
|
w() = -1.0;
|
||||||
|
nMarkedEdges++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In-place override face
|
||||||
patchFaces[coarseI] = face
|
patchFaces[coarseI] = face
|
||||||
(
|
(
|
||||||
renumber
|
renumber
|
||||||
@ -398,6 +576,7 @@ void Foam::pairPatchAgglomeration::agglomerate()
|
|||||||
|
|
||||||
label nCoarseFaces = 0;
|
label nCoarseFaces = 0;
|
||||||
label nCoarseFacesOld = 0;
|
label nCoarseFacesOld = 0;
|
||||||
|
label nMarkedEdges = 0;
|
||||||
|
|
||||||
while (nCreatedLevels < maxLevels_)
|
while (nCreatedLevels < maxLevels_)
|
||||||
{
|
{
|
||||||
@ -421,18 +600,28 @@ void Foam::pairPatchAgglomeration::agglomerate()
|
|||||||
{
|
{
|
||||||
// Attempt to create coarse face addressing
|
// Attempt to create coarse face addressing
|
||||||
// - returns true if successful; otherwise resets edge weights
|
// - returns true if successful; otherwise resets edge weights
|
||||||
// and assume try again...
|
// and tries again...
|
||||||
createdLevel = agglomeratePatch
|
createdLevel = agglomeratePatch
|
||||||
(
|
(
|
||||||
patch,
|
patch,
|
||||||
tfinalAgglom,
|
tfinalAgglom,
|
||||||
nCreatedLevels
|
nCreatedLevels,
|
||||||
|
nMarkedEdges
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (createdLevel)
|
if (createdLevel)
|
||||||
{
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
const auto& agglomPatch = patchLevels_[nCreatedLevels];
|
||||||
|
OBJstream os("agglomPatch"+Foam::name(nCreatedLevels)+".obj");
|
||||||
|
Pout<< "Writing new patch at level:" << nCreatedLevels
|
||||||
|
<< " to:" << os.name() << endl;
|
||||||
|
os.write(agglomPatch, agglomPatch.points(), true);
|
||||||
|
}
|
||||||
|
|
||||||
restrictAddressing_.set(nCreatedLevels, tfinalAgglom);
|
restrictAddressing_.set(nCreatedLevels, tfinalAgglom);
|
||||||
|
|
||||||
mapBaseToTopAgglom(nCreatedLevels);
|
mapBaseToTopAgglom(nCreatedLevels);
|
||||||
@ -455,7 +644,7 @@ void Foam::pairPatchAgglomeration::agglomerate()
|
|||||||
|
|
||||||
// Check to see if we need to continue agglomerating
|
// Check to see if we need to continue agglomerating
|
||||||
// - Note: performs parallel reductions
|
// - Note: performs parallel reductions
|
||||||
if (!continueAgglomerating(nCoarseFaces, nCoarseFacesOld))
|
if (!continueAgglomerating(nCoarseFaces, nCoarseFacesOld, nMarkedEdges))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -480,82 +669,64 @@ Foam::tmp<Foam::labelField> Foam::pairPatchAgglomeration::agglomerateOneLevel
|
|||||||
|
|
||||||
const labelListList& faceFaces = patch.faceFaces();
|
const labelListList& faceFaces = patch.faceFaces();
|
||||||
|
|
||||||
|
//labelListList coarseToFine(nFineFaces);
|
||||||
nCoarseFaces = 0;
|
nCoarseFaces = 0;
|
||||||
|
|
||||||
forAll(faceFaces, facei)
|
forAll(faceFaces, facei)
|
||||||
{
|
{
|
||||||
const labelList& fFaces = faceFaces[facei];
|
|
||||||
|
|
||||||
if (coarseCellMap[facei] < 0)
|
if (coarseCellMap[facei] < 0)
|
||||||
{
|
{
|
||||||
label matchFaceNo = -1;
|
const label matchFaceNeibNo = maxValidNeighbour
|
||||||
label matchFaceNeibNo = -1;
|
(
|
||||||
scalar maxFaceWeight = -GREAT;
|
false, // ungrouped neighbours only
|
||||||
|
patch,
|
||||||
|
facei,
|
||||||
|
coarseCellMap
|
||||||
|
//coarseToFine
|
||||||
|
);
|
||||||
|
|
||||||
// Check faces to find ungrouped neighbour with largest face weight
|
if (matchFaceNeibNo >= 0)
|
||||||
forAll(fFaces, i)
|
|
||||||
{
|
|
||||||
label faceNeig = fFaces[i];
|
|
||||||
const edge edgeCommon = edge(facei, faceNeig);
|
|
||||||
if
|
|
||||||
(
|
|
||||||
facePairWeight_[edgeCommon] > maxFaceWeight
|
|
||||||
&& coarseCellMap[faceNeig] < 0
|
|
||||||
&& facePairWeight_[edgeCommon] != -1.0
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Match found. Pick up all the necessary data
|
|
||||||
matchFaceNo = facei;
|
|
||||||
matchFaceNeibNo = faceNeig;
|
|
||||||
maxFaceWeight = facePairWeight_[edgeCommon];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matchFaceNo >= 0)
|
|
||||||
{
|
{
|
||||||
// Make a new group
|
// Make a new group
|
||||||
coarseCellMap[matchFaceNo] = nCoarseFaces;
|
coarseCellMap[facei] = nCoarseFaces;
|
||||||
coarseCellMap[matchFaceNeibNo] = nCoarseFaces;
|
coarseCellMap[matchFaceNeibNo] = nCoarseFaces;
|
||||||
|
//coarseToFine[nCoarseFaces] =
|
||||||
|
// labelList({facei, matchFaceNeibNo});
|
||||||
nCoarseFaces++;
|
nCoarseFaces++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// No match. Find the best neighbouring cluster and
|
// No match. Find the best neighbouring cluster and
|
||||||
// put the cell there
|
// put the cell there
|
||||||
label clusterMatchFaceNo = -1;
|
const label clusterMatchFaceNo = maxValidNeighbour
|
||||||
scalar clusterMaxFaceCoeff = -GREAT;
|
(
|
||||||
|
true, // grouped neighbours only
|
||||||
|
patch,
|
||||||
|
facei,
|
||||||
|
coarseCellMap
|
||||||
|
//coarseToFine
|
||||||
|
);
|
||||||
|
|
||||||
forAll(fFaces, i)
|
if (clusterMatchFaceNo >= 0)
|
||||||
{
|
|
||||||
label faceNeig = fFaces[i];
|
|
||||||
const edge edgeCommon = edge(facei, faceNeig);
|
|
||||||
if
|
|
||||||
(
|
|
||||||
facePairWeight_[edgeCommon] > clusterMaxFaceCoeff
|
|
||||||
&& facePairWeight_[edgeCommon] != -1.0
|
|
||||||
&& coarseCellMap[faceNeig] >= 0
|
|
||||||
)
|
|
||||||
{
|
|
||||||
clusterMatchFaceNo = faceNeig;
|
|
||||||
clusterMaxFaceCoeff = facePairWeight_[edgeCommon];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clusterMatchFaceNo > 0)
|
|
||||||
{
|
{
|
||||||
// Add the cell to the best cluster
|
// Add the cell to the best cluster
|
||||||
coarseCellMap[facei] = coarseCellMap[clusterMatchFaceNo];
|
const label coarsei = coarseCellMap[clusterMatchFaceNo];
|
||||||
|
coarseCellMap[facei] = coarsei;
|
||||||
|
//coarseToFine[coarsei].append(facei);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If not create single-cell "clusters" for each
|
// If not create single-cell "clusters" for each
|
||||||
coarseCellMap[facei] = nCoarseFaces;
|
coarseCellMap[facei] = nCoarseFaces;
|
||||||
|
//coarseToFine[nCoarseFaces] = labelList({facei});
|
||||||
nCoarseFaces++;
|
nCoarseFaces++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//coarseToFine.setSize(nCoarseFaces);
|
||||||
|
|
||||||
// Check that all faces are part of clusters,
|
// Check that all faces are part of clusters,
|
||||||
for (label facei=0; facei<nFineFaces; facei++)
|
for (label facei=0; facei<nFineFaces; facei++)
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||||
Copyright (C) 2016-2020 OpenCFD Ltd.
|
Copyright (C) 2016-2020,2023 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -101,9 +101,30 @@ private:
|
|||||||
(
|
(
|
||||||
const bPatch& patch,
|
const bPatch& patch,
|
||||||
const labelList& fineToCoarse,
|
const labelList& fineToCoarse,
|
||||||
const label fineLevelIndex
|
const label fineLevelIndex,
|
||||||
|
label& nMarkedEdges
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//- Does combining facei with faceIDs produce a single face?
|
||||||
|
bool isSingleEdgeLoop
|
||||||
|
(
|
||||||
|
const bPatch& patch,
|
||||||
|
const labelList& faceIDs,
|
||||||
|
const label facei
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Select neighbour with highest inbetween edge weight. Either looks
|
||||||
|
//- at already clustered faces (addToCluster=true) or only
|
||||||
|
// unclustered
|
||||||
|
label maxValidNeighbour
|
||||||
|
(
|
||||||
|
const bool addToCluster,
|
||||||
|
const bPatch& patch,
|
||||||
|
const label facei,
|
||||||
|
const labelList& coarseCellMap
|
||||||
|
//const labelListList& coarseToFine
|
||||||
|
) const;
|
||||||
|
|
||||||
//- Agglomerate one level
|
//- Agglomerate one level
|
||||||
tmp<labelField> agglomerateOneLevel
|
tmp<labelField> agglomerateOneLevel
|
||||||
(
|
(
|
||||||
@ -121,7 +142,8 @@ private:
|
|||||||
bool continueAgglomerating
|
bool continueAgglomerating
|
||||||
(
|
(
|
||||||
const label nLocal,
|
const label nLocal,
|
||||||
const label nLocalOld
|
const label nLocalOld,
|
||||||
|
const label nMarkedEdges
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Set edge weights
|
//- Set edge weights
|
||||||
@ -142,6 +164,10 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("pairPatch");
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
//- Construct given faces, points and control dictionary
|
//- Construct given faces, points and control dictionary
|
||||||
@ -166,7 +192,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
~pairPatchAgglomeration();
|
virtual ~pairPatchAgglomeration();
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
@ -14,9 +14,26 @@ FoamFile
|
|||||||
}
|
}
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
writeViewFactorMatrix true;
|
|
||||||
writePatchViewFactors false;
|
writeViewFactorMatrix true;
|
||||||
// dumpRays true;
|
writePatchViewFactors false;
|
||||||
|
|
||||||
|
// Write rays as lines to .obj file
|
||||||
|
//dumpRays true;
|
||||||
|
|
||||||
|
|
||||||
|
// Switch on debug for faceAgglomerate
|
||||||
|
//debug 1;
|
||||||
|
writeFacesAgglomeration true;
|
||||||
|
patchAgglomeration
|
||||||
|
{
|
||||||
|
// Do all of the view-factor patches
|
||||||
|
viewFactorWall
|
||||||
|
{
|
||||||
|
nFacesInCoarsestLevel 10;
|
||||||
|
featureAngle 45;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
maxDynListLength 200000;
|
maxDynListLength 200000;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user