ENH: surfaceMeshTriangulate: generalise for MeshedSurface instead of triSurface. Add patchSet. Add topological point merging

This commit is contained in:
mattijs
2012-05-30 11:42:37 +01:00
parent 9ec1e9d2c2
commit b06e2e6589

View File

@ -22,23 +22,29 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Description Description
Extracts triSurface from a polyMesh. Triangulates all boundary faces. Extracts surface from a polyMesh. Depending on output surface format
Region numbers on triangles are the patch numbers of the polyMesh. triangulates faces.
Region numbers on faces cannot be guaranteed to be the same as the patch
indices.
Optionally only triangulates named patches. Optionally only triangulates named patches.
If run in parallel the processor patches get filtered out by default and If run in parallel the processor patches get filtered out by default and
the mesh gets merged. (based on vertex position, not topology, so might go the mesh gets merged (based on topology).
wrong!).
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "MeshedSurface.H"
#include "UnsortedMeshedSurface.H"
#include "argList.H" #include "argList.H"
#include "Time.H" #include "Time.H"
#include "polyMesh.H" #include "polyMesh.H"
#include "triSurface.H"
#include "triSurfaceTools.H"
#include "processorPolyPatch.H" #include "processorPolyPatch.H"
#include "ListListOps.H" #include "ListListOps.H"
#include "uindirectPrimitivePatch.H"
#include "globalMeshData.H"
#include "globalIndex.H"
using namespace Foam; using namespace Foam;
@ -50,7 +56,7 @@ int main(int argc, char *argv[])
{ {
argList::addNote argList::addNote
( (
"extract surface from a polyMesh and triangulate boundary faces" "extract surface from a polyMesh"
); );
argList::validArgs.append("output file"); argList::validArgs.append("output file");
#include "addRegionOption.H" #include "addRegionOption.H"
@ -63,27 +69,37 @@ int main(int argc, char *argv[])
( (
"patches", "patches",
"(patch0 .. patchN)", "(patch0 .. patchN)",
"only triangulate named patches" "only triangulate selected patches (wildcards supported)"
); );
#include "setRootCase.H" #include "setRootCase.H"
#include "createTime.H" #include "createTime.H"
const fileName outFileName(runTime.path()/args[1]); const word outFileName(args[1]);
Info<< "Extracting triSurface from boundaryMesh ..." Info<< "Extracting surface from boundaryMesh ..."
<< endl << endl; << endl << endl;
Pout<< "Reading mesh from time " << runTime.value() << endl;
#include "createNamedPolyMesh.H"
const bool includeProcPatches = const bool includeProcPatches =
!( !(
args.optionFound("excludeProcPatches") args.optionFound("excludeProcPatches")
|| Pstream::parRun() || Pstream::parRun()
); );
if (includeProcPatches)
{
Info<< "Including all processor patches." << nl << endl;
}
else if (Pstream::parRun())
{
Info<< "Excluding all processor patches." << nl << endl;
}
Info<< "Reading mesh from time " << runTime.value() << endl;
#include "createNamedPolyMesh.H"
// Create local surface from: // Create local surface from:
// - explicitly named patches only (-patches (at your option) // - explicitly named patches only (-patches (at your option)
// - all patches (default in sequential mode) // - all patches (default in sequential mode)
@ -98,24 +114,10 @@ int main(int argc, char *argv[])
if (args.optionFound("patches")) if (args.optionFound("patches"))
{ {
const wordList patchNames includePatches = bMesh.patchSet
( (
args.optionLookup("patches")() wordReList(args.optionLookup("patches")())
); );
forAll(patchNames, patchNameI)
{
const word& patchName = patchNames[patchNameI];
const label patchI = bMesh.findPatchID(patchName);
if (patchI == -1)
{
FatalErrorIn(args.executable()) << "No such patch "
<< patchName << endl << "Patches are " << bMesh.names()
<< exit(FatalError);
}
includePatches.insert(patchI);
}
} }
else else
{ {
@ -127,212 +129,155 @@ int main(int argc, char *argv[])
{ {
includePatches.insert(patchI); includePatches.insert(patchI);
} }
else
{
Pout<< patch.name() << " : skipped since processorPatch"
<< endl;
}
} }
} }
triSurface localSurface
// Collect sizes. Hash on names to handle local-only patches (e.g.
// processor patches)
HashTable<label> patchSize(1000);
label nFaces = 0;
forAllConstIter(labelHashSet, includePatches, iter)
{
const polyPatch& pp = bMesh[iter.key()];
patchSize.insert(pp.name(), pp.size());
nFaces += pp.size();
}
Pstream::mapCombineGather(patchSize, plusEqOp<label>());
// Allocate zone/patch for all patches
HashTable<label> compactZoneID(1000);
forAllConstIter(HashTable<label>, patchSize, iter)
{
label sz = compactZoneID.size();
compactZoneID.insert(iter.key(), sz);
}
Pstream::mapCombineScatter(compactZoneID);
// Rework HashTable into labelList just for speed of conversion
labelList patchToCompactZone(bMesh.size(), -1);
forAllConstIter(HashTable<label>, compactZoneID, iter)
{
label patchI = bMesh.findPatchID(iter.key());
if (patchI != -1)
{
patchToCompactZone[patchI] = iter();
}
}
// Collect faces on zones
DynamicList<label> faceLabels(nFaces);
DynamicList<label> compactZones(nFaces);
forAllConstIter(labelHashSet, includePatches, iter)
{
const polyPatch& pp = bMesh[iter.key()];
forAll(pp, i)
{
faceLabels.append(pp.start()+i);
compactZones.append(patchToCompactZone[pp.index()]);
}
}
// Addressing engine for all faces
uindirectPrimitivePatch allBoundary
( (
triSurfaceTools::triangulate UIndirectList<face>(mesh.faces(), faceLabels),
( mesh.points()
mesh.boundaryMesh(),
includePatches
)
); );
// Find correspondence to master points
labelList pointToGlobal;
labelList uniqueMeshPoints;
autoPtr<globalIndex> globalNumbers = mesh.globalData().mergePoints
(
allBoundary.meshPoints(),
allBoundary.meshPointMap(),
pointToGlobal,
uniqueMeshPoints
);
if (!Pstream::parRun()) // Gather all unique points on master
List<pointField> gatheredPoints(Pstream::nProcs());
gatheredPoints[Pstream::myProcNo()] = pointField
(
mesh.points(),
uniqueMeshPoints
);
Pstream::gatherList(gatheredPoints);
// Gather all faces
List<faceList> gatheredFaces(Pstream::nProcs());
gatheredFaces[Pstream::myProcNo()] = allBoundary.localFaces();
forAll(gatheredFaces[Pstream::myProcNo()], i)
{ {
Info<< "Writing surface to " << outFileName << endl; inplaceRenumber(pointToGlobal, gatheredFaces[Pstream::myProcNo()][i]);
localSurface.write(outFileName);
} }
else Pstream::gatherList(gatheredFaces);
// Gather all ZoneIDs
List<labelList> gatheredZones(Pstream::nProcs());
gatheredZones[Pstream::myProcNo()] = compactZones.xfer();
Pstream::gatherList(gatheredZones);
// On master combine all points, faces, zones
if (Pstream::master())
{ {
// Write local surface pointField allPoints = ListListOps::combine<pointField>
fileName localPath = runTime.path()/runTime.caseName() + ".obj"; (
gatheredPoints,
accessOp<pointField>()
);
gatheredPoints.clear();
Pout<< "Writing local surface to " << localPath << endl; faceList allFaces = ListListOps::combine<faceList>
(
gatheredFaces,
accessOp<faceList>()
);
gatheredFaces.clear();
localSurface.write(localPath); labelList allZones = ListListOps::combine<labelList>
(
Info<< endl; gatheredZones,
accessOp<labelList>()
);
gatheredZones.clear();
// Gather all points on master // Zones
List<pointField> gatheredPoints(Pstream::nProcs()); surfZoneIdentifierList surfZones(compactZoneID.size());
forAllConstIter(HashTable<label>, compactZoneID, iter)
gatheredPoints[Pstream::myProcNo()] = localSurface.points();
Pstream::gatherList(gatheredPoints);
// Gather all localSurface patches
List<geometricSurfacePatchList> gatheredPatches(Pstream::nProcs());
gatheredPatches[Pstream::myProcNo()] = localSurface.patches();
Pstream::gatherList(gatheredPatches);
// Gather all faces
List<List<labelledTri> > gatheredFaces(Pstream::nProcs());
gatheredFaces[Pstream::myProcNo()] = localSurface;
Pstream::gatherList(gatheredFaces);
if (Pstream::master())
{ {
// On master combine all points surfZones[iter()] = surfZoneIdentifier(iter.key(), iter());
pointField allPoints = Info<< "surfZone " << iter() << " : " << surfZones[iter()].name()
ListListOps::combine<pointField> << endl;
(
gatheredPoints,
accessOp<pointField>()
);
// Count number of patches.
label nPatches = 0;
forAll(gatheredPatches, procI)
{
nPatches += gatheredPatches[procI].size();
}
// Count number of faces.
label nFaces = 0;
forAll(gatheredFaces, procI)
{
nFaces += gatheredFaces[procI].size();
}
// Loop over all processors and
// - construct mapping from local to global patches
// - relabel faces (both points and regions)
label newPatchI = 0;
// Name to new patchI
HashTable<label> nameToIndex(2*nPatches);
// Storage (oversized) for all patches
geometricSurfacePatchList allPatches(nPatches);
label newFaceI = 0;
// Storage for all faces
List<labelledTri> allFaces(nFaces);
// Offset into allPoints for current processor
label pointOffset = 0;
for (label procI = 0; procI < Pstream::nProcs(); procI++)
{
Info<< "Processor " << procI << endl
<< "-----------" << endl;
const geometricSurfacePatchList& patches =
gatheredPatches[procI];
// From local patch numbering to global
labelList localToGlobal(patches.size());
forAll(patches, patchI)
{
const geometricSurfacePatch& sp = patches[patchI];
if (!nameToIndex.found(sp.name()))
{
nameToIndex.insert(sp.name(), newPatchI);
localToGlobal[patchI] = newPatchI;
allPatches[newPatchI] = sp;
newPatchI++;
}
else
{
localToGlobal[patchI] = nameToIndex[sp.name()];
}
}
Info<< "Local patch to global patch mapping:"
<< endl;
forAll(patches, patchI)
{
Info<< " name : " << patches[patchI].name() << endl
<< " local : " << patchI << endl
<< " global : " << localToGlobal[patchI]
<< endl;
}
Info<< "Local points added in global points starting at "
<< pointOffset
<< endl;
// Collect and relabel faces
const List<labelledTri>& localFaces = gatheredFaces[procI];
forAll(localFaces, faceI)
{
const labelledTri& f = localFaces[faceI];
allFaces[newFaceI++] =
labelledTri
(
f[0] + pointOffset,
f[1] + pointOffset,
f[2] + pointOffset,
localToGlobal[f.region()]
);
}
pointOffset += gatheredPoints[procI].size();
Info<< endl;
}
allPatches.setSize(newPatchI);
// We now have allPoints, allFaces and allPatches.
// Construct overall (yet unmerged) surface from these.
triSurface allSurf(allFaces, allPatches, allPoints);
// Cleanup (which does point merge as well)
allSurf.cleanup(false);
// Write surface mesh
label slashIndex = runTime.caseName().find_last_of('/');
fileName globalCasePath(runTime.caseName().substr(0, slashIndex));
Info<< "Writing merged surface to " << globalCasePath << endl;
// create database for the sequential run
fileName globalPath
(
runTime.rootPath()
/ globalCasePath
/ args[1]
);
allSurf.write(globalPath);
} }
UnsortedMeshedSurface<face> unsortedFace
(
xferMove(allPoints),
xferMove(allFaces),
xferMove(allZones),
xferMove(surfZones)
);
MeshedSurface<face> sortedFace(unsortedFace);
fileName globalCasePath
(
runTime.processorCase()
? runTime.path()/".."/outFileName
: runTime.path()/outFileName
);
Info<< "Writing merged surface to " << globalCasePath << endl;
sortedFace.write(globalCasePath);
} }
Info<< "End\n" << endl; Info<< "End\n" << endl;