/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | foam-extend: Open Source CFD
\\ / O peration |
\\ / A nd | For copyright notice see file Copyright
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of foam-extend.
foam-extend 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.
foam-extend 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 foam-extend. If not, see .
Application
blockMesh
Description
A multi-block mesh generator.
Uses the block mesh description found in
@a constant/polyMesh/blockMeshDict
(or @a constant/\/polyMesh/blockMeshDict).
Usage
- blockMesh [OPTION]
@param -blockTopology \n
Write the topology as a set of edges in OBJ format.
@param -region \ \n
Specify an alternative mesh region.
@param -dict \ \n
Specify an alternative dictionary for the block mesh description.
\*---------------------------------------------------------------------------*/
#include "objectRegistry.H"
#include "Time.H"
#include "IOdictionary.H"
#include "IOPtrList.H"
#include "blockMesh.H"
#include "preservePatchTypes.H"
#include "emptyPolyPatch.H"
#include "cellSet.H"
#include "argList.H"
#include "OSspecific.H"
#include "OFstream.H"
#include "Pair.H"
#include "mapPolyMesh.H"
#include "polyTopoChanger.H"
#include "slidingInterface.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
argList::noParallel();
argList::validOptions.insert("blockTopology", "");
argList::validOptions.insert("dict", "dictionary");
# include "addRegionOption.H"
# include "setRootCase.H"
# include "createTime.H"
const word dictName("blockMeshDict");
word regionName;
fileName polyMeshDir;
if (args.optionFound("region"))
{
// constant//polyMesh/blockMeshDict
regionName = args.option("region");
polyMeshDir = regionName/polyMesh::meshSubDir;
Info<< nl << "Generating mesh for region " << regionName << endl;
}
else
{
// constant/polyMesh/blockMeshDict
regionName = polyMesh::defaultRegion;
polyMeshDir = polyMesh::meshSubDir;
}
autoPtr meshDictIoPtr;
if (args.optionFound("dict"))
{
fileName dictPath(args.option("dict"));
meshDictIoPtr.set
(
new IOobject
(
(
isDir(dictPath)
? dictPath/dictName
: dictPath
),
runTime,
IOobject::MUST_READ,
IOobject::NO_WRITE,
false
)
);
}
else
{
meshDictIoPtr.set
(
new IOobject
(
dictName,
runTime.constant(),
polyMeshDir,
runTime,
IOobject::MUST_READ,
IOobject::NO_WRITE,
false
)
);
}
if (!meshDictIoPtr->headerOk())
{
FatalErrorIn(args.executable())
<< "Cannot open mesh description file\n "
<< meshDictIoPtr->objectPath()
<< nl
<< exit(FatalError);
}
Info<< nl << "Creating block mesh from\n "
<< meshDictIoPtr->objectPath() << nl << endl;
IOdictionary meshDict(meshDictIoPtr());
blockMesh blocks(meshDict);
if (args.optionFound("blockTopology"))
{
// Write mesh as edges.
{
fileName objMeshFile("blockTopology.obj");
OFstream str(runTime.path()/objMeshFile);
Info<< nl << "Dumping block structure as Lightwave obj format"
<< " to " << objMeshFile << endl;
blocks.writeTopology(str);
}
// Write centres of blocks
{
fileName objCcFile("blockCentres.obj");
OFstream str(runTime.path()/objCcFile);
Info<< nl << "Dumping block centres as Lightwave obj format"
<< " to " << objCcFile << endl;
const polyMesh& topo = blocks.topology();
const pointField& cellCentres = topo.cellCentres();
forAll(cellCentres, cellI)
{
//point cc = b.blockShape().centre(b.points());
const point& cc = cellCentres[cellI];
str << "v " << cc.x() << ' ' << cc.y() << ' ' << cc.z() << nl;
}
}
Info<< nl << "end" << endl;
return 0;
}
Info<< nl << "Creating mesh from block mesh" << endl;
wordList patchNames = blocks.patchNames();
wordList patchTypes = blocks.patchTypes();
word defaultFacesName = "defaultFaces";
word defaultFacesType = emptyPolyPatch::typeName;
wordList patchPhysicalTypes = blocks.patchPhysicalTypes();
preservePatchTypes
(
runTime,
runTime.constant(),
polyMeshDir,
patchNames,
patchTypes,
defaultFacesName,
defaultFacesType,
patchPhysicalTypes
);
polyMesh mesh
(
IOobject
(
regionName,
runTime.constant(),
runTime
),
xferCopy(blocks.points()),
blocks.cells(),
blocks.patches(),
patchNames,
patchTypes,
defaultFacesName,
defaultFacesType,
patchPhysicalTypes
);
// Read in a list of dictionaries for the merge patch pairs
if (meshDict.found("mergePatchPairs"))
{
List > mergePatchPairs
(
meshDict.lookup("mergePatchPairs")
);
if (mergePatchPairs.size() > 0)
{
// Create and add point and face zones and mesh modifiers
List pz(mergePatchPairs.size());
List fz(3*mergePatchPairs.size());
List cz(0);
forAll (mergePatchPairs, pairI)
{
const word mergeName
(
mergePatchPairs[pairI].first()
+ mergePatchPairs[pairI].second()
+ name(pairI)
);
pz[pairI] = new pointZone
(
mergeName + "CutPointZone",
labelList(0),
0,
mesh.pointZones()
);
// Master patch
const word masterPatchName(mergePatchPairs[pairI].first());
const polyPatch& masterPatch =
mesh.boundaryMesh()
[
mesh.boundaryMesh().findPatchID(masterPatchName)
];
labelList isf(masterPatch.size());
forAll (isf, i)
{
isf[i] = masterPatch.start() + i;
}
fz[3*pairI] = new faceZone
(
mergeName + "MasterZone",
isf,
boolList(masterPatch.size(), false),
0,
mesh.faceZones()
);
// Slave patch
const word slavePatchName(mergePatchPairs[pairI].second());
const polyPatch& slavePatch =
mesh.boundaryMesh()
[
mesh.boundaryMesh().findPatchID(slavePatchName)
];
labelList osf(slavePatch.size());
forAll (osf, i)
{
osf[i] = slavePatch.start() + i;
}
fz[3*pairI + 1] = new faceZone
(
mergeName + "SlaveZone",
osf,
boolList(slavePatch.size(), false),
1,
mesh.faceZones()
);
// Add empty zone for cut faces
fz[3*pairI + 2] = new faceZone
(
mergeName + "CutFaceZone",
labelList(0),
boolList(0, false),
2,
mesh.faceZones()
);
} // end of all merge pairs
Info << "Adding point and face zones" << endl;
mesh.addZones(pz, fz, cz);
Info << "Creating topo change" << endl;
polyTopoChanger attacher(mesh);
attacher.setSize(mergePatchPairs.size());
forAll (mergePatchPairs, pairI)
{
const word mergeName
(
mergePatchPairs[pairI].first()
+ mergePatchPairs[pairI].second()
+ name(pairI)
);
// Add the sliding interface mesh modifier
attacher.set
(
pairI,
new slidingInterface
(
"couple" + name(pairI),
pairI,
attacher,
mergeName + "MasterZone",
mergeName + "SlaveZone",
mergeName + "CutPointZone",
mergeName + "CutFaceZone",
mergePatchPairs[pairI].first(),
mergePatchPairs[pairI].second(),
slidingInterface::INTEGRAL, // always integral
false, // attach-detach action
intersection::VISIBLE
)
);
}
attacher.changeMesh();
// Clean the mesh after attach
labelList patchSizes(mesh.boundaryMesh().size());
labelList patchStarts(mesh.boundaryMesh().size());
forAll (mesh.boundaryMesh(), patchI)
{
patchSizes[patchI] = mesh.boundaryMesh()[patchI].size();
patchStarts[patchI] = mesh.boundaryMesh()[patchI].start();
}
mesh.resetPrimitives
(
xferCopy(mesh.points()),
xferCopy(mesh.faces()),
xferCopy(mesh.faceOwner()),
xferCopy(mesh.faceNeighbour()),
patchSizes,
patchStarts
);
mesh.setInstance(runTime.constant());
mesh.removeZones();
}
}
else
{
Info<< nl << "There are no merge patch pairs" << endl;
}
// Set any cellZones (note: cell labelling unaffected by above
// mergePatchPairs)
label nZones = blocks.numZonedBlocks();
if (nZones > 0)
{
Info<< nl << "Adding cell zones" << endl;
// Map from zoneName to cellZone index
HashTable