checkTools.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2015 OpenFOAM Foundation
6  \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "checkTools.H"
27 #include "polyMesh.H"
28 #include "globalMeshData.H"
29 #include "hexMatcher.H"
30 #include "wedgeMatcher.H"
31 #include "prismMatcher.H"
32 #include "pyrMatcher.H"
33 #include "tetWedgeMatcher.H"
34 #include "tetMatcher.H"
35 #include "IOmanip.H"
36 #include "faceSet.H"
37 #include "cellSet.H"
38 #include "PatchTools.H"
39 #include "Time.H"
40 #include "surfaceWriter.H"
41 #include "sampledSurfaces.H"
42 #include "syncTools.H"
43 
44 
45 void Foam::printMeshStats(const polyMesh& mesh, const bool allTopology)
46 {
47  Info<< "Mesh stats" << nl
48  << " points: "
49  << returnReduce(mesh.points().size(), sumOp<label>()) << nl;
50 
51  label nInternalPoints = returnReduce
52  (
53  mesh.nInternalPoints(),
54  sumOp<label>()
55  );
56 
57  if (nInternalPoints != -Pstream::nProcs())
58  {
59  Info<< " internal points: " << nInternalPoints << nl;
60 
61  if (returnReduce(mesh.nInternalPoints(), minOp<label>()) == -1)
62  {
64  << "Some processors have their points sorted into internal"
65  << " and external and some do not." << endl
66  << "This can cause problems later on." << endl;
67  }
68  }
69 
70  if (allTopology && nInternalPoints != -Pstream::nProcs())
71  {
72  label nEdges = returnReduce(mesh.nEdges(), sumOp<label>());
73  label nInternalEdges = returnReduce
74  (
75  mesh.nInternalEdges(),
76  sumOp<label>()
77  );
78  label nInternal1Edges = returnReduce
79  (
80  mesh.nInternal1Edges(),
81  sumOp<label>()
82  );
83  label nInternal0Edges = returnReduce
84  (
85  mesh.nInternal0Edges(),
86  sumOp<label>()
87  );
88 
89  Info<< " edges: " << nEdges << nl
90  << " internal edges: " << nInternalEdges << nl
91  << " internal edges using one boundary point: "
92  << nInternal1Edges-nInternal0Edges << nl
93  << " internal edges using two boundary points: "
94  << nInternalEdges-nInternal1Edges << nl;
95  }
96 
97  label nFaces = returnReduce(mesh.faces().size(), sumOp<label>());
98  label nIntFaces = returnReduce(mesh.faceNeighbour().size(), sumOp<label>());
99  label nCells = returnReduce(mesh.cells().size(), sumOp<label>());
100 
101  Info<< " faces: " << nFaces << nl
102  << " internal faces: " << nIntFaces << nl
103  << " cells: " << nCells << nl
104  << " faces per cell: "
105  << scalar(nFaces + nIntFaces)/max(1, nCells) << nl
106  << " boundary patches: " << mesh.boundaryMesh().size() << nl
107  << " point zones: " << mesh.pointZones().size() << nl
108  << " face zones: " << mesh.faceZones().size() << nl
109  << " cell zones: " << mesh.cellZones().size() << nl
110  << endl;
111 
112  // Construct shape recognizers
113  hexMatcher hex;
114  prismMatcher prism;
115  wedgeMatcher wedge;
116  pyrMatcher pyr;
117  tetWedgeMatcher tetWedge;
118  tetMatcher tet;
119 
120  // Counters for different cell types
121  label nHex = 0;
122  label nWedge = 0;
123  label nPrism = 0;
124  label nPyr = 0;
125  label nTet = 0;
126  label nTetWedge = 0;
127  label nUnknown = 0;
128 
129  Map<label> polyhedralFaces;
130 
131  for (label cellI = 0; cellI < mesh.nCells(); cellI++)
132  {
133  if (hex.isA(mesh, cellI))
134  {
135  nHex++;
136  }
137  else if (tet.isA(mesh, cellI))
138  {
139  nTet++;
140  }
141  else if (pyr.isA(mesh, cellI))
142  {
143  nPyr++;
144  }
145  else if (prism.isA(mesh, cellI))
146  {
147  nPrism++;
148  }
149  else if (wedge.isA(mesh, cellI))
150  {
151  nWedge++;
152  }
153  else if (tetWedge.isA(mesh, cellI))
154  {
155  nTetWedge++;
156  }
157  else
158  {
159  nUnknown++;
160  polyhedralFaces(mesh.cells()[cellI].size())++;
161  }
162  }
163 
164  reduce(nHex,sumOp<label>());
165  reduce(nPrism,sumOp<label>());
166  reduce(nWedge,sumOp<label>());
167  reduce(nPyr,sumOp<label>());
168  reduce(nTetWedge,sumOp<label>());
169  reduce(nTet,sumOp<label>());
170  reduce(nUnknown,sumOp<label>());
171 
172  Info<< "Overall number of cells of each type:" << nl
173  << " hexahedra: " << nHex << nl
174  << " prisms: " << nPrism << nl
175  << " wedges: " << nWedge << nl
176  << " pyramids: " << nPyr << nl
177  << " tet wedges: " << nTetWedge << nl
178  << " tetrahedra: " << nTet << nl
179  << " polyhedra: " << nUnknown
180  << endl;
181 
182  if (nUnknown > 0)
183  {
184  Pstream::mapCombineGather(polyhedralFaces, plusEqOp<label>());
185 
186  Info<< " Breakdown of polyhedra by number of faces:" << nl
187  << " faces" << " number of cells" << endl;
188 
189  const labelList sortedKeys = polyhedralFaces.sortedToc();
190 
191  forAll(sortedKeys, keyI)
192  {
193  const label nFaces = sortedKeys[keyI];
194 
195  Info<< setf(std::ios::right) << setw(13)
196  << nFaces << " " << polyhedralFaces[nFaces] << nl;
197  }
198  }
199 
200  Info<< endl;
201 }
202 
203 
205 (
206  const surfaceWriter& writer,
207  const faceSet& set
208 )
209 {
210  const polyMesh& mesh = refCast<const polyMesh>(set.db());
211 
212  const indirectPrimitivePatch setPatch
213  (
214  IndirectList<face>(mesh.faces(), set.sortedToc()),
215  mesh.points()
216  );
217 
218  const fileName outputDir
219  (
220  set.time().path()
221  / (Pstream::parRun() ? ".." : "")
222  / "postProcessing"
223  / mesh.pointsInstance()
224  / set.name()
225  );
226 
227 
228  if (Pstream::parRun())
229  {
230  // Use tolerance from sampling (since we're doing exactly the same
231  // when parallel merging)
232  const scalar tol = sampledSurfaces::mergeTol();
233  // dimension as fraction of mesh bounding box
234  scalar mergeDim = tol * mesh.bounds().mag();
235 
236  pointField mergedPoints;
237  faceList mergedFaces;
238  labelList pointMergeMap;
239 
240  PatchTools::gatherAndMerge
241  (
242  mergeDim,
243  setPatch,
244  mergedPoints,
245  mergedFaces,
246  pointMergeMap
247  );
248  if (Pstream::master())
249  {
250  writer.write
251  (
252  outputDir,
253  set.name(),
254  mergedPoints,
255  mergedFaces
256  );
257  }
258  }
259  else
260  {
261  writer.write
262  (
263  outputDir,
264  set.name(),
265  setPatch.localPoints(),
266  setPatch.localFaces()
267  );
268  }
269 }
270 
271 
273 (
274  const surfaceWriter& writer,
275  const cellSet& set
276 )
277 {
278  const polyMesh& mesh = refCast<const polyMesh>(set.db());
279  const polyBoundaryMesh& pbm = mesh.boundaryMesh();
280 
281 
282  // Determine faces on outside of cellSet
283  PackedBoolList isInSet(mesh.nCells());
284  forAllConstIter(cellSet, set, iter)
285  {
286  isInSet[iter.key()] = true;
287  }
288 
289 
290  boolList bndInSet(mesh.nFaces()-mesh.nInternalFaces());
291  forAll(pbm, patchI)
292  {
293  const polyPatch& pp = pbm[patchI];
294  const labelList& fc = pp.faceCells();
295  forAll(fc, i)
296  {
297  bndInSet[pp.start()+i-mesh.nInternalFaces()] = isInSet[fc[i]];
298  }
299  }
300  syncTools::swapBoundaryFaceList(mesh, bndInSet);
301 
302 
303  DynamicList<label> outsideFaces(3*set.size());
304  for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
305  {
306  bool ownVal = isInSet[mesh.faceOwner()[faceI]];
307  bool neiVal = isInSet[mesh.faceNeighbour()[faceI]];
308 
309  if (ownVal != neiVal)
310  {
311  outsideFaces.append(faceI);
312  }
313  }
314 
315 
316  forAll(pbm, patchI)
317  {
318  const polyPatch& pp = pbm[patchI];
319  const labelList& fc = pp.faceCells();
320  if (pp.coupled())
321  {
322  forAll(fc, i)
323  {
324  label faceI = pp.start()+i;
325 
326  bool neiVal = bndInSet[faceI-mesh.nInternalFaces()];
327  if (isInSet[fc[i]] && !neiVal)
328  {
329  outsideFaces.append(faceI);
330  }
331  }
332  }
333  else
334  {
335  forAll(fc, i)
336  {
337  if (isInSet[fc[i]])
338  {
339  outsideFaces.append(pp.start()+i);
340  }
341  }
342  }
343  }
344 
345 
346  const indirectPrimitivePatch setPatch
347  (
348  IndirectList<face>(mesh.faces(), outsideFaces),
349  mesh.points()
350  );
351 
352  const fileName outputDir
353  (
354  set.time().path()
355  / (Pstream::parRun() ? ".." : "")
356  / "postProcessing"
357  / mesh.pointsInstance()
358  / set.name()
359  );
360 
361 
362  if (Pstream::parRun())
363  {
364  // Use tolerance from sampling (since we're doing exactly the same
365  // when parallel merging)
366  const scalar tol = sampledSurfaces::mergeTol();
367  // dimension as fraction of mesh bounding box
368  scalar mergeDim = tol * mesh.bounds().mag();
369 
370  pointField mergedPoints;
371  faceList mergedFaces;
372  labelList pointMergeMap;
373 
374  PatchTools::gatherAndMerge
375  (
376  mergeDim,
377  setPatch,
378  mergedPoints,
379  mergedFaces,
380  pointMergeMap
381  );
382  if (Pstream::master())
383  {
384  writer.write
385  (
386  outputDir,
387  set.name(),
388  mergedPoints,
389  mergedFaces
390  );
391  }
392  }
393  else
394  {
395  writer.write
396  (
397  outputDir,
398  set.name(),
399  setPatch.localPoints(),
400  setPatch.localFaces()
401  );
402  }
403 }
Foam::setf
Smanip< ios_base::fmtflags > setf(const ios_base::fmtflags flags)
Definition: IOmanip.H:164
Foam::prismMatcher
A cellMatcher for prism cells.
Definition: prismMatcher.H:51
Foam::PackedBoolList
A bit-packed bool list.
Definition: PackedBoolList.H:63
wedgeMatcher.H
Foam::surfaceWriter
Base class for surface writers.
Definition: surfaceWriter.H:54
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
checkTools.H
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:86
Foam::polyBoundaryMesh
Foam::polyBoundaryMesh.
Definition: polyBoundaryMesh.H:60
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::DynamicList< label >
Foam::tetWedgeMatcher
A cellMatcher for tetWedge cells.
Definition: tetWedgeMatcher.H:51
globalMeshData.H
Foam::PrimitivePatch::localPoints
const Field< PointType > & localPoints() const
Return pointField of points in patch.
Definition: PrimitivePatchTemplate.C:432
Foam::pyrMatcher::isA
virtual bool isA(const primitiveMesh &mesh, const label cellI)
Exact match. Uses faceSizeMatch.
Definition: pyrMatcher.C:267
hexMatcher.H
Foam::minOp
Definition: ops.H:173
Foam::polyPatch::coupled
virtual bool coupled() const
Return true if this patch is geometrically coupled (i.e. faces and.
Definition: polyPatch.H:322
Foam::tetMatcher
A cellMatcher for tet cells.
Definition: tetMatcher.H:51
Foam::writer::write
virtual void write(const coordSet &, const wordList &, const List< const Field< Type > * > &, Ostream &) const =0
General entry point for writing.
Foam::Map< label >
Foam::faceSet
A list of face labels.
Definition: faceSet.H:48
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Foam::printMeshStats
void printMeshStats(const polyMesh &mesh, const bool allTopology)
Definition: checkTools.C:45
surfaceWriter.H
tetWedgeMatcher.H
polyMesh.H
Foam::IOobject::time
const Time & time() const
Return time.
Definition: IOobject.C:245
syncTools.H
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
forAllConstIter
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:39
Foam::IOobject::db
const objectRegistry & db() const
Return the local objectRegistry.
Definition: IOobject.C:239
sampledSurfaces.H
Foam::pyrMatcher
A cellMatcher for pyr cells.
Definition: pyrMatcher.H:51
Foam::prismMatcher::isA
virtual bool isA(const primitiveMesh &mesh, const label cellI)
Exact match. Uses faceSizeMatch.
Definition: prismMatcher.C:343
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:43
Foam::hexMatcher
A cellMatcher for hex cells.
Definition: hexMatcher.H:51
prismMatcher.H
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Foam::Field
Pre-declare SubField and related Field type.
Definition: Field.H:57
Foam::nl
static const char nl
Definition: Ostream.H:260
Foam::Info
messageStream Info
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:66
faceSet.H
Foam::IndirectList
A List with indirect addressing.
Definition: IndirectList.H:102
IOmanip.H
Istream and Ostream manipulators taking arguments.
Foam::IOobject::name
const word & name() const
Return name.
Definition: IOobject.H:273
Foam::mergeAndWrite
void mergeAndWrite(const surfaceWriter &, const faceSet &)
Write vtk representation of (assembled) faceSet to vtk file in.
Definition: checkTools.C:205
Foam::HashTable::size
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:18
Foam::plusEqOp
Definition: ops.H:71
Foam::writer
Base class for graphics format writing. Entry points are.
Definition: writer.H:78
Foam::polyPatch::faceCells
const labelUList & faceCells() const
Return face-cell addressing.
Definition: polyPatch.C:340
Foam::setw
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
Foam::cellSet
A collection of cell labels.
Definition: cellSet.H:48
Foam::HashTable::sortedToc
List< Key > sortedToc() const
Return the table of contents as a sorted list.
Definition: HashTable.C:216
Foam::polyPatch::start
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:312
Foam::tetWedgeMatcher::isA
virtual bool isA(const primitiveMesh &mesh, const label cellI)
Exact match. Uses faceSizeMatch.
Definition: tetWedgeMatcher.C:271
Foam::DynamicList::append
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Foam::hex
IOstream & hex(IOstream &io)
Definition: IOstream.H:564
Foam::max
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
Foam::sumOp
Definition: ops.H:162
Foam::Time::path
fileName path() const
Return path.
Definition: Time.H:281
Foam::wedgeMatcher
A cellMatcher for wedge cells.
Definition: wedgeMatcher.H:51
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
Foam::tetMatcher::isA
virtual bool isA(const primitiveMesh &mesh, const label cellI)
Exact match. Uses faceSizeMatch.
Definition: tetMatcher.C:218
tetMatcher.H
Foam::PrimitivePatch::localFaces
const List< Face > & localFaces() const
Return patch faces addressing into local point list.
Definition: PrimitivePatchTemplate.C:372
cellSet.H
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:259
Foam::wedgeMatcher::isA
virtual bool isA(const primitiveMesh &mesh, const label cellI)
Exact match. Uses faceSizeMatch.
Definition: wedgeMatcher.C:370
pyrMatcher.H
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatchTemplate.H:88