1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
28 Automatic split hex mesher. Refines and snaps to surface.
30 \*---------------------------------------------------------------------------*/
35 #include "autoRefineDriver.H"
36 #include "autoSnapDriver.H"
37 #include "autoLayerDriver.H"
38 #include "searchableSurfaces.H"
39 #include "refinementSurfaces.H"
40 #include "refinementFeatures.H"
41 #include "shellSurfaces.H"
42 #include "decompositionMethod.H"
43 #include "fvMeshDistribute.H"
44 #include "wallPolyPatch.H"
45 #include "refinementParameters.H"
46 #include "snapParameters.H"
47 #include "layerParameters.H"
52 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
54 // Check writing tolerance before doing any serious work
55 scalar getMergeDistance(const polyMesh& mesh, const scalar mergeTol)
57 const boundBox& meshBb = mesh.bounds();
58 scalar mergeDist = mergeTol * meshBb.mag();
61 << "Overall mesh bounding box : " << meshBb << nl
62 << "Relative tolerance : " << mergeTol << nl
63 << "Absolute matching distance : " << mergeDist << nl
66 // check writing tolerance
67 if (mesh.time().writeFormat() == IOstream::ASCII)
69 const scalar writeTol = std::pow
72 -scalar(IOstream::defaultPrecision())
75 if (mergeTol < writeTol)
77 FatalErrorIn("getMergeDistance(const polyMesh&, const dictionary&)")
78 << "Your current settings specify ASCII writing with "
79 << IOstream::defaultPrecision() << " digits precision." << nl
80 << "Your merging tolerance (" << mergeTol
81 << ") is finer than this." << nl
82 << "Change to binary writeFormat, "
83 << "or increase the writePrecision" << endl
84 << "or adjust the merge tolerance (mergeTol)."
93 // Write mesh and additional information
97 const meshRefinement& meshRefiner,
101 const fvMesh& mesh = meshRefiner.mesh();
103 meshRefiner.printMeshInfo(debug, msg);
104 Info<< "Writing mesh to time " << meshRefiner.timeName() << endl;
106 meshRefiner.write(meshRefinement::MESH|meshRefinement::SCALARLEVELS, "");
107 if (debug & meshRefinement::OBJINTERSECTIONS)
111 meshRefinement::OBJINTERSECTIONS,
112 mesh.time().path()/meshRefiner.timeName()
115 Info<< "Wrote mesh in = "
116 << mesh.time().cpuTimeIncrement() << " s." << endl;
121 int main(int argc, char *argv[])
123 # include "addOverwriteOption.H"
125 # include "setRootCase.H"
126 # include "createTime.H"
127 runTime.functionObjects().off();
128 # include "createMesh.H"
130 Info<< "Read mesh in = "
131 << runTime.cpuTimeIncrement() << " s" << endl;
133 const bool overwrite = args.optionFound("overwrite");
135 // Check patches and faceZones are synchronised
136 mesh.boundaryMesh().checkParallelSync(true);
137 meshRefinement::checkCoupledFaceZones(mesh);
140 // Read decomposePar dictionary
141 IOdictionary decomposeDict
148 IOobject::MUST_READ_IF_MODIFIED,
153 // Read meshing dictionary
154 IOdictionary meshDict
161 IOobject::MUST_READ_IF_MODIFIED,
166 // all surface geometry
167 const dictionary& geometryDict = meshDict.subDict("geometry");
169 // refinement parameters
170 const dictionary& refineDict = meshDict.subDict("castellatedMeshControls");
172 // mesh motion and mesh quality parameters
173 const dictionary& motionDict = meshDict.subDict("meshQualityControls");
175 // snap-to-surface parameters
176 const dictionary& snapDict = meshDict.subDict("snapControls");
178 // layer addition parameters
179 const dictionary& layerDict = meshDict.subDict("addLayersControls");
181 // absolute merge distance
182 const scalar mergeDist = getMergeDistance
185 readScalar(meshDict.lookup("mergeTolerance"))
192 const label debug = meshDict.lookupOrDefault<label>("debug", 0);
195 meshRefinement::debug = debug;
196 autoRefineDriver::debug = debug;
197 autoSnapDriver::debug = debug;
198 autoLayerDriver::debug = debug;
205 searchableSurfaces allGeometry
210 mesh.time().constant(), // instance
211 //mesh.time().findInstance("triSurface", word::null),// instance
212 "triSurface", // local
213 mesh.time(), // registry
221 // Read refinement surfaces
222 // ~~~~~~~~~~~~~~~~~~~~~~~~
224 Info<< "Reading refinement surfaces." << endl;
225 refinementSurfaces surfaces
228 refineDict.subDict("refinementSurfaces")
230 Info<< "Read refinement surfaces in = "
231 << mesh.time().cpuTimeIncrement() << " s" << nl << endl;
234 // Read refinement shells
235 // ~~~~~~~~~~~~~~~~~~~~~~
237 Info<< "Reading refinement shells." << endl;
241 refineDict.subDict("refinementRegions")
243 Info<< "Read refinement shells in = "
244 << mesh.time().cpuTimeIncrement() << " s" << nl << endl;
247 Info<< "Setting refinement level of surface to be consistent"
248 << " with shells." << endl;
249 surfaces.setMinLevelFields(shells);
250 Info<< "Checked shell refinement in = "
251 << mesh.time().cpuTimeIncrement() << " s" << nl << endl;
254 // Read feature meshes
255 // ~~~~~~~~~~~~~~~~~~~
257 Info<< "Reading features." << endl;
258 refinementFeatures features
261 refineDict.lookup("features")
263 Info<< "Read features in = "
264 << mesh.time().cpuTimeIncrement() << " s" << nl << endl;
272 << "Determining initial surface intersections" << nl
273 << "-----------------------------------------" << nl
276 // Main refinement engine
277 meshRefinement meshRefiner
280 mergeDist, // tolerance used in sorting coordinates
281 overwrite, // overwrite mesh files?
282 surfaces, // for surface intersection refinement
283 features, // for feature edges/point based refinement
284 shells // for volume (inside/outside) refinement
286 Info<< "Calculated surface intersections in = "
287 << mesh.time().cpuTimeIncrement() << " s" << nl << endl;
290 meshRefiner.printMeshInfo(debug, "Initial mesh");
294 debug & meshRefinement::OBJINTERSECTIONS,
295 mesh.time().path()/meshRefiner.timeName()
299 // Add all the surface regions as patches
300 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
302 labelList globalToPatch;
305 << "Adding patches for surface regions" << nl
306 << "----------------------------------" << nl
309 // From global region number to mesh patch.
310 globalToPatch.setSize(surfaces.nRegions(), -1);
312 Info<< "Patch\tType\tRegion" << nl
313 << "-----\t----\t------"
316 const labelList& surfaceGeometry = surfaces.surfaces();
317 const PtrList<dictionary>& surfacePatchInfo = surfaces.patchInfo();
319 forAll(surfaceGeometry, surfI)
321 label geomI = surfaceGeometry[surfI];
323 const wordList& regNames = allGeometry.regionNames()[geomI];
325 Info<< surfaces.names()[surfI] << ':' << nl << nl;
329 label globalRegionI = surfaces.globalRegion(surfI, i);
333 if (surfacePatchInfo.set(globalRegionI))
335 patchI = meshRefiner.addMeshedPatch
338 surfacePatchInfo[globalRegionI]
343 dictionary patchInfo;
344 patchInfo.set("type", wallPolyPatch::typeName);
346 patchI = meshRefiner.addMeshedPatch
353 Info<< patchI << '\t' << mesh.boundaryMesh()[patchI].type()
354 << '\t' << regNames[i] << nl;
356 globalToPatch[globalRegionI] = patchI;
361 Info<< "Added patches in = "
362 << mesh.time().cpuTimeIncrement() << " s" << nl << endl;
370 autoPtr<decompositionMethod> decomposerPtr
372 decompositionMethod::New
377 decompositionMethod& decomposer = decomposerPtr();
379 if (Pstream::parRun() && !decomposer.parallelAware())
381 FatalErrorIn(args.executable())
382 << "You have selected decomposition method "
383 << decomposer.typeName
384 << " which is not parallel aware." << endl
385 << "Please select one that is (hierarchical, ptscotch)"
389 // Mesh distribution engine (uses tolerance to reconstruct meshes)
390 fvMeshDistribute distributor(mesh, mergeDist);
396 // Now do the real work -refinement -snapping -layers
397 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
399 const Switch wantRefine(meshDict.lookup("castellatedMesh"));
400 const Switch wantSnap(meshDict.lookup("snap"));
401 const Switch wantLayers(meshDict.lookup("addLayers"));
407 autoRefineDriver refineDriver
415 // Refinement parameters
416 refinementParameters refineParams(refineDict);
420 const_cast<Time&>(mesh.time())++;
423 refineDriver.doRefine(refineDict, refineParams, wantSnap, motionDict);
432 Info<< "Mesh refined in = "
433 << timer.cpuTimeIncrement() << " s." << endl;
440 autoSnapDriver snapDriver
447 snapParameters snapParams(snapDict);
448 // Temporary hack to get access to resolveFeatureAngle
451 refinementParameters refineParams(refineDict);
452 curvature = refineParams.curvature();
457 const_cast<Time&>(mesh.time())++;
460 snapDriver.doSnap(snapDict, motionDict, curvature, snapParams);
469 Info<< "Mesh snapped in = "
470 << timer.cpuTimeIncrement() << " s." << endl;
477 autoLayerDriver layerDriver(meshRefiner, globalToPatch);
479 // Layer addition parameters
480 layerParameters layerParams(layerDict, mesh.boundaryMesh());
482 //!!! Temporary hack to get access to maxLocalCells
485 refinementParameters refineParams(refineDict);
487 preBalance = returnReduce
489 (mesh.nCells() >= refineParams.maxLocalCells()),
497 const_cast<Time&>(mesh.time())++;
517 Info<< "Layers added in = "
518 << timer.cpuTimeIncrement() << " s." << endl;
522 Info<< "Finished meshing in = "
523 << runTime.elapsedCpuTime() << " s." << endl;
525 Info<< "End\n" << endl;
531 // ************************************************************************* //