cellClassification.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2025 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "cellClassification.H"
27 #include "triSurfaceSearch.H"
28 #include "meshSearch.H"
29 #include "treeDataFace.H"
30 #include "cellInfo.H"
31 #include "polyMesh.H"
32 #include "FaceCellWave.H"
33 #include "ListOps.H"
34 #include "meshTools.H"
35 #include "cpuTime.H"
36 #include "triSurface.H"
37 #include "globalMeshData.H"
38 
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 
41 namespace Foam
42 {
44 }
45 
46 
47 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
48 
49 Foam::label Foam::cellClassification::count
50 (
51  const labelList& elems,
52  const label elem
53 )
54 {
55  label cnt = 0;
56 
57  forAll(elems, elemI)
58  {
59  if (elems[elemI] == elem)
60  {
61  cnt++;
62  }
63  }
64  return cnt;
65 
66 }
67 
68 
69 // Mark all faces that are cut by the surface. Two pass:
70 // Pass1: mark all mesh edges that intersect surface (quick since triangle
71 // pierce test).
72 // Pass2: Check for all point neighbours of these faces whether any of their
73 // faces are pierced.
74 Foam::boolList Foam::cellClassification::markFaces
75 (
76  const triSurfaceSearch& search
77 ) const
78 {
79  cpuTime timer;
80 
81  boolList cutFace(mesh_.nFaces(), false);
82 
83  label nCutFaces = 0;
84 
85  // Intersect mesh edges with surface (is fast) and mark all faces that
86  // use edge.
87 
88  forAll(mesh_.edges(), edgeI)
89  {
90  if (debug && (edgeI % 10000 == 0))
91  {
92  Pout<< "Intersecting mesh edge " << edgeI << " with surface"
93  << endl;
94  }
95 
96  const edge& e = mesh_.edges()[edgeI];
97 
98  const point& p0 = mesh_.points()[e.start()];
99  const point& p1 = mesh_.points()[e.end()];
100 
101  pointIndexHit pHit(search.tree().findLineAny(p0, p1));
102 
103  if (pHit.hit())
104  {
105  const labelList& myFaces = mesh_.edgeFaces()[edgeI];
106 
107  forAll(myFaces, myFacei)
108  {
109  label facei = myFaces[myFacei];
110 
111  if (!cutFace[facei])
112  {
113  cutFace[facei] = true;
114 
115  nCutFaces++;
116  }
117  }
118  }
119  }
120 
121  if (debug)
122  {
123  Pout<< "Intersected edges of mesh with surface in = "
124  << timer.cpuTimeIncrement() << " s\n" << endl << endl;
125  }
126 
127  //
128  // Construct octree on faces that have not yet been marked as cut
129  //
130 
131  labelList allFaces(mesh_.nFaces() - nCutFaces);
132 
133  label allFacei = 0;
134 
135  forAll(cutFace, facei)
136  {
137  if (!cutFace[facei])
138  {
139  allFaces[allFacei++] = facei;
140  }
141  }
142 
143  if (debug)
144  {
145  Pout<< "Testing " << allFacei << " faces for piercing by surface"
146  << endl;
147  }
148 
149  treeBoundBox allBb(mesh_.points());
150 
151  // Extend domain slightly (also makes it 3D if was 2D)
152  scalar tol = 1e-6 * allBb.avgDim();
153 
154  point& bbMin = allBb.min();
155  bbMin.x() -= tol;
156  bbMin.y() -= tol;
157  bbMin.z() -= tol;
158 
159  point& bbMax = allBb.max();
160  bbMax.x() += 2*tol;
161  bbMax.y() += 2*tol;
162  bbMax.z() += 2*tol;
163 
164  indexedOctree<treeDataFace> faceTree
165  (
166  treeDataFace(false, mesh_, allFaces),
167  allBb, // overall search domain
168  8, // maxLevel
169  10, // leafsize
170  3.0 // duplicity
171  );
172 
173  const triSurface& surf = search.surface();
174  const edgeList& edges = surf.edges();
175  const pointField& localPoints = surf.localPoints();
176 
177  label nAddFaces = 0;
178 
179  forAll(edges, edgeI)
180  {
181  if (debug && (edgeI % 10000 == 0))
182  {
183  Pout<< "Intersecting surface edge " << edgeI
184  << " with mesh faces" << endl;
185  }
186  const edge& e = edges[edgeI];
187 
188  const point& start = localPoints[e.start()];
189  const point& end = localPoints[e.end()];
190 
191  vector edgeNormal(end - start);
192  const scalar edgeMag = mag(edgeNormal);
193  const vector smallVec = 1e-9*edgeNormal;
194 
195  edgeNormal /= edgeMag+vSmall;
196 
197  // Current start of pierce test
198  point pt = start;
199 
200  while (true)
201  {
202  pointIndexHit pHit(faceTree.findLine(pt, end));
203 
204  if (!pHit.hit())
205  {
206  break;
207  }
208  else
209  {
210  label facei = faceTree.shapes().faceLabels()[pHit.index()];
211 
212  if (!cutFace[facei])
213  {
214  cutFace[facei] = true;
215 
216  nAddFaces++;
217  }
218 
219  // Restart from previous endpoint
220  pt = pHit.hitPoint() + smallVec;
221 
222  if (((pt-start) & edgeNormal) >= edgeMag)
223  {
224  break;
225  }
226  }
227  }
228  }
229 
230  if (debug)
231  {
232  Pout<< "Detected an additional " << nAddFaces << " faces cut"
233  << endl;
234 
235  Pout<< "Intersected edges of surface with mesh faces in = "
236  << timer.cpuTimeIncrement() << " s\n" << endl << endl;
237  }
238 
239  return cutFace;
240 }
241 
242 
243 // Determine faces cut by surface and use to divide cells into types. See
244 // cellInfo. All cells reachable from outsidePts are considered to be of type
245 // 'outside'
246 void Foam::cellClassification::markCells
247 (
248  const boolList& piercedFace,
249  const List<point>& outsidePts
250 )
251 {
252  // Use meshwave to partition mesh, starting from outsidePt
253 
254  // Construct null; sets type to NOTSET
255  List<cellInfo> cellInfoList(mesh_.nCells());
256 
257  // Mark cut cells first
258  forAll(piercedFace, facei)
259  {
260  if (piercedFace[facei])
261  {
262  cellInfoList[mesh_.faceOwner()[facei]] =
263  cellInfo(cellClassification::CUT);
264 
265  if (mesh_.isInternalFace(facei))
266  {
267  cellInfoList[mesh_.faceNeighbour()[facei]] =
268  cellInfo(cellClassification::CUT);
269  }
270  }
271  }
272 
273 
274  //
275  // Mark cells containing outside points as being outside
276  //
277 
278  // Coarse guess number of faces
279  labelHashSet outsideFacesMap(outsidePts.size() * 6 * 2);
280 
281  forAll(outsidePts, outsidePtI)
282  {
283  // Use linear search for points.
284  label celli = meshSearch::findCellNoTree(mesh_, outsidePts[outsidePtI]);
285 
286  if (returnReduce(celli, maxOp<label>()) == -1)
287  {
289  << "outsidePoint " << outsidePts[outsidePtI]
290  << " is not inside any cell"
291  << nl << "It might be on a face or outside the geometry"
292  << exit(FatalError);
293  }
294 
295  if (celli >= 0)
296  {
297  cellInfoList[celli] = cellInfo(cellClassification::OUTSIDE);
298 
299  // Mark faces of celli
300  const labelList& myFaces = mesh_.cells()[celli];
301  forAll(myFaces, myFacei)
302  {
303  outsideFacesMap.insert(myFaces[myFacei]);
304  }
305  }
306  }
307 
308 
309  //
310  // Mark faces to start wave from
311  //
312 
313  labelList changedFaces(outsideFacesMap.toc());
314 
315  List<cellInfo> changedFacesInfo
316  (
317  changedFaces.size(),
319  );
320 
321  List<cellInfo> faceInfoList(mesh().nFaces());
322  FaceCellWave<cellInfo> cellInfoCalc
323  (
324  mesh_,
325  changedFaces, // Labels of changed faces
326  changedFacesInfo, // Information on changed faces
327  faceInfoList,
328  cellInfoList, // Information on all cells
329  mesh_.globalData().nTotalCells() + 1 // max iterations
330  );
331 
332  forAll(cellInfoList, celli)
333  {
334  label t = cellInfoList[celli].type();
335 
337  {
339  }
340  operator[](celli) = t;
341  }
342 }
343 
344 
345 void Foam::cellClassification::classifyPoints
346 (
347  const label meshType,
348  const labelList& cellType,
349  List<pointStatus>& pointSide
350 ) const
351 {
352  pointSide.setSize(mesh_.nPoints());
353 
354  forAll(mesh_.pointCells(), pointi)
355  {
356  const labelList& pCells = mesh_.pointCells()[pointi];
357 
358  pointSide[pointi] = UNSET;
359 
360  forAll(pCells, i)
361  {
362  label type = cellType[pCells[i]];
363 
364  if (type == meshType)
365  {
366  if (pointSide[pointi] == UNSET)
367  {
368  pointSide[pointi] = MESH;
369  }
370  else if (pointSide[pointi] == NONMESH)
371  {
372  pointSide[pointi] = MIXED;
373 
374  break;
375  }
376  }
377  else
378  {
379  if (pointSide[pointi] == UNSET)
380  {
381  pointSide[pointi] = NONMESH;
382  }
383  else if (pointSide[pointi] == MESH)
384  {
385  pointSide[pointi] = MIXED;
386 
387  break;
388  }
389  }
390  }
391  }
392 }
393 
394 
395 bool Foam::cellClassification::usesMixedPointsOnly
396 (
397  const List<pointStatus>& pointSide,
398  const label celli
399 ) const
400 {
401  const faceList& faces = mesh_.faces();
402 
403  const cell& cFaces = mesh_.cells()[celli];
404 
405  forAll(cFaces, cFacei)
406  {
407  const face& f = faces[cFaces[cFacei]];
408 
409  forAll(f, fp)
410  {
411  if (pointSide[f[fp]] != MIXED)
412  {
413  return false;
414  }
415  }
416  }
417 
418  // All points are mixed.
419  return true;
420 }
421 
422 
423 void Foam::cellClassification::getMeshOutside
424 (
425  const label meshType,
426  faceList& outsideFaces,
427  labelList& outsideOwner
428 ) const
429 {
430  const labelList& own = mesh_.faceOwner();
431  const labelList& nbr = mesh_.faceNeighbour();
432  const faceList& faces = mesh_.faces();
433 
434  outsideFaces.setSize(mesh_.nFaces());
435  outsideOwner.setSize(mesh_.nFaces());
436  label outsideI = 0;
437 
438  // Get faces on interface between meshType and non-meshType
439 
440  for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
441  {
442  label ownType = operator[](own[facei]);
443  label nbrType = operator[](nbr[facei]);
444 
445  if (ownType == meshType && nbrType != meshType)
446  {
447  outsideFaces[outsideI] = faces[facei];
448  outsideOwner[outsideI] = own[facei]; // meshType cell
449  outsideI++;
450  }
451  else if (ownType != meshType && nbrType == meshType)
452  {
453  outsideFaces[outsideI] = faces[facei];
454  outsideOwner[outsideI] = nbr[facei]; // meshType cell
455  outsideI++;
456  }
457  }
458 
459  // Get faces on outside of real mesh with cells of meshType.
460 
461  for (label facei = mesh_.nInternalFaces(); facei < mesh_.nFaces(); facei++)
462  {
463  if (operator[](own[facei]) == meshType)
464  {
465  outsideFaces[outsideI] = faces[facei];
466  outsideOwner[outsideI] = own[facei]; // meshType cell
467  outsideI++;
468  }
469  }
470  outsideFaces.setSize(outsideI);
471  outsideOwner.setSize(outsideI);
472 }
473 
474 
475 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
476 
477 // Construct from mesh and surface and point(s) on outside
479 (
480  const polyMesh& mesh,
481  const triSurfaceSearch& surfQuery,
482  const List<point>& outsidePoints
483 )
484 :
485  labelList(mesh.nCells(), cellClassification::NOTSET),
486  mesh_(mesh)
487 {
488  markCells(markFaces(surfQuery), outsidePoints);
489 }
490 
491 
492 // Construct from mesh and meshType.
494 (
495  const polyMesh& mesh,
496  const labelList& cellType
497 )
498 :
499  labelList(cellType),
500  mesh_(mesh)
501 {
502  if (mesh_.nCells() != size())
503  {
505  << "Number of elements of cellType argument is not equal to the"
506  << " number of cells" << abort(FatalError);
507  }
508 }
509 
510 
511 // Copy constructor
513 :
514  labelList(cType),
515  mesh_(cType.mesh())
516 {}
517 
518 
519 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
520 
521 
522 // Makes cutCells further than nLayers away from meshType to
523 // fillType. Returns number of cells changed.
525 (
526  const label nLayers,
527  const label meshType,
528  const label fillType
529 )
530 {
531  // Temporary cell type for growing.
532  labelList newCellType(*this);
533 
534 // // Split types into outside and rest
535 // forAll(*this, celli)
536 // {
537 // label type = operator[](celli);
538 //
539 // if (type == meshType)
540 // {
541 // newCellType[celli] = type;
542 // }
543 // else
544 // {
545 // newCellType[celli] = fillType;
546 // }
547 // }
548 
549  newCellType = *this;
550 
551 
552  // Do point-cell-point walk on newCellType out from meshType cells
553  for (label iter = 0; iter < nLayers; iter++)
554  {
555  // Get status of points: visible from meshType (pointSide == MESH)
556  // or fillType/cutCells cells (pointSide == NONMESH) or
557  // both (pointSide == MIXED)
558  List<pointStatus> pointSide(mesh_.nPoints());
559  classifyPoints(meshType, newCellType, pointSide);
560 
561  // Grow layer of outside cells
562  forAll(pointSide, pointi)
563  {
564  if (pointSide[pointi] == MIXED)
565  {
566  // Make cut
567  const labelList& pCells = mesh_.pointCells()[pointi];
568 
569  forAll(pCells, i)
570  {
571  label type = newCellType[pCells[i]];
572 
574  {
575  // Found cut cell sharing point with
576  // mesh type cell. Grow.
577  newCellType[pCells[i]] = meshType;
578  }
579  }
580  }
581  }
582  }
583 
584  // Merge newCellType into *this:
585  // - leave meshType cells intact
586  // - leave nonMesh cells intact
587  // - make cutcells fillType if they were not marked in newCellType
588 
589  label nChanged = 0;
590 
591  forAll(newCellType, celli)
592  {
593  if (operator[](celli) == cellClassification::CUT)
594  {
595  if (newCellType[celli] != meshType)
596  {
597  // Cell was cutCell but further than nLayers away from
598  // meshType. Convert to fillType.
599  operator[](celli) = fillType;
600  nChanged++;
601  }
602  }
603  }
604 
605  return nChanged;
606 }
607 
608 
609 // Grow surface by pointNeighbours of type meshType
611 (
612  const label meshType,
613  const label fillType
614 )
615 {
616  boolList hasMeshType(mesh_.nPoints(), false);
617 
618  // Mark points used by meshType cells
619 
620  forAll(mesh_.pointCells(), pointi)
621  {
622  const labelList& myCells = mesh_.pointCells()[pointi];
623 
624  // Check if one of cells has meshType
625  forAll(myCells, myCelli)
626  {
627  label type = operator[](myCells[myCelli]);
628 
629  if (type == meshType)
630  {
631  hasMeshType[pointi] = true;
632 
633  break;
634  }
635  }
636  }
637 
638  // Change neighbours of marked points
639 
640  label nChanged = 0;
641 
642  forAll(hasMeshType, pointi)
643  {
644  if (hasMeshType[pointi])
645  {
646  const labelList& myCells = mesh_.pointCells()[pointi];
647 
648  forAll(myCells, myCelli)
649  {
650  if (operator[](myCells[myCelli]) != meshType)
651  {
652  operator[](myCells[myCelli]) = fillType;
653 
654  nChanged++;
655  }
656  }
657  }
658  }
659  return nChanged;
660 }
661 
662 
663 // Check all points used by cells of meshType for use of at least one point
664 // which is not on the outside. If all points are on the outside of the mesh
665 // this would probably result in a flattened cell when projecting the cell
666 // onto the surface.
668 (
669  const label meshType,
670  const label fillType,
671  const label maxIter
672 )
673 {
674  label nTotChanged = 0;
675 
676  for (label iter = 0; iter < maxIter; iter++)
677  {
678  label nChanged = 0;
679 
680  // Get status of points: visible from meshType or non-meshType cells
681  List<pointStatus> pointSide(mesh_.nPoints());
682  classifyPoints(meshType, *this, pointSide);
683 
684  // Check all cells using mixed point type for whether they use mixed
685  // points only. Note: could probably speed this up by counting number
686  // of mixed verts per face and mixed faces per cell or something?
687  forAll(pointSide, pointi)
688  {
689  if (pointSide[pointi] == MIXED)
690  {
691  const labelList& pCells = mesh_.pointCells()[pointi];
692 
693  forAll(pCells, i)
694  {
695  label celli = pCells[i];
696 
697  if (operator[](celli) == meshType)
698  {
699  if (usesMixedPointsOnly(pointSide, celli))
700  {
701  operator[](celli) = fillType;
702 
703  nChanged++;
704  }
705  }
706  }
707  }
708  }
709  nTotChanged += nChanged;
710 
711  Pout<< "removeHangingCells : changed " << nChanged
712  << " hanging cells" << endl;
713 
714  if (nChanged == 0)
715  {
716  break;
717  }
718  }
719 
720  return nTotChanged;
721 }
722 
723 
725 (
726  const label meshType,
727  const label fillType,
728  const label maxIter
729 )
730 {
731  label nTotChanged = 0;
732 
733  for (label iter = 0; iter < maxIter; iter++)
734  {
735  // Get interface between meshType cells and non-meshType cells as a list
736  // of faces and for each face the cell which is the meshType.
737  faceList outsideFaces;
738  labelList outsideOwner;
739 
740  getMeshOutside(meshType, outsideFaces, outsideOwner);
741 
742  // Build primitivePatch out of it and check it for problems.
743  primitiveFacePatch fp(outsideFaces, mesh_.points());
744 
745  const labelListList& edgeFaces = fp.edgeFaces();
746 
747  label nChanged = 0;
748 
749  // Check all edgeFaces for non-manifoldness
750 
751  forAll(edgeFaces, edgeI)
752  {
753  const labelList& eFaces = edgeFaces[edgeI];
754 
755  if (eFaces.size() > 2)
756  {
757  // patch connected through pinched edge. Remove first face using
758  // edge (and not yet changed)
759 
760  forAll(eFaces, i)
761  {
762  label patchFacei = eFaces[i];
763 
764  label ownerCell = outsideOwner[patchFacei];
765 
766  if (operator[](ownerCell) == meshType)
767  {
768  operator[](ownerCell) = fillType;
769 
770  nChanged++;
771 
772  break;
773  }
774  }
775  }
776  }
777 
778  nTotChanged += nChanged;
779 
780  Pout<< "fillRegionEdges : changed " << nChanged
781  << " cells using multiply connected edges" << endl;
782 
783  if (nChanged == 0)
784  {
785  break;
786  }
787  }
788 
789  return nTotChanged;
790 }
791 
792 
794 (
795  const label meshType,
796  const label fillType,
797  const label maxIter
798 )
799 {
800  label nTotChanged = 0;
801 
802  for (label iter = 0; iter < maxIter; iter++)
803  {
804  // Get interface between meshType cells and non-meshType cells as a list
805  // of faces and for each face the cell which is the meshType.
806  faceList outsideFaces;
807  labelList outsideOwner;
808 
809  getMeshOutside(meshType, outsideFaces, outsideOwner);
810 
811  // Build primitivePatch out of it and check it for problems.
812  primitiveFacePatch fp(outsideFaces, mesh_.points());
813 
814  labelHashSet nonManifoldPoints;
815 
816  // Check for non-manifold points.
817  fp.checkPointManifold(false, &nonManifoldPoints);
818 
819  const Map<label>& meshPointMap = fp.meshPointMap();
820 
821  label nChanged = 0;
822 
823  forAllConstIter(labelHashSet, nonManifoldPoints, iter)
824  {
825  // Find a face on fp using point and remove it.
826  const label patchPointi = meshPointMap[iter.key()];
827 
828  const labelList& pFaces = fp.pointFaces()[patchPointi];
829 
830  // Remove any face using conflicting point. Does first face which
831  // has not yet been done. Could be more intelligent and decide which
832  // one would be best to remove.
833  forAll(pFaces, i)
834  {
835  const label patchFacei = pFaces[i];
836  const label ownerCell = outsideOwner[patchFacei];
837 
838  if (operator[](ownerCell) == meshType)
839  {
840  operator[](ownerCell) = fillType;
841 
842  nChanged++;
843  break;
844  }
845  }
846  }
847 
848  nTotChanged += nChanged;
849 
850  Pout<< "fillRegionPoints : changed " << nChanged
851  << " cells using multiply connected points" << endl;
852 
853  if (nChanged == 0)
854  {
855  break;
856  }
857  }
858 
859  return nTotChanged;
860 }
861 
862 
864 {
865  os << "Cells:" << size() << endl
866  << " notset : " << count(*this, NOTSET) << endl
867  << " cut : " << count(*this, CUT) << endl
868  << " inside : " << count(*this, INSIDE) << endl
869  << " outside : " << count(*this, OUTSIDE) << endl;
870 }
871 
872 
873 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
874 
876 {
878 }
879 
880 
881 // ************************************************************************* //
Various functions to operate on Lists.
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:492
label size() const
Return the number of elements in the UList.
Definition: ListI.H:171
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
void operator=(const UList< label > &)
Assignment to UList operator. Takes linear time.
Definition: List.C:376
void setSize(const label)
Reset size of List.
Definition: List.C:281
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
A list of faces which address into the list of points.
const Map< label > & meshPointMap() const
Mesh point map. Given the global point index find its.
bool checkPointManifold(const bool report=false, labelHashSet *setPtr=nullptr) const
Checks primitivePatch for faces sharing point but not edge.
const labelListList & pointFaces() const
Return point-face addressing.
const labelListList & edgeFaces() const
Return edge-face addressing.
static const Form max
Definition: VectorSpace.H:120
static const Form min
Definition: VectorSpace.H:121
'Cuts' a mesh with a surface.
label fillRegionPoints(const label meshType, const label fillType, const label maxIter)
Find regionPoints and fill all neighbours. Iterate until nothing.
cellClassification(const polyMesh &mesh, const triSurfaceSearch &surfQuery, const List< point > &outsidePoints)
Construct from mesh and surface and point(s) on outside.
label fillHangingCells(const label meshType, const label fillType, const label maxIter)
Find hanging cells (cells with all points on outside) and set their.
label growSurface(const label meshType, const label fillType)
Sets vertex neighbours of meshType cells to fillType.
void operator=(const cellClassification &)
label trimCutCells(const label nLayers, const label meshType, const label fillType)
void writeStats(Ostream &os) const
Write statistics on cell types to Ostream.
label fillRegionEdges(const label meshType, const label fillType, const label maxIter)
Find regionEdges and fill one neighbour. Iterate until nothing.
static label findCellNoTree(const polyMesh &mesh, const point &p, const pointInCellShapes=pointInCellShapes::tets)
Find the cell containing the given point. Do a.
Definition: meshSearch.C:183
Motion of the mesh specified as a list of pointMeshMovers.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:78
label nCells() const
Helper class to search on triSurface.
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
const doubleScalar e
Definition: doubleScalar.H:106
List< label > labelList
A List of labels.
Definition: labelList.H:56
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
PointIndexHit< point > pointIndexHit
Definition: pointIndexHit.H:42
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
errorManip< error > abort(error &err)
Definition: errorManip.H:131
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
List< bool > boolList
Bool container classes.
Definition: boolList.H:50
vector point
Point is a vector.
Definition: point.H:41
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
HashSet< label, Hash< label > > labelHashSet
A HashSet with label keys.
Definition: HashSet.H:213
tmp< DimensionedField< scalar, GeoMesh, Field > > mag(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
error FatalError
List< edge > edgeList
Definition: edgeList.H:38
label count(const ListType &l, typename ListType::const_reference x)
Count the number of occurrences of a value in a list.
List< face > faceList
Definition: faceListFwd.H:41
defineTypeNameAndDebug(atmosphericBoundaryLayer, 0)
static const char nl
Definition: Ostream.H:297
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.
Definition: POSIX.C:488
fileName search(const word &file, const fileName &directory)
Recursively search the given directory for the file.
labelList f(nPoints)
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=*(cellModeller::lookup("hex"));labelList hexLabels(8);label activeCells=0;labelList pointMap(nPoints);forAll(pointMap, i){ pointMap[i]=i;}for(label i=0;i< nPoints;i++){ if(f[i] > 0.0) { hexLabels[0]=i;hexLabels[1]=i1tab[i];hexLabels[2]=i3tab[i1tab[i]];hexLabels[3]=i3tab[i];hexLabels[4]=i8tab[i];hexLabels[5]=i1tab[i8tab[i]];hexLabels[6]=i3tab[i1tab[i8tab[i]]];hexLabels[7]=i3tab[i8tab[i]];cellShapes[activeCells]=cellShape(hex, hexLabels);edgeList edges=cellShapes[activeCells].edges();forAll(edges, ei) { if(edges[ei].mag(points)< small) { label start=pointMap[edges[ei].start()];while(start !=pointMap[start]) { start=pointMap[start];} label end=pointMap[edges[ei].end()];while(end !=pointMap[end]) { end=pointMap[end];} label minLabel=min(start, end);pointMap[start]=pointMap[end]=minLabel;} } cellZoning[activeCells]=idreg[i];activeCells++;}}cellShapes.setSize(activeCells);cellZoning.setSize(activeCells);forAll(cellShapes, celli){ cellShape &cs=cellShapes[celli];forAll(cs, i) { cs[i]=pointMap[cs[i]];} cs.collapse();}label bcIDs[11]={-1, 0, 2, 4, -1, 5, -1, 6, 7, 8, 9};const label nBCs=12;const word *kivaPatchTypes[nBCs]={ &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &symmetryPolyPatch::typeName, &wedgePolyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &symmetryPolyPatch::typeName, &mergedCyclicPolyPatch::typeName};enum patchTypeNames{ PISTON, VALVE, LINER, CYLINDERHEAD, AXIS, WEDGE, INFLOW, OUTFLOW, PRESIN, PRESOUT, SYMMETRYPLANE, CYCLIC};const char *kivaPatchNames[nBCs]={ "piston", "valve", "liner", "cylinderHead", "axis", "wedge", "inflow", "outflow", "presin", "presout", "symmetryPlane", "cyclic"};List< SLList< face > > pFaces[nBCs]
Definition: readKivaGrid.H:229