polyMeshTetDecomposition.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-2019 OpenFOAM Foundation
9 Copyright (C) 2019-2022 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
30
31// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
32
33// Note: the use of this tolerance is ad-hoc, there may be extreme
34// cases where the resulting tetrahedra still have particle tracking
35// problems, or tets with lower quality may track OK.
36const Foam::scalar Foam::polyMeshTetDecomposition::minTetQuality = sqr(SMALL);
37
38
39// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
40
42(
43 const polyMesh& mesh,
44 const point& cC,
45 const label fI,
46 const bool isOwner,
47 const label faceBasePtI
48)
49{
50 // Does fan decomposition of face (starting at faceBasePti) and determines
51 // min quality over all resulting tets.
52
53 const pointField& pPts = mesh.points();
54 const face& f = mesh.faces()[fI];
55 const point& tetBasePt = pPts[f[faceBasePtI]];
56
57 scalar thisBaseMinTetQuality = VGREAT;
58
59 for (label tetPtI = 1; tetPtI < f.size() - 1; tetPtI++)
60 {
61 label facePtI = (tetPtI + faceBasePtI) % f.size();
62 label otherFacePtI = f.fcIndex(facePtI);
63
64 label ptAI = -1;
65 label ptBI = -1;
66
67 if (isOwner)
68 {
69 ptAI = f[facePtI];
70 ptBI = f[otherFacePtI];
71 }
72 else
73 {
74 ptAI = f[otherFacePtI];
75 ptBI = f[facePtI];
76 }
77
78 const point& pA = pPts[ptAI];
79 const point& pB = pPts[ptBI];
80
81 tetPointRef tet(cC, tetBasePt, pA, pB);
82
83 scalar tetQuality = tet.quality();
84
85 if (tetQuality < thisBaseMinTetQuality)
86 {
87 thisBaseMinTetQuality = tetQuality;
88 }
89 }
90 return thisBaseMinTetQuality;
91}
92
93
95(
96 const polyMesh& mesh,
97 const label facei,
98 const label faceBasePtI
99)
100{
101 const scalar ownQuality =
102 minQuality
103 (
104 mesh,
105 mesh.cellCentres()[mesh.faceOwner()[facei]],
106 facei,
107 true,
108 faceBasePtI
109 );
110
111 if (mesh.isInternalFace(facei))
112 {
113 const scalar neiQuality =
114 minQuality
115 (
116 mesh,
118 facei,
119 false,
120 faceBasePtI
121 );
122
123 if (neiQuality < ownQuality)
124 {
125 return neiQuality;
126 }
127 }
128
129 return ownQuality;
130}
131
132
134(
135 const polyMesh& mesh,
136 label fI,
137 const point& nCc,
138 scalar tol,
139 bool report
140)
141{
142 const faceList& pFaces = mesh.faces();
143 const vectorField& pC = mesh.cellCentres();
144 const labelList& pOwner = mesh.faceOwner();
145
146 const face& f = pFaces[fI];
147
148 label oCI = pOwner[fI];
149
150 const point& oCc = pC[oCI];
151
152 forAll(f, faceBasePtI)
153 {
154 scalar ownQuality = minQuality(mesh, oCc, fI, true, faceBasePtI);
155 scalar neiQuality = minQuality(mesh, nCc, fI, false, faceBasePtI);
156
157 if (min(ownQuality, neiQuality) > tol)
158 {
159 return faceBasePtI;
160 }
161 }
162
163 // If a base point hasn't triggered a return by now, then there is
164 // none that can produce a good decomposition
165 return -1;
166}
167
168
170(
171 const polyMesh& mesh,
172 label fI,
173 scalar tol,
174 bool report
175)
176{
177 return findSharedBasePoint
178 (
179 mesh,
180 fI,
182 tol,
183 report
184 );
185}
186
187
189(
190 const polyMesh& mesh,
191 label fI,
192 scalar tol,
193 bool report
194)
195{
196 const faceList& pFaces = mesh.faces();
197 const vectorField& pC = mesh.cellCentres();
198 const labelList& pOwner = mesh.faceOwner();
199
200 const face& f = pFaces[fI];
201
202 label cI = pOwner[fI];
203
204 bool own = (pOwner[fI] == cI);
205
206 const point& cC = pC[cI];
207
208 forAll(f, faceBasePtI)
209 {
210 scalar quality = minQuality(mesh, cC, fI, own, faceBasePtI);
211
212 if (quality > tol)
213 {
214 return faceBasePtI;
215 }
216 }
217
218 // If a base point hasn't triggered a return by now, then there is
219 // none that can produce a good decomposition
220 return -1;
221}
222
223
225(
226 const polyMesh& mesh,
227 scalar tol,
228 bool report
229)
230{
231 const labelList& pOwner = mesh.faceOwner();
232 const vectorField& pC = mesh.cellCentres();
233
234 // Find a suitable base point for each face, considering both
235 // cells for interface faces or those on coupled patches
236
237 labelList tetBasePtIs(mesh.nFaces(), -1);
238
239 const label nInternalFaces = mesh.nInternalFaces();
240
241 for (label fI = 0; fI < nInternalFaces; ++fI)
242 {
243 tetBasePtIs[fI] = findSharedBasePoint(mesh, fI, tol, report);
244 }
245
246 pointField neighbourCellCentres(mesh.nBoundaryFaces());
247
248 for (label facei = nInternalFaces; facei < mesh.nFaces(); ++facei)
249 {
250 neighbourCellCentres[facei - nInternalFaces] = pC[pOwner[facei]];
251 }
252
253 syncTools::swapBoundaryFacePositions(mesh, neighbourCellCentres);
254
256
257 SubList<label> boundaryFaceTetBasePtIs
258 (
259 tetBasePtIs,
262 );
263
264 for
265 (
266 label fI = nInternalFaces, bFI = 0;
267 fI < mesh.nFaces();
268 fI++, bFI++
269 )
270 {
271 label patchi = mesh.boundaryMesh().patchID()[bFI];
272
273 if (patches[patchi].coupled())
274 {
275 const coupledPolyPatch& pp =
276 refCast<const coupledPolyPatch>(patches[patchi]);
277
278 if (pp.owner())
279 {
280 boundaryFaceTetBasePtIs[bFI] = findSharedBasePoint
281 (
282 mesh,
283 fI,
284 neighbourCellCentres[bFI],
285 tol,
286 report
287 );
288 }
289 else
290 {
291 // Assign -2, to distinguish from a failed base point
292 // find, which returns -1.
293 boundaryFaceTetBasePtIs[bFI] = -2;
294 }
295 }
296 else
297 {
298 boundaryFaceTetBasePtIs[bFI] = findBasePoint
299 (
300 mesh,
301 fI,
302 tol,
303 report
304 );
305 }
306 }
307
308 // maxEqOp will replace the -2 values on the neighbour patches
309 // with the result from the owner base point find.
310
312 (
313 mesh,
314 boundaryFaceTetBasePtIs,
316 );
317
318 for
319 (
320 label fI = nInternalFaces, bFI = 0;
321 fI < mesh.nFaces();
322 fI++, bFI++
323 )
324 {
325 label& bFTetBasePtI = boundaryFaceTetBasePtIs[bFI];
326
327 if (bFTetBasePtI == -2)
328 {
330 << "Coupled face base point exchange failure for face "
331 << fI << " at " << mesh.faceCentres()[fI]
332 << abort(FatalError);
333 }
334
335 if (bFTetBasePtI < 1)
336 {
337 // If the base point is -1, it should be left as such to
338 // indicate a problem, if it is 0, then no action is required.
339
340 continue;
341 }
342
343 label patchi = mesh.boundaryMesh().patchID()[bFI];
344
345 if (patches[patchi].coupled())
346 {
347 const coupledPolyPatch& pp =
348 refCast<const coupledPolyPatch>(patches[patchi]);
349
350 // Calculated base points on coupled faces are those of
351 // the owner patch face. They need to be reindexed to for
352 // the non-owner face, which has the opposite order.
353
354 // So, for fPtI_o != 0, fPtI_n = f.size() - fPtI_o
355
356 // i.e.:
357
358 // owner coupledPolyPatch face
359 // face (a b c d e f)
360 // fPtI 0 1 2 3 4 5
361 // +
362 // #
363
364 // neighbour coupledPolyPatch face
365 // face (a f e d c b)
366 // fPtI 0 1 2 3 4 5
367 // +
368 // #
369 // +: 6 - 1 = 5
370 // #: 6 - 2 = 4
371
372 if (!pp.owner())
373 {
374 bFTetBasePtI = mesh.faces()[fI].size() - bFTetBasePtI;
375 }
376 }
377 }
378
379 return tetBasePtIs;
380}
381
382
384(
385 const polyMesh& mesh,
386 scalar tol,
387 const bool report,
388 labelHashSet* setPtr
389)
390{
391 const labelList& own = mesh.faceOwner();
392 const labelList& nei = mesh.faceNeighbour();
394
395 const vectorField& cc = mesh.cellCentres();
396 const vectorField& fc = mesh.faceCentres();
397
398 // Calculate coupled cell centre
400
401 for (label facei = mesh.nInternalFaces(); facei < mesh.nFaces(); ++facei)
402 {
403 neiCc[facei - mesh.nInternalFaces()] = cc[own[facei]];
404 }
405
407
408 const faceList& fcs = mesh.faces();
409
410 const pointField& p = mesh.points();
411
412 label nErrorTets = 0;
413
414 forAll(fcs, facei)
415 {
416 const face& f = fcs[facei];
417
418 forAll(f, fPtI)
419 {
420 scalar tetQual = tetPointRef
421 (
422 p[f[fPtI]],
423 p[f.nextLabel(fPtI)],
424 fc[facei],
425 cc[own[facei]]
426 ).quality();
427
428 if (tetQual > -tol)
429 {
430 if (setPtr)
431 {
432 setPtr->insert(facei);
433 }
434
435 nErrorTets++;
436 break; // no need to check other tets
437 }
438 }
439
440 if (mesh.isInternalFace(facei))
441 {
442 // Create the neighbour tet - it will have positive volume
443 const face& f = fcs[facei];
444
445 forAll(f, fPtI)
446 {
447 scalar tetQual = tetPointRef
448 (
449 p[f[fPtI]],
450 p[f.nextLabel(fPtI)],
451 fc[facei],
452 cc[nei[facei]]
453 ).quality();
454
455 if (tetQual < tol)
456 {
457 if (setPtr)
458 {
459 setPtr->insert(facei);
460 }
461
462 nErrorTets++;
463 break;
464 }
465 }
466
467 if (findSharedBasePoint(mesh, facei, tol, report) == -1)
468 {
469 if (setPtr)
470 {
471 setPtr->insert(facei);
472 }
473
474 nErrorTets++;
475 }
476 }
477 else
478 {
479 label patchi = patches.patchID()[facei - mesh.nInternalFaces()];
480
481 if (patches[patchi].coupled())
482 {
483 if
484 (
485 findSharedBasePoint
486 (
487 mesh,
488 facei,
489 neiCc[facei - mesh.nInternalFaces()],
490 tol,
491 report
492 ) == -1
493 )
494 {
495 if (setPtr)
496 {
497 setPtr->insert(facei);
498 }
499
500 nErrorTets++;
501 }
502 }
503 else
504 {
505 if (findBasePoint(mesh, facei, tol, report) == -1)
506 {
507 if (setPtr)
508 {
509 setPtr->insert(facei);
510 }
511
512 nErrorTets++;
513 }
514 }
515 }
516 }
517
518 reduce(nErrorTets, sumOp<label>());
519
520 if (nErrorTets > 0)
521 {
522 if (report)
523 {
524 Info<< " ***Error in face tets: "
525 << nErrorTets << " faces with low quality or negative volume "
526 << "decomposition tets." << endl;
527 }
528
529 return true;
530 }
531
532 if (report)
533 {
534 Info<< " Face tets OK." << endl;
535 }
536
537 return false;
538}
539
540
542(
543 const polyMesh& mesh,
544 label facei,
545 label celli
546)
547{
548 const faceList& pFaces = mesh.faces();
549
550 const face& f = pFaces[facei];
551
552 label nTets = f.size() - 2;
553
554 List<tetIndices> faceTets(nTets);
555
556 for (label tetPti = 1; tetPti < f.size() - 1; ++tetPti)
557 {
558 faceTets[tetPti - 1] = tetIndices(celli, facei, tetPti);
559 }
560
561 return faceTets;
562}
563
564
566(
567 const polyMesh& mesh,
568 label celli
569)
570{
571 const faceList& pFaces = mesh.faces();
572 const cellList& pCells = mesh.cells();
573
574 const cell& thisCell = pCells[celli];
575
576 label nTets = 0;
577
578 for (const label facei : thisCell)
579 {
580 nTets += pFaces[facei].size() - 2;
581 }
582
583 DynamicList<tetIndices> cellTets(nTets);
584
585 for (const label facei : thisCell)
586 {
587 cellTets.append(faceTetIndices(mesh, facei, celli));
588 }
589
590 return cellTets;
591}
592
593
595(
596 const polyMesh& mesh,
597 label celli,
598 const point& pt
599)
600{
601 const faceList& pFaces = mesh.faces();
602 const cellList& pCells = mesh.cells();
603
604 const cell& thisCell = pCells[celli];
605
606 tetIndices tetContainingPt;
607
608
609 for (const label facei : thisCell)
610 {
611 const face& f = pFaces[facei];
612
613 for (label tetPti = 1; tetPti < f.size() - 1; ++tetPti)
614 {
615 // Get tetIndices of face triangle
616 tetIndices faceTetIs(celli, facei, tetPti);
617
618 // Check if inside
619 if (faceTetIs.tet(mesh).inside(pt))
620 {
621 tetContainingPt = faceTetIs;
622 break;
623 }
624 }
625
626 if (tetContainingPt.cell() != -1)
627 {
628 break;
629 }
630 }
631
632 return tetContainingPt;
633}
634
635
637(
638 const polyMesh& mesh,
639 const bool report
640)
641{
642 // Determine points used by two faces on the same cell
643 const cellList& cells = mesh.cells();
644 const faceList& faces = mesh.faces();
645 const labelList& faceOwn = mesh.faceOwner();
646 const labelList& faceNei = mesh.faceNeighbour();
647
648
649 // Get face triangulation base point
650 labelList tetBasePtIs(mesh.tetBasePtIs());
651
652
653 // Pre-filter: mark all cells with illegal base points
654 bitSet problemCells(cells.size());
655
656 forAll(tetBasePtIs, facei)
657 {
658 if (tetBasePtIs[facei] == -1)
659 {
660 problemCells.set(faceOwn[facei]);
661
662 if (mesh.isInternalFace(facei))
663 {
664 problemCells.set(faceNei[facei]);
665 }
666 }
667 }
668
669
670 // Mark all points that are shared by just two faces within an adjacent
671 // problem cell as problematic
672 bitSet problemPoints(mesh.points().size());
673
674 {
675 // Number of times a point occurs in a cell.
676 // Used to detect dangling vertices (count = 2)
677 Map<label> pointCount;
678
679 // Analyse problem cells for points shared by two faces only
680 for (const label celli : problemCells)
681 {
682 pointCount.clear();
683
684 for (const label facei : cells[celli])
685 {
686 for (const label pointi : faces[facei])
687 {
688 ++pointCount(pointi);
689 }
690 }
691
692 forAllConstIters(pointCount, iter)
693 {
694 if (iter.val() == 1)
695 {
697 << "point:" << iter.key()
698 << " at:" << mesh.points()[iter.key()]
699 << " only used by one face" << nl
700 << exit(FatalError);
701 }
702 else if (iter.val() == 2)
703 {
704 problemPoints.set(iter.key());
705 }
706 }
707 }
708 }
709
710
711 // For all faces which form a part of a problem-cell, check if the base
712 // point is adjacent to any problem points. If it is, re-calculate the base
713 // point so that it is not.
714 label nAdapted = 0;
715 forAll(tetBasePtIs, facei)
716 {
717 if
718 (
719 problemCells.test(faceOwn[facei])
720 || (mesh.isInternalFace(facei) && problemCells.test(faceNei[facei]))
721 )
722 {
723 const face& f = faces[facei];
724
725 // Check if either of the points adjacent to the base point is a
726 // problem point. If not, the existing base point can be retained.
727 const label fp0 = tetBasePtIs[facei] < 0 ? 0 : tetBasePtIs[facei];
728
729 if
730 (
731 !problemPoints.test(f.rcValue(fp0))
732 && !problemPoints.test(f.fcValue(fp0))
733 )
734 {
735 continue;
736 }
737
738 // A new base point is required. Pick the point that results in the
739 // least-worst tet and which is not adjacent to any problem points.
740 scalar maxQ = -GREAT;
741 label maxFp = -1;
742 forAll(f, fp)
743 {
744 if
745 (
746 !problemPoints.test(f.rcValue(fp))
747 && !problemPoints.test(f.fcValue(fp))
748 )
749 {
750 const scalar q = minQuality(mesh, facei, fp);
751 if (q > maxQ)
752 {
753 maxQ = q;
754 maxFp = fp;
755 }
756 }
757 }
758
759 if (maxFp != -1)
760 {
761 // Success! Set the new base point
762 tetBasePtIs[facei] = maxFp;
763 }
764 else
765 {
766 // No point was found on face that would not result in some
767 // duplicate triangle. Do what? Continue and hope? Spit an
768 // error? Silently or noisily reduce the filtering level?
769
770 tetBasePtIs[facei] = 0;
771 }
772
773 ++nAdapted;
774 }
775 }
776
778
779 if (report && returnReduce(nAdapted, sumOp<label>()))
780 {
781 Pout<< "Adapted starting point of triangulation on "
782 << nAdapted << " faces." << endl;
783 }
784
785 return tetBasePtIs;
786}
787
788
789// ************************************************************************* //
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:72
void append(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:503
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:191
void clear()
Clear all entries from table.
Definition: HashTable.C:678
A HashTable to objects of type <T> with a label key.
Definition: Map.H:60
A List obtained as a section of another List.
Definition: SubList.H:70
const T & rcValue(const label i) const
Return reverse circular value (ie, previous value in the list)
Definition: UListI.H:88
const T & fcValue(const label i) const
Return forward circular value (ie, next value in the list)
Definition: UListI.H:74
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
label fcIndex(const label i) const noexcept
Definition: UListI.H:60
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:66
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition: bitSetI.H:590
bool test(const label pos) const
Test value at specified position, never auto-vivify entries.
Definition: bitSetI.H:521
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:57
The coupledPolyPatch is an abstract base class for patches that couple regions of the computational d...
virtual bool owner() const =0
Does this side own the patch ?
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
const labelList & patchID() const
Per boundary face label the patch index.
static List< tetIndices > cellTetIndices(const polyMesh &mesh, label cI)
Return the tet decomposition of the given cell, see.
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.
static labelList findFaceBasePts(const polyMesh &mesh, scalar tol=minTetQuality, bool report=false)
static tetIndices findTet(const polyMesh &mesh, label cI, const point &pt)
Find the tet decomposition of the cell containing the given point.
static const scalar minTetQuality
Minimum tetrahedron quality.
static bool checkFaceTets(const polyMesh &mesh, scalar tol=minTetQuality, const bool report=false, labelHashSet *setPtr=nullptr)
Check face-decomposition tet volume.
static labelList adjustTetBasePtIs(const polyMesh &mesh, const bool report=false)
Return an adjusted list of tet base points.
static label findBasePoint(const polyMesh &mesh, label fI, scalar tol, bool report=false)
Find the base point to use for a minimum triangle.
static List< tetIndices > faceTetIndices(const polyMesh &mesh, label fI, label cI)
Return the tet decomposition of the given face, with.
static scalar minQuality(const polyMesh &mesh, const point &cC, const label fI, const bool isOwner, const label faceBasePtI)
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:81
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1108
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1121
const labelIOList & tetBasePtIs() const
Return the tetBasePtIs.
Definition: polyMesh.C:906
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:456
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1127
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1083
bool isInternalFace(const label faceIndex) const noexcept
Return true if given face label is internal to the mesh.
label nBoundaryFaces() const noexcept
Number of boundary faces (== nFaces - nInternalFaces)
const vectorField & faceCentres() const
label nInternalFaces() const noexcept
Number of internal faces.
const vectorField & cellCentres() const
label nFaces() const noexcept
Number of mesh faces.
const cellList & cells() const
static void swapBoundaryFacePositions(const polyMesh &mesh, UList< point > &positions)
Swap coupled positions. Uses eqOp.
Definition: syncTools.H:461
static void syncFaceList(const polyMesh &mesh, UList< T > &faceValues, const CombineOp &cop)
Synchronize values on all mesh faces.
Definition: syncTools.H:396
static void syncBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues, const CombineOp &cop, const TransformOp &top, const bool parRun=Pstream::parRun())
Synchronize values on boundary faces only.
Storage and named access for the indices of a tet which is part of the decomposition of a cell.
Definition: tetIndices.H:84
tetPointRef tet(const polyMesh &mesh) const
Return the geometry corresponding to this tet.
Definition: tetIndicesI.H:134
label cell() const noexcept
Return the cell index.
Definition: tetIndices.H:133
A tetrahedron primitive.
Definition: tetrahedron.H:87
bool inside(const point &pt) const
Return true if point is inside tetrahedron.
Definition: tetrahedronI.H:415
scalar quality() const
Return quality: Ratio of tetrahedron and circum-sphere.
Definition: tetrahedronI.H:232
volScalarField & p
const polyBoundaryMesh & patches
bool coupled(solutionDict.getOrDefault("coupledEnergyField", false))
dynamicFvMesh & mesh
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
const cellShapeList & cells
tetrahedron< point, const point & > tetPointRef
A tetrahedron using referred points.
Definition: tetPointRef.H:47
dimensionedSymmTensor sqr(const dimensionedVector &dv)
messageStream Info
Information stream (stdout output on master, null elsewhere)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
errorManip< error > abort(error &err)
Definition: errorManip.H:144
error FatalError
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.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
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)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
#define forAllConstIters(container, iter)
Iterate across all elements of the container object with const access.
Definition: stdFoam.H:278