primitiveMeshCheck.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) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2019 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 "primitiveMesh.H"
30 #include "pyramidPointFaceRef.H"
31 #include "ListOps.H"
32 #include "unitConversion.H"
33 #include "SortableList.H"
34 #include "edgeHashes.H"
35 #include "primitiveMeshTools.H"
36 
37 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38 
39 Foam::scalar Foam::primitiveMesh::closedThreshold_ = 1.0e-6;
40 Foam::scalar Foam::primitiveMesh::aspectThreshold_ = 1000;
41 Foam::scalar Foam::primitiveMesh::nonOrthThreshold_ = 70; // deg
43 Foam::scalar Foam::primitiveMesh::planarCosAngle_ = 1.0e-6;
44 
45 
46 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
47 
49 (
50  const vectorField& areas,
51  const bool report,
52  const bitSet& internalOrCoupledFaces
53 ) const
54 {
55  if (debug)
56  {
58  << "Checking whether the boundary is closed" << endl;
59  }
60 
61  // Loop through all boundary faces and sum up the face area vectors.
62  // For a closed boundary, this should be zero in all vector components
63 
64  Vector<solveScalar> sumClosed(Zero);
65  solveScalar sumMagClosedBoundary = 0;
66 
67  for (label facei = nInternalFaces(); facei < areas.size(); facei++)
68  {
69  if (!internalOrCoupledFaces.size() || !internalOrCoupledFaces[facei])
70  {
71  sumClosed += Vector<solveScalar>(areas[facei]);
72  sumMagClosedBoundary += mag(areas[facei]);
73  }
74  }
75 
76  reduce(sumClosed, sumOp<Vector<solveScalar>>());
77  reduce(sumMagClosedBoundary, sumOp<solveScalar>());
78 
79  Vector<solveScalar> openness = sumClosed/(sumMagClosedBoundary + VSMALL);
80 
81  if (cmptMax(cmptMag(openness)) > closedThreshold_)
82  {
83  if (debug || report)
84  {
85  Info<< " ***Boundary openness " << openness
86  << " possible hole in boundary description."
87  << endl;
88  }
89 
90  return true;
91  }
92 
93  if (debug || report)
94  {
95  Info<< " Boundary openness " << openness << " OK."
96  << endl;
97  }
98 
99  return false;
100 }
101 
102 
104 (
105  const vectorField& faceAreas,
106  const scalarField& cellVolumes,
107  const bool report,
108  labelHashSet* setPtr,
109  labelHashSet* aspectSetPtr,
110  const Vector<label>& meshD
111 ) const
112 {
113  if (debug)
114  {
116  << "Checking whether cells are closed" << endl;
117  }
118 
119  // Check that all cells labels are valid
120  const cellList& c = cells();
121 
122  label nErrorClosed = 0;
123 
124  forAll(c, cI)
125  {
126  const cell& curCell = c[cI];
127 
128  if (min(curCell) < 0 || max(curCell) > nFaces())
129  {
130  if (setPtr)
131  {
132  setPtr->insert(cI);
133  }
134 
135  nErrorClosed++;
136  }
137  }
138 
139  if (nErrorClosed > 0)
140  {
141  if (debug || report)
142  {
143  Info<< " ***Cells with invalid face labels found, number of cells "
144  << nErrorClosed << endl;
145  }
146 
147  return true;
148  }
149 
150 
151  scalarField openness;
152  scalarField aspectRatio;
153  primitiveMeshTools::cellClosedness
154  (
155  *this,
156  meshD,
157  faceAreas,
158  cellVolumes,
159  openness,
160  aspectRatio
161  );
162 
163  label nOpen = 0;
164  scalar maxOpennessCell = max(openness);
165  label nAspect = 0;
166  scalar maxAspectRatio = max(aspectRatio);
167 
168  // Check the sums
169  forAll(openness, celli)
170  {
171  if (openness[celli] > closedThreshold_)
172  {
173  if (setPtr)
174  {
175  setPtr->insert(celli);
176  }
177 
178  nOpen++;
179  }
180 
181  if (aspectRatio[celli] > aspectThreshold_)
182  {
183  if (aspectSetPtr)
184  {
185  aspectSetPtr->insert(celli);
186  }
187 
188  nAspect++;
189  }
190  }
191 
192  reduce(nOpen, sumOp<label>());
193  reduce(maxOpennessCell, maxOp<scalar>());
194 
195  reduce(nAspect, sumOp<label>());
196  reduce(maxAspectRatio, maxOp<scalar>());
197 
198 
199  if (nOpen > 0)
200  {
201  if (debug || report)
202  {
203  Info<< " ***Open cells found, max cell openness: "
204  << maxOpennessCell << ", number of open cells " << nOpen
205  << endl;
206  }
207 
208  return true;
209  }
210 
211  if (nAspect > 0)
212  {
213  if (debug || report)
214  {
215  Info<< " ***High aspect ratio cells found, Max aspect ratio: "
216  << maxAspectRatio
217  << ", number of cells " << nAspect
218  << endl;
219  }
220 
221  return true;
222  }
223 
224  if (debug || report)
225  {
226  Info<< " Max cell openness = " << maxOpennessCell << " OK." << nl
227  << " Max aspect ratio = " << maxAspectRatio << " OK."
228  << endl;
229  }
230 
231  return false;
232 }
233 
234 
236 (
237  const vectorField& faceAreas,
238  const bool report,
239  const bool detailedReport,
240  labelHashSet* setPtr
241 ) const
242 {
243  if (debug)
244  {
245  InfoInFunction << "Checking face area magnitudes" << endl;
246  }
247 
248  const scalarField magFaceAreas(mag(faceAreas));
249 
250  scalar minArea = GREAT;
251  scalar maxArea = -GREAT;
252 
253  forAll(magFaceAreas, facei)
254  {
255  if (magFaceAreas[facei] < VSMALL)
256  {
257  if (setPtr)
258  {
259  setPtr->insert(facei);
260  }
261  if (detailedReport)
262  {
263  if (isInternalFace(facei))
264  {
265  Pout<< "Zero or negative face area detected for "
266  << "internal face "<< facei << " between cells "
267  << faceOwner()[facei] << " and "
268  << faceNeighbour()[facei]
269  << ". Face area magnitude = " << magFaceAreas[facei]
270  << endl;
271  }
272  else
273  {
274  Pout<< "Zero or negative face area detected for "
275  << "boundary face " << facei << " next to cell "
276  << faceOwner()[facei] << ". Face area magnitude = "
277  << magFaceAreas[facei] << endl;
278  }
279  }
280  }
281 
282  minArea = min(minArea, magFaceAreas[facei]);
283  maxArea = max(maxArea, magFaceAreas[facei]);
284  }
285 
286  reduce(minArea, minOp<scalar>());
287  reduce(maxArea, maxOp<scalar>());
288 
289  if (minArea < VSMALL)
290  {
291  if (debug || report)
292  {
293  Info<< " ***Zero or negative face area detected. "
294  "Minimum area: " << minArea << endl;
295  }
296 
297  return true;
298  }
299 
300  if (debug || report)
301  {
302  Info<< " Minimum face area = " << minArea
303  << ". Maximum face area = " << maxArea
304  << ". Face area magnitudes OK." << endl;
305  }
306 
307  return false;
308 }
309 
310 
312 (
313  const scalarField& vols,
314  const bool report,
315  const bool detailedReport,
316  labelHashSet* setPtr
317 ) const
318 {
319  if (debug)
320  {
321  InfoInFunction << "Checking cell volumes" << endl;
322  }
323 
324  scalar minVolume = GREAT;
325  scalar maxVolume = -GREAT;
326 
327  label nNegVolCells = 0;
328 
329  forAll(vols, celli)
330  {
331  if (vols[celli] < VSMALL)
332  {
333  if (setPtr)
334  {
335  setPtr->insert(celli);
336  }
337  if (detailedReport)
338  {
339  Pout<< "Zero or negative cell volume detected for cell "
340  << celli << ". Volume = " << vols[celli] << endl;
341  }
342 
343  nNegVolCells++;
344  }
345 
346  minVolume = min(minVolume, vols[celli]);
347  maxVolume = max(maxVolume, vols[celli]);
348  }
349 
350  reduce(minVolume, minOp<scalar>());
351  reduce(maxVolume, maxOp<scalar>());
352  reduce(nNegVolCells, sumOp<label>());
353 
354  if (minVolume < VSMALL)
355  {
356  if (debug || report)
357  {
358  Info<< " ***Zero or negative cell volume detected. "
359  << "Minimum negative volume: " << minVolume
360  << ", Number of negative volume cells: " << nNegVolCells
361  << endl;
362  }
363 
364  return true;
365  }
366 
367  if (debug || report)
368  {
369  Info<< " Min volume = " << minVolume
370  << ". Max volume = " << maxVolume
371  << ". Total volume = " << gSum(vols)
372  << ". Cell volumes OK." << endl;
373  }
374 
375  return false;
376 }
377 
378 
380 (
381  const vectorField& fAreas,
382  const vectorField& cellCtrs,
383  const bool report,
384  labelHashSet* setPtr
385 ) const
386 {
387  if (debug)
388  {
389  InfoInFunction << "Checking mesh non-orthogonality" << endl;
390  }
391 
392 
393  tmp<scalarField> tortho = primitiveMeshTools::faceOrthogonality
394  (
395  *this,
396  fAreas,
397  cellCtrs
398  );
399  const scalarField& ortho = tortho();
400 
401  // Severe nonorthogonality threshold
402  const scalar severeNonorthogonalityThreshold =
403  ::cos(degToRad(nonOrthThreshold_));
404 
405  scalar minDDotS = min(ortho);
406 
407  scalar sumDDotS = sum(ortho);
408 
409  label severeNonOrth = 0;
410 
411  label errorNonOrth = 0;
412 
413 
414  forAll(ortho, facei)
415  {
416  if (ortho[facei] < severeNonorthogonalityThreshold)
417  {
418  if (ortho[facei] > SMALL)
419  {
420  if (setPtr)
421  {
422  setPtr->insert(facei);
423  }
424 
425  severeNonOrth++;
426  }
427  else
428  {
429  if (setPtr)
430  {
431  setPtr->insert(facei);
432  }
433 
434  errorNonOrth++;
435  }
436  }
437  }
438 
439  reduce(minDDotS, minOp<scalar>());
440  reduce(sumDDotS, sumOp<scalar>());
441  reduce(severeNonOrth, sumOp<label>());
442  reduce(errorNonOrth, sumOp<label>());
443 
444  if (debug || report)
445  {
446  label neiSize = ortho.size();
447  reduce(neiSize, sumOp<label>());
448 
449  if (neiSize > 0)
450  {
451  if (debug || report)
452  {
453  Info<< " Mesh non-orthogonality Max: "
454  << radToDeg(::acos(minDDotS))
455  << " average: " << radToDeg(::acos(sumDDotS/neiSize))
456  << endl;
457  }
458  }
459 
460  if (severeNonOrth > 0)
461  {
462  Info<< " *Number of severely non-orthogonal faces: "
463  << severeNonOrth << "." << endl;
464  }
465  }
466 
467  if (errorNonOrth > 0)
468  {
469  if (debug || report)
470  {
471  Info<< " ***Number of non-orthogonality errors: "
472  << errorNonOrth << "." << endl;
473  }
474 
475  return true;
476  }
477 
478  if (debug || report)
479  {
480  Info<< " Non-orthogonality check OK." << endl;
481  }
482 
483  return false;
484 }
485 
486 
488 (
489  const pointField& points,
490  const vectorField& ctrs,
491  const bool report,
492  const bool detailedReport,
493  const scalar minPyrVol,
494  labelHashSet* setPtr
495 ) const
496 {
497  if (debug)
498  {
499  InfoInFunction << "Checking face orientation" << endl;
500  }
501 
502  const labelList& own = faceOwner();
503  const labelList& nei = faceNeighbour();
504  const faceList& f = faces();
505 
506 
507  scalarField ownPyrVol;
508  scalarField neiPyrVol;
509  primitiveMeshTools::facePyramidVolume
510  (
511  *this,
512  points,
513  ctrs,
514  ownPyrVol,
515  neiPyrVol
516  );
517 
518 
519  label nErrorPyrs = 0;
520 
521  forAll(ownPyrVol, facei)
522  {
523  if (ownPyrVol[facei] < minPyrVol)
524  {
525  if (setPtr)
526  {
527  setPtr->insert(facei);
528  }
529  if (detailedReport)
530  {
531  Pout<< "Negative pyramid volume: " << ownPyrVol[facei]
532  << " for face " << facei << " " << f[facei]
533  << " and owner cell: " << own[facei] << endl
534  << "Owner cell vertex labels: "
535  << cells()[own[facei]].labels(faces())
536  << endl;
537  }
538 
539  nErrorPyrs++;
540  }
541 
542  if (isInternalFace(facei))
543  {
544  if (neiPyrVol[facei] < minPyrVol)
545  {
546  if (setPtr)
547  {
548  setPtr->insert(facei);
549  }
550  if (detailedReport)
551  {
552  Pout<< "Negative pyramid volume: " << neiPyrVol[facei]
553  << " for face " << facei << " " << f[facei]
554  << " and neighbour cell: " << nei[facei] << nl
555  << "Neighbour cell vertex labels: "
556  << cells()[nei[facei]].labels(faces())
557  << endl;
558  }
559  nErrorPyrs++;
560  }
561  }
562  }
563 
564  reduce(nErrorPyrs, sumOp<label>());
565 
566  if (nErrorPyrs > 0)
567  {
568  if (debug || report)
569  {
570  Info<< " ***Error in face pyramids: "
571  << nErrorPyrs << " faces are incorrectly oriented."
572  << endl;
573  }
574 
575  return true;
576  }
577 
578  if (debug || report)
579  {
580  Info<< " Face pyramids OK." << endl;
581  }
582 
583  return false;
584 }
585 
586 
588 (
589  const pointField& points,
590  const vectorField& fCtrs,
591  const vectorField& fAreas,
592  const vectorField& cellCtrs,
593  const bool report,
594  labelHashSet* setPtr
595 ) const
596 {
597  if (debug)
598  {
599  InfoInFunction << "Checking face skewness" << endl;
600  }
601 
602  // Warn if the skew correction vector is more than skewWarning times
603  // larger than the face area vector
604 
605  tmp<scalarField> tskewness = primitiveMeshTools::faceSkewness
606  (
607  *this,
608  points,
609  fCtrs,
610  fAreas,
611  cellCtrs
612  );
613  const scalarField& skewness = tskewness();
614 
615  scalar maxSkew = max(skewness);
616  label nWarnSkew = 0;
617 
618  forAll(skewness, facei)
619  {
620  // Check if the skewness vector is greater than the PN vector.
621  // This does not cause trouble but is a good indication of a poor mesh.
622  if (skewness[facei] > skewThreshold_)
623  {
624  if (setPtr)
625  {
626  setPtr->insert(facei);
627  }
628 
629  nWarnSkew++;
630  }
631  }
632 
633  reduce(maxSkew, maxOp<scalar>());
634  reduce(nWarnSkew, sumOp<label>());
635 
636  if (nWarnSkew > 0)
637  {
638  if (debug || report)
639  {
640  Info<< " ***Max skewness = " << maxSkew
641  << ", " << nWarnSkew << " highly skew faces detected"
642  " which may impair the quality of the results"
643  << endl;
644  }
645 
646  return true;
647  }
648 
649  if (debug || report)
650  {
651  Info<< " Max skewness = " << maxSkew << " OK." << endl;
652  }
653 
654  return false;
655 }
656 
657 
659 (
660  const pointField& points,
661  const vectorField& faceAreas,
662  const bool report,
663  const scalar maxDeg,
664  labelHashSet* setPtr
665 ) const
666 {
667  if (debug)
668  {
669  InfoInFunction << "Checking face angles" << endl;
670  }
671 
672  if (maxDeg < -SMALL || maxDeg > 180+SMALL)
673  {
675  << "maxDeg should be [0..180] but is now " << maxDeg
676  << exit(FatalError);
677  }
678 
679  const scalar maxSin = Foam::sin(degToRad(maxDeg));
680 
681 
682  tmp<scalarField> tfaceAngles = primitiveMeshTools::faceConcavity
683  (
684  maxSin,
685  *this,
686  points,
687  faceAreas
688  );
689  const scalarField& faceAngles = tfaceAngles();
690 
691  scalar maxEdgeSin = max(faceAngles);
692 
693  label nConcave = 0;
694 
695  forAll(faceAngles, facei)
696  {
697  if (faceAngles[facei] > SMALL)
698  {
699  nConcave++;
700 
701  if (setPtr)
702  {
703  setPtr->insert(facei);
704  }
705  }
706  }
707 
708  reduce(nConcave, sumOp<label>());
709  reduce(maxEdgeSin, maxOp<scalar>());
710 
711  if (nConcave > 0)
712  {
713  scalar maxConcaveDegr =
714  radToDeg(Foam::asin(Foam::min(1.0, maxEdgeSin)));
715 
716  if (debug || report)
717  {
718  Info<< " *There are " << nConcave
719  << " faces with concave angles between consecutive"
720  << " edges. Max concave angle = " << maxConcaveDegr
721  << " degrees." << endl;
722  }
723 
724  return true;
725  }
726 
727  if (debug || report)
728  {
729  Info<< " All angles in faces OK." << endl;
730  }
731 
732  return false;
733 }
734 
735 
737 (
738  const pointField& points,
739  const vectorField& faceCentres,
740  const vectorField& faceAreas,
741  const bool report,
742  const scalar warnFlatness,
743  labelHashSet* setPtr
744 ) const
745 {
746  if (debug)
747  {
748  InfoInFunction << "Checking face flatness" << endl;
749  }
750 
751  if (warnFlatness < 0 || warnFlatness > 1)
752  {
754  << "warnFlatness should be [0..1] but is now " << warnFlatness
755  << exit(FatalError);
756  }
757 
758  const faceList& fcs = faces();
759 
760  tmp<scalarField> tfaceFlatness = primitiveMeshTools::faceFlatness
761  (
762  *this,
763  points,
764  faceCentres,
765  faceAreas
766  );
767  const scalarField& faceFlatness = tfaceFlatness();
768 
769  scalarField magAreas(mag(faceAreas));
770 
771  scalar minFlatness = GREAT;
772  scalar sumFlatness = 0;
773  label nSummed = 0;
774  label nWarped = 0;
775 
776  forAll(faceFlatness, facei)
777  {
778  if (fcs[facei].size() > 3 && magAreas[facei] > VSMALL)
779  {
780  sumFlatness += faceFlatness[facei];
781  nSummed++;
782 
783  minFlatness = min(minFlatness, faceFlatness[facei]);
784 
785  if (faceFlatness[facei] < warnFlatness)
786  {
787  nWarped++;
788 
789  if (setPtr)
790  {
791  setPtr->insert(facei);
792  }
793  }
794  }
795  }
796 
797 
798  reduce(nWarped, sumOp<label>());
799  reduce(minFlatness, minOp<scalar>());
800 
801  reduce(nSummed, sumOp<label>());
802  reduce(sumFlatness, sumOp<scalar>());
803 
804  if (debug || report)
805  {
806  if (nSummed > 0)
807  {
808  Info<< " Face flatness (1 = flat, 0 = butterfly) : min = "
809  << minFlatness << " average = " << sumFlatness / nSummed
810  << endl;
811  }
812  }
813 
814 
815  if (nWarped > 0)
816  {
817  if (debug || report)
818  {
819  Info<< " *There are " << nWarped
820  << " faces with ratio between projected and actual area < "
821  << warnFlatness << endl;
822 
823  Info<< " Minimum ratio (minimum flatness, maximum warpage) = "
824  << minFlatness << endl;
825  }
826 
827  return true;
828  }
829 
830  if (debug || report)
831  {
832  Info<< " All face flatness OK." << endl;
833  }
834 
835  return false;
836 }
837 
838 
840 (
841  const vectorField& fAreas,
842  const pointField& fCentres,
843  const bool report,
844  labelHashSet* setPtr
845 ) const
846 {
847  if (debug)
848  {
849  InfoInFunction << "Checking for concave cells" << endl;
850  }
851 
852  const cellList& c = cells();
853  const labelList& fOwner = faceOwner();
854 
855  label nConcaveCells = 0;
856 
857  forAll(c, celli)
858  {
859  const cell& cFaces = c[celli];
860 
861  bool concave = false;
862 
863  forAll(cFaces, i)
864  {
865  if (concave)
866  {
867  break;
868  }
869 
870  label fI = cFaces[i];
871 
872  const point& fC = fCentres[fI];
873 
874  vector fN = fAreas[fI];
875 
876  fN /= max(mag(fN), VSMALL);
877 
878  // Flip normal if required so that it is always pointing out of
879  // the cell
880  if (fOwner[fI] != celli)
881  {
882  fN *= -1;
883  }
884 
885  // Is the centre of any other face of the cell on the
886  // wrong side of the plane of this face?
887 
888  forAll(cFaces, j)
889  {
890  if (j != i)
891  {
892  label fJ = cFaces[j];
893 
894  const point& pt = fCentres[fJ];
895 
896  // If the cell is concave, the point will be on the
897  // positive normal side of the plane of f, defined by
898  // its centre and normal, and the angle between (pt -
899  // fC) and fN will be less than 90 degrees, so the dot
900  // product will be positive.
901 
902  vector pC = (pt - fC);
903 
904  pC /= max(mag(pC), VSMALL);
905 
906  if ((pC & fN) > -planarCosAngle_)
907  {
908  // Concave or planar face
909 
910  concave = true;
911 
912  if (setPtr)
913  {
914  setPtr->insert(celli);
915  }
916 
917  nConcaveCells++;
918 
919  break;
920  }
921  }
922  }
923  }
924  }
925 
926  reduce(nConcaveCells, sumOp<label>());
927 
928  if (nConcaveCells > 0)
929  {
930  if (debug || report)
931  {
932  Info<< " ***Concave cells (using face planes) found,"
933  << " number of cells: " << nConcaveCells << endl;
934  }
935 
936  return true;
937  }
938 
939  if (debug || report)
940  {
941  Info<< " Concave cell check OK." << endl;
942  }
943 
944  return false;
945 }
946 
947 
949 (
950  const bool report,
951  labelHashSet* setPtr
952 ) const
953 {
954  if (debug)
955  {
956  InfoInFunction << "Checking face ordering" << endl;
957  }
958 
959  // Check whether internal faces are ordered in the upper triangular order
960  const labelList& own = faceOwner();
961  const labelList& nei = faceNeighbour();
962 
963  const cellList& c = cells();
964 
965  label internal = nInternalFaces();
966 
967  // Has error occurred?
968  bool error = false;
969  // Have multiple faces been detected?
970  label nMultipleCells = false;
971 
972  // Loop through faceCells once more and make sure that for internal cell
973  // the first label is smaller
974  for (label facei = 0; facei < internal; facei++)
975  {
976  if (own[facei] >= nei[facei])
977  {
978  error = true;
979 
980  if (setPtr)
981  {
982  setPtr->insert(facei);
983  }
984  }
985  }
986 
987  // Loop through all cells. For each cell, find the face that is internal
988  // and add it to the check list (upper triangular order).
989  // Once the list is completed, check it against the faceCell list
990 
991  forAll(c, celli)
992  {
993  const labelList& curFaces = c[celli];
994 
995  // Neighbouring cells
996  SortableList<label> nbr(curFaces.size());
997 
998  forAll(curFaces, i)
999  {
1000  label facei = curFaces[i];
1001 
1002  if (facei >= nInternalFaces())
1003  {
1004  // Sort last
1005  nbr[i] = labelMax;
1006  }
1007  else
1008  {
1009  label nbrCelli = nei[facei];
1010 
1011  if (nbrCelli == celli)
1012  {
1013  nbrCelli = own[facei];
1014  }
1015 
1016  if (celli < nbrCelli)
1017  {
1018  // celli is master
1019  nbr[i] = nbrCelli;
1020  }
1021  else
1022  {
1023  // nbrCell is master. Let it handle this face.
1024  nbr[i] = labelMax;
1025  }
1026  }
1027  }
1028 
1029  nbr.sort();
1030 
1031  // Now nbr holds the cellCells in incremental order. Check:
1032  // - neighbouring cells appear only once. Since nbr is sorted this
1033  // is simple check on consecutive elements
1034  // - faces indexed in same order as nbr are incrementing as well.
1035 
1036  label prevCell = nbr[0];
1037  label prevFace = curFaces[nbr.indices()[0]];
1038 
1039  bool hasMultipleFaces = false;
1040 
1041  for (label i = 1; i < nbr.size(); i++)
1042  {
1043  label thisCell = nbr[i];
1044  label thisFace = curFaces[nbr.indices()[i]];
1045 
1046  if (thisCell == labelMax)
1047  {
1048  break;
1049  }
1050 
1051  if (thisCell == prevCell)
1052  {
1053  hasMultipleFaces = true;
1054 
1055  if (setPtr)
1056  {
1057  setPtr->insert(prevFace);
1058  setPtr->insert(thisFace);
1059  }
1060  }
1061  else if (thisFace < prevFace)
1062  {
1063  error = true;
1064 
1065  if (setPtr)
1066  {
1067  setPtr->insert(thisFace);
1068  }
1069  }
1070 
1071  prevCell = thisCell;
1072  prevFace = thisFace;
1073  }
1074 
1075  if (hasMultipleFaces)
1076  {
1077  nMultipleCells++;
1078  }
1079  }
1080 
1081  reduce(error, orOp<bool>());
1082  reduce(nMultipleCells, sumOp<label>());
1083 
1084  if ((debug || report) && nMultipleCells > 0)
1085  {
1086  Info<< " <<Found " << nMultipleCells
1087  << " neighbouring cells with multiple inbetween faces." << endl;
1088  }
1089 
1090  if (error)
1091  {
1092  if (debug || report)
1093  {
1094  Info<< " ***Faces not in upper triangular order." << endl;
1095  }
1096 
1097  return true;
1098  }
1099 
1100  if (debug || report)
1101  {
1102  Info<< " Upper triangular ordering OK." << endl;
1103  }
1104 
1105  return false;
1106 }
1107 
1108 
1111  const bool report,
1112  labelHashSet* setPtr
1113 ) const
1114 {
1115  if (debug)
1116  {
1117  InfoInFunction << "Checking topological cell openness" << endl;
1118  }
1119 
1120  label nOpenCells = 0;
1121 
1122  const faceList& f = faces();
1123  const cellList& c = cells();
1124 
1125  forAll(c, celli)
1126  {
1127  const labelList& curFaces = c[celli];
1128 
1129  const edgeList cellEdges = c[celli].edges(f);
1130 
1131  labelList edgeUsage(cellEdges.size(), Zero);
1132 
1133  forAll(curFaces, facei)
1134  {
1135  edgeList curFaceEdges = f[curFaces[facei]].edges();
1136 
1137  forAll(curFaceEdges, faceEdgeI)
1138  {
1139  const edge& curEdge = curFaceEdges[faceEdgeI];
1140 
1141  forAll(cellEdges, cellEdgeI)
1142  {
1143  if (cellEdges[cellEdgeI] == curEdge)
1144  {
1145  edgeUsage[cellEdgeI]++;
1146  break;
1147  }
1148  }
1149  }
1150  }
1151 
1152  edgeList singleEdges(cellEdges.size());
1153  label nSingleEdges = 0;
1154 
1155  forAll(edgeUsage, edgeI)
1156  {
1157  if (edgeUsage[edgeI] == 1)
1158  {
1159  singleEdges[nSingleEdges] = cellEdges[edgeI];
1160  nSingleEdges++;
1161  }
1162  else if (edgeUsage[edgeI] != 2)
1163  {
1164  if (setPtr)
1165  {
1166  setPtr->insert(celli);
1167  }
1168  }
1169  }
1170 
1171  if (nSingleEdges > 0)
1172  {
1173  if (setPtr)
1174  {
1175  setPtr->insert(celli);
1176  }
1177 
1178  nOpenCells++;
1179  }
1180  }
1181 
1182  reduce(nOpenCells, sumOp<label>());
1183 
1184  if (nOpenCells > 0)
1185  {
1186  if (debug || report)
1187  {
1188  Info<< " ***Open cells found, number of cells: " << nOpenCells
1189  << ". This problem may be fixable using the zipUpMesh utility."
1190  << endl;
1191  }
1192 
1193  return true;
1194  }
1195 
1196  if (debug || report)
1197  {
1198  Info<< " Topological cell zip-up check OK." << endl;
1199  }
1200 
1201  return false;
1202 }
1203 
1204 
1207  const bool report,
1208  labelHashSet* setPtr
1209 ) const
1210 {
1211  if (debug)
1212  {
1213  InfoInFunction << "Checking face vertices" << endl;
1214  }
1215 
1216  // Check that all vertex labels are valid
1217  const faceList& f = faces();
1218 
1219  label nErrorFaces = 0;
1220 
1221  forAll(f, fI)
1222  {
1223  const face& curFace = f[fI];
1224 
1225  if (min(curFace) < 0 || max(curFace) > nPoints())
1226  {
1227  if (setPtr)
1228  {
1229  setPtr->insert(fI);
1230  }
1231 
1232  nErrorFaces++;
1233  }
1234 
1235  // Uniqueness of vertices
1236  labelHashSet facePoints(2*curFace.size());
1237 
1238  forAll(curFace, fp)
1239  {
1240  bool inserted = facePoints.insert(curFace[fp]);
1241 
1242  if (!inserted)
1243  {
1244  if (setPtr)
1245  {
1246  setPtr->insert(fI);
1247  }
1248 
1249  nErrorFaces++;
1250  }
1251  }
1252  }
1253 
1254  reduce(nErrorFaces, sumOp<label>());
1255 
1256  if (nErrorFaces > 0)
1257  {
1258  if (debug || report)
1259  {
1260  Info<< " Faces with invalid vertex labels found, "
1261  << " number of faces: " << nErrorFaces << endl;
1262  }
1263 
1264  return true;
1265  }
1266 
1267  if (debug || report)
1268  {
1269  Info<< " Face vertices OK." << endl;
1270  }
1271 
1272  return false;
1273 }
1274 
1275 
1278  const bool report,
1279  labelHashSet* setPtr
1280 ) const
1281 {
1282  if (debug)
1283  {
1284  InfoInFunction << "Checking points" << endl;
1285  }
1286 
1287  label nFaceErrors = 0;
1288  label nCellErrors = 0;
1289 
1290  const labelListList& pf = pointFaces();
1291 
1292  forAll(pf, pointi)
1293  {
1294  if (pf[pointi].empty())
1295  {
1296  if (setPtr)
1297  {
1298  setPtr->insert(pointi);
1299  }
1300 
1301  nFaceErrors++;
1302  }
1303  }
1304 
1305 
1306  forAll(pf, pointi)
1307  {
1308  const labelList& pc = pointCells(pointi);
1309 
1310  if (pc.empty())
1311  {
1312  if (setPtr)
1313  {
1314  setPtr->insert(pointi);
1315  }
1316 
1317  nCellErrors++;
1318  }
1319  }
1320 
1321  reduce(nFaceErrors, sumOp<label>());
1322  reduce(nCellErrors, sumOp<label>());
1323 
1324  if (nFaceErrors > 0 || nCellErrors > 0)
1325  {
1326  if (debug || report)
1327  {
1328  Info<< " ***Unused points found in the mesh, "
1329  "number unused by faces: " << nFaceErrors
1330  << " number unused by cells: " << nCellErrors
1331  << endl;
1332  }
1333 
1334  return true;
1335  }
1336 
1337  if (debug || report)
1338  {
1339  Info<< " Point usage OK." << endl;
1340  }
1341 
1342  return false;
1343 }
1344 
1345 
1348  const label facei,
1349  const Map<label>& nCommonPoints,
1350  label& nBaffleFaces,
1351  labelHashSet* setPtr
1352 ) const
1353 {
1354  bool error = false;
1355 
1356  forAllConstIters(nCommonPoints, iter)
1357  {
1358  label nbFacei = iter.key();
1359  label nCommon = iter();
1360 
1361  const face& curFace = faces()[facei];
1362  const face& nbFace = faces()[nbFacei];
1363 
1364  if (nCommon == nbFace.size() || nCommon == curFace.size())
1365  {
1366  if (nbFace.size() != curFace.size())
1367  {
1368  error = true;
1369  }
1370  else
1371  {
1372  nBaffleFaces++;
1373  }
1374 
1375  if (setPtr)
1376  {
1377  setPtr->insert(facei);
1378  setPtr->insert(nbFacei);
1379  }
1380  }
1381  }
1382 
1383  return error;
1384 }
1385 
1386 
1389  const label facei,
1390  const Map<label>& nCommonPoints,
1391  labelHashSet* setPtr
1392 ) const
1393 {
1394  bool error = false;
1395 
1396  forAllConstIters(nCommonPoints, iter)
1397  {
1398  label nbFacei = iter.key();
1399  label nCommon = iter();
1400 
1401  const face& curFace = faces()[facei];
1402  const face& nbFace = faces()[nbFacei];
1403 
1404  if
1405  (
1406  nCommon >= 2
1407  && nCommon != nbFace.size()
1408  && nCommon != curFace.size()
1409  )
1410  {
1411  forAll(curFace, fp)
1412  {
1413  // Get the index in the neighbouring face shared with curFace
1414  label nb = nbFace.find(curFace[fp]);
1415 
1416  if (nb != -1)
1417  {
1418 
1419  // Check the whole face from nb onwards for shared vertices
1420  // with neighbouring face. Rule is that any shared vertices
1421  // should be consecutive on both faces i.e. if they are
1422  // vertices fp,fp+1,fp+2 on one face they should be
1423  // vertices nb, nb+1, nb+2 (or nb+2, nb+1, nb) on the
1424  // other face.
1425 
1426 
1427  // Vertices before and after on curFace
1428  label fpPlus1 = curFace.fcIndex(fp);
1429  label fpMin1 = curFace.rcIndex(fp);
1430 
1431  // Vertices before and after on nbFace
1432  label nbPlus1 = nbFace.fcIndex(nb);
1433  label nbMin1 = nbFace.rcIndex(nb);
1434 
1435  // Find order of walking by comparing next points on both
1436  // faces.
1437  label curInc = labelMax;
1438  label nbInc = labelMax;
1439 
1440  if (nbFace[nbPlus1] == curFace[fpPlus1])
1441  {
1442  curInc = 1;
1443  nbInc = 1;
1444  }
1445  else if (nbFace[nbPlus1] == curFace[fpMin1])
1446  {
1447  curInc = -1;
1448  nbInc = 1;
1449  }
1450  else if (nbFace[nbMin1] == curFace[fpMin1])
1451  {
1452  curInc = -1;
1453  nbInc = -1;
1454  }
1455  else
1456  {
1457  curInc = 1;
1458  nbInc = -1;
1459  }
1460 
1461 
1462  // Pass1: loop until start of common vertices found.
1463  label curNb = nb;
1464  label curFp = fp;
1465 
1466  do
1467  {
1468  curFp += curInc;
1469 
1470  if (curFp >= curFace.size())
1471  {
1472  curFp = 0;
1473  }
1474  else if (curFp < 0)
1475  {
1476  curFp = curFace.size()-1;
1477  }
1478 
1479  curNb += nbInc;
1480 
1481  if (curNb >= nbFace.size())
1482  {
1483  curNb = 0;
1484  }
1485  else if (curNb < 0)
1486  {
1487  curNb = nbFace.size()-1;
1488  }
1489  } while (curFace[curFp] == nbFace[curNb]);
1490 
1491 
1492  // Pass2: check equality walking from curFp, curNb
1493  // in opposite order.
1494 
1495  curInc = -curInc;
1496  nbInc = -nbInc;
1497 
1498  for (label commonI = 0; commonI < nCommon; commonI++)
1499  {
1500  curFp += curInc;
1501 
1502  if (curFp >= curFace.size())
1503  {
1504  curFp = 0;
1505  }
1506  else if (curFp < 0)
1507  {
1508  curFp = curFace.size()-1;
1509  }
1510 
1511  curNb += nbInc;
1512 
1513  if (curNb >= nbFace.size())
1514  {
1515  curNb = 0;
1516  }
1517  else if (curNb < 0)
1518  {
1519  curNb = nbFace.size()-1;
1520  }
1521 
1522  if (curFace[curFp] != nbFace[curNb])
1523  {
1524  if (setPtr)
1525  {
1526  setPtr->insert(facei);
1527  setPtr->insert(nbFacei);
1528  }
1529 
1530  error = true;
1531 
1532  break;
1533  }
1534  }
1535 
1536 
1537  // Done the curFace - nbFace combination.
1538  break;
1539  }
1540  }
1541  }
1542  }
1543 
1544  return error;
1545 }
1546 
1547 
1550  const bool report,
1551  labelHashSet* setPtr
1552 ) const
1553 {
1554  if (debug)
1555  {
1556  InfoInFunction << "Checking face-face connectivity" << endl;
1557  }
1558 
1559  const labelListList& pf = pointFaces();
1560 
1561  label nBaffleFaces = 0;
1562  label nErrorDuplicate = 0;
1563  label nErrorOrder = 0;
1564  Map<label> nCommonPoints(128);
1565 
1566  for (label facei = 0; facei < nFaces(); facei++)
1567  {
1568  const face& curFace = faces()[facei];
1569 
1570  // Calculate number of common points between current facei and
1571  // neighbouring face. Store on map.
1572  nCommonPoints.clear();
1573 
1574  forAll(curFace, fp)
1575  {
1576  label pointi = curFace[fp];
1577 
1578  const labelList& nbs = pf[pointi];
1579 
1580  forAll(nbs, nbI)
1581  {
1582  label nbFacei = nbs[nbI];
1583 
1584  if (facei < nbFacei)
1585  {
1586  // Only check once for each combination of two faces.
1587  ++(nCommonPoints(nbFacei, 0));
1588  }
1589  }
1590  }
1591 
1592  // Perform various checks on common points
1593 
1594  // Check all vertices shared (duplicate point)
1595  if (checkDuplicateFaces(facei, nCommonPoints, nBaffleFaces, setPtr))
1596  {
1597  nErrorDuplicate++;
1598  }
1599 
1600  // Check common vertices are consecutive on both faces
1601  if (checkCommonOrder(facei, nCommonPoints, setPtr))
1602  {
1603  nErrorOrder++;
1604  }
1605  }
1606 
1607  reduce(nBaffleFaces, sumOp<label>());
1608  reduce(nErrorDuplicate, sumOp<label>());
1609  reduce(nErrorOrder, sumOp<label>());
1610 
1611  if (nBaffleFaces)
1612  {
1613  Info<< " Number of identical duplicate faces (baffle faces): "
1614  << nBaffleFaces << endl;
1615  }
1616 
1617  if (nErrorDuplicate > 0 || nErrorOrder > 0)
1618  {
1619  // These are actually warnings, not errors.
1620  if (nErrorDuplicate > 0)
1621  {
1622  Info<< " <<Number of duplicate (not baffle) faces found: "
1623  << nErrorDuplicate
1624  << ". This might indicate a problem." << endl;
1625  }
1626 
1627  if (nErrorOrder > 0)
1628  {
1629  Info<< " <<Number of faces with non-consecutive shared points: "
1630  << nErrorOrder << ". This might indicate a problem." << endl;
1631  }
1632 
1633  return false; //return true;
1634  }
1635 
1636  if (debug || report)
1637  {
1638  Info<< " Face-face connectivity OK." << endl;
1639  }
1640 
1641  return false;
1642 }
1643 
1644 
1645 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1646 
1647 bool Foam::primitiveMesh::checkClosedBoundary(const bool report) const
1648 {
1649  return checkClosedBoundary(faceAreas(), report, bitSet());
1650 }
1651 
1652 
1655  const bool report,
1656  labelHashSet* setPtr,
1657  labelHashSet* aspectSetPtr,
1658  const Vector<label>& solutionD
1659 ) const
1660 {
1661  return checkClosedCells
1662  (
1663  faceAreas(),
1664  cellVolumes(),
1665  report,
1666  setPtr,
1667  aspectSetPtr,
1668  solutionD
1669  );
1670 }
1671 
1672 
1675  const bool report,
1676  labelHashSet* setPtr
1677 ) const
1678 {
1679  return checkFaceAreas
1680  (
1681  faceAreas(),
1682  report,
1683  false, // detailedReport,
1684  setPtr
1685  );
1686 }
1687 
1688 
1691  const bool report,
1692  labelHashSet* setPtr
1693 ) const
1694 {
1695  return checkCellVolumes
1696  (
1697  cellVolumes(),
1698  report,
1699  false, // detailedReport,
1700  setPtr
1701  );
1702 }
1703 
1704 
1707  const bool report,
1708  labelHashSet* setPtr
1709 ) const
1710 {
1711  return checkFaceOrthogonality
1712  (
1713  faceAreas(),
1714  cellCentres(),
1715  report,
1716  setPtr
1717  );
1718 }
1719 
1720 
1723  const bool report,
1724  const scalar minPyrVol,
1725  labelHashSet* setPtr
1726 ) const
1727 {
1728  return checkFacePyramids
1729  (
1730  points(),
1731  cellCentres(),
1732  report,
1733  false, // detailedReport,
1734  minPyrVol,
1735  setPtr
1736  );
1737 }
1738 
1739 
1742  const bool report,
1743  labelHashSet* setPtr
1744 ) const
1745 {
1746  return checkFaceSkewness
1747  (
1748  points(),
1749  faceCentres(),
1750  faceAreas(),
1751  cellCentres(),
1752  report,
1753  setPtr
1754  );
1755 }
1756 
1757 
1760  const bool report,
1761  const scalar maxDeg,
1762  labelHashSet* setPtr
1763 ) const
1764 {
1765  return checkFaceAngles
1766  (
1767  points(),
1768  faceAreas(),
1769  report,
1770  maxDeg,
1771  setPtr
1772  );
1773 }
1774 
1775 
1778  const bool report,
1779  const scalar warnFlatness,
1780  labelHashSet* setPtr
1781 ) const
1782 {
1783  return checkFaceFlatness
1784  (
1785  points(),
1786  faceCentres(),
1787  faceAreas(),
1788  report,
1789  warnFlatness,
1790  setPtr
1791  );
1792 }
1793 
1794 
1797  const bool report,
1798  labelHashSet* setPtr
1799 ) const
1800 {
1801  return checkConcaveCells
1802  (
1803  faceAreas(),
1804  faceCentres(),
1805  report,
1806  setPtr
1807  );
1808 }
1809 
1810 
1811 bool Foam::primitiveMesh::checkTopology(const bool report) const
1812 {
1813  label nFailedChecks = 0;
1814 
1815  if (checkPoints(report)) ++nFailedChecks;
1816  if (checkUpperTriangular(report)) ++nFailedChecks;
1817  if (checkCellsZipUp(report)) ++nFailedChecks;
1818  if (checkFaceVertices(report)) ++nFailedChecks;
1819  if (checkFaceFaces(report)) ++nFailedChecks;
1820 
1821  if (nFailedChecks)
1822  {
1823  if (debug || report)
1824  {
1825  Info<< " Failed " << nFailedChecks
1826  << " mesh topology checks." << endl;
1827  }
1828 
1829  return true;
1830  }
1831 
1832  if (debug || report)
1833  {
1834  Info<< " Mesh topology OK." << endl;
1835  }
1836 
1837  return false;
1838 }
1839 
1840 
1841 bool Foam::primitiveMesh::checkGeometry(const bool report) const
1842 {
1843  label nFailedChecks = 0;
1844 
1845  if (checkClosedBoundary(report)) ++nFailedChecks;
1846  if (checkClosedCells(report)) ++nFailedChecks;
1847  if (checkFaceAreas(report)) ++nFailedChecks;
1848  if (checkCellVolumes(report)) ++nFailedChecks;
1849  if (checkFaceOrthogonality(report)) ++nFailedChecks;
1850  if (checkFacePyramids(report)) ++nFailedChecks;
1851  if (checkFaceSkewness(report)) ++nFailedChecks;
1852 
1853  if (nFailedChecks)
1854  {
1855  if (debug || report)
1856  {
1857  Info<< " Failed " << nFailedChecks
1858  << " mesh geometry checks." << endl;
1859  }
1860 
1861  return true;
1862  }
1863 
1864  if (debug || report)
1865  {
1866  Info<< " Mesh geometry OK." << endl;
1867  }
1868 
1869  return false;
1870 }
1871 
1872 
1873 bool Foam::primitiveMesh::checkMesh(const bool report) const
1874 {
1875  if (debug)
1876  {
1877  InfoInFunction << "Checking primitiveMesh" << endl;
1878  }
1879 
1880  label nFailedChecks = checkTopology(report) + checkGeometry(report);
1881 
1882  if (nFailedChecks)
1883  {
1884  if (debug || report)
1885  {
1886  Info<< " Failed " << nFailedChecks
1887  << " mesh checks." << endl;
1888  }
1889 
1890  return true;
1891  }
1892 
1893  if (debug || report)
1894  {
1895  Info<< "Mesh OK." << endl;
1896  }
1897 
1898  return false;
1899 }
1900 
1901 
1903 {
1904  scalar prev = closedThreshold_;
1905  closedThreshold_ = val;
1906 
1907  return prev;
1908 }
1909 
1910 
1912 {
1913  scalar prev = aspectThreshold_;
1914  aspectThreshold_ = val;
1915 
1916  return prev;
1917 }
1918 
1919 
1921 {
1922  scalar prev = nonOrthThreshold_;
1923  nonOrthThreshold_ = val;
1924 
1925  return prev;
1926 }
1927 
1928 
1929 Foam::scalar Foam::primitiveMesh::setSkewThreshold(const scalar val)
1930 {
1931  scalar prev = skewThreshold_;
1932  skewThreshold_ = val;
1933 
1934  return prev;
1935 }
1936 
1937 
1938 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::primitiveMesh::checkFaceFlatness
bool checkFaceFlatness(const pointField &points, const vectorField &faceCentres, const vectorField &faceAreas, const bool report, const scalar warnFlatness, labelHashSet *setPtr) const
Check face warpage.
Definition: primitiveMeshCheck.C:737
Foam::primitiveMesh::checkFaceSkewness
bool checkFaceSkewness(const pointField &points, const vectorField &fCtrs, const vectorField &fAreas, const vectorField &cellCtrs, const bool report, labelHashSet *setPtr) const
Check face skewness.
Definition: primitiveMeshCheck.C:588
Foam::maxOp
Definition: ops.H:223
Foam::primitiveMesh::checkFacePyramids
bool checkFacePyramids(const pointField &points, const vectorField &ctrs, const bool report, const bool detailedReport, const scalar minPyrVol, labelHashSet *setPtr) const
Check face pyramid volume.
Definition: primitiveMeshCheck.C:488
InfoInFunction
#define InfoInFunction
Report an information message using Foam::Info.
Definition: messageStream.H:316
Foam::val
label ListType::const_reference val
Definition: ListOps.H:407
Foam::primitiveMesh::checkFaceAreas
bool checkFaceAreas(const vectorField &faceAreas, const bool report, const bool detailedReport, labelHashSet *setPtr) const
Check for negative face areas.
Definition: primitiveMeshCheck.C:236
Foam::primitiveMesh::checkFaceFaces
virtual bool checkFaceFaces(const bool report=false, labelHashSet *setPtr=nullptr) const
Check face-face connectivity.
Definition: primitiveMeshCheck.C:1549
Foam::labelMax
constexpr label labelMax
Definition: label.H:65
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:64
Foam::primitiveMesh::checkMesh
virtual bool checkMesh(const bool report=false) const
Check mesh for correctness. Returns false for no error.
Definition: primitiveMeshCheck.C:1873
primitiveMeshTools.H
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:59
Foam::Zero
static constexpr const zero Zero
Global zero.
Definition: zero.H:128
Foam::minOp
Definition: ops.H:224
Foam::sin
dimensionedScalar sin(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:264
Foam::primitiveMesh::setSkewThreshold
static scalar setSkewThreshold(const scalar)
Set the skewness warning threshold as percentage.
Definition: primitiveMeshCheck.C:1929
Foam::primitiveMesh::checkDuplicateFaces
bool checkDuplicateFaces(const label, const Map< label > &, label &nBaffleFaces, labelHashSet *) const
Check if all points on face are shared with another face.
Definition: primitiveMeshCheck.C:1347
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:63
Foam::primitiveMesh::checkFaceAngles
bool checkFaceAngles(const pointField &points, const vectorField &faceAreas, const bool report, const scalar maxDeg, labelHashSet *setPtr) const
Check face angles.
Definition: primitiveMeshCheck.C:659
Foam::Map< label >
unitConversion.H
Unit conversion functions.
Foam::primitiveMesh::checkCellVolumes
bool checkCellVolumes(const scalarField &vols, const bool report, const bool detailedReport, labelHashSet *setPtr) const
Check for negative cell volumes.
Definition: primitiveMeshCheck.C:312
primitiveMesh.H
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::gSum
Type gSum(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:594
Foam::checkTopology
label checkTopology(const polyMesh &mesh, const bool allTopology, const bool allGeometry, autoPtr< surfaceWriter > &surfWriter, const autoPtr< writer< scalar >> &setWriter)
Foam::Pout
prefixOSstream Pout
An Ostream wrapper for parallel output to std::cout.
Foam::HashSet< label, Hash< label > >
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
Foam::primitiveMesh::checkTopology
virtual bool checkTopology(const bool report=false) const
Check mesh topology for correctness.
Definition: primitiveMeshCheck.C:1811
Foam::sumOp
Definition: ops.H:213
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::primitiveMesh::checkConcaveCells
bool checkConcaveCells(const vectorField &fAreas, const pointField &fCentres, const bool report, labelHashSet *setPtr) const
Check for concave cells by the planes of faces.
Definition: primitiveMeshCheck.C:840
Foam::cmptMag
void cmptMag(FieldField< Field, Type > &cf, const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:400
Foam::primitiveMesh::setClosedThreshold
static scalar setClosedThreshold(const scalar)
Set the closedness ratio warning threshold.
Definition: primitiveMeshCheck.C:1902
Foam::cmptMax
void cmptMax(FieldField< Field, typename FieldField< Field, Type >::cmptType > &cf, const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:253
SortableList.H
Foam::primitiveMesh::checkGeometry
virtual bool checkGeometry(const bool report=false) const
Check mesh geometry (& implicitly topology) for correctness.
Definition: primitiveMeshCheck.C:1841
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:51
Foam::primitiveMesh::setNonOrthThreshold
static scalar setNonOrthThreshold(const scalar)
Set the non-orthogonality warning threshold in degrees.
Definition: primitiveMeshCheck.C:1920
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:62
Foam::Field< vector >
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::radToDeg
constexpr scalar radToDeg(const scalar rad) noexcept
Conversion from radians to degrees.
Definition: unitConversion.H:54
Foam::checkGeometry
label checkGeometry(const polyMesh &mesh, const bool allGeometry, autoPtr< surfaceWriter > &surfWriter, const autoPtr< writer< scalar >> &setWriter)
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::FatalError
error FatalError
Foam::SortableList
A list that is sorted upon construction or when explicitly requested with the sort() method.
Definition: List.H:66
Foam::primitiveMesh::aspectThreshold_
static scalar aspectThreshold_
Aspect ratio warning threshold.
Definition: primitiveMesh.H:241
Foam::degToRad
constexpr scalar degToRad(const scalar deg) noexcept
Conversion from degrees to radians.
Definition: unitConversion.H:48
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::primitiveMesh::checkPoints
virtual bool checkPoints(const bool report=false, labelHashSet *setPtr=nullptr) const
Check for unused points.
Definition: primitiveMeshCheck.C:1277
Foam::primitiveMesh::closedThreshold_
static scalar closedThreshold_
Static data to control mesh checking.
Definition: primitiveMesh.H:238
Foam::primitiveMesh::nonOrthThreshold_
static scalar nonOrthThreshold_
Non-orthogonality warning threshold in deg.
Definition: primitiveMesh.H:244
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
edgeHashes.H
Foam::nl
constexpr char nl
Definition: Ostream.H:372
forAllConstIters
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
Foam::primitiveMesh::planarCosAngle_
static scalar planarCosAngle_
Threshold where faces are considered coplanar.
Definition: primitiveMesh.H:250
Foam::primitiveMesh::setAspectThreshold
static scalar setAspectThreshold(const scalar)
Set the aspect ratio warning threshold.
Definition: primitiveMeshCheck.C:1911
f
labelList f(nPoints)
Foam::primitiveMesh::skewThreshold_
static scalar skewThreshold_
Skewness warning threshold.
Definition: primitiveMesh.H:247
Foam::primitiveMesh::checkClosedCells
bool checkClosedCells(const vectorField &faceAreas, const scalarField &cellVolumes, const bool report, labelHashSet *setPtr, labelHashSet *aspectSetPtr, const Vector< label > &meshD) const
Check cells for closedness.
Definition: primitiveMeshCheck.C:104
Foam::Vector
Templated 3D Vector derived from VectorSpace adding construction from 3 components,...
Definition: Vector.H:62
Foam::primitiveMesh::checkClosedBoundary
bool checkClosedBoundary(const vectorField &areas, const bool report, const bitSet &internalOrCoupledFaces) const
Check boundary for closedness.
Definition: primitiveMeshCheck.C:49
Foam::List< cell >
Foam::acos
dimensionedScalar acos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:268
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::PackedList::size
label size() const noexcept
Number of entries.
Definition: PackedListI.H:366
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::HashSet::insert
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:182
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:327
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:74
Foam::primitiveMesh::checkFaceOrthogonality
bool checkFaceOrthogonality(const vectorField &fAreas, const vectorField &cellCtrs, const bool report, labelHashSet *setPtr) const
Check for non-orthogonality.
Definition: primitiveMeshCheck.C:380
Foam::pointCells
Smooth ATC in cells having a point to a set of patches supplied by type.
Definition: pointCells.H:56
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
ListOps.H
Various functions to operate on Lists.
Foam::orOp
Definition: ops.H:234
Foam::primitiveMesh::checkFaceVertices
virtual bool checkFaceVertices(const bool report=false, labelHashSet *setPtr=nullptr) const
Check uniqueness of face vertices.
Definition: primitiveMeshCheck.C:1206
pyramidPointFaceRef.H
Foam::cell
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:54
Foam::error
Class to handle errors and exceptions in a simple, consistent stream-based manner.
Definition: error.H:64
Foam::asin
dimensionedScalar asin(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:267
Foam::primitiveMesh::checkCellsZipUp
virtual bool checkCellsZipUp(const bool report=false, labelHashSet *setPtr=nullptr) const
Check cell zip-up.
Definition: primitiveMeshCheck.C:1110
Foam::primitiveMesh::checkCommonOrder
bool checkCommonOrder(const label, const Map< label > &, labelHashSet *) const
Check that shared points are in consecutive order.
Definition: primitiveMeshCheck.C:1388
Foam::cos
dimensionedScalar cos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:265
Foam::primitiveMesh::faceAreas
const vectorField & faceAreas() const
Definition: primitiveMeshFaceCentresAndAreas.C:156
Foam::primitiveMesh::checkUpperTriangular
virtual bool checkUpperTriangular(const bool report=false, labelHashSet *setPtr=nullptr) const
Check face ordering.
Definition: primitiveMeshCheck.C:949