conformalVoronoiMeshCalcDualMesh.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 | Copyright (C) 2012-2015 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "conformalVoronoiMesh.H"
27 #include "motionSmoother.H"
29 #include "polyMeshGeometry.H"
30 #include "indexedCellChecks.H"
31 #include "OBJstream.H"
32 #include "indexedCellOps.H"
33 #include "ListOps.H"
34 #include "DelaunayMeshTools.H"
35 
36 // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
37 
39 (
41  labelList& boundaryPts,
42  faceList& faces,
43  labelList& owner,
44  labelList& neighbour,
46  PtrList<dictionary>& patchDicts,
47  pointField& cellCentres,
48  labelList& cellToDelaunayVertex,
49  labelListList& patchToDelaunayVertex,
50  PackedBoolList& boundaryFacesToRemove
51 )
52 {
53  timeCheck("Start calcDualMesh");
54 
56 
57  timeCheck("After setVertexSizeAndAlignment");
58 
59  indexDualVertices(points, boundaryPts);
60 
61  {
62  Info<< nl << "Merging identical points" << endl;
63 
64  // There is no guarantee that a merge of close points is no-risk
65  mergeIdenticalDualVertices(points, boundaryPts);
66  }
67 
68  // Final dual face and owner neighbour construction
69 
70  timeCheck("Before createFacesOwnerNeighbourAndPatches");
71 
73  (
74  points,
75  faces,
76  owner,
77  neighbour,
78  patchNames,
79  patchDicts,
80  patchToDelaunayVertex, // from patch face to Delaunay vertex (slavePp)
81  boundaryFacesToRemove,
82  false
83  );
84 
85  // deferredCollapseFaceSet(owner, neighbour, deferredCollapseFaces);
86 
87  cellCentres = DelaunayMeshTools::allPoints(*this);
88 
89  cellToDelaunayVertex = removeUnusedCells(owner, neighbour);
90 
91  cellCentres = pointField(cellCentres, cellToDelaunayVertex);
92 
93  removeUnusedPoints(faces, points, boundaryPts);
94 
95  timeCheck("End of calcDualMesh");
96 }
97 
98 
100 (
102  labelList& pointToDelaunayVertex,
103  faceList& faces,
104  labelList& owner,
105  labelList& neighbour,
107  PtrList<dictionary>& patchDicts
108 )
109 {
110  labelList vertexMap(number_of_vertices());
111 
112  label vertI = 0;
113 
114  points.setSize(number_of_vertices());
115  pointToDelaunayVertex.setSize(number_of_vertices());
116 
117  for
118  (
119  Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
120  vit != finite_vertices_end();
121  ++vit
122  )
123  {
124  if (vit->internalPoint() || vit->boundaryPoint())
125  {
126  vertexMap[vit->index()] = vertI;
127  points[vertI] = topoint(vit->point());
128  pointToDelaunayVertex[vertI] = vit->index();
129  vertI++;
130  }
131  }
132 
133  points.setSize(vertI);
134  pointToDelaunayVertex.setSize(vertI);
135 
136  label cellI = 0;
137 
138  for
139  (
140  Delaunay::Finite_cells_iterator cit = finite_cells_begin();
141  cit != finite_cells_end();
142  ++cit
143  )
144  {
145  if (cit->internalOrBoundaryDualVertex())
146  {
147  cit->cellIndex() = cellI++;
148  }
149  else
150  {
151  cit->cellIndex() = Cb::ctFar;
152  }
153  }
154 
155  patchNames = geometryToConformTo_.patchNames();
156 
158 
159  patchNames[patchNames.size() - 1] = "foamyHexMesh_defaultPatch";
160 
162 
163  List<DynamicList<face> > patchFaces(nPatches, DynamicList<face>(0));
164 
165  List<DynamicList<label> > patchOwners(nPatches, DynamicList<label>(0));
166 
167  faces.setSize(number_of_finite_facets());
168 
169  owner.setSize(number_of_finite_facets());
170 
171  neighbour.setSize(number_of_finite_facets());
172 
173  label faceI = 0;
174 
175  labelList verticesOnTriFace(3, label(-1));
176 
177  face newFace(verticesOnTriFace);
178 
179  for
180  (
181  Delaunay::Finite_facets_iterator fit = finite_facets_begin();
182  fit != finite_facets_end();
183  ++fit
184  )
185  {
186  const Cell_handle c1(fit->first);
187  const label oppositeVertex = fit->second;
188  const Cell_handle c2(c1->neighbor(oppositeVertex));
189 
190  if (c1->hasFarPoint() && c2->hasFarPoint())
191  {
192  // Both tets are outside, skip
193  continue;
194  }
195 
196  label c1I = c1->cellIndex();
197  label c2I = c2->cellIndex();
198 
199  label ownerCell = -1;
200  label neighbourCell = -1;
201 
202  for (label i = 0; i < 3; i++)
203  {
204  verticesOnTriFace[i] = vertexMap
205  [
206  c1->vertex(vertex_triple_index(oppositeVertex, i))->index()
207  ];
208  }
209 
210  newFace = face(verticesOnTriFace);
211 
212  if (c1->hasFarPoint() || c2->hasFarPoint())
213  {
214  // Boundary face...
215  if (c1->hasFarPoint())
216  {
217  //... with c1 outside
218  ownerCell = c2I;
219  }
220  else
221  {
222  // ... with c2 outside
223  ownerCell = c1I;
224 
225  reverse(newFace);
226  }
227 
228  label patchIndex = geometryToConformTo_.findPatch
229  (
230  newFace.centre(points)
231  );
232 
233  if (patchIndex == -1)
234  {
235  patchIndex = patchNames.size() - 1;
236 
238  << newFace.centre(points) << nl
239  << "did not find a surface patch. Adding to "
240  << patchNames[patchIndex]
241  << endl;
242  }
243 
244  patchFaces[patchIndex].append(newFace);
245  patchOwners[patchIndex].append(ownerCell);
246  }
247  else
248  {
249  // Internal face...
250  if (c1I < c2I)
251  {
252  // ...with c1 as the ownerCell
253  ownerCell = c1I;
254  neighbourCell = c2I;
255 
256  reverse(newFace);
257  }
258  else
259  {
260  // ...with c2 as the ownerCell
261  ownerCell = c2I;
262  neighbourCell = c1I;
263  }
264 
265  faces[faceI] = newFace;
266  owner[faceI] = ownerCell;
267  neighbour[faceI] = neighbourCell;
268  faceI++;
269  }
270  }
271 
272  label nInternalFaces = faceI;
273 
274  faces.setSize(nInternalFaces);
275  owner.setSize(nInternalFaces);
276  neighbour.setSize(nInternalFaces);
277 
278  sortFaces(faces, owner, neighbour);
279 
280 // PackedBoolList boundaryFacesToRemove;
281 // List<DynamicList<bool> > indirectPatchFace;
282 //
283 // addPatches
284 // (
285 // nInternalFaces,
286 // faces,
287 // owner,
288 // patchDicts,
289 // boundaryFacesToRemove,
290 // patchFaces,
291 // patchOwners,
292 // indirectPatchFace
293 // );
294 }
295 
296 
298 (
299  const pointField& pts,
300  labelList& boundaryPts
301 )
302 {
303  // Assess close points to be merged
304 
305  label nPtsMerged = 0;
306  label nPtsMergedSum = 0;
307 
308  do
309  {
310  Map<label> dualPtIndexMap;
311 
312  nPtsMerged = mergeIdenticalDualVertices
313  (
314  pts,
315  dualPtIndexMap
316  );
317 
318  reindexDualVertices(dualPtIndexMap, boundaryPts);
319 
320  reduce(nPtsMerged, sumOp<label>());
321 
322  nPtsMergedSum += nPtsMerged;
323 
324  } while (nPtsMerged > 0);
325 
326  if (nPtsMergedSum > 0)
327  {
328  Info<< " Merged " << nPtsMergedSum << " points " << endl;
329  }
330 }
331 
332 
334 (
335  const pointField& pts,
336  Map<label>& dualPtIndexMap
337 ) const
338 {
339  label nPtsMerged = 0;
340 
341  for
342  (
343  Delaunay::Finite_facets_iterator fit = finite_facets_begin();
344  fit != finite_facets_end();
345  ++fit
346  )
347  {
348  const Cell_handle c1(fit->first);
349  const label oppositeVertex = fit->second;
350  const Cell_handle c2(c1->neighbor(oppositeVertex));
351 
352  if (is_infinite(c1) || is_infinite(c2))
353  {
354  continue;
355  }
356 
357  label& c1I = c1->cellIndex();
358  label& c2I = c2->cellIndex();
359 
360  if ((c1I != c2I) && !c1->hasFarPoint() && !c2->hasFarPoint())
361  {
362  const Foam::point& p1 = pts[c1I];
363  const Foam::point& p2 = pts[c2I];
364 
365  if (p1 == p2)
366  {
367 // if (c1->parallelDualVertex() || c2->parallelDualVertex())
368 // {
369 // if (c1->vertexLowestProc() < c2->vertexLowestProc())
370 // {
371 // dualPtIndexMap.insert(c1I, c1I);
372 // dualPtIndexMap.insert(c2I, c1I);
373 // }
374 // else
375 // {
376 // dualPtIndexMap.insert(c1I, c2I);
377 // dualPtIndexMap.insert(c2I, c2I);
378 // }
379 // }
380  if (c1I < c2I)
381  {
382  dualPtIndexMap.insert(c1I, c1I);
383  dualPtIndexMap.insert(c2I, c1I);
384  }
385  else
386  {
387  dualPtIndexMap.insert(c1I, c2I);
388  dualPtIndexMap.insert(c2I, c2I);
389  }
390 
391  nPtsMerged++;
392  }
393  }
394  }
395 
396  if (debug)
397  {
398  Info<< "mergeIdenticalDualVertices:" << endl
399  << " zero-length edges : "
400  << returnReduce(nPtsMerged, sumOp<label>()) << endl
401  << endl;
402  }
403 
404  return nPtsMerged;
405 }
406 
407 
408 //void Foam::conformalVoronoiMesh::smoothSurface
409 //(
410 // pointField& pts,
411 // const labelList& boundaryPts
412 //)
413 //{
414 // label nCollapsedFaces = 0;
415 //
416 // label iterI = 0;
417 //
418 // do
419 // {
420 // Map<label> dualPtIndexMap;
421 //
422 // nCollapsedFaces = smoothSurfaceDualFaces
423 // (
424 // pts,
425 // boundaryPts,
426 // dualPtIndexMap
427 // );
428 //
429 // reduce(nCollapsedFaces, sumOp<label>());
430 //
431 // reindexDualVertices(dualPtIndexMap);
432 //
433 // mergeIdenticalDualVertices(pts, boundaryPts);
434 //
435 // if (nCollapsedFaces > 0)
436 // {
437 // Info<< " Collapsed " << nCollapsedFaces << " boundary faces"
438 // << endl;
439 // }
440 //
441 // if (++iterI > foamyHexMeshControls().maxCollapseIterations())
442 // {
443 // Info<< " maxCollapseIterations reached, stopping collapse"
444 // << endl;
445 //
446 // break;
447 // }
448 //
449 // } while (nCollapsedFaces > 0);
450 //
451 // // Force all points of boundary faces to be on the surface
502 //}
503 //
504 //
505 //Foam::label Foam::conformalVoronoiMesh::smoothSurfaceDualFaces
506 //(
507 // pointField& pts,
508 // const labelList& boundaryPts,
509 // Map<label>& dualPtIndexMap
510 //) const
511 //{
512 // label nCollapsedFaces = 0;
513 //
514 // const scalar cosPerpendicularToleranceAngle = cos
515 // (
516 // degToRad(foamyHexMeshControls().surfaceStepFaceAngle())
517 // );
518 //
519 // for
520 // (
521 // Delaunay::Finite_edges_iterator eit = finite_edges_begin();
522 // eit != finite_edges_end();
523 // ++eit
524 // )
525 // {
526 // Cell_circulator ccStart = incident_cells(*eit);
527 // Cell_circulator cc = ccStart;
528 //
529 // bool skipFace = false;
530 //
531 // do
532 // {
533 // if (dualPtIndexMap.found(cc->cellIndex()))
534 // {
535 // // One of the points of this face has already been
536 // // collapsed this sweep, leave for next sweep
537 //
538 // skipFace = true;
539 //
540 // break;
541 // }
542 //
543 // } while (++cc != ccStart);
544 //
545 // if (skipFace)
546 // {
547 // continue;
548 // }
549 //
550 // if (isBoundaryDualFace(eit))
551 // {
552 // face dualFace = buildDualFace(eit);
553 //
554 // if (dualFace.size() < 3)
555 // {
556 // // This face has been collapsed already
557 // continue;
558 // }
559 //
560 // label maxFC = maxFilterCount(eit);
561 //
562 // if (maxFC > foamyHexMeshControls().filterCountSkipThreshold())
563 // {
564 // // A vertex on this face has been limited too many
565 // // times, skip
566 // continue;
567 // }
568 //
569 // Cell_handle c = eit->first;
570 // Vertex_handle vA = c->vertex(eit->second);
571 // Vertex_handle vB = c->vertex(eit->third);
572 //
573 // if
574 // (
575 // vA->internalBoundaryPoint() && vA->surfacePoint()
576 // && vB->externalBoundaryPoint() && vB->surfacePoint()
577 // )
578 // {
579 // if (vA->index() == vB->index() - 1)
580 // {
581 // continue;
582 // }
583 // }
584 // else if
585 // (
586 // vA->externalBoundaryPoint() && vA->surfacePoint()
587 // && vB->internalBoundaryPoint() && vB->surfacePoint()
588 // )
589 // {
590 // if (vA->index() == vB->index() + 1)
591 // {
592 // continue;
593 // }
594 // }
639 //
640 //
641 // if ((faceNormal & surfaceNormal) < cosPerpendicularToleranceAngle)
642 // {
643 // scalar targetFaceSize = averageAnyCellSize(vA, vB);
644 //
645 // // Selecting faces to collapse based on angle to
646 // // surface, so set collapseSizeLimitCoeff to GREAT to
647 // // allow collapse of all faces
648 //
649 // faceCollapseMode mode = collapseFace
650 // (
651 // dualFace,
652 // pts,
653 // boundaryPts,
654 // dualPtIndexMap,
655 // targetFaceSize,
656 // GREAT,
657 // maxFC
658 // );
659 //
660 // if (mode == fcmPoint || mode == fcmEdge)
661 // {
662 // nCollapsedFaces++;
663 // }
664 // }
665 // }
666 // }
667 //
668 // return nCollapsedFaces;
669 //}
670 
671 
673 (
674  labelList& owner,
675  labelList& neighbour,
676  const HashSet<labelPair, labelPair::Hash<> >& deferredCollapseFaces
677 ) const
678 {
679  DynamicList<label> faceLabels;
680 
681  forAll(neighbour, nI)
682  {
683  if (deferredCollapseFaces.found(Pair<label>(owner[nI], neighbour[nI])))
684  {
685  faceLabels.append(nI);
686  }
687  }
688 
689  Pout<< "facesToCollapse" << nl << faceLabels << endl;
690 }
691 
692 
695 (
696  const pointField& pts
697 ) const
698 {
699  faceList faces;
700  labelList owner;
701  labelList neighbour;
703  PtrList<dictionary> patchDicts;
704  pointField cellCentres;
705  labelListList patchToDelaunayVertex;
706  PackedBoolList boundaryFacesToRemove;
707 
708  timeCheck("Start of checkPolyMeshQuality");
709 
710  Info<< nl << "Creating polyMesh to assess quality" << endl;
711 
712  createFacesOwnerNeighbourAndPatches
713  (
714  pts,
715  faces,
716  owner,
717  neighbour,
718  patchNames,
719  patchDicts,
720  patchToDelaunayVertex,
721  boundaryFacesToRemove,
722  false
723  );
724 
725  cellCentres = DelaunayMeshTools::allPoints(*this);
726 
727  labelList cellToDelaunayVertex(removeUnusedCells(owner, neighbour));
728  cellCentres = pointField(cellCentres, cellToDelaunayVertex);
729 
730  autoPtr<polyMesh> meshPtr
731  (
732  new polyMesh
733  (
734  IOobject
735  (
736  "foamyHexMesh_temporary",
737  runTime_.timeName(),
738  runTime_,
741  ),
742  xferCopy(pts),
743  xferMove(faces),
744  xferMove(owner),
745  xferMove(neighbour)
746  )
747  );
748 
749  polyMesh& pMesh = meshPtr();
750 
752 
753  label nValidPatches = 0;
754 
755  forAll(patches, p)
756  {
757  label totalPatchSize = readLabel(patchDicts[p].lookup("nFaces"));
758 
759  if
760  (
761  patchDicts.set(p)
762  && word(patchDicts[p].lookup("type")) == processorPolyPatch::typeName
763  )
764  {
765  // Do not create empty processor patches
766  if (totalPatchSize > 0)
767  {
768  patchDicts[p].set("transform", "coincidentFullMatch");
769 
770  patches[nValidPatches] = new processorPolyPatch
771  (
772  patchNames[p],
773  patchDicts[p],
774  nValidPatches,
775  pMesh.boundaryMesh(),
776  processorPolyPatch::typeName
777  );
778 
779  nValidPatches++;
780  }
781  }
782  else
783  {
784  // Check that the patch is not empty on every processor
785  reduce(totalPatchSize, sumOp<label>());
786 
787  if (totalPatchSize > 0)
788  {
789  patches[nValidPatches] = polyPatch::New
790  (
791  patchNames[p],
792  patchDicts[p],
793  nValidPatches,
794  pMesh.boundaryMesh()
795  ).ptr();
796 
797  nValidPatches++;
798  }
799  }
800  }
801 
802  patches.setSize(nValidPatches);
803 
804  pMesh.addPatches(patches);
805 
806  return meshPtr;
807 }
808 
809 
811 {
812  Info<< "Checking cell sizes..."<< endl;
813 
814  timeCheck("Start of Cell Sizing");
815 
816  labelList boundaryPts(number_of_finite_cells(), internal);
817  pointField ptsField;
818 
819  indexDualVertices(ptsField, boundaryPts);
820 
821  // Merge close dual vertices.
822  mergeIdenticalDualVertices(ptsField, boundaryPts);
823 
824  autoPtr<polyMesh> meshPtr = createPolyMeshFromPoints(ptsField);
825  const polyMesh& pMesh = meshPtr();
826 
827  //pMesh.write();
828 
829  // Find cells with poor quality
830  DynamicList<label> checkFaces(identity(pMesh.nFaces()));
831  labelHashSet wrongFaces(pMesh.nFaces()/100);
832 
833  Info<< "Running checkMesh on mesh with " << pMesh.nCells()
834  << " cells "<< endl;
835 
836  const dictionary& dict
837  = foamyHexMeshControls().foamyHexMeshDict();
838 
839  const dictionary& meshQualityDict
840  = dict.subDict("meshQualityControls");
841 
842  const scalar maxNonOrtho =
843  readScalar(meshQualityDict.lookup("maxNonOrtho", true));
844 
845  label nWrongFaces = 0;
846 
847  if (maxNonOrtho < 180.0 - SMALL)
848  {
850  (
851  false,
852  maxNonOrtho,
853  pMesh,
854  pMesh.cellCentres(),
855  pMesh.faceAreas(),
856  checkFaces,
857  List<labelPair>(),
858  &wrongFaces
859  );
860 
861  label nNonOrthogonal = returnReduce(wrongFaces.size(), sumOp<label>());
862 
863  Info<< " non-orthogonality > " << maxNonOrtho
864  << " degrees : " << nNonOrthogonal << endl;
865 
866  nWrongFaces += nNonOrthogonal;
867  }
868 
869  labelHashSet protrudingCells = findOffsetPatchFaces(pMesh, 0.25);
870 
871  label nProtrudingCells = protrudingCells.size();
872 
873  Info<< " protruding/intruding cells : " << nProtrudingCells << endl;
874 
875  nWrongFaces += nProtrudingCells;
876 
877 // motionSmoother::checkMesh
878 // (
879 // false,
880 // pMesh,
881 // meshQualityDict,
882 // checkFaces,
883 // wrongFaces
884 // );
885 
886  Info<< " Found total of " << nWrongFaces << " bad faces" << endl;
887 
888  {
889  labelHashSet cellsToResizeMap(pMesh.nFaces()/100);
890 
891  // Find cells that are attached to the faces in wrongFaces.
892  forAllConstIter(labelHashSet, wrongFaces, iter)
893  {
894  const label faceOwner = pMesh.faceOwner()[iter.key()];
895  const label faceNeighbour = pMesh.faceNeighbour()[iter.key()];
896 
897  if (!cellsToResizeMap.found(faceOwner))
898  {
899  cellsToResizeMap.insert(faceOwner);
900  }
901 
902  if (!cellsToResizeMap.found(faceNeighbour))
903  {
904  cellsToResizeMap.insert(faceNeighbour);
905  }
906  }
907 
908  cellsToResizeMap += protrudingCells;
909 
910  pointField cellsToResize(cellsToResizeMap.size());
911 
912  label count = 0;
913  for (label cellI = 0; cellI < pMesh.nCells(); ++cellI)
914  {
915  if (cellsToResizeMap.found(cellI))
916  {
917  cellsToResize[count++] = pMesh.cellCentres()[cellI];
918  }
919  }
920 
921  Info<< " DISABLED: Automatically re-sizing " << cellsToResize.size()
922  << " cells that are attached to the bad faces: " << endl;
923 
924  //cellSizeControl_.setCellSizes(cellsToResize);
925  }
926 
927  timeCheck("End of Cell Sizing");
928 
929  Info<< "Finished checking cell sizes"<< endl;
930 }
931 
932 
934 (
935  const polyMesh& mesh,
936  const scalar allowedOffset
937 ) const
938 {
939  timeCheck("Start findRemainingProtrusionSet");
940 
941  const polyBoundaryMesh& patches = mesh.boundaryMesh();
942 
943  cellSet offsetBoundaryCells
944  (
945  mesh,
946  "foamyHexMesh_protrudingCells",
947  mesh.nCells()/1000
948  );
949 
950  forAll(patches, patchI)
951  {
952  const polyPatch& patch = patches[patchI];
953 
954  const faceList& localFaces = patch.localFaces();
955  const pointField& localPoints = patch.localPoints();
956 
957  const labelList& fCell = patch.faceCells();
958 
959  forAll(localFaces, pLFI)
960  {
961  const face& f = localFaces[pLFI];
962 
963  const Foam::point& faceCentre = f.centre(localPoints);
964 
965  const scalar targetSize = targetCellSize(faceCentre);
966 
967  pointIndexHit pHit;
968  label surfHit = -1;
969 
970  geometryToConformTo_.findSurfaceNearest
971  (
972  faceCentre,
973  sqr(targetSize),
974  pHit,
975  surfHit
976  );
977 
978  if
979  (
980  pHit.hit()
981  && (mag(pHit.hitPoint() - faceCentre) > allowedOffset*targetSize)
982  )
983  {
984  offsetBoundaryCells.insert(fCell[pLFI]);
985  }
986  }
987  }
988 
989  if (foamyHexMeshControls().objOutput())
990  {
991  offsetBoundaryCells.write();
992  }
993 
994  return offsetBoundaryCells;
995 }
996 
997 
999 (
1000  const pointField& pts
1001 ) const
1002 {
1003  autoPtr<polyMesh> meshPtr = createPolyMeshFromPoints(pts);
1004  polyMesh& pMesh = meshPtr();
1005 
1006  timeCheck("polyMesh created, checking quality");
1007 
1008  labelHashSet wrongFaces(pMesh.nFaces()/100);
1009 
1010  DynamicList<label> checkFaces(pMesh.nFaces());
1011 
1012  const vectorField& fAreas = pMesh.faceAreas();
1013 
1014  scalar faceAreaLimit = SMALL;
1015 
1016  forAll(fAreas, fI)
1017  {
1018  if (mag(fAreas[fI]) > faceAreaLimit)
1019  {
1020  checkFaces.append(fI);
1021  }
1022  }
1023 
1024  Info<< nl << "Excluding "
1025  << returnReduce(fAreas.size() - checkFaces.size(), sumOp<label>())
1026  << " faces from check, < " << faceAreaLimit << " area" << endl;
1027 
1028  const dictionary& dict
1029  = foamyHexMeshControls().foamyHexMeshDict();
1030 
1031  const dictionary& meshQualityDict
1032  = dict.subDict("meshQualityControls");
1033 
1035  (
1036  false,
1037  pMesh,
1038  meshQualityDict,
1039  checkFaces,
1040  wrongFaces
1041  );
1042 
1043  {
1044  // Check for cells with more than 1 but fewer than 4 faces
1045  label nInvalidPolyhedra = 0;
1046 
1047  const cellList& cells = pMesh.cells();
1048 
1049  forAll(cells, cI)
1050  {
1051  if (cells[cI].size() < 4 && cells[cI].size() > 0)
1052  {
1053  // Pout<< "cell " << cI << " " << cells[cI]
1054  // << " has " << cells[cI].size() << " faces."
1055  // << endl;
1056 
1057  nInvalidPolyhedra++;
1058 
1059  forAll(cells[cI], cFI)
1060  {
1061  wrongFaces.insert(cells[cI][cFI]);
1062  }
1063  }
1064  }
1065 
1066  Info<< " cells with more than 1 but fewer than 4 faces : "
1067  << returnReduce(nInvalidPolyhedra, sumOp<label>())
1068  << endl;
1069 
1070  // Check for cells with one internal face only
1071 
1072  labelList nInternalFaces(pMesh.nCells(), label(0));
1073 
1074  for (label fI = 0; fI < pMesh.nInternalFaces(); fI++)
1075  {
1076  nInternalFaces[pMesh.faceOwner()[fI]]++;
1077  nInternalFaces[pMesh.faceNeighbour()[fI]]++;
1078  }
1079 
1080  const polyBoundaryMesh& patches = pMesh.boundaryMesh();
1081 
1082  forAll(patches, patchI)
1083  {
1084  if (patches[patchI].coupled())
1085  {
1086  const labelUList& owners = patches[patchI].faceCells();
1087 
1088  forAll(owners, i)
1089  {
1090  nInternalFaces[owners[i]]++;
1091  }
1092  }
1093  }
1094 
1095  label oneInternalFaceCells = 0;
1096 
1097  forAll(nInternalFaces, cI)
1098  {
1099  if (nInternalFaces[cI] <= 1)
1100  {
1101  oneInternalFaceCells++;
1102 
1103  forAll(cells[cI], cFI)
1104  {
1105  wrongFaces.insert(cells[cI][cFI]);
1106  }
1107  }
1108  }
1109 
1110  Info<< " cells with with zero or one non-boundary face : "
1111  << returnReduce(oneInternalFaceCells, sumOp<label>())
1112  << endl;
1113  }
1114 
1115 
1116  PackedBoolList ptToBeLimited(pts.size(), false);
1117 
1118  forAllConstIter(labelHashSet, wrongFaces, iter)
1119  {
1120  const face f = pMesh.faces()[iter.key()];
1121 
1122  forAll(f, fPtI)
1123  {
1124  ptToBeLimited[f[fPtI]] = true;
1125  }
1126  }
1127 
1128  // // Limit connected cells
1129 
1130  // labelHashSet limitCells(pMesh.nCells()/100);
1131 
1132  // const labelListList& ptCells = pMesh.pointCells();
1133 
1134  // forAllConstIter(labelHashSet, wrongFaces, iter)
1135  // {
1136  // const face f = pMesh.faces()[iter.key()];
1137 
1138  // forAll(f, fPtI)
1139  // {
1140  // label ptI = f[fPtI];
1141 
1142  // const labelList& pC = ptCells[ptI];
1143 
1144  // forAll(pC, pCI)
1145  // {
1146  // limitCells.insert(pC[pCI]);
1147  // }
1148  // }
1149  // }
1150 
1151  // const labelListList& cellPts = pMesh.cellPoints();
1152 
1153  // forAllConstIter(labelHashSet, limitCells, iter)
1154  // {
1155  // label cellI = iter.key();
1156 
1157  // const labelList& cP = cellPts[cellI];
1158 
1159  // forAll(cP, cPI)
1160  // {
1161  // ptToBeLimited[cP[cPI]] = true;
1162  // }
1163  // }
1164 
1165 
1166  // Apply Delaunay cell filterCounts and determine the maximum
1167  // overall filterCount
1168 
1169  label maxFilterCount = 0;
1170 
1171  for
1172  (
1173  Delaunay::Finite_cells_iterator cit = finite_cells_begin();
1174  cit != finite_cells_end();
1175  ++cit
1176  )
1177  {
1178  label cI = cit->cellIndex();
1179 
1180  if (cI >= 0)
1181  {
1182  if (ptToBeLimited[cI] == true)
1183  {
1184  cit->filterCount()++;
1185  }
1186 
1187  if (cit->filterCount() > maxFilterCount)
1188  {
1189  maxFilterCount = cit->filterCount();
1190  }
1191  }
1192  }
1193 
1194  Info<< nl << "Maximum number of filter limits applied: "
1195  << returnReduce(maxFilterCount, maxOp<label>()) << endl;
1196 
1197  return wrongFaces;
1198 }
1199 
1200 
1202 (
1203  Cell_handle cit
1204 ) const
1205 {
1206  if (cit->boundaryDualVertex())
1207  {
1208  if (cit->featurePointDualVertex())
1209  {
1210  return featurePoint;
1211  }
1212  else if (cit->featureEdgeDualVertex())
1213  {
1214  return featureEdge;
1215  }
1216  else
1217  {
1218  return surface;
1219  }
1220  }
1221  else if (cit->baffleSurfaceDualVertex())
1222  {
1223  return surface;
1224  }
1225  else if (cit->baffleEdgeDualVertex())
1226  {
1227  return featureEdge;
1228  }
1229  else
1230  {
1231  return internal;
1232  }
1233 }
1234 
1235 
1237 (
1238  pointField& pts,
1239  labelList& boundaryPts
1240 )
1241 {
1242  // Indexing Delaunay cells, which are the dual vertices
1243 
1244  this->resetCellCount();
1245 
1246  label nConstrainedVertices = 0;
1247  if (foamyHexMeshControls().guardFeaturePoints())
1248  {
1249  for
1250  (
1251  Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
1252  vit != finite_vertices_end();
1253  ++vit
1254  )
1255  {
1256  if (vit->constrained())
1257  {
1258  vit->index() = number_of_finite_cells() + nConstrainedVertices;
1259  nConstrainedVertices++;
1260  }
1261  }
1262  }
1263 
1264  pts.setSize(number_of_finite_cells() + nConstrainedVertices);
1265  boundaryPts.setSize
1266  (
1267  number_of_finite_cells() + nConstrainedVertices,
1268  internal
1269  );
1270 
1271  if (foamyHexMeshControls().guardFeaturePoints())
1272  {
1273  nConstrainedVertices = 0;
1274  for
1275  (
1276  Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
1277  vit != finite_vertices_end();
1278  ++vit
1279  )
1280  {
1281  if (vit->constrained())
1282  {
1283  pts[number_of_finite_cells() + nConstrainedVertices] =
1284  topoint(vit->point());
1285 
1286  boundaryPts[number_of_finite_cells() + nConstrainedVertices] =
1287  constrained;
1288 
1289  nConstrainedVertices++;
1290  }
1291  }
1292  }
1293 
1294  //OBJstream snapping1("snapToSurface1.obj");
1295  //OBJstream snapping2("snapToSurface2.obj");
1296  //OFstream tetToSnapTo("tetsToSnapTo.obj");
1297 
1298  for
1299  (
1300  Delaunay::Finite_cells_iterator cit = finite_cells_begin();
1301  cit != finite_cells_end();
1302  ++cit
1303  )
1304  {
1305 // if (tetrahedron(cit).volume() == 0)
1306 // {
1307 // Pout<< "ZERO VOLUME TET" << endl;
1308 // Pout<< cit->info();
1309 // Pout<< "Dual = " << cit->dual();
1310 // }
1311 
1312  if (!cit->hasFarPoint())
1313  {
1314  cit->cellIndex() = getNewCellIndex();
1315 
1316  // For nearly coplanar Delaunay cells that are present on different
1317  // processors the result of the circumcentre calculation depends on
1318  // the ordering of the vertices, so synchronise it across processors
1319 
1320  if (Pstream::parRun() && cit->parallelDualVertex())
1321  {
1322  typedef CGAL::Exact_predicates_exact_constructions_kernel Exact;
1323  typedef CGAL::Point_3<Exact> ExactPoint;
1324 
1325  List<labelPair> cellVerticesPair(4);
1326  List<ExactPoint> cellVertices(4);
1327 
1328  for (label vI = 0; vI < 4; ++vI)
1329  {
1330  cellVerticesPair[vI] = labelPair
1331  (
1332  cit->vertex(vI)->procIndex(),
1333  cit->vertex(vI)->index()
1334  );
1335 
1336  cellVertices[vI] = ExactPoint
1337  (
1338  cit->vertex(vI)->point().x(),
1339  cit->vertex(vI)->point().y(),
1340  cit->vertex(vI)->point().z()
1341  );
1342  }
1343 
1344  // Sort the vertices so that they will be in the same order on
1345  // each processor
1346  labelList oldToNew;
1347  sortedOrder(cellVerticesPair, oldToNew);
1348  oldToNew = invert(oldToNew.size(), oldToNew);
1349  inplaceReorder(oldToNew, cellVertices);
1350 
1351  ExactPoint synchronisedDual = CGAL::circumcenter
1352  (
1353  cellVertices[0],
1354  cellVertices[1],
1355  cellVertices[2],
1356  cellVertices[3]
1357  );
1358 
1359  pts[cit->cellIndex()] = Foam::point
1360  (
1361  CGAL::to_double(synchronisedDual.x()),
1362  CGAL::to_double(synchronisedDual.y()),
1363  CGAL::to_double(synchronisedDual.z())
1364  );
1365  }
1366  else
1367  {
1368  pts[cit->cellIndex()] = cit->dual();
1369  }
1370 
1371  // Feature point snapping
1372  if (foamyHexMeshControls().snapFeaturePoints())
1373  {
1374  if (cit->featurePointDualVertex())
1375  {
1376  pointFromPoint dual = cit->dual();
1377 
1378  pointIndexHit fpHit;
1379  label featureHit;
1380 
1381  // Find nearest feature point and compare
1382  geometryToConformTo_.findFeaturePointNearest
1383  (
1384  dual,
1385  sqr(targetCellSize(dual)),
1386  fpHit,
1387  featureHit
1388  );
1389 
1390  if (fpHit.hit())
1391  {
1392  if (debug)
1393  {
1394  Info<< "Dual = " << dual << nl
1395  << " Nearest = " << fpHit.hitPoint() << endl;
1396  }
1397 
1398  pts[cit->cellIndex()] = fpHit.hitPoint();
1399  }
1400  }
1401  }
1402 
1403 // {
1404 // // Snapping points far outside
1405 // if (cit->boundaryDualVertex() && !cit->parallelDualVertex())
1406 // {
1407 // pointFromPoint dual = cit->dual();
1408 //
1409 // pointIndexHit hitInfo;
1410 // label surfHit;
1411 //
1412 // // Find nearest surface point
1413 // geometryToConformTo_.findSurfaceNearest
1414 // (
1415 // dual,
1416 // sqr(targetCellSize(dual)),
1417 // hitInfo,
1418 // surfHit
1419 // );
1420 //
1421 // if (!hitInfo.hit())
1422 // {
1423 // // Project dual to nearest point on tet
1424 //
1425 // tetPointRef tet
1426 // (
1427 // topoint(cit->vertex(0)->point()),
1428 // topoint(cit->vertex(1)->point()),
1429 // topoint(cit->vertex(2)->point()),
1430 // topoint(cit->vertex(3)->point())
1431 // );
1432 //
1433 // pointFromPoint nearestPointOnTet =
1434 // tet.nearestPoint(dual).rawPoint();
1435 //
1436 // // Get nearest point on surface from tet.
1437 // geometryToConformTo_.findSurfaceNearest
1438 // (
1439 // nearestPointOnTet,
1440 // sqr(targetCellSize(nearestPointOnTet)),
1441 // hitInfo,
1442 // surfHit
1443 // );
1444 //
1445 // vector snapDir = nearestPointOnTet - dual;
1446 // snapDir /= mag(snapDir) + SMALL;
1447 //
1448 // drawDelaunayCell(tetToSnapTo, cit, offset);
1449 // offset += 1;
1450 //
1451 // vectorField norm(1);
1452 // allGeometry_[surfHit].getNormal
1453 // (
1454 // List<pointIndexHit>(1, hitInfo),
1455 // norm
1456 // );
1457 // norm[0] /= mag(norm[0]) + SMALL;
1458 //
1459 // if
1460 // (
1461 // hitInfo.hit()
1462 // && (mag(snapDir & norm[0]) > 0.5)
1463 // )
1464 // {
1465 // snapping1.write
1466 // (
1467 // linePointRef(dual, nearestPointOnTet)
1468 // );
1469 //
1470 // snapping2.write
1471 // (
1472 // linePointRef
1473 // (
1474 // nearestPointOnTet,
1475 // hitInfo.hitPoint()
1476 // )
1477 // );
1478 //
1479 // pts[cit->cellIndex()] = hitInfo.hitPoint();
1480 // }
1481 // }
1482 // }
1483 // }
1484 
1485  boundaryPts[cit->cellIndex()] = classifyBoundaryPoint(cit);
1486  }
1487  else
1488  {
1489  cit->cellIndex() = Cb::ctFar;
1490  }
1491  }
1492 
1493  //pts.setSize(this->cellCount());
1494 
1495  //boundaryPts.setSize(this->cellCount());
1496 }
1497 
1498 
1500 (
1501  const Map<label>& dualPtIndexMap,
1502  labelList& boundaryPts
1503 )
1504 {
1505  for
1506  (
1507  Delaunay::Finite_cells_iterator cit = finite_cells_begin();
1508  cit != finite_cells_end();
1509  ++cit
1510  )
1511  {
1512  if (dualPtIndexMap.found(cit->cellIndex()))
1513  {
1514  cit->cellIndex() = dualPtIndexMap[cit->cellIndex()];
1515  boundaryPts[cit->cellIndex()] =
1516  max
1517  (
1518  boundaryPts[cit->cellIndex()],
1519  boundaryPts[dualPtIndexMap[cit->cellIndex()]]
1520  );
1521  }
1522  }
1523 }
1524 
1525 
1527 (
1529  PtrList<dictionary>& patchDicts
1530 ) const
1531 {
1532  patchNames = geometryToConformTo_.patchNames();
1533 
1534  patchDicts.setSize(patchNames.size() + 1);
1535 
1536  const PtrList<dictionary>& patchInfo = geometryToConformTo_.patchInfo();
1537 
1538  forAll(patchNames, patchI)
1539  {
1540  if (patchInfo.set(patchI))
1541  {
1542  patchDicts.set(patchI, new dictionary(patchInfo[patchI]));
1543  }
1544  else
1545  {
1546  patchDicts.set(patchI, new dictionary());
1547  patchDicts[patchI].set
1548  (
1549  "type",
1550  wallPolyPatch::typeName
1551  );
1552  }
1553  }
1554 
1556  label defaultPatchIndex = patchNames.size() - 1;
1557  patchNames[defaultPatchIndex] = "foamyHexMesh_defaultPatch";
1558  patchDicts.set(defaultPatchIndex, new dictionary());
1559  patchDicts[defaultPatchIndex].set
1560  (
1561  "type",
1562  wallPolyPatch::typeName
1563  );
1564 
1565  label nProcPatches = 0;
1566 
1567  if (Pstream::parRun())
1568  {
1569  List<boolList> procUsedList
1570  (
1571  Pstream::nProcs(),
1572  boolList(Pstream::nProcs(), false)
1573  );
1574 
1575  boolList& procUsed = procUsedList[Pstream::myProcNo()];
1576 
1577  // Determine which processor patches are required
1578  for
1579  (
1580  Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
1581  vit != finite_vertices_end();
1582  vit++
1583  )
1584  {
1585  // This test is not sufficient if one of the processors does
1586  // not receive a referred vertex from another processor, but does
1587  // send one to the other processor.
1588  if (vit->referred())
1589  {
1590  procUsed[vit->procIndex()] = true;
1591  }
1592  }
1593 
1594  // Because the previous test was insufficient, combine the lists.
1595  Pstream::gatherList(procUsedList);
1596  Pstream::scatterList(procUsedList);
1597 
1598  forAll(procUsedList, procI)
1599  {
1600  if (procI != Pstream::myProcNo())
1601  {
1602  if (procUsedList[procI][Pstream::myProcNo()])
1603  {
1604  procUsed[procI] = true;
1605  }
1606  }
1607  }
1608 
1609  forAll(procUsed, pUI)
1610  {
1611  if (procUsed[pUI])
1612  {
1613  nProcPatches++;
1614  }
1615  }
1616 
1617  label nNonProcPatches = patchNames.size();
1618  label nTotalPatches = nNonProcPatches + nProcPatches;
1619 
1620  patchNames.setSize(nTotalPatches);
1621  patchDicts.setSize(nTotalPatches);
1622  for (label pI = nNonProcPatches; pI < nTotalPatches; ++pI)
1623  {
1624  patchDicts.set(pI, new dictionary());
1625  }
1626 
1627  label procAddI = 0;
1628 
1629  forAll(procUsed, pUI)
1630  {
1631  if (procUsed[pUI])
1632  {
1633  patchNames[nNonProcPatches + procAddI] =
1634  "procBoundary"
1635  + name(Pstream::myProcNo())
1636  + "to"
1637  + name(pUI);
1638 
1639  patchDicts[nNonProcPatches + procAddI].set
1640  (
1641  "type",
1642  processorPolyPatch::typeName
1643  );
1644 
1645  patchDicts[nNonProcPatches + procAddI].set
1646  (
1647  "myProcNo",
1649  );
1650 
1651  patchDicts[nNonProcPatches + procAddI].set("neighbProcNo", pUI);
1652 
1653  procAddI++;
1654  }
1655  }
1656  }
1657 
1658  return defaultPatchIndex;
1659 }
1660 
1661 
1663 (
1664  Cell_handle c1,
1665  Cell_handle c2
1666 ) const
1667 {
1668  List<Foam::point> patchEdge(2, point::max);
1669 
1670  // Get shared Facet
1671  for (label cI = 0; cI < 4; ++cI)
1672  {
1673  if (c1->neighbor(cI) != c2 && !c1->vertex(cI)->constrained())
1674  {
1675  if (c1->vertex(cI)->internalBoundaryPoint())
1676  {
1677  patchEdge[0] = topoint(c1->vertex(cI)->point());
1678  }
1679  else
1680  {
1681  patchEdge[1] = topoint(c1->vertex(cI)->point());
1682  }
1683  }
1684  }
1685 
1686  Info<< " " << patchEdge << endl;
1687 
1688  return vector(patchEdge[1] - patchEdge[0]);
1689 }
1690 
1691 
1693 (
1694  Cell_handle c1,
1695  Cell_handle c2
1696 ) const
1697 {
1698  label nInternal = 0;
1699  label nExternal = 0;
1700 
1701  for (label cI = 0; cI < 4; ++cI)
1702  {
1703  if (c1->neighbor(cI) != c2 && !c1->vertex(cI)->constrained())
1704  {
1705  if (c1->vertex(cI)->internalBoundaryPoint())
1706  {
1707  nInternal++;
1708  }
1709  else if (c1->vertex(cI)->externalBoundaryPoint())
1710  {
1711  nExternal++;
1712  }
1713  }
1714  }
1715 
1716  Info<< "in = " << nInternal << " out = " << nExternal << endl;
1717 
1718  return (nInternal == 1 && nExternal == 1);
1719 }
1720 
1721 
1723 (
1724  const pointField& pts,
1725  faceList& faces,
1726  labelList& owner,
1727  labelList& neighbour,
1729  PtrList<dictionary>& patchDicts,
1730  labelListList& patchPointPairSlaves,
1731  PackedBoolList& boundaryFacesToRemove,
1732  bool includeEmptyPatches
1733 ) const
1734 {
1735  const label defaultPatchIndex = createPatchInfo(patchNames, patchDicts);
1736 
1737  const label nPatches = patchNames.size();
1738 
1740  forAll(procNeighbours, patchI)
1741  {
1742  if (patchDicts[patchI].found("neighbProcNo"))
1743  {
1744  procNeighbours[patchI] =
1745  (
1746  patchDicts[patchI].found("neighbProcNo")
1747  ? readLabel(patchDicts[patchI].lookup("neighbProcNo"))
1748  : -1
1749  );
1750  }
1751  }
1752 
1753  List<DynamicList<face> > patchFaces(nPatches, DynamicList<face>(0));
1754  List<DynamicList<label> > patchOwners(nPatches, DynamicList<label>(0));
1755  // Per patch face the index of the slave node of the point pair
1756  List<DynamicList<label> > patchPPSlaves(nPatches, DynamicList<label>(0));
1757 
1758  List<DynamicList<bool> > indirectPatchFace(nPatches, DynamicList<bool>(0));
1759 
1760 
1761  faces.setSize(number_of_finite_edges());
1762  owner.setSize(number_of_finite_edges());
1763  neighbour.setSize(number_of_finite_edges());
1764  boundaryFacesToRemove.setSize(number_of_finite_edges(), false);
1765 
1766  labelPairPairDynListList procPatchSortingIndex(nPatches);
1767 
1768  label dualFaceI = 0;
1769 
1770  if (foamyHexMeshControls().guardFeaturePoints())
1771  {
1772  OBJstream startCellStr("startingCell.obj");
1773  OBJstream featurePointFacesStr("ftPtFaces.obj");
1774  OBJstream featurePointDualsStr("ftPtDuals.obj");
1775  OFstream cellStr("vertexCells.obj");
1776 
1777  label vcount = 1;
1778 
1779  for
1780  (
1781  Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
1782  vit != finite_vertices_end();
1783  ++vit
1784  )
1785  {
1786  if (vit->constrained())
1787  {
1788  // Find a starting cell
1789  std::list<Cell_handle> vertexCells;
1790  finite_incident_cells(vit, std::back_inserter(vertexCells));
1791 
1792  Cell_handle startCell;
1793 
1794  for
1795  (
1796  std::list<Cell_handle>::iterator vcit = vertexCells.begin();
1797  vcit != vertexCells.end();
1798  ++vcit
1799  )
1800  {
1801  if ((*vcit)->featurePointExternalCell())
1802  {
1803  startCell = *vcit;
1804  }
1805 
1806  if ((*vcit)->real())
1807  {
1808  featurePointDualsStr.write
1809  (
1810  linePointRef(topoint(vit->point()), (*vcit)->dual())
1811  );
1812  }
1813  }
1814 
1815  // Error if startCell is null
1816  if (startCell == NULL)
1817  {
1818  Pout<< "Start cell is null!" << endl;
1819  }
1820 
1821  // Need to pick a direction to walk in
1822  Cell_handle vc1 = startCell;
1823  Cell_handle vc2;
1824 
1825  Info<< "c1 index = " << vc1->cellIndex() << " "
1826  << vc1->dual() << endl;
1827 
1828  for (label cI = 0; cI < 4; ++cI)
1829  {
1830  Info<< "c1 = " << cI << " "
1831  << vc1->neighbor(cI)->cellIndex() << " v = "
1832  << vc1->neighbor(cI)->dual() << endl;
1833 
1834  Info<< vc1->vertex(cI)->info();
1835  }
1836 
1837  Cell_handle nextCell;
1838 
1839  for (label cI = 0; cI < 4; ++cI)
1840  {
1841  if (vc1->vertex(cI)->externalBoundaryPoint())
1842  {
1843  vc2 = vc1->neighbor(cI);
1844 
1845  Info<< " c2 is neighbor "
1846  << vc2->cellIndex()
1847  << " of c1" << endl;
1848 
1849  for (label cI = 0; cI < 4; ++cI)
1850  {
1851  Info<< " c2 = " << cI << " "
1852  << vc2->neighbor(cI)->cellIndex() << " v = "
1853  << vc2->vertex(cI)->index() << endl;
1854  }
1855 
1856  face f(3);
1857  f[0] = vit->index();
1858  f[1] = vc1->cellIndex();
1859  f[2] = vc2->cellIndex();
1860 
1861  Info<< "f " << f << endl;
1862  forAll(f, pI)
1863  {
1864  Info<< " " << pts[f[pI]] << endl;
1865  }
1866 
1867  vector correctNormal = calcSharedPatchNormal(vc1, vc2);
1868  correctNormal /= mag(correctNormal);
1869 
1870  Info<< " cN " << correctNormal << endl;
1871 
1872  vector fN = f.normal(pts);
1873 
1874  if (mag(fN) < SMALL)
1875  {
1876  nextCell = vc2;
1877  continue;
1878  }
1879 
1880  fN /= mag(fN);
1881  Info<< " fN " << fN << endl;
1882 
1883  if ((fN & correctNormal) > 0)
1884  {
1885  nextCell = vc2;
1886  break;
1887  }
1888  }
1889  }
1890 
1891  vc2 = nextCell;
1892 
1893  label own = vit->index();
1894  face f(3);
1895  f[0] = own;
1896 
1897  Info<< "Start walk from " << vc1->cellIndex()
1898  << " to " << vc2->cellIndex() << endl;
1899 
1900  // Walk while not at start cell
1901 
1902  label iter = 0;
1903  do
1904  {
1905  Info<< " Walk from " << vc1->cellIndex()
1906  << " " << vc1->dual()
1907  << " to " << vc2->cellIndex()
1908  << " " << vc2->dual()
1909  << endl;
1910 
1911  startCellStr.write(linePointRef(vc1->dual(), vc2->dual()));
1912 
1913  // Get patch by getting face between cells and the two
1914  // points on the face that are not the feature vertex
1915  label patchIndex =
1916  geometryToConformTo_.findPatch
1917  (
1918  topoint(vit->point())
1919  );
1920 
1921  f[1] = vc1->cellIndex();
1922  f[2] = vc2->cellIndex();
1923 
1924  patchFaces[patchIndex].append(f);
1925  patchOwners[patchIndex].append(own);
1926  patchPPSlaves[patchIndex].append(own);
1927 
1928  // Find next cell
1929  Cell_handle nextCell;
1930 
1931  Info<< " c1 vertices " << vc2->dual() << endl;
1932  for (label cI = 0; cI < 4; ++cI)
1933  {
1934  Info<< " " << vc2->vertex(cI)->info();
1935  }
1936  Info<< " c1 neighbour vertices " << endl;
1937  for (label cI = 0; cI < 4; ++cI)
1938  {
1939  if
1940  (
1941  !vc2->vertex(cI)->constrained()
1942  && vc2->neighbor(cI) != vc1
1943  && !is_infinite(vc2->neighbor(cI))
1944  &&
1945  (
1946  vc2->neighbor(cI)->featurePointExternalCell()
1947  || vc2->neighbor(cI)->featurePointInternalCell()
1948  )
1949  && vc2->neighbor(cI)->hasConstrainedPoint()
1950  )
1951  {
1953  (
1954  cellStr,
1955  vc2->neighbor(cI),
1956  vcount++
1957  );
1958 
1959  Info<< " neighbour " << cI << " "
1960  << vc2->neighbor(cI)->dual() << endl;
1961  for (label I = 0; I < 4; ++I)
1962  {
1963  Info<< " "
1964  << vc2->neighbor(cI)->vertex(I)->info();
1965  }
1966  }
1967  }
1968 
1969  for (label cI = 0; cI < 4; ++cI)
1970  {
1971  if
1972  (
1973  !vc2->vertex(cI)->constrained()
1974  && vc2->neighbor(cI) != vc1
1975  && !is_infinite(vc2->neighbor(cI))
1976  &&
1977  (
1978  vc2->neighbor(cI)->featurePointExternalCell()
1979  || vc2->neighbor(cI)->featurePointInternalCell()
1980  )
1981  && vc2->neighbor(cI)->hasConstrainedPoint()
1982  )
1983  {
1984  // check if shared edge is internal/internal
1985  if (boundaryDualFace(vc2, vc2->neighbor(cI)))
1986  {
1987  nextCell = vc2->neighbor(cI);
1988  break;
1989  }
1990  }
1991  }
1992 
1993  vc1 = vc2;
1994  vc2 = nextCell;
1995 
1996  iter++;
1997  } while (vc1 != startCell && iter < 100);
1998  }
1999  }
2000  }
2001 
2002  for
2003  (
2004  Delaunay::Finite_edges_iterator eit = finite_edges_begin();
2005  eit != finite_edges_end();
2006  ++eit
2007  )
2008  {
2009  Cell_handle c = eit->first;
2010  Vertex_handle vA = c->vertex(eit->second);
2011  Vertex_handle vB = c->vertex(eit->third);
2012 
2013  if (vA->constrained() && vB->constrained())
2014  {
2015  continue;
2016  }
2017 
2018  if
2019  (
2020  (vA->constrained() && vB->internalOrBoundaryPoint())
2021  || (vB->constrained() && vA->internalOrBoundaryPoint())
2022  )
2023  {
2024  face newDualFace = buildDualFace(eit);
2025 
2026  label own = -1;
2027  label nei = -1;
2028 
2029  if (ownerAndNeighbour(vA, vB, own, nei))
2030  {
2031  reverse(newDualFace);
2032  }
2033 
2034  // internal face
2035  faces[dualFaceI] = newDualFace;
2036  owner[dualFaceI] = own;
2037  neighbour[dualFaceI] = nei;
2038 
2039  dualFaceI++;
2040  }
2041  else if
2042  (
2043  (vA->internalOrBoundaryPoint() && !vA->referred())
2044  || (vB->internalOrBoundaryPoint() && !vB->referred())
2045  )
2046  {
2047  if
2048  (
2049  (vA->internalPoint() && vB->externalBoundaryPoint())
2050  || (vB->internalPoint() && vA->externalBoundaryPoint())
2051  )
2052  {
2053  Cell_circulator ccStart = incident_cells(*eit);
2054  Cell_circulator cc1 = ccStart;
2055  Cell_circulator cc2 = cc1;
2056 
2057  cc2++;
2058 
2059  bool skipEdge = false;
2060 
2061  do
2062  {
2063  if
2064  (
2065  cc1->hasFarPoint() || cc2->hasFarPoint()
2066  || is_infinite(cc1) || is_infinite(cc2)
2067  )
2068  {
2069  Pout<< "Ignoring edge between internal and external: "
2070  << vA->info()
2071  << vB->info();
2072 
2073  skipEdge = true;
2074  break;
2075  }
2076 
2077  cc1++;
2078  cc2++;
2079 
2080  } while (cc1 != ccStart);
2081 
2082 
2083  // Do not create faces if the internal point is outside!
2084  // This occurs because the internal point is not determined to
2085  // be outside in the inside/outside test. This is most likely
2086  // due to the triangle.nearestPointClassify test not returning
2087  // edge/point as the nearest type.
2088 
2089  if (skipEdge)
2090  {
2091  continue;
2092  }
2093  }
2094 
2095  face newDualFace = buildDualFace(eit);
2096 
2097  if (newDualFace.size() >= 3)
2098  {
2099  label own = -1;
2100  label nei = -1;
2101 
2102  if (ownerAndNeighbour(vA, vB, own, nei))
2103  {
2104  reverse(newDualFace);
2105  }
2106 
2107  label patchIndex = -1;
2108 
2109  pointFromPoint ptA = topoint(vA->point());
2110  pointFromPoint ptB = topoint(vB->point());
2111 
2112  if (nei == -1)
2113  {
2114  // boundary face
2115 
2116  if (isProcBoundaryEdge(eit))
2117  {
2118  // One (and only one) of the points is an internal
2119  // point from another processor
2120 
2121  label procIndex = max(vA->procIndex(), vB->procIndex());
2122 
2123  patchIndex = max
2124  (
2125  findIndex(procNeighbours, vA->procIndex()),
2126  findIndex(procNeighbours, vB->procIndex())
2127  );
2128 
2129  // The lower processor index is the owner of the
2130  // two for the purpose of sorting the patch faces.
2131 
2132  if (Pstream::myProcNo() < procIndex)
2133  {
2134  // Use this processor's vertex index as the master
2135  // for sorting
2136 
2137  DynamicList<Pair<labelPair> >& sortingIndex =
2138  procPatchSortingIndex[patchIndex];
2139 
2140  if (vB->internalOrBoundaryPoint() && vB->referred())
2141  {
2142  sortingIndex.append
2143  (
2144  Pair<labelPair>
2145  (
2146  labelPair(vA->index(), vA->procIndex()),
2147  labelPair(vB->index(), vB->procIndex())
2148  )
2149  );
2150  }
2151  else
2152  {
2153  sortingIndex.append
2154  (
2155  Pair<labelPair>
2156  (
2157  labelPair(vB->index(), vB->procIndex()),
2158  labelPair(vA->index(), vA->procIndex())
2159  )
2160  );
2161  }
2162  }
2163  else
2164  {
2165  // Use the other processor's vertex index as the
2166  // master for sorting
2167 
2168  DynamicList<Pair<labelPair> >& sortingIndex =
2169  procPatchSortingIndex[patchIndex];
2170 
2171  if (vA->internalOrBoundaryPoint() && vA->referred())
2172  {
2173  sortingIndex.append
2174  (
2175  Pair<labelPair>
2176  (
2177  labelPair(vA->index(), vA->procIndex()),
2178  labelPair(vB->index(), vB->procIndex())
2179  )
2180  );
2181  }
2182  else
2183  {
2184  sortingIndex.append
2185  (
2186  Pair<labelPair>
2187  (
2188  labelPair(vB->index(), vB->procIndex()),
2189  labelPair(vA->index(), vA->procIndex())
2190  )
2191  );
2192  }
2193  }
2194 
2195 // Pout<< ptA << " " << ptB
2196 // << " proc indices "
2197 // << vA->procIndex() << " " << vB->procIndex()
2198 // << " indices " << vA->index()
2199 // << " " << vB->index()
2200 // << " my proc " << Pstream::myProcNo()
2201 // << " addedIndex "
2202 // << procPatchSortingIndex[patchIndex].last()
2203 // << endl;
2204  }
2205  else
2206  {
2207  patchIndex = geometryToConformTo_.findPatch(ptA, ptB);
2208  }
2209 
2210  if (patchIndex == -1)
2211  {
2212  // Did not find a surface patch between
2213  // between Dv pair, finding nearest patch
2214 
2215 // Pout<< "Did not find a surface patch between "
2216 // << "for face, finding nearest patch to"
2217 // << 0.5*(ptA + ptB) << endl;
2218 
2219  patchIndex = geometryToConformTo_.findPatch
2220  (
2221  0.5*(ptA + ptB)
2222  );
2223  }
2224 
2225  patchFaces[patchIndex].append(newDualFace);
2226  patchOwners[patchIndex].append(own);
2227 
2228  // If the two vertices are a pair, then the patch face is
2229  // a desired one.
2230  if
2231  (
2232  vA->boundaryPoint() && vB->boundaryPoint()
2233  && !ptPairs_.isPointPair(vA, vB)
2234  && !ftPtConformer_.featurePointPairs().isPointPair(vA, vB)
2235  )
2236  {
2237  indirectPatchFace[patchIndex].append(true);
2238  }
2239  else
2240  {
2241  indirectPatchFace[patchIndex].append(false);
2242  }
2243 
2244  // Store the non-internal or boundary point
2245  if (vA->internalOrBoundaryPoint())
2246  {
2247  patchPPSlaves[patchIndex].append(vB->index());
2248  }
2249  else
2250  {
2251  patchPPSlaves[patchIndex].append(vA->index());
2252  }
2253  }
2254  else
2255  {
2256 // if
2257 // (
2258 // ptPairs_.isPointPair(vA, vB)
2259 // || ftPtConformer_.featurePointPairs().isPointPair(vA, vB)
2260 // )
2261 // {
2262  patchIndex = geometryToConformTo_.findPatch(ptA, ptB);
2263 // }
2264 
2265  if (patchIndex != -1)
2266  {
2267 // if
2268 // (
2269 // vA->boundaryPoint() && vB->boundaryPoint()
2270 // && !ptPairs_.isPointPair(vA, vB)
2271 // )
2272 // {
2273 // indirectPatchFace[patchIndex].append(true);
2274 // }
2275 // else
2276 // {
2277 // indirectPatchFace[patchIndex].append(false);
2278 // }
2279 // patchFaces[patchIndex].append(newDualFace);
2280 // patchOwners[patchIndex].append(own);
2281 // indirectPatchFace[patchIndex].append(false);
2282 //
2283 // if
2284 // (
2285 // labelPair(vB->index(), vB->procIndex())
2286 // < labelPair(vA->index(), vA->procIndex())
2287 // )
2288 // {
2289 // patchPPSlaves[patchIndex].append(vB->index());
2290 // }
2291 // else
2292 // {
2293 // patchPPSlaves[patchIndex].append(vA->index());
2294 // }
2295  }
2296 // else
2297  {
2298  // internal face
2299  faces[dualFaceI] = newDualFace;
2300  owner[dualFaceI] = own;
2301  neighbour[dualFaceI] = nei;
2302 
2303  dualFaceI++;
2304  }
2305  }
2306  }
2307  }
2308  }
2309 
2310  if (!patchFaces[defaultPatchIndex].empty())
2311  {
2312  Pout<< nl << patchFaces[defaultPatchIndex].size()
2313  << " faces were not able to have their patch determined from "
2314  << "the surface. "
2315  << nl << "Adding to patch " << patchNames[defaultPatchIndex]
2316  << endl;
2317  }
2318 
2319  label nInternalFaces = dualFaceI;
2320 
2321  faces.setSize(nInternalFaces);
2322  owner.setSize(nInternalFaces);
2323  neighbour.setSize(nInternalFaces);
2324 
2325  timeCheck("polyMesh quality checked");
2326 
2327  sortFaces(faces, owner, neighbour);
2328 
2329  sortProcPatches
2330  (
2331  patchFaces,
2332  patchOwners,
2333  patchPPSlaves,
2334  procPatchSortingIndex
2335  );
2336 
2337  timeCheck("faces, owner, neighbour sorted");
2338 
2339  addPatches
2340  (
2341  nInternalFaces,
2342  faces,
2343  owner,
2344  patchDicts,
2345  boundaryFacesToRemove,
2346  patchFaces,
2347  patchOwners,
2348  indirectPatchFace
2349  );
2350 
2351  // Return patchPointPairSlaves.setSize(nPatches);
2352  patchPointPairSlaves.setSize(nPatches);
2353  forAll(patchPPSlaves, patchI)
2354  {
2355  patchPointPairSlaves[patchI].transfer(patchPPSlaves[patchI]);
2356  }
2357 
2358  if (foamyHexMeshControls().objOutput())
2359  {
2360  Info<< "Writing processor interfaces" << endl;
2361 
2362  forAll(patchDicts, nbI)
2363  {
2364  if (patchFaces[nbI].size() > 0)
2365  {
2366  const label neighbour =
2367  (
2368  patchDicts[nbI].found("neighbProcNo")
2369  ? readLabel(patchDicts[nbI].lookup("neighbProcNo"))
2370  : -1
2371  );
2372 
2373  faceList procPatchFaces = patchFaces[nbI];
2374 
2375  // Reverse faces as it makes it easier to analyse the output
2376  // using a diff
2377  if (neighbour < Pstream::myProcNo())
2378  {
2379  forAll(procPatchFaces, fI)
2380  {
2381  procPatchFaces[fI] = procPatchFaces[fI].reverseFace();
2382  }
2383  }
2384 
2385  if (neighbour != -1)
2386  {
2387  word fName =
2388  "processor_"
2389  + name(Pstream::myProcNo())
2390  + "_to_"
2391  + name(neighbour)
2392  + "_interface.obj";
2393 
2395  (
2396  time().path()/fName,
2397  *this,
2398  procPatchFaces
2399  );
2400  }
2401  }
2402  }
2403  }
2404 }
2405 
2406 
2408 (
2409  faceList& faces,
2410  labelList& owner,
2411  labelList& neighbour
2412 ) const
2413 {
2414  // Upper triangular order:
2415  // + owner is sorted in ascending cell order
2416  // + within each block of equal value for owner, neighbour is sorted in
2417  // ascending cell order.
2418  // + faces sorted to correspond
2419  // e.g.
2420  // owner | neighbour
2421  // 0 | 2
2422  // 0 | 23
2423  // 0 | 71
2424  // 1 | 23
2425  // 1 | 24
2426  // 1 | 91
2427 
2428  List<labelPair> ownerNeighbourPair(owner.size());
2429 
2430  forAll(ownerNeighbourPair, oNI)
2431  {
2432  ownerNeighbourPair[oNI] = labelPair(owner[oNI], neighbour[oNI]);
2433  }
2434 
2435  Info<< nl
2436  << "Sorting faces, owner and neighbour into upper triangular order"
2437  << endl;
2438 
2439  labelList oldToNew;
2440 
2441  sortedOrder(ownerNeighbourPair, oldToNew);
2442 
2443  oldToNew = invert(oldToNew.size(), oldToNew);
2444 
2445  inplaceReorder(oldToNew, faces);
2446  inplaceReorder(oldToNew, owner);
2447  inplaceReorder(oldToNew, neighbour);
2448 }
2449 
2450 
2452 (
2453  List<DynamicList<face> >& patchFaces,
2454  List<DynamicList<label> >& patchOwners,
2455  List<DynamicList<label> >& patchPointPairSlaves,
2456  labelPairPairDynListList& patchSortingIndices
2457 ) const
2458 {
2459  if (!Pstream::parRun())
2460  {
2461  return;
2462  }
2463 
2464  forAll(patchSortingIndices, patchI)
2465  {
2466  faceList& faces = patchFaces[patchI];
2467  labelList& owner = patchOwners[patchI];
2468  DynamicList<label>& slaves = patchPointPairSlaves[patchI];
2469  DynamicList<Pair<labelPair> >& sortingIndices
2470  = patchSortingIndices[patchI];
2471 
2472  if (!sortingIndices.empty())
2473  {
2474  if
2475  (
2476  faces.size() != sortingIndices.size()
2477  || owner.size() != sortingIndices.size()
2478  || slaves.size() != sortingIndices.size()
2479  )
2480  {
2482  << "patch size and size of sorting indices is inconsistent "
2483  << " for patch " << patchI << nl
2484  << " faces.size() " << faces.size() << nl
2485  << " owner.size() " << owner.size() << nl
2486  << " slaves.size() " << slaves.size() << nl
2487  << " sortingIndices.size() "
2488  << sortingIndices.size()
2489  << exit(FatalError) << endl;
2490  }
2491 
2492  labelList oldToNew;
2493 
2494  sortedOrder(sortingIndices, oldToNew);
2495 
2496  oldToNew = invert(oldToNew.size(), oldToNew);
2497 
2498  inplaceReorder(oldToNew, sortingIndices);
2499  inplaceReorder(oldToNew, faces);
2500  inplaceReorder(oldToNew, owner);
2501  inplaceReorder(oldToNew, slaves);
2502  }
2503  }
2504 }
2505 
2506 
2508 (
2509  const label nInternalFaces,
2510  faceList& faces,
2511  labelList& owner,
2512  PtrList<dictionary>& patchDicts,
2513  PackedBoolList& boundaryFacesToRemove,
2514  const List<DynamicList<face> >& patchFaces,
2515  const List<DynamicList<label> >& patchOwners,
2516  const List<DynamicList<bool> >& indirectPatchFace
2517 ) const
2518 {
2519  label nBoundaryFaces = 0;
2520 
2521  forAll(patchFaces, p)
2522  {
2523  patchDicts[p].set("nFaces", patchFaces[p].size());
2524  patchDicts[p].set("startFace", nInternalFaces + nBoundaryFaces);
2525 
2526  nBoundaryFaces += patchFaces[p].size();
2527  }
2528 
2529  faces.setSize(nInternalFaces + nBoundaryFaces);
2530  owner.setSize(nInternalFaces + nBoundaryFaces);
2531  boundaryFacesToRemove.setSize(nInternalFaces + nBoundaryFaces);
2532 
2533  label faceI = nInternalFaces;
2534 
2535  forAll(patchFaces, p)
2536  {
2537  forAll(patchFaces[p], f)
2538  {
2539  faces[faceI] = patchFaces[p][f];
2540  owner[faceI] = patchOwners[p][f];
2541  boundaryFacesToRemove[faceI] = indirectPatchFace[p][f];
2542 
2543  faceI++;
2544  }
2545  }
2546 }
2547 
2548 
2550 (
2551  faceList& faces,
2552  pointField& pts,
2553  labelList& boundaryPts
2554 ) const
2555 {
2556  Info<< nl << "Removing unused points" << endl;
2557 
2558  PackedBoolList ptUsed(pts.size(), false);
2559 
2560  // Scan all faces to find all of the points that are used
2561 
2562  forAll(faces, fI)
2563  {
2564  const face& f = faces[fI];
2565 
2566  forAll(f, fPtI)
2567  {
2568  ptUsed[f[fPtI]] = true;
2569  }
2570  }
2571 
2572  label pointI = 0;
2573 
2574  labelList oldToNew(pts.size(), label(-1));
2575 
2576  // Move all of the used points to the start of the pointField and
2577  // truncate it
2578 
2579  forAll(ptUsed, ptUI)
2580  {
2581  if (ptUsed[ptUI] == true)
2582  {
2583  oldToNew[ptUI] = pointI++;
2584  }
2585  }
2586 
2587  inplaceReorder(oldToNew, pts);
2588  inplaceReorder(oldToNew, boundaryPts);
2589 
2590  Info<< " Removing "
2591  << returnReduce(pts.size() - pointI, sumOp<label>())
2592  << " unused points"
2593  << endl;
2594 
2595  pts.setSize(pointI);
2596  boundaryPts.setSize(pointI);
2597 
2598  // Renumber the faces to use the new point numbers
2599 
2600  forAll(faces, fI)
2601  {
2602  inplaceRenumber(oldToNew, faces[fI]);
2603  }
2604 }
2605 
2606 
2608 (
2609  labelList& owner,
2610  labelList& neighbour
2611 ) const
2612 {
2613  Info<< nl << "Removing unused cells" << endl;
2614 
2615  PackedBoolList cellUsed(vertexCount(), false);
2616 
2617  // Scan all faces to find all of the cells that are used
2618 
2619  forAll(owner, oI)
2620  {
2621  cellUsed[owner[oI]] = true;
2622  }
2623 
2624  forAll(neighbour, nI)
2625  {
2626  cellUsed[neighbour[nI]] = true;
2627  }
2628 
2629  label cellI = 0;
2630 
2631  labelList oldToNew(cellUsed.size(), label(-1));
2632 
2633  // Move all of the used cellCentres to the start of the pointField and
2634  // truncate it
2635 
2636  forAll(cellUsed, cellUI)
2637  {
2638  if (cellUsed[cellUI] == true)
2639  {
2640  oldToNew[cellUI] = cellI++;
2641  }
2642  }
2643 
2644  labelList newToOld(invert(cellI, oldToNew));
2645 
2646  // Find all of the unused cells, create a list of them, then
2647  // subtract one from each owner and neighbour entry for each of
2648  // the unused cell indices that it is above.
2649 
2650  DynamicList<label> unusedCells;
2651 
2652  forAll(cellUsed, cUI)
2653  {
2654  if (cellUsed[cUI] == false)
2655  {
2656  unusedCells.append(cUI);
2657  }
2658  }
2659 
2660  if (unusedCells.size() > 0)
2661  {
2662  Info<< " Removing "
2663  << returnReduce(unusedCells.size(), sumOp<label>())
2664  << " unused cell labels" << endl;
2665 
2666  forAll(owner, oI)
2667  {
2668  label& o = owner[oI];
2669 
2670  o -= findLower(unusedCells, o) + 1;
2671  }
2672 
2673  forAll(neighbour, nI)
2674  {
2675  label& n = neighbour[nI];
2676 
2677  n -= findLower(unusedCells, n) + 1;
2678  }
2679  }
2680 
2681  return newToOld;
2682 }
2683 
2684 
2685 // ************************************************************************* //
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
Foam::polyMeshGeometry::checkFaceDotProduct
static bool checkFaceDotProduct(const bool report, const scalar orthWarn, const polyMesh &, const vectorField &cellCentres, const vectorField &faceAreas, const labelList &checkFaces, const List< labelPair > &baffles, labelHashSet *setPtr)
See primitiveMesh.
Definition: polyMeshGeometry.C:371
Foam::conformalVoronoiMesh::findOffsetPatchFaces
labelHashSet findOffsetPatchFaces(const polyMesh &mesh, const scalar allowedOffset) const
Find all cells with a patch face that is not near the surface. The.
p
p
Definition: pEqn.H:62
Foam::labelList
List< label > labelList
A List of labels.
Definition: labelList.H:56
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:86
Foam::conformalVoronoiMesh::checkPolyMeshQuality
labelHashSet checkPolyMeshQuality(const pointField &pts) const
Create a polyMesh and check its quality, reports which.
nPatches
label nPatches
Definition: readKivaGrid.H:402
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::findIndex
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurence of given element and return index,.
Foam::conformalVoronoiMesh::createPolyMeshFromPoints
autoPtr< polyMesh > createPolyMeshFromPoints(const pointField &pts) const
Create a polyMesh from points.
polyMeshGeometry.H
Foam::Pstream::scatterList
static void scatterList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Scatter data. Reverse of gatherList.
Definition: gatherScatterList.C:205
Foam::UPstream::nProcs
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:387
Foam::Vector< scalar >::max
static const Vector max
Definition: Vector.H:82
Foam::conformalVoronoiMesh::timeCheck
static void timeCheck(const Time &runTime, const string &description=string::null, const bool check=true)
Write the elapsedCpuTime and memory usage, with an optional.
motionSmoother.H
Foam::UPstream::parRun
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:377
Foam::conformalVoronoiMesh::removeUnusedPoints
void removeUnusedPoints(faceList &faces, pointField &pts, labelList &boundaryPts) const
Remove points that are no longer used by any faces.
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:421
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Foam::conformalVoronoiMesh::boundaryDualFace
bool boundaryDualFace(Cell_handle c1, Cell_handle c2) const
Foam::conformalVoronoiMesh::classifyBoundaryPoint
label classifyBoundaryPoint(Cell_handle cit) const
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
Foam::conformalVoronoiMesh::removeUnusedCells
labelList removeUnusedCells(labelList &owner, labelList &neighbour) const
Remove dual cells that are not used by any faces. Return compaction.
Foam::conformalVoronoiMesh::calcTetMesh
void calcTetMesh(pointField &points, labelList &pointToDelaunayVertex, faceList &faces, labelList &owner, labelList &neighbour, wordList &patchNames, PtrList< dictionary > &patchDicts)
Tet mesh calculation.
Foam::HashSet< label, Hash< label > >
patchFaces
labelList patchFaces(const polyBoundaryMesh &patches, const wordList &names)
Definition: extrudeMesh.C:148
Foam::conformalVoronoiMesh::addPatches
void addPatches(const label nInternalFaces, faceList &faces, labelList &owner, PtrList< dictionary > &patchDicts, PackedBoolList &boundaryFacesToRemove, const List< DynamicList< face > > &patchFaces, const List< DynamicList< label > > &patchOwners, const List< DynamicList< bool > > &indirectPatchFace) const
Add the faces and owner information for the patches.
Foam::conformalVoronoiMesh::calcDualMesh
void calcDualMesh(pointField &points, labelList &boundaryPts, faceList &faces, labelList &owner, labelList &neighbour, wordList &patchNames, PtrList< dictionary > &patchDicts, pointField &cellCentres, labelList &cellToDelaunayVertex, labelListList &patchToDelaunayVertex, PackedBoolList &boundaryFacesToRemove)
Dual calculation.
Foam::DelaunayMeshTools::drawDelaunayCell
void drawDelaunayCell(Ostream &os, const CellHandle &c, label offset=0)
Draws a tet cell to an output stream. The offset is supplied as the tet.
Foam::conformalVoronoiMesh::deferredCollapseFaceSet
void deferredCollapseFaceSet(labelList &owner, labelList &neighbour, const HashSet< labelPair, labelPair::Hash<> > &deferredCollapseFaces) const
Identify the face labels of the deferred collapse faces.
Foam::topoint
pointFromPoint topoint(const Point &P)
Definition: pointConversion.H:70
Foam::IOobject::NO_WRITE
@ NO_WRITE
Definition: IOobject.H:118
patchDicts
PtrList< dictionary > patchDicts
Definition: readKivaGrid.H:537
forAllConstIter
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:39
Foam::vectorField
Field< vector > vectorField
Specialisation of Field<T> for vector.
Definition: primitiveFieldsFwd.H:49
Foam::wordList
List< word > wordList
A List of words.
Definition: fileName.H:54
Foam::inplaceRenumber
void inplaceRenumber(const labelUList &oldToNew, ListType &)
Inplace renumber the values of a list.
Definition: ListOpsTemplates.C:57
Foam::primitiveMesh::nCells
label nCells() const
Definition: primitiveMeshI.H:64
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::sortedOrder
void sortedOrder(const UList< T > &, labelList &order)
Generate the (stable) sort order for the list.
Definition: ListOpsTemplates.C:179
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:43
backgroundMeshDecomposition.H
Foam::constant::physicoChemical::c1
const dimensionedScalar c1
First radiation constant: default SI units: [W/m2].
Foam::inplaceReorder
void inplaceReorder(const labelUList &oldToNew, ListType &)
Inplace reorder the elements of a list.
Definition: ListOpsTemplates.C:102
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Foam::List::append
void append(const T &)
Append an element at the end of the list.
Foam::Ostream::write
virtual Ostream & write(const token &)=0
Write next token to stream.
Foam::IOobject::NO_READ
@ NO_READ
Definition: IOobject.H:111
Foam::nl
static const char nl
Definition: Ostream.H:260
Foam::Info
messageStream Info
Foam::conformalVoronoiMesh::sortFaces
void sortFaces(faceList &faces, labelList &owner, labelList &neighbour) const
Sort the faces, owner and neighbour lists into.
Foam::cellList
List< cell > cellList
list of cells
Definition: cellList.H:42
Foam::IOstream::info
InfoProxy< IOstream > info() const
Return info proxy.
Definition: IOstream.H:531
Foam::findLower
label findLower(const ListType &, typename ListType::const_reference, const label start, const BinaryOp &bop)
Find last element < given value in sorted list and return index,.
patchNames
wordList patchNames(nPatches)
Foam::I
static const sphericalTensor I(1)
Foam::identity
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
dict
dictionary dict
Definition: searchingEngine.H:14
procNeighbours
labelList procNeighbours(const polyMesh &mesh)
Definition: Test-processorRouter.C:49
meshPtr
static fvMesh * meshPtr
Definition: globalFoam.H:52
Foam::FatalError
error FatalError
Foam::polyPatch::New
static autoPtr< polyPatch > New(const word &patchType, const word &name, const label size, const label start, const label index, const polyBoundaryMesh &bm)
Return a pointer to a new patch created on freestore from.
Definition: polyPatchNew.C:32
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:18
Foam::conformalVoronoiMesh::calcSharedPatchNormal
vector calcSharedPatchNormal(Cell_handle c1, Cell_handle c2) const
DelaunayMeshTools.H
Foam::conformalVoronoiMesh::createPatchInfo
label createPatchInfo(wordList &patchNames, PtrList< dictionary > &patchDicts) const
Foam::DelaunayMeshTools::writeProcessorInterface
void writeProcessorInterface(const fileName &fName, const Triangulation &t, const faceList &faces)
Write the processor interface to an OBJ file.
Foam::constant::physicoChemical::c2
const dimensionedScalar c2
Second radiation constant: default SI units: [m.K].
Foam::boolList
List< bool > boolList
Bool container classes.
Definition: boolList.H:50
Foam::vector
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
Foam::conformalVoronoiMesh::mergeIdenticalDualVertices
void mergeIdenticalDualVertices(const pointField &pts, labelList &boundaryPts)
Merge vertices that are identical.
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:405
Foam::max
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
found
bool found
Definition: TABSMDCalcMethod2.H:32
Foam::List::setSize
void setSize(const label)
Reset size of List.
Foam::autoPtr
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:117
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:57
Foam::linePointRef
line< point, const point & > linePointRef
Line using referred points.
Definition: linePointRef.H:45
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:318
Foam::Pstream::gatherList
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
Definition: gatherScatterList.C:49
Foam::conformalVoronoiMesh::reindexDualVertices
void reindexDualVertices(const Map< label > &dualPtIndexMap, labelList &boundaryPts)
Re-index all of the Delaunay cells.
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:49
Foam::pointIndexHit
PointIndexHit< point > pointIndexHit
Definition: pointIndexHit.H:42
Foam::xferMove
Xfer< T > xferMove(T &)
Construct by transferring the contents of the arg.
Foam::readScalar
bool readScalar(const char *buf, doubleScalar &s)
Read whole of buf as a scalar. Return true if succesful.
Definition: doubleScalar.H:63
Foam::Pout
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
f
labelList f(nPoints)
Foam::motionSmootherAlgo::checkMesh
static bool checkMesh(const bool report, const polyMesh &mesh, const dictionary &dict, labelHashSet &wrongFaces)
Check mesh with mesh settings in dict. Collects incorrect faces.
Definition: motionSmootherAlgoCheck.C:415
Foam::faceList
List< face > faceList
Definition: faceListFwd.H:43
Foam::xferCopy
Xfer< T > xferCopy(const T &)
Construct by copying the contents of the arg.
Foam::Vector< scalar >
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
points
const pointField & points
Definition: gmvOutputHeader.H:1
path
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
Foam::readLabel
label readLabel(Istream &is)
Definition: label.H:64
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
Foam::conformalVoronoiMesh::checkCellSizing
void checkCellSizing()
Check whether the cell sizes are fine enough. Creates a polyMesh.
Foam::invert
labelList invert(const label len, const labelUList &)
Invert one-to-one map. Unmapped elements will be -1.
Definition: ListOps.C:37
patches
patches[0]
Definition: createSingleCellMesh.H:36
List
Definition: Test.C:19
Foam::DelaunayMeshTools::allPoints
tmp< pointField > allPoints(const Triangulation &t)
Extract all points in vertex-index order.
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
ListOps.H
Various functions to operate on Lists.
Foam::conformalVoronoiMesh::createFacesOwnerNeighbourAndPatches
void createFacesOwnerNeighbourAndPatches(const pointField &pts, faceList &faces, labelList &owner, labelList &neighbour, wordList &patchNames, PtrList< dictionary > &patchDicts, labelListList &patchPointPairSlaves, PackedBoolList &boundaryFacesToRemove, bool includeEmptyPatches=false) const
Create all of the internal and boundary faces.
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
Foam::point
vector point
Point is a vector.
Definition: point.H:41
Foam::labelUList
UList< label > labelUList
Definition: UList.H:63
Foam::labelHashSet
HashSet< label, Hash< label > > labelHashSet
A HashSet with label keys.
Definition: HashSet.H:210
Foam::dictionary::subDict
const dictionary & subDict(const word &) const
Find and return a sub-dictionary.
Definition: dictionary.C:631
indexedCellOps.H
Foam::conformalVoronoiMesh::setVertexSizeAndAlignment
void setVertexSizeAndAlignment()
Set the size and alignment data for each vertex.
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:259
Foam::labelPair
Pair< label > labelPair
Label pair.
Definition: labelPair.H:48
OBJstream.H
Foam::name
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
conformalVoronoiMesh.H
indexedCellChecks.H
lookup
stressControl lookup("compactNormalStress") >> compactNormalStress
Foam::conformalVoronoiMesh::sortProcPatches
void sortProcPatches(List< DynamicList< face > > &patchFaces, List< DynamicList< label > > &patchOwners, List< DynamicList< label > > &patchPointPairSlaves, labelPairPairDynListList &patchSortingIndices) const
Sort the processor patches so that the faces are in the same order.
Foam::conformalVoronoiMesh::indexDualVertices
void indexDualVertices(pointField &pts, labelList &boundaryPts)
Index all of the the Delaunay cells and calculate their dual points.
Foam::reverse
void reverse(UList< T > &, const label n)
Definition: UListI.H:322