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 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 InClass
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 
42 namespace Foam
43 {
44  defineTypeNameAndDebug(polyDualMesh, 0);
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)
52 Foam::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
148 void 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.
217 Foam::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.
331 void 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 
434 void 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
577 void 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 
714 void 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(),
743  mesh.pointEdges()
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  // unnecessary...
1233  // forAll(dualCells, celli)
1234  // {
1235  // dualCells[celli].clear();
1236  // }
1237 
1238  forAll(dualOwner, facei)
1239  {
1240  label celli = dualOwner[facei];
1241 
1242  if (celli != -1)
1243  {
1244  dualCells[celli].push_back(facei);
1245  }
1246  }
1247  forAll(dualNeighbour, facei)
1248  {
1249  label celli = dualNeighbour[facei];
1250 
1251  if (celli != -1)
1252  {
1253  dualCells[celli].push_back(facei);
1254  }
1255  }
1256 
1257 
1258  // Do upper-triangular face ordering. Determines face reordering map and
1259  // number of internal faces.
1260  label dummy;
1261 
1262  labelList oldToNew
1263  (
1264  getFaceOrder
1265  (
1266  dualOwner,
1267  dualNeighbour,
1268  dualCells,
1269  dummy
1270  )
1271  );
1272 
1273  // Reorder faces.
1274  inplaceReorder(oldToNew, dualFaces);
1275  inplaceReorder(oldToNew, dualOwner);
1276  inplaceReorder(oldToNew, dualNeighbour);
1277  inplaceReorder(oldToNew, dualRegion);
1278  forAll(dualCells, celli)
1279  {
1280  inplaceRenumber(oldToNew, dualCells[celli]);
1281  }
1282 
1283 
1284  // Create patches
1285  labelList patchSizes(patches.size(), Zero);
1286 
1287  forAll(dualRegion, facei)
1288  {
1289  if (dualRegion[facei] >= 0)
1290  {
1291  patchSizes[dualRegion[facei]]++;
1292  }
1293  }
1294 
1295  labelList patchStarts(patches.size(), Zero);
1296 
1297  label facei = nInternalFaces;
1298 
1299  forAll(patches, patchi)
1300  {
1301  patchStarts[patchi] = facei;
1302 
1303  facei += patchSizes[patchi];
1304  }
1305 
1306 
1307  Pout<< "nFaces:" << dualFaces.size()
1308  << " patchSizes:" << patchSizes
1309  << " patchStarts:" << patchStarts
1310  << endl;
1311 
1312 
1313  // Add patches. First add zero sized (since mesh still 0 size)
1314  polyPatchList dualPatches(patches.size());
1315 
1316  forAll(patches, patchi)
1317  {
1318  const polyPatch& pp = patches[patchi];
1319 
1320  dualPatches.set
1321  (
1322  patchi,
1323  pp.clone
1324  (
1325  boundaryMesh(),
1326  patchi,
1327  0, //patchSizes[patchi],
1328  0 //patchStarts[patchi]
1329  )
1330  );
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 }
1346 
1347 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1348 
1349 // Construct from components
1350 Foam::polyDualMesh::polyDualMesh(const IOobject& io)
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
1381 Foam::polyDualMesh::polyDualMesh
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);
1418 
1419 
1420 // Construct from polyMesh and feature angle
1421 Foam::polyDualMesh::polyDualMesh
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(),
1476  mesh.nBoundaryFaces(),
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(),
1590  SubList<label>
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);
1610 
1611 
1612 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
1613 
1615 {}
1616 
1617 
1618 // ************************************************************************* //
const labelListList & cellEdges() const
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
List< cell > cellList
List of cell.
Definition: cellListFwd.H:39
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
void transfer(List< T > &list)
Transfer the contents of the argument List into this list and annul the argument list.
Definition: List.C:326
label nPoints() const noexcept
Number of mesh points.
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
void append(const T &val)
Append an element at the end of the list.
Definition: List.H:517
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1122
const labelListList & pointEdges() const
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
static void calcFeatures(const polyMesh &, const scalar featureCos, labelList &featureEdges, labelList &featurePoints)
Helper function to create feature edges and points based on.
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
Inplace reorder the elements of a list.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
const cellList & cells() const
void writeOBJ(Ostream &os, const point &pt)
Write obj representation of a point.
Definition: meshTools.C:196
label nFaces() const noexcept
Number of mesh faces.
virtual const fileName & name() const override
Get the name of the output serial stream. (eg, the name of the Fstream file name) ...
Definition: OSstream.H:128
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1078
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
List< face > faceList
List of faces.
Definition: faceListFwd.H:39
const labelListList & edgeCells() const
PtrList< polyPatch > polyPatchList
Store lists of polyPatch as a PtrList.
Definition: polyPatch.H:56
label size() const noexcept
The number of elements in table.
Definition: HashTable.H:342
A list of faces which address into the list of points.
A List obtained as a section of another List.
Definition: SubList.H:50
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
void setSize(const label n)
Alias for resize()
Definition: List.H:316
dynamicFvMesh & mesh
const cellShapeList & cells
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition: polyMesh.H:608
label size() const noexcept
The number of entries in the list.
Definition: UPtrListI.H:106
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1116
label nInternalFaces() const noexcept
Number of internal faces.
void reverse(UList< T > &list, const label n)
Reverse the first n elements of the list.
Definition: UListI.H:520
Vector< scalar > vector
Definition: vector.H:57
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1103
const vectorField & cellCentres() const
errorManip< error > abort(error &err)
Definition: errorManip.H:139
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie...
Definition: PtrList.H:159
label nEdges() const
Number of mesh edges.
label find(const T &val) const
Find index of the first occurrence of the value.
Definition: UList.C:173
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO...
int debug
Static debugging option.
defineTypeNameAndDebug(combustionModel, 0)
labelList f(nPoints)
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
A PrimitivePatch with a SubList addressing for the faces, const reference for the point field...
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=cellModel::ref(cellModel::HEX);labelList hexLabels(8);label activeCells=0;labelList pointMap(nPoints);forAll(pointMap, i){ pointMap[i]=i;}for(label i=0;i< nPoints;i++){ if(f[i] > 0.0) { hexLabels[0]=i;hexLabels[1]=i1tab[i];hexLabels[2]=i3tab[i1tab[i]];hexLabels[3]=i3tab[i];hexLabels[4]=i8tab[i];hexLabels[5]=i1tab[i8tab[i]];hexLabels[6]=i3tab[i1tab[i8tab[i]]];hexLabels[7]=i3tab[i8tab[i]];cellShapes[activeCells].reset(hex, hexLabels);edgeList edges=cellShapes[activeCells].edges();forAll(edges, ei) { if(edges[ei].mag(points)< SMALL) { label start=pointMap[edges[ei].start()];while(start !=pointMap[start]) { start=pointMap[start];} label end=pointMap[edges[ei].end()];while(end !=pointMap[end]) { end=pointMap[end];} label minLabel=min(start, end);pointMap[start]=pointMap[end]=minLabel;} } cellZoning[activeCells]=idreg[i];activeCells++;}}cellShapes.setSize(activeCells);cellZoning.setSize(activeCells);forAll(cellShapes, celli){ cellShape &cs=cellShapes[celli];forAll(cs, i) { cs[i]=pointMap[cs[i]];} cs.collapse();}label bcIDs[11]={-1, 0, 2, 4, -1, 5, -1, 6, 7, 8, 9};const label nBCs=12;const word *kivaPatchTypes[nBCs]={ &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &symmetryPolyPatch::typeName, &wedgePolyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &symmetryPolyPatch::typeName, &oldCyclicPolyPatch::typeName};enum patchTypeNames{ PISTON, VALVE, LINER, CYLINDERHEAD, AXIS, WEDGE, INFLOW, OUTFLOW, PRESIN, PRESOUT, SYMMETRYPLANE, CYCLIC};const char *kivaPatchNames[nBCs]={ "piston", "valve", "liner", "cylinderHead", "axis", "wedge", "inflow", "outflow", "presin", "presout", "symmetryPlane", "cyclic"};List< SLList< face > > pFaces[nBCs]
Definition: readKivaGrid.H:235
T & last()
Access last element of the list, position [size()-1].
Definition: UList.H:867
~polyDualMesh()
Destructor.
const edgeList & edges() const
Return mesh edges. Uses calcEdges.
const vectorField & faceCentres() const
void inplaceRenumber(const labelUList &oldToNew, IntListType &input)
Inplace renumber the values (not the indices) of a list.
#define WarningInFunction
Report a warning using Foam::Warning.
label nCells() const noexcept
Number of mesh cells.
const polyBoundaryMesh & patches
const std::string patch
OpenFOAM patch number as a std::string.
Field< vector > vectorField
Specialisation of Field<T> for vector.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
List< label > labelList
A List of labels.
Definition: List.H:62
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
static autoPtr< T > New(Args &&... args)
Construct autoPtr with forwarding arguments.
Definition: autoPtr.H:178
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:69
label nBoundaryFaces() const noexcept
Number of boundary faces (== nFaces - nInternalFaces)
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:172
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
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:472
Namespace for OpenFOAM.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127