cellClassification.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) 2018-2022 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 "cellClassification.H"
30 #include "triSurfaceSearch.H"
31 #include "indexedOctree.H"
32 #include "treeDataFace.H"
33 #include "meshSearch.H"
34 #include "cellInfo.H"
35 #include "polyMesh.H"
36 #include "MeshWave.H"
37 #include "ListOps.H"
38 #include "meshTools.H"
39 #include "cpuTime.H"
40 #include "triSurface.H"
41 #include "globalMeshData.H"
42 
43 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
44 
45 namespace Foam
46 {
47 defineTypeNameAndDebug(cellClassification, 0);
48 }
49 
50 
51 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
52 
53 Foam::label Foam::cellClassification::count
54 (
55  const labelList& elems,
56  const label elem
57 )
58 {
59  label cnt = 0;
60 
61  forAll(elems, elemI)
62  {
63  if (elems[elemI] == elem)
64  {
65  cnt++;
66  }
67  }
68  return cnt;
69 
70 }
71 
72 
73 // Mark all faces that are cut by the surface. Two pass:
74 // Pass1: mark all mesh edges that intersect surface (quick since triangle
75 // pierce test).
76 // Pass2: Check for all point neighbours of these faces whether any of their
77 // faces are pierced.
78 Foam::boolList Foam::cellClassification::markFaces
79 (
80  const triSurfaceSearch& search
81 ) const
82 {
83  cpuTime timer;
84 
85  boolList cutFace(mesh_.nFaces(), false);
86 
87  label nCutFaces = 0;
88 
89  // Intersect mesh edges with surface (is fast) and mark all faces that
90  // use edge.
91 
92  forAll(mesh_.edges(), edgeI)
93  {
94  if (debug && (edgeI % 10000 == 0))
95  {
96  Pout<< "Intersecting mesh edge " << edgeI << " with surface"
97  << endl;
98  }
99 
100  const edge& e = mesh_.edges()[edgeI];
101 
102  const point& p0 = mesh_.points()[e.start()];
103  const point& p1 = mesh_.points()[e.end()];
104 
105  pointIndexHit pHit(search.tree().findLineAny(p0, p1));
106 
107  if (pHit.hit())
108  {
109  const labelList& myFaces = mesh_.edgeFaces()[edgeI];
110 
111  forAll(myFaces, myFacei)
112  {
113  label facei = myFaces[myFacei];
114 
115  if (!cutFace[facei])
116  {
117  cutFace[facei] = true;
118 
119  nCutFaces++;
120  }
121  }
122  }
123  }
124 
125  if (debug)
126  {
127  Pout<< "Intersected edges of mesh with surface in = "
128  << timer.cpuTimeIncrement() << " s\n" << endl << endl;
129  }
130 
131  //
132  // Construct octree on faces that have not yet been marked as cut
133  //
134 
135  labelList allFaces(mesh_.nFaces() - nCutFaces);
136 
137  label allFacei = 0;
138 
139  forAll(cutFace, facei)
140  {
141  if (!cutFace[facei])
142  {
143  allFaces[allFacei++] = facei;
144  }
145  }
146 
147  if (debug)
148  {
149  Pout<< "Testing " << allFacei << " faces for piercing by surface"
150  << endl;
151  }
152 
153  treeBoundBox allBb(mesh_.points());
154 
155  // Extend domain slightly (also makes it 3D if was 2D)
156  scalar tol = 1e-6 * allBb.avgDim();
157 
158  point& bbMin = allBb.min();
159  bbMin.x() -= tol;
160  bbMin.y() -= tol;
161  bbMin.z() -= tol;
162 
163  point& bbMax = allBb.max();
164  bbMax.x() += 2*tol;
165  bbMax.y() += 2*tol;
166  bbMax.z() += 2*tol;
167 
168  indexedOctree<treeDataFace> faceTree
169  (
170  treeDataFace(mesh_, allFaces),
171  allBb, // overall search domain
172  8, // maxLevel
173  10, // leafsize
174  3.0 // duplicity
175  );
176 
177  const triSurface& surf = search.surface();
178  const edgeList& edges = surf.edges();
179  const pointField& localPoints = surf.localPoints();
180 
181  label nAddFaces = 0;
182 
183  forAll(edges, edgeI)
184  {
185  if (debug && (edgeI % 10000 == 0))
186  {
187  Pout<< "Intersecting surface edge " << edgeI
188  << " with mesh faces" << endl;
189  }
190  const edge& e = edges[edgeI];
191 
192  const point& start = localPoints[e.start()];
193  const point& end = localPoints[e.end()];
194 
195  vector edgeNormal(end - start);
196  const scalar edgeMag = mag(edgeNormal);
197  const vector smallVec = 1e-9*edgeNormal;
198 
199  edgeNormal /= edgeMag+VSMALL;
200 
201  // Current start of pierce test
202  point pt = start;
203 
204  while (true)
205  {
206  pointIndexHit pHit(faceTree.findLine(pt, end));
207 
208  if (!pHit.hit())
209  {
210  break;
211  }
212  else
213  {
214  label facei = faceTree.shapes().objectIndex(pHit.index());
215 
216  if (!cutFace[facei])
217  {
218  cutFace[facei] = true;
219 
220  nAddFaces++;
221  }
222 
223  // Restart from previous endpoint
224  pt = pHit.point() + smallVec;
225 
226  if (((pt-start) & edgeNormal) >= edgeMag)
227  {
228  break;
229  }
230  }
231  }
232  }
233 
234  if (debug)
235  {
236  Pout<< "Detected an additional " << nAddFaces << " faces cut"
237  << endl;
238 
239  Pout<< "Intersected edges of surface with mesh faces in = "
240  << timer.cpuTimeIncrement() << " s\n" << endl << endl;
241  }
242 
243  return cutFace;
244 }
245 
246 
247 // Determine faces cut by surface and use to divide cells into types. See
248 // cellInfo. All cells reachable from outsidePts are considered to be of type
249 // 'outside'
250 void Foam::cellClassification::markCells
251 (
252  const meshSearch& queryMesh,
253  const boolList& piercedFace,
254  const pointField& outsidePts
255 )
256 {
257  // Use meshwave to partition mesh, starting from outsidePt
258 
259 
260  // Construct null; sets type to NOTSET
261  List<cellInfo> cellInfoList(mesh_.nCells());
262 
263  // Mark cut cells first
264  forAll(piercedFace, facei)
265  {
266  if (piercedFace[facei])
267  {
268  cellInfoList[mesh_.faceOwner()[facei]] =
269  cellInfo(cellClassification::CUT);
270 
271  if (mesh_.isInternalFace(facei))
272  {
273  cellInfoList[mesh_.faceNeighbour()[facei]] =
274  cellInfo(cellClassification::CUT);
275  }
276  }
277  }
278 
279  //
280  // Mark cells containing outside points as being outside
281  //
282 
283  // Coarse guess number of faces
284  labelHashSet outsideFacesMap(outsidePts.size() * 6 * 2);
285 
286  forAll(outsidePts, outsidePtI)
287  {
288  // Use linear search for points.
289  label celli = queryMesh.findCell(outsidePts[outsidePtI], -1, false);
290 
291  if (returnReduceAnd(celli < 0))
292  {
294  << "outsidePoint " << outsidePts[outsidePtI]
295  << " is not inside any cell" << nl
296  << "It might be on a face or outside the geometry"
297  << exit(FatalError);
298  }
299 
300  if (celli >= 0)
301  {
302  cellInfoList[celli] = cellInfo(cellClassification::OUTSIDE);
303 
304  // Mark faces of celli
305  const labelList& myFaces = mesh_.cells()[celli];
306  outsideFacesMap.insert(myFaces);
307  }
308  }
309 
310 
311  //
312  // Mark faces to start wave from
313  //
314 
315  labelList changedFaces(outsideFacesMap.toc());
316 
317  List<cellInfo> changedFacesInfo
318  (
319  changedFaces.size(),
321  );
322 
323  MeshWave<cellInfo> cellInfoCalc
324  (
325  mesh_,
326  changedFaces, // Labels of changed faces
327  changedFacesInfo, // Information on changed faces
328  cellInfoList, // Information on all cells
329  mesh_.globalData().nTotalCells()+1 // max iterations
330  );
331 
332  // Get information out of cellInfoList
333  const List<cellInfo>& allInfo = cellInfoCalc.allCellInfo();
334 
335  forAll(allInfo, celli)
336  {
337  label t = allInfo[celli].type();
338 
340  {
342  }
343  operator[](celli) = t;
344  }
345 }
346 
347 
348 void Foam::cellClassification::classifyPoints
349 (
350  const label meshType,
351  const labelList& cellType,
352  List<pointStatus>& pointSide
353 ) const
354 {
355  pointSide.setSize(mesh_.nPoints());
356 
357  forAll(mesh_.pointCells(), pointi)
358  {
359  const labelList& pCells = mesh_.pointCells()[pointi];
360 
361  pointSide[pointi] = UNSET;
362 
363  forAll(pCells, i)
364  {
365  label type = cellType[pCells[i]];
366 
367  if (type == meshType)
368  {
369  if (pointSide[pointi] == UNSET)
370  {
371  pointSide[pointi] = MESH;
372  }
373  else if (pointSide[pointi] == NONMESH)
374  {
375  pointSide[pointi] = MIXED;
376 
377  break;
378  }
379  }
380  else
381  {
382  if (pointSide[pointi] == UNSET)
383  {
384  pointSide[pointi] = NONMESH;
385  }
386  else if (pointSide[pointi] == MESH)
387  {
388  pointSide[pointi] = MIXED;
389 
390  break;
391  }
392  }
393  }
394  }
395 }
396 
397 
398 bool Foam::cellClassification::usesMixedPointsOnly
399 (
400  const List<pointStatus>& pointSide,
401  const label celli
402 ) const
403 {
404  const faceList& faces = mesh_.faces();
405 
406  const cell& cFaces = mesh_.cells()[celli];
407 
408  forAll(cFaces, cFacei)
409  {
410  const face& f = faces[cFaces[cFacei]];
411 
412  forAll(f, fp)
413  {
414  if (pointSide[f[fp]] != MIXED)
415  {
416  return false;
417  }
418  }
419  }
420 
421  // All points are mixed.
422  return true;
423 }
424 
425 
426 void Foam::cellClassification::getMeshOutside
427 (
428  const label meshType,
429  faceList& outsideFaces,
430  labelList& outsideOwner
431 ) const
432 {
433  const labelList& own = mesh_.faceOwner();
434  const labelList& nbr = mesh_.faceNeighbour();
435  const faceList& faces = mesh_.faces();
436 
437  outsideFaces.setSize(mesh_.nFaces());
438  outsideOwner.setSize(mesh_.nFaces());
439  label outsideI = 0;
440 
441  // Get faces on interface between meshType and non-meshType
442 
443  for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
444  {
445  label ownType = operator[](own[facei]);
446  label nbrType = operator[](nbr[facei]);
447 
448  if (ownType == meshType && nbrType != meshType)
449  {
450  outsideFaces[outsideI] = faces[facei];
451  outsideOwner[outsideI] = own[facei]; // meshType cell
452  outsideI++;
453  }
454  else if (ownType != meshType && nbrType == meshType)
455  {
456  outsideFaces[outsideI] = faces[facei];
457  outsideOwner[outsideI] = nbr[facei]; // meshType cell
458  outsideI++;
459  }
460  }
461 
462  // Get faces on outside of real mesh with cells of meshType.
463 
464  for (label facei = mesh_.nInternalFaces(); facei < mesh_.nFaces(); facei++)
465  {
466  if (operator[](own[facei]) == meshType)
467  {
468  outsideFaces[outsideI] = faces[facei];
469  outsideOwner[outsideI] = own[facei]; // meshType cell
470  outsideI++;
471  }
472  }
473  outsideFaces.setSize(outsideI);
474  outsideOwner.setSize(outsideI);
475 }
476 
477 
478 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
479 
480 // Construct from mesh and surface and point(s) on outside
482 (
483  const polyMesh& mesh,
484  const meshSearch& meshQuery,
485  const triSurfaceSearch& surfQuery,
486  const pointField& outsidePoints
487 )
488 :
489  labelList(mesh.nCells(), cellClassification::NOTSET),
490  mesh_(mesh)
491 {
492  markCells
493  (
494  meshQuery,
495  markFaces(surfQuery),
496  outsidePoints
497  );
498 }
499 
500 
501 // Construct from mesh and meshType.
503 (
504  const polyMesh& mesh,
505  const labelList& cellType
506 )
507 :
509  mesh_(mesh)
510 {
511  if (mesh_.nCells() != size())
512  {
514  << "Number of elements of cellType argument is not equal to the"
515  << " number of cells" << abort(FatalError);
516  }
517 }
518 
519 
520 // Construct as copy
521 Foam::cellClassification::cellClassification(const cellClassification& cType)
522 :
523  labelList(cType),
524  mesh_(cType.mesh())
525 {}
526 
528 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
529 
530 
531 // Makes cutCells further than nLayers away from meshType to
532 // fillType. Returns number of cells changed.
534 (
535  const label nLayers,
536  const label meshType,
537  const label fillType
538 )
539 {
540  // Temporary cell type for growing.
541  labelList newCellType(*this);
542 
543 // // Split types into outside and rest
544 // forAll(*this, celli)
545 // {
546 // label type = operator[](celli);
547 //
548 // if (type == meshType)
549 // {
550 // newCellType[celli] = type;
551 // }
552 // else
553 // {
554 // newCellType[celli] = fillType;
555 // }
556 // }
557 
558  newCellType = *this;
559 
560 
561  // Do point-cell-point walk on newCellType out from meshType cells
562  for (label iter = 0; iter < nLayers; iter++)
563  {
564  // Get status of points: visible from meshType (pointSide == MESH)
565  // or fillType/cutCells cells (pointSide == NONMESH) or
566  // both (pointSide == MIXED)
567  List<pointStatus> pointSide(mesh_.nPoints());
568  classifyPoints(meshType, newCellType, pointSide);
569 
570  // Grow layer of outside cells
571  forAll(pointSide, pointi)
572  {
573  if (pointSide[pointi] == MIXED)
574  {
575  // Make cut
576  const labelList& pCells = mesh_.pointCells()[pointi];
577 
578  forAll(pCells, i)
579  {
580  label type = newCellType[pCells[i]];
581 
583  {
584  // Found cut cell sharing point with
585  // mesh type cell. Grow.
586  newCellType[pCells[i]] = meshType;
587  }
588  }
589  }
590  }
591  }
592 
593  // Merge newCellType into *this:
594  // - leave meshType cells intact
595  // - leave nonMesh cells intact
596  // - make cutcells fillType if they were not marked in newCellType
597 
598  label nChanged = 0;
599 
600  forAll(newCellType, celli)
601  {
602  if (operator[](celli) == cellClassification::CUT)
603  {
604  if (newCellType[celli] != meshType)
605  {
606  // Cell was cutCell but further than nLayers away from
607  // meshType. Convert to fillType.
608  operator[](celli) = fillType;
609  nChanged++;
610  }
611  }
612  }
614  return nChanged;
615 }
616 
617 
618 // Grow surface by pointNeighbours of type meshType
620 (
621  const label meshType,
622  const label fillType
623 )
624 {
625  boolList hasMeshType(mesh_.nPoints(), false);
626 
627  // Mark points used by meshType cells
628 
629  forAll(mesh_.pointCells(), pointi)
630  {
631  const labelList& myCells = mesh_.pointCells()[pointi];
632 
633  // Check if one of cells has meshType
634  forAll(myCells, myCelli)
635  {
636  label type = operator[](myCells[myCelli]);
637 
638  if (type == meshType)
639  {
640  hasMeshType[pointi] = true;
641 
642  break;
643  }
644  }
645  }
646 
647  // Change neighbours of marked points
648 
649  label nChanged = 0;
650 
651  forAll(hasMeshType, pointi)
652  {
653  if (hasMeshType[pointi])
654  {
655  const labelList& myCells = mesh_.pointCells()[pointi];
656 
657  forAll(myCells, myCelli)
658  {
659  if (operator[](myCells[myCelli]) != meshType)
660  {
661  operator[](myCells[myCelli]) = fillType;
662 
663  nChanged++;
664  }
665  }
666  }
667  }
668  return nChanged;
669 }
671 
672 // Check all points used by cells of meshType for use of at least one point
673 // which is not on the outside. If all points are on the outside of the mesh
674 // this would probably result in a flattened cell when projecting the cell
675 // onto the surface.
677 (
678  const label meshType,
679  const label fillType,
680  const label maxIter
681 )
682 {
683  label nTotChanged = 0;
684 
685  for (label iter = 0; iter < maxIter; iter++)
686  {
687  label nChanged = 0;
688 
689  // Get status of points: visible from meshType or non-meshType cells
690  List<pointStatus> pointSide(mesh_.nPoints());
691  classifyPoints(meshType, *this, pointSide);
692 
693  // Check all cells using mixed point type for whether they use mixed
694  // points only. Note: could probably speed this up by counting number
695  // of mixed verts per face and mixed faces per cell or something?
696  forAll(pointSide, pointi)
697  {
698  if (pointSide[pointi] == MIXED)
699  {
700  const labelList& pCells = mesh_.pointCells()[pointi];
701 
702  forAll(pCells, i)
703  {
704  label celli = pCells[i];
705 
706  if (operator[](celli) == meshType)
707  {
708  if (usesMixedPointsOnly(pointSide, celli))
709  {
710  operator[](celli) = fillType;
711 
712  nChanged++;
713  }
714  }
715  }
716  }
717  }
718  nTotChanged += nChanged;
719 
720  Pout<< "removeHangingCells : changed " << nChanged
721  << " hanging cells" << endl;
722 
723  if (nChanged == 0)
724  {
725  break;
726  }
727  }
728 
729  return nTotChanged;
730 }
731 
732 
734 (
735  const label meshType,
736  const label fillType,
737  const label maxIter
738 )
739 {
740  label nTotChanged = 0;
741 
742  for (label iter = 0; iter < maxIter; iter++)
743  {
744  // Get interface between meshType cells and non-meshType cells as a list
745  // of faces and for each face the cell which is the meshType.
746  faceList outsideFaces;
747  labelList outsideOwner;
748 
749  getMeshOutside(meshType, outsideFaces, outsideOwner);
750 
751  // Build primitivePatch out of it and check it for problems.
752  primitiveFacePatch fp(outsideFaces, mesh_.points());
753 
754  const labelListList& edgeFaces = fp.edgeFaces();
755 
756  label nChanged = 0;
757 
758  // Check all edgeFaces for non-manifoldness
759 
760  forAll(edgeFaces, edgeI)
761  {
762  const labelList& eFaces = edgeFaces[edgeI];
763 
764  if (eFaces.size() > 2)
765  {
766  // patch connected through pinched edge. Remove first face using
767  // edge (and not yet changed)
768 
769  forAll(eFaces, i)
770  {
771  label patchFacei = eFaces[i];
772 
773  label ownerCell = outsideOwner[patchFacei];
774 
775  if (operator[](ownerCell) == meshType)
776  {
777  operator[](ownerCell) = fillType;
778 
779  nChanged++;
780 
781  break;
782  }
783  }
784  }
785  }
786 
787  nTotChanged += nChanged;
788 
789  Pout<< "fillRegionEdges : changed " << nChanged
790  << " cells using multiply connected edges" << endl;
791 
792  if (nChanged == 0)
793  {
794  break;
795  }
796  }
797 
798  return nTotChanged;
799 }
800 
801 
803 (
804  const label meshType,
805  const label fillType,
806  const label maxIter
807 )
808 {
809  label nTotChanged = 0;
810 
811  for (label iter = 0; iter < maxIter; ++iter)
812  {
813  // Get interface between meshType cells and non-meshType cells as a list
814  // of faces and for each face the cell which is the meshType.
815  faceList outsideFaces;
816  labelList outsideOwner;
817 
818  getMeshOutside(meshType, outsideFaces, outsideOwner);
819 
820  // Build primitivePatch out of it and check it for problems.
821  primitiveFacePatch fp(outsideFaces, mesh_.points());
822 
823  labelHashSet nonManifoldPoints;
824 
825  // Check for non-manifold points.
826  fp.checkPointManifold(false, &nonManifoldPoints);
827 
828  const Map<label>& meshPointMap = fp.meshPointMap();
829 
830  label nChanged = 0;
831 
832  for (const label nonManPti : nonManifoldPoints)
833  {
834  // Find a face on fp using point and remove it.
835  const label patchPointi = meshPointMap[nonManPti];
836 
837  const labelList& pFaces = fp.pointFaces()[patchPointi];
838 
839  // Remove any face using conflicting point. Does first face which
840  // has not yet been done. Could be more intelligent and decide which
841  // one would be best to remove.
842  for (const label patchFacei : pFaces)
843  {
844  const label ownerCell = outsideOwner[patchFacei];
845 
846  if (operator[](ownerCell) == meshType)
847  {
848  operator[](ownerCell) = fillType;
849 
850  ++nChanged;
851  break;
852  }
853  }
854  }
855 
856  nTotChanged += nChanged;
857 
858  Pout<< "fillRegionPoints : changed " << nChanged
859  << " cells using multiply connected points" << endl;
860 
861  if (nChanged == 0)
862  {
863  break;
864  }
865  }
866 
867  return nTotChanged;
868 }
869 
870 
871 void Foam::cellClassification::writeStats(Ostream& os) const
872 {
873  os << "Cells:" << size() << endl
874  << " notset : " << count(*this, NOTSET) << endl
875  << " cut : " << count(*this, CUT) << endl
876  << " inside : " << count(*this, INSIDE) << endl
877  << " outside : " << count(*this, OUTSIDE) << endl;
878 }
879 
880 
881 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
882 
884 {
886 }
887 
888 
889 // ************************************************************************* //
cellType
Equivalent to enumeration in "vtkCellType.h" (should be uint8_t)
Definition: foamVtkCore.H:96
Various (local, not parallel) searches on polyMesh; uses (demand driven) octree to search...
Definition: meshSearch.H:56
label trimCutCells(const label nLayers, const label meshType, const label fillType)
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Mixed uniform/non-uniform (eg, after reduction)
Definition: ListPolicy.H:108
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
List< edge > edgeList
List of edge.
Definition: edgeList.H:32
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
PointIndexHit< point > pointIndexHit
A PointIndexHit with a 3D point.
Definition: pointIndexHit.H:58
void operator=(const cellClassification &)
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
Various functions to operate on Lists.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
cellClassification(const polyMesh &mesh, const meshSearch &meshQuery, const triSurfaceSearch &surfQuery, const pointField &outsidePoints)
Construct from mesh and surface and point(s) on outside.
List< face > faceList
List of faces.
Definition: faceListFwd.H:39
Helper class to search on triSurface.
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:799
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of &#39;true&#39; entries.
Definition: BitOps.H:73
bool returnReduceAnd(const bool value, const label comm=UPstream::worldComm)
Perform logical (and) MPI Allreduce on a copy. Uses UPstream::reduceAnd.
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
void setSize(const label n)
Alias for resize()
Definition: List.H:316
dynamicFvMesh & mesh
&#39;Cuts&#39; a mesh with a surface.
void operator=(const UList< label > &list)
Assignment to UList operator. Takes linear time.
Definition: List.C:360
label fillRegionPoints(const label meshType, const label fillType, const label maxIter)
Find regionPoints and fill all neighbours. Iterate until nothing.
Vector< scalar > vector
Definition: vector.H:57
errorManip< error > abort(error &err)
Definition: errorManip.H:139
label size() const noexcept
The number of elements in the container.
Definition: UList.H:671
int debug
Static debugging option.
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:201
OBJstream os(runTime.globalPath()/outputName)
defineTypeNameAndDebug(combustionModel, 0)
labelList f(nPoints)
PrimitivePatch< List< face >, const pointField & > primitiveFacePatch
A PrimitivePatch with List storage for the faces, const reference for the point field.
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=cellModel::ref(cellModel::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].reset(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, &oldCyclicPolyPatch::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:235
vector point
Point is a vector.
Definition: point.H:37
cpuTimePosix cpuTime
Selection of preferred clock mechanism for the elapsed cpu time.
Definition: cpuTimeFwd.H:36
label growSurface(const label meshType, const label fillType)
Sets vertex neighbours of meshType cells to fillType.
label nCells() const noexcept
Number of mesh cells.
label fillRegionEdges(const label meshType, const label fillType, const label maxIter)
Find regionEdges and fill one neighbour. Iterate until nothing.
void writeStats(Ostream &os) const
Write statistics on cell types to Ostream.
fileName search(const word &file, const fileName &directory)
Recursively search the given directory for the file.
Definition: fileName.C:642
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
List< label > labelList
A List of labels.
Definition: List.H:62
label fillHangingCells(const label meshType, const label fillType, const label maxIter)
Find hanging cells (cells with all points on outside) and set their.
List< bool > boolList
A List of bools.
Definition: List.H:60
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
const volScalarField & p0
Definition: EEqn.H:36
Namespace for OpenFOAM.