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 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
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
45namespace Foam
46{
48}
49
50
51// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
52
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.
78Foam::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(false, 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().faceLabels()[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.hitPoint() + 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'
250void 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 (returnReduce(celli, maxOp<label>()) == -1)
292 {
294 << "outsidePoint " << outsidePts[outsidePtI]
295 << " is not inside any cell"
296 << nl << "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
348void 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
398bool 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
426void 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:
508 labelList(cellType),
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
522:
524 mesh_(cType.mesh())
525{}
526
527
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 }
613
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}
670
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
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// ************************************************************************* //
Various functions to operate on Lists.
void setSize(const label n)
Alias for resize()
Definition: List.H:218
void operator=(const UList< label > &a)
Assignment to UList operator. Takes linear time.
Definition: List.C:480
A HashTable to objects of type <T> with a label key.
Definition: Map.H:60
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:62
A list of faces which address into the list of points.
const Map< label > & meshPointMap() const
Mesh point map.
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.
iterator end() noexcept
Return an iterator to end traversing the UList.
Definition: UListI.H:350
label size() const noexcept
The number of elements in the UList.
Definition: UListI.H:420
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
static const Form max
Definition: VectorSpace.H:117
static const Form min
Definition: VectorSpace.H:118
'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.
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.
Various (local, not parallel) searches on polyMesh; uses (demand driven) octree to search.
Definition: meshSearch.H:61
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:81
label nCells() const noexcept
Number of mesh cells.
label count() const
Helper class to search on triSurface.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
const volScalarField & p0
Definition: EEqn.H:36
dynamicFvMesh & mesh
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
OBJstream os(runTime.globalPath()/outputName)
cellType
Equivalent to enumeration in "vtkCellType.h" (should be uint8_t)
Definition: foamVtkCore.H:90
Namespace for OpenFOAM.
List< label > labelList
A List of labels.
Definition: List.H:66
PointIndexHit< point > pointIndexHit
A PointIndexHit for 3D points.
Definition: pointIndexHit.H:46
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
vector point
Point is a vector.
Definition: point.H:43
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: MSwindows.C:598
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
errorManip< error > abort(error &err)
Definition: errorManip.H:144
List< bool > boolList
A List of bools.
Definition: List.H:64
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
error FatalError
List< edge > edgeList
A List of edges.
Definition: edgeList.H:63
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce (copy) and return value.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
List< face > faceList
A List of faces.
Definition: faceListFwd.H:47
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
cpuTimeCxx cpuTime
Selection of preferred clock mechanism for the elapsed cpu time.
Definition: cpuTimeFwd.H:43
fileName search(const word &file, const fileName &directory)
Recursively search the given directory for the file.
Definition: fileName.C:624
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:158
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
labelList f(nPoints)
volScalarField & e
Definition: createFields.H:11
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333