snappyHexMesh.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2015-2023 OpenCFD Ltd.
10  Copyright (C) 2026 Keysight Technologies
11 -------------------------------------------------------------------------------
12 License
13  This file is part of OpenFOAM.
14 
15  OpenFOAM is free software: you can redistribute it and/or modify it
16  under the terms of the GNU General Public License as published by
17  the Free Software Foundation, either version 3 of the License, or
18  (at your option) any later version.
19 
20  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
21  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23  for more details.
24 
25  You should have received a copy of the GNU General Public License
26  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
27 
28 Application
29  snappyHexMesh
30 
31 Group
32  grpMeshGenerationUtilities
33 
34 Description
35  Automatic split hex mesher. Refines and snaps to surface.
36 
37 \*---------------------------------------------------------------------------*/
38 
39 #include "argList.H"
40 #include "Time.H"
41 #include "fvMesh.H"
42 #include "snappyRefineDriver.H"
43 #include "snappySnapDriver.H"
44 #include "snappyLayerDriver.H"
45 #include "searchableSurfaces.H"
46 #include "refinementSurfaces.H"
47 #include "refinementFeatures.H"
48 #include "shellSurfaces.H"
49 #include "decompositionMethod.H"
50 #include "fvMeshDistribute.H"
51 #include "wallPolyPatch.H"
52 #include "refinementParameters.H"
53 #include "snapParameters.H"
54 #include "layerParameters.H"
55 #include "vtkCoordSetWriter.H"
56 #include "vtkSurfaceWriter.H"
57 #include "faceSet.H"
58 #include "motionSmoother.H"
59 #include "polyTopoChange.H"
60 #include "indirectPrimitivePatch.H"
61 #include "surfZoneIdentifierList.H"
62 #include "UnsortedMeshedSurface.H"
63 #include "MeshedSurface.H"
64 #include "globalIndex.H"
65 #include "IOmanip.H"
66 #include "decompositionModel.H"
67 #include "fvMeshTools.H"
68 #include "profiling.H"
69 #include "processorMeshes.H"
70 #include "snappyVoxelMeshDriver.H"
71 
72 using namespace Foam;
73 
74 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
75 
76 // Convert size (as fraction of defaultCellSize) to refinement level
77 label sizeCoeffToRefinement
78 (
79  const scalar level0Coeff, // ratio of hex cell size v.s. defaultCellSize
80  const scalar sizeCoeff
81 )
82 {
83  return round(::log(level0Coeff/sizeCoeff)/::log(2));
84 }
85 
86 
87 autoPtr<refinementSurfaces> createRefinementSurfaces
88 (
89  const searchableSurfaces& allGeometry,
90  const dictionary& surfacesDict,
91  const dictionary& shapeControlDict,
92  const label gapLevelIncrement,
93  const scalar level0Coeff
94 )
95 {
96  autoPtr<refinementSurfaces> surfacePtr;
97 
98  // Count number of surfaces.
99  label surfi = 0;
100  forAll(allGeometry.names(), geomi)
101  {
102  const word& geomName = allGeometry.names()[geomi];
103 
104  if (surfacesDict.found(geomName))
105  {
106  surfi++;
107  }
108  }
109 
110  labelList surfaces(surfi);
111  wordList names(surfi);
112  PtrList<surfaceZonesInfo> surfZones(surfi);
113 
114  labelList regionOffset(surfi);
115 
116  labelList globalMinLevel(surfi, Zero);
117  labelList globalMaxLevel(surfi, Zero);
118  labelList globalLevelIncr(surfi, Zero);
119  PtrList<dictionary> globalPatchInfo(surfi);
120  List<Map<label>> regionMinLevel(surfi);
121  List<Map<label>> regionMaxLevel(surfi);
122  List<Map<label>> regionLevelIncr(surfi);
123  List<Map<scalar>> regionAngle(surfi);
124  List<Map<autoPtr<dictionary>>> regionPatchInfo(surfi);
125 
126  wordHashSet unmatchedKeys(surfacesDict.toc());
127 
128  surfi = 0;
129  forAll(allGeometry.names(), geomi)
130  {
131  const word& geomName = allGeometry.names()[geomi];
132 
133  const entry* ePtr = surfacesDict.findEntry(geomName, keyType::REGEX);
134 
135  if (ePtr)
136  {
137  const dictionary& shapeDict = ePtr->dict();
138  unmatchedKeys.erase(ePtr->keyword());
139 
140  names[surfi] = geomName;
141  surfaces[surfi] = geomi;
142 
143  const searchableSurface& surface = allGeometry[geomi];
144 
145  // Find the index in shapeControlDict
146  // Invert surfaceCellSize to get the refinementLevel
147 
148  const word scsFuncName =
149  shapeDict.get<word>("surfaceCellSizeFunction");
150 
151  const dictionary& scsDict =
152  shapeDict.optionalSubDict(scsFuncName + "Coeffs");
153 
154  const scalar surfaceCellSize =
155  scsDict.get<scalar>("surfaceCellSizeCoeff");
156 
157  const label refLevel = sizeCoeffToRefinement
158  (
159  level0Coeff,
160  surfaceCellSize
161  );
162 
163  globalMinLevel[surfi] = refLevel;
164  globalMaxLevel[surfi] = refLevel;
165  globalLevelIncr[surfi] = gapLevelIncrement;
166 
167  // Surface zones
168  surfZones.set
169  (
170  surfi,
171  new surfaceZonesInfo
172  (
173  surface,
174  shapeDict,
175  allGeometry.regionNames()[surfaces[surfi]]
176  )
177  );
178 
179 
180  // Global perpendicular angle
181  if (shapeDict.found("patchInfo"))
182  {
183  globalPatchInfo.set
184  (
185  surfi,
186  shapeDict.subDict("patchInfo").clone()
187  );
188  }
189 
190 
191  // Per region override of patchInfo
192 
193  if (shapeDict.found("regions"))
194  {
195  const dictionary& regionsDict = shapeDict.subDict("regions");
196  const wordList& regionNames =
197  allGeometry[surfaces[surfi]].regions();
198 
199  forAll(regionNames, regioni)
200  {
201  if (regionsDict.found(regionNames[regioni]))
202  {
203  // Get the dictionary for region
204  const dictionary& regionDict = regionsDict.subDict
205  (
206  regionNames[regioni]
207  );
208 
209  if (regionDict.found("patchInfo"))
210  {
211  regionPatchInfo[surfi].insert
212  (
213  regioni,
214  regionDict.subDict("patchInfo").clone()
215  );
216  }
217  }
218  }
219  }
220 
221  // Per region override of cellSize
222  if (shapeDict.found("regions"))
223  {
224  const dictionary& shapeControlRegionsDict =
225  shapeDict.subDict("regions");
226  const wordList& regionNames =
227  allGeometry[surfaces[surfi]].regions();
228 
229  forAll(regionNames, regioni)
230  {
231  if (shapeControlRegionsDict.found(regionNames[regioni]))
232  {
233  const dictionary& shapeControlRegionDict =
234  shapeControlRegionsDict.subDict
235  (
236  regionNames[regioni]
237  );
238 
239  const word scsFuncName =
240  shapeControlRegionDict.get<word>
241  (
242  "surfaceCellSizeFunction"
243  );
244  const dictionary& scsDict =
245  shapeControlRegionDict.subDict
246  (
247  scsFuncName + "Coeffs"
248  );
249 
250  const scalar surfaceCellSize =
251  scsDict.get<scalar>("surfaceCellSizeCoeff");
252 
253  const label refLevel = sizeCoeffToRefinement
254  (
255  level0Coeff,
256  surfaceCellSize
257  );
258 
259  regionMinLevel[surfi].insert(regioni, refLevel);
260  regionMaxLevel[surfi].insert(regioni, refLevel);
261  regionLevelIncr[surfi].insert(regioni, 0);
262  }
263  }
264  }
265 
266  surfi++;
267  }
268  }
269 
270  // Calculate local to global region offset
271  label nRegions = 0;
272 
273  forAll(surfaces, surfi)
274  {
275  regionOffset[surfi] = nRegions;
276  nRegions += allGeometry[surfaces[surfi]].regions().size();
277  }
278 
279  // Rework surface specific information into information per global region
280  labelList minLevel(nRegions, Zero);
281  labelList maxLevel(nRegions, Zero);
282  labelList gapLevel(nRegions, -1);
283  PtrList<dictionary> patchInfo(nRegions);
284 
285  forAll(globalMinLevel, surfi)
286  {
287  label nRegions = allGeometry[surfaces[surfi]].regions().size();
288 
289  // Initialise to global (i.e. per surface)
290  for (label i = 0; i < nRegions; i++)
291  {
292  label globalRegioni = regionOffset[surfi] + i;
293  minLevel[globalRegioni] = globalMinLevel[surfi];
294  maxLevel[globalRegioni] = globalMaxLevel[surfi];
295  gapLevel[globalRegioni] =
296  maxLevel[globalRegioni]
297  + globalLevelIncr[surfi];
298 
299  if (globalPatchInfo.set(surfi))
300  {
301  patchInfo.set
302  (
303  globalRegioni,
304  globalPatchInfo[surfi].clone()
305  );
306  }
307  }
308 
309  // Overwrite with region specific information
310  forAllConstIters(regionMinLevel[surfi], iter)
311  {
312  label globalRegioni = regionOffset[surfi] + iter.key();
313 
314  minLevel[globalRegioni] = iter();
315  maxLevel[globalRegioni] = regionMaxLevel[surfi][iter.key()];
316  gapLevel[globalRegioni] =
317  maxLevel[globalRegioni]
318  + regionLevelIncr[surfi][iter.key()];
319  }
320 
321  const Map<autoPtr<dictionary>>& localInfo = regionPatchInfo[surfi];
322  forAllConstIters(localInfo, iter)
323  {
324  label globalRegioni = regionOffset[surfi] + iter.key();
325  patchInfo.set(globalRegioni, iter()().clone());
326  }
327  }
328 
329  surfacePtr.reset
330  (
332  (
333  allGeometry,
334  surfaces,
335  names,
336  surfZones,
337  regionOffset,
338  minLevel,
339  maxLevel,
340  gapLevel,
341  scalarField(nRegions, -GREAT), //perpendicularAngle,
342  patchInfo,
343  false //dryRun
344  )
345  );
346 
347 
348  const refinementSurfaces& rf = surfacePtr();
349 
350  // Determine maximum region name length
351  label maxLen = 0;
352  forAll(rf.surfaces(), surfi)
353  {
354  label geomi = rf.surfaces()[surfi];
355  const wordList& regionNames = allGeometry.regionNames()[geomi];
356  forAll(regionNames, regioni)
357  {
358  maxLen = Foam::max(maxLen, label(regionNames[regioni].size()));
359  }
360  }
361 
362 
363  Info<< setw(maxLen) << "Region"
364  << setw(10) << "Min Level"
365  << setw(10) << "Max Level"
366  << setw(10) << "Gap Level" << nl
367  << setw(maxLen) << "------"
368  << setw(10) << "---------"
369  << setw(10) << "---------"
370  << setw(10) << "---------" << endl;
371 
372  forAll(rf.surfaces(), surfi)
373  {
374  label geomi = rf.surfaces()[surfi];
375 
376  Info<< rf.names()[surfi] << ':' << nl;
377 
378  const wordList& regionNames = allGeometry.regionNames()[geomi];
379 
380  forAll(regionNames, regioni)
381  {
382  label globali = rf.globalRegion(surfi, regioni);
383 
384  Info<< setw(maxLen) << regionNames[regioni]
385  << setw(10) << rf.minLevel()[globali]
386  << setw(10) << rf.maxLevel()[globali]
387  << setw(10) << rf.gapLevel()[globali] << endl;
388  }
389  }
390 
391 
392  return surfacePtr;
393 }
394 
395 
396 void extractSurface
397 (
398  const polyMesh& mesh,
399  const Time& runTime,
400  const labelHashSet& includePatches,
401  const fileName& outFileName
402 )
403 {
405 
406  // Collect sizes. Hash on names to handle local-only patches (e.g.
407  // processor patches)
408  HashTable<label> patchSize(1024);
409  label nFaces = 0;
410  for (const label patchi : includePatches)
411  {
412  const polyPatch& pp = bMesh[patchi];
413  patchSize.insert(pp.name(), pp.size());
414  nFaces += pp.size();
415  }
417 
418 
419  // Allocate zone/patch for all patches
420  HashTable<label> compactZoneID(1024);
421  if (Pstream::master())
422  {
423  forAllConstIters(patchSize, iter)
424  {
425  compactZoneID.insert(iter.key(), compactZoneID.size());
426  }
427  }
428  Pstream::broadcast(compactZoneID);
429 
430 
431  // Rework HashTable into labelList just for speed of conversion
432  labelList patchToCompactZone(bMesh.size(), -1);
433  forAllConstIters(compactZoneID, iter)
434  {
435  label patchi = bMesh.findPatchID(iter.key());
436  if (patchi != -1)
437  {
438  patchToCompactZone[patchi] = iter.val();
439  }
440  }
441 
442  // Collect faces on zones
444  DynamicList<label> compactZones(nFaces);
445  for (const label patchi : includePatches)
446  {
447  const polyPatch& pp = bMesh[patchi];
448  forAll(pp, i)
449  {
450  faceLabels.append(pp.start()+i);
451  compactZones.append(patchToCompactZone[pp.index()]);
452  }
453  }
454 
455  // Addressing engine for all faces
456  uindirectPrimitivePatch allBoundary
457  (
459  mesh.points()
460  );
461 
462 
463  // Find correspondence to master points
464  labelList pointToGlobal;
465  labelList uniqueMeshPoints;
467  (
468  allBoundary.meshPoints(),
469  allBoundary.meshPointMap(),
470  pointToGlobal,
471  uniqueMeshPoints
472  );
473 
474  // Gather all unique points on master
475  List<pointField> gatheredPoints(Pstream::nProcs());
476  gatheredPoints[Pstream::myProcNo()] = pointField
477  (
478  mesh.points(),
479  uniqueMeshPoints
480  );
481  Pstream::gatherList(gatheredPoints);
482 
483  // Gather all faces
484  List<faceList> gatheredFaces(Pstream::nProcs());
485  gatheredFaces[Pstream::myProcNo()] = allBoundary.localFaces();
486  forAll(gatheredFaces[Pstream::myProcNo()], i)
487  {
488  inplaceRenumber(pointToGlobal, gatheredFaces[Pstream::myProcNo()][i]);
489  }
490  Pstream::gatherList(gatheredFaces);
491 
492  // Gather all ZoneIDs
493  List<labelList> gatheredZones(Pstream::nProcs());
494  gatheredZones[Pstream::myProcNo()].transfer(compactZones);
495  Pstream::gatherList(gatheredZones);
496 
497  // On master combine all points, faces, zones
498  if (Pstream::master())
499  {
500  pointField allPoints = ListListOps::combine<pointField>
501  (
502  gatheredPoints,
504  );
505  gatheredPoints.clear();
506 
507  faceList allFaces = ListListOps::combine<faceList>
508  (
509  gatheredFaces,
511  );
512  gatheredFaces.clear();
513 
514  labelList allZones = ListListOps::combine<labelList>
515  (
516  gatheredZones,
518  );
519  gatheredZones.clear();
520 
521 
522  // Zones
523  surfZoneIdentifierList surfZones(compactZoneID.size());
524  forAllConstIters(compactZoneID, iter)
525  {
526  surfZones[iter()] = surfZoneIdentifier(iter.key(), iter());
527  Info<< "surfZone " << iter() << " : " << surfZones[iter()].name()
528  << endl;
529  }
530 
531  UnsortedMeshedSurface<face> unsortedFace
532  (
533  std::move(allPoints),
534  std::move(allFaces),
535  std::move(allZones),
536  surfZones
537  );
538 
539 
540  MeshedSurface<face> sortedFace(unsortedFace);
541 
542  fileName globalCasePath
543  (
545  ? runTime.globalPath()/outFileName
546  : runTime.path()/outFileName
547  );
548  globalCasePath.clean(); // Remove unneeded ".."
549 
550  Info<< "Writing merged surface to " << globalCasePath << endl;
551 
552  sortedFace.write(globalCasePath);
553  }
554 }
555 
556 
557 label checkAlignment(const polyMesh& mesh, const scalar tol, Ostream& os)
558 {
559  // Check all edges aligned with one of the coordinate axes
560  const faceList& faces = mesh.faces();
561  const pointField& points = mesh.points();
562 
563  label nUnaligned = 0;
564 
565  forAll(faces, facei)
566  {
567  const face& f = faces[facei];
568  forAll(f, fp)
569  {
570  label fp1 = f.fcIndex(fp);
571  const linePointRef e(edge(f[fp], f[fp1]).line(points));
572  const vector v(e.vec());
573  const scalar magV(mag(v));
574  if (magV > ROOTVSMALL)
575  {
576  for
577  (
578  direction dir = 0;
580  ++dir
581  )
582  {
583  const scalar s(mag(v[dir]));
584  if (s > magV*tol && s < magV*(1-tol))
585  {
586  ++nUnaligned;
587  break;
588  }
589  }
590  }
591  }
592  }
593 
594  reduce(nUnaligned, sumOp<label>());
595 
596  if (nUnaligned)
597  {
598  os << "Initial mesh has " << nUnaligned
599  << " edges unaligned with any of the coordinate axes" << nl << endl;
600  }
601  return nUnaligned;
602 }
603 
604 
605 // Check writing tolerance before doing any serious work
606 scalar getMergeDistance
607 (
608  const polyMesh& mesh,
609  const scalar mergeTol,
610  const bool dryRun
611 )
612 {
613  const boundBox& meshBb = mesh.bounds();
614  scalar mergeDist = mergeTol * meshBb.mag();
615 
616  Info<< nl
617  << "Overall mesh bounding box : " << meshBb << nl
618  << "Relative tolerance : " << mergeTol << nl
619  << "Absolute matching distance : " << mergeDist << nl
620  << endl;
621 
622  // check writing tolerance
623  if (mesh.time().writeFormat() == IOstreamOption::ASCII && !dryRun)
624  {
625  const scalar writeTol = std::pow
626  (
627  scalar(10),
628  -scalar(IOstream::defaultPrecision())
629  );
630 
631  if (mergeTol < writeTol)
632  {
634  << "Your current settings specify ASCII writing with "
635  << IOstream::defaultPrecision() << " digits precision." << nl
636  << "Your merging tolerance (" << mergeTol
637  << ") is finer than this." << nl
638  << "Change to binary writeFormat, "
639  << "or increase the writePrecision" << endl
640  << "or adjust the merge tolerance (mergeTol)."
641  << exit(FatalError);
642  }
643  }
644 
645  return mergeDist;
646 }
647 
648 
649 void removeZeroSizedPatches(fvMesh& mesh)
650 {
651  // Remove any zero-sized ones. Assumes
652  // - processor patches are already only there if needed
653  // - all other patches are available on all processors
654  // - but coupled ones might still be needed, even if zero-size
655  // (e.g. processorCyclic)
656  // See also logic in createPatch.
658 
659  labelList oldToNew(pbm.size(), -1);
660  label newPatchi = 0;
661  forAll(pbm, patchi)
662  {
663  const polyPatch& pp = pbm[patchi];
664 
665  if (!isA<processorPolyPatch>(pp))
666  {
667  if
668  (
669  isA<coupledPolyPatch>(pp)
670  || returnReduceOr(pp.size())
671  )
672  {
673  // Coupled (and unknown size) or uncoupled and used
674  oldToNew[patchi] = newPatchi++;
675  }
676  }
677  }
678 
679  forAll(pbm, patchi)
680  {
681  const polyPatch& pp = pbm[patchi];
682 
683  if (isA<processorPolyPatch>(pp))
684  {
685  oldToNew[patchi] = newPatchi++;
686  }
687  }
688 
689 
690  const label nKeepPatches = newPatchi;
691 
692  // Shuffle unused ones to end
693  if (nKeepPatches != pbm.size())
694  {
695  Info<< endl
696  << "Removing zero-sized patches:" << endl << incrIndent;
697 
698  forAll(oldToNew, patchi)
699  {
700  if (oldToNew[patchi] == -1)
701  {
702  Info<< indent << pbm[patchi].name()
703  << " type " << pbm[patchi].type()
704  << " at position " << patchi << endl;
705  oldToNew[patchi] = newPatchi++;
706  }
707  }
708  Info<< decrIndent;
709 
710  fvMeshTools::reorderPatches(mesh, oldToNew, nKeepPatches, true);
711  Info<< endl;
712  }
713 }
714 
715 
716 // Write mesh and additional information
717 void writeMesh
718 (
719  const string& msg,
720  const meshRefinement& meshRefiner,
721  const meshRefinement::debugType debugLevel,
722  const meshRefinement::writeType writeLevel,
723  const bool writeData = true
724 )
725 {
726  const fvMesh& mesh = meshRefiner.mesh();
727 
728  meshRefiner.printMeshInfo(debugLevel, msg, true);
729 
730  if (writeData)
731  {
732  // Note: don't want to use time().cpuTimeIncrement since layer
733  // addition somehow resets timer ...
734  cpuTime timer;
735 
736  Info<< "Writing mesh to time " << meshRefiner.timeName() << endl;
737 
739  if (!debugLevel && !(writeLevel&meshRefinement::WRITELAYERSETS))
740  {
742  }
744 
745  meshRefiner.write
746  (
747  debugLevel,
749  mesh.time().path()/meshRefiner.timeName()
750  );
751  Info<< "Wrote mesh in = "
752  << timer.cpuTimeIncrement() << " s." << endl;
753  }
754 }
755 
756 
757 int main(int argc, char *argv[])
758 {
760  (
761  "Automatic split hex mesher. Refines and snaps to surface"
762  );
763 
764  #include "addRegionOption.H"
765  #include "addOverwriteOption.H"
766  #include "addProfilingOption.H"
768  (
769  "checkGeometry",
770  "Check all surface geometry for quality"
771  );
773  (
774  "no-intermediate-write",
775  "Do not write intermediate meshes after castellate and snap steps",
776  true // advanced
777  );
779  (
780  "Check case set-up only using a single time step"
781  );
783  (
784  "surfaceSimplify",
785  "boundBox",
786  "Simplify the surface using snappyHexMesh starting from a boundBox"
787  );
789  (
790  "patches",
791  "(patch0 .. patchN)",
792  "Only triangulate selected patches (wildcards supported)"
793  );
795  (
796  "outFile",
797  "file",
798  "Name of the file to save the simplified surface to"
799  );
800  argList::addOption("dict", "file", "Alternative snappyHexMeshDict");
801 
802  argList::noFunctionObjects(); // Never use function objects
803 
804  #include "setRootCase.H"
805  #include "createTime.H"
806 
807  const bool overwrite = args.found("overwrite");
808  const bool checkGeometry = args.found("checkGeometry");
809  const bool surfaceSimplify = args.found("surfaceSimplify");
810  const bool noIntermediateWrite = args.found("no-intermediate-write");
811  const bool dryRun = args.dryRun();
812  const bool optProfiling = args.found("profiling");
813 
814  if (dryRun)
815  {
816  Info<< "Operating in dry-run mode to detect set-up errors"
817  << nl << endl;
818  }
819 
820 
821  #include "createNamedMesh.H"
822  Info<< "Read mesh in = "
823  << runTime.cpuTimeIncrement() << " s" << endl;
824 
825  // Check patches and faceZones are synchronised
828 
829  if (dryRun)
830  {
831  // Check if mesh aligned with cartesian axes
832  checkAlignment(mesh, 1e-6, Pout); //FatalIOError);
833  }
834 
835  if (optProfiling)
836  {
837  PrintMemoryIn("initial memory");
838  }
839 
840  // Read meshing dictionary
841  const word dictName("snappyHexMeshDict");
842  #include "setSystemMeshDictionaryIO.H"
844 
845  // Overall mesh generation mode
846  const meshRefinement::MeshType meshType
847  (
848  meshRefinement::MeshTypeNames.getOrDefault
849  (
850  "type",
851  meshDict,
853  )
854  );
855 
856 
857  // all surface geometry
858  const dictionary& geometryDict =
859  meshRefinement::subDict(meshDict, "geometry", dryRun);
860 
861  // refinement parameters
862  const dictionary& refineDict =
863  meshRefinement::subDict(meshDict, "castellatedMeshControls", dryRun);
864 
865  // mesh motion and mesh quality parameters
866  const dictionary& motionDict =
867  meshRefinement::subDict(meshDict, "meshQualityControls", dryRun);
868 
869  // snap-to-surface parameters
870  const dictionary& snapDict =
871  meshRefinement::subDict(meshDict, "snapControls", dryRun);
872 
873  // layer addition parameters
874  const dictionary& layerDict =
875  meshRefinement::subDict(meshDict, "addLayersControls", dryRun);
876 
877  // absolute merge distance
878  const scalar mergeDist = getMergeDistance
879  (
880  mesh,
881  meshRefinement::get<scalar>
882  (
883  meshDict,
884  "mergeTolerance",
885  dryRun
886  ),
887  dryRun
888  );
889 
890  const bool keepPatches(meshDict.getOrDefault("keepPatches", false));
891 
892  // Writer for writing lines
893  autoPtr<coordSetWriter> setFormatter;
894  {
895  const word writerType
896  (
898  (
899  "setFormat",
900  coordSetWriters::vtkWriter::typeName // Default: "vtk"
901  )
902  );
903 
904  setFormatter = coordSetWriter::New
905  (
906  writerType,
907  meshDict.subOrEmptyDict("formatOptions").optionalSubDict(writerType)
908  );
909  }
910  // Writer for writing surfaces
911  refPtr<surfaceWriter> surfFormatter;
912  {
913  const word type
914  (
916  (
917  "surfaceFormat",
918  surfaceWriters::vtkWriter::typeName // Default: "vtk"
919  )
920  );
921  surfFormatter = surfaceWriter::New
922  (
923  type,
924  meshDict.subOrEmptyDict("formatOptions").optionalSubDict(type)
925  );
926  }
927 
928 
929  const scalar maxSizeRatio
930  (
931  meshDict.getOrDefault<scalar>("maxSizeRatio", 100)
932  );
933 
934 
935  // Read decomposePar dictionary
936  dictionary decomposeDict;
937  if (Pstream::parRun())
938  {
939  // Ensure demand-driven decompositionMethod finds alternative
940  // decomposeParDict location properly.
941 
942  IOdictionary* dictPtr = new IOdictionary
943  (
945  (
946  IOobject
947  (
949  runTime.system(),
950  runTime,
954  ),
955  args.getOrDefault<fileName>("decomposeParDict", "")
956  )
957  );
958 
959  // Store it on the object registry, but to be found it must also
960  // have the expected "decomposeParDict" name.
961 
963  runTime.store(dictPtr);
964 
965  decomposeDict = *dictPtr;
966  }
967  else
968  {
969  decomposeDict.add("method", "none");
970  decomposeDict.add("numberOfSubdomains", 1);
971  }
972 
973 
974  // Debug
975  // ~~~~~
976 
977  // Set debug level
979  (
980  meshDict.getOrDefault<label>
981  (
982  "debug",
983  0
984  )
985  );
986  {
987  wordList flags;
988  if (meshDict.readIfPresent("debugFlags", flags))
989  {
990  debugLevel = meshRefinement::debugType
991  (
993  (
995  flags
996  )
997  );
998  }
999  }
1000  if (debugLevel > 0)
1001  {
1002  meshRefinement::debug = debugLevel;
1003  snappyRefineDriver::debug = debugLevel;
1004  snappySnapDriver::debug = debugLevel;
1005  snappyLayerDriver::debug = debugLevel;
1006  }
1007 
1008  // Set file writing level
1009  {
1010  wordList flags;
1011  if (meshDict.readIfPresent("writeFlags", flags))
1012  {
1014  (
1016  (
1018  (
1020  flags
1021  )
1022  )
1023  );
1024  }
1025  }
1026 
1028  //{
1029  // wordList flags;
1030  // if (meshDict.readIfPresent("outputFlags", flags))
1031  // {
1032  // meshRefinement::outputLevel
1033  // (
1034  // meshRefinement::outputType
1035  // (
1036  // meshRefinement::readFlags
1037  // (
1038  // meshRefinement::outputTypeNames,
1039  // flags
1040  // )
1041  // )
1042  // );
1043  // }
1044  //}
1045 
1046  // for the impatient who want to see some output files:
1048 
1049  // Read geometry
1050  // ~~~~~~~~~~~~~
1051 
1052  searchableSurfaces allGeometry
1053  (
1054  IOobject
1055  (
1056  "abc", // dummy name
1057  mesh.time().constant(), // instance
1058  //mesh.time().findInstance("triSurface", word::null),// instance
1059  "triSurface", // local
1060  mesh.time(), // registry
1063  ),
1064  geometryDict,
1065  meshDict.getOrDefault("singleRegionName", true)
1066  );
1067 
1068 
1069  // Read refinement surfaces
1070  // ~~~~~~~~~~~~~~~~~~~~~~~~
1071 
1072  autoPtr<refinementSurfaces> surfacesPtr;
1073 
1074  Info<< "Reading refinement surfaces." << endl;
1075 
1076  if (surfaceSimplify)
1077  {
1078  addProfiling(surfaceSimplify, "snappyHexMesh::surfaceSimplify");
1079  IOdictionary foamyHexMeshDict
1080  (
1081  IOobject
1082  (
1083  "foamyHexMeshDict",
1084  runTime.system(),
1085  runTime,
1088  )
1089  );
1090 
1091  const dictionary& conformationDict =
1092  foamyHexMeshDict.subDict("surfaceConformation").subDict
1093  (
1094  "geometryToConformTo"
1095  );
1096 
1097  const dictionary& motionDict =
1098  foamyHexMeshDict.subDict("motionControl");
1099 
1100  const dictionary& shapeControlDict =
1101  motionDict.subDict("shapeControlFunctions");
1102 
1103  // Calculate current ratio of hex cells v.s. wanted cell size
1104  const scalar defaultCellSize =
1105  motionDict.get<scalar>("defaultCellSize");
1106 
1107  const scalar initialCellSize = ::pow(mesh.V()[0], 1.0/3.0);
1108 
1109  //Info<< "Wanted cell size = " << defaultCellSize << endl;
1110  //Info<< "Current cell size = " << initialCellSize << endl;
1111  //Info<< "Fraction = " << initialCellSize/defaultCellSize
1112  // << endl;
1113 
1114  surfacesPtr =
1115  createRefinementSurfaces
1116  (
1117  allGeometry,
1118  conformationDict,
1119  shapeControlDict,
1120  refineDict.getOrDefault("gapLevelIncrement", 0),
1121  initialCellSize/defaultCellSize
1122  );
1123 
1125  }
1126  else
1127  {
1128  surfacesPtr.reset
1129  (
1130  new refinementSurfaces
1131  (
1132  allGeometry,
1134  (
1135  refineDict,
1136  "refinementSurfaces",
1137  dryRun
1138  ),
1139  refineDict.getOrDefault("gapLevelIncrement", 0),
1140  dryRun
1141  )
1142  );
1143 
1144  Info<< "Read refinement surfaces in = "
1145  << mesh.time().cpuTimeIncrement() << " s" << nl << endl;
1146  }
1147 
1148  refinementSurfaces& surfaces = surfacesPtr();
1149 
1150 
1151  // Checking only?
1152 
1153  if (checkGeometry)
1154  {
1155  // Check geometry amongst itself (e.g. intersection, size differences)
1156 
1157  // Extract patchInfo
1158  List<wordList> patchTypes(allGeometry.size());
1159 
1160  const PtrList<dictionary>& patchInfo = surfaces.patchInfo();
1161  const labelList& surfaceGeometry = surfaces.surfaces();
1162  forAll(surfaceGeometry, surfi)
1163  {
1164  label geomi = surfaceGeometry[surfi];
1165  const wordList& regNames = allGeometry.regionNames()[geomi];
1166 
1167  patchTypes[geomi].setSize(regNames.size());
1168  forAll(regNames, regioni)
1169  {
1170  label globalRegioni = surfaces.globalRegion(surfi, regioni);
1171 
1172  if (patchInfo.set(globalRegioni))
1173  {
1174  patchTypes[geomi][regioni] =
1175  meshRefinement::get<word>
1176  (
1177  patchInfo[globalRegioni],
1178  "type",
1179  dryRun,
1181  word::null
1182  );
1183  }
1184  else
1185  {
1186  patchTypes[geomi][regioni] = wallPolyPatch::typeName;
1187  }
1188  }
1189  }
1190 
1191  // Write some stats
1192  allGeometry.writeStats(patchTypes, Info);
1193  // Check topology
1194  allGeometry.checkTopology(true);
1195  // Check geometry
1196  allGeometry.checkGeometry
1197  (
1198  maxSizeRatio, // max size ratio
1199  1e-9, // intersection tolerance
1200  setFormatter,
1201  0.01, // min triangle quality
1202  true
1203  );
1204 
1205  if (!dryRun)
1206  {
1207  return 0;
1208  }
1209  }
1210 
1211 
1212  if (dryRun)
1213  {
1214  // Check geometry to mesh bounding box
1215  Info<< "Checking for geometry size relative to mesh." << endl;
1216  const boundBox& meshBb = mesh.bounds();
1217  forAll(allGeometry, geomi)
1218  {
1219  const searchableSurface& s = allGeometry[geomi];
1220  const boundBox& bb = s.bounds();
1221 
1222  scalar ratio = bb.mag() / meshBb.mag();
1223  if (ratio > maxSizeRatio || ratio < 1.0/maxSizeRatio)
1224  {
1225  Warning
1226  << " " << allGeometry.names()[geomi]
1227  << " bounds differ from mesh"
1228  << " by more than a factor " << maxSizeRatio << ":" << nl
1229  << " bounding box : " << bb << nl
1230  << " mesh bounding box : " << meshBb
1231  << endl;
1232  }
1233  if (!meshBb.contains(bb))
1234  {
1235  Warning
1236  << " " << allGeometry.names()[geomi]
1237  << " bounds not fully contained in mesh" << nl
1238  << " bounding box : " << bb << nl
1239  << " mesh bounding box : " << meshBb
1240  << endl;
1241  }
1242  }
1243  Info<< endl;
1244  }
1245 
1246 
1247 
1248 
1249  // Read refinement shells
1250  // ~~~~~~~~~~~~~~~~~~~~~~
1251 
1252  Info<< "Reading refinement shells." << endl;
1253  shellSurfaces shells
1254  (
1255  allGeometry,
1256  meshRefinement::subDict(refineDict, "refinementRegions", dryRun),
1257  dryRun
1258  );
1259  Info<< "Read refinement shells in = "
1260  << mesh.time().cpuTimeIncrement() << " s" << nl << endl;
1261 
1262 
1263  Info<< "Setting refinement level of surface to be consistent"
1264  << " with shells." << endl;
1265  surfaces.setMinLevelFields(shells);
1266  Info<< "Checked shell refinement in = "
1267  << mesh.time().cpuTimeIncrement() << " s" << nl << endl;
1268 
1269 
1270  // Optionally read limit shells
1271  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1272 
1273  const dictionary limitDict(refineDict.subOrEmptyDict("limitRegions"));
1274 
1275  if (!limitDict.empty())
1276  {
1277  Info<< "Reading limit shells." << endl;
1278  }
1279 
1280  shellSurfaces limitShells(allGeometry, limitDict, dryRun);
1281 
1282  if (!limitDict.empty())
1283  {
1284  Info<< "Read limit shells in = "
1285  << mesh.time().cpuTimeIncrement() << " s" << nl << endl;
1286  }
1287 
1288  if (dryRun)
1289  {
1290  // Check for use of all geometry
1291  const wordList& allGeomNames = allGeometry.names();
1292 
1293  labelHashSet unusedGeometries(identity(allGeomNames.size()));
1294  unusedGeometries.erase(surfaces.surfaces());
1295  unusedGeometries.erase(shells.shells());
1296  unusedGeometries.erase(limitShells.shells());
1297 
1298  if (unusedGeometries.size())
1299  {
1300  IOWarningInFunction(geometryDict)
1301  << "The following geometry entries are not used:" << nl;
1302  for (const label geomi : unusedGeometries)
1303  {
1304  Info<< " " << allGeomNames[geomi] << nl;
1305  }
1306  Info<< endl;
1307  }
1308  }
1309 
1310 
1311 
1312 
1313  // Read feature meshes
1314  // ~~~~~~~~~~~~~~~~~~~
1315 
1316  Info<< "Reading features." << endl;
1317  refinementFeatures features
1318  (
1319  mesh,
1321  (
1322  meshRefinement::lookup(refineDict, "features", dryRun)
1323  ),
1324  dryRun
1325  );
1326  Info<< "Read features in = "
1327  << mesh.time().cpuTimeIncrement() << " s" << nl << endl;
1328 
1329 
1330  if (dryRun)
1331  {
1332  // Check geometry to mesh bounding box
1333  Info<< "Checking for line geometry size relative to surface geometry."
1334  << endl;
1335 
1336  OStringStream os;
1337  bool hasErrors = features.checkSizes
1338  (
1339  maxSizeRatio, //const scalar maxRatio,
1340  mesh.bounds(),
1341  true, //const bool report,
1342  os //FatalIOError
1343  );
1344  if (hasErrors)
1345  {
1346  Warning<< os.str() << endl;
1347  }
1348  }
1349 
1350 
1351  // Refinement engine
1352  // ~~~~~~~~~~~~~~~~~
1353 
1354  Info<< nl
1355  << "Determining initial surface intersections" << nl
1356  << "-----------------------------------------" << nl
1357  << endl;
1358 
1359  // Main refinement engine
1360  meshRefinement meshRefiner
1361  (
1362  mesh,
1363  mergeDist, // tolerance used in sorting coordinates
1364  overwrite, // overwrite mesh files?
1365  surfaces, // for surface intersection refinement
1366  features, // for feature edges/point based refinement
1367  shells, // for volume (inside/outside) refinement
1368  limitShells, // limit of volume refinement
1369  labelList(), // initial faces to test
1370  meshType, // how to operate
1371  dryRun
1372  );
1373 
1374  if (!dryRun)
1375  {
1376  meshRefiner.updateIntersections(identity(mesh.nFaces()));
1377  Info<< "Calculated surface intersections in = "
1378  << mesh.time().cpuTimeIncrement() << " s" << nl << endl;
1379  }
1380 
1381  // Some stats
1382  meshRefiner.printMeshInfo(debugLevel, "Initial mesh", true);
1383 
1384  meshRefiner.write
1385  (
1388  mesh.time().path()/meshRefiner.timeName()
1389  );
1390 
1391 
1392  // Refinement parameters
1393  const refinementParameters refineParams(refineDict, dryRun);
1394 
1395  // Snap parameters
1396  const snapParameters snapParams(snapDict, dryRun);
1397 
1398 
1399  Info<< "Setting refinement level of surface to be consistent"
1400  << " with curvature." << endl;
1402  (
1403  refineParams.curvature(),
1404  meshRefiner.meshCutter().level0EdgeLength()
1405  );
1406  Info<< "Checked curvature refinement in = "
1407  << mesh.time().cpuTimeIncrement() << " s" << nl << endl;
1408 
1409 
1410 
1411  // Add all the cellZones and faceZones
1412  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1413 
1414  // 1. cellZones relating to surface (faceZones added later)
1415 
1416  const labelList namedSurfaces
1417  (
1419  );
1420 
1422  (
1423  surfaces.surfZones(),
1424  namedSurfaces,
1425  mesh
1426  );
1427 
1428 
1429  // 2. cellZones relating to locations
1430 
1431  refineParams.addCellZonesToMesh(mesh);
1432 
1433 
1434 
1435  // Add all the surface regions as patches
1436  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1437 
1438  //- Global surface region to patch (non faceZone surface) or patches
1439  // (faceZone surfaces)
1440  labelList globalToMasterPatch;
1441  labelList globalToSlavePatch;
1442 
1443 
1444  {
1445  Info<< nl
1446  << "Adding patches for surface regions" << nl
1447  << "----------------------------------" << nl
1448  << endl;
1449 
1450  // From global region number to mesh patch.
1451  globalToMasterPatch.setSize(surfaces.nRegions(), -1);
1452  globalToSlavePatch.setSize(surfaces.nRegions(), -1);
1453 
1454  if (!dryRun)
1455  {
1456  Info<< setf(ios_base::left)
1457  << setw(6) << "Patch"
1458  << setw(20) << "Type"
1459  << setw(30) << "Region" << nl
1460  << setw(6) << "-----"
1461  << setw(20) << "----"
1462  << setw(30) << "------" << endl;
1463  }
1464 
1465  const labelList& surfaceGeometry = surfaces.surfaces();
1466  const PtrList<dictionary>& surfacePatchInfo = surfaces.patchInfo();
1468 
1469  forAll(surfaceGeometry, surfi)
1470  {
1471  label geomi = surfaceGeometry[surfi];
1472 
1473  const wordList& regNames = allGeometry.regionNames()[geomi];
1474 
1475  if (!dryRun)
1476  {
1477  Info<< surfaces.names()[surfi] << ':' << nl << nl;
1478  }
1479 
1480  const wordList& fzNames =
1481  surfaces.surfZones()[surfi].faceZoneNames();
1482 
1483  if (fzNames.empty())
1484  {
1485  // 'Normal' surface
1486  forAll(regNames, i)
1487  {
1488  label globalRegioni = surfaces.globalRegion(surfi, i);
1489 
1490  label patchi;
1491 
1492  if (surfacePatchInfo.set(globalRegioni))
1493  {
1494  patchi = meshRefiner.addMeshedPatch
1495  (
1496  regNames[i],
1497  surfacePatchInfo[globalRegioni]
1498  );
1499  }
1500  else
1501  {
1502  dictionary patchInfo;
1503  patchInfo.set("type", wallPolyPatch::typeName);
1504 
1505  patchi = meshRefiner.addMeshedPatch
1506  (
1507  regNames[i],
1508  patchInfo
1509  );
1510  }
1511 
1512  if (!dryRun)
1513  {
1514  Info<< setf(ios_base::left)
1515  << setw(6) << patchi
1516  << setw(20) << pbm[patchi].type()
1517  << setw(30) << regNames[i] << nl;
1518  }
1519 
1520  globalToMasterPatch[globalRegioni] = patchi;
1521  globalToSlavePatch[globalRegioni] = patchi;
1522  }
1523  }
1524  else
1525  {
1526  // Zoned surface
1527  forAll(regNames, i)
1528  {
1529  label globalRegioni = surfaces.globalRegion(surfi, i);
1530 
1531  // Add master side patch
1532  {
1533  label patchi;
1534 
1535  if (surfacePatchInfo.set(globalRegioni))
1536  {
1537  patchi = meshRefiner.addMeshedPatch
1538  (
1539  regNames[i],
1540  surfacePatchInfo[globalRegioni]
1541  );
1542  }
1543  else
1544  {
1545  dictionary patchInfo;
1546  patchInfo.set("type", wallPolyPatch::typeName);
1547 
1548  patchi = meshRefiner.addMeshedPatch
1549  (
1550  regNames[i],
1551  patchInfo
1552  );
1553  }
1554 
1555  if (!dryRun)
1556  {
1557  Info<< setf(ios_base::left)
1558  << setw(6) << patchi
1559  << setw(20) << pbm[patchi].type()
1560  << setw(30) << regNames[i] << nl;
1561  }
1562 
1563  globalToMasterPatch[globalRegioni] = patchi;
1564  }
1565  // Add slave side patch
1566  {
1567  const word slaveName = regNames[i] + "_slave";
1568  label patchi;
1569 
1570  if (surfacePatchInfo.set(globalRegioni))
1571  {
1572  patchi = meshRefiner.addMeshedPatch
1573  (
1574  slaveName,
1575  surfacePatchInfo[globalRegioni]
1576  );
1577  }
1578  else
1579  {
1580  dictionary patchInfo;
1581  patchInfo.set("type", wallPolyPatch::typeName);
1582 
1583  patchi = meshRefiner.addMeshedPatch
1584  (
1585  slaveName,
1586  patchInfo
1587  );
1588  }
1589 
1590  if (!dryRun)
1591  {
1592  Info<< setf(ios_base::left)
1593  << setw(6) << patchi
1594  << setw(20) << pbm[patchi].type()
1595  << setw(30) << slaveName << nl;
1596  }
1597 
1598  globalToSlavePatch[globalRegioni] = patchi;
1599  }
1600  }
1601 
1602  // For now: have single faceZone per surface. Use first
1603  // region in surface for patch for zoning
1604  if (regNames.size())
1605  {
1606  forAll(fzNames, fzi)
1607  {
1608  const word& fzName = fzNames[fzi];
1609  label globalRegioni = surfaces.globalRegion(surfi, fzi);
1610 
1611  meshRefiner.addFaceZone
1612  (
1613  fzName,
1614  pbm[globalToMasterPatch[globalRegioni]].name(),
1615  pbm[globalToSlavePatch[globalRegioni]].name(),
1616  surfaces.surfZones()[surfi].faceType()
1617  );
1618  }
1619  }
1620  }
1621 
1622  if (!dryRun)
1623  {
1624  Info<< nl;
1625  }
1626  }
1627  Info<< "Added patches in = "
1628  << mesh.time().cpuTimeIncrement() << " s" << nl << endl;
1629  }
1630 
1631 
1632 
1633  // Add all information for all the remaining faceZones
1634  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1635 
1636  HashTable<Pair<word>> faceZoneToPatches;
1637  forAll(mesh.faceZones(), zonei)
1638  {
1639  const word& fzName = mesh.faceZones()[zonei].name();
1640 
1641  label mpI, spI;
1643  bool hasInfo = meshRefiner.getFaceZoneInfo(fzName, mpI, spI, fzType);
1644 
1645  if (!hasInfo)
1646  {
1647  // faceZone does not originate from a surface but presumably
1648  // from a cellZone pair instead
1649  string::size_type i = fzName.find("_to_");
1650  if (i != string::npos)
1651  {
1652  word cz0 = fzName.substr(0, i);
1653  word cz1 = fzName.substr(i+4, fzName.size()-i+4);
1654  word slaveName(cz1 + "_to_" + cz0);
1655  faceZoneToPatches.insert(fzName, Pair<word>(fzName, slaveName));
1656  }
1657  else
1658  {
1659  // Add as fzName + fzName_slave
1660  const word slaveName = fzName + "_slave";
1661  faceZoneToPatches.insert(fzName, Pair<word>(fzName, slaveName));
1662  }
1663  }
1664  }
1665 
1666  if (faceZoneToPatches.size())
1667  {
1669  (
1670  meshRefiner,
1671  refineParams,
1672  faceZoneToPatches
1673  );
1674  }
1675 
1676 
1677 
1678  // Re-do intersections on meshed boundaries since they use an extrapolated
1679  // other side
1680  {
1681  const labelList adaptPatchIDs(meshRefiner.meshedPatches());
1682 
1684 
1685  label nFaces = 0;
1686  forAll(adaptPatchIDs, i)
1687  {
1688  nFaces += pbm[adaptPatchIDs[i]].size();
1689  }
1690 
1691  labelList faceLabels(nFaces);
1692  nFaces = 0;
1693  forAll(adaptPatchIDs, i)
1694  {
1695  const polyPatch& pp = pbm[adaptPatchIDs[i]];
1696  forAll(pp, i)
1697  {
1698  faceLabels[nFaces++] = pp.start()+i;
1699  }
1700  }
1701  meshRefiner.updateIntersections(faceLabels);
1702  }
1703 
1704 
1705 
1706  // Parallel
1707  // ~~~~~~~~
1708 
1709  // Construct decomposition engine. Note: cannot use decompositionModel
1710  // MeshObject since we're clearing out the mesh inside the mesh generation.
1711  autoPtr<decompositionMethod> decomposerPtr
1712  (
1714  (
1715  decomposeDict
1716  )
1717  );
1718  decompositionMethod& decomposer = *decomposerPtr;
1719 
1720  if (Pstream::parRun() && !decomposer.parallelAware())
1721  {
1723  << "You have selected decomposition method "
1724  << decomposer.typeName
1725  << " which is not parallel aware." << endl
1726  << "Please select one that is (hierarchical, ptscotch)"
1727  << exit(FatalError);
1728  }
1729 
1730  // Mesh distribution engine (uses tolerance to reconstruct meshes)
1731  fvMeshDistribute distributor(mesh);
1732 
1733 
1734 
1735 
1736 
1737  // Now do the real work -refinement -snapping -layers
1738  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1739 
1740  const bool wantRefine
1741  (
1742  meshRefinement::get<bool>(meshDict, "castellatedMesh", dryRun)
1743  );
1744  const bool wantSnap
1745  (
1746  meshRefinement::get<bool>(meshDict, "snap", dryRun)
1747  );
1748  const bool wantLayers
1749  (
1750  meshRefinement::get<bool>(meshDict, "addLayers", dryRun)
1751  );
1752 
1753  if (dryRun)
1754  {
1755  string errorMsg(FatalError.message());
1756  string IOerrorMsg(FatalIOError.message());
1757 
1758  if (errorMsg.size() || IOerrorMsg.size())
1759  {
1760  //errorMsg = "[dryRun] " + errorMsg;
1761  //errorMsg.replaceAll("\n", "\n[dryRun] ");
1762  //IOerrorMsg = "[dryRun] " + IOerrorMsg;
1763  //IOerrorMsg.replaceAll("\n", "\n[dryRun] ");
1764 
1765  Warning
1766  << nl
1767  << "Missing/incorrect required dictionary entries:" << nl
1768  << nl
1769  << IOerrorMsg.c_str() << nl
1770  << errorMsg.c_str() << nl << nl
1771  << "Exiting dry-run" << nl << endl;
1772 
1773  FatalError.clear();
1774  FatalIOError.clear();
1775 
1776  return 0;
1777  }
1778  }
1779 
1780 
1781  // How to treat co-planar faces
1782  meshRefinement::FaceMergeType mergeType =
1783  meshRefinement::FaceMergeType::GEOMETRIC;
1784  {
1785  const bool mergePatchFaces
1786  (
1787  meshDict.getOrDefault("mergePatchFaces", true)
1788  );
1789 
1790  if (!mergePatchFaces)
1791  {
1792  Info<< "Not merging patch-faces of cell to preserve"
1793  << " (split)hex cell shape."
1794  << nl << endl;
1795  mergeType = meshRefinement::FaceMergeType::NONE;
1796  }
1797  else
1798  {
1799  const bool mergeAcrossPatches
1800  (
1801  meshDict.getOrDefault("mergeAcrossPatches", false)
1802  );
1803 
1804  if (mergeAcrossPatches)
1805  {
1806  Info<< "Merging co-planar patch-faces of cells"
1807  << ", regardless of patch assignment"
1808  << nl << endl;
1809  mergeType = meshRefinement::FaceMergeType::IGNOREPATCH;
1810  }
1811  }
1812  }
1813 
1814 
1815 
1816  if (wantRefine)
1817  {
1818  cpuTime timer;
1819 
1820  snappyRefineDriver refineDriver
1821  (
1822  meshRefiner,
1823  decomposer,
1824  distributor,
1825  globalToMasterPatch,
1826  globalToSlavePatch,
1827  setFormatter(),
1828  surfFormatter,
1829  dryRun
1830  );
1831 
1832 
1833  if (!overwrite && !debugLevel)
1834  {
1835  const_cast<Time&>(mesh.time())++;
1836  }
1837 
1838 
1839  refineDriver.doRefine
1840  (
1841  refineDict,
1842  refineParams,
1843  snapParams,
1844  refineParams.handleSnapProblems(),
1845  mergeType,
1846  motionDict
1847  );
1848 
1849  // Remove zero sized patches originating from faceZones
1850  if (!keepPatches && !wantSnap && !wantLayers)
1851  {
1853  }
1854 
1855  if (!dryRun)
1856  {
1857  writeMesh
1858  (
1859  "Refined mesh",
1860  meshRefiner,
1861  debugLevel,
1863  !(noIntermediateWrite && (wantSnap || wantLayers))
1864  );
1865  }
1866 
1867  Info<< "Mesh refined in = "
1868  << timer.cpuTimeIncrement() << " s." << endl;
1869 
1871 
1872  if (optProfiling)
1873  {
1874  PrintMemoryIn("after mesh refine");
1875  }
1876  }
1877 
1878  if (wantSnap)
1879  {
1880  cpuTime timer;
1881 
1882  snappySnapDriver snapDriver
1883  (
1884  meshRefiner,
1885  globalToMasterPatch,
1886  globalToSlavePatch,
1887  dryRun
1888  );
1889 
1890  if (!overwrite && !debugLevel)
1891  {
1892  const_cast<Time&>(mesh.time())++;
1893  }
1894 
1895  // Use the resolveFeatureAngle from the refinement parameters
1896  scalar curvature = refineParams.curvature();
1897  scalar planarAngle = refineParams.planarAngle();
1898 
1899  snapDriver.doSnap
1900  (
1901  snapDict,
1902  motionDict,
1903  mergeType,
1904  curvature,
1905  planarAngle,
1906  snapParams
1907  );
1908 
1909  // Remove zero sized patches originating from faceZones
1910  if (!keepPatches && !wantLayers)
1911  {
1913  }
1914 
1915  if (!dryRun)
1916  {
1917  writeMesh
1918  (
1919  "Snapped mesh",
1920  meshRefiner,
1921  debugLevel,
1923  !(noIntermediateWrite && wantLayers)
1924  );
1925  }
1926 
1927  Info<< "Mesh snapped in = "
1928  << timer.cpuTimeIncrement() << " s." << endl;
1929 
1931 
1932  if (optProfiling)
1933  {
1934  PrintMemoryIn("after mesh snap");
1935  }
1936  }
1937 
1938  if (wantLayers)
1939  {
1940  cpuTime timer;
1941 
1942  // Layer addition parameters
1943  const layerParameters layerParams
1944  (
1945  layerDict,
1946  mesh.boundaryMesh(),
1947  dryRun
1948  );
1949 
1950  snappyLayerDriver layerDriver
1951  (
1952  meshRefiner,
1953  globalToMasterPatch,
1954  globalToSlavePatch,
1955  dryRun
1956  );
1957 
1958  // Use the maxLocalCells from the refinement parameters
1959  const bool preBalance =
1960  returnReduceOr(mesh.nCells() >= refineParams.maxLocalCells());
1961 
1962 
1963  if (!overwrite && !debugLevel)
1964  {
1965  const_cast<Time&>(mesh.time())++;
1966  }
1967 
1968  layerDriver.doLayers
1969  (
1970  layerDict,
1971  motionDict,
1972  layerParams,
1973  mergeType,
1974  preBalance,
1975  decomposer,
1976  distributor
1977  );
1978 
1979  // Remove zero sized patches originating from faceZones
1980  if (!keepPatches)
1981  {
1983  }
1984 
1985  if (!dryRun)
1986  {
1987  writeMesh
1988  (
1989  "Layer mesh",
1990  meshRefiner,
1991  debugLevel,
1993  );
1994  }
1995 
1996  Info<< "Layers added in = "
1997  << timer.cpuTimeIncrement() << " s." << endl;
1998 
2000 
2001  if (optProfiling)
2002  {
2003  PrintMemoryIn("after mesh layers");
2004  }
2005  }
2006 
2007  {
2008  addProfiling(checkMesh, "snappyHexMesh::checkMesh");
2009 
2010  // Check final mesh
2011  Info<< "Checking final mesh ..." << endl;
2012  faceSet wrongFaces(mesh, "wrongFaces", mesh.nFaces()/100);
2013  motionSmoother::checkMesh(false, mesh, motionDict, wrongFaces, dryRun);
2014  const label nErrors = returnReduce
2015  (
2016  wrongFaces.size(),
2017  sumOp<label>()
2018  );
2019 
2020  if (nErrors > 0)
2021  {
2022  Info<< "Finished meshing with " << nErrors << " illegal faces"
2023  << " (concave, zero area or negative cell pyramid volume)"
2024  << endl;
2025  wrongFaces.write();
2026  }
2027  else
2028  {
2029  Info<< "Finished meshing without any errors" << endl;
2030  }
2031 
2033  }
2034 
2035 
2036  if (surfaceSimplify)
2037  {
2038  addProfiling(surfaceSimplify, "snappyHexMesh::surfaceSimplify");
2039 
2041 
2042  labelHashSet includePatches(bMesh.size());
2043 
2044  if (args.found("patches"))
2045  {
2046  includePatches = bMesh.patchSet
2047  (
2048  args.getList<wordRe>("patches")
2049  );
2050  }
2051  else
2052  {
2053  forAll(bMesh, patchi)
2054  {
2055  const polyPatch& patch = bMesh[patchi];
2056 
2057  if (!isA<processorPolyPatch>(patch))
2058  {
2059  includePatches.insert(patchi);
2060  }
2061  }
2062  }
2063 
2064  fileName outFileName
2065  (
2067  (
2068  "outFile",
2069  "constant/triSurface/simplifiedSurface.stl"
2070  )
2071  );
2072 
2073  extractSurface
2074  (
2075  mesh,
2076  runTime,
2077  includePatches,
2078  outFileName
2079  );
2080 
2081  pointIOField cellCentres
2082  (
2083  IOobject
2084  (
2085  "internalCellCentres",
2086  runTime.timeName(),
2087  mesh,
2090  ),
2091  mesh.cellCentres()
2092  );
2093 
2094  cellCentres.write();
2095  }
2096 
2098 
2099  Info<< "Finished meshing in = "
2100  << runTime.elapsedCpuTime() << " s." << endl;
2101 
2102  // Report max memory usage
2103  Info<< "Memory per-node = "
2105 
2106  if (dryRun)
2107  {
2108  string errorMsg(FatalError.message());
2109  string IOerrorMsg(FatalIOError.message());
2110 
2111  if (errorMsg.size() || IOerrorMsg.size())
2112  {
2113  //errorMsg = "[dryRun] " + errorMsg;
2114  //errorMsg.replaceAll("\n", "\n[dryRun] ");
2115  //IOerrorMsg = "[dryRun] " + IOerrorMsg;
2116  //IOerrorMsg.replaceAll("\n", "\n[dryRun] ");
2117 
2118  Perr<< nl
2119  << "Missing/incorrect required dictionary entries:" << nl
2120  << nl
2121  << IOerrorMsg.c_str() << nl
2122  << errorMsg.c_str() << nl << nl
2123  << "Exiting dry-run" << nl << endl;
2124 
2125  FatalError.clear();
2126  FatalIOError.clear();
2127 
2128  return 0;
2129  }
2130  }
2131 
2132 
2133  Info<< "End\n" << endl;
2134 
2135  return 0;
2136 }
2137 
2138 
2139 // ************************************************************************* //
const IOdictionary & meshDict
A surface geometry mesh, in which the surface zone information is conveyed by the &#39;zoneId&#39; associated...
Definition: MeshedSurface.H:76
static bool checkMesh(const bool report, const polyMesh &mesh, const dictionary &dict, labelHashSet &wrongFaces, const bool dryRun=false)
Check mesh with mesh settings in dict. Collects incorrect faces.
const polyBoundaryMesh & pbm
prefixOSstream Perr
OSstream wrapped stderr (std::cerr) with parallel prefix.
label addFaceZone(const word &fzName, const word &masterPatch, const word &slavePatch, const surfaceZonesInfo::faceZoneType &fzType)
Add/lookup faceZone and update information. Return index of.
static void noFunctionObjects(bool addWithOption=false)
Remove &#39;-noFunctionObjects&#39; option and ignore any occurrences.
Definition: argList.C:562
static void reorderPatches(fvMesh &, const labelList &oldToNew, const label nPatches, const bool validBoundary)
Reorder and remove trailing patches.
Definition: fvMeshTools.C:317
static void addNote(const string &note)
Add extra notes for the usage information.
Definition: argList.C:477
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:119
static FOAM_NO_DANGLING_REFERENCE const dictionary & subDict(const dictionary &dict, const word &keyword, const bool noExit, enum keyType::option matchOpt=keyType::REGEX)
Wrapper around dictionary::subDict which does not exit.
Simple container to keep together layer specific information.
uint8_t direction
Definition: direction.H:46
A line primitive.
Definition: line.H:52
void clear() const
Clear any accumulated error messages.
Definition: error.C:474
A class for handling file names.
Definition: fileName.H:72
const labelList & surfaces() const
Ostream & indent(Ostream &os)
Indent stream.
Definition: Ostream.H:480
A list of face labels.
Definition: faceSet.H:47
virtual bool parallelAware() const =0
Is method parallel aware?
Identifies a surface patch/zone by name and index, with optional geometric type.
label checkTopology(const bool report) const
All topological checks. Return number of failed checks.
dimensionedScalar log(const dimensionedScalar &ds)
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:68
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
MeshType
Enumeration for how to operate.
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:130
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:652
void append(const T &val)
Append an element at the end of the list.
Definition: List.H:496
fileName path() const
The path for the case = rootPath/caseName.
Definition: TimePathsI.H:102
bool getFaceZoneInfo(const word &fzName, label &masterPatchID, label &slavePatchID, surfaceZonesInfo::faceZoneType &fzType) const
Lookup faceZone information. Return false if no information.
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:205
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
void printMeshInfo(const bool debug, const string &msg, const bool printCellLevel) const
Print some mesh stats.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
static ITstream & lookup(const dictionary &dict, const word &keyword, const bool noExit, enum keyType::option matchOpt=keyType::REGEX)
Wrapper around dictionary::lookup which does not exit.
Implements a timeout mechanism via sigalarm.
Definition: timer.H:82
"ascii" (normal default)
bool empty() const noexcept
True if List is empty (ie, size() is zero)
Definition: UList.H:702
wordList patchTypes(nPatches)
const word dictName("faMeshDefinition")
engineTime & runTime
Object access operator or list access operator (default is pass-through)
Definition: UList.H:1130
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:518
static autoPtr< surfaceWriter > New(const word &writeType)
Select construct a surfaceWriter.
List< T > getList(const label index) const
Get a List of values from the argument at index.
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1774
static int myProcNo(label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Negative if the process is not a...
Definition: UPstream.H:1799
Required Classes.
#define addProfiling(Name,...)
Define profiling trigger with specified name and description string. The description is generated by ...
static writeType writeLevel()
Get/set write level.
virtual const dictionary & dict() const =0
Return dictionary, if entry is a dictionary, otherwise Fatal.
static unsigned int defaultPrecision() noexcept
Return the default precision.
Definition: IOstream.H:437
static void addBoolOption(const word &optName, const string &usage="", bool advanced=false)
Add a bool option to validOptions with usage information.
Definition: argList.C:389
bool store()
Register object with its registry and transfer ownership to the registry.
Definition: regIOobjectI.H:36
static bool writeNow()
Write profiling information now.
Definition: profiling.C:131
static const Enum< MeshType > MeshTypeNames
static const word canonicalName
The canonical name ("decomposeParDict") under which the MeshObject is registered. ...
static labelList addCellZonesToMesh(const PtrList< surfaceZonesInfo > &surfList, const labelList &namedSurfaces, polyMesh &mesh)
fileName globalPath() const
The global path for the case = rootPath/globalCaseName.
Definition: TimePathsI.H:108
A bounding box defined in terms of min/max extrema points.
Definition: boundBox.H:70
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:625
::Foam::direction nComponents(const expressions::valueTypeCode) noexcept
The number of components associated with given valueTypeCode.
Definition: exprTraits.C:40
Base class of (analytical or triangulated) surface. Encapsulates all the search routines. WIP.
autoPtr< globalIndex > mergePoints(labelList &pointToGlobal, labelList &uniquePoints) const
Helper for merging (collocated!) mesh point data.
wordList regionNames
const labelList & minLevel() const
From global region number to refinement level.
static void broadcast(Type &value, const int communicator=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all communicator ranks. Does nothing in non-paral...
Ignore writing from objectRegistry::writeObject()
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T. FatalIOError if not found, or if the number of tokens is incorrect.
T getOrDefault(const word &optName, const T &deflt) const
Get a value from the named option if present, or return default.
Definition: argListI.H:300
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:360
label nFaces() const noexcept
Number of mesh faces.
const DimensionedField< scalar, volMesh > & V() const
Return cell volumes.
Simple container to keep together refinement specific information.
const bool writeData(pdfDictionary.get< bool >("writeData"))
labelList faceLabels(nFaceLabels)
bool contains(const T &val) const
True if the value is contained in the list.
Definition: UListI.H:295
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
Definition: dictionary.C:441
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:68
A class for managing references or pointers (no reference counting)
Definition: HashPtrTable.H:49
autoPtr< dictionary > clone() const
Construct and return clone.
Definition: dictionary.C:165
bool processorCase() const noexcept
True if this is a processor case.
Definition: TimePathsI.H:52
scalar level0EdgeLength() const
Typical edge length between unrefined points.
Definition: hexRef8.H:499
wordList toc() const
Return the table of contents.
Definition: dictionary.C:587
const fvMesh & mesh() const
Reference to mesh.
static void gatherList(UList< T > &values, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Gather data, but keep individual values separate.
void reduce(T &value, [[maybe_unused]] BinaryOp bop, [[maybe_unused]] const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce)
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry (const access) with the given keyword.
Definition: dictionaryI.H:104
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:50
Container for data on surfaces used for surface-driven refinement. Contains all the data about the le...
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1063
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:400
label fcIndex(const label i) const noexcept
The forward circular index. The next index in the list which returns to the first at the end of the l...
Definition: UListI.H:99
Foam::string str() const
Get the string. As Foam::string instead of std::string (may change in future)
Definition: StringStream.H:251
void reset(T *p=nullptr) noexcept
Delete managed object and set to new given pointer.
Definition: autoPtrI.H:36
static const Enum< writeType > writeTypeNames
Encapsulates queries for features.
bool insert(const Key &key, const T &obj)
Copy insert a new entry, not overwriting existing entries.
Definition: HashTableI.H:152
label size() const noexcept
The number of elements in table.
Definition: HashTable.H:358
const dictionary & optionalSubDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary, otherwise return this dictionary.
Definition: dictionary.C:560
static void removeFiles(const polyMesh &mesh)
Helper: remove all procAddressing files from mesh instance.
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:805
static autoPtr< coordSetWriter > New(const word &writeFormat)
Return a reference to the selected writer.
A list of faces which address into the list of points.
Required Classes.
Sends/receives parts of mesh+fvfields to neighbouring processors. Used in load balancing.
static void removeFiles(const polyMesh &)
Helper: remove all sets files from mesh instance.
Definition: topoSet.C:693
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
const keyType & keyword() const noexcept
Return keyword.
Definition: entry.H:231
FaceMergeType
Enumeration for what to do with co-planar patch faces on a single.
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
const pointField & points
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition: polyMesh.H:611
A class for handling words, derived from Foam::string.
Definition: word.H:63
static void addDryRunOption(const string &usage, bool advanced=false)
Enable a &#39;dry-run&#39; bool option, with usage information.
Definition: argList.C:519
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Simple container to keep together snap specific information.
int dryRun() const noexcept
Return the dry-run flag.
Definition: argListI.H:109
const labelList & gapLevel() const
From global region number to small gap refinement level.
const List< wordList > & regionNames() const
Region names per surface.
scalar mag() const
The magnitude/length of the bounding box diagonal.
Definition: boundBoxI.H:198
label size() const noexcept
The number of entries in the list.
Definition: UPtrListI.H:106
string message() const
The accumulated error message.
Definition: error.C:463
const word & system() const noexcept
Return system name.
Definition: TimePathsI.H:137
static void checkCoupledFaceZones(const polyMesh &)
Helper function: check that face zones are synced.
virtual bool write(const bool writeOnProc=true) const
Write using setting from DB.
static const word null
An empty word.
Definition: word.H:84
Container for searchableSurfaces. The collection is specified as a dictionary. For example...
static void addOption(const word &optName, const string &param="", const string &usage="", bool advanced=false)
Add an option to validOptions with usage information.
Definition: argList.C:400
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
T returnReduce(const T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
const globalMeshData & globalData() const
Return parallel info (demand-driven)
Definition: polyMesh.C:1296
Abstract base class for domain decomposition.
Encapsulates queries for volume refinement (&#39;refine all cells within shell&#39;).
Definition: shellSurfaces.H:53
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1088
static void mapCombineGather(Container &values, CombineOp cop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Forwards to Pstream::mapGather with an in-place cop.
graph_traits< Graph >::vertices_size_type size_type
Definition: SloanRenumber.C:71
const PtrList< surfaceZonesInfo > & surfZones() const
const vectorField & cellCentres() const
bool returnReduceOr(const bool value, const int communicator=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie...
Definition: PtrList.H:174
A wordRe is a Foam::word, but can contain a regular expression for matching words or strings...
Definition: wordRe.H:78
word timeName() const
Replacement for Time::timeName() that returns oldInstance (if overwrite_)
A polyBoundaryMesh is a polyPatch list with registered IO, a reference to the associated polyMesh...
const hexRef8 & meshCutter() const
Reference to meshcutting engine.
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
Istream and Ostream manipulators taking arguments.
static int readFlags(const EnumContainer &namedEnum, const wordList &words)
Helper: convert wordList into bit pattern using provided Enum.
bool checkParallelSync(const bool report=false) const
Check whether all procs have all patches and in same order.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
static word timeName(const scalar t, const int precision=precision_)
Return a time name for the given scalar time value formatted with the given precision.
Definition: Time.C:713
Smanip< std::ios_base::fmtflags > setf(std::ios_base::fmtflags flags)
Definition: IOmanip.H:169
const word & constant() const noexcept
Return constant name.
Definition: TimePathsI.H:131
int debug
Static debugging option.
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry if present, and assign to T val. FatalIOError if it is found and the number of tokens i...
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition: polyMesh.H:673
static bool clean(std::string &str)
Cleanup filename string, possibly applies other transformations such as changing the path separator e...
Definition: fileName.C:192
label addMeshedPatch(const word &name, const dictionary &)
Add patch originating from meshing. Update meshedPatches_.
labelList meshedPatches() const
Get patchIDs for patches added in addMeshedPatch.
const wordList edge
Standard (finite-area) edge field types (scalar, vector, tensor, etc)
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
Definition: Ostream.H:498
virtual void rename(const word &newName)
Rename.
Definition: regIOobject.C:481
labelList f(nPoints)
dictionary subOrEmptyDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX, const bool mandatory=false) const
Find and return a sub-dictionary as a copy, otherwise return an empty dictionary. ...
Definition: dictionary.C:521
All to do with adding layers.
double cpuTimeIncrement() const
Return CPU time [seconds] since last call to cpuTimeIncrement(), resetCpuTimeIncrement().
Definition: cpuTimePosix.C:86
static void addFaceZones(meshRefinement &meshRefiner, const refinementParameters &refineParams, const HashTable< Pair< word >> &faceZoneToPatches)
Helper: add faceZones and patches.
static List< int64_t > list_mem_hwm(const bool useMaxValue=false)
List of the per-node memory high-water mark values. These are summed per-node and aggregated across a...
Definition: error.C:243
messageStream Warning
Warning stream (stdout output on master, null elsewhere), with additional &#39;FOAM Warning&#39; header text...
void setCurvatureMinLevelFields(const scalar cosAngle, const scalar level0EdgeLength)
Update minLevelFields according to (triSurface-only) curvature.
Helper class which maintains intersections of (changing) mesh with (static) surfaces.
bool erase(T *item)
Remove the specified element from the list and delete it.
Definition: ILList.C:101
void updateIntersections(const labelUList &changedFaces)
Find any intersection of surface. Store in surfaceIndex_.
All to do with snapping to surface.
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
static autoPtr< decompositionMethod > New(const dictionary &decompDict, const word &regionName="")
Return a reference to the selected decomposition method, optionally region-specific.
const wordList & names() const
Names of surfaces.
void inplaceRenumber(const labelUList &oldToNew, IntListType &input)
Inplace renumber the values within a list.
static label nProcs(label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run. ...
Definition: UPstream.H:1790
static void removeFiles(const polyMesh &)
Helper: remove all sets files from mesh instance.
label checkGeometry(const scalar maxRatio, const scalar tolerance, autoPtr< coordSetWriter > &setWriter, const scalar minQuality, const bool report) const
All geometric checks. Return number of failed checks.
bool set(const label i, bool val=true)
A bitSet::set() method for a list of bool.
Definition: List.H:468
label nCells() const noexcept
Number of mesh cells.
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Definition: PtrList.H:56
const wordList & names() const
Surface names, not region names.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
A List with indirect addressing. Like IndirectList but does not store addressing. ...
Definition: faMatrix.H:52
Nothing to be read.
Automatically write from objectRegistry::writeObject()
const std::string patch
OpenFOAM patch number as a std::string.
label globalRegion(const label surfI, const label regionI) const
From surface and region on surface to global region.
const entry * findEntry(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry (const access) with the given keyword.
Definition: dictionaryI.H:84
static const Enum< debugType > debugTypeNames
static labelList getNamedSurfaces(const PtrList< surfaceZonesInfo > &surfList)
Get indices of named surfaces (surfaces with faceZoneName)
messageStream Info
Information stream (stdout output on master, null elsewhere)
const PtrList< dictionary > & patchInfo() const
From global region number to patch type.
static bool master(label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1807
writeType
Enumeration for what to write. Used as a bit-pattern.
const boundBox & bounds() const noexcept
Return mesh bounding box.
Definition: polyMesh.H:619
tmp< pointField > allPoints(const Triangulation &t)
Extract all points in vertex-index order.
IOobject dictIO
faceZoneType
What to do with faceZone faces.
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
debugType
Enumeration for what to debug. Used as a bit-pattern.
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:76
entry * set(entry *entryPtr)
Assign a new entry, overwriting any existing entry.
Definition: dictionary.C:765
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
bool write() const
Write mesh and all data.
double elapsedCpuTime() const
Return CPU time [seconds] from the start.
Definition: cpuTimePosix.C:79
IOstreamOption::streamFormat writeFormat() const noexcept
Get write stream format.
Definition: TimeI.H:123
List< label > labelList
A List of labels.
Definition: List.H:61
auto & names
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:69
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
#define PrintMemoryIn(functionName)
Report memory high-water mark using Foam::error::Pout_mem_hwm() for functionName in file __FILE__ at ...
Definition: error.H:748
void setMinLevelFields(const shellSurfaces &shells)
Calculate minLevelFields according to both surface- and.
Foam::argList args(argc, argv)
void writeStats(const List< wordList > &, Ostream &) const
Write some stats.
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:489
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:188
Request registration (bool: true)
Output to string buffer, using a OSstream. Always UNCOMPRESSED.
Definition: StringStream.H:208
A primitive field of type <T> with automated input and output.
Regular expression.
Definition: keyType.H:83
void setSize(label n)
Alias for resize()
Definition: List.H:535
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
List< treeBoundBox > meshBb(1, treeBoundBox(coarseMesh.points()).extend(rndGen, 1e-3))
bool found(const word &optName) const
Return true if the named option is found.
Definition: argListI.H:171
const wordList surface
Standard surface field types (scalar, vector, tensor, etc)
static labelList removeEmptyPatches(fvMesh &, const bool validBoundary)
Remove zero sized patches. All but processor patches are.
Definition: fvMeshTools.C:442
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
Namespace for OpenFOAM.
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
A keyword and a list of tokens is an &#39;entry&#39;.
Definition: entry.H:63
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i), works like std::iota() but returning a...
static IOobject selectIO(const IOobject &io, const fileName &altFile, const word &ioName="")
Return the IOobject, but also consider an alternative file name.
Definition: IOobject.C:256
A HashTable to objects of type <T> with a label key.
const labelList & maxLevel() const
From global region number to refinement level.
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:217
label checkGeometry(const polyMesh &mesh, const bool allGeometry, autoPtr< surfaceWriter > &surfWriter, autoPtr< coordSetWriter > &setWriter)
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127
Starts timing CPU usage and return elapsed time from start.
Definition: cpuTimePosix.H:52