FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

autoHexMeshDriver.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
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 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00042 
00043 namespace Foam
00044 {
00045     defineTypeNameAndDebug(autoHexMeshDriver, 0);
00046 }
00047 
00048 
00049 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00050 
00051 // Check writing tolerance before doing any serious work
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 //void Foam::autoHexMeshDriver::orientOutside
00088 //(
00089 //    PtrList<searchableSurface>& shells
00090 //)
00091 //{
00092 //    // Determine outside point.
00093 //    boundBox overallBb = boundBox::invertedBox;
00094 //
00095 //    bool hasSurface = false;
00096 //
00097 //    forAll(shells, shellI)
00098 //    {
00099 //        if (isA<triSurfaceMesh>(shells[shellI]))
00100 //        {
00101 //            const triSurfaceMesh& shell =
00102 //                refCast<const triSurfaceMesh>(shells[shellI]);
00103 //
00104 //            hasSurface = true;
00105 //
00106 //            boundBox shellBb(shell.localPoints(), false);
00107 //
00108 //            overallBb.min() = min(overallBb.min(), shellBb.min());
00109 //            overallBb.max() = max(overallBb.max(), shellBb.max());
00110 //        }
00111 //    }
00112 //
00113 //    if (hasSurface)
00114 //    {
00115 //        const point outsidePt = 2 * overallBb.span();
00116 //
00117 //        //Info<< "Using point " << outsidePt << " to orient shells" << endl;
00118 //
00119 //        forAll(shells, shellI)
00120 //        {
00121 //            if (isA<triSurfaceMesh>(shells[shellI]))
00122 //            {
00123 //                triSurfaceMesh& shell =
00124 //                  refCast<triSurfaceMesh>(shells[shellI]);
00125 //
00126 //                if (!refinementSurfaces::isSurfaceClosed(shell))
00127 //                {
00128 //                    FatalErrorIn("orientOutside(PtrList<searchableSurface>&)")
00129 //                        << "Refinement shell "
00130 //                        << shell.searchableSurface::name()
00131 //                        << " is not closed." << exit(FatalError);
00132 //                }
00133 //
00134 //                refinementSurfaces::orientSurface(outsidePt, shell);
00135 //            }
00136 //        }
00137 //    }
00138 //}
00139 
00140 
00141 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00142 
00143 // Construct from components
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     // Read geometry
00185     // ~~~~~~~~~~~~~
00186 
00187     {
00188         Info<< "Reading all geometry." << endl;
00189 
00190         // Construct dictionary with all shells and all refinement surfaces
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",                                      // dummy name
00224                     //mesh_.time().findInstance("triSurface", word::null),
00225                                                                 // instance
00226                     mesh_.time().constant(),                    // instance
00227                     "triSurface",                               // local
00228                     mesh_.time(),                               // registry
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     // Read refinement surfaces
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     // Read refinement shells
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         //Info<< "Orienting triSurface shells so point far away is outside."
00277         //    << endl;
00278         //orientOutside(shells_);
00279         //Info<< "Oriented shells in = "
00280         //    << mesh_.time().cpuTimeIncrement() << " s" << endl;
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     // Check faceZones are synchronised
00291     meshRefinement::checkCoupledFaceZones(mesh_);
00292 
00293 
00294     // Refinement engine
00295     // ~~~~~~~~~~~~~~~~~
00296 
00297     {
00298         Info<< nl
00299             << "Determining initial surface intersections" << nl
00300             << "-----------------------------------------" << nl
00301             << endl;
00302 
00303         // Main refinement engine
00304         meshRefinerPtr_.reset
00305         (
00306             new meshRefinement
00307             (
00308                 mesh,
00309                 mergeDist_,         // tolerance used in sorting coordinates
00310                 overwrite,
00311                 surfaces(),
00312                 shells()
00313             )
00314         );
00315         Info<< "Calculated surface intersections in = "
00316             << mesh_.time().cpuTimeIncrement() << " s" << endl;
00317 
00318         // Some stats
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     // Add all the surface regions as patches
00330     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00331 
00332     {
00333         Info<< nl
00334             << "Adding patches for surface regions" << nl
00335             << "----------------------------------" << nl
00336             << endl;
00337 
00338         // From global region number to mesh patch.
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     //labelList namedSurfaces(surfaces().getNamedSurfaces());
00380     //if (namedSurfaces.size())
00381     //{
00382     //    Info<< nl
00383     //        << "Introducing cyclics for faceZones" << nl
00384     //        << "---------------------------------" << nl
00385     //        << endl;
00386     //
00387     //    // From surface to cyclic patch
00388     //    surfaceToCyclicPatch_.setSize(surfaces().size(), -1);
00389     //
00390     //    Info<< "Patch\tZone" << nl
00391     //        << "----\t-----"
00392     //        << endl;
00393     //
00394     //    forAll(namedSurfaces, i)
00395     //    {
00396     //        label surfI = namedSurfaces[i];
00397     //
00398     //        surfaceToCyclicPatch_[surfI] = meshRefinement::addPatch
00399     //        (
00400     //            mesh,
00401     //            surfaces().faceZoneNames()[surfI],
00402     //            cyclicPolyPatch::typeName
00403     //        );
00404     //
00405     //        Info<< surfaceToCyclicPatch_[surfI] << '\t'
00406     //            << surfaces().faceZoneNames()[surfI] << nl << endl;
00407     //    }
00408     //    Info<< "Added cyclic patches in = "
00409     //        << mesh_.time().cpuTimeIncrement() << " s" << endl;
00410     //}
00411 
00412 
00413     // Parallel
00414     // ~~~~~~~~
00415 
00416     {
00417         // Decomposition
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         // Mesh distribution engine (uses tolerance to reconstruct meshes)
00438         distributorPtr_.reset(new fvMeshDistribute(mesh_, mergeDist_));
00439     }
00440 }
00441 
00442 
00443 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
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         // Get all the refinement specific params
00490         refinementParameters refineParams(dict_, 1);
00491 
00492         refineDriver.doRefine(dict_, refineParams, wantSnap, motionDict);
00493 
00494         // Write mesh
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         // Get all the snapping specific params
00510         snapParameters snapParams(snapDict, 1);
00511 
00512         snapDriver.doSnap(snapDict, motionDict, snapParams);
00513 
00514         // Write mesh.
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         // Get all the layer specific params
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,                   // pre-balance
00542             decomposerPtr_(),
00543             distributorPtr_()
00544         );
00545 
00546         // Write mesh.
00547         writeMesh("Layer mesh");
00548     }
00549 }
00550 
00551 
00552 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines