checkPatchTopology.H
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2023 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
12 
13 Description
14  Check topology of poly patches used for finite-area.
15 
16 Input
17  mesh (polyMesh)
18  meshDefDict (system/faMeshDefintion)
19 
20 \*---------------------------------------------------------------------------*/
21 
22 // Preliminary checks
23 {
24  typedef typename uindirectPrimitivePatch::surfaceTopo TopoType;
25 
26  const polyBoundaryMesh& pbm = mesh.boundaryMesh();
27 
28  wordRes polyPatchNames;
29  meshDefDict.readIfPresent("polyMeshPatches", polyPatchNames);
30 
31  const labelList patchIDs
32  (
33  pbm.patchSet
34  (
36  false, // warnNotFound
37  true // useGroups
38  ).sortedToc()
39  );
40 
41  label nFaceLabels = 0;
42  for (const label patchi : patchIDs)
43  {
44  nFaceLabels += pbm[patchi].size();
45  }
46 
48 
49  nFaceLabels = 0;
50  for (const label patchi : patchIDs)
51  {
52  for (const label facei : pbm[patchi].range())
53  {
54  faceLabels[nFaceLabels] = facei;
55  ++nFaceLabels;
56  }
57  }
58 
60  (
61  UIndirectList<face>(mesh.faces(), faceLabels),
62  mesh.points()
63  );
64 
65  // Non-manifold
66  labelHashSet badEdges(pp.nEdges()/20);
67 
68  labelHashSet* pointSetPtr = nullptr;
70 
71  bool foundError = false;
72 
73  if (returnReduceAnd(pp.empty()))
74  {
75  // Empty
76  }
77  else if (UPstream::parRun())
78  {
79  const labelList meshEdges
80  (
81  pp.meshEdges(mesh.edges(), mesh.pointEdges())
82  );
83 
84  // Parallel - use mesh edges
85  // - no check for point-pinch
86  // - no check for consistent orientation (if that is posible to
87  // check?)
88 
89  // Count number of edge/face connections (globally)
90  labelList nEdgeConnections(mesh.nEdges(), Zero);
91 
92  const labelListList& edgeFaces = pp.edgeFaces();
93 
94  forAll(edgeFaces, edgei)
95  {
96  nEdgeConnections[meshEdges[edgei]] = edgeFaces[edgei].size();
97  }
98 
99  // Synchronise across coupled edges
100  syncTools::syncEdgeList
101  (
102  mesh,
103  nEdgeConnections,
104  plusEqOp<label>(),
105  label(0) // null value
106  );
107 
108  label labelTyp = TopoType::MANIFOLD;
109  forAll(meshEdges, edgei)
110  {
111  const label meshEdgei = meshEdges[edgei];
112  const label numNbrs = nEdgeConnections[meshEdgei];
113  if (numNbrs == 1)
114  {
115  //if (pointSetPtr) pointSetPtr->insert(mesh.edges()[meshEdgei]);
116  labelTyp = max(labelTyp, TopoType::OPEN);
117  }
118  else if (numNbrs == 0 || numNbrs > 2)
119  {
120  if (pointSetPtr) pointSetPtr->insert(mesh.edges()[meshEdgei]);
121  if (badEdgesPtr) badEdgesPtr->insert(edgei);
122  labelTyp = max(labelTyp, TopoType::ILLEGAL);
123  }
124  }
125  reduce(labelTyp, maxOp<label>());
126 
127  foundError = (labelTyp == TopoType::ILLEGAL);
128  }
129  else
130  {
131  const TopoType pTyp = pp.surfaceType(badEdgesPtr);
132 
133  foundError = (pTyp == TopoType::ILLEGAL);
134  }
135 
136  if (foundError)
137  {
138  edgeList dumpEdges(pp.edges(), badEdges.sortedToc());
139 
140  vtk::lineWriter writer
141  (
142  pp.localPoints(),
143  dumpEdges,
144  fileName
145  (
146  mesh.time().globalPath()
147  / ("faMesh-construct.illegalEdges")
148  )
149  );
150 
151  writer.writeGeometry();
152 
153  // CellData
154  writer.beginCellData();
155  writer.writeProcIDs();
156 
157  Info<< "Wrote "
158  << returnReduce(dumpEdges.size(), sumOp<label>())
159  << " bad edges: " << writer.output().name() << nl;
160  writer.close();
161  }
162 }
163 
164 // ************************************************************************* //
const polyBoundaryMesh & pbm
const labelList patchIDs(pbm.patchSet(polyPatchNames, false, true).sortedToc())
IOdictionary & meshDefDict
vtk::lineWriter writer(edgeCentres, edgeList::null(), fileName(aMesh.time().globalPath()/"finiteArea-edgesCentres"))
List< edge > edgeList
List of edge.
Definition: edgeList.H:32
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
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.
Definition: labelList.H:38
scalar range
labelHashSet badEdges(pp.nEdges()/20)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:414
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
bool returnReduceAnd(const bool value, const label comm=UPstream::worldComm)
Perform logical (and) MPI Allreduce on a copy. Uses UPstream::reduceAnd.
dynamicFvMesh & mesh
labelHashSet * pointSetPtr
wordRes polyPatchNames
label nFaceLabels
labelHashSet * badEdgesPtr
bool foundError
PrimitivePatch< UIndirectList< face >, const pointField & > uindirectPrimitivePatch
A PrimitivePatch with UIndirectList for the faces, const reference for the point field.
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)
List< label > labelList
A List of labels.
Definition: List.H:62
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:133