BUG: blockMesh mergePatchPairs fails with edge-shared points (fixes #2589)

- remedy by performing the attach() action sequentially (as per
  stitchMesh changes). This ensures that the current point addressing
  is always used and avoids references to the already-merged points
  (which is what causes the failure).

ENH: improve handling of empty patch removal

- only remove empty *merged* patches, but leave any other empty
  patches untouched since they may intentional placeholders for other
  parts of a workflow.

- remove any empty point/face zones created for patch merging
This commit is contained in:
Mark Olesen 2022-09-23 10:01:39 +02:00
parent 9fa37ba068
commit 56e9f7bf4b
6 changed files with 371 additions and 39 deletions

View File

@ -1,30 +1,56 @@
// Handle merging of patch pairs
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2009 OpenFOAM Foundation
Copyright (C) 2017-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
Description
Handle merging of patch pairs
\*---------------------------------------------------------------------------*/
{
wordPairList mergePatchPairs;
// Read in a list of dictionaries for the merge patch pairs
// Read in a list of merge patch pairs
if
(
meshDict.readIfPresent("mergePatchPairs", mergePatchPairs)
&& mergePatchPairs.size()
)
{
Info<< "Creating merge patch pairs" << nl << endl;
Info<< "Merging " << mergePatchPairs.size() << " patch pairs" << nl;
Info<< "Adding point and face zones" << endl;
// Cleanup
wordHashSet cleanupPatches(4*mergePatchPairs.size());
wordHashSet cleanupPointZones(2*mergePatchPairs.size());
wordHashSet cleanupFaceZones(2*mergePatchPairs.size());
Info<< " Adding point and face zones" << endl;
{
auto& pzs = mesh.pointZones();
pzs.clearAddressing();
auto& fzs = mesh.faceZones();
fzs.clearAddressing();
const auto& pbm = mesh.boundaryMesh();
auto& pzs = mesh.pointZones(); pzs.clearAddressing();
auto& fzs = mesh.faceZones(); fzs.clearAddressing();
forAll(mergePatchPairs, pairi)
{
// Patch pairs
const polyPatch& patch0 = pbm[mergePatchPairs[pairi].first()];
const polyPatch& patch1 = pbm[mergePatchPairs[pairi].second()];
const word mergeName
(
mergePatchPairs[pairi].first()
+ mergePatchPairs[pairi].second()
+ name(pairi)
+ Foam::name(pairi)
);
// An empty zone for cut points
@ -37,40 +63,35 @@
pzs
)
);
cleanupPointZones.insert(pzs.last().name());
// Master patch
const word masterPatchName(mergePatchPairs[pairi].first());
const polyPatch& masterPatch =
mesh.boundaryMesh()[masterPatchName];
// Coupling side 0 (master)
fzs.append
(
new faceZone
(
mergeName + "MasterZone",
identity(masterPatch.range()),
mergeName + "Side0Zone",
identity(patch0.range()),
false, // none are flipped
fzs.size(),
fzs
)
);
cleanupFaceZones.insert(fzs.last().name());
// Slave patch
const word slavePatchName(mergePatchPairs[pairi].second());
const polyPatch& slavePatch =
mesh.boundaryMesh()[slavePatchName];
// Coupling side 1 (slave)
fzs.append
(
new faceZone
(
mergeName + "SlaveZone",
identity(slavePatch.range()),
mergeName + "Side1Zone",
identity(patch1.range()),
false, // none are flipped
fzs.size(),
fzs
)
);
cleanupFaceZones.insert(fzs.last().name());
// An empty zone for cut faces
fzs.append
@ -82,35 +103,38 @@
fzs
)
);
} // end of all merge pairs
cleanupFaceZones.insert(fzs.last().name());
}
}
Info<< "Creating attachPolyTopoChanger" << endl;
Info<< " Merging with attachPolyTopoChanger" << endl;
attachPolyTopoChanger polyMeshAttacher(mesh);
polyMeshAttacher.setSize(mergePatchPairs.size());
polyMeshAttacher.resize(1);
forAll(mergePatchPairs, pairi)
{
cleanupPatches.insert(mergePatchPairs[pairi].first());
cleanupPatches.insert(mergePatchPairs[pairi].second());
const word mergeName
(
mergePatchPairs[pairi].first()
+ mergePatchPairs[pairi].second()
+ name(pairi)
+ Foam::name(pairi)
);
// Add the sliding interface mesh modifier
polyMeshAttacher.set
(
pairi,
0,
new slidingInterface
(
"couple" + name(pairi),
"couple" + Foam::name(pairi),
pairi,
polyMeshAttacher,
mergeName + "MasterZone",
mergeName + "SlaveZone",
mergeName + "Side0Zone",
mergeName + "Side1Zone",
mergeName + "CutPointZone",
mergeName + "CutFaceZone",
mergePatchPairs[pairi].first(),
@ -120,12 +144,135 @@
intersection::VISIBLE
)
);
polyMeshAttacher.attach(false); // Do not yet remove empty patches
}
polyMeshAttacher.attach(true);
// Re-do the boundary patches, removing empty merge patches
// but keeping any other empty patches
{
const polyBoundaryMesh& oldPatches = mesh.boundaryMesh();
polyPatchList newPatches(oldPatches.size());
label nNewPatches = 0;
wordHashSet removedPatches(cleanupPatches.capacity());
forAll(oldPatches, patchi)
{
const word& patchName = oldPatches[patchi].name();
if
(
!cleanupPatches.found(patchName)
|| returnReduceOr(oldPatches[patchi].size())
)
{
newPatches.set
(
nNewPatches,
oldPatches[patchi].clone
(
mesh.boundaryMesh(),
nNewPatches,
oldPatches[patchi].size(),
oldPatches[patchi].start()
)
);
++nNewPatches;
}
else
{
removedPatches.insert(patchName);
}
}
newPatches.resize(nNewPatches);
mesh.removeBoundary();
mesh.addPatches(newPatches);
Info<< "Removed " << removedPatches.size()
<< " empty merged patches:" << nl
<< " " << flatOutput(removedPatches.sortedToc()) << endl;
}
// Cleanup empty merged point zones
{
PtrList<pointZone>& zones = mesh.pointZones();
mesh.pointZones().clearAddressing();
wordHashSet removedZones(2*zones.size());
label nZones = 0;
forAll(zones, zonei)
{
if
(
!cleanupPointZones.found(zones[zonei].name())
|| returnReduceOr(zones[zonei].size())
)
{
zones.set(nZones, zones.release(zonei));
zones[nZones].index() = nZones; // re-index
++nZones;
}
else
{
removedZones.insert(zones[zonei].name());
}
}
zones.resize(nZones);
if (removedZones.size())
{
Info<< "Removed " << removedZones.size()
<< " empty point zones:" << nl
<< " " << flatOutput(removedZones.sortedToc()) << endl;
}
}
// Cleanup empty merged face zones
{
PtrList<faceZone>& zones = mesh.faceZones();
mesh.faceZones().clearAddressing();
wordHashSet removedZones(2*zones.size());
label nZones = 0;
forAll(zones, zonei)
{
if
(
!cleanupFaceZones.found(zones[zonei].name())
|| returnReduceOr(zones[zonei].size())
)
{
zones.set(nZones, zones.release(zonei));
zones[nZones].index() = nZones; // re-index
++nZones;
}
else
{
removedZones.insert(zones[zonei].name());
}
}
zones.resize(nZones);
if (removedZones.size())
{
Info<< "Removed " << removedZones.size()
<< " empty merged face zones:" << nl
<< " " << flatOutput(removedZones.sortedToc()) << endl;
}
}
}
else
{
Info<< nl << "There are no merge patch pairs" << endl;
Info<< "No patch pairs to merge" << endl;
}
}
// ************************************************************************* //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2017-2020 OpenCFD Ltd.
Copyright (C) 2017-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -564,7 +564,7 @@ int main(int argc, char *argv[])
mesh.faceZones()
(
mergePatchName + "MasterZone",
mergePatchName + "Side0Zone",
true // verbose
).resetAddressing(std::move(faceIds), false);
@ -574,7 +574,7 @@ int main(int argc, char *argv[])
mesh.faceZones()
(
mergePatchName + "SlaveZone",
mergePatchName + "Side1Zone",
true // verbose
).resetAddressing(std::move(faceIds), false);
@ -595,8 +595,8 @@ int main(int argc, char *argv[])
"couple" + Foam::name(actioni),
0,
stitcher,
mergePatchName + "MasterZone",
mergePatchName + "SlaveZone",
mergePatchName + "Side0Zone",
mergePatchName + "Side1Zone",
mergePatchName + "CutPointZone",
cutZoneName,
masterPatchName,

