polyMeshGeometry.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-2017 OpenFOAM Foundation
9  Copyright (C) 2015-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 "polyMeshGeometry.H"
31 #include "pyramidPointFaceRef.H"
32 #include "tetPointRef.H"
33 #include "syncTools.H"
34 #include "unitConversion.H"
35 #include "primitiveMeshTools.H"
36 
37 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
38 
39 namespace Foam
40 {
41  defineTypeNameAndDebug(polyMeshGeometry, 0);
42 }
43 
44 
45 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
46 
47 void Foam::polyMeshGeometry::updateFaceCentresAndAreas
48 (
49  const pointField& p,
50  const labelList& changedFaces
51 )
52 {
53  const faceList& fs = mesh_.faces();
54 
55  for (const label facei : changedFaces)
56  {
57  const labelList& f = fs[facei];
58  label nPoints = f.size();
59 
60  // If the face is a triangle, do a direct calculation for efficiency
61  // and to avoid round-off error-related problems
62  if (nPoints == 3)
63  {
64  faceCentres_[facei] = (1.0/3.0)*(p[f[0]] + p[f[1]] + p[f[2]]);
65  faceAreas_[facei] = 0.5*((p[f[1]] - p[f[0]])^(p[f[2]] - p[f[0]]));
66  }
67  else
68  {
69  vector sumN = Zero;
70  scalar sumA = Zero;
71  vector sumAc = Zero;
72 
73  point fCentre = p[f[0]];
74  for (label pi = 1; pi < nPoints; ++pi)
75  {
76  fCentre += p[f[pi]];
77  }
78 
79  fCentre /= nPoints;
80 
81  for (label pi = 0; pi < nPoints; ++pi)
82  {
83  const point& nextPoint = p[f[(pi + 1) % nPoints]];
84 
85  vector c = p[f[pi]] + nextPoint + fCentre;
86  vector n = (nextPoint - p[f[pi]])^(fCentre - p[f[pi]]);
87  scalar a = mag(n);
88 
89  sumN += n;
90  sumA += a;
91  sumAc += a*c;
92  }
93 
94  faceCentres_[facei] = (1.0/3.0)*sumAc/(sumA + VSMALL);
95  faceAreas_[facei] = 0.5*sumN;
96  }
97  }
98 }
99 
100 
101 void Foam::polyMeshGeometry::updateCellCentresAndVols
102 (
103  const labelList& changedCells,
104  const labelList& changedFaces
105 )
106 {
107  const labelList& own = mesh().faceOwner();
108  const cellList& cells = mesh().cells();
109 
110  // Clear the fields for accumulation
111  UIndirectList<vector>(cellCentres_, changedCells) = Zero;
112  UIndirectList<scalar>(cellVolumes_, changedCells) = Zero;
113 
114 
115  // Re-calculate the changed cell centres and volumes
116  for (const label celli : changedCells)
117  {
118  const labelList& cFaces = cells[celli];
119 
120  // Estimate the cell centre and bounding box using the face centres
121  vector cEst(Zero);
122  boundBox bb(boundBox::invertedBox);
123 
124  for (const label facei : cFaces)
125  {
126  const point& fc = faceCentres_[facei];
127  cEst += fc;
128  bb.add(fc);
129  }
130  cEst /= cFaces.size();
131 
132 
133  // Sum up the face-pyramid contributions
134  for (const label facei : cFaces)
135  {
136  // Calculate 3* the face-pyramid volume
137  scalar pyr3Vol = faceAreas_[facei] & (faceCentres_[facei] - cEst);
138 
139  if (own[facei] != celli)
140  {
141  pyr3Vol = -pyr3Vol;
142  }
143 
144  // Accumulate face-pyramid volume
145  cellVolumes_[celli] += pyr3Vol;
146 
147  // Calculate the face-pyramid centre
148  const vector pCtr = (3.0/4.0)*faceCentres_[facei] + (1.0/4.0)*cEst;
149 
150  // Accumulate volume-weighted face-pyramid centre
151  cellCentres_[celli] += pyr3Vol*pCtr;
152  }
153 
154  // Average the accumulated quantities
155 
156  if (mag(cellVolumes_[celli]) > VSMALL)
157  {
158  point cc = cellCentres_[celli] / cellVolumes_[celli];
159 
160  // Do additional check for collapsed cells since some volumes
161  // (e.g. 1e-33) do not trigger above but do return completely
162  // wrong cell centre
163  if (bb.contains(cc))
164  {
165  cellCentres_[celli] = cc;
166  }
167  else
168  {
169  cellCentres_[celli] = cEst;
170  }
171  }
172  else
173  {
174  cellCentres_[celli] = cEst;
175  }
176 
177  cellVolumes_[celli] *= (1.0/3.0);
178  }
179 }
180 
181 
183 (
184  const polyMesh& mesh,
185  const labelList& changedFaces
186 )
187 {
188  const labelList& own = mesh.faceOwner();
189  const labelList& nei = mesh.faceNeighbour();
190 
191  labelHashSet affectedCells(2*changedFaces.size());
192 
193  for (const label facei : changedFaces)
194  {
195  affectedCells.insert(own[facei]);
196 
197  if (mesh.isInternalFace(facei))
198  {
199  affectedCells.insert(nei[facei]);
200  }
201  }
202  return affectedCells.toc();
203 }
204 
205 
206 Foam::scalar Foam::polyMeshGeometry::checkNonOrtho
207 (
208  const polyMesh& mesh,
209  const bool report,
210  const scalar severeNonorthogonalityThreshold,
211  const label facei,
212  const vector& s, // face area vector
213  const vector& d, // cc-cc vector
214 
215  label& severeNonOrth,
216  label& errorNonOrth,
217  labelHashSet* setPtr
218 )
219 {
220  scalar dDotS = (d & s)/(mag(d)*mag(s) + VSMALL);
221 
222  if (dDotS < severeNonorthogonalityThreshold)
223  {
224  label nei = -1;
225 
226  if (mesh.isInternalFace(facei))
227  {
228  nei = mesh.faceNeighbour()[facei];
229  }
230 
231  if (dDotS > SMALL)
232  {
233  if (report)
234  {
235  // Severe non-orthogonality but mesh still OK
236  Pout<< "Severe non-orthogonality for face " << facei
237  << " between cells " << mesh.faceOwner()[facei]
238  << " and " << nei
239  << ": Angle = "
240  << radToDeg(::acos(dDotS))
241  << " deg." << endl;
242  }
243 
244  ++severeNonOrth;
245  }
246  else
247  {
248  // Non-orthogonality greater than 90 deg
249  if (report)
250  {
252  << "Severe non-orthogonality detected for face "
253  << facei
254  << " between cells " << mesh.faceOwner()[facei]
255  << " and " << nei
256  << ": Angle = "
257  << radToDeg(::acos(dDotS))
258  << " deg." << endl;
259  }
260 
261  ++errorNonOrth;
262  }
263 
264  if (setPtr)
265  {
266  setPtr->insert(facei);
267  }
268  }
269  return dDotS;
270 }
271 
272 
273 // Create the neighbour pyramid - it will have positive volume
274 bool Foam::polyMeshGeometry::checkFaceTet
275 (
276  const polyMesh& mesh,
277  const bool report,
278  const scalar minTetQuality,
279  const pointField& p,
280  const label facei,
281  const point& fc, // face centre
282  const point& cc, // cell centre
283 
284  labelHashSet* setPtr
285 )
286 {
287  const face& f = mesh.faces()[facei];
288 
289  forAll(f, fp)
290  {
291  scalar tetQual = tetPointRef
292  (
293  p[f[fp]],
294  p[f.nextLabel(fp)],
295  fc,
296  cc
297  ).quality();
298 
299  if (tetQual < minTetQuality)
300  {
301  if (report)
302  {
303  Pout<< "bool polyMeshGeometry::checkFaceTets("
304  << "const bool, const scalar, const pointField&"
305  << ", const pointField&"
306  << ", const labelList&, labelHashSet*) : "
307  << "face " << facei
308  << " has a triangle that points the wrong way." << nl
309  << "Tet quality: " << tetQual
310  << " Face " << facei
311  << endl;
312  }
313  if (setPtr)
314  {
315  setPtr->insert(facei);
316  }
317  return true;
318  }
319  }
320 
321  return false;
322 }
323 
324 
325 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
326 
327 // Construct from components
329 :
330  mesh_(mesh)
331 {
332  correct();
333 }
334 
335 
336 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
337 
339 {
340  faceAreas_ = mesh_.faceAreas();
341  faceCentres_ = mesh_.faceCentres();
342  cellCentres_ = mesh_.cellCentres();
343  cellVolumes_ = mesh_.cellVolumes();
344 }
345 
346 
348 (
349  const pointField& p,
350  const labelList& changedFaces
351 )
352 {
353  // Update face quantities
354  updateFaceCentresAndAreas(p, changedFaces);
355  // Update cell quantities from face quantities
356  updateCellCentresAndVols(affectedCells(mesh_, changedFaces), changedFaces);
357 }
358 
359 
361 (
362  const bool report,
363  const scalar orthWarn,
364  const polyMesh& mesh,
365  const vectorField& cellCentres,
366  const vectorField& faceAreas,
367  const labelList& checkFaces,
368  const List<labelPair>& baffles,
369  labelHashSet* setPtr
370 )
371 {
372  // for all internal and coupled faces check that the d dot S product
373  // is positive
374 
375  const labelList& own = mesh.faceOwner();
376  const labelList& nei = mesh.faceNeighbour();
378 
379  // Severe nonorthogonality threshold
380  const scalar severeNonorthogonalityThreshold = ::cos(degToRad(orthWarn));
381 
382  // Calculate coupled cell centre
383  pointField neiCc(mesh.nBoundaryFaces());
384 
385  for (label facei = mesh.nInternalFaces(); facei < mesh.nFaces(); ++facei)
386  {
387  neiCc[facei-mesh.nInternalFaces()] = cellCentres[own[facei]];
388  }
389 
391 
392  scalar minDDotS = GREAT;
393 
394  scalar sumDDotS = 0;
395  label nDDotS = 0;
396 
397  label severeNonOrth = 0;
398 
399  label errorNonOrth = 0;
400 
401  for (const label facei : checkFaces)
402  {
403  const point& ownCc = cellCentres[own[facei]];
404 
405  if (mesh.isInternalFace(facei))
406  {
407  scalar dDotS = checkNonOrtho
408  (
409  mesh,
410  report,
411  severeNonorthogonalityThreshold,
412  facei,
413  faceAreas[facei],
414  cellCentres[nei[facei]] - ownCc,
415 
416  severeNonOrth,
417  errorNonOrth,
418  setPtr
419  );
420 
421  if (dDotS < minDDotS)
422  {
423  minDDotS = dDotS;
424  }
425 
426  sumDDotS += dDotS;
427  ++nDDotS;
428  }
429  else
430  {
431  const label patchi = patches.whichPatch(facei);
432 
433  if (patches[patchi].coupled())
434  {
435  scalar dDotS = checkNonOrtho
436  (
437  mesh,
438  report,
439  severeNonorthogonalityThreshold,
440  facei,
441  faceAreas[facei],
442  neiCc[facei-mesh.nInternalFaces()] - ownCc,
443 
444  severeNonOrth,
445  errorNonOrth,
446  setPtr
447  );
448 
449  if (dDotS < minDDotS)
450  {
451  minDDotS = dDotS;
452  }
453 
454  sumDDotS += dDotS;
455  ++nDDotS;
456  }
457  }
458  }
459 
460  for (const labelPair& baffle : baffles)
461  {
462  const label face0 = baffle.first();
463  const label face1 = baffle.second();
464 
465  const point& ownCc = cellCentres[own[face0]];
466 
467  scalar dDotS = checkNonOrtho
468  (
469  mesh,
470  report,
471  severeNonorthogonalityThreshold,
472  face0,
473  faceAreas[face0],
474  cellCentres[own[face1]] - ownCc,
475 
476  severeNonOrth,
477  errorNonOrth,
478  setPtr
479  );
480 
481  if (dDotS < minDDotS)
482  {
483  minDDotS = dDotS;
484  }
485 
486  sumDDotS += dDotS;
487  ++nDDotS;
488  }
489 
490  reduce(minDDotS, minOp<scalar>());
491  reduce(sumDDotS, sumOp<scalar>());
492  reduce(nDDotS, sumOp<label>());
493  reduce(severeNonOrth, sumOp<label>());
494  reduce(errorNonOrth, sumOp<label>());
495 
496  // Only report if there are some internal faces
497  if (nDDotS > 0)
498  {
499  if (report && minDDotS < severeNonorthogonalityThreshold)
500  {
501  Info<< "Number of non-orthogonality errors: " << errorNonOrth
502  << ". Number of severely non-orthogonal faces: "
503  << severeNonOrth << "." << endl;
504  }
505  }
506 
507  if (report)
508  {
509  if (nDDotS > 0)
510  {
511  Info<< "Mesh non-orthogonality Max: "
512  << radToDeg(::acos(minDDotS))
513  << " average: " << radToDeg(::acos(sumDDotS/nDDotS))
514  << endl;
515  }
516  }
517 
518  if (errorNonOrth > 0)
519  {
520  if (report)
521  {
523  << "Error in non-orthogonality detected" << endl;
524  }
525 
526  return true;
527  }
528 
529  if (report)
530  {
531  Info<< "Non-orthogonality check OK.\n" << endl;
532  }
533 
534  return false;
535 }
536 
537 
539 (
540  const bool report,
541  const scalar minPyrVol,
542  const polyMesh& mesh,
543  const vectorField& cellCentres,
544  const pointField& p,
545  const labelList& checkFaces,
546  const List<labelPair>& baffles,
547  labelHashSet* setPtr
548 )
549 {
550  // check whether face area vector points to the cell with higher label
551  const labelList& own = mesh.faceOwner();
552  const labelList& nei = mesh.faceNeighbour();
553 
554  const faceList& f = mesh.faces();
555 
556  label nErrorPyrs = 0;
557 
558  for (const label facei : checkFaces)
559  {
560  // Create the owner pyramid - it will have negative volume
561  scalar pyrVol = pyramidPointFaceRef
562  (
563  f[facei],
564  cellCentres[own[facei]]
565  ).mag(p);
566 
567  if (pyrVol > -minPyrVol)
568  {
569  ++nErrorPyrs;
570 
571  if (report)
572  {
573  Pout<< "bool polyMeshGeometry::checkFacePyramids("
574  << "const bool, const scalar, const pointField&"
575  << ", const labelList&, labelHashSet*): "
576  << "face " << facei << " points the wrong way. " << endl
577  << "Pyramid volume: " << -pyrVol
578  << " Face " << f[facei] << " area: " << f[facei].mag(p)
579  << " Owner cell: " << own[facei] << endl
580  << "Owner cell vertex labels: "
581  << mesh.cells()[own[facei]].labels(f)
582  << endl;
583  }
584  if (setPtr)
585  {
586  setPtr->insert(facei);
587  }
588  }
589 
590  if (mesh.isInternalFace(facei))
591  {
592  // Create the neighbour pyramid - it will have positive volume
593  scalar pyrVol =
594  pyramidPointFaceRef(f[facei], cellCentres[nei[facei]]).mag(p);
595 
596  if (pyrVol < minPyrVol)
597  {
598  ++nErrorPyrs;
599 
600  if (report)
601  {
602  Pout<< "bool polyMeshGeometry::checkFacePyramids("
603  << "const bool, const scalar, const pointField&"
604  << ", const labelList&, labelHashSet*): "
605  << "face " << facei << " points the wrong way. " << endl
606  << "Pyramid volume: " << -pyrVol
607  << " Face " << f[facei] << " area: " << f[facei].mag(p)
608  << " Neighbour cell: " << nei[facei] << endl
609  << "Neighbour cell vertex labels: "
610  << mesh.cells()[nei[facei]].labels(f)
611  << endl;
612  }
613  if (setPtr)
614  {
615  setPtr->insert(facei);
616  }
617  }
618  }
619  }
620 
621  for (const labelPair& baffle : baffles)
622  {
623  const label face0 = baffle.first();
624  const label face1 = baffle.second();
625 
626  const point& ownCc = cellCentres[own[face0]];
627 
628  // Create the owner pyramid - it will have negative volume
629  scalar pyrVolOwn = pyramidPointFaceRef
630  (
631  f[face0],
632  ownCc
633  ).mag(p);
634 
635  if (pyrVolOwn > -minPyrVol)
636  {
637  ++nErrorPyrs;
638 
639  if (report)
640  {
641  Pout<< "bool polyMeshGeometry::checkFacePyramids("
642  << "const bool, const scalar, const pointField&"
643  << ", const labelList&, labelHashSet*): "
644  << "face " << face0 << " points the wrong way. " << endl
645  << "Pyramid volume: " << -pyrVolOwn
646  << " Face " << f[face0] << " area: " << f[face0].mag(p)
647  << " Owner cell: " << own[face0] << endl
648  << "Owner cell vertex labels: "
649  << mesh.cells()[own[face0]].labels(f)
650  << endl;
651  }
652  if (setPtr)
653  {
654  setPtr->insert(face0);
655  }
656  }
657 
658  // Create the neighbour pyramid - it will have positive volume
659  scalar pyrVolNbr =
660  pyramidPointFaceRef(f[face0], cellCentres[own[face1]]).mag(p);
661 
662  if (pyrVolNbr < minPyrVol)
663  {
664  ++nErrorPyrs;
665 
666  if (report)
667  {
668  Pout<< "bool polyMeshGeometry::checkFacePyramids("
669  << "const bool, const scalar, const pointField&"
670  << ", const labelList&, labelHashSet*): "
671  << "face " << face0 << " points the wrong way. " << endl
672  << "Pyramid volume: " << -pyrVolNbr
673  << " Face " << f[face0] << " area: " << f[face0].mag(p)
674  << " Neighbour cell: " << own[face1] << endl
675  << "Neighbour cell vertex labels: "
676  << mesh.cells()[own[face1]].labels(f)
677  << endl;
678  }
679  if (setPtr)
680  {
681  setPtr->insert(face0);
682  }
683  }
684  }
685 
686  reduce(nErrorPyrs, sumOp<label>());
687 
688  if (nErrorPyrs > 0)
689  {
690  if (report)
691  {
693  << "Error in face pyramids: faces pointing the wrong way."
694  << endl;
695  }
696 
697  return true;
698  }
699 
700  if (report)
701  {
702  Info<< "Face pyramids OK.\n" << endl;
703  }
704 
705  return false;
706 }
707 
708 
710 (
711  const bool report,
712  const scalar minTetQuality,
713  const polyMesh& mesh,
714  const vectorField& cellCentres,
715  const vectorField& faceCentres,
716  const pointField& p,
717  const labelList& checkFaces,
718  const List<labelPair>& baffles,
719  labelHashSet* setPtr
720 )
721 {
722  // check whether decomposing each cell into tets results in
723  // positive volume, non-flat tets
724  const labelList& own = mesh.faceOwner();
725  const labelList& nei = mesh.faceNeighbour();
727 
728  // Calculate coupled cell centre
729  pointField neiCc(mesh.nBoundaryFaces());
730 
731  for (label facei = mesh.nInternalFaces(); facei < mesh.nFaces(); ++facei)
732  {
733  neiCc[facei - mesh.nInternalFaces()] = cellCentres[own[facei]];
734  }
735 
737 
738  label nErrorTets = 0;
739 
740  for (const label facei : checkFaces)
741  {
742  // Create the owner pyramid - note: exchange cell and face centre
743  // to get positive volume.
744  bool tetError = checkFaceTet
745  (
746  mesh,
747  report,
748  minTetQuality,
749  p,
750  facei,
751  cellCentres[own[facei]], // face centre
752  faceCentres[facei], // cell centre
753  setPtr
754  );
755 
756  if (tetError)
757  {
758  ++nErrorTets;
759  }
760 
761  if (mesh.isInternalFace(facei))
762  {
763  // Create the neighbour tets - they will have positive volume
764  bool tetError = checkFaceTet
765  (
766  mesh,
767  report,
768  minTetQuality,
769  p,
770  facei,
771  faceCentres[facei], // face centre
772  cellCentres[nei[facei]], // cell centre
773  setPtr
774  );
775 
776  if (tetError)
777  {
778  ++nErrorTets;
779  }
780 
781  if
782  (
784  (
785  mesh,
786  facei,
787  minTetQuality,
788  report
789  ) == -1
790  )
791  {
792  ++nErrorTets;
793  if (setPtr)
794  {
795  setPtr->insert(facei);
796  }
797  }
798  }
799  else
800  {
801  label patchi = patches.whichPatch(facei);
802 
803  if (patches[patchi].coupled())
804  {
805  if
806  (
808  (
809  mesh,
810  facei,
811  neiCc[facei - mesh.nInternalFaces()],
812  minTetQuality,
813  report
814  ) == -1
815  )
816  {
817  ++nErrorTets;
818  if (setPtr)
819  {
820  setPtr->insert(facei);
821  }
822  }
823  }
824  else
825  {
826  if
827  (
829  (
830  mesh,
831  facei,
832  minTetQuality,
833  report
834  ) == -1
835  )
836  {
837  ++nErrorTets;
838  if (setPtr)
839  {
840  setPtr->insert(facei);
841  }
842  }
843  }
844  }
845  }
846 
847  for (const labelPair& baffle : baffles)
848  {
849  const label face0 = baffle.first();
850  const label face1 = baffle.second();
851 
852  bool tetError = checkFaceTet
853  (
854  mesh,
855  report,
856  minTetQuality,
857  p,
858  face0,
859  cellCentres[own[face0]], // face centre
860  faceCentres[face0], // cell centre
861  setPtr
862  );
863 
864  if (tetError)
865  {
866  ++nErrorTets;
867  }
868 
869  // Create the neighbour tets - they will have positive volume
870  tetError = checkFaceTet
871  (
872  mesh,
873  report,
874  minTetQuality,
875  p,
876  face0,
877  faceCentres[face0], // face centre
878  cellCentres[own[face1]], // cell centre
879  setPtr
880  );
881 
882  if (tetError)
883  {
884  ++nErrorTets;
885  }
886 
887  if
888  (
890  (
891  mesh,
892  face0,
893  cellCentres[own[face1]],
894  minTetQuality,
895  report
896  ) == -1
897  )
898  {
899  ++nErrorTets;
900  if (setPtr)
901  {
902  setPtr->insert(face0);
903  }
904  }
905  }
906 
907  reduce(nErrorTets, sumOp<label>());
908 
909  if (nErrorTets > 0)
910  {
911  if (report)
912  {
914  << "Error in face decomposition: negative tets."
915  << endl;
916  }
917 
918  return true;
919  }
920 
921  if (report)
922  {
923  Info<< "Face tets OK.\n" << endl;
924  }
925 
926  return false;
927 }
928 
929 
931 (
932  const bool report,
933  const scalar internalSkew,
934  const scalar boundarySkew,
935  const polyMesh& mesh,
936  const pointField& points,
937  const vectorField& cellCentres,
938  const vectorField& faceCentres,
939  const vectorField& faceAreas,
940  const labelList& checkFaces,
941  const List<labelPair>& baffles,
942  labelHashSet* setPtr
943 )
944 {
945  // Warn if the skew correction vector is more than skew times
946  // larger than the face area vector
947 
948  const labelList& own = mesh.faceOwner();
949  const labelList& nei = mesh.faceNeighbour();
951 
952  // Calculate coupled cell centre
953  pointField neiCc;
954  syncTools::swapBoundaryCellPositions(mesh, cellCentres, neiCc);
955 
956  scalar maxSkew = 0;
957 
958  label nWarnSkew = 0;
959 
960  for (const label facei : checkFaces)
961  {
962  if (mesh.isInternalFace(facei))
963  {
964  scalar skewness = primitiveMeshTools::faceSkewness
965  (
966  mesh,
967  points,
968  faceCentres,
969  faceAreas,
970 
971  facei,
972  cellCentres[own[facei]],
973  cellCentres[nei[facei]]
974  );
975 
976  // Check if the skewness vector is greater than the PN vector.
977  // This does not cause trouble but is a good indication of a poor
978  // mesh.
979  if (skewness > internalSkew)
980  {
981  ++nWarnSkew;
982 
983  if (report)
984  {
985  Pout<< "Severe skewness for face " << facei
986  << " skewness = " << skewness << endl;
987  }
988  if (setPtr)
989  {
990  setPtr->insert(facei);
991  }
992  }
993 
994  maxSkew = max(maxSkew, skewness);
995  }
996  else if (patches[patches.whichPatch(facei)].coupled())
997  {
998  scalar skewness = primitiveMeshTools::faceSkewness
999  (
1000  mesh,
1001  points,
1002  faceCentres,
1003  faceAreas,
1004 
1005  facei,
1006  cellCentres[own[facei]],
1007  neiCc[facei-mesh.nInternalFaces()]
1008  );
1009 
1010  // Check if the skewness vector is greater than the PN vector.
1011  // This does not cause trouble but is a good indication of a poor
1012  // mesh.
1013  if (skewness > internalSkew)
1014  {
1015  ++nWarnSkew;
1016 
1017  if (report)
1018  {
1019  Pout<< "Severe skewness for coupled face " << facei
1020  << " skewness = " << skewness << endl;
1021  }
1022  if (setPtr)
1023  {
1024  setPtr->insert(facei);
1025  }
1026  }
1027 
1028  maxSkew = max(maxSkew, skewness);
1029  }
1030  else
1031  {
1033  (
1034  mesh,
1035  points,
1036  faceCentres,
1037  faceAreas,
1038 
1039  facei,
1040  cellCentres[own[facei]]
1041  );
1042 
1043 
1044  // Check if the skewness vector is greater than the PN vector.
1045  // This does not cause trouble but is a good indication of a poor
1046  // mesh.
1047  if (skewness > boundarySkew)
1048  {
1049  ++nWarnSkew;
1050 
1051  if (report)
1052  {
1053  Pout<< "Severe skewness for boundary face " << facei
1054  << " skewness = " << skewness << endl;
1055  }
1056  if (setPtr)
1057  {
1058  setPtr->insert(facei);
1059  }
1060  }
1061 
1062  maxSkew = max(maxSkew, skewness);
1063  }
1064  }
1065 
1066  for (const labelPair& baffle : baffles)
1067  {
1068  const label face0 = baffle.first();
1069  const label face1 = baffle.second();
1070 
1071  const point& ownCc = cellCentres[own[face0]];
1072  const point& neiCc = cellCentres[own[face1]];
1073 
1074  scalar skewness = primitiveMeshTools::faceSkewness
1075  (
1076  mesh,
1077  points,
1078  faceCentres,
1079  faceAreas,
1080 
1081  face0,
1082  ownCc,
1083  neiCc
1084  );
1085 
1086  // Check if the skewness vector is greater than the PN vector.
1087  // This does not cause trouble but is a good indication of a poor
1088  // mesh.
1089  if (skewness > internalSkew)
1090  {
1091  ++nWarnSkew;
1092 
1093  if (report)
1094  {
1095  Pout<< "Severe skewness for face " << face0
1096  << " skewness = " << skewness << endl;
1097  }
1098  if (setPtr)
1099  {
1100  setPtr->insert(face0);
1101  }
1102  }
1103 
1104  maxSkew = max(maxSkew, skewness);
1105  }
1106 
1107 
1108  reduce(maxSkew, maxOp<scalar>());
1109  reduce(nWarnSkew, sumOp<label>());
1110 
1111  if (nWarnSkew > 0)
1112  {
1113  if (report)
1114  {
1116  << 100*maxSkew
1117  << " percent.\nThis may impair the quality of the result." << nl
1118  << nWarnSkew << " highly skew faces detected."
1119  << endl;
1120  }
1121 
1122  return true;
1123  }
1124 
1125  if (report)
1126  {
1127  Info<< "Max skewness = " << 100*maxSkew
1128  << " percent. Face skewness OK.\n" << endl;
1129  }
1130 
1131  return false;
1132 }
1133 
1134 
1137  const bool report,
1138  const scalar warnWeight,
1139  const polyMesh& mesh,
1140  const vectorField& cellCentres,
1141  const vectorField& faceCentres,
1142  const vectorField& faceAreas,
1143  const labelList& checkFaces,
1144  const List<labelPair>& baffles,
1145  labelHashSet* setPtr
1146 )
1147 {
1148  // Warn if the delta factor (0..1) is too large.
1149 
1150  const labelList& own = mesh.faceOwner();
1151  const labelList& nei = mesh.faceNeighbour();
1153 
1154  // Calculate coupled cell centre
1155  pointField neiCc(mesh.nBoundaryFaces());
1156 
1157  for (label facei = mesh.nInternalFaces(); facei < mesh.nFaces(); ++facei)
1158  {
1159  neiCc[facei-mesh.nInternalFaces()] = cellCentres[own[facei]];
1160  }
1162 
1163 
1164  scalar minWeight = GREAT;
1165 
1166  label nWarnWeight = 0;
1167 
1168  for (const label facei : checkFaces)
1169  {
1170  const point& fc = faceCentres[facei];
1171  const vector& fa = faceAreas[facei];
1172 
1173  scalar dOwn = mag(fa & (fc-cellCentres[own[facei]]));
1174 
1175  if (mesh.isInternalFace(facei))
1176  {
1177  scalar dNei = mag(fa & (cellCentres[nei[facei]]-fc));
1178  scalar weight = min(dNei,dOwn)/(dNei+dOwn+VSMALL);
1179 
1180  if (weight < warnWeight)
1181  {
1182  ++nWarnWeight;
1183 
1184  if (report)
1185  {
1186  Pout<< "Small weighting factor for face " << facei
1187  << " weight = " << weight << endl;
1188  }
1189  if (setPtr)
1190  {
1191  setPtr->insert(facei);
1192  }
1193  }
1194 
1195  minWeight = min(minWeight, weight);
1196  }
1197  else
1198  {
1199  label patchi = patches.whichPatch(facei);
1200 
1201  if (patches[patchi].coupled())
1202  {
1203  scalar dNei = mag(fa & (neiCc[facei-mesh.nInternalFaces()]-fc));
1204  scalar weight = min(dNei,dOwn)/(dNei+dOwn+VSMALL);
1205 
1206  if (weight < warnWeight)
1207  {
1208  ++nWarnWeight;
1209 
1210  if (report)
1211  {
1212  Pout<< "Small weighting factor for face " << facei
1213  << " weight = " << weight << endl;
1214  }
1215  if (setPtr)
1216  {
1217  setPtr->insert(facei);
1218  }
1219  }
1220 
1221  minWeight = min(minWeight, weight);
1222  }
1223  }
1224  }
1225 
1226  for (const labelPair& baffle : baffles)
1227  {
1228  const label face0 = baffle.first();
1229  const label face1 = baffle.second();
1230 
1231  const point& ownCc = cellCentres[own[face0]];
1232  const point& fc = faceCentres[face0];
1233  const vector& fa = faceAreas[face0];
1234 
1235  scalar dOwn = mag(fa & (fc-ownCc));
1236  scalar dNei = mag(fa & (cellCentres[own[face1]]-fc));
1237  scalar weight = min(dNei,dOwn)/(dNei+dOwn+VSMALL);
1238 
1239  if (weight < warnWeight)
1240  {
1241  ++nWarnWeight;
1242 
1243  if (report)
1244  {
1245  Pout<< "Small weighting factor for face " << face0
1246  << " weight = " << weight << endl;
1247  }
1248  if (setPtr)
1249  {
1250  setPtr->insert(face0);
1251  }
1252  }
1253 
1254  minWeight = min(minWeight, weight);
1255  }
1256 
1257  reduce(minWeight, minOp<scalar>());
1258  reduce(nWarnWeight, sumOp<label>());
1259 
1260  if (minWeight < warnWeight)
1261  {
1262  if (report)
1263  {
1265  << minWeight << '.' << nl
1266  << nWarnWeight << " faces with small weights detected."
1267  << endl;
1268  }
1269 
1270  return true;
1271  }
1272 
1273  if (report)
1274  {
1275  Info<< "Min weight = " << minWeight
1276  << ". Weights OK.\n" << endl;
1277  }
1278 
1279  return false;
1280 }
1281 
1282 
1285  const bool report,
1286  const scalar warnRatio,
1287  const polyMesh& mesh,
1288  const scalarField& cellVolumes,
1289  const labelList& checkFaces,
1290  const List<labelPair>& baffles,
1291  labelHashSet* setPtr
1292 )
1293 {
1294  // Warn if the volume ratio between neighbouring cells is too large
1295 
1296  const labelList& own = mesh.faceOwner();
1297  const labelList& nei = mesh.faceNeighbour();
1299 
1300  // Calculate coupled cell vol
1301  scalarField neiVols(mesh.nBoundaryFaces());
1302 
1303  for (label facei = mesh.nInternalFaces(); facei < mesh.nFaces(); ++facei)
1304  {
1305  neiVols[facei-mesh.nInternalFaces()] = cellVolumes[own[facei]];
1306  }
1308 
1309 
1310  scalar minRatio = GREAT;
1311 
1312  label nWarnRatio = 0;
1313 
1314  for (const label facei : checkFaces)
1315  {
1316  scalar ownVol = mag(cellVolumes[own[facei]]);
1317 
1318  scalar neiVol = -GREAT;
1319 
1320  if (mesh.isInternalFace(facei))
1321  {
1322  neiVol = mag(cellVolumes[nei[facei]]);
1323  }
1324  else
1325  {
1326  label patchi = patches.whichPatch(facei);
1327 
1328  if (patches[patchi].coupled())
1329  {
1330  neiVol = mag(neiVols[facei-mesh.nInternalFaces()]);
1331  }
1332  }
1333 
1334  if (neiVol >= 0)
1335  {
1336  scalar ratio = min(ownVol, neiVol) / (max(ownVol, neiVol) + VSMALL);
1337 
1338  if (ratio < warnRatio)
1339  {
1340  ++nWarnRatio;
1341 
1342  if (report)
1343  {
1344  Pout<< "Small ratio for face " << facei
1345  << " ratio = " << ratio << endl;
1346  }
1347  if (setPtr)
1348  {
1349  setPtr->insert(facei);
1350  }
1351  }
1352 
1353  minRatio = min(minRatio, ratio);
1354  }
1355  }
1356 
1357  for (const labelPair& baffle : baffles)
1358  {
1359  const label face0 = baffle.first();
1360  const label face1 = baffle.second();
1361 
1362  scalar ownVol = mag(cellVolumes[own[face0]]);
1363 
1364  scalar neiVol = mag(cellVolumes[own[face1]]);
1365 
1366  if (neiVol >= 0)
1367  {
1368  scalar ratio = min(ownVol, neiVol) / (max(ownVol, neiVol) + VSMALL);
1369 
1370  if (ratio < warnRatio)
1371  {
1372  ++nWarnRatio;
1373 
1374  if (report)
1375  {
1376  Pout<< "Small ratio for face " << face0
1377  << " ratio = " << ratio << endl;
1378  }
1379  if (setPtr)
1380  {
1381  setPtr->insert(face0);
1382  }
1383  }
1384 
1385  minRatio = min(minRatio, ratio);
1386  }
1387  }
1388 
1389  reduce(minRatio, minOp<scalar>());
1390  reduce(nWarnRatio, sumOp<label>());
1391 
1392  if (minRatio < warnRatio)
1393  {
1394  if (report)
1395  {
1397  << minRatio << '.' << nl
1398  << nWarnRatio << " faces with small ratios detected."
1399  << endl;
1400  }
1401 
1402  return true;
1403  }
1404 
1405  if (report)
1406  {
1407  Info<< "Min ratio = " << minRatio
1408  << ". Ratios OK.\n" << endl;
1409  }
1410 
1411  return false;
1412 }
1413 
1414 
1415 // Check convexity of angles in a face. Allow a slight non-convexity.
1416 // E.g. maxDeg = 10 allows for angles < 190 (or 10 degrees concavity)
1417 // (if truly concave and points not visible from face centre the face-pyramid
1418 // check in checkMesh will fail)
1421  const bool report,
1422  const scalar maxDeg,
1423  const polyMesh& mesh,
1424  const vectorField& faceAreas,
1425  const pointField& p,
1426  const labelList& checkFaces,
1427  labelHashSet* setPtr
1428 )
1429 {
1430  if (maxDeg < -SMALL || maxDeg > 180+SMALL)
1431  {
1433  << "maxDeg should be [0..180] but is now " << maxDeg
1434  << abort(FatalError);
1435  }
1436 
1437  const scalar maxSin = Foam::sin(degToRad(maxDeg));
1438 
1439  const faceList& fcs = mesh.faces();
1440 
1441  scalar maxEdgeSin = 0.0;
1442 
1443  label nConcave = 0;
1444 
1445  label errorFacei = -1;
1446 
1447  for (const label facei : checkFaces)
1448  {
1449  const face& f = fcs[facei];
1450 
1451  const vector faceNormal = normalised(faceAreas[facei]);
1452 
1453  // Get edge from f[0] to f[size-1];
1454  vector ePrev(p[f.first()] - p[f.last()]);
1455  scalar magEPrev = mag(ePrev);
1456  ePrev /= magEPrev + VSMALL;
1457 
1458  forAll(f, fp0)
1459  {
1460  // Get vertex after fp
1461  label fp1 = f.fcIndex(fp0);
1462 
1463  // Normalized vector between two consecutive points
1464  vector e10(p[f[fp1]] - p[f[fp0]]);
1465  scalar magE10 = mag(e10);
1466  e10 /= magE10 + VSMALL;
1467 
1468  if (magEPrev > SMALL && magE10 > SMALL)
1469  {
1470  vector edgeNormal = ePrev ^ e10;
1471  scalar magEdgeNormal = mag(edgeNormal);
1472 
1473  if (magEdgeNormal < maxSin)
1474  {
1475  // Edges (almost) aligned -> face is ok.
1476  }
1477  else
1478  {
1479  // Check normal
1480  edgeNormal /= magEdgeNormal;
1481 
1482  if ((edgeNormal & faceNormal) < SMALL)
1483  {
1484  if (facei != errorFacei)
1485  {
1486  // Count only one error per face.
1487  errorFacei = facei;
1488  ++nConcave;
1489  }
1490 
1491  maxEdgeSin = max(maxEdgeSin, magEdgeNormal);
1492 
1493  if (setPtr)
1494  {
1495  setPtr->insert(facei);
1496  }
1497  }
1498  }
1499  }
1500 
1501  ePrev = e10;
1502  magEPrev = magE10;
1503  }
1504  }
1505 
1506  reduce(nConcave, sumOp<label>());
1507  reduce(maxEdgeSin, maxOp<scalar>());
1508 
1509  if (report)
1510  {
1511  if (maxEdgeSin > SMALL)
1512  {
1513  scalar maxConcaveDegr =
1514  radToDeg(Foam::asin(Foam::min(1.0, maxEdgeSin)));
1515 
1516  Info<< "There are " << nConcave
1517  << " faces with concave angles between consecutive"
1518  << " edges. Max concave angle = " << maxConcaveDegr
1519  << " degrees.\n" << endl;
1520  }
1521  else
1522  {
1523  Info<< "All angles in faces are convex or less than " << maxDeg
1524  << " degrees concave.\n" << endl;
1525  }
1526  }
1527 
1528  if (nConcave > 0)
1529  {
1530  if (report)
1531  {
1533  << nConcave << " face points with severe concave angle (> "
1534  << maxDeg << " deg) found.\n"
1535  << endl;
1536  }
1537 
1538  return true;
1539  }
1540 
1541  return false;
1542 }
1543 
1544 
1545 // Check twist of faces. Is calculated as the difference between normals of
1546 // individual triangles and the cell-cell centre edge.
1549  const bool report,
1550  const scalar minTwist,
1551  const polyMesh& mesh,
1552  const vectorField& cellCentres,
1553  const vectorField& faceAreas,
1554  const vectorField& faceCentres,
1555  const pointField& p,
1556  const labelList& checkFaces,
1557  labelHashSet* setPtr
1558 )
1559 {
1560  if (minTwist < -1-SMALL || minTwist > 1+SMALL)
1561  {
1563  << "minTwist should be [-1..1] but is now " << minTwist
1564  << abort(FatalError);
1565  }
1566 
1567 
1568  const faceList& fcs = mesh.faces();
1569 
1570  label nWarped = 0;
1571 
1572  const labelList& own = mesh.faceOwner();
1573  const labelList& nei = mesh.faceNeighbour();
1575 
1576  // Calculate coupled cell centre
1577  pointField neiCc(mesh.nBoundaryFaces());
1578 
1579  for (label facei = mesh.nInternalFaces(); facei < mesh.nFaces(); ++facei)
1580  {
1581  neiCc[facei-mesh.nInternalFaces()] = cellCentres[own[facei]];
1582  }
1584 
1585  for (const label facei : checkFaces)
1586  {
1587  const face& f = fcs[facei];
1588 
1589  if (f.size() > 3)
1590  {
1591  vector nf(Zero);
1592 
1593  if (mesh.isInternalFace(facei))
1594  {
1595  nf =
1596  normalised
1597  (
1598  cellCentres[nei[facei]]
1599  - cellCentres[own[facei]]
1600  );
1601  }
1602  else if (patches[patches.whichPatch(facei)].coupled())
1603  {
1604  nf =
1605  normalised
1606  (
1607  neiCc[facei-mesh.nInternalFaces()]
1608  - cellCentres[own[facei]]
1609  );
1610  }
1611  else
1612  {
1613  nf =
1614  normalised
1615  (
1616  faceCentres[facei]
1617  - cellCentres[own[facei]]
1618  );
1619  }
1620 
1621  if (nf != vector::zero)
1622  {
1623  const point& fc = faceCentres[facei];
1624 
1625  forAll(f, fpI)
1626  {
1627  vector triArea
1628  (
1629  triPointRef
1630  (
1631  p[f[fpI]],
1632  p[f.nextLabel(fpI)],
1633  fc
1634  ).areaNormal()
1635  );
1636 
1637  scalar magTri = mag(triArea);
1638 
1639  if (magTri > VSMALL && ((nf & triArea/magTri) < minTwist))
1640  {
1641  ++nWarped;
1642 
1643  if (setPtr)
1644  {
1645  setPtr->insert(facei);
1646  }
1647 
1648  break;
1649  }
1650  }
1651  }
1652  }
1653  }
1654 
1655  reduce(nWarped, sumOp<label>());
1656 
1657  if (report)
1658  {
1659  if (nWarped> 0)
1660  {
1661  Info<< "There are " << nWarped
1662  << " faces with cosine of the angle"
1663  << " between triangle normal and face normal less than "
1664  << minTwist << nl << endl;
1665  }
1666  else
1667  {
1668  Info<< "All faces are flat in that the cosine of the angle"
1669  << " between triangle normal and face normal less than "
1670  << minTwist << nl << endl;
1671  }
1672  }
1673 
1674  if (nWarped > 0)
1675  {
1676  if (report)
1677  {
1679  << nWarped << " faces with severe warpage "
1680  << "(cosine of the angle between triangle normal and "
1681  << "face normal < " << minTwist << ") found.\n"
1682  << endl;
1683  }
1684 
1685  return true;
1686  }
1687 
1688  return false;
1689 }
1690 
1691 
1692 // Like checkFaceTwist but compares normals of consecutive triangles.
1695  const bool report,
1696  const scalar minTwist,
1697  const polyMesh& mesh,
1698  const vectorField& faceAreas,
1699  const vectorField& faceCentres,
1700  const pointField& p,
1701  const labelList& checkFaces,
1702  labelHashSet* setPtr
1703 )
1704 {
1705  if (minTwist < -1-SMALL || minTwist > 1+SMALL)
1706  {
1708  << "minTwist should be [-1..1] but is now " << minTwist
1709  << abort(FatalError);
1710  }
1711 
1712  const faceList& fcs = mesh.faces();
1713 
1714  label nWarped = 0;
1715 
1716  for (const label facei : checkFaces)
1717  {
1718  const face& f = fcs[facei];
1719 
1720  if (f.size() > 3)
1721  {
1722  const point& fc = faceCentres[facei];
1723 
1724  // Find starting triangle (at startFp) with non-zero area
1725  label startFp = -1;
1726  vector prevN;
1727 
1728  forAll(f, fp)
1729  {
1730  prevN = triPointRef
1731  (
1732  p[f[fp]],
1733  p[f.nextLabel(fp)],
1734  fc
1735  ).areaNormal();
1736 
1737  scalar magTri = mag(prevN);
1738 
1739  if (magTri > VSMALL)
1740  {
1741  startFp = fp;
1742  prevN /= magTri;
1743  break;
1744  }
1745  }
1746 
1747  if (startFp != -1)
1748  {
1749  label fp = startFp;
1750 
1751  do
1752  {
1753  fp = f.fcIndex(fp);
1754 
1755  vector triN
1756  (
1757  triPointRef
1758  (
1759  p[f[fp]],
1760  p[f.nextLabel(fp)],
1761  fc
1762  ).areaNormal()
1763  );
1764  scalar magTri = mag(triN);
1765 
1766  if (magTri > VSMALL)
1767  {
1768  triN /= magTri;
1769 
1770  if ((prevN & triN) < minTwist)
1771  {
1772  ++nWarped;
1773 
1774  if (setPtr)
1775  {
1776  setPtr->insert(facei);
1777  }
1778 
1779  break;
1780  }
1781 
1782  prevN = triN;
1783  }
1784  else if (minTwist > 0)
1785  {
1786  ++nWarped;
1787 
1788  if (setPtr)
1789  {
1790  setPtr->insert(facei);
1791  }
1792 
1793  break;
1794  }
1795  }
1796  while (fp != startFp);
1797  }
1798  }
1799  }
1800 
1801 
1802  reduce(nWarped, sumOp<label>());
1803 
1804  if (report)
1805  {
1806  if (nWarped> 0)
1807  {
1808  Info<< "There are " << nWarped
1809  << " faces with cosine of the angle"
1810  << " between consecutive triangle normals less than "
1811  << minTwist << nl << endl;
1812  }
1813  else
1814  {
1815  Info<< "All faces are flat in that the cosine of the angle"
1816  << " between consecutive triangle normals is less than "
1817  << minTwist << nl << endl;
1818  }
1819  }
1820 
1821  if (nWarped > 0)
1822  {
1823  if (report)
1824  {
1826  << nWarped << " faces with severe warpage "
1827  << "(cosine of the angle between consecutive triangle normals"
1828  << " < " << minTwist << ") found.\n"
1829  << endl;
1830  }
1831 
1832  return true;
1833  }
1834 
1835  return false;
1836 }
1837 
1838 
1841  const bool report,
1842  const scalar minFlatness,
1843  const polyMesh& mesh,
1844  const vectorField& faceAreas,
1845  const vectorField& faceCentres,
1846  const pointField& p,
1847  const labelList& checkFaces,
1848  labelHashSet* setPtr
1849 )
1850 {
1851  if (minFlatness < -SMALL || minFlatness > 1+SMALL)
1852  {
1854  << "minFlatness should be [0..1] but is now " << minFlatness
1855  << abort(FatalError);
1856  }
1857 
1858  const faceList& fcs = mesh.faces();
1859 
1860  label nWarped = 0;
1861 
1862  for (const label facei : checkFaces)
1863  {
1864  const face& f = fcs[facei];
1865 
1866  if (f.size() > 3)
1867  {
1868  const point& fc = faceCentres[facei];
1869 
1870  // Sum triangle areas
1871  scalar sumArea = 0.0;
1872 
1873  forAll(f, fp)
1874  {
1875  sumArea += triPointRef
1876  (
1877  p[f[fp]],
1878  p[f.nextLabel(fp)],
1879  fc
1880  ).mag();
1881  }
1882 
1883  if (sumArea/mag(faceAreas[facei]) < minFlatness)
1884  {
1885  ++nWarped;
1886  if (setPtr)
1887  {
1888  setPtr->insert(facei);
1889  }
1890  }
1891  }
1892  }
1893 
1894  reduce(nWarped, sumOp<label>());
1895 
1896  if (report)
1897  {
1898  if (nWarped> 0)
1899  {
1900  Info<< "There are " << nWarped
1901  << " faces with area of invidual triangles"
1902  << " compared to overall area less than "
1903  << minFlatness << nl << endl;
1904  }
1905  else
1906  {
1907  Info<< "All faces are flat in that the area of invidual triangles"
1908  << " compared to overall area is less than "
1909  << minFlatness << nl << endl;
1910  }
1911  }
1912 
1913  if (nWarped > 0)
1914  {
1915  if (report)
1916  {
1918  << nWarped << " non-flat faces "
1919  << "(area of invidual triangles"
1920  << " compared to overall area"
1921  << " < " << minFlatness << ") found.\n"
1922  << endl;
1923  }
1924 
1925  return true;
1926  }
1927 
1928  return false;
1929 }
1930 
1931 
1934  const bool report,
1935  const scalar minArea,
1936  const polyMesh& mesh,
1937  const vectorField& faceAreas,
1938  const labelList& checkFaces,
1939  labelHashSet* setPtr
1940 )
1941 {
1942  label nZeroArea = 0;
1943 
1944  for (const label facei : checkFaces)
1945  {
1946  if (mag(faceAreas[facei]) < minArea)
1947  {
1948  ++nZeroArea;
1949  if (setPtr)
1950  {
1951  setPtr->insert(facei);
1952  }
1953  }
1954  }
1955 
1956 
1957  reduce(nZeroArea, sumOp<label>());
1958 
1959  if (report)
1960  {
1961  if (nZeroArea > 0)
1962  {
1963  Info<< "There are " << nZeroArea
1964  << " faces with area < " << minArea << '.' << nl << endl;
1965  }
1966  else
1967  {
1968  Info<< "All faces have area > " << minArea << '.' << nl << endl;
1969  }
1970  }
1971 
1972  if (nZeroArea > 0)
1973  {
1974  if (report)
1975  {
1977  << nZeroArea << " faces with area < " << minArea
1978  << " found.\n"
1979  << endl;
1980  }
1981 
1982  return true;
1983  }
1984 
1985  return false;
1986 }
1987 
1988 
1991  const bool report,
1992  const scalar warnDet,
1993  const polyMesh& mesh,
1994  const vectorField& faceAreas,
1995  const labelList& checkFaces,
1996  const labelList& affectedCells,
1997  labelHashSet* setPtr
1998 )
1999 {
2000  const cellList& cells = mesh.cells();
2001 
2002  scalar minDet = GREAT;
2003  scalar sumDet = 0.0;
2004  label nSumDet = 0;
2005  label nWarnDet = 0;
2006 
2007  for (const label celli : affectedCells)
2008  {
2009  const cell& cFaces = cells[celli];
2010 
2011  tensor areaSum(Zero);
2012  scalar magAreaSum = 0;
2013 
2014  for (const label facei : cFaces)
2015  {
2016  scalar magArea = mag(faceAreas[facei]);
2017 
2018  magAreaSum += magArea;
2019  areaSum += faceAreas[facei]*(faceAreas[facei]/(magArea+VSMALL));
2020  }
2021 
2022  scalar scaledDet = det(areaSum/(magAreaSum+VSMALL))/0.037037037037037;
2023 
2024  minDet = min(minDet, scaledDet);
2025  sumDet += scaledDet;
2026  ++nSumDet;
2027 
2028  if (scaledDet < warnDet)
2029  {
2030  ++nWarnDet;
2031  if (setPtr)
2032  {
2033  setPtr->insert(cFaces); // Insert all faces of the cell
2034  }
2035  }
2036  }
2037 
2038  reduce(minDet, minOp<scalar>());
2039  reduce(sumDet, sumOp<scalar>());
2040  reduce(nSumDet, sumOp<label>());
2041  reduce(nWarnDet, sumOp<label>());
2042 
2043  if (report)
2044  {
2045  if (nSumDet > 0)
2046  {
2047  Info<< "Cell determinant (1 = uniform cube) : average = "
2048  << sumDet / nSumDet << " min = " << minDet << endl;
2049  }
2050 
2051  if (nWarnDet > 0)
2052  {
2053  Info<< "There are " << nWarnDet
2054  << " cells with determinant < " << warnDet << '.' << nl
2055  << endl;
2056  }
2057  else
2058  {
2059  Info<< "All faces have determinant > " << warnDet << '.' << nl
2060  << endl;
2061  }
2062  }
2063 
2064  if (nWarnDet > 0)
2065  {
2066  if (report)
2067  {
2069  << nWarnDet << " cells with determinant < " << warnDet
2070  << " found.\n"
2071  << endl;
2072  }
2073 
2074  return true;
2075  }
2076 
2077  return false;
2078 }
2079 
2080 
2083  const bool report,
2084  const scalar orthWarn,
2085  const labelList& checkFaces,
2086  const List<labelPair>& baffles,
2087  labelHashSet* setPtr
2088 ) const
2089 {
2090  return checkFaceDotProduct
2091  (
2092  report,
2093  orthWarn,
2094  mesh_,
2095  cellCentres_,
2096  faceAreas_,
2097  checkFaces,
2098  baffles,
2099  setPtr
2100  );
2101 }
2102 
2103 
2106  const bool report,
2107  const scalar minPyrVol,
2108  const pointField& p,
2109  const labelList& checkFaces,
2110  const List<labelPair>& baffles,
2111  labelHashSet* setPtr
2112 ) const
2113 {
2114  return checkFacePyramids
2115  (
2116  report,
2117  minPyrVol,
2118  mesh_,
2119  cellCentres_,
2120  p,
2121  checkFaces,
2122  baffles,
2123  setPtr
2124  );
2125 }
2126 
2127 
2130  const bool report,
2131  const scalar minTetQuality,
2132  const pointField& p,
2133  const labelList& checkFaces,
2134  const List<labelPair>& baffles,
2135  labelHashSet* setPtr
2136 ) const
2137 {
2138  return checkFaceTets
2139  (
2140  report,
2141  minTetQuality,
2142  mesh_,
2143  cellCentres_,
2144  faceCentres_,
2145  p,
2146  checkFaces,
2147  baffles,
2148  setPtr
2149  );
2150 }
2151 
2152 
2153 //bool Foam::polyMeshGeometry::checkFaceSkewness
2154 //(
2155 // const bool report,
2156 // const scalar internalSkew,
2157 // const scalar boundarySkew,
2158 // const labelList& checkFaces,
2159 // const List<labelPair>& baffles,
2160 // labelHashSet* setPtr
2161 //) const
2162 //{
2163 // return checkFaceSkewness
2164 // (
2165 // report,
2166 // internalSkew,
2167 // boundarySkew,
2168 // mesh_,
2169 // cellCentres_,
2170 // faceCentres_,
2171 // faceAreas_,
2172 // checkFaces,
2173 // baffles,
2174 // setPtr
2175 // );
2176 //}
2177 
2178 
2181  const bool report,
2182  const scalar warnWeight,
2183  const labelList& checkFaces,
2184  const List<labelPair>& baffles,
2185  labelHashSet* setPtr
2186 ) const
2187 {
2188  return checkFaceWeights
2189  (
2190  report,
2191  warnWeight,
2192  mesh_,
2193  cellCentres_,
2194  faceCentres_,
2195  faceAreas_,
2196  checkFaces,
2197  baffles,
2198  setPtr
2199  );
2200 }
2201 
2202 
2205  const bool report,
2206  const scalar warnRatio,
2207  const labelList& checkFaces,
2208  const List<labelPair>& baffles,
2209  labelHashSet* setPtr
2210 ) const
2211 {
2212  return checkVolRatio
2213  (
2214  report,
2215  warnRatio,
2216  mesh_,
2217  cellVolumes_,
2218  checkFaces,
2219  baffles,
2220  setPtr
2221  );
2222 }
2223 
2224 
2227  const bool report,
2228  const scalar maxDeg,
2229  const pointField& p,
2230  const labelList& checkFaces,
2231  labelHashSet* setPtr
2232 ) const
2233 {
2234  return checkFaceAngles
2235  (
2236  report,
2237  maxDeg,
2238  mesh_,
2239  faceAreas_,
2240  p,
2241  checkFaces,
2242  setPtr
2243  );
2244 }
2245 
2246 
2249  const bool report,
2250  const scalar minTwist,
2251  const pointField& p,
2252  const labelList& checkFaces,
2253  labelHashSet* setPtr
2254 ) const
2255 {
2256  return checkFaceTwist
2257  (
2258  report,
2259  minTwist,
2260  mesh_,
2261  cellCentres_,
2262  faceAreas_,
2263  faceCentres_,
2264  p,
2265  checkFaces,
2266  setPtr
2267  );
2268 }
2269 
2270 
2273  const bool report,
2274  const scalar minTwist,
2275  const pointField& p,
2276  const labelList& checkFaces,
2277  labelHashSet* setPtr
2278 ) const
2279 {
2280  return checkTriangleTwist
2281  (
2282  report,
2283  minTwist,
2284  mesh_,
2285  faceAreas_,
2286  faceCentres_,
2287  p,
2288  checkFaces,
2289  setPtr
2290  );
2291 }
2292 
2293 
2296  const bool report,
2297  const scalar minFlatness,
2298  const pointField& p,
2299  const labelList& checkFaces,
2300  labelHashSet* setPtr
2301 ) const
2302 {
2303  return checkFaceFlatness
2304  (
2305  report,
2306  minFlatness,
2307  mesh_,
2308  faceAreas_,
2309  faceCentres_,
2310  p,
2311  checkFaces,
2312  setPtr
2313  );
2314 }
2315 
2316 
2319  const bool report,
2320  const scalar minArea,
2321  const labelList& checkFaces,
2322  labelHashSet* setPtr
2323 ) const
2324 {
2325  return checkFaceArea
2326  (
2327  report,
2328  minArea,
2329  mesh_,
2330  faceAreas_,
2331  checkFaces,
2332  setPtr
2333  );
2334 }
2335 
2336 
2339  const bool report,
2340  const scalar warnDet,
2341  const labelList& checkFaces,
2342  const labelList& affectedCells,
2343  labelHashSet* setPtr
2344 ) const
2345 {
2346  return checkCellDeterminant
2347  (
2348  report,
2349  warnDet,
2350  mesh_,
2351  faceAreas_,
2352  checkFaces,
2353  affectedCells,
2354  setPtr
2355  );
2356 }
2357 
2358 
2359 // ************************************************************************* //
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:74
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
Foam::polyMeshGeometry::checkFaceDotProduct
static bool checkFaceDotProduct(const bool report, const scalar orthWarn, const polyMesh &, const vectorField &cellCentres, const vectorField &faceAreas, const labelList &checkFaces, const List< labelPair > &baffles, labelHashSet *setPtr)
See primitiveMesh.
Definition: polyMeshGeometry.C:361
Foam::Tensor< scalar >
Foam::maxOp
Definition: ops.H:223
p
volScalarField & p
Definition: createFieldRefs.H:8
s
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputSpray.H:25
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:62
primitiveMeshTools.H
Foam::Zero
static constexpr const zero Zero
Global zero.
Definition: zero.H:128
Foam::primitiveMesh::nInternalFaces
label nInternalFaces() const
Number of internal faces.
Definition: primitiveMeshI.H:78
polyMeshGeometry.H
Foam::minOp
Definition: ops.H:224
Foam::sin
dimensionedScalar sin(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:264
Foam::primitiveMesh::nFaces
label nFaces() const
Number of mesh faces.
Definition: primitiveMeshI.H:90
Foam::boundBox::invertedBox
static const boundBox invertedBox
A large inverted boundBox: min/max == +/- ROOTVGREAT.
Definition: boundBox.H:86
Foam::polyMeshGeometry::checkFaceWeights
static bool checkFaceWeights(const bool report, const scalar warnWeight, const polyMesh &mesh, const vectorField &cellCentres, const vectorField &faceCentres, const vectorField &faceAreas, const labelList &checkFaces, const List< labelPair > &baffles, labelHashSet *setPtr)
Interpolation weights (0.5 for regular mesh)
Definition: polyMeshGeometry.C:1136
Foam::VectorSpace::size
static constexpr direction size()
Return the number of elements in the VectorSpace = Ncmpts.
Definition: VectorSpaceI.H:92
Foam::primitiveMesh::cells
const cellList & cells() const
Definition: primitiveMeshCells.C:138
unitConversion.H
Unit conversion functions.
Foam::syncTools::swapBoundaryFaceList
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues)
Swap coupled boundary face values. Uses eqOp.
Definition: syncTools.H:439
tetPointRef.H
Foam::polyMeshGeometry::correct
void correct()
Take over properties from mesh.
Definition: polyMeshGeometry.C:338
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:435
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::polyMeshGeometry::checkFaceTets
static bool checkFaceTets(const bool report, const scalar minPyrVol, const polyMesh &, const vectorField &cellCentres, const vectorField &faceCentres, const pointField &p, const labelList &checkFaces, const List< labelPair > &baffles, labelHashSet *)
See primitiveMesh.
Definition: polyMeshGeometry.C:710
Foam::Pout
prefixOSstream Pout
An Ostream wrapper for parallel output to std::cout.
Foam::polyMeshGeometry::polyMeshGeometry
polyMeshGeometry(const polyMesh &)
Construct from mesh.
Definition: polyMeshGeometry.C:328
Foam::HashSet< label, Hash< label > >
syncTools.H
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::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
polyMeshTetDecomposition.H
Foam::sumOp
Definition: ops.H:213
Foam::tetPointRef
tetrahedron< point, const point & > tetPointRef
Definition: tetPointRef.H:46
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
Foam::polyMeshGeometry::checkFaceSkewness
static bool checkFaceSkewness(const bool report, const scalar internalSkew, const scalar boundarySkew, const polyMesh &mesh, const pointField &points, const vectorField &cellCentres, const vectorField &faceCentres, const vectorField &faceAreas, const labelList &checkFaces, const List< labelPair > &baffles, labelHashSet *setPtr)
See primitiveMesh.
Definition: polyMeshGeometry.C:931
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::polyMeshTetDecomposition::findSharedBasePoint
static label findSharedBasePoint(const polyMesh &mesh, label fI, const point &nCc, scalar tol, bool report=false)
Find the first suitable base point to use for a minimum.
Definition: polyMeshTetDecomposition.C:95
Foam::triangle
A triangle primitive used to calculate face normals and swept volumes.
Definition: triangle.H:62
n
label n
Definition: TABSMDCalcMethod2.H:31
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::polyMeshTetDecomposition::findBasePoint
static label findBasePoint(const polyMesh &mesh, label fI, scalar tol, bool report=false)
Find the base point to use for a minimum triangle.
Definition: polyMeshTetDecomposition.C:150
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::polyMeshGeometry::affectedCells
static labelList affectedCells(const polyMesh &, const labelList &changedFaces)
Helper function: get affected cells from faces.
Definition: polyMeshGeometry.C:183
Foam::polyMeshGeometry::checkFaceArea
static bool checkFaceArea(const bool report, const scalar minArea, const polyMesh &, const vectorField &faceAreas, const labelList &checkFaces, labelHashSet *setPtr)
Small faces.
Definition: polyMeshGeometry.C:1933
Foam::Field< vector >
Foam::syncTools::swapBoundaryCellPositions
static void swapBoundaryCellPositions(const polyMesh &mesh, const UList< point > &cellData, List< point > &neighbourCellData)
Swap to obtain neighbour cell positions for all boundary faces.
Definition: syncTools.C:34
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::polyMesh::faceOwner
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1076
SeriousErrorInFunction
#define SeriousErrorInFunction
Report an error message using Foam::SeriousError.
Definition: messageStream.H:272
Foam::cellList
List< cell > cellList
A List of cells.
Definition: cellListFwd.H:47
Foam::polyBoundaryMesh::whichPatch
label whichPatch(const label faceIndex) const
Return patch index for a given face label.
Definition: polyBoundaryMesh.C:805
Foam::radToDeg
constexpr scalar radToDeg(const scalar rad) noexcept
Conversion from radians to degrees.
Definition: unitConversion.H:54
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::syncTools::swapBoundaryFacePositions
static void swapBoundaryFacePositions(const polyMesh &mesh, UList< point > &positions)
Swap coupled positions. Uses eqOp.
Definition: syncTools.H:455
Foam::FatalError
error FatalError
Foam::primitiveMesh::nBoundaryFaces
label nBoundaryFaces() const
Number of boundary faces (== nFaces - nInternalFaces)
Definition: primitiveMeshI.H:84
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:137
Foam::vector
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:51
Foam::degToRad
constexpr scalar degToRad(const scalar deg) noexcept
Conversion from degrees to radians.
Definition: unitConversion.H:48
Foam::polyMeshGeometry::checkFaceTwist
static bool checkFaceTwist(const bool report, const scalar minTwist, const polyMesh &, const vectorField &cellCentres, const vectorField &faceAreas, const vectorField &faceCentres, const pointField &p, const labelList &checkFaces, labelHashSet *setPtr)
Triangle (from face-centre decomposition) normal v.s.
Definition: polyMeshGeometry.C:1548
Foam::normalised
VectorSpace< Form, Cmpt, Ncmpts > normalised(const VectorSpace< Form, Cmpt, Ncmpts > &vs)
Definition: VectorSpaceI.H:496
Foam::polyMeshGeometry::checkFaceFlatness
static bool checkFaceFlatness(const bool report, const scalar minFlatness, const polyMesh &, const vectorField &faceAreas, const vectorField &faceCentres, const pointField &p, const labelList &checkFaces, labelHashSet *setPtr)
Area of faces v.s. sum of triangle areas.
Definition: polyMeshGeometry.C:1840
Foam::primitiveMeshTools::faceSkewness
static tmp< scalarField > faceSkewness(const primitiveMesh &mesh, const pointField &points, const vectorField &fCtrs, const vectorField &fAreas, const vectorField &cellCtrs)
Generate skewness field.
Definition: primitiveMeshTools.C:153
Foam::polyMesh::faces
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1063
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
Foam::constant::mathematical::pi
constexpr scalar pi(M_PI)
Foam::nl
constexpr char nl
Definition: Ostream.H:372
Foam::Pair
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: Pair.H:54
f
labelList f(nPoints)
Foam::faceList
List< face > faceList
A List of faces.
Definition: faceListFwd.H:47
Foam::Vector< scalar >
Foam::List< label >
Foam::primitiveMesh::isInternalFace
bool isInternalFace(const label faceIndex) const
Return true if given face label is internal to the mesh.
Definition: primitiveMeshI.H:102
Foam::acos
dimensionedScalar acos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:268
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
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::primitiveMeshTools::boundaryFaceSkewness
static scalar boundaryFaceSkewness(const primitiveMesh &mesh, const pointField &p, const vectorField &fCtrs, const vectorField &fAreas, const label facei, const point &ownCc)
Skewness of single boundary face.
Definition: primitiveMeshTools.C:72
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:65
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
Foam::VectorSpace< Vector< scalar >, scalar, 3 >::zero
static const Vector< scalar > zero
Definition: VectorSpace.H:115
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:74
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
Foam::det
dimensionedScalar det(const dimensionedSphericalTensor &dt)
Definition: dimensionedSphericalTensor.C:62
Foam::polyMeshGeometry::checkFacePyramids
static bool checkFacePyramids(const bool report, const scalar minPyrVol, const polyMesh &, const vectorField &cellCentres, const pointField &p, const labelList &checkFaces, const List< labelPair > &baffles, labelHashSet *)
See primitiveMesh.
Definition: polyMeshGeometry.C:539
Foam::point
vector point
Point is a vector.
Definition: point.H:43
Foam::polyMeshGeometry::checkCellDeterminant
static bool checkCellDeterminant(const bool report, const scalar minDet, const polyMesh &, const vectorField &faceAreas, const labelList &checkFaces, const labelList &affectedCells, labelHashSet *setPtr)
Area of internal faces v.s. boundary faces.
Definition: polyMeshGeometry.C:1990
Foam::labelHashSet
HashSet< label, Hash< label > > labelHashSet
A HashSet with label keys and label hasher.
Definition: HashSet.H:415
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::polyMeshGeometry::checkTriangleTwist
static bool checkTriangleTwist(const bool report, const scalar minTwist, const polyMesh &, const vectorField &faceAreas, const vectorField &faceCentres, const pointField &p, const labelList &checkFaces, labelHashSet *setPtr)
Consecutive triangle (from face-centre decomposition) normals.
Definition: polyMeshGeometry.C:1694
Foam::pyramidPointFaceRef
pyramid< point, const point &, const face & > pyramidPointFaceRef
Definition: pyramidPointFaceRef.H:47
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:294
pyramidPointFaceRef.H
Foam::cell
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:54
Foam::asin
dimensionedScalar asin(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:267
Foam::polyMesh::faceNeighbour
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1082
Foam::polyMeshGeometry::checkVolRatio
static bool checkVolRatio(const bool report, const scalar warnRatio, const polyMesh &mesh, const scalarField &cellVolumes, const labelList &checkFaces, const List< labelPair > &baffles, labelHashSet *setPtr)
Cell volume ratio of neighbouring cells (1 for regular mesh)
Definition: polyMeshGeometry.C:1284
Foam::triPointRef
triangle< point, const point & > triPointRef
Definition: triangle.H:78
Foam::cos
dimensionedScalar cos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:265
Foam::polyMeshGeometry::checkFaceAngles
static bool checkFaceAngles(const bool report, const scalar maxDeg, const polyMesh &mesh, const vectorField &faceAreas, const pointField &p, const labelList &checkFaces, labelHashSet *setPtr)
See primitiveMesh.
Definition: polyMeshGeometry.C:1420