polyDualMesh.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) 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
27InClass
28 polyDualMesh
29
30\*---------------------------------------------------------------------------*/
31
32#include "polyDualMesh.H"
33#include "meshTools.H"
34#include "OFstream.H"
35#include "Time.H"
36#include "SortableList.H"
37#include "pointSet.H"
38#include "bitSet.H"
39
40// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
41
42namespace Foam
43{
45}
46
47// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
48
49// Determine order for faces:
50// - upper-triangular order for internal faces
51// - external faces after internal faces (were already so)
52Foam::labelList Foam::polyDualMesh::getFaceOrder
53(
54 const labelList& faceOwner,
55 const labelList& faceNeighbour,
56 const cellList& cells,
57 label& nInternalFaces
58)
59{
60 labelList oldToNew(faceOwner.size(), -1);
61
62 // First unassigned face
63 label newFacei = 0;
64
65 forAll(cells, celli)
66 {
67 const labelList& cFaces = cells[celli];
68
69 SortableList<label> nbr(cFaces.size());
70
71 forAll(cFaces, i)
72 {
73 label facei = cFaces[i];
74
75 label nbrCelli = faceNeighbour[facei];
76
77 if (nbrCelli != -1)
78 {
79 // Internal face. Get cell on other side.
80 if (nbrCelli == celli)
81 {
82 nbrCelli = faceOwner[facei];
83 }
84
85 if (celli < nbrCelli)
86 {
87 // Celli is master
88 nbr[i] = nbrCelli;
89 }
90 else
91 {
92 // nbrCell is master. Let it handle this face.
93 nbr[i] = -1;
94 }
95 }
96 else
97 {
98 // External face. Do later.
99 nbr[i] = -1;
100 }
101 }
102
103 nbr.sort();
104
105 forAll(nbr, i)
106 {
107 if (nbr[i] != -1)
108 {
109 oldToNew[cFaces[nbr.indices()[i]]] = newFacei++;
110 }
111 }
112 }
113
114 nInternalFaces = newFacei;
115
116 Pout<< "nInternalFaces:" << nInternalFaces << endl;
117 Pout<< "nFaces:" << faceOwner.size() << endl;
118 Pout<< "nCells:" << cells.size() << endl;
119
120 // Leave patch faces intact.
121 for (label facei = newFacei; facei < faceOwner.size(); facei++)
122 {
123 oldToNew[facei] = facei;
124 }
125
126
127 // Check done all faces.
128 forAll(oldToNew, facei)
129 {
130 if (oldToNew[facei] == -1)
131 {
133 << "Did not determine new position"
134 << " for face " << facei
135 << abort(FatalError);
136 }
137 }
138
139 return oldToNew;
140}
141
142
143// Get the two edges on facei using pointi. Returns them such that the order
144// - otherVertex of e0
145// - pointi
146// - otherVertex(pointi) of e1
147// is in face order
148void Foam::polyDualMesh::getPointEdges
149(
150 const primitivePatch& patch,
151 const label facei,
152 const label pointi,
153 label& e0,
154 label& e1
155)
156{
157 const labelList& fEdges = patch.faceEdges()[facei];
158 const face& f = patch.localFaces()[facei];
159
160 e0 = -1;
161 e1 = -1;
162
163 forAll(fEdges, i)
164 {
165 label edgeI = fEdges[i];
166
167 const edge& e = patch.edges()[edgeI];
168
169 if (e[0] == pointi)
170 {
171 // One of the edges using pointi. Check which one.
172 label index = f.find(pointi);
173
174 if (f.nextLabel(index) == e[1])
175 {
176 e1 = edgeI;
177 }
178 else
179 {
180 e0 = edgeI;
181 }
182
183 if (e0 != -1 && e1 != -1)
184 {
185 return;
186 }
187 }
188 else if (e[1] == pointi)
189 {
190 // One of the edges using pointi. Check which one.
191 label index = f.find(pointi);
192
193 if (f.nextLabel(index) == e[0])
194 {
195 e1 = edgeI;
196 }
197 else
198 {
199 e0 = edgeI;
200 }
201
202 if (e0 != -1 && e1 != -1)
203 {
204 return;
205 }
206 }
207 }
208
210 << " vertices:" << patch.localFaces()[facei]
211 << " that uses point:" << pointi
212 << abort(FatalError);
213}
214
215
216// Collect the face on an external point of the patch.
217Foam::labelList Foam::polyDualMesh::collectPatchSideFace
218(
219 const polyPatch& patch,
220 const label patchToDualOffset,
221 const labelList& edgeToDualPoint,
222 const labelList& pointToDualPoint,
223 const label pointi,
224
225 label& edgeI
226)
227{
228 // Construct face by walking around e[eI] starting from
229 // patchEdgeI
230
231 label meshPointi = patch.meshPoints()[pointi];
232 const labelList& pFaces = patch.pointFaces()[pointi];
233
234 DynamicList<label> dualFace;
235
236 if (pointToDualPoint[meshPointi] >= 0)
237 {
238 // Number of pFaces + 2 boundary edge + feature point
239 dualFace.setCapacity(pFaces.size()+2+1);
240 // Store dualVertex for feature edge
241 dualFace.append(pointToDualPoint[meshPointi]);
242 }
243 else
244 {
245 dualFace.setCapacity(pFaces.size()+2);
246 }
247
248 // Store dual vertex for starting edge.
249 if (edgeToDualPoint[patch.meshEdges()[edgeI]] < 0)
250 {
252 << abort(FatalError);
253 }
254
255 dualFace.append(edgeToDualPoint[patch.meshEdges()[edgeI]]);
256
257 label facei = patch.edgeFaces()[edgeI][0];
258
259 // Check order of vertices of edgeI in face to see if we need to reverse.
260 bool reverseFace;
261
262 label e0, e1;
263 getPointEdges(patch, facei, pointi, e0, e1);
264
265 if (e0 == edgeI)
266 {
267 reverseFace = true;
268 }
269 else
270 {
271 reverseFace = false;
272 }
273
274 while (true)
275 {
276 // Store dual vertex for facei.
277 dualFace.append(facei + patchToDualOffset);
278
279 // Cross face to other edge on pointi
280 label e0, e1;
281 getPointEdges(patch, facei, pointi, e0, e1);
282
283 if (e0 == edgeI)
284 {
285 edgeI = e1;
286 }
287 else
288 {
289 edgeI = e0;
290 }
291
292 if (edgeToDualPoint[patch.meshEdges()[edgeI]] >= 0)
293 {
294 // Feature edge. Insert dual vertex for edge.
295 dualFace.append(edgeToDualPoint[patch.meshEdges()[edgeI]]);
296 }
297
298 const labelList& eFaces = patch.edgeFaces()[edgeI];
299
300 if (eFaces.size() == 1)
301 {
302 // Reached other edge of patch
303 break;
304 }
305
306 // Cross edge to other face.
307 if (eFaces[0] == facei)
308 {
309 facei = eFaces[1];
310 }
311 else
312 {
313 facei = eFaces[0];
314 }
315 }
316
317 dualFace.shrink();
318
319 if (reverseFace)
320 {
321 reverse(dualFace);
322 }
323
324 return dualFace;
325}
326
327
328// Collect face around pointi which is not on the outside of the patch.
329// Returns the vertices of the face and the indices in these vertices of
330// any points which are on feature edges.
331void Foam::polyDualMesh::collectPatchInternalFace
332(
333 const polyPatch& patch,
334 const label patchToDualOffset,
335 const labelList& edgeToDualPoint,
336
337 const label pointi,
338 const label startEdgeI,
339
340 labelList& dualFace2,
341 labelList& featEdgeIndices2
342)
343{
344 // Construct face by walking around pointi starting from startEdgeI
345 const labelList& meshEdges = patch.meshEdges();
346 const labelList& pFaces = patch.pointFaces()[pointi];
347
348 // Vertices of dualFace
349 DynamicList<label> dualFace(pFaces.size());
350 // Indices in dualFace of vertices added because of feature edge
351 DynamicList<label> featEdgeIndices(dualFace.size());
352
353
354 label edgeI = startEdgeI;
355 label facei = patch.edgeFaces()[edgeI][0];
356
357 // Check order of vertices of edgeI in face to see if we need to reverse.
358 bool reverseFace;
359
360 label e0, e1;
361 getPointEdges(patch, facei, pointi, e0, e1);
362
363 if (e0 == edgeI)
364 {
365 reverseFace = true;
366 }
367 else
368 {
369 reverseFace = false;
370 }
371
372 while (true)
373 {
374 // Insert dual vertex for face
375 dualFace.append(facei + patchToDualOffset);
376
377 // Cross face to other edge on pointi
378 label e0, e1;
379 getPointEdges(patch, facei, pointi, e0, e1);
380
381 if (e0 == edgeI)
382 {
383 edgeI = e1;
384 }
385 else
386 {
387 edgeI = e0;
388 }
389
390 if (edgeToDualPoint[meshEdges[edgeI]] >= 0)
391 {
392 // Feature edge. Insert dual vertex for edge.
393 dualFace.append(edgeToDualPoint[meshEdges[edgeI]]);
394 featEdgeIndices.append(dualFace.size()-1);
395 }
396
397 if (edgeI == startEdgeI)
398 {
399 break;
400 }
401
402 // Cross edge to other face.
403 const labelList& eFaces = patch.edgeFaces()[edgeI];
404
405 if (eFaces[0] == facei)
406 {
407 facei = eFaces[1];
408 }
409 else
410 {
411 facei = eFaces[0];
412 }
413 }
414
415 dualFace2.transfer(dualFace);
416
417 featEdgeIndices2.transfer(featEdgeIndices);
418
419 if (reverseFace)
420 {
421 reverse(dualFace2);
422
423 // Correct featEdgeIndices for change in dualFace2
424 forAll(featEdgeIndices2, i)
425 {
426 featEdgeIndices2[i] = dualFace2.size() -1 - featEdgeIndices2[i];
427 }
428 // Reverse indices (might not be necessary but do anyway)
429 reverse(featEdgeIndices2);
430 }
431}
432
433
434void Foam::polyDualMesh::splitFace
435(
436 const polyPatch& patch,
437 const labelList& pointToDualPoint,
438
439 const label pointi,
440 const labelList& dualFace,
441 const labelList& featEdgeIndices,
442
443 DynamicList<face>& dualFaces,
444 DynamicList<label>& dualOwner,
445 DynamicList<label>& dualNeighbour,
446 DynamicList<label>& dualRegion
447)
448{
449
450 // Split face because of feature edges/points
451 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
452 label meshPointi = patch.meshPoints()[pointi];
453
454 if (pointToDualPoint[meshPointi] >= 0)
455 {
456 // Feature point. Do face-centre decomposition.
457
458 if (featEdgeIndices.size() < 2)
459 {
460 // Feature point but no feature edges. Not handled at the moment
461 dualFaces.append(face(dualFace));
462 dualOwner.append(meshPointi);
463 dualNeighbour.append(-1);
464 dualRegion.append(patch.index());
465 }
466 else
467 {
468 // Do 'face-centre' decomposition. Start from first feature
469 // edge create face up until next feature edge.
470
471 forAll(featEdgeIndices, i)
472 {
473 label startFp = featEdgeIndices[i];
474
475 label endFp = featEdgeIndices[(i+1) % featEdgeIndices.size()];
476
477 // Collect face from startFp to endFp
478 label sz = 0;
479
480 if (endFp > startFp)
481 {
482 sz = endFp - startFp + 2;
483 }
484 else
485 {
486 sz = endFp + dualFace.size() - startFp + 2;
487 }
488 face subFace(sz);
489
490 // feature point becomes face centre.
491 subFace[0] = pointToDualPoint[patch.meshPoints()[pointi]];
492
493 // Copy from startFp up to endFp.
494 for (label subFp = 1; subFp < subFace.size(); subFp++)
495 {
496 subFace[subFp] = dualFace[startFp];
497
498 startFp = (startFp+1) % dualFace.size();
499 }
500
501 dualFaces.append(face(subFace));
502 dualOwner.append(meshPointi);
503 dualNeighbour.append(-1);
504 dualRegion.append(patch.index());
505 }
506 }
507 }
508 else
509 {
510 // No feature point. Check if feature edges.
511 if (featEdgeIndices.size() < 2)
512 {
513 // Not enough feature edges. No split.
514 dualFaces.append(face(dualFace));
515 dualOwner.append(meshPointi);
516 dualNeighbour.append(-1);
517 dualRegion.append(patch.index());
518 }
519 else
520 {
521 // Multiple feature edges but no feature point.
522 // Split face along feature edges. Gives weird result if
523 // number of feature edges > 2.
524
525 // Storage for new face
526 DynamicList<label> subFace(dualFace.size());
527
528 forAll(featEdgeIndices, featI)
529 {
530 label startFp = featEdgeIndices[featI];
531 label endFp = featEdgeIndices[featEdgeIndices.fcIndex(featI)];
532
533 label fp = startFp;
534
535 while (true)
536 {
537 label vertI = dualFace[fp];
538
539 subFace.append(vertI);
540
541 if (fp == endFp)
542 {
543 break;
544 }
545
546 fp = dualFace.fcIndex(fp);
547 }
548
549 if (subFace.size() > 2)
550 {
551 // Enough vertices to create a face from.
552 dualFaces.append(face(subFace));
553 dualOwner.append(meshPointi);
554 dualNeighbour.append(-1);
555 dualRegion.append(patch.index());
556
557 subFace.clear();
558 }
559 }
560 // Check final face.
561 if (subFace.size() > 2)
562 {
563 // Enough vertices to create a face from.
564 dualFaces.append(face(subFace));
565 dualOwner.append(meshPointi);
566 dualNeighbour.append(-1);
567 dualRegion.append(patch.index());
568
569 subFace.clear();
570 }
571 }
572 }
573}
574
575
576// Create boundary face for every point in patch
577void Foam::polyDualMesh::dualPatch
578(
579 const polyPatch& patch,
580 const label patchToDualOffset,
581 const labelList& edgeToDualPoint,
582 const labelList& pointToDualPoint,
583
584 const pointField& dualPoints,
585
586 DynamicList<face>& dualFaces,
587 DynamicList<label>& dualOwner,
588 DynamicList<label>& dualNeighbour,
589 DynamicList<label>& dualRegion
590)
591{
592 const labelList& meshEdges = patch.meshEdges();
593
594 // Whether edge has been done.
595 // 0 : not
596 // 1 : done e.start()
597 // 2 : done e.end()
598 // 3 : done both
599 labelList doneEdgeSide(meshEdges.size(), Zero);
600
601 bitSet donePoint(patch.nPoints(), false);
602
603
604 // Do points on edge of patch
605 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
606
607 forAll(doneEdgeSide, patchEdgeI)
608 {
609 const labelList& eFaces = patch.edgeFaces()[patchEdgeI];
610
611 if (eFaces.size() == 1)
612 {
613 const edge& e = patch.edges()[patchEdgeI];
614
615 forAll(e, eI)
616 {
617 label bitMask = 1<<eI;
618
619 if ((doneEdgeSide[patchEdgeI] & bitMask) == 0)
620 {
621 // Construct face by walking around e[eI] starting from
622 // patchEdgeI
623
624 label pointi = e[eI];
625
626 label edgeI = patchEdgeI;
627 labelList dualFace
628 (
629 collectPatchSideFace
630 (
631 patch,
632 patchToDualOffset,
633 edgeToDualPoint,
634 pointToDualPoint,
635
636 pointi,
637 edgeI
638 )
639 );
640
641 // Now edgeI is end edge. Mark as visited
642 if (patch.edges()[edgeI][0] == pointi)
643 {
644 doneEdgeSide[edgeI] |= 1;
645 }
646 else
647 {
648 doneEdgeSide[edgeI] |= 2;
649 }
650
651 dualFaces.append(face(dualFace));
652 dualOwner.append(patch.meshPoints()[pointi]);
653 dualNeighbour.append(-1);
654 dualRegion.append(patch.index());
655
656 doneEdgeSide[patchEdgeI] |= bitMask;
657 donePoint.set(pointi);
658 }
659 }
660 }
661 }
662
663
664
665 // Do patch-internal points
666 // ~~~~~~~~~~~~~~~~~~~~~~~~
667
668 forAll(donePoint, pointi)
669 {
670 if (!donePoint.test(pointi))
671 {
672 labelList dualFace, featEdgeIndices;
673
674 collectPatchInternalFace
675 (
676 patch,
677 patchToDualOffset,
678 edgeToDualPoint,
679 pointi,
680 patch.pointEdges()[pointi][0], // Arbitrary starting edge
681
682 dualFace,
683 featEdgeIndices
684 );
685
686 //- Either keep in one piece or split face according to feature.
687
689 //dualFaces.append(face(dualFace));
690 //dualOwner.append(patch.meshPoints()[pointi]);
691 //dualNeighbour.append(-1);
692 //dualRegion.append(patch.index());
693
694 splitFace
695 (
696 patch,
697 pointToDualPoint,
698 pointi,
699 dualFace,
700 featEdgeIndices,
701
702 dualFaces,
703 dualOwner,
704 dualNeighbour,
705 dualRegion
706 );
707
708 donePoint[pointi] = true;
709 }
710 }
711}
712
713
714void Foam::polyDualMesh::calcDual
715(
716 const polyMesh& mesh,
717 const labelList& featureEdges,
718 const labelList& featurePoints
719)
720{
721 const polyBoundaryMesh& patches = mesh.boundaryMesh();
722 const label nIntFaces = mesh.nInternalFaces();
723
724
725 // Get patch for all of outside
726 primitivePatch allBoundary
727 (
728 SubList<face>
729 (
730 mesh.faces(),
733 ),
734 mesh.points()
735 );
736
737 // Correspondence from patch edge to mesh edge.
738 labelList meshEdges
739 (
740 allBoundary.meshEdges
741 (
742 mesh.edges(),
744 )
745 );
746
747 {
748 pointSet nonManifoldPoints
749 (
750 mesh,
751 "nonManifoldPoints",
752 meshEdges.size() / 100
753 );
754
755 allBoundary.checkPointManifold(true, &nonManifoldPoints);
756
757 if (nonManifoldPoints.size())
758 {
759 nonManifoldPoints.write();
760
762 << "There are " << nonManifoldPoints.size() << " points where"
763 << " the outside of the mesh is non-manifold." << nl
764 << "Such a mesh cannot be converted to a dual." << nl
765 << "Writing points at non-manifold sites to pointSet "
766 << nonManifoldPoints.name()
767 << exit(FatalError);
768 }
769 }
770
771
772 // Assign points
773 // ~~~~~~~~~~~~~
774
775 // mesh label dualMesh vertex
776 // ---------- ---------------
777 // celli celli
778 // facei nCells+facei-nIntFaces
779 // featEdgeI nCells+nFaces-nIntFaces+featEdgeI
780 // featPointi nCells+nFaces-nIntFaces+nFeatEdges+featPointi
781
782 pointField dualPoints
783 (
784 mesh.nCells() // cell centres
785 + mesh.nBoundaryFaces() // boundary face centres
786 + featureEdges.size() // additional boundary edges
787 + featurePoints.size() // additional boundary points
788 );
789
790 label dualPointi = 0;
791
792
793 // Cell centres.
794 const pointField& cellCentres = mesh.cellCentres();
795
796 cellPoint_.setSize(cellCentres.size());
797
798 forAll(cellCentres, celli)
799 {
800 cellPoint_[celli] = dualPointi;
801 dualPoints[dualPointi++] = cellCentres[celli];
802 }
803
804 // Boundary faces centres
805 const pointField& faceCentres = mesh.faceCentres();
806
807 boundaryFacePoint_.setSize(mesh.nBoundaryFaces());
808
809 for (label facei = nIntFaces; facei < mesh.nFaces(); facei++)
810 {
811 boundaryFacePoint_[facei - nIntFaces] = dualPointi;
812 dualPoints[dualPointi++] = faceCentres[facei];
813 }
814
815 // Edge status:
816 // >0 : dual point label (edge is feature edge)
817 // -1 : is boundary edge.
818 // -2 : is internal edge.
819 labelList edgeToDualPoint(mesh.nEdges(), -2);
820
821 forAll(meshEdges, patchEdgeI)
822 {
823 label edgeI = meshEdges[patchEdgeI];
824
825 edgeToDualPoint[edgeI] = -1;
826 }
827
828 forAll(featureEdges, i)
829 {
830 label edgeI = featureEdges[i];
831
832 const edge& e = mesh.edges()[edgeI];
833
834 edgeToDualPoint[edgeI] = dualPointi;
835 dualPoints[dualPointi++] = e.centre(mesh.points());
836 }
837
838
839
840 // Point status:
841 // >0 : dual point label (point is feature point)
842 // -1 : is point on edge of patch
843 // -2 : is point on patch (but not on edge)
844 // -3 : is internal point.
845 labelList pointToDualPoint(mesh.nPoints(), -3);
846
847 forAll(patches, patchi)
848 {
849 const labelList& meshPoints = patches[patchi].meshPoints();
850
851 forAll(meshPoints, i)
852 {
853 pointToDualPoint[meshPoints[i]] = -2;
854 }
855
856 const labelListList& loops = patches[patchi].edgeLoops();
857
858 forAll(loops, i)
859 {
860 const labelList& loop = loops[i];
861
862 forAll(loop, j)
863 {
864 pointToDualPoint[meshPoints[loop[j]]] = -1;
865 }
866 }
867 }
868
869 forAll(featurePoints, i)
870 {
871 label pointi = featurePoints[i];
872
873 pointToDualPoint[pointi] = dualPointi;
874 dualPoints[dualPointi++] = mesh.points()[pointi];
875 }
876
877
878 // Storage for new faces.
879 // Dynamic sized since we don't know size.
880
881 DynamicList<face> dynDualFaces(mesh.nEdges());
882 DynamicList<label> dynDualOwner(mesh.nEdges());
883 DynamicList<label> dynDualNeighbour(mesh.nEdges());
884 DynamicList<label> dynDualRegion(mesh.nEdges());
885
886
887 // Generate faces from edges on the boundary
888 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
889
890 forAll(meshEdges, patchEdgeI)
891 {
892 label edgeI = meshEdges[patchEdgeI];
893
894 const edge& e = mesh.edges()[edgeI];
895
896 label owner = -1;
897 label neighbour = -1;
898
899 if (e[0] < e[1])
900 {
901 owner = e[0];
902 neighbour = e[1];
903 }
904 else
905 {
906 owner = e[1];
907 neighbour = e[0];
908 }
909
910 // Find the boundary faces using the edge.
911 const labelList& patchFaces = allBoundary.edgeFaces()[patchEdgeI];
912
913 if (patchFaces.size() != 2)
914 {
916 << "Cannot handle edges with " << patchFaces.size()
917 << " connected boundary faces."
918 << abort(FatalError);
919 }
920
921 label face0 = patchFaces[0] + nIntFaces;
922 const face& f0 = mesh.faces()[face0];
923
924 label face1 = patchFaces[1] + nIntFaces;
925
926 // We want to start walking from patchFaces[0] or patchFaces[1],
927 // depending on which one uses owner,neighbour in the right order.
928
929 label startFacei = -1;
930 label endFacei = -1;
931
932 label index = f0.find(neighbour);
933
934 if (f0.nextLabel(index) == owner)
935 {
936 startFacei = face0;
937 endFacei = face1;
938 }
939 else
940 {
941 startFacei = face1;
942 endFacei = face0;
943 }
944
945 // Now walk from startFacei to cell to face to cell etc. until endFacei
946
947 DynamicList<label> dualFace;
948
949 if (edgeToDualPoint[edgeI] >= 0)
950 {
951 // Number of cells + 2 boundary faces + feature edge point
952 dualFace.setCapacity(mesh.edgeCells()[edgeI].size()+2+1);
953 // Store dualVertex for feature edge
954 dualFace.append(edgeToDualPoint[edgeI]);
955 }
956 else
957 {
958 dualFace.setCapacity(mesh.edgeCells()[edgeI].size()+2);
959 }
960
961 // Store dual vertex for starting face.
962 dualFace.append(mesh.nCells() + startFacei - nIntFaces);
963
964 label celli = mesh.faceOwner()[startFacei];
965 label facei = startFacei;
966
967 while (true)
968 {
969 // Store dual vertex from celli.
970 dualFace.append(celli);
971
972 // Cross cell to other face on edge.
973 label f0, f1;
974 meshTools::getEdgeFaces(mesh, celli, edgeI, f0, f1);
975
976 if (f0 == facei)
977 {
978 facei = f1;
979 }
980 else
981 {
982 facei = f0;
983 }
984
985 // Cross face to other cell.
986 if (facei == endFacei)
987 {
988 break;
989 }
990
991 if (mesh.faceOwner()[facei] == celli)
992 {
993 celli = mesh.faceNeighbour()[facei];
994 }
995 else
996 {
997 celli = mesh.faceOwner()[facei];
998 }
999 }
1000
1001 // Store dual vertex for endFace.
1002 dualFace.append(mesh.nCells() + endFacei - nIntFaces);
1003
1004 dynDualFaces.append(face(dualFace.shrink()));
1005 dynDualOwner.append(owner);
1006 dynDualNeighbour.append(neighbour);
1007 dynDualRegion.append(-1);
1008
1009 {
1010 // Check orientation.
1011 const face& f = dynDualFaces.last();
1012 const vector areaNorm = f.areaNormal(dualPoints);
1013
1014 if (((mesh.points()[owner] - dualPoints[f[0]]) & areaNorm) > 0)
1015 {
1017 << " on boundary edge:" << edgeI
1018 << mesh.points()[mesh.edges()[edgeI][0]]
1019 << mesh.points()[mesh.edges()[edgeI][1]]
1020 << endl;
1021 }
1022 }
1023 }
1024
1025
1026 // Generate faces from internal edges
1027 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1028
1029 forAll(edgeToDualPoint, edgeI)
1030 {
1031 if (edgeToDualPoint[edgeI] == -2)
1032 {
1033 // Internal edge.
1034
1035 // Find dual owner, neighbour
1036
1037 const edge& e = mesh.edges()[edgeI];
1038
1039 label owner = -1;
1040 label neighbour = -1;
1041
1042 if (e[0] < e[1])
1043 {
1044 owner = e[0];
1045 neighbour = e[1];
1046 }
1047 else
1048 {
1049 owner = e[1];
1050 neighbour = e[0];
1051 }
1052
1053 // Get a starting cell
1054 const labelList& eCells = mesh.edgeCells()[edgeI];
1055
1056 label celli = eCells[0];
1057
1058 // Get the two faces on the cell and edge.
1059 label face0, face1;
1060 meshTools::getEdgeFaces(mesh, celli, edgeI, face0, face1);
1061
1062 // Find the starting face by looking at the order in which
1063 // the face uses the owner, neighbour
1064 const face& f0 = mesh.faces()[face0];
1065
1066 label index = f0.find(neighbour);
1067
1068 bool f0OrderOk = (f0.nextLabel(index) == owner);
1069
1070 label startFacei = -1;
1071
1072 if (f0OrderOk == (mesh.faceOwner()[face0] == celli))
1073 {
1074 startFacei = face0;
1075 }
1076 else
1077 {
1078 startFacei = face1;
1079 }
1080
1081 // Walk face-cell-face until starting face reached.
1082 DynamicList<label> dualFace(mesh.edgeCells()[edgeI].size());
1083
1084 label facei = startFacei;
1085
1086 while (true)
1087 {
1088 // Store dual vertex from celli.
1089 dualFace.append(celli);
1090
1091 // Cross cell to other face on edge.
1092 label f0, f1;
1093 meshTools::getEdgeFaces(mesh, celli, edgeI, f0, f1);
1094
1095 if (f0 == facei)
1096 {
1097 facei = f1;
1098 }
1099 else
1100 {
1101 facei = f0;
1102 }
1103
1104 // Cross face to other cell.
1105 if (facei == startFacei)
1106 {
1107 break;
1108 }
1109
1110 if (mesh.faceOwner()[facei] == celli)
1111 {
1112 celli = mesh.faceNeighbour()[facei];
1113 }
1114 else
1115 {
1116 celli = mesh.faceOwner()[facei];
1117 }
1118 }
1119
1120 dynDualFaces.append(face(dualFace.shrink()));
1121 dynDualOwner.append(owner);
1122 dynDualNeighbour.append(neighbour);
1123 dynDualRegion.append(-1);
1124
1125 {
1126 // Check orientation.
1127 const face& f = dynDualFaces.last();
1128 const vector areaNorm = f.areaNormal(dualPoints);
1129
1130 if (((mesh.points()[owner] - dualPoints[f[0]]) & areaNorm) > 0)
1131 {
1133 << " on internal edge:" << edgeI
1134 << mesh.points()[mesh.edges()[edgeI][0]]
1135 << mesh.points()[mesh.edges()[edgeI][1]]
1136 << endl;
1137 }
1138 }
1139 }
1140 }
1141
1142 // Dump faces.
1143 if (debug)
1144 {
1145 dynDualFaces.shrink();
1146 dynDualOwner.shrink();
1147 dynDualNeighbour.shrink();
1148 dynDualRegion.shrink();
1149
1150 OFstream str("dualInternalFaces.obj");
1151 Pout<< "polyDualMesh::calcDual : dumping internal faces to "
1152 << str.name() << endl;
1153
1154 forAll(dualPoints, dualPointi)
1155 {
1156 meshTools::writeOBJ(str, dualPoints[dualPointi]);
1157 }
1158 forAll(dynDualFaces, dualFacei)
1159 {
1160 const face& f = dynDualFaces[dualFacei];
1161
1162 str<< 'f';
1163 forAll(f, fp)
1164 {
1165 str<< ' ' << f[fp]+1;
1166 }
1167 str<< nl;
1168 }
1169 }
1170
1171 const label nInternalFaces = dynDualFaces.size();
1172
1173 // Outside faces
1174 // ~~~~~~~~~~~~~
1175
1176 forAll(patches, patchi)
1177 {
1178 const polyPatch& pp = patches[patchi];
1179
1180 dualPatch
1181 (
1182 pp,
1183 mesh.nCells() + pp.start() - nIntFaces,
1184 edgeToDualPoint,
1185 pointToDualPoint,
1186
1187 dualPoints,
1188
1189 dynDualFaces,
1190 dynDualOwner,
1191 dynDualNeighbour,
1192 dynDualRegion
1193 );
1194 }
1195
1196
1197 // Transfer face info to straight lists
1198 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1199 faceList dualFaces(std::move(dynDualFaces));
1200 labelList dualOwner(std::move(dynDualOwner));
1201 labelList dualNeighbour(std::move(dynDualNeighbour));
1202 labelList dualRegion(std::move(dynDualRegion));
1203
1204
1205 // Dump faces.
1206 if (debug)
1207 {
1208 OFstream str("dualFaces.obj");
1209 Pout<< "polyDualMesh::calcDual : dumping all faces to "
1210 << str.name() << endl;
1211
1212 forAll(dualPoints, dualPointi)
1213 {
1214 meshTools::writeOBJ(str, dualPoints[dualPointi]);
1215 }
1216 forAll(dualFaces, dualFacei)
1217 {
1218 const face& f = dualFaces[dualFacei];
1219
1220 str<< 'f';
1221 forAll(f, fp)
1222 {
1223 str<< ' ' << f[fp]+1;
1224 }
1225 str<< nl;
1226 }
1227 }
1228
1229 // Create cells.
1230 cellList dualCells(mesh.nPoints());
1231
1232 forAll(dualCells, celli)
1233 {
1234 dualCells[celli].setSize(0);
1235 }
1236
1237 forAll(dualOwner, facei)
1238 {
1239 label celli = dualOwner[facei];
1240
1241 labelList& cFaces = dualCells[celli];
1242
1243 label sz = cFaces.size();
1244 cFaces.setSize(sz+1);
1245 cFaces[sz] = facei;
1246 }
1247 forAll(dualNeighbour, facei)
1248 {
1249 label celli = dualNeighbour[facei];
1250
1251 if (celli != -1)
1252 {
1253 labelList& cFaces = dualCells[celli];
1254
1255 label sz = cFaces.size();
1256 cFaces.setSize(sz+1);
1257 cFaces[sz] = facei;
1258 }
1259 }
1260
1261
1262 // Do upper-triangular face ordering. Determines face reordering map and
1263 // number of internal faces.
1264 label dummy;
1265
1266 labelList oldToNew
1267 (
1268 getFaceOrder
1269 (
1270 dualOwner,
1271 dualNeighbour,
1272 dualCells,
1273 dummy
1274 )
1275 );
1276
1277 // Reorder faces.
1278 inplaceReorder(oldToNew, dualFaces);
1279 inplaceReorder(oldToNew, dualOwner);
1280 inplaceReorder(oldToNew, dualNeighbour);
1281 inplaceReorder(oldToNew, dualRegion);
1282 forAll(dualCells, celli)
1283 {
1284 inplaceRenumber(oldToNew, dualCells[celli]);
1285 }
1286
1287
1288 // Create patches
1289 labelList patchSizes(patches.size(), Zero);
1290
1291 forAll(dualRegion, facei)
1292 {
1293 if (dualRegion[facei] >= 0)
1294 {
1295 patchSizes[dualRegion[facei]]++;
1296 }
1297 }
1298
1299 labelList patchStarts(patches.size(), Zero);
1300
1301 label facei = nInternalFaces;
1302
1303 forAll(patches, patchi)
1304 {
1305 patchStarts[patchi] = facei;
1306
1307 facei += patchSizes[patchi];
1308 }
1309
1310
1311 Pout<< "nFaces:" << dualFaces.size()
1312 << " patchSizes:" << patchSizes
1313 << " patchStarts:" << patchStarts
1314 << endl;
1315
1316
1317 // Add patches. First add zero sized (since mesh still 0 size)
1318 List<polyPatch*> dualPatches(patches.size());
1319
1320 forAll(patches, patchi)
1321 {
1322 const polyPatch& pp = patches[patchi];
1323
1324 dualPatches[patchi] = pp.clone
1325 (
1326 boundaryMesh(),
1327 patchi,
1328 0, //patchSizes[patchi],
1329 0 //patchStarts[patchi]
1330 ).ptr();
1331 }
1332 addPatches(dualPatches);
1333
1334 // Assign to mesh.
1335 resetPrimitives
1336 (
1337 autoPtr<pointField>::New(std::move(dualPoints)),
1338 autoPtr<faceList>::New(std::move(dualFaces)),
1339 autoPtr<labelList>::New(std::move(dualOwner)),
1340 autoPtr<labelList>::New(std::move(dualNeighbour)),
1341 patchSizes,
1342 patchStarts
1343 );
1344}
1345
1346
1347// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1348
1349// Construct from components
1351:
1352 polyMesh(io),
1353 cellPoint_
1354 (
1355 IOobject
1356 (
1357 "cellPoint",
1358 time().findInstance(meshDir(), "cellPoint"),
1359 meshSubDir,
1360 *this,
1361 IOobject::MUST_READ,
1362 IOobject::NO_WRITE
1363 )
1364 ),
1365 boundaryFacePoint_
1366 (
1367 IOobject
1368 (
1369 "boundaryFacePoint",
1370 time().findInstance(meshDir(), "boundaryFacePoint"),
1371 meshSubDir,
1372 *this,
1373 IOobject::MUST_READ,
1374 IOobject::NO_WRITE
1375 )
1376 )
1377{}
1378
1379
1380// Construct from polyMesh
1382(
1383 const polyMesh& mesh,
1384 const labelList& featureEdges,
1385 const labelList& featurePoints
1386)
1387:
1388 polyMesh(mesh, Zero),
1389 cellPoint_
1390 (
1391 IOobject
1392 (
1393 "cellPoint",
1394 time().findInstance(meshDir(), "faces"),
1395 meshSubDir,
1396 *this,
1397 IOobject::NO_READ,
1398 IOobject::AUTO_WRITE
1399 ),
1400 labelList(mesh.nCells(), -1)
1401 ),
1402 boundaryFacePoint_
1403 (
1404 IOobject
1405 (
1406 "boundaryFacePoint",
1407 time().findInstance(meshDir(), "faces"),
1408 meshSubDir,
1409 *this,
1410 IOobject::NO_READ,
1411 IOobject::AUTO_WRITE
1412 ),
1413 labelList(mesh.nBoundaryFaces(), -1)
1414 )
1415{
1416 calcDual(mesh, featureEdges, featurePoints);
1417}
1418
1419
1420// Construct from polyMesh and feature angle
1422(
1423 const polyMesh& mesh,
1424 const scalar featureCos
1425)
1426:
1427 polyMesh(mesh, Zero),
1428 cellPoint_
1429 (
1430 IOobject
1431 (
1432 "cellPoint",
1433 time().findInstance(meshDir(), "faces"),
1434 meshSubDir,
1435 *this,
1436 IOobject::NO_READ,
1437 IOobject::AUTO_WRITE
1438 ),
1439 labelList(mesh.nCells(), -1)
1440 ),
1441 boundaryFacePoint_
1442 (
1443 IOobject
1444 (
1445 "boundaryFacePoint",
1446 time().findInstance(meshDir(), "faces"),
1447 meshSubDir,
1448 *this,
1449 IOobject::NO_READ,
1450 IOobject::AUTO_WRITE
1451 ),
1452 labelList(mesh.nBoundaryFaces(), -1)
1453 )
1454{
1455 labelList featureEdges, featurePoints;
1456
1457 calcFeatures(mesh, featureCos, featureEdges, featurePoints);
1458 calcDual(mesh, featureEdges, featurePoints);
1459}
1460
1461
1463(
1464 const polyMesh& mesh,
1465 const scalar featureCos,
1466 labelList& featureEdges,
1467 labelList& featurePoints
1468)
1469{
1470 // Create big primitivePatch for all outside.
1471 primitivePatch allBoundary
1472 (
1474 (
1475 mesh.faces(),
1478 ),
1479 mesh.points()
1480 );
1481
1482 // For ease of use store patch number per face in allBoundary.
1483 labelList allRegion(allBoundary.size());
1484
1486
1487 forAll(patches, patchi)
1488 {
1489 const polyPatch& pp = patches[patchi];
1490
1491 forAll(pp, i)
1492 {
1493 allRegion[i + pp.start() - mesh.nInternalFaces()] = patchi;
1494 }
1495 }
1496
1497
1498 // Calculate patch/feature edges
1499 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1500
1501 const labelListList& edgeFaces = allBoundary.edgeFaces();
1502 const vectorField& faceNormals = allBoundary.faceNormals();
1503 const labelList& meshPoints = allBoundary.meshPoints();
1504
1505 bitSet isFeatureEdge(edgeFaces.size(), false);
1506
1507 forAll(edgeFaces, edgeI)
1508 {
1509 const labelList& eFaces = edgeFaces[edgeI];
1510
1511 if (eFaces.size() != 2)
1512 {
1513 // Non-manifold. Problem?
1514 const edge& e = allBoundary.edges()[edgeI];
1515
1517 << meshPoints[e[0]] << ' ' << meshPoints[e[1]]
1518 << " coords:" << mesh.points()[meshPoints[e[0]]]
1519 << mesh.points()[meshPoints[e[1]]]
1520 << " has more than 2 faces connected to it:"
1521 << eFaces.size() << endl;
1522
1523 isFeatureEdge.set(edgeI);
1524 }
1525 else if (allRegion[eFaces[0]] != allRegion[eFaces[1]])
1526 {
1527 isFeatureEdge.set(edgeI);
1528 }
1529 else if
1530 (
1531 (faceNormals[eFaces[0]] & faceNormals[eFaces[1]])
1532 < featureCos
1533 )
1534 {
1535 isFeatureEdge.set(edgeI);
1536 }
1537 }
1538
1539
1540 // Calculate feature points
1541 // ~~~~~~~~~~~~~~~~~~~~~~~~
1542
1543 const labelListList& pointEdges = allBoundary.pointEdges();
1544
1545 DynamicList<label> allFeaturePoints(pointEdges.size());
1546
1547 forAll(pointEdges, pointi)
1548 {
1549 const labelList& pEdges = pointEdges[pointi];
1550
1551 label nFeatEdges = 0;
1552
1553 forAll(pEdges, i)
1554 {
1555 if (isFeatureEdge.test(pEdges[i]))
1556 {
1557 ++nFeatEdges;
1558 }
1559 }
1560 if (nFeatEdges > 2)
1561 {
1562 // Store in mesh vertex label
1563 allFeaturePoints.append(allBoundary.meshPoints()[pointi]);
1564 }
1565 }
1566 featurePoints.transfer(allFeaturePoints);
1567
1568 if (debug)
1569 {
1570 OFstream str("featurePoints.obj");
1571
1572 Pout<< "polyDualMesh::calcFeatures : dumping feature points to "
1573 << str.name() << endl;
1574
1575 forAll(featurePoints, i)
1576 {
1577 label pointi = featurePoints[i];
1578 meshTools::writeOBJ(str, mesh.points()[pointi]);
1579 }
1580 }
1581
1582
1583 // Get all feature edges.
1584 labelList meshEdges
1585 (
1586 allBoundary.meshEdges
1587 (
1588 mesh.edges(),
1589 mesh.cellEdges(),
1591 (
1592 mesh.faceOwner(),
1593 allBoundary.size(),
1595 )
1596 )
1597 );
1598
1599 DynamicList<label> allFeatureEdges(isFeatureEdge.size());
1600 forAll(isFeatureEdge, edgeI)
1601 {
1602 if (isFeatureEdge.test(edgeI))
1603 {
1604 // Store in mesh edge label.
1605 allFeatureEdges.append(meshEdges[edgeI]);
1606 }
1607 }
1608 featureEdges.transfer(allFeatureEdges);
1609}
1610
1611
1612// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
1613
1615{}
1616
1617
1618// ************************************************************************* //
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
label size() const noexcept
The number of elements in table.
Definition: HashTableI.H:52
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:170
void transfer(List< T > &list)
Definition: List.C:447
void setSize(const label n)
Alias for resize()
Definition: List.H:218
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:175
Output to file stream, using an OSstream.
Definition: OFstream.H:57
virtual const fileName & name() const
Read/write access to the name of the stream.
Definition: OSstream.H:107
virtual const fileName & name() const
Get the name of the stream.
Definition: OSstream.H:107
label size() const noexcept
Number of entries.
Definition: PackedListI.H:377
A list of faces which address into the list of points.
const labelListList & pointEdges() const
Return point-edge addressing.
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
labelList meshEdges(const edgeList &allEdges, const labelListList &cellEdges, const labelList &faceCells) const
const labelList & meshPoints() const
Return labelList of mesh points in patch.
const Field< point_type > & faceNormals() const
Return face unit normals for patch.
const labelListList & edgeFaces() const
Return edge-face addressing.
PtrList< T > clone(Args &&... args) const
Make a copy by cloning each of the list elements.
A List obtained as a section of another List.
Definition: SubList.H:70
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
Definition: Time.C:717
label find(const T &val, label pos=0) const
Find index of the first occurrence of the value.
Definition: UList.C:212
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
T & last()
Return the last element of the list.
Definition: UListI.H:216
label size() const noexcept
The number of elements in the list.
Definition: UPtrListI.H:106
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
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:66
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Creates dual of polyMesh.
Definition: polyDualMesh.H:60
~polyDualMesh()
Destructor.
static void calcFeatures(const polyMesh &, const scalar featureCos, labelList &featureEdges, labelList &featurePoints)
Helper function to create feature edges and points based on.
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 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
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:75
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:364
label nBoundaryFaces() const noexcept
Number of boundary faces (== nFaces - nInternalFaces)
const labelListList & pointEdges() const
const edgeList & edges() const
Return mesh edges. Uses calcEdges.
const labelListList & cellEdges() const
const vectorField & faceCentres() const
label nInternalFaces() const noexcept
Number of internal faces.
const vectorField & cellCentres() const
label nPoints() const noexcept
Number of mesh points.
label nCells() const noexcept
Number of mesh cells.
label nFaces() const noexcept
Number of mesh faces.
const labelListList & edgeCells() const
const cellList & cells() const
label nEdges() const
Number of mesh edges.
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 polyBoundaryMesh & patches
dynamicFvMesh & mesh
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
const cellShapeList & cells
surfaceVectorField faceNormals(mesh.Sf()/mesh.magSf())
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, false)
#define WarningInFunction
Report a warning using Foam::Warning.
const std::string patch
OpenFOAM patch number as a std::string.
void getEdgeFaces(const primitiveMesh &mesh, const label celli, const label edgeI, label &face0, label &face1)
Get faces on cell using edgeI. Throws error if no two found.
Definition: meshTools.C:479
void writeOBJ(Ostream &os, const point &pt)
Write obj representation of a point.
Definition: meshTools.C:203
Namespace for OpenFOAM.
void inplaceRenumber(const labelUList &oldToNew, IntListType &input)
Inplace renumber the values (not the indices) of a list.
List< label > labelList
A List of labels.
Definition: List.H:66
List< cell > cellList
A List of cells.
Definition: cellListFwd.H:47
void reverse(UList< T > &list, const label n)
Reverse the first n elements of the list.
Definition: UListI.H:449
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
A PrimitivePatch with a SubList addressing for the faces, const reference for the point field.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
Inplace reorder the elements of a list.
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
errorManip< error > abort(error &err)
Definition: errorManip.H:144
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
error FatalError
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
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)
volScalarField & e
Definition: createFields.H:11
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333