conformalVoronoiMeshIO.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2012-2018 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 "IOstreams.H"
28 #include "OFstream.H"
29 #include "pointMesh.H"
30 #include "pointFields.H"
31 #include "ListOps.H"
32 #include "polyMeshFilter.H"
33 #include "polyTopoChange.H"
34 #include "PrintTable.H"
35 #include "pointMesh.H"
36 #include "indexedVertexOps.H"
37 #include "DelaunayMeshTools.H"
38 #include "syncTools.H"
39 #include "faceSet.H"
40 #include "OBJstream.H"
41 
42 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
43 
45 (
46  const string& description
47 ) const
48 {
49  timeCheck(time(), description, foamyHexMeshControls().timeChecks());
50 }
51 
52 
54 (
55  const Time& runTime,
56  const string& description,
57  const bool check
58 )
59 {
60  if (check)
61  {
62  Info<< nl << "--- [ cpuTime "
63  << runTime.elapsedCpuTime() << " s, "
64  << "delta " << runTime.cpuTimeIncrement()<< " s";
65 
66  if (description != word::null)
67  {
68  Info<< ", " << description << " ";
69  }
70  else
71  {
72  Info<< " ";
73  }
74 
75  Info<< "] --- " << endl;
76 
77  memInfo m;
78 
79  if (m.valid())
80  {
81  PrintTable<word, label> memoryTable
82  (
83  "Memory Usage (kB): "
84  + description
85  );
86 
87  memoryTable.add("mSize", m.size());
88  memoryTable.add("mPeak", m.peak());
89  memoryTable.add("mRss", m.rss());
90 
91  Info<< incrIndent;
92  memoryTable.print(Info, true, true);
93  Info<< decrIndent;
94  }
95  }
96 }
97 
98 
99 void Foam::conformalVoronoiMesh::writeMesh(const fileName& instance)
100 {
102 
103  // Per cell the Delaunay vertex
104  labelList cellToDelaunayVertex;
105  // Per patch, per face the Delaunay vertex
106  labelListList patchToDelaunayVertex;
107 
108  labelList dualPatchStarts;
109 
110  {
112  labelList boundaryPts;
113  faceList faces;
114  labelList owner;
115  labelList neighbour;
117  PtrList<dictionary> patchDicts;
118  pointField cellCentres;
119  PackedBoolList boundaryFacesToRemove;
120 
121  calcDualMesh
122  (
123  points,
124  boundaryPts,
125  faces,
126  owner,
127  neighbour,
128  patchNames,
129  patchDicts,
130  cellCentres,
131  cellToDelaunayVertex,
132  patchToDelaunayVertex,
133  boundaryFacesToRemove
134  );
135 
136  Info<< nl << "Writing polyMesh to " << instance << endl;
137 
138  writeMesh
139  (
141  instance,
142  points,
143  boundaryPts,
144  faces,
145  owner,
146  neighbour,
147  patchNames,
148  patchDicts,
149  cellCentres,
150  boundaryFacesToRemove
151  );
152 
153  dualPatchStarts.setSize(patchDicts.size());
154 
155  forAll(dualPatchStarts, patchi)
156  {
157  dualPatchStarts[patchi] =
158  readLabel(patchDicts[patchi].lookup("startFace"));
159  }
160  }
161 
162  if (foamyHexMeshControls().writeCellShapeControlMesh())
163  {
165  }
166 
167  if (foamyHexMeshControls().writeBackgroundMeshDecomposition())
168  {
169  Info<< nl << "Writing " << "backgroundMeshDecomposition" << endl;
170 
171  // Have to explicitly update the mesh instance.
172  const_cast<fvMesh&>(decomposition_().mesh()).setInstance
173  (
174  time().timeName()
175  );
176 
177  decomposition_().mesh().write();
178  }
179 
180  if (foamyHexMeshControls().writeTetDualMesh())
181  {
182  label celli = 0;
183  for
184  (
185  Finite_cells_iterator cit = finite_cells_begin();
186  cit != finite_cells_end();
187  ++cit
188  )
189  {
190  if
191  (
192  !cit->hasFarPoint()
193  && !is_infinite(cit)
194  )
195  {
196  cit->cellIndex() = celli++;
197  }
198  }
199 
200  Info<< nl << "Writing " << "tetDualMesh" << endl;
201 
203  labelList cellMap;
204  autoPtr<polyMesh> tetMesh =
205  createMesh("tetDualMesh", vertexMap, cellMap);
206 
207  tetMesh().write();
208 
209 // // Determine map from Delaunay vertex to Dual mesh
210 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
211 //
212 // // From all Delaunay vertices to cell (positive index)
213 // // or patch face (negative index)
214 // labelList vertexToDualAddressing(number_of_vertices(), 0);
215 //
216 // forAll(cellToDelaunayVertex, celli)
217 // {
218 // label vertI = cellToDelaunayVertex[celli];
219 //
220 // if (vertexToDualAddressing[vertI] != 0)
221 // {
222 // FatalErrorInFunction
223 // << "Delaunay vertex " << vertI
224 // << " from cell " << celli
225 // << " is already mapped to "
226 // << vertexToDualAddressing[vertI]
227 // << exit(FatalError);
228 // }
229 // vertexToDualAddressing[vertI] = celli+1;
230 // }
231 //
232 // forAll(patchToDelaunayVertex, patchi)
233 // {
234 // const labelList& patchVertices = patchToDelaunayVertex[patchi];
235 //
236 // forAll(patchVertices, i)
237 // {
238 // label vertI = patchVertices[i];
239 //
240 // if (vertexToDualAddressing[vertI] > 0)
241 // {
242 // FatalErrorInFunction
243 // << "Delaunay vertex " << vertI
244 // << " from patch " << patchi
245 // << " local index " << i
246 // << " is already mapped to cell "
247 // << vertexToDualAddressing[vertI]-1
248 // << exit(FatalError);
249 // }
250 //
251 // // Vertex might be used by multiple faces. Which one to
252 // // use? For now last one wins.
253 // label dualFacei = dualPatchStarts[patchi]+i;
254 // vertexToDualAddressing[vertI] = -dualFacei-1;
255 // }
256 // }
257 //
258 //
259 // // Calculate tet mesh addressing
260 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
261 //
262 // pointField points;
263 // labelList boundaryPts(number_of_finite_cells(), -1);
264 // // From tet point back to Delaunay vertex index
265 // labelList pointToDelaunayVertex;
266 // faceList faces;
267 // labelList owner;
268 // labelList neighbour;
269 // wordList patchTypes;
270 // wordList patchNames;
271 // PtrList<dictionary> patchDicts;
272 // pointField cellCentres;
273 //
274 // calcTetMesh
275 // (
276 // points,
277 // pointToDelaunayVertex,
278 // faces,
279 // owner,
280 // neighbour,
281 // patchTypes,
282 // patchNames,
283 // patchDicts
284 // );
285 //
286 //
287 //
288 // // Calculate map from tet points to dual mesh cells/patch faces
289 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
290 //
291 // labelIOList pointDualAddressing
292 // (
293 // IOobject
294 // (
295 // "pointDualAddressing",
296 // instance,
297 // "tetDualMesh"/polyMesh::meshSubDir,
298 // runTime_,
299 // IOobject::NO_READ,
300 // IOobject::AUTO_WRITE,
301 // false
302 // ),
303 // UIndirectList<label>
304 // (
305 // vertexToDualAddressing,
306 // pointToDelaunayVertex
307 // )()
308 // );
309 //
310 // label pointi = findIndex(pointDualAddressing, -1);
311 // if (pointi != -1)
312 // {
313 // WarningInFunction
314 // << "Delaunay vertex " << pointi
315 // << " does not have a corresponding dual cell." << endl;
316 // }
317 //
318 // Info<< "Writing map from tetDualMesh points to Voronoi mesh to "
319 // << pointDualAddressing.objectPath() << endl;
320 // pointDualAddressing.write();
321 //
322 //
323 //
324 // // Write tet points corresponding to the Voronoi cell/face centre
325 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
326 // {
327 // // Read Voronoi mesh
328 // fvMesh mesh
329 // (
330 // IOobject
331 // (
332 // Foam::polyMesh::defaultRegion,
333 // instance,
334 // runTime_,
335 // IOobject::MUST_READ
336 // )
337 // );
338 // pointIOField dualPoints
339 // (
340 // IOobject
341 // (
342 // "dualPoints",
343 // instance,
344 // "tetDualMesh"/polyMesh::meshSubDir,
345 // runTime_,
346 // IOobject::NO_READ,
347 // IOobject::AUTO_WRITE,
348 // false
349 // ),
350 // points
351 // );
352 //
353 // forAll(pointDualAddressing, pointi)
354 // {
355 // label index = pointDualAddressing[pointi];
356 //
357 // if (index > 0)
358 // {
359 // label celli = index-1;
360 // dualPoints[pointi] = mesh.cellCentres()[celli];
361 // }
362 // else if (index < 0)
363 // {
364 // label facei = -index-1;
365 // if (facei >= mesh.nInternalFaces())
366 // {
367 // dualPoints[pointi] = mesh.faceCentres()[facei];
368 // }
369 // }
370 // }
371 //
372 // Info<< "Writing tetDualMesh points mapped onto Voronoi mesh to "
373 // << dualPoints.objectPath() << endl
374 // << "Replace the polyMesh/points with these." << endl;
375 // dualPoints.write();
376 // }
377 //
378 //
379 // Info<< nl << "Writing tetDualMesh to " << instance << endl;
380 //
381 // PackedBoolList boundaryFacesToRemove;
382 // writeMesh
383 // (
384 // "tetDualMesh",
385 // instance,
386 // points,
387 // boundaryPts,
388 // faces,
389 // owner,
390 // neighbour,
391 // patchTypes,
392 // patchNames,
393 // patchDicts,
394 // cellCentres,
395 // boundaryFacesToRemove
396 // );
397  }
398 }
399 
400 
401 Foam::autoPtr<Foam::fvMesh> Foam::conformalVoronoiMesh::createDummyMesh
402 (
403  const IOobject& io,
404  const wordList& patchNames,
405  const PtrList<dictionary>& patchDicts
406 ) const
407 {
408  autoPtr<fvMesh> meshPtr
409  (
410  new fvMesh
411  (
412  io,
413  xferCopy(pointField()),
414  xferCopy(faceList()),
415  xferCopy(cellList())
416  )
417  );
418  fvMesh& mesh = meshPtr();
419 
420  List<polyPatch*> patches(patchDicts.size());
421 
422  forAll(patches, patchi)
423  {
424  if
425  (
426  patchDicts.set(patchi)
427  && (
428  word(patchDicts[patchi].lookup("type"))
429  == processorPolyPatch::typeName
430  )
431  )
432  {
433  patches[patchi] = new processorPolyPatch
434  (
435  0, // patchSizes[p],
436  0, // patchStarts[p],
437  patchi,
438  mesh.boundaryMesh(),
439  readLabel(patchDicts[patchi].lookup("myProcNo")),
440  readLabel(patchDicts[patchi].lookup("neighbProcNo")),
442  );
443  }
444  else
445  {
446  patches[patchi] = polyPatch::New
447  (
448  patchDicts[patchi].lookup("type"),
449  patchNames[patchi],
450  0, // patchSizes[p],
451  0, // patchStarts[p],
452  patchi,
453  mesh.boundaryMesh()
454  ).ptr();
455  }
456  }
457 
458  mesh.addFvPatches(patches);
459 
460  return meshPtr;
461 }
462 
463 
464 void Foam::conformalVoronoiMesh::checkProcessorPatchesMatch
465 (
466  const PtrList<dictionary>& patchDicts
467 ) const
468 {
469  // Check patch sizes
470  labelListList procPatchSizes
471  (
472  Pstream::nProcs(),
474  );
475 
476  forAll(patchDicts, patchi)
477  {
478  if
479  (
480  patchDicts.set(patchi)
481  && (
482  word(patchDicts[patchi].lookup("type"))
483  == processorPolyPatch::typeName
484  )
485  )
486  {
487  const label procNeighb =
488  readLabel(patchDicts[patchi].lookup("neighbProcNo"));
489 
490  procPatchSizes[Pstream::myProcNo()][procNeighb]
491  = readLabel(patchDicts[patchi].lookup("nFaces"));
492  }
493  }
494 
495  Pstream::gatherList(procPatchSizes);
496 
497  if (Pstream::master())
498  {
499  bool allMatch = true;
500 
501  forAll(procPatchSizes, proci)
502  {
503  const labelList& patchSizes = procPatchSizes[proci];
504 
505  forAll(patchSizes, patchi)
506  {
507  if (patchSizes[patchi] != procPatchSizes[patchi][proci])
508  {
509  allMatch = false;
510 
511  Info<< indent << "Patches " << proci << " and " << patchi
512  << " have different sizes: " << patchSizes[patchi]
513  << " and " << procPatchSizes[patchi][proci] << endl;
514  }
515  }
516  }
517 
518  if (allMatch)
519  {
520  Info<< indent << "All processor patches have matching numbers of "
521  << "faces" << endl;
522  }
523  }
524 }
525 
526 
527 void Foam::conformalVoronoiMesh::reorderPoints
528 (
529  pointField& points,
530  labelList& boundaryPts,
531  faceList& faces,
532  const label nInternalFaces
533 ) const
534 {
535  Info<< incrIndent << indent << "Reordering points into internal/external"
536  << endl;
537 
538  labelList oldToNew(points.size(), label(0));
539 
540  // Find points that are internal
541  for (label fI = nInternalFaces; fI < faces.size(); ++fI)
542  {
543  const face& f = faces[fI];
544 
545  forAll(f, fpI)
546  {
547  oldToNew[f[fpI]] = 1;
548  }
549  }
550 
551  const label nInternalPoints = points.size() - sum(oldToNew);
552 
553  label countInternal = 0;
554  label countExternal = nInternalPoints;
555 
556  forAll(points, pI)
557  {
558  if (oldToNew[pI] == 0)
559  {
560  oldToNew[pI] = countInternal++;
561  }
562  else
563  {
564  oldToNew[pI] = countExternal++;
565  }
566  }
567 
568  Info<< indent
569  << "Number of internal points: " << countInternal << nl
570  << indent << "Number of external points: " << countExternal
571  << decrIndent << endl;
572 
573  inplaceReorder(oldToNew, points);
574  inplaceReorder(oldToNew, boundaryPts);
575 
576  forAll(faces, fI)
577  {
578  face& f = faces[fI];
579 
580  forAll(f, fpI)
581  {
582  f[fpI] = oldToNew[f[fpI]];
583  }
584  }
585 }
586 
587 
588 void Foam::conformalVoronoiMesh::reorderProcessorPatches
589 (
590  const word& meshName,
591  const fileName& instance,
592  const pointField& points,
593  faceList& faces,
594  const wordList& patchNames,
595  const PtrList<dictionary>& patchDicts
596 ) const
597 {
598  Info<< incrIndent << indent << "Reordering processor patches" << endl;
599 
600  Info<< incrIndent;
601  checkProcessorPatchesMatch(patchDicts);
602 
603  // Create dummy mesh with correct proc boundaries to do sorting
604  autoPtr<fvMesh> sortMeshPtr
605  (
606  createDummyMesh
607  (
608  IOobject
609  (
610  meshName,
611  instance,
612  runTime_,
613  IOobject::NO_READ,
615  false
616  ),
617  patchNames,
618  patchDicts
619  )
620  );
621  const fvMesh& sortMesh = sortMeshPtr();
622 
623  // Rotation on new faces.
624  labelList rotation(faces.size(), label(0));
625  labelList faceMap(faces.size(), label(-1));
626 
627  PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
628 
629  // Send ordering
630  forAll(sortMesh.boundaryMesh(), patchi)
631  {
632  const polyPatch& pp = sortMesh.boundaryMesh()[patchi];
633 
634  if (isA<processorPolyPatch>(pp))
635  {
636  refCast<const processorPolyPatch>(pp).initOrder
637  (
638  pBufs,
640  (
641  SubList<face>
642  (
643  faces,
644  readLabel(patchDicts[patchi].lookup("nFaces")),
645  readLabel(patchDicts[patchi].lookup("startFace"))
646  ),
647  points
648  )
649  );
650  }
651  }
652 
653  pBufs.finishedSends();
654 
655  Info<< incrIndent << indent << "Face ordering initialised..." << endl;
656 
657  // Receive and calculate ordering
658  bool anyChanged = false;
659 
660  forAll(sortMesh.boundaryMesh(), patchi)
661  {
662  const polyPatch& pp = sortMesh.boundaryMesh()[patchi];
663 
664  if (isA<processorPolyPatch>(pp))
665  {
666  const label nPatchFaces =
667  readLabel(patchDicts[patchi].lookup("nFaces"));
668  const label patchStartFace =
669  readLabel(patchDicts[patchi].lookup("startFace"));
670 
671  labelList patchFaceMap(nPatchFaces, label(-1));
672  labelList patchFaceRotation(nPatchFaces, label(0));
673 
674  bool changed = refCast<const processorPolyPatch>(pp).order
675  (
676  pBufs,
678  (
679  SubList<face>
680  (
681  faces,
682  nPatchFaces,
683  patchStartFace
684  ),
685  points
686  ),
687  patchFaceMap,
688  patchFaceRotation
689  );
690 
691  if (changed)
692  {
693  // Merge patch face reordering into mesh face reordering table
694  forAll(patchFaceRotation, patchFacei)
695  {
696  rotation[patchFacei + patchStartFace]
697  = patchFaceRotation[patchFacei];
698  }
699 
700  forAll(patchFaceMap, patchFacei)
701  {
702  if (patchFaceMap[patchFacei] != patchFacei)
703  {
704  faceMap[patchFacei + patchStartFace]
705  = patchFaceMap[patchFacei] + patchStartFace;
706  }
707  }
708 
709  anyChanged = true;
710  }
711  }
712  }
713 
714  Info<< incrIndent << indent << "Faces matched." << endl;
715 
716  reduce(anyChanged, orOp<bool>());
717 
718  if (anyChanged)
719  {
720  label nReorderedFaces = 0;
721 
722  forAll(faceMap, facei)
723  {
724  if (faceMap[facei] != -1)
725  {
726  nReorderedFaces++;
727  }
728  }
729 
730  if (nReorderedFaces > 0)
731  {
732  inplaceReorder(faceMap, faces);
733  }
734 
735  // Rotate faces (rotation is already in new face indices).
736  label nRotated = 0;
737 
738  forAll(rotation, facei)
739  {
740  if (rotation[facei] != 0)
741  {
742  faces[facei] = rotateList(faces[facei], rotation[facei]);
743  nRotated++;
744  }
745  }
746 
747  Info<< indent << returnReduce(nReorderedFaces, sumOp<label>())
748  << " faces have been reordered" << nl
749  << indent << returnReduce(nRotated, sumOp<label>())
750  << " faces have been rotated"
751  << decrIndent << decrIndent
752  << decrIndent << decrIndent << endl;
753  }
754 }
755 
756 
758 (
759  const word& meshName,
760  const fileName& instance,
761  pointField& points,
762  labelList& boundaryPts,
763  faceList& faces,
764  labelList& owner,
765  labelList& neighbour,
766  const wordList& patchNames,
767  const PtrList<dictionary>& patchDicts,
768  const pointField& cellCentres,
769  PackedBoolList& boundaryFacesToRemove
770 ) const
771 {
772  if (foamyHexMeshControls().objOutput())
773  {
775  (
776  time().path()/word(meshName + ".obj"),
777  points,
778  faces
779  );
780  }
781 
782  const label nInternalFaces = readLabel(patchDicts[0].lookup("startFace"));
783 
784  reorderPoints(points, boundaryPts, faces, nInternalFaces);
785 
786  if (Pstream::parRun())
787  {
788  reorderProcessorPatches
789  (
790  meshName,
791  instance,
792  points,
793  faces,
794  patchNames,
795  patchDicts
796  );
797  }
798 
799  Info<< incrIndent;
800  Info<< indent << "Constructing mesh" << endl;
801 
802  timeCheck("Before fvMesh construction");
803 
804  fvMesh mesh
805  (
806  IOobject
807  (
808  meshName,
809  instance,
810  runTime_,
811  IOobject::NO_READ,
813  ),
814  xferMove(points),
815  xferMove(faces),
816  xferMove(owner),
817  xferMove(neighbour)
818  );
819 
820  Info<< indent << "Adding patches to mesh" << endl;
821 
822  List<polyPatch*> patches(patchNames.size());
823 
824  label nValidPatches = 0;
825 
826  forAll(patches, p)
827  {
828  label totalPatchSize = readLabel(patchDicts[p].lookup("nFaces"));
829 
830  if
831  (
832  patchDicts.set(p)
833  && (
834  word(patchDicts[p].lookup("type"))
835  == processorPolyPatch::typeName
836  )
837  )
838  {
839  const_cast<dictionary&>(patchDicts[p]).set
840  (
841  "transform",
842  "coincidentFullMatch"
843  );
844 
845  // Do not create empty processor patches
846  if (totalPatchSize > 0)
847  {
848  patches[nValidPatches] = new processorPolyPatch
849  (
850  patchNames[p],
851  patchDicts[p],
852  nValidPatches,
853  mesh.boundaryMesh(),
854  processorPolyPatch::typeName
855  );
856 
857  nValidPatches++;
858  }
859  }
860  else
861  {
862  // Check that the patch is not empty on every processor
863  reduce(totalPatchSize, sumOp<label>());
864 
865  if (totalPatchSize > 0)
866  {
867  patches[nValidPatches] = polyPatch::New
868  (
869  patchNames[p],
870  patchDicts[p],
871  nValidPatches,
872  mesh.boundaryMesh()
873  ).ptr();
874 
875  nValidPatches++;
876  }
877  }
878  }
879 
880  patches.setSize(nValidPatches);
881 
882  mesh.addFvPatches(patches);
883 
884 
885 
886  // Add zones to the mesh
887  addZones(mesh, cellCentres);
888 
889 
890 
891  Info<< indent << "Add pointZones" << endl;
892  {
893  label sz = mesh.pointZones().size();
894 
895  DynamicList<label> bPts(boundaryPts.size());
896 
898  {
899  forAll(boundaryPts, ptI)
900  {
901  const label& bPtType = boundaryPts[ptI];
902 
903  if (bPtType == typeI)
904  {
905  bPts.append(ptI);
906  }
907  }
908 
909 // syncTools::syncPointList(mesh, bPts, maxEqOp<label>(), -1);
910 
911  Info<< incrIndent << indent
912  << "Adding " << bPts.size()
913  << " points of type " << dualMeshPointTypeNames_.words()[typeI]
914  << decrIndent << endl;
915 
916  mesh.pointZones().append
917  (
918  new pointZone
919  (
921  bPts,
922  sz + typeI,
923  mesh.pointZones()
924  )
925  );
926 
927  bPts.clear();
928  }
929  }
930 
931 
932 
933  // Add indirectPatchFaces to a face zone
934  Info<< indent << "Adding indirect patch faces set" << endl;
935 
937  (
938  mesh,
939  boundaryFacesToRemove,
940  orEqOp<unsigned int>()
941  );
942 
943  labelList addr(boundaryFacesToRemove.count());
944  label count = 0;
945 
946  forAll(boundaryFacesToRemove, facei)
947  {
948  if (boundaryFacesToRemove[facei])
949  {
950  addr[count++] = facei;
951  }
952  }
953 
954  addr.setSize(count);
955 
956  faceSet indirectPatchFaces
957  (
958  mesh,
959  "indirectPatchFaces",
960  addr,
962  );
963 
964  indirectPatchFaces.sync(mesh);
965 
966 
967  Info<< decrIndent;
968 
969  timeCheck("Before fvMesh filtering");
970 
971  autoPtr<polyMeshFilter> meshFilter;
972 
973  label nInitialBadFaces = 0;
974 
975  if (foamyHexMeshControls().filterEdges())
976  {
977  Info<< nl << "Filtering edges on polyMesh" << nl << endl;
978 
979  meshFilter.reset(new polyMeshFilter(mesh, boundaryPts));
980 
981  // Filter small edges only. This reduces the number of faces so that
982  // the face filtering is sped up.
983  nInitialBadFaces = meshFilter().filterEdges(0);
984  {
985  const autoPtr<fvMesh>& newMesh = meshFilter().filteredMesh();
986 
987  polyTopoChange meshMod(newMesh());
988 
989  autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false);
990 
991  polyMeshFilter::copySets(newMesh(), mesh);
992  }
993  }
994 
995  if (foamyHexMeshControls().filterFaces())
996  {
997  labelIOList boundaryPtsIO
998  (
999  IOobject
1000  (
1001  "pointPriority",
1002  instance,
1003  time(),
1004  IOobject::NO_READ,
1006  ),
1007  labelList(mesh.nPoints(), labelMin)
1008  );
1009 
1010  forAll(mesh.points(), ptI)
1011  {
1012  boundaryPtsIO[ptI] = mesh.pointZones().whichZone(ptI);
1013  }
1014 
1015 
1016  Info<< nl << "Filtering faces on polyMesh" << nl << endl;
1017 
1018  meshFilter.reset(new polyMeshFilter(mesh, boundaryPtsIO));
1019 
1020  meshFilter().filter(nInitialBadFaces);
1021  {
1022  const autoPtr<fvMesh>& newMesh = meshFilter().filteredMesh();
1023 
1024  polyTopoChange meshMod(newMesh());
1025 
1026  autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false);
1027 
1028  polyMeshFilter::copySets(newMesh(), mesh);
1029  }
1030  }
1031 
1032  timeCheck("After fvMesh filtering");
1033 
1034  mesh.setInstance(instance);
1035 
1036  if (!mesh.write())
1037  {
1039  << "Failed writing polyMesh."
1040  << exit(FatalError);
1041  }
1042  else
1043  {
1044  Info<< nl << "Written filtered mesh to "
1045  << mesh.polyMesh::instance() << nl
1046  << endl;
1047  }
1048 
1049  {
1050  pointScalarField boundaryPtsScalarField
1051  (
1052  IOobject
1053  (
1054  "boundaryPoints_collapsed",
1055  instance,
1056  time(),
1057  IOobject::NO_READ,
1059  ),
1060  pointMesh::New(mesh),
1061  scalar(labelMin)
1062  );
1063 
1064  labelIOList boundaryPtsIO
1065  (
1066  IOobject
1067  (
1068  "pointPriority",
1069  instance,
1070  time(),
1071  IOobject::NO_READ,
1073  ),
1074  labelList(mesh.nPoints(), labelMin)
1075  );
1076 
1077  forAll(mesh.points(), ptI)
1078  {
1079  boundaryPtsScalarField[ptI] = mesh.pointZones().whichZone(ptI);
1080  boundaryPtsIO[ptI] = mesh.pointZones().whichZone(ptI);
1081  }
1082 
1083  boundaryPtsScalarField.write();
1084  boundaryPtsIO.write();
1085  }
1086 
1087 // writeCellSizes(mesh);
1088 
1089 // writeCellAlignments(mesh);
1090 
1091 // writeCellCentres(mesh);
1092 
1094 }
1095 
1096 
1098 (
1099  const fvMesh& mesh
1100 ) const
1101 {
1102  {
1103  timeCheck("Start writeCellSizes");
1104 
1105  Info<< nl << "Create targetCellSize volScalarField" << endl;
1106 
1107  volScalarField targetCellSize
1108  (
1109  IOobject
1110  (
1111  "targetCellSize",
1112  mesh.polyMesh::instance(),
1113  mesh,
1116  ),
1117  mesh,
1118  dimensionedScalar("cellSize", dimLength, 0),
1119  zeroGradientFvPatchScalarField::typeName
1120  );
1121 
1122  scalarField& cellSize = targetCellSize.primitiveFieldRef();
1123 
1124  const vectorField& C = mesh.cellCentres();
1125 
1126  forAll(cellSize, i)
1127  {
1128  cellSize[i] = cellShapeControls().cellSize(C[i]);
1129  }
1130 
1131  // Info<< nl << "Create targetCellVolume volScalarField" << endl;
1132 
1133  // volScalarField targetCellVolume
1134  // (
1135  // IOobject
1136  // (
1137  // "targetCellVolume",
1138  // mesh.polyMesh::instance(),
1139  // mesh,
1140  // IOobject::NO_READ,
1141  // IOobject::AUTO_WRITE
1142  // ),
1143  // mesh,
1144  // dimensionedScalar("cellVolume", dimLength, 0),
1145  // zeroGradientFvPatchScalarField::typeName
1146  // );
1147 
1148  // targetCellVolume.primitiveFieldRef() = pow3(cellSize);
1149 
1150  // Info<< nl << "Create actualCellVolume volScalarField" << endl;
1151 
1152  // volScalarField actualCellVolume
1153  // (
1154  // IOobject
1155  // (
1156  // "actualCellVolume",
1157  // mesh.polyMesh::instance(),
1158  // mesh,
1159  // IOobject::NO_READ,
1160  // IOobject::AUTO_WRITE
1161  // ),
1162  // mesh,
1163  // dimensionedScalar("cellVolume", dimVolume, 0),
1164  // zeroGradientFvPatchScalarField::typeName
1165  // );
1166 
1167  // actualCellVolume.primitiveFieldRef() = mesh.cellVolumes();
1168 
1169  // Info<< nl << "Create equivalentCellSize volScalarField" << endl;
1170 
1171  // volScalarField equivalentCellSize
1172  // (
1173  // IOobject
1174  // (
1175  // "equivalentCellSize",
1176  // mesh.polyMesh::instance(),
1177  // mesh,
1178  // IOobject::NO_READ,
1179  // IOobject::AUTO_WRITE
1180  // ),
1181  // mesh,
1182  // dimensionedScalar("cellSize", dimLength, 0),
1183  // zeroGradientFvPatchScalarField::typeName
1184  // );
1185 
1186  // equivalentCellSize.primitiveFieldRef() = pow
1187  // (
1188  // actualCellVolume.primitiveField(),
1189  // 1.0/3.0
1190  // );
1191 
1192  targetCellSize.correctBoundaryConditions();
1193  // targetCellVolume.correctBoundaryConditions();
1194  // actualCellVolume.correctBoundaryConditions();
1195  // equivalentCellSize.correctBoundaryConditions();
1196 
1197  targetCellSize.write();
1198  // targetCellVolume.write();
1199  // actualCellVolume.write();
1200  // equivalentCellSize.write();
1201  }
1202 
1203  // {
1204  // polyMesh tetMesh
1205  // (
1206  // IOobject
1207  // (
1208  // "tetDualMesh",
1209  // runTime_.constant(),
1210  // runTime_,
1211  // IOobject::MUST_READ
1212  // )
1213  // );
1214 
1215  // pointMesh ptMesh(tetMesh);
1216 
1217  // pointScalarField ptTargetCellSize
1218  // (
1219  // IOobject
1220  // (
1221  // "ptTargetCellSize",
1222  // runTime_.timeName(),
1223  // tetMesh,
1224  // IOobject::NO_READ,
1225  // IOobject::AUTO_WRITE
1226  // ),
1227  // ptMesh,
1228  // dimensionedScalar("ptTargetCellSize", dimLength, 0),
1229  // pointPatchVectorField::calculatedType()
1230  // );
1231 
1232  // scalarField& cellSize = ptTargetCellSize.primitiveFieldRef();
1233 
1234  // const vectorField& P = tetMesh.points();
1235 
1236  // forAll(cellSize, i)
1237  // {
1238  // cellSize[i] = cellShapeControls().cellSize(P[i]);
1239  // }
1240 
1241  // ptTargetCellSize.write();
1242  // }
1243 }
1244 
1245 
1247 (
1248  const fvMesh& mesh
1249 ) const
1250 {
1251 // Info<< nl << "Create cellAlignments volTensorField" << endl;
1252 //
1253 // volTensorField cellAlignments
1254 // (
1255 // IOobject
1256 // (
1257 // "cellAlignments",
1258 // mesh.polyMesh::instance(),
1259 // mesh,
1260 // IOobject::NO_READ,
1261 // IOobject::AUTO_WRITE
1262 // ),
1263 // mesh,
1264 // tensor::I,
1265 // zeroGradientFvPatchTensorField::typeName
1266 // );
1267 //
1268 // tensorField& cellAlignment = cellAlignments.primitiveFieldRef();
1269 //
1270 // const vectorField& C = mesh.cellCentres();
1271 //
1272 // vectorField xDir(cellAlignment.size());
1273 // vectorField yDir(cellAlignment.size());
1274 // vectorField zDir(cellAlignment.size());
1275 //
1276 // forAll(cellAlignment, i)
1277 // {
1278 // cellAlignment[i] = cellShapeControls().cellAlignment(C[i]);
1279 // xDir[i] = cellAlignment[i] & vector(1, 0, 0);
1280 // yDir[i] = cellAlignment[i] & vector(0, 1, 0);
1281 // zDir[i] = cellAlignment[i] & vector(0, 0, 1);
1282 // }
1283 //
1284 // OFstream xStr("xDir.obj");
1285 // OFstream yStr("yDir.obj");
1286 // OFstream zStr("zDir.obj");
1287 //
1288 // forAll(xDir, i)
1289 // {
1290 // meshTools::writeOBJ(xStr, C[i], C[i] + xDir[i]);
1291 // meshTools::writeOBJ(yStr, C[i], C[i] + yDir[i]);
1292 // meshTools::writeOBJ(zStr, C[i], C[i] + zDir[i]);
1293 // }
1294 //
1295 // cellAlignments.correctBoundaryConditions();
1296 //
1297 // cellAlignments.write();
1298 }
1299 
1300 
1302 (
1303  const fvMesh& mesh
1304 ) const
1305 {
1306  Info<< "Writing components of cellCentre positions to volScalarFields"
1307  << " ccx, ccy, ccz in " << runTime_.timeName() << endl;
1308 
1309  for (direction i=0; i<vector::nComponents; i++)
1310  {
1311  volScalarField cci
1312  (
1313  IOobject
1314  (
1315  "cc" + word(vector::componentNames[i]),
1316  runTime_.timeName(),
1317  mesh,
1320  ),
1321  mesh.C().component(i)
1322  );
1323 
1324  cci.write();
1325  }
1326 }
1327 
1328 
1330 (
1331  const polyMesh& mesh
1332 ) const
1333 {
1334  timeCheck("Start findRemainingProtrusionSet");
1335 
1336  const polyBoundaryMesh& patches = mesh.boundaryMesh();
1337 
1338  labelHashSet protrudingBoundaryPoints;
1339 
1340  forAll(patches, patchi)
1341  {
1342  const polyPatch& patch = patches[patchi];
1343 
1344  forAll(patch.localPoints(), pLPI)
1345  {
1346  label meshPtI = patch.meshPoints()[pLPI];
1347 
1348  const Foam::point& pt = patch.localPoints()[pLPI];
1349 
1350  if
1351  (
1352  geometryToConformTo_.wellOutside
1353  (
1354  pt,
1355  sqr(targetCellSize(pt))
1356  )
1357  )
1358  {
1359  protrudingBoundaryPoints.insert(meshPtI);
1360  }
1361  }
1362  }
1363 
1364  cellSet protrudingCells
1365  (
1366  mesh,
1367  "foamyHexMesh_remainingProtrusions",
1368  mesh.nCells()/1000
1369  );
1370 
1371  forAllConstIter(labelHashSet, protrudingBoundaryPoints, iter)
1372  {
1373  const label pointi = iter.key();
1374  const labelList& pCells = mesh.pointCells()[pointi];
1375 
1376  forAll(pCells, pCI)
1377  {
1378  protrudingCells.insert(pCells[pCI]);
1379  }
1380  }
1381 
1382  label protrudingCellsSize = protrudingCells.size();
1383 
1384  reduce(protrudingCellsSize, sumOp<label>());
1385 
1386  if (foamyHexMeshControls().objOutput() && protrudingCellsSize > 0)
1387  {
1388  Info<< nl << "Found " << protrudingCellsSize
1389  << " cells protruding from the surface, writing cellSet "
1390  << protrudingCells.name()
1391  << endl;
1392 
1393  protrudingCells.write();
1394  }
1395 
1396  return protrudingCells;
1397 }
1398 
1399 
1400 void Foam::conformalVoronoiMesh::writePointPairs
1401 (
1402  const fileName& fName
1403 ) const
1404 {
1405  OBJstream os(fName);
1406 
1407  for
1408  (
1409  Delaunay::Finite_edges_iterator eit = finite_edges_begin();
1410  eit != finite_edges_end();
1411  ++eit
1412  )
1413  {
1414  Cell_handle c = eit->first;
1415  Vertex_handle vA = c->vertex(eit->second);
1416  Vertex_handle vB = c->vertex(eit->third);
1417 
1418  if (ptPairs_.isPointPair(vA, vB))
1419  {
1420  os.write
1421  (
1422  linePointRef(topoint(vA->point()), topoint(vB->point()))
1423  );
1424  }
1425  }
1426 }
1427 
1428 
1429 // ************************************************************************* //
GeometricField< scalar, pointPatchField, pointMesh > pointScalarField
Definition: pointFields.H:49
labelHashSet findRemainingProtrusionSet(const polyMesh &mesh) const
Find the cellSet of the boundary cells which have points that.
static wordList words()
The set of names as a list of words.
Definition: NamedEnum.C:105
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:57
Delaunay::Cell_handle Cell_handle
A HashTable with keys but without contents.
Definition: HashSet.H:59
void inplaceReorder(const labelUList &oldToNew, ListType &)
Inplace reorder the elements of a list.
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
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
Ostream & indent(Ostream &os)
Indent stream.
Definition: Ostream.H:226
Delaunay::Vertex_handle Vertex_handle
pointFromPoint topoint(const Point &P)
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
error FatalError
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
ListType rotateList(const ListType &list, const label n)
Rotate a list by n places. If n is positive rotate clockwise/right/down.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
static fvMesh * meshPtr
Definition: globalFoam.H:52
const cellShapeControl & cellShapeControls() const
Return the cellShapeControl object.
uint8_t direction
Definition: direction.H:45
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:427
List< face > faceList
Definition: faceListFwd.H:43
HashTable< label, labelPair, FixedList< label, 2 >::Hash<> > labelTolabelPairHashTable
Definition: DelaunayMesh.H:90
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:309
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:256
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:421
static void timeCheck(const Time &runTime, const string &description=string::null, const bool check=true)
Write the elapsedCpuTime and memory usage, with an optional.
Xfer< T > xferCopy(const T &)
Construct by copying the contents of the arg.
void writeCellCentres(const fvMesh &mesh) const
Calculate and write the cell centres.
static word timeName(const scalar, const int precision=precision_)
Return time name of given scalar time.
Definition: Time.C:626
patches[0]
void writeMesh(const fileName &instance)
Prepare data and call writeMesh for polyMesh and.
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Various functions to operate on Lists.
static const pointMesh & New(const polyMesh &mesh)
Definition: MeshObject.C:44
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:52
HashSet< label, Hash< label > > labelHashSet
A HashSet with label keys.
Definition: HashSet.H:210
void writeObjMesh(const fileName &fName, const pointField &points, const faceList &faces)
Write an OBJ mesh consisting of points and faces.
static const direction nComponents
Number of components in this vector space.
Definition: VectorSpace.H:96
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
stressControl lookup("compactNormalStress") >> compactNormalStress
void writeCellSizes(const fvMesh &mesh) const
Calculate and write a field of the target cell size,.
dynamicFvMesh & mesh
line< point, const point & > linePointRef
Line using referred points.
Definition: linePointRef.H:45
const pointField & points
Xfer< T > xferMove(T &)
Construct by transferring the contents of the arg.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
wordList patchNames(nPatches)
static const word null
An empty word.
Definition: word.H:77
List< label > labelList
A List of labels.
Definition: labelList.H:56
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:29
label readLabel(Istream &is)
Definition: label.H:64
static const char nl
Definition: Ostream.H:265
Delaunay ::Finite_cells_iterator Finite_cells_iterator
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
Field< bool > wellOutside(const pointField &samplePts, const scalarField &testDistSqr) const
Check if point is outside surfaces to conform to by at least.
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
Definition: Ostream.H:240
labelList f(nPoints)
PrimitivePatch< face, SubList, const pointField & > primitivePatch
Addressing for a faceList slice.
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
bool isPointPair(const Vertex_handle &vA, const Vertex_handle &vB) const
List< word > wordList
A List of words.
Definition: fileName.H:54
static void syncFaceList(const polyMesh &mesh, UList< T > &l, const CombineOp &cop)
Synchronize values on all mesh faces.
Definition: syncTools.H:381
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:397
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:409
label patchi
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:50
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
messageStream Info
void writeCellAlignments(const fvMesh &mesh) const
static const NamedEnum< dualMeshPointType, 5 > dualMeshPointTypeNames_
cellShapeControlMesh & shapeControlMesh()
Field< vector > vectorField
Specialisation of Field<T> for vector.
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
virtual Ostream & write(const token &)=0
Write next token to stream.
const cvControls & foamyHexMeshControls() const
Return the foamyHexMeshControls object.
const Time & time() const
Return the Time object.
PtrList< dictionary > patchDicts
Definition: readKivaGrid.H:537
volScalarField & p
virtual void print(Ostream &) const
Print description of IOstream to Ostream.
Definition: IOstream.C:126
virtual bool write(const bool valid=true) const
Write using setting from DB.
void writeInternalDelaunayVertices(const fileName &instance, const Triangulation &t)
Write the internal Delaunay vertices of the tessellation as a.
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:233
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
List< cell > cellList
list of cells
Definition: cellList.H:42
static const label labelMin
Definition: label.H:61
IOList< label > labelIOList
Label container classes.
Definition: labelIOList.H:42
autoPtr< polyMesh > createMesh(const fileName &name, labelTolabelPairHashTable &vertexMap, labelList &cellMap, const bool writeDelaunayData=true) const
Create an fvMesh from the triangulation.
scalar cellSize(const point &pt) const
Return the cell size at the given location.