Skip to content
Snippets Groups Projects
tetMeshGenerator.C 10.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • franjo's avatar
    franjo committed
    /*---------------------------------------------------------------------------*\
      =========                 |
    
    Tomislav Lugaric's avatar
    Tomislav Lugaric committed
      \\      /  F ield         | cfMesh: A library for mesh generation
    
    franjo's avatar
    franjo committed
       \\    /   O peration     |
    
    Tomislav Lugaric's avatar
    Tomislav Lugaric committed
        \\  /    A nd           | Author: Franjo Juretic (franjo.juretic@c-fields.com)
         \\/     M anipulation  | Copyright (C) Creative Fields, Ltd.
    
    franjo's avatar
    franjo committed
    -------------------------------------------------------------------------------
    License
    
    Tomislav Lugaric's avatar
    Tomislav Lugaric committed
        This file is part of cfMesh.
    
    franjo's avatar
    franjo committed
    
    
    Tomislav Lugaric's avatar
    Tomislav Lugaric committed
        cfMesh is free software; you can redistribute it and/or modify it
    
    franjo's avatar
    franjo committed
        under the terms of the GNU General Public License as published by the
    
    Tomislav Lugaric's avatar
    Tomislav Lugaric committed
        Free Software Foundation; either version 3 of the License, or (at your
    
    franjo's avatar
    franjo committed
        option) any later version.
    
    
    Tomislav Lugaric's avatar
    Tomislav Lugaric committed
        cfMesh is distributed in the hope that it will be useful, but WITHOUT
    
    franjo's avatar
    franjo committed
        ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
        FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        for more details.
    
        You should have received a copy of the GNU General Public License
    
    Tomislav Lugaric's avatar
    Tomislav Lugaric committed
        along with cfMesh.  If not, see <http://www.gnu.org/licenses/>.
    
    franjo's avatar
    franjo committed
    
    Description
    
    \*---------------------------------------------------------------------------*/
    
    #include "tetMeshGenerator.H"
    #include "triSurf.H"
    #include "demandDrivenData.H"
    #include "meshOctreeCreator.H"
    #include "tetMeshExtractorOctree.H"
    #include "meshSurfaceEngine.H"
    #include "meshSurfaceMapper.H"
    
    #include "edgeExtractor.H"
    
    franjo's avatar
    franjo committed
    #include "meshSurfaceEdgeExtractorNonTopo.H"
    #include "surfaceMorpherCells.H"
    #include "meshOptimizer.H"
    #include "meshSurfaceOptimizer.H"
    #include "topologicalCleaner.H"
    #include "boundaryLayers.H"
    #include "renameBoundaryPatches.H"
    #include "checkMeshDict.H"
    
    #include "triSurfacePatchManipulator.H"
    
    #include "refineBoundaryLayers.H"
    
    Franjo's avatar
    Franjo committed
    #include "triSurfaceMetaData.H"
    
    #include "polyMeshGenGeometryModification.H"
    #include "surfaceMeshGeometryModification.H"
    
    franjo's avatar
    franjo committed
    
    //#define DEBUG
    
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    
    namespace Foam
    {
    
    // * * * * * * * * * * * * Private member functions  * * * * * * * * * * * * //
    
    void tetMeshGenerator::createTetMesh()
    {
        //- create tet Mesh from octree and Delaunay tets
    
        tetMeshExtractorOctree tme(*octreePtr_, meshDict_, mesh_);
    
    franjo's avatar
    franjo committed
    
        tme.createMesh();
    }
    
    void tetMeshGenerator::surfacePreparation()
    {
        //- removes unnecessary cells and morph the boundary
        //- such that there is only one boundary face per cell
        //- It also checks topology of cells after morphing is performed
        do
        {
    
            surfaceMorpherCells* cmPtr = new surfaceMorpherCells(mesh_);
    
    franjo's avatar
    franjo committed
            cmPtr->morphMesh();
    
            deleteDemandDrivenData(cmPtr);
    
    franjo's avatar
    franjo committed
        }
    
        while( topologicalCleaner(mesh_).cleanTopology() );
    
    franjo's avatar
    franjo committed
    }
    
    void tetMeshGenerator::mapMeshToSurface()
    {
        //- calculate mesh surface
    
        meshSurfaceEngine* msePtr = new meshSurfaceEngine(mesh_);
    
    franjo's avatar
    franjo committed
    
        //- map mesh surface on the geometry surface
    
        meshSurfaceMapper(*msePtr, *octreePtr_).mapVerticesOntoSurface();
    
    franjo's avatar
    franjo committed
        //- untangle surface faces
    
        meshSurfaceOptimizer(*msePtr, *octreePtr_).untangleSurface();
    
    franjo's avatar
    franjo committed
    
    
        deleteDemandDrivenData(msePtr);
    
    franjo's avatar
    franjo committed
    }
    
    
    void tetMeshGenerator::extractPatches()
    {
        edgeExtractor extractor(mesh_, *octreePtr_);
    
        Info << "Extracting edges" << endl;
        extractor.extractEdges();
    
        extractor.updateMeshPatches();
    }
    
    
    franjo's avatar
    franjo committed
    void tetMeshGenerator::mapEdgesAndCorners()
    {
    
        meshSurfaceEdgeExtractorNonTopo(mesh_, *octreePtr_);
    
    franjo's avatar
    franjo committed
    }
    
    void tetMeshGenerator::optimiseMeshSurface()
    {
    
        meshSurfaceEngine mse(mesh_);
        meshSurfaceOptimizer(mse, *octreePtr_).optimizeSurface();
    
    franjo's avatar
    franjo committed
    }
    
    
    void tetMeshGenerator::generateBoundaryLayers()
    
    franjo's avatar
    franjo committed
    {
    
        if( meshDict_.found("boundaryLayers") )
    
    franjo's avatar
    franjo committed
        {
    
            boundaryLayers bl(mesh_);
    
            const dictionary& bndLayers = meshDict_.subDict("boundaryLayers");
    
            if( bndLayers.found("nLayers") )
    
                const label nLayers = readLabel(bndLayers.lookup("nLayers"));
    
                if( nLayers > 0 )
                    bl.addLayerForAllPatches();
    
            else if( bndLayers.found("patchBoundaryLayers") )
    
                const dictionary& patchLayers =
                    bndLayers.subDict("patchBoundaryLayers");
                const wordList createLayers = patchLayers.toc();
    
    franjo's avatar
    franjo committed
    
    
                forAll(createLayers, patchI)
                    bl.addLayerForPatch(createLayers[patchI]);
            }
    
    franjo's avatar
    franjo committed
        }
    }
    
    void tetMeshGenerator::optimiseFinalMesh()
    {
        //- final optimisation
    
        bool enforceConstraints(false);
        if( meshDict_.found("enforceGeometryConstraints") )
        {
            enforceConstraints =
                readBool(meshDict_.lookup("enforceGeometryConstraints"));
        }
    
    
        meshOptimizer optimizer(mesh_);
    
        if( enforceConstraints )
            optimizer.enforceConstraints();
    
    franjo's avatar
    franjo committed
    
    
        optimizer.optimizeSurface(*octreePtr_);
    
    franjo's avatar
    franjo committed
    
    
        optimizer.optimizeMeshFV();
        optimizer.optimizeLowQualityFaces();
    
        optimizer.optimizeBoundaryLayer(false);
    
        optimizer.untangleMeshFV();
    
        deleteDemandDrivenData(octreePtr_);
    
    franjo's avatar
    franjo committed
    
    
        mesh_.clearAddressingData();
    
    
        if( modSurfacePtr_ )
        {
            polyMeshGenGeometryModification meshMod(mesh_, meshDict_);
    
            //- revert the mesh into the original space
            meshMod.revertGeometryModification();
    
            //- delete modified surface mesh
            deleteDemandDrivenData(modSurfacePtr_);
        }
    
    franjo's avatar
    franjo committed
    }
    
    
    void tetMeshGenerator::projectSurfaceAfterBackScaling()
    {
        if( !meshDict_.found("anisotropicSources") )
            return;
    
        deleteDemandDrivenData(octreePtr_);
        octreePtr_ = new meshOctree(*surfacePtr_);
    
        meshOctreeCreator
        (
            *octreePtr_,
            meshDict_
        ).createOctreeWithRefinedBoundary(20, 30);
    
        //- calculate mesh surface
        meshSurfaceEngine mse(mesh_);
    
        //- pre-map mesh surface
        meshSurfaceMapper mapper(mse, *octreePtr_);
    
        //- map mesh surface on the geometry surface
        mapper.mapVerticesOntoSurface();
    
        optimiseFinalMesh();
    }
    
    
    void tetMeshGenerator::refBoundaryLayers()
    {
        if( meshDict_.isDict("boundaryLayers") )
        {
            refineBoundaryLayers refLayers(mesh_);
    
            refineBoundaryLayers::readSettings(meshDict_, refLayers);
    
            refLayers.refineLayers();
    
    
            labelLongList pointsInLayer;
            refLayers.pointsInBndLayer(pointsInLayer);
    
            meshOptimizer opt(mesh_);
            opt.lockPoints(pointsInLayer);
            opt.untangleBoundaryLayer();
    
    franjo's avatar
    franjo committed
    void tetMeshGenerator::replaceBoundaries()
    {
    
        renameBoundaryPatches rbp(mesh_, meshDict_);
    
    franjo's avatar
    franjo committed
    }
    
    void tetMeshGenerator::renumberMesh()
    {
    
        polyMeshGenModifier(mesh_).renumberMesh();
    
    franjo's avatar
    franjo committed
    }
    
    void tetMeshGenerator::generateMesh()
    {
    
            if( controller_.runCurrentStep("templateGeneration") )
            {
                createTetMesh();
            }
    
    franjo's avatar
    franjo committed
    
    
            if( controller_.runCurrentStep("surfaceTopology") )
            {
                surfacePreparation();
            }
    
    franjo's avatar
    franjo committed
    
    
            if( controller_.runCurrentStep("surfaceProjection") )
            {
                mapMeshToSurface();
            }
    
    franjo's avatar
    franjo committed
    
    
            if( controller_.runCurrentStep("patchAssignment") )
            {
                extractPatches();
            }
    
    franjo's avatar
    franjo committed
    
    
            if( controller_.runCurrentStep("edgeExtraction") )
    
            {
                mapEdgesAndCorners();
    
    franjo's avatar
    franjo committed
    
    
                optimiseMeshSurface();
    
    franjo's avatar
    franjo committed
    
    
            if( controller_.runCurrentStep("boundaryLayerGeneration") )
            {
    
                generateBoundaryLayers();
            }
    
    franjo's avatar
    franjo committed
    
    
            if( controller_.runCurrentStep("meshOptimisation") )
            {
                optimiseFinalMesh();
    
    
                projectSurfaceAfterBackScaling();
    
            }
    
            if( controller_.runCurrentStep("boundaryLayerRefinement") )
            {
                refBoundaryLayers();
            }
    
    franjo's avatar
    franjo committed
    
    
    
            controller_.workflowCompleted();
    
    Franjo's avatar
    Franjo committed
        catch(const std::string& message)
        {
            Info << message << endl;
        }
    
        catch(...)
        {
            WarningIn
            (
                "void tetMeshGenerator::generateMesh()"
            ) << "Meshing process terminated!" << endl;
        }
    
    franjo's avatar
    franjo committed
    }
    
    // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
    
    // Construct from Time
    
    tetMeshGenerator::tetMeshGenerator(const Time& time)
    
    :
        runTime_(time),
        surfacePtr_(NULL),
    
    franjo's avatar
    franjo committed
            (
    
                "meshDict",
                runTime_.system(),
                runTime_,
                IOobject::MUST_READ,
                IOobject::NO_WRITE
            )
        ),
        octreePtr_(NULL),
    
        mesh_(time),
        controller_(mesh_)
    
    franjo's avatar
    franjo committed
    {
    
    franjo's avatar
    franjo committed
        {
    
            checkMeshDict cmd(meshDict_);
    
    franjo's avatar
    franjo committed
        }
    
    
        const fileName surfaceFile = meshDict_.lookup("surfaceFile");
    
    franjo's avatar
    franjo committed
    
    
        surfacePtr_ = new triSurf(runTime_.path()/surfaceFile);
    
    franjo's avatar
    franjo committed
    
    
    Franjo's avatar
    Franjo committed
        if( true )
        {
            //- save meta data with the mesh (surface mesh + its topology info)
            triSurfaceMetaData sMetaData(*surfacePtr_);
            const dictionary& surfMetaDict = sMetaData.metaData();
    
    
            mesh_.metaData().add("surfaceFile", surfaceFile, true);
            mesh_.metaData().add("surfaceMeta", surfMetaDict, true);
    
        if( surfacePtr_->featureEdges().size() != 0 )
        {
            //- create surface patches based on the feature edges
            //- and update the meshDict based on the given data
            triSurfacePatchManipulator manipulator(*surfacePtr_);
    
            const triSurf* surfaceWithPatches =
                manipulator.surfaceWithPatches(&meshDict_);
    
            //- delete the old surface and assign the new one
            deleteDemandDrivenData(surfacePtr_);
            surfacePtr_ = surfaceWithPatches;
        }
    
    franjo's avatar
    franjo committed
    
    
        if( meshDict_.found("anisotropicSources") )
        {
            surfaceMeshGeometryModification surfMod(*surfacePtr_, meshDict_);
    
            modSurfacePtr_ = surfMod.modifyGeometry();
    
            octreePtr_ = new meshOctree(*modSurfacePtr_);
        }
        else
        {
            octreePtr_ = new meshOctree(*surfacePtr_);
        }
    
    franjo's avatar
    franjo committed
    
    
        meshOctreeCreator(*octreePtr_, meshDict_).createOctreeBoxes();
    
    franjo's avatar
    franjo committed
    
        generateMesh();
    }
    
    // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
    
    tetMeshGenerator::~tetMeshGenerator()
    {
    
        deleteDemandDrivenData(surfacePtr_);
        deleteDemandDrivenData(octreePtr_);
    
        deleteDemandDrivenData(modSurfacePtr_);
    
    franjo's avatar
    franjo committed
    }
    
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    
    void tetMeshGenerator::writeMesh() const
    {
        mesh_.write();
    }
    
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    
    } // End namespace Foam
    
    // ************************************************************************* //