51 template<
class PatchType>
54 const bool allGeometry,
55 const std::string&
name,
68 typedef typename PatchType::surfaceTopo TopoType;
76 <<
setw(9) << globalSize
83 else if (UPstream::parRun())
97 nEdgeConnections[meshEdges[edgei]] = edgeFaces[edgei].size();
101 syncTools::syncEdgeList
109 label labelTyp = TopoType::MANIFOLD;
112 const label meshEdgei = meshEdges[edgei];
113 const label numNbrs = nEdgeConnections[meshEdgei];
117 labelTyp =
max(labelTyp, TopoType::OPEN);
119 else if (numNbrs == 0 || numNbrs > 2)
123 labelTyp =
max(labelTyp, TopoType::ILLEGAL);
126 reduce(labelTyp, maxOp<label>());
128 if (labelTyp == TopoType::MANIFOLD)
130 Info<<
setw(34) <<
"ok (closed singly connected)";
132 else if (labelTyp == TopoType::OPEN)
134 Info<<
setw(34) <<
"ok (non-closed singly connected)";
138 Info<<
setw(34) <<
"multiply connected (shared edge)";
147 if (pTyp == TopoType::MANIFOLD)
151 Info<<
setw(34) <<
"multiply connected (shared point)";
155 Info<<
setw(34) <<
"ok (closed singly connected)";
171 if (pTyp == TopoType::OPEN)
173 Info<<
setw(34) <<
"ok (non-closed singly connected)";
177 Info<<
setw(34) <<
"multiply connected (shared edge)";
186 boundBox bb(
pp.box());
202 template<
class PatchType>
205 const bool allGeometry,
206 const std::string&
name,
207 const polyMesh&
mesh,
220 typedef typename PatchType::surfaceTopo TopoType;
228 <<
setw(9) << globalSize
235 else if (UPstream::parRun())
254 const globalIndex globalFaces(
mesh.nFaces());
258 const label meshEdgei = meshEdges[edgei];
259 const labelList& eFaces = edgeFaces[edgei];
262 labelList& globalEFaces = globalEdgeFaces[meshEdgei];
263 globalEFaces.
resize(eFaces.size());
266 globalEFaces[i] = globalFaces.toGlobal(meshFaces[eFaces[i]]);
275 syncTools::syncEdgeList
279 ListOps::uniqueEqOp<label>(),
283 label labelTyp = TopoType::MANIFOLD;
286 const label meshEdgei = meshEdges[edgei];
287 const labelList& globalEFaces = globalEdgeFaces[meshEdgei];
288 const label numNbrs = globalEFaces.
size();
292 labelTyp =
max(labelTyp, TopoType::OPEN);
294 else if (numNbrs == 0 || numNbrs > 2)
298 labelTyp =
max(labelTyp, TopoType::ILLEGAL);
301 reduce(labelTyp, maxOp<label>());
303 if (labelTyp == TopoType::MANIFOLD)
305 Info<<
setw(34) <<
"ok (closed singly connected)";
307 else if (labelTyp == TopoType::OPEN)
309 Info<<
setw(34) <<
"ok (non-closed singly connected)";
313 Info<<
setw(34) <<
"multiply connected (shared edge)";
322 if (pTyp == TopoType::MANIFOLD)
326 Info<<
setw(34) <<
"multiply connected (shared point)";
330 Info<<
setw(34) <<
"ok (closed singly connected)";
346 if (pTyp == TopoType::OPEN)
348 Info<<
setw(34) <<
"ok (non-closed singly connected)";
352 Info<<
setw(34) <<
"multiply connected (shared edge)";
361 boundBox bb(
pp.box());
377 const polyMesh&
mesh,
378 const ZoneMesh<Zone, polyMesh>& zones,
383 for (
const auto& zone : zones)
385 for (
const label elem : zone)
390 && zoneID[elem] != zone.index()
395 zoneID[elem] = zone.index();
405 const polyMesh&
mesh,
406 const bool allTopology,
407 const bool allGeometry,
408 autoPtr<surfaceWriter>& surfWriter,
409 autoPtr<coordSetWriter>& setWriter,
410 const bool writeBadEdges
413 label noFailedChecks = 0;
415 Info<<
"Checking topology..." <<
endl;
418 mesh.boundaryMesh().checkDefinition(
true);
425 if (isA<emptyPolyPatch>(
mesh.boundaryMesh()[patchi]))
427 nEmpty +=
mesh.boundaryMesh()[patchi].size();
430 reduce(nEmpty, sumOp<label>());
434 if (nCells && (nEmpty % nCells))
436 Info<<
" ***Total number of faces on empty patches" 437 <<
" is not divisible by the number of cells in the mesh." 438 <<
" Hence this mesh is not 1D or 2D." 444 mesh.boundaryMesh().checkParallelSync(
true);
447 mesh.cellZones().checkDefinition(
true);
448 if (
mesh.cellZones().checkParallelSync(
true))
452 mesh.faceZones().checkDefinition(
true);
453 if (
mesh.faceZones().checkParallelSync(
true))
457 mesh.pointZones().checkDefinition(
true);
458 if (
mesh.pointZones().checkParallelSync(
true))
469 const cell& cFaces =
mesh.cells()[celli];
471 if (cFaces.size() <= 3)
475 for (
const label facei : cFaces)
477 if (facei < 0 || facei >=
mesh.nFaces())
488 Info<<
" Illegal cells (less than 4 faces or out of range faces)" 489 <<
" found, number of cells: " << nCells <<
endl;
492 Info<<
" <<Writing " << nCells
493 <<
" illegal cells to set " <<
cells.name() <<
endl;
494 cells.instance() =
mesh.pointsInstance();
496 if (surfWriter && surfWriter->enabled())
503 Info<<
" Cell to face addressing OK." <<
endl;
517 <<
" unused points to set " <<
points.name() <<
endl;
520 if (setWriter && setWriter->enabled())
528 faceSet faces(
mesh,
"upperTriangularFace",
mesh.nFaces()/100);
529 if (
mesh.checkUpperTriangular(
true, &faces))
534 const label nFaces =
returnReduce(faces.size(), sumOp<label>());
538 Info<<
" <<Writing " << nFaces
539 <<
" unordered faces to set " << faces.name() <<
endl;
540 faces.instance() =
mesh.pointsInstance();
542 if (surfWriter && surfWriter->enabled())
550 faceSet faces(
mesh,
"outOfRangeFaces",
mesh.nFaces()/100);
551 if (
mesh.checkFaceVertices(
true, &faces))
555 const label nFaces =
returnReduce(faces.size(), sumOp<label>());
557 Info<<
" <<Writing " << nFaces
558 <<
" faces with out-of-range or duplicate vertices to set " 559 << faces.name() <<
endl;
560 faces.instance() =
mesh.pointsInstance();
562 if (surfWriter && surfWriter->enabled())
578 Info<<
" <<Writing " << nCells
579 <<
" cells with over used edges to set " <<
cells.name()
581 cells.instance() =
mesh.pointsInstance();
583 if (surfWriter && surfWriter->enabled())
592 faceSet faces(
mesh,
"edgeFaces",
mesh.nFaces()/100);
593 if (
mesh.checkFaceFaces(
true, &faces))
598 const label nFaces =
returnReduce(faces.size(), sumOp<label>());
601 Info<<
" <<Writing " << nFaces
602 <<
" faces with non-standard edge connectivity to set " 603 << faces.name() <<
endl;
604 faces.instance() =
mesh.pointsInstance();
606 if (surfWriter && surfWriter->enabled())
617 for (label facei = 0; facei <
mesh.nInternalFaces(); facei++)
619 nInternalFaces[
mesh.faceOwner()[facei]]++;
620 nInternalFaces[
mesh.faceNeighbour()[facei]]++;
622 const polyBoundaryMesh&
patches =
mesh.boundaryMesh();
629 for (
const label facei : owners)
631 nInternalFaces[facei]++;
636 cellSet oneCells(
mesh,
"oneInternalFaceCells",
mesh.nCells()/100);
637 cellSet twoCells(
mesh,
"twoInternalFacesCells",
mesh.nCells()/100);
639 forAll(nInternalFaces, celli)
641 if (nInternalFaces[celli] <= 1)
643 oneCells.insert(celli);
645 else if (nInternalFaces[celli] == 2)
647 twoCells.insert(celli);
651 const label nOneCells =
returnReduce(oneCells.size(), sumOp<label>());
655 Info<<
" <<Writing " << nOneCells
656 <<
" cells with zero or one non-boundary face to set " 659 oneCells.instance() =
mesh.pointsInstance();
661 if (surfWriter && surfWriter->enabled())
667 const label nTwoCells =
returnReduce(twoCells.size(), sumOp<label>());
671 Info<<
" <<Writing " << nTwoCells
672 <<
" cells with two non-boundary faces to set " 675 twoCells.instance() =
mesh.pointsInstance();
677 if (surfWriter && surfWriter->enabled())
685 regionSplit rs(
mesh);
687 if (rs.nRegions() <= 1)
689 Info<<
" Number of regions: " << rs.nRegions() <<
" (OK)." 695 Info<<
" *Number of regions: " << rs.nRegions() <<
endl;
697 Info<<
" The mesh has multiple regions which are not connected " 698 "by any face." <<
endl 699 <<
" <<Writing region information to " 700 <<
mesh.time().timeName()/
"cellToRegion" 708 mesh.time().timeName(),
712 IOobject::NO_REGISTER
727 boolList regionDisconnected(rs.nRegions(),
true);
737 label facei =
mesh.nInternalFaces();
738 facei <
mesh.nFaces();
742 const label regioni = rs[
mesh.faceOwner()[facei]];
743 const face&
f =
mesh.faces()[facei];
744 for (
const label verti :
f)
746 label& pRegion = pointToRegion[verti];
751 else if (pRegion == -2)
754 regionDisconnected[regioni] =
false;
756 else if (pRegion != regioni)
759 regionDisconnected[regioni] =
false;
760 regionDisconnected[pRegion] =
false;
767 Pstream::listCombineReduce(regionDisconnected, andEqOp<bool>());
773 PtrList<cellSet> cellRegions(rs.nRegions());
774 for (label i = 0; i < rs.nRegions(); i++)
790 cellRegions[rs[i]].insert(i);
793 for (label i = 0; i < rs.nRegions(); i++)
795 Info<<
" <<Writing region " << i;
798 if (regionDisconnected[i])
800 Info<<
" (fully disconnected)";
804 Info<<
" (point connected)";
809 <<
" cells to cellSet " << cellRegions[i].name() <<
endl;
811 cellRegions[i].
write();
818 <<
" points that are in multiple regions to set " 821 if (setWriter && setWriter->enabled())
830 pointSet nonManifoldPoints
838 Info<<
"\nChecking patch topology for multiply connected" 839 <<
" surfaces..." <<
endl;
841 const polyBoundaryMesh&
patches =
mesh.boundaryMesh();
846 <<
setw(20) <<
"Patch" 847 <<
setw(9) <<
"Faces" 848 <<
setw(9) <<
"Points" 849 <<
" Surface topology";
852 Info<<
" Bounding box";
858 if (!UPstream::parRun() || !isA<processorPolyPatch>(
pp))
876 const label nGlobalPatches
888 patches.range(nGlobalPatches-1).end_value()
911 pp.meshEdges(
mesh.edges(),
mesh.pointEdges()),
917 if (writeBadEdges && hadBadEdges)
927 mesh.time().globalPath()
928 / (
"checkMesh-illegal-edges")
940 <<
" bad edges: " <<
writer.output().name() <<
nl;
943 else if (hadBadEdges)
947 <<
" bad edges (possibly relevant for finite-area)" <<
nl;
955 Info<<
"\nChecking faceZone topology for multiply connected" 956 <<
" surfaces..." <<
endl;
962 if (faceZones.size())
965 <<
setw(20) <<
"FaceZone" 966 <<
setw(9) <<
"Faces" 967 <<
setw(9) <<
"Points" 968 <<
setw(34) <<
"Surface topology";
971 Info<<
" Bounding box";
975 for (
const faceZone& fz : faceZones)
993 faceSet mzFaces(
mesh,
"multiZoneFaces",
mesh.nFaces()/100);
997 Info<<
" <<Writing " << nMulti
998 <<
" faces that are in multiple zones" 999 <<
" to set " << mzFaces.name() <<
endl;
1000 mzFaces.instance() =
mesh.pointsInstance();
1002 if (surfWriter && surfWriter->enabled())
1011 Info<<
" No faceZones found."<<
endl;
1017 returnReduce(nonManifoldPoints.size(), sumOp<label>());
1022 <<
" conflicting points to set " << nonManifoldPoints.name()
1024 nonManifoldPoints.instance() =
mesh.pointsInstance();
1025 nonManifoldPoints.write();
1026 if (setWriter && setWriter->enabled())
1033 Info<<
"\nChecking basic cellZone addressing..." <<
endl;
1039 if (cellZones.size())
1042 <<
setw(20) <<
"CellZone" 1043 <<
setw(13) <<
"Cells" 1044 <<
setw(13) <<
"Points" 1045 <<
setw(13) <<
"Volume" 1046 <<
"BoundingBox" <<
endl;
1052 bitSet isZonePoint(
mesh.nPoints());
1054 for (
const cellZone& cZone : cellZones)
1057 isZonePoint.reset();
1060 for (
const label celli : cZone)
1062 v += cellVolumes[celli];
1063 for (
const label facei :
cells[celli])
1065 const face&
f = faces[facei];
1066 for (
const label verti :
f)
1068 if (isZonePoint.set(verti))
1070 bb.add(
mesh.points()[verti]);
1079 <<
setw(19) << cZone.name()
1086 <<
' ' << bb <<
endl;
1093 cellSet mzCells(
mesh,
"multiZoneCells",
mesh.nCells()/100);
1097 Info<<
" <<Writing " << nMulti
1098 <<
" cells that are in multiple zones" 1099 <<
" to set " << mzCells.name() <<
endl;
1100 mzCells.instance() =
mesh.pointsInstance();
1102 if (surfWriter && surfWriter->enabled())
1111 Info<<
" No cellZones found."<<
endl;
1117 Info<<
"\nChecking basic pointZone addressing..." <<
endl;
1123 if (pointZones.size())
1126 <<
setw(20) <<
"PointZone" 1127 <<
setw(8) <<
"Points" 1128 <<
"BoundingBox" <<
nl;
1130 for (
const auto& zone : pointZones)
1140 <<
setw(20) << zone.name()
1150 pointSet mzPoints(
mesh,
"multiZonePoints",
mesh.nPoints()/100);
1154 Info<<
" <<Writing " << nMulti
1155 <<
" points that are in multiple zones" 1156 <<
" to set " << mzPoints.name() <<
endl;
1157 mzPoints.instance() =
mesh.pointsInstance();
1159 if (setWriter && setWriter->enabled())
1168 Info<<
" No pointZones found."<<
endl;
1182 mesh.faceNeighbour();
1193 return noFailedChecks;
void size(const label n)
Older name for setAddressableSize.
ZoneMesh< faceZone, polyMesh > faceZoneMesh
A ZoneMesh with the type faceZone.
List< cell > cellList
List of cell.
vtk::lineWriter writer(edgeCentres, edgeList::null(), fileName(aMesh.time().globalPath()/"finiteArea-edgesCentres"))
ios_base::fmtflags setf(const ios_base::fmtflags f)
Set flags of stream.
void resize(const label len)
Adjust allocated size of list.
List< edge > edgeList
List of edge.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
constexpr char nl
The newline '\n' character (0x0a)
label checkTopology(const polyMesh &mesh, const bool allTopology, const bool allGeometry, autoPtr< surfaceWriter > &surfWriter, autoPtr< coordSetWriter > &setWriter, const bool writeBadEdges=false)
Ostream & endl(Ostream &os)
Add newline and flush stream.
void mergeAndWrite(const polyMesh &mesh, surfaceWriter &writer, const word &name, const indirectPrimitivePatch &setPatch, const fileName &outputDir)
Generate merged surface on master and write. Needs input patch.
label checkZones(const polyMesh &mesh, const ZoneMesh< Zone, polyMesh > &zones, topoSet &set)
labelList faceLabels(nFaceLabels)
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
List< labelList > labelListList
List of labelList.
UList< label > labelUList
A UList of labels.
labelHashSet badEdges(pp.nEdges()/20)
#define forAll(list, i)
Loop across all elements in list.
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
List< face > faceList
List of faces.
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i), works like std::iota() but returning a...
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
labelHashSet * pointSetPtr
labelHashSet * badEdgesPtr
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
ZoneMesh< pointZone, polyMesh > pointZoneMesh
A ZoneMesh with the type pointZone.
Istream and Ostream manipulators taking arguments.
PrimitivePatch< UIndirectList< face >, const pointField & > uindirectPrimitivePatch
A PrimitivePatch with UIndirectList for the faces, const reference for the point field.
const polyBoundaryMesh & patches
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
Reduce inplace (cf. MPI Allreduce) using specified communication schedule.
messageStream Info
Information stream (stdout output on master, null elsewhere)
Omanip< int > setw(const int i)
List< label > labelList
A List of labels.
List< bool > boolList
A List of bools.
bool checkPatch(const bool allGeometry, const std::string &name, const polyMesh &mesh, const PatchType &pp, const labelUList &meshEdges, labelHashSet *pointSetPtr=nullptr, labelHashSet *badEdgesPtr=nullptr)
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
ZoneMesh< cellZone, polyMesh > cellZoneMesh
A ZoneMesh with the type cellZone.
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
static constexpr const zero Zero
Global zero (0)