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