View File

@ -0,0 +1,10 @@
#!/bin/sh
cd "${0%/*}" || exit # Run from this directory
. ${WM_PROJECT_DIR:?}/bin/tools/CleanFunctions # Tutorial clean functions
#------------------------------------------------------------------------------
cleanCase0
rm -rf constant
#------------------------------------------------------------------------------

View File

@ -0,0 +1,8 @@
#!/bin/sh
cd "${0%/*}" || exit # Run from this directory
. ${WM_PROJECT_DIR:?}/bin/tools/RunFunctions # Tutorial run functions
#------------------------------------------------------------------------------
runApplication blockMesh
#------------------------------------------------------------------------------

View File

@ -0,0 +1,119 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v2212 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object blockMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
scale 0.001;
vertices
(
// Block d
( 50 -17 -12.5)
(100 -17 -12.5)
(100 -2 -12.5)
( 50 -2 -12.5)
( 50 -17 12.5)
(100 -17 12.5)
(100 -2 12.5)
( 50 -2 12.5)
// Block e
( 0 -17 -12.5)
( 50 -17 -12.5)
( 50 -2 -12.5)
( 0 -2 -12.5)
( 0 -17 12.5)
( 50 -17 12.5)
( 50 -2 12.5)
( 0 -2 12.5)
// Block f
( 0 -19 -12.5)
( 50 -19 -12.5)
( 50 -17 -12.5)
( 0 -17 -12.5)
( 0 -19 12.5)
( 50 -19 12.5)
( 50 -17 12.5)
( 0 -17 12.5)
);
blocks
(
// Block d
hex (0 1 2 3 4 5 6 7) block-d (4 5 4) grading (1 1 1)
// Block e
hex (8 9 10 11 12 13 14 15) block-e (4 4 4) grading (1 1 1)
// Block f
hex (16 17 18 19 20 21 22 23) block-f (5 4 4) grading (1 1 1)
);
edges
(
);
boundary
(
mid6
{
type patch;
faces
(
(0 0) // Block d
);
}
mid7
{
type patch;
faces
(
(1 1) // Block e
);
}
mid8
{
type patch;
faces
(
(1 2) // Block e
);
}
mid9
{
type patch;
faces
(
(2 3) // Block e
);
}
other
{
type patch;
faces ();
}
);
mergePatchPairs
(
(mid6 mid7)
(mid8 mid9)
);
// ************************************************************************* //

View File

@ -0,0 +1,48 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v2206 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object controlDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
application blockMesh;
startFrom startTime;
startTime 0;
stopAt endTime;
endTime 0;
deltaT 0;
writeControl timeStep;
writeInterval 1;
purgeWrite 0;
writeFormat ascii;
writePrecision 6;
writeCompression off;
timeFormat general;
timePrecision 6;
runTimeModifiable true;
// ************************************************************************* //