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