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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2015-2017 OpenFOAM Foundation
9  Copyright (C) 2015-2021 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "checkTools.H"
30 #include "polyMesh.H"
31 #include "globalMeshData.H"
32 #include "hexMatcher.H"
33 #include "wedgeMatcher.H"
34 #include "prismMatcher.H"
35 #include "pyrMatcher.H"
36 #include "tetWedgeMatcher.H"
37 #include "tetMatcher.H"
38 #include "IOmanip.H"
39 #include "pointSet.H"
40 #include "faceSet.H"
41 #include "cellSet.H"
42 #include "Time.H"
43 #include "surfaceWriter.H"
44 #include "syncTools.H"
45 #include "globalIndex.H"
46 #include "PatchTools.H"
47 #include "functionObject.H"
48 
49 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
50 
51 void Foam::printMeshStats(const polyMesh& mesh, const bool allTopology)
52 {
53  if (mesh.name() == Foam::polyMesh::defaultRegion)
54  {
55  Info<< "Mesh stats" << nl;
56  }
57  else
58  {
59  Info<< "Mesh " << mesh.name() << " stats" << nl;
60  }
61  Info<< " points: "
62  << returnReduce(mesh.points().size(), sumOp<label>()) << nl;
63 
64 
65  // Count number of internal points (-1 if not sorted; 0 if no internal
66  // points)
67  const label minInt = returnReduce(mesh.nInternalPoints(), minOp<label>());
68  const label maxInt = returnReduce(mesh.nInternalPoints(), maxOp<label>());
69 
70  if (minInt == -1 && maxInt > 0)
71  {
73  << "Some processors have their points sorted into internal"
74  << " and external and some do not." << endl
75  << " This can cause problems later on." << endl;
76  }
77  else if (minInt != -1)
78  {
79  // Assume all sorted
80  label nInternalPoints = returnReduce
81  (
82  mesh.nInternalPoints(),
83  sumOp<label>()
84  );
85  Info<< " internal points: " << nInternalPoints << nl;
86  }
87 
88  if (allTopology && (minInt != -1))
89  {
90  label nEdges = returnReduce(mesh.nEdges(), sumOp<label>());
91  label nInternalEdges = returnReduce
92  (
93  mesh.nInternalEdges(),
94  sumOp<label>()
95  );
96  label nInternal1Edges = returnReduce
97  (
98  mesh.nInternal1Edges(),
99  sumOp<label>()
100  );
101  label nInternal0Edges = returnReduce
102  (
103  mesh.nInternal0Edges(),
104  sumOp<label>()
105  );
106 
107  Info<< " edges: " << nEdges << nl
108  << " internal edges: " << nInternalEdges << nl
109  << " internal edges using one boundary point: "
110  << nInternal1Edges-nInternal0Edges << nl
111  << " internal edges using two boundary points: "
112  << nInternalEdges-nInternal1Edges << nl;
113  }
114 
115  label nFaces = returnReduce(mesh.faces().size(), sumOp<label>());
116  label nIntFaces = returnReduce(mesh.faceNeighbour().size(), sumOp<label>());
117  label nCells = returnReduce(mesh.cells().size(), sumOp<label>());
118  label nPatches = mesh.boundaryMesh().size();
119 
120  Info<< " faces: " << nFaces << nl
121  << " internal faces: " << nIntFaces << nl
122  << " cells: " << nCells << nl
123  << " faces per cell: "
124  << (scalar(nFaces) + scalar(nIntFaces))/max(1, nCells) << nl
125  << " boundary patches: ";
126 
127  if (Pstream::parRun())
128  {
129  // Number of global patches and min-max range of total patches
130  Info<< mesh.boundaryMesh().nNonProcessor() << ' '
131  << returnReduce(labelMinMax(nPatches), minMaxOp<label>()) << nl;
132  }
133  else
134  {
135  Info<< nPatches << nl;
136  }
137 
138  Info<< " point zones: " << mesh.pointZones().size() << nl
139  << " face zones: " << mesh.faceZones().size() << nl
140  << " cell zones: " << mesh.cellZones().size() << nl
141  << endl;
142 
143  // Construct shape recognizers
144  prismMatcher prism;
145  wedgeMatcher wedge;
146  tetWedgeMatcher tetWedge;
147 
148  // Counters for different cell types
149  label nHex = 0;
150  label nWedge = 0;
151  label nPrism = 0;
152  label nPyr = 0;
153  label nTet = 0;
154  label nTetWedge = 0;
155  label nUnknown = 0;
156 
157  Map<label> polyhedralFaces;
158 
159  for (label celli = 0; celli < mesh.nCells(); celli++)
160  {
161  if (hexMatcher::test(mesh, celli))
162  {
163  nHex++;
164  }
165  else if (tetMatcher::test(mesh, celli))
166  {
167  nTet++;
168  }
169  else if (pyrMatcher::test(mesh, celli))
170  {
171  nPyr++;
172  }
173  else if (prism.isA(mesh, celli))
174  {
175  nPrism++;
176  }
177  else if (wedge.isA(mesh, celli))
178  {
179  nWedge++;
180  }
181  else if (tetWedge.isA(mesh, celli))
182  {
183  nTetWedge++;
184  }
185  else
186  {
187  nUnknown++;
188  polyhedralFaces(mesh.cells()[celli].size())++;
189  }
190  }
191 
192  reduce(nHex,sumOp<label>());
193  reduce(nPrism,sumOp<label>());
194  reduce(nWedge,sumOp<label>());
195  reduce(nPyr,sumOp<label>());
196  reduce(nTetWedge,sumOp<label>());
197  reduce(nTet,sumOp<label>());
198  reduce(nUnknown,sumOp<label>());
199 
200  Info<< "Overall number of cells of each type:" << nl
201  << " hexahedra: " << nHex << nl
202  << " prisms: " << nPrism << nl
203  << " wedges: " << nWedge << nl
204  << " pyramids: " << nPyr << nl
205  << " tet wedges: " << nTetWedge << nl
206  << " tetrahedra: " << nTet << nl
207  << " polyhedra: " << nUnknown
208  << endl;
209 
210  if (nUnknown > 0)
211  {
212  Pstream::mapCombineGather(polyhedralFaces, plusEqOp<label>());
213 
214  Info<< " Breakdown of polyhedra by number of faces:" << nl
215  << " faces" << " number of cells" << endl;
216 
217  const labelList sortedKeys = polyhedralFaces.sortedToc();
218 
219  forAll(sortedKeys, keyi)
220  {
221  const label nFaces = sortedKeys[keyi];
222 
223  Info<< setf(std::ios::right) << setw(13)
224  << nFaces << " " << polyhedralFaces[nFaces] << nl;
225  }
226  }
227 
228  Info<< endl;
229 }
230 
231 
233 (
234  const polyMesh& mesh,
235  surfaceWriter& writer,
236  const word& name,
237  const indirectPrimitivePatch& setPatch,
238  const fileName& outputDir
239 )
240 {
241  if (Pstream::parRun())
242  {
243  labelList pointToGlobal;
244  labelList uniqueMeshPointLabels;
245  autoPtr<globalIndex> globalPoints;
246  autoPtr<globalIndex> globalFaces;
247  faceList mergedFaces;
248  pointField mergedPoints;
250  (
251  mesh,
252  setPatch.localFaces(),
253  setPatch.meshPoints(),
254  setPatch.meshPointMap(),
255 
256  pointToGlobal,
257  uniqueMeshPointLabels,
258  globalPoints,
259  globalFaces,
260 
261  mergedFaces,
262  mergedPoints
263  );
264 
265  // Write
266  if (Pstream::master())
267  {
268  writer.open
269  (
270  mergedPoints,
271  mergedFaces,
272  (outputDir / name),
273  false // serial - already merged
274  );
275 
276  writer.write();
277  writer.clear();
278  }
279  }
280  else
281  {
282  writer.open
283  (
284  setPatch.localPoints(),
285  setPatch.localFaces(),
286  (outputDir / name),
287  false // serial - already merged
288  );
289 
290  writer.write();
291  writer.clear();
292  }
293 }
294 
295 
297 (
298  surfaceWriter& writer,
299  const faceSet& set
300 )
301 {
302  const polyMesh& mesh = refCast<const polyMesh>(set.db());
303 
304  const indirectPrimitivePatch setPatch
305  (
306  IndirectList<face>(mesh.faces(), set.sortedToc()),
307  mesh.points()
308  );
309 
310  fileName outputDir
311  (
312  set.time().globalPath()
313  / functionObject::outputPrefix
314  / mesh.pointsInstance()
315  / set.name()
316  );
317  outputDir.clean(); // Remove unneeded ".."
318 
319  mergeAndWrite(mesh, writer, set.name(), setPatch, outputDir);
320 }
321 
322 
324 (
325  surfaceWriter& writer,
326  const cellSet& set
327 )
328 {
329  const polyMesh& mesh = refCast<const polyMesh>(set.db());
330  const polyBoundaryMesh& pbm = mesh.boundaryMesh();
331 
332 
333  // Determine faces on outside of cellSet
334  bitSet isInSet(mesh.nCells());
335  for (const label celli : set)
336  {
337  isInSet.set(celli);
338  }
339 
340 
341  boolList bndInSet(mesh.nBoundaryFaces());
342  forAll(pbm, patchi)
343  {
344  const polyPatch& pp = pbm[patchi];
345  const labelList& fc = pp.faceCells();
346  forAll(fc, i)
347  {
348  bndInSet[pp.start()+i-mesh.nInternalFaces()] = isInSet[fc[i]];
349  }
350  }
351  syncTools::swapBoundaryFaceList(mesh, bndInSet);
352 
353 
354  DynamicList<label> outsideFaces(3*set.size());
355  for (label facei = 0; facei < mesh.nInternalFaces(); facei++)
356  {
357  const bool ownVal = isInSet[mesh.faceOwner()[facei]];
358  const bool neiVal = isInSet[mesh.faceNeighbour()[facei]];
359 
360  if (ownVal != neiVal)
361  {
362  outsideFaces.append(facei);
363  }
364  }
365 
366 
367  forAll(pbm, patchi)
368  {
369  const polyPatch& pp = pbm[patchi];
370  const labelList& fc = pp.faceCells();
371  if (pp.coupled())
372  {
373  forAll(fc, i)
374  {
375  label facei = pp.start()+i;
376 
377  const bool neiVal = bndInSet[facei-mesh.nInternalFaces()];
378  if (isInSet[fc[i]] && !neiVal)
379  {
380  outsideFaces.append(facei);
381  }
382  }
383  }
384  else
385  {
386  forAll(fc, i)
387  {
388  if (isInSet[fc[i]])
389  {
390  outsideFaces.append(pp.start()+i);
391  }
392  }
393  }
394  }
395 
396 
397  const indirectPrimitivePatch setPatch
398  (
399  IndirectList<face>(mesh.faces(), outsideFaces),
400  mesh.points()
401  );
402 
403  fileName outputDir
404  (
405  set.time().globalPath()
406  / functionObject::outputPrefix
407  / mesh.pointsInstance()
408  / set.name()
409  );
410  outputDir.clean(); // Remove unneeded ".."
411 
412  mergeAndWrite(mesh, writer, set.name(), setPatch, outputDir);
413 }
414 
415 
417 (
418  const writer<scalar>& writer,
419  const pointSet& set
420 )
421 {
422  const polyMesh& mesh = refCast<const polyMesh>(set.db());
423 
424  pointField mergedPts;
425  labelList mergedIDs;
426 
427  if (Pstream::parRun())
428  {
429  // Note: we explicitly do not merge the points
430  // (mesh.globalData().mergePoints etc) since this might
431  // hide any synchronisation problem
432 
433  globalIndex globalNumbering(mesh.nPoints());
434 
435  mergedPts.setSize(returnReduce(set.size(), sumOp<label>()));
436  mergedIDs.setSize(mergedPts.size());
437 
438  labelList setPointIDs(set.sortedToc());
439 
440  // Get renumbered local data
441  pointField myPoints(mesh.points(), setPointIDs);
442  labelList myIDs(globalNumbering.toGlobal(setPointIDs));
443 
444  if (Pstream::master())
445  {
446  // Insert master data first
447  label pOffset = 0;
448  SubList<point>(mergedPts, myPoints.size(), pOffset) = myPoints;
449  SubList<label>(mergedIDs, myIDs.size(), pOffset) = myIDs;
450  pOffset += myPoints.size();
451 
452  // Receive slave ones
453  for (const int slave : Pstream::subProcs())
454  {
455  IPstream fromSlave(Pstream::commsTypes::scheduled, slave);
456 
457  pointField slavePts(fromSlave);
458  labelList slaveIDs(fromSlave);
459 
460  SubList<point>(mergedPts, slavePts.size(), pOffset) = slavePts;
461  SubList<label>(mergedIDs, slaveIDs.size(), pOffset) = slaveIDs;
462  pOffset += slaveIDs.size();
463  }
464  }
465  else
466  {
467  // Construct processor stream with estimate of size. Could
468  // be improved.
469  OPstream toMaster
470  (
471  Pstream::commsTypes::scheduled,
472  Pstream::masterNo(),
473  myPoints.byteSize() + myIDs.byteSize()
474  );
475  toMaster << myPoints << myIDs;
476  }
477  }
478  else
479  {
480  mergedIDs = set.sortedToc();
481  mergedPts = pointField(mesh.points(), mergedIDs);
482  }
483 
484 
485  // Write with scalar pointID
486  if (Pstream::master())
487  {
488  scalarField scalarPointIDs(mergedIDs.size());
489  forAll(mergedIDs, i)
490  {
491  scalarPointIDs[i] = 1.0*mergedIDs[i];
492  }
493 
494  coordSet points(set.name(), "distance", mergedPts, mag(mergedPts));
495 
496  List<const scalarField*> flds(1, &scalarPointIDs);
497 
498  wordList fldNames(1, "pointID");
499 
500  // Output e.g. pointSet p0 to
501  // postProcessing/<time>/p0.vtk
502  fileName outputDir
503  (
504  set.time().globalPath()
505  / functionObject::outputPrefix
506  / mesh.pointsInstance()
507  // set.name()
508  );
509  outputDir.clean(); // Remove unneeded ".."
510  mkDir(outputDir);
511 
512  fileName outputFile(outputDir/writer.getFileName(points, wordList()));
513  //fileName outputFile(outputDir/set.name());
514 
515  OFstream os(outputFile);
516 
517  writer.write(points, fldNames, flds, os);
518  }
519 }
520 
521 
522 // ************************************************************************* //
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:63
Foam::setf
Smanip< ios_base::fmtflags > setf(const ios_base::fmtflags flags)
Definition: IOmanip.H:169
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
Foam::scalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Definition: primitiveFieldsFwd.H:46
Foam::BitOps::set
void set(List< bool > &bools, const labelRange &range)
Definition: BitOps.C:30
wedgeMatcher.H
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:88
Foam::polyMesh::defaultRegion
static word defaultRegion
Definition: polyMesh.H:314
PatchTools.H
globalMeshData.H
Foam::PatchTools::gatherAndMerge
static void gatherAndMerge(const scalar mergeDist, const PrimitivePatch< FaceList, PointField > &p, Field< typename PrimitivePatch< FaceList, PointField >::point_type > &mergedPoints, List< typename PrimitivePatch< FaceList, PointField >::face_type > &mergedFaces, labelList &pointMergeMap)
Definition: PatchToolsGatherAndMerge.C:31
globalIndex.H
hexMatcher.H
Foam::boolList
List< bool > boolList
A List of bools.
Definition: List.H:61
Foam::endl
Ostream & endl(Ostream &os)
Definition: Ostream.H:381
surfaceWriter.H
tetWedgeMatcher.H
polyMesh.H
syncTools.H
forAll
#define forAll(list, i)
Definition: stdFoam.H:349
Foam::wordList
List< word > wordList
A List of words.
Definition: fileName.H:58
nPatches
const label nPatches
Definition: printMeshSummary.H:24
prismMatcher.H
Foam::Info
messageStream Info
faceSet.H
IOmanip.H
Istream and Ostream manipulators taking arguments.
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Definition: hashSets.C:40
reduce
reduce(hasMovingMesh, orOp< bool >())
os
OBJstream os(runTime.globalPath()/outputName)
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::labelMinMax
MinMax< label > labelMinMax
A label min/max range.
Definition: MinMax.H:107
Foam::setw
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
Foam::indirectPrimitivePatch
PrimitivePatch< IndirectList< face >, const pointField & > indirectPrimitivePatch
A PrimitivePatch with an IndirectList for the faces, const reference for the point field.
Definition: indirectPrimitivePatch.H:43
Time.H
Foam::nl
constexpr char nl
Definition: Ostream.H:424
Foam::faceList
List< face > faceList
A List of faces.
Definition: faceListFwd.H:41
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::printMeshStats
void printMeshStats(const polyMesh &mesh, const bool allTopology)
tetMatcher.H
Foam::mergeAndWrite
void mergeAndWrite(const polyMesh &mesh, surfaceWriter &writer, const word &name, const indirectPrimitivePatch &setPatch, const fileName &outputDir)
Foam::name
word name(const expressions::valueTypeCode typeCode)
Definition: exprTraits.C:52
cellSet.H
functionObject.H
writer
vtk::internalMeshWriter writer(topoMesh, topoCells, vtk::formatType::INLINE_ASCII, runTime.path()/"blockTopology")
Foam::mkDir
bool mkDir(const fileName &pathName, mode_t mode=0777)
Definition: POSIX.C:533
WarningInFunction
#define WarningInFunction
Definition: messageStream.H:353
checkTools.H
pyrMatcher.H
pointSet.H