Newer
Older
/*---------------------------------------------------------------------------*\
========= |
\\ / O peration |
\\ / A nd | www.cfmesh.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2014-2017 Creative Fields, Ltd.
-------------------------------------------------------------------------------
Author
Franjo Juretic (franjo.juretic@c-fields.com)
License
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
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
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "cartesian2DMeshGenerator.H"
#include "polyMeshGen2DEngine.H"
#include "triSurf.H"
#include "triSurfacePatchManipulator.H"
#include "triSurfaceCleanupDuplicateTriangles.H"
#include "demandDrivenData.H"
#include "meshOctreeCreator.H"
#include "cartesianMeshExtractor.H"
#include "meshSurfaceEngine.H"
#include "meshSurfaceMapper2D.H"
#include "meshSurfaceEdgeExtractor2D.H"
#include "meshSurfaceOptimizer.H"
#include "topologicalCleaner.H"
#include "boundaryLayers.H"
#include "refineBoundaryLayers.H"
#include "renameBoundaryPatches.H"
#include "checkMeshDict.H"
#include "checkCellConnectionsOverFaces.H"
#include "checkIrregularSurfaceConnections.H"
#include "checkNonMappableCellConnections.H"
#include "checkBoundaryFacesSharingTwoEdges.H"
#include "polyMeshGenGeometryModification.H"
#include "surfaceMeshGeometryModification.H"
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
void Foam::Module::cartesian2DMeshGenerator::createCartesianMesh()
{
cartesianMeshExtractor cme(*octreePtr_, meshDict_, mesh_);
if
(
meshDict_.lookupOrDefault<bool>
(
"decomposePolyhedraIntoTetsAndPyrs",
false
)
)
{
}
cme.createMesh();
}
void Foam::Module::cartesian2DMeshGenerator::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
bool changed;
do
{
changed = false;
checkIrregularSurfaceConnections checkConnections(mesh_);
if (checkConnections.checkAndFixIrregularConnections())
changed = true;
if (checkNonMappableCellConnections(mesh_).removeCells())
changed = true;
if (checkCellConnectionsOverFaces(mesh_).checkCellGroups())
changed = true;
checkBoundaryFacesSharingTwoEdges(mesh_).improveTopology();
}
void Foam::Module::cartesian2DMeshGenerator::mapMeshToSurface()
{
meshSurfaceEngine* msePtr = new meshSurfaceEngine(mesh_);
meshSurfaceMapper2D mapper(*msePtr, *octreePtr_);
mapper.adjustZCoordinates();
mapper.preMapVertices();
mapper.mapVerticesOntoSurface();
deleteDemandDrivenData(msePtr);
}
void Foam::Module::cartesian2DMeshGenerator::extractPatches()
{
meshSurfaceEdgeExtractor2D(mesh_, *octreePtr_).distributeBoundaryFaces();
}
void Foam::Module::cartesian2DMeshGenerator::mapEdgesAndCorners()
{
meshSurfaceEdgeExtractor2D(mesh_, *octreePtr_).remapBoundaryPoints();
}
void Foam::Module::cartesian2DMeshGenerator::optimiseMeshSurface()
{
meshSurfaceEngine mse(mesh_);
meshSurfaceOptimizer optimizer(mse, *octreePtr_);
optimizer.optimizeSurface2D();
optimizer.untangleSurface2D();
}
void Foam::Module::cartesian2DMeshGenerator::generateBoundaryLayers()
{
boundaryLayers bl(mesh_);
bl.activate2DMode();
bl.addLayerForAllPatches();
{
polyMeshGenGeometryModification meshMod(mesh_, meshDict_);
meshMod.revertGeometryModification();
deleteDemandDrivenData(modSurfacePtr_);
deleteDemandDrivenData(octreePtr_);
// contruct a new octree from the input surface
octreePtr_ = new meshOctree(*surfacePtr_, true);
meshOctreeCreator(*octreePtr_).createOctreeWithRefinedBoundary(20);
mapEdgesAndCorners();
optimiseMeshSurface();
}
void Foam::Module::cartesian2DMeshGenerator::refBoundaryLayers()
{
{
refineBoundaryLayers refLayers(mesh_);
refineBoundaryLayers::readSettings(meshDict_, refLayers);
refLayers.activate2DMode();
refLayers.refineLayers();
meshSurfaceEngine mse(mesh_);
meshSurfaceOptimizer optimizer(mse, *octreePtr_);
optimizer.untangleSurface2D();
}
}
void Foam::Module::cartesian2DMeshGenerator::replaceBoundaries()
{
renameBoundaryPatches rbp(mesh_, meshDict_, true);
}
void Foam::Module::cartesian2DMeshGenerator::renumberMesh()
{
polyMeshGenModifier(mesh_).renumberMesh();
}
void Foam::Module::cartesian2DMeshGenerator::generateMesh()
{
if (controller_.runCurrentStep("templateGeneration"))
createCartesianMesh();
}
if (controller_.runCurrentStep("surfaceTopology"))
{
surfacePreparation();
}
if (controller_.runCurrentStep("surfaceProjection"))
{
mapMeshToSurface();
}
if (controller_.runCurrentStep("patchAssignment"))
{
extractPatches();
}
if (controller_.runCurrentStep("edgeExtraction"))
{
mapEdgesAndCorners();
optimiseMeshSurface();
}
if (controller_.runCurrentStep("boundaryLayerGeneration"))
{
generateBoundaryLayers();
if (controller_.runCurrentStep("meshOptimisation"))
optimiseMeshSurface();
if (controller_.runCurrentStep("boundaryLayerRefinement"))
refBoundaryLayers();
renumberMesh();
replaceBoundaries();
controller_.workflowCompleted();
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::Module::cartesian2DMeshGenerator::cartesian2DMeshGenerator
(
const Time& time
)
:
db_(time),
surfacePtr_(nullptr),
modSurfacePtr_(nullptr),
meshDict_
(
IOobject
(
"meshDict",
db_.system(),
db_,
IOobject::MUST_READ,
IOobject::NO_WRITE
)
),
mesh_(time),
controller_(mesh_)
{
{
{
checkMeshDict cmd(meshDict_);
}
fileName surfaceFile(meshDict_.lookup("surfaceFile"));
surfaceFile = ".."/surfaceFile;
surfacePtr_ = new triSurf(db_.path()/surfaceFile);
// 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);
triSurface2DCheck surfCheck(*surfacePtr_);
{
surfCheck.createSubsets();
Info<< "Writting surface with subsets to file "
<< "badSurfaceWithSubsets.fms" << endl;
surfacePtr_->writeSurface("badSurfaceWithSubsets.fms");
}
}
// get rid of duplicate triangles as they cause strange problems
triSurfaceCleanupDuplicateTriangles
(
const_cast<triSurf&>(*surfacePtr_)
);
// 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;
{
surfaceMeshGeometryModification surfMod(*surfacePtr_, meshDict_);
modSurfacePtr_ = surfMod.modifyGeometry();
octreePtr_ = new meshOctree(*modSurfacePtr_, true);
}
else
{
octreePtr_ = new meshOctree(*surfacePtr_, true);
}
meshOctreeCreator(*octreePtr_, meshDict_).createOctreeBoxes();
generateMesh();
}
WarningInFunction
<< "Meshing process terminated!" << endl;
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::Module::cartesian2DMeshGenerator::~cartesian2DMeshGenerator()
{
deleteDemandDrivenData(surfacePtr_);
deleteDemandDrivenData(modSurfacePtr_);
deleteDemandDrivenData(octreePtr_);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
void Foam::Module::cartesian2DMeshGenerator::writeMesh() const
{
mesh_.write();
}
// ************************************************************************* //