conformalVoronoiMeshIO.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-2017 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  // Change the transform type on processors to coincident full match.
624 // forAll(sortMesh.boundaryMesh(), patchi)
625 // {
626 // const polyPatch& patch = sortMesh.boundaryMesh()[patchi];
627 //
628 // if (isA<processorPolyPatch>(patch))
629 // {
630 // const processorPolyPatch& cpPatch
631 // = refCast<const processorPolyPatch>(patch);
632 //
633 // processorPolyPatch& pPatch
634 // = const_cast<processorPolyPatch&>(cpPatch);
635 //
636 // pPatch.transform() = coupledPolyPatch::COINCIDENTFULLMATCH;
637 // }
638 // }
639 
640  // Rotation on new faces.
641  labelList rotation(faces.size(), label(0));
642  labelList faceMap(faces.size(), label(-1));
643 
644  PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
645 
646  // Send ordering
647  forAll(sortMesh.boundaryMesh(), patchi)
648  {
649  const polyPatch& pp = sortMesh.boundaryMesh()[patchi];
650 
651  if (isA<processorPolyPatch>(pp))
652  {
653  refCast<const processorPolyPatch>(pp).initOrder
654  (
655  pBufs,
657  (
658  SubList<face>
659  (
660  faces,
661  readLabel(patchDicts[patchi].lookup("nFaces")),
662  readLabel(patchDicts[patchi].lookup("startFace"))
663  ),
664  points
665  )
666  );
667  }
668  }
669 
670  pBufs.finishedSends();
671 
672  Info<< incrIndent << indent << "Face ordering initialised..." << endl;
673 
674  // Receive and calculate ordering
675  bool anyChanged = false;
676 
677  forAll(sortMesh.boundaryMesh(), patchi)
678  {
679  const polyPatch& pp = sortMesh.boundaryMesh()[patchi];
680 
681  if (isA<processorPolyPatch>(pp))
682  {
683  const label nPatchFaces =
684  readLabel(patchDicts[patchi].lookup("nFaces"));
685  const label patchStartFace =
686  readLabel(patchDicts[patchi].lookup("startFace"));
687 
688  labelList patchFaceMap(nPatchFaces, label(-1));
689  labelList patchFaceRotation(nPatchFaces, label(0));
690 
691  bool changed = refCast<const processorPolyPatch>(pp).order
692  (
693  pBufs,
695  (
696  SubList<face>
697  (
698  faces,
699  nPatchFaces,
700  patchStartFace
701  ),
702  points
703  ),
704  patchFaceMap,
705  patchFaceRotation
706  );
707 
708  if (changed)
709  {
710  // Merge patch face reordering into mesh face reordering table
711  forAll(patchFaceRotation, patchFacei)
712  {
713  rotation[patchFacei + patchStartFace]
714  = patchFaceRotation[patchFacei];
715  }
716 
717  forAll(patchFaceMap, patchFacei)
718  {
719  if (patchFaceMap[patchFacei] != patchFacei)
720  {
721  faceMap[patchFacei + patchStartFace]
722  = patchFaceMap[patchFacei] + patchStartFace;
723  }
724  }
725 
726  anyChanged = true;
727  }
728  }
729  }
730 
731  Info<< incrIndent << indent << "Faces matched." << endl;
732 
733  reduce(anyChanged, orOp<bool>());
734 
735  if (anyChanged)
736  {
737  label nReorderedFaces = 0;
738 
739  forAll(faceMap, facei)
740  {
741  if (faceMap[facei] != -1)
742  {
743  nReorderedFaces++;
744  }
745  }
746 
747  if (nReorderedFaces > 0)
748  {
749  inplaceReorder(faceMap, faces);
750  }
751 
752  // Rotate faces (rotation is already in new face indices).
753  label nRotated = 0;
754 
755  forAll(rotation, facei)
756  {
757  if (rotation[facei] != 0)
758  {
759  faces[facei] = rotateList(faces[facei], rotation[facei]);
760  nRotated++;
761  }
762  }
763 
764  Info<< indent << returnReduce(nReorderedFaces, sumOp<label>())
765  << " faces have been reordered" << nl
766  << indent << returnReduce(nRotated, sumOp<label>())
767  << " faces have been rotated"
768  << decrIndent << decrIndent
769  << decrIndent << decrIndent << endl;
770  }
771 }
772 
773 
775 (
776  const word& meshName,
777  const fileName& instance,
778  pointField& points,
779  labelList& boundaryPts,
780  faceList& faces,
781  labelList& owner,
782  labelList& neighbour,
783  const wordList& patchNames,
784  const PtrList<dictionary>& patchDicts,
785  const pointField& cellCentres,
786  PackedBoolList& boundaryFacesToRemove
787 ) const
788 {
789  if (foamyHexMeshControls().objOutput())
790  {
792  (
793  time().path()/word(meshName + ".obj"),
794  points,
795  faces
796  );
797  }
798 
799  const label nInternalFaces = readLabel(patchDicts[0].lookup("startFace"));
800 
801  reorderPoints(points, boundaryPts, faces, nInternalFaces);
802 
803  if (Pstream::parRun())
804  {
805  reorderProcessorPatches
806  (
807  meshName,
808  instance,
809  points,
810  faces,
811  patchNames,
812  patchDicts
813  );
814  }
815 
816  Info<< incrIndent;
817  Info<< indent << "Constructing mesh" << endl;
818 
819  timeCheck("Before fvMesh construction");
820 
821  fvMesh mesh
822  (
823  IOobject
824  (
825  meshName,
826  instance,
827  runTime_,
828  IOobject::NO_READ,
830  ),
831  xferMove(points),
832  xferMove(faces),
833  xferMove(owner),
834  xferMove(neighbour)
835  );
836 
837  Info<< indent << "Adding patches to mesh" << endl;
838 
839  List<polyPatch*> patches(patchNames.size());
840 
841  label nValidPatches = 0;
842 
843  forAll(patches, p)
844  {
845  label totalPatchSize = readLabel(patchDicts[p].lookup("nFaces"));
846 
847  if
848  (
849  patchDicts.set(p)
850  && (
851  word(patchDicts[p].lookup("type"))
852  == processorPolyPatch::typeName
853  )
854  )
855  {
856  const_cast<dictionary&>(patchDicts[p]).set
857  (
858  "transform",
859  "noOrdering"
860  //"coincidentFullMatch"
861  );
862 
863  // Do not create empty processor patches
864  if (totalPatchSize > 0)
865  {
866  patches[nValidPatches] = new processorPolyPatch
867  (
868  patchNames[p],
869  patchDicts[p],
870  nValidPatches,
871  mesh.boundaryMesh(),
872  processorPolyPatch::typeName
873  );
874 
875  nValidPatches++;
876  }
877  }
878  else
879  {
880  // Check that the patch is not empty on every processor
881  reduce(totalPatchSize, sumOp<label>());
882 
883  if (totalPatchSize > 0)
884  {
885  patches[nValidPatches] = polyPatch::New
886  (
887  patchNames[p],
888  patchDicts[p],
889  nValidPatches,
890  mesh.boundaryMesh()
891  ).ptr();
892 
893  nValidPatches++;
894  }
895  }
896  }
897 
898  patches.setSize(nValidPatches);
899 
900  mesh.addFvPatches(patches);
901 
902 
903 
904  // Add zones to the mesh
905  addZones(mesh, cellCentres);
906 
907 
908 
909  Info<< indent << "Add pointZones" << endl;
910  {
911  label sz = mesh.pointZones().size();
912 
913  DynamicList<label> bPts(boundaryPts.size());
914 
916  {
917  forAll(boundaryPts, ptI)
918  {
919  const label& bPtType = boundaryPts[ptI];
920 
921  if (bPtType == typeI)
922  {
923  bPts.append(ptI);
924  }
925  }
926 
927 // syncTools::syncPointList(mesh, bPts, maxEqOp<label>(), -1);
928 
929  Info<< incrIndent << indent
930  << "Adding " << bPts.size()
931  << " points of type " << dualMeshPointTypeNames_.words()[typeI]
932  << decrIndent << endl;
933 
934  mesh.pointZones().append
935  (
936  new pointZone
937  (
939  bPts,
940  sz + typeI,
941  mesh.pointZones()
942  )
943  );
944 
945  bPts.clear();
946  }
947  }
948 
949 
950 
951  // Add indirectPatchFaces to a face zone
952  Info<< indent << "Adding indirect patch faces set" << endl;
953 
955  (
956  mesh,
957  boundaryFacesToRemove,
958  orEqOp<unsigned int>()
959  );
960 
961  labelList addr(boundaryFacesToRemove.count());
962  label count = 0;
963 
964  forAll(boundaryFacesToRemove, facei)
965  {
966  if (boundaryFacesToRemove[facei])
967  {
968  addr[count++] = facei;
969  }
970  }
971 
972  addr.setSize(count);
973 
974  faceSet indirectPatchFaces
975  (
976  mesh,
977  "indirectPatchFaces",
978  addr,
980  );
981 
982  indirectPatchFaces.sync(mesh);
983 
984 
985  Info<< decrIndent;
986 
987  timeCheck("Before fvMesh filtering");
988 
989  autoPtr<polyMeshFilter> meshFilter;
990 
991  label nInitialBadFaces = 0;
992 
993  if (foamyHexMeshControls().filterEdges())
994  {
995  Info<< nl << "Filtering edges on polyMesh" << nl << endl;
996 
997  meshFilter.reset(new polyMeshFilter(mesh, boundaryPts));
998 
999  // Filter small edges only. This reduces the number of faces so that
1000  // the face filtering is sped up.
1001  nInitialBadFaces = meshFilter().filterEdges(0);
1002  {
1003  const autoPtr<fvMesh>& newMesh = meshFilter().filteredMesh();
1004 
1005  polyTopoChange meshMod(newMesh());
1006 
1007  autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false);
1008 
1009  polyMeshFilter::copySets(newMesh(), mesh);
1010  }
1011  }
1012 
1013  if (foamyHexMeshControls().filterFaces())
1014  {
1015  labelIOList boundaryPtsIO
1016  (
1017  IOobject
1018  (
1019  "pointPriority",
1020  instance,
1021  time(),
1022  IOobject::NO_READ,
1024  ),
1025  labelList(mesh.nPoints(), labelMin)
1026  );
1027 
1028  forAll(mesh.points(), ptI)
1029  {
1030  boundaryPtsIO[ptI] = mesh.pointZones().whichZone(ptI);
1031  }
1032 
1033 
1034  Info<< nl << "Filtering faces on polyMesh" << nl << endl;
1035 
1036  meshFilter.reset(new polyMeshFilter(mesh, boundaryPtsIO));
1037 
1038  meshFilter().filter(nInitialBadFaces);
1039  {
1040  const autoPtr<fvMesh>& newMesh = meshFilter().filteredMesh();
1041 
1042  polyTopoChange meshMod(newMesh());
1043 
1044  autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false);
1045 
1046  polyMeshFilter::copySets(newMesh(), mesh);
1047  }
1048  }
1049 
1050  timeCheck("After fvMesh filtering");
1051 
1052  mesh.setInstance(instance);
1053 
1054  if (!mesh.write())
1055  {
1057  << "Failed writing polyMesh."
1058  << exit(FatalError);
1059  }
1060  else
1061  {
1062  Info<< nl << "Written filtered mesh to "
1063  << mesh.polyMesh::instance() << nl
1064  << endl;
1065  }
1066 
1067  {
1068  pointScalarField boundaryPtsScalarField
1069  (
1070  IOobject
1071  (
1072  "boundaryPoints_collapsed",
1073  instance,
1074  time(),
1075  IOobject::NO_READ,
1077  ),
1078  pointMesh::New(mesh),
1079  scalar(labelMin)
1080  );
1081 
1082  labelIOList boundaryPtsIO
1083  (
1084  IOobject
1085  (
1086  "pointPriority",
1087  instance,
1088  time(),
1089  IOobject::NO_READ,
1091  ),
1092  labelList(mesh.nPoints(), labelMin)
1093  );
1094 
1095  forAll(mesh.points(), ptI)
1096  {
1097  boundaryPtsScalarField[ptI] = mesh.pointZones().whichZone(ptI);
1098  boundaryPtsIO[ptI] = mesh.pointZones().whichZone(ptI);
1099  }
1100 
1101  boundaryPtsScalarField.write();
1102  boundaryPtsIO.write();
1103  }
1104 
1105 // writeCellSizes(mesh);
1106 
1107 // writeCellAlignments(mesh);
1108 
1109 // writeCellCentres(mesh);
1110 
1112 }
1113 
1114 
1116 (
1117  const fvMesh& mesh
1118 ) const
1119 {
1120  {
1121  timeCheck("Start writeCellSizes");
1122 
1123  Info<< nl << "Create targetCellSize volScalarField" << endl;
1124 
1125  volScalarField targetCellSize
1126  (
1127  IOobject
1128  (
1129  "targetCellSize",
1130  mesh.polyMesh::instance(),
1131  mesh,
1134  ),
1135  mesh,
1136  dimensionedScalar("cellSize", dimLength, 0),
1137  zeroGradientFvPatchScalarField::typeName
1138  );
1139 
1140  scalarField& cellSize = targetCellSize.primitiveFieldRef();
1141 
1142  const vectorField& C = mesh.cellCentres();
1143 
1144  forAll(cellSize, i)
1145  {
1146  cellSize[i] = cellShapeControls().cellSize(C[i]);
1147  }
1148 
1149  // Info<< nl << "Create targetCellVolume volScalarField" << endl;
1150 
1151  // volScalarField targetCellVolume
1152  // (
1153  // IOobject
1154  // (
1155  // "targetCellVolume",
1156  // mesh.polyMesh::instance(),
1157  // mesh,
1158  // IOobject::NO_READ,
1159  // IOobject::AUTO_WRITE
1160  // ),
1161  // mesh,
1162  // dimensionedScalar("cellVolume", dimLength, 0),
1163  // zeroGradientFvPatchScalarField::typeName
1164  // );
1165 
1166  // targetCellVolume.primitiveFieldRef() = pow3(cellSize);
1167 
1168  // Info<< nl << "Create actualCellVolume volScalarField" << endl;
1169 
1170  // volScalarField actualCellVolume
1171  // (
1172  // IOobject
1173  // (
1174  // "actualCellVolume",
1175  // mesh.polyMesh::instance(),
1176  // mesh,
1177  // IOobject::NO_READ,
1178  // IOobject::AUTO_WRITE
1179  // ),
1180  // mesh,
1181  // dimensionedScalar("cellVolume", dimVolume, 0),
1182  // zeroGradientFvPatchScalarField::typeName
1183  // );
1184 
1185  // actualCellVolume.primitiveFieldRef() = mesh.cellVolumes();
1186 
1187  // Info<< nl << "Create equivalentCellSize volScalarField" << endl;
1188 
1189  // volScalarField equivalentCellSize
1190  // (
1191  // IOobject
1192  // (
1193  // "equivalentCellSize",
1194  // mesh.polyMesh::instance(),
1195  // mesh,
1196  // IOobject::NO_READ,
1197  // IOobject::AUTO_WRITE
1198  // ),
1199  // mesh,
1200  // dimensionedScalar("cellSize", dimLength, 0),
1201  // zeroGradientFvPatchScalarField::typeName
1202  // );
1203 
1204  // equivalentCellSize.primitiveFieldRef() = pow
1205  // (
1206  // actualCellVolume.primitiveField(),
1207  // 1.0/3.0
1208  // );
1209 
1210  targetCellSize.correctBoundaryConditions();
1211  // targetCellVolume.correctBoundaryConditions();
1212  // actualCellVolume.correctBoundaryConditions();
1213  // equivalentCellSize.correctBoundaryConditions();
1214 
1215  targetCellSize.write();
1216  // targetCellVolume.write();
1217  // actualCellVolume.write();
1218  // equivalentCellSize.write();
1219  }
1220 
1221  // {
1222  // polyMesh tetMesh
1223  // (
1224  // IOobject
1225  // (
1226  // "tetDualMesh",
1227  // runTime_.constant(),
1228  // runTime_,
1229  // IOobject::MUST_READ
1230  // )
1231  // );
1232 
1233  // pointMesh ptMesh(tetMesh);
1234 
1235  // pointScalarField ptTargetCellSize
1236  // (
1237  // IOobject
1238  // (
1239  // "ptTargetCellSize",
1240  // runTime_.timeName(),
1241  // tetMesh,
1242  // IOobject::NO_READ,
1243  // IOobject::AUTO_WRITE
1244  // ),
1245  // ptMesh,
1246  // dimensionedScalar("ptTargetCellSize", dimLength, 0),
1247  // pointPatchVectorField::calculatedType()
1248  // );
1249 
1250  // scalarField& cellSize = ptTargetCellSize.primitiveFieldRef();
1251 
1252  // const vectorField& P = tetMesh.points();
1253 
1254  // forAll(cellSize, i)
1255  // {
1256  // cellSize[i] = cellShapeControls().cellSize(P[i]);
1257  // }
1258 
1259  // ptTargetCellSize.write();
1260  // }
1261 }
1262 
1263 
1265 (
1266  const fvMesh& mesh
1267 ) const
1268 {
1269 // Info<< nl << "Create cellAlignments volTensorField" << endl;
1270 //
1271 // volTensorField cellAlignments
1272 // (
1273 // IOobject
1274 // (
1275 // "cellAlignments",
1276 // mesh.polyMesh::instance(),
1277 // mesh,
1278 // IOobject::NO_READ,
1279 // IOobject::AUTO_WRITE
1280 // ),
1281 // mesh,
1282 // tensor::I,
1283 // zeroGradientFvPatchTensorField::typeName
1284 // );
1285 //
1286 // tensorField& cellAlignment = cellAlignments.primitiveFieldRef();
1287 //
1288 // const vectorField& C = mesh.cellCentres();
1289 //
1290 // vectorField xDir(cellAlignment.size());
1291 // vectorField yDir(cellAlignment.size());
1292 // vectorField zDir(cellAlignment.size());
1293 //
1294 // forAll(cellAlignment, i)
1295 // {
1296 // cellAlignment[i] = cellShapeControls().cellAlignment(C[i]);
1297 // xDir[i] = cellAlignment[i] & vector(1, 0, 0);
1298 // yDir[i] = cellAlignment[i] & vector(0, 1, 0);
1299 // zDir[i] = cellAlignment[i] & vector(0, 0, 1);
1300 // }
1301 //
1302 // OFstream xStr("xDir.obj");
1303 // OFstream yStr("yDir.obj");
1304 // OFstream zStr("zDir.obj");
1305 //
1306 // forAll(xDir, i)
1307 // {
1308 // meshTools::writeOBJ(xStr, C[i], C[i] + xDir[i]);
1309 // meshTools::writeOBJ(yStr, C[i], C[i] + yDir[i]);
1310 // meshTools::writeOBJ(zStr, C[i], C[i] + zDir[i]);
1311 // }
1312 //
1313 // cellAlignments.correctBoundaryConditions();
1314 //
1315 // cellAlignments.write();
1316 }
1317 
1318 
1320 (
1321  const fvMesh& mesh
1322 ) const
1323 {
1324  Info<< "Writing components of cellCentre positions to volScalarFields"
1325  << " ccx, ccy, ccz in " << runTime_.timeName() << endl;
1326 
1327  for (direction i=0; i<vector::nComponents; i++)
1328  {
1329  volScalarField cci
1330  (
1331  IOobject
1332  (
1333  "cc" + word(vector::componentNames[i]),
1334  runTime_.timeName(),
1335  mesh,
1338  ),
1339  mesh.C().component(i)
1340  );
1341 
1342  cci.write();
1343  }
1344 }
1345 
1346 
1348 (
1349  const polyMesh& mesh
1350 ) const
1351 {
1352  timeCheck("Start findRemainingProtrusionSet");
1353 
1354  const polyBoundaryMesh& patches = mesh.boundaryMesh();
1355 
1356  labelHashSet protrudingBoundaryPoints;
1357 
1358  forAll(patches, patchi)
1359  {
1360  const polyPatch& patch = patches[patchi];
1361 
1362  forAll(patch.localPoints(), pLPI)
1363  {
1364  label meshPtI = patch.meshPoints()[pLPI];
1365 
1366  const Foam::point& pt = patch.localPoints()[pLPI];
1367 
1368  if
1369  (
1370  geometryToConformTo_.wellOutside
1371  (
1372  pt,
1373  sqr(targetCellSize(pt))
1374  )
1375  )
1376  {
1377  protrudingBoundaryPoints.insert(meshPtI);
1378  }
1379  }
1380  }
1381 
1382  cellSet protrudingCells
1383  (
1384  mesh,
1385  "foamyHexMesh_remainingProtrusions",
1386  mesh.nCells()/1000
1387  );
1388 
1389  forAllConstIter(labelHashSet, protrudingBoundaryPoints, iter)
1390  {
1391  const label pointi = iter.key();
1392  const labelList& pCells = mesh.pointCells()[pointi];
1393 
1394  forAll(pCells, pCI)
1395  {
1396  protrudingCells.insert(pCells[pCI]);
1397  }
1398  }
1399 
1400  label protrudingCellsSize = protrudingCells.size();
1401 
1402  reduce(protrudingCellsSize, sumOp<label>());
1403 
1404  if (foamyHexMeshControls().objOutput() && protrudingCellsSize > 0)
1405  {
1406  Info<< nl << "Found " << protrudingCellsSize
1407  << " cells protruding from the surface, writing cellSet "
1408  << protrudingCells.name()
1409  << endl;
1410 
1411  protrudingCells.write();
1412  }
1413 
1414  return protrudingCells;
1415 }
1416 
1417 
1418 void Foam::conformalVoronoiMesh::writePointPairs
1419 (
1420  const fileName& fName
1421 ) const
1422 {
1423  OBJstream os(fName);
1424 
1425  for
1426  (
1427  Delaunay::Finite_edges_iterator eit = finite_edges_begin();
1428  eit != finite_edges_end();
1429  ++eit
1430  )
1431  {
1432  Cell_handle c = eit->first;
1433  Vertex_handle vA = c->vertex(eit->second);
1434  Vertex_handle vB = c->vertex(eit->third);
1435 
1436  if (ptPairs_.isPointPair(vA, vB))
1437  {
1438  os.write
1439  (
1440  linePointRef(topoint(vA->point()), topoint(vB->point()))
1441  );
1442  }
1443  }
1444 }
1445 
1446 
1447 // ************************************************************************* //
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
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:223
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:418
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:253
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:412
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:644
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:262
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:237
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:394
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:400
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:230
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.