00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "autoHexMeshDriver.H"
00027 #include <finiteVolume/fvMesh.H>
00028 #include <OpenFOAM/Time.H>
00029 #include <OpenFOAM/boundBox.H>
00030 #include <OpenFOAM/wallPolyPatch.H>
00031 #include <meshTools/cellSet.H>
00032 #include <OpenFOAM/syncTools.H>
00033 #include <autoMesh/refinementParameters.H>
00034 #include <autoMesh/snapParameters.H>
00035 #include <autoMesh/layerParameters.H>
00036 #include "autoRefineDriver.H"
00037 #include "autoSnapDriver.H"
00038 #include "autoLayerDriver.H"
00039 #include <meshTools/triSurfaceMesh.H>
00040
00041
00042
00043 namespace Foam
00044 {
00045 defineTypeNameAndDebug(autoHexMeshDriver, 0);
00046 }
00047
00048
00049
00050
00051
00052 Foam::scalar Foam::autoHexMeshDriver::getMergeDistance(const scalar mergeTol)
00053 const
00054 {
00055 const boundBox& meshBb = mesh_.bounds();
00056 scalar mergeDist = mergeTol * meshBb.mag();
00057 scalar writeTol = std::pow
00058 (
00059 scalar(10.0),
00060 -scalar(IOstream::defaultPrecision())
00061 );
00062
00063 Info<< nl
00064 << "Overall mesh bounding box : " << meshBb << nl
00065 << "Relative tolerance : " << mergeTol << nl
00066 << "Absolute matching distance : " << mergeDist << nl
00067 << endl;
00068
00069 if (mesh_.time().writeFormat() == IOstream::ASCII && mergeTol < writeTol)
00070 {
00071 FatalErrorIn("autoHexMeshDriver::getMergeDistance(const scalar) const")
00072 << "Your current settings specify ASCII writing with "
00073 << IOstream::defaultPrecision() << " digits precision." << endl
00074 << "Your merging tolerance (" << mergeTol << ") is finer than this."
00075 << endl
00076 << "Please change your writeFormat to binary"
00077 << " or increase the writePrecision" << endl
00078 << "or adjust the merge tolerance (-mergeTol)."
00079 << exit(FatalError);
00080 }
00081
00082 return mergeDist;
00083 }
00084
00085
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 Foam::autoHexMeshDriver::autoHexMeshDriver
00145 (
00146 fvMesh& mesh,
00147 const bool overwrite,
00148 const dictionary& dict,
00149 const dictionary& decomposeDict
00150 )
00151 :
00152 mesh_(mesh),
00153 dict_(dict),
00154 debug_(readLabel(dict_.lookup("debug"))),
00155 mergeDist_(getMergeDistance(readScalar(dict_.lookup("mergeTolerance"))))
00156 {
00157 if (debug_ > 0)
00158 {
00159 meshRefinement::debug = debug_;
00160 autoHexMeshDriver::debug = debug_;
00161 autoRefineDriver::debug = debug;
00162 autoSnapDriver::debug = debug;
00163 autoLayerDriver::debug = debug;
00164 }
00165
00166 refinementParameters refineParams(dict, 1);
00167
00168 Info<< "Overall cell limit : "
00169 << refineParams.maxGlobalCells() << endl;
00170 Info<< "Per processor cell limit : "
00171 << refineParams.maxLocalCells() << endl;
00172 Info<< "Minimum number of cells to refine : "
00173 << refineParams.minRefineCells() << endl;
00174 Info<< "Curvature : "
00175 << refineParams.curvature() << nl << endl;
00176 Info<< "Layers between different refinement levels : "
00177 << refineParams.nBufferLayers() << endl;
00178
00179 PtrList<dictionary> shellDicts(dict_.lookup("refinementShells"));
00180
00181 PtrList<dictionary> surfaceDicts(dict_.lookup("surfaces"));
00182
00183
00184
00185
00186
00187 {
00188 Info<< "Reading all geometry." << endl;
00189
00190
00191 dictionary geometryDict;
00192
00193 forAll(shellDicts, shellI)
00194 {
00195 dictionary shellDict = shellDicts[shellI];
00196 const word name(shellDict.lookup("name"));
00197 shellDict.remove("name");
00198 shellDict.remove("level");
00199 shellDict.remove("refineInside");
00200 geometryDict.add(name, shellDict);
00201 }
00202
00203 forAll(surfaceDicts, surfI)
00204 {
00205 dictionary surfDict = surfaceDicts[surfI];
00206 const word name(string::validate<word>(surfDict.lookup("file")));
00207 surfDict.remove("file");
00208 surfDict.remove("regions");
00209 if (!surfDict.found("name"))
00210 {
00211 surfDict.add("name", name);
00212 }
00213 surfDict.add("type", triSurfaceMesh::typeName);
00214 geometryDict.add(name, surfDict);
00215 }
00216
00217 allGeometryPtr_.reset
00218 (
00219 new searchableSurfaces
00220 (
00221 IOobject
00222 (
00223 "abc",
00224
00225
00226 mesh_.time().constant(),
00227 "triSurface",
00228 mesh_.time(),
00229 IOobject::MUST_READ,
00230 IOobject::NO_WRITE
00231 ),
00232 geometryDict
00233 )
00234 );
00235
00236 Info<< "Read geometry in = "
00237 << mesh_.time().cpuTimeIncrement() << " s" << endl;
00238 }
00239
00240
00241
00242
00243
00244 {
00245 Info<< "Reading surfaces and constructing search trees." << endl;
00246
00247 surfacesPtr_.reset
00248 (
00249 new refinementSurfaces
00250 (
00251 allGeometryPtr_(),
00252 surfaceDicts
00253 )
00254 );
00255 Info<< "Read surfaces in = "
00256 << mesh_.time().cpuTimeIncrement() << " s" << endl;
00257 }
00258
00259
00260
00261
00262 {
00263 Info<< "Reading refinement shells." << endl;
00264 shellsPtr_.reset
00265 (
00266 new shellSurfaces
00267 (
00268 allGeometryPtr_(),
00269 shellDicts
00270 )
00271 );
00272 Info<< "Read refinement shells in = "
00273 << mesh_.time().cpuTimeIncrement() << " s" << endl;
00274
00276
00277
00278
00279
00280
00281
00282 Info<< "Setting refinement level of surface to be consistent"
00283 << " with shells." << endl;
00284 surfacesPtr_().setMinLevelFields(shells());
00285 Info<< "Checked shell refinement in = "
00286 << mesh_.time().cpuTimeIncrement() << " s" << endl;
00287 }
00288
00289
00290
00291 meshRefinement::checkCoupledFaceZones(mesh_);
00292
00293
00294
00295
00296
00297 {
00298 Info<< nl
00299 << "Determining initial surface intersections" << nl
00300 << "-----------------------------------------" << nl
00301 << endl;
00302
00303
00304 meshRefinerPtr_.reset
00305 (
00306 new meshRefinement
00307 (
00308 mesh,
00309 mergeDist_,
00310 overwrite,
00311 surfaces(),
00312 shells()
00313 )
00314 );
00315 Info<< "Calculated surface intersections in = "
00316 << mesh_.time().cpuTimeIncrement() << " s" << endl;
00317
00318
00319 meshRefinerPtr_().printMeshInfo(debug_, "Initial mesh");
00320
00321 meshRefinerPtr_().write
00322 (
00323 debug_&meshRefinement::OBJINTERSECTIONS,
00324 mesh_.time().path()/meshRefinerPtr_().timeName()
00325 );
00326 }
00327
00328
00329
00330
00331
00332 {
00333 Info<< nl
00334 << "Adding patches for surface regions" << nl
00335 << "----------------------------------" << nl
00336 << endl;
00337
00338
00339 globalToPatch_.setSize(surfaces().nRegions(), -1);
00340
00341 Info<< "Patch\tRegion" << nl
00342 << "-----\t------"
00343 << endl;
00344
00345 const labelList& surfaceGeometry = surfaces().surfaces();
00346 forAll(surfaceGeometry, surfI)
00347 {
00348 label geomI = surfaceGeometry[surfI];
00349
00350 const wordList& regNames = allGeometryPtr_().regionNames()[geomI];
00351
00352 Info<< surfaces().names()[surfI] << ':' << nl << nl;
00353
00354 forAll(regNames, i)
00355 {
00356 label patchI = meshRefinerPtr_().addMeshedPatch
00357 (
00358 regNames[i],
00359 wallPolyPatch::typeName
00360 );
00361
00362 Info<< patchI << '\t' << regNames[i] << nl;
00363
00364 globalToPatch_[surfaces().globalRegion(surfI, i)] = patchI;
00365 }
00366
00367 Info<< nl;
00368 }
00369 Info<< "Added patches in = "
00370 << mesh_.time().cpuTimeIncrement() << " s" << nl << endl;
00371 }
00372
00373
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416 {
00417
00418 decomposerPtr_ = decompositionMethod::New
00419 (
00420 decomposeDict,
00421 mesh_
00422 );
00423 decompositionMethod& decomposer = decomposerPtr_();
00424
00425
00426 if (Pstream::parRun() && !decomposer.parallelAware())
00427 {
00428 FatalErrorIn("autoHexMeshDriver::autoHexMeshDriver"
00429 "(const IOobject&, fvMesh&)")
00430 << "You have selected decomposition method "
00431 << decomposer.typeName
00432 << " which is not parallel aware." << endl
00433 << "Please select one that is (parMetis, hierarchical)"
00434 << exit(FatalError);
00435 }
00436
00437
00438 distributorPtr_.reset(new fvMeshDistribute(mesh_, mergeDist_));
00439 }
00440 }
00441
00442
00443
00444
00445 void Foam::autoHexMeshDriver::writeMesh(const string& msg) const
00446 {
00447 const meshRefinement& meshRefiner = meshRefinerPtr_();
00448
00449 meshRefiner.printMeshInfo(debug_, msg);
00450 Info<< "Writing mesh to time " << meshRefiner.timeName() << endl;
00451
00452 meshRefiner.write(meshRefinement::MESH|meshRefinement::SCALARLEVELS, "");
00453 if (debug_ & meshRefinement::OBJINTERSECTIONS)
00454 {
00455 meshRefiner.write
00456 (
00457 meshRefinement::OBJINTERSECTIONS,
00458 mesh_.time().path()/meshRefiner.timeName()
00459 );
00460 }
00461 Info<< "Written mesh in = "
00462 << mesh_.time().cpuTimeIncrement() << " s." << endl;
00463 }
00464
00465
00466 void Foam::autoHexMeshDriver::doMesh()
00467 {
00468 Switch wantRefine(dict_.lookup("doRefine"));
00469 Switch wantSnap(dict_.lookup("doSnap"));
00470 Switch wantLayers(dict_.lookup("doLayers"));
00471
00472 Info<< "Do refinement : " << wantRefine << nl
00473 << "Do snapping : " << wantSnap << nl
00474 << "Do layers : " << wantLayers << nl
00475 << endl;
00476
00477 if (wantRefine)
00478 {
00479 const dictionary& motionDict = dict_.subDict("motionDict");
00480
00481 autoRefineDriver refineDriver
00482 (
00483 meshRefinerPtr_(),
00484 decomposerPtr_(),
00485 distributorPtr_(),
00486 globalToPatch_
00487 );
00488
00489
00490 refinementParameters refineParams(dict_, 1);
00491
00492 refineDriver.doRefine(dict_, refineParams, wantSnap, motionDict);
00493
00494
00495 writeMesh("Refined mesh");
00496 }
00497
00498 if (wantSnap)
00499 {
00500 const dictionary& snapDict = dict_.subDict("snapDict");
00501 const dictionary& motionDict = dict_.subDict("motionDict");
00502
00503 autoSnapDriver snapDriver
00504 (
00505 meshRefinerPtr_(),
00506 globalToPatch_
00507 );
00508
00509
00510 snapParameters snapParams(snapDict, 1);
00511
00512 snapDriver.doSnap(snapDict, motionDict, snapParams);
00513
00514
00515 writeMesh("Snapped mesh");
00516 }
00517
00518 if (wantLayers)
00519 {
00520 const dictionary& motionDict = dict_.subDict("motionDict");
00521 const dictionary& shrinkDict = dict_.subDict("shrinkDict");
00522 PtrList<dictionary> surfaceDicts(dict_.lookup("surfaces"));
00523
00524 autoLayerDriver layerDriver(meshRefinerPtr_());
00525
00526
00527 layerParameters layerParams
00528 (
00529 surfaceDicts,
00530 surfacesPtr_(),
00531 globalToPatch_,
00532 shrinkDict,
00533 mesh_.boundaryMesh()
00534 );
00535
00536 layerDriver.doLayers
00537 (
00538 shrinkDict,
00539 motionDict,
00540 layerParams,
00541 true,
00542 decomposerPtr_(),
00543 distributorPtr_()
00544 );
00545
00546
00547 writeMesh("Layer mesh");
00548 }
00549 }
00550
00551
00552