460 lines
12 KiB
C
460 lines
12 KiB
C
|
/*---------------------------------------------------------------------------*\
|
||
|
========= |
|
||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||
|
\\ / O peration |
|
||
|
\\ / A nd | Copyright held by original author
|
||
|
\\/ M anipulation |
|
||
|
-------------------------------------------------------------------------------
|
||
|
License
|
||
|
This file is part of OpenFOAM.
|
||
|
|
||
|
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 2 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, write to the Free Software Foundation,
|
||
|
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||
|
|
||
|
\*---------------------------------------------------------------------------*/
|
||
|
|
||
|
#include "blockMesh.H"
|
||
|
#include "Time.H"
|
||
|
#include "preservePatchTypes.H"
|
||
|
#include "emptyPolyPatch.H"
|
||
|
|
||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||
|
|
||
|
bool Foam::blockMesh::blockLabelsOK
|
||
|
(
|
||
|
const label blockLabel,
|
||
|
const pointField& points,
|
||
|
const cellShape& blockShape
|
||
|
)
|
||
|
{
|
||
|
bool ok = true;
|
||
|
|
||
|
for (int i=0; i<blockShape.size(); i++)
|
||
|
{
|
||
|
if (blockShape[i] < 0)
|
||
|
{
|
||
|
ok = false;
|
||
|
|
||
|
WarningIn
|
||
|
(
|
||
|
"bool Foam::blockMesh::blockLabelsOK"
|
||
|
"(const label blockLabel, const pointField& points, "
|
||
|
"const cellShape& blockShape)"
|
||
|
) << "block " << blockLabel
|
||
|
<< " point label " << blockShape[i]
|
||
|
<< " less than zero" << endl;
|
||
|
}
|
||
|
else if (blockShape[i] >= points.size())
|
||
|
{
|
||
|
ok = false;
|
||
|
|
||
|
WarningIn
|
||
|
(
|
||
|
"bool Foam::blockMesh::blockLabelsOK"
|
||
|
"(const label blockLabel, const pointField& points, "
|
||
|
"const cellShape& blockShape)"
|
||
|
) << "block " << blockLabel
|
||
|
<< " point label " << blockShape[i]
|
||
|
<< " larger than " << points.size() - 1
|
||
|
<< " the largest defined point label" << endl;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ok;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool Foam::blockMesh::patchLabelsOK
|
||
|
(
|
||
|
const label patchLabel,
|
||
|
const pointField& points,
|
||
|
const faceList& patchFaces
|
||
|
)
|
||
|
{
|
||
|
bool ok = true;
|
||
|
|
||
|
for (label facei=0; facei<patchFaces.size(); facei++)
|
||
|
{
|
||
|
const labelList& labels = patchFaces[facei];
|
||
|
|
||
|
for (int i=0; i<labels.size(); i++)
|
||
|
{
|
||
|
if (labels[i] < 0)
|
||
|
{
|
||
|
ok = false;
|
||
|
|
||
|
WarningIn
|
||
|
(
|
||
|
"bool Foam::blockMesh::patchLabelsOK"
|
||
|
"(const label patchLabel, const pointField& points, "
|
||
|
"const faceList& patchFaces)"
|
||
|
) << "patch " << patchLabel
|
||
|
<< " face " << facei
|
||
|
<< " point label " << labels[i]
|
||
|
<< " less than zero" << endl;
|
||
|
}
|
||
|
else if (labels[i] >= points.size())
|
||
|
{
|
||
|
ok = false;
|
||
|
|
||
|
WarningIn
|
||
|
(
|
||
|
"bool Foam::blockMesh::patchLabelsOK"
|
||
|
"(const label patchLabel, const pointField& points, "
|
||
|
"const faceList& patchFaces)"
|
||
|
) << "patch " << patchLabel
|
||
|
<< " face " << facei
|
||
|
<< " point label " << labels[i]
|
||
|
<< " larger than " << points.size() - 1
|
||
|
<< " the largest defined point label" << endl;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ok;
|
||
|
}
|
||
|
|
||
|
|
||
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||
|
|
||
|
Foam::polyMesh* Foam::blockMesh::createTopology(IOdictionary& meshDescription)
|
||
|
{
|
||
|
bool topologyOK = true;
|
||
|
|
||
|
blockMesh& blocks = *this;
|
||
|
|
||
|
word defaultPatchName = "defaultFaces";
|
||
|
word defaultPatchType = emptyPolyPatch::typeName;
|
||
|
|
||
|
// get names and types for the unassigned patch faces
|
||
|
if (meshDescription.found("defaultPatch"))
|
||
|
{
|
||
|
const dictionary& defaultPatch =
|
||
|
meshDescription.subDict("defaultPatch");
|
||
|
|
||
|
// this is a bit heavy handed (and ugly), but there is currently
|
||
|
// no easy way to rename polyMesh patches subsequently
|
||
|
if (defaultPatch.found("name"))
|
||
|
{
|
||
|
defaultPatch.lookup("name") >> defaultPatchName;
|
||
|
}
|
||
|
|
||
|
if (defaultPatch.found("type"))
|
||
|
{
|
||
|
defaultPatch.lookup("type") >> defaultPatchType;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Info<< nl << "Creating blockCorners" << endl;
|
||
|
|
||
|
// create blockCorners
|
||
|
pointField tmpBlockPoints(meshDescription.lookup("vertices"));
|
||
|
|
||
|
if (meshDescription.found("edges"))
|
||
|
{
|
||
|
// read number of non-linear edges in mesh
|
||
|
Info<< nl << "Creating curved edges" << endl;
|
||
|
|
||
|
ITstream& edgesStream(meshDescription.lookup("edges"));
|
||
|
|
||
|
label nEdges = 0;
|
||
|
|
||
|
token firstToken(edgesStream);
|
||
|
|
||
|
if (firstToken.isLabel())
|
||
|
{
|
||
|
nEdges = firstToken.labelToken();
|
||
|
edges_.setSize(nEdges);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
edgesStream.putBack(firstToken);
|
||
|
}
|
||
|
|
||
|
// Read beginning of edges
|
||
|
edgesStream.readBegin("edges");
|
||
|
|
||
|
nEdges = 0;
|
||
|
|
||
|
token lastToken(edgesStream);
|
||
|
while
|
||
|
(
|
||
|
!(
|
||
|
lastToken.isPunctuation()
|
||
|
&& lastToken.pToken() == token::END_LIST
|
||
|
)
|
||
|
)
|
||
|
{
|
||
|
if (edges_.size() <= nEdges)
|
||
|
{
|
||
|
edges_.setSize(nEdges + 1);
|
||
|
}
|
||
|
|
||
|
edgesStream.putBack(lastToken);
|
||
|
|
||
|
edges_.set
|
||
|
(
|
||
|
nEdges,
|
||
|
curvedEdge::New(tmpBlockPoints, edgesStream)
|
||
|
);
|
||
|
|
||
|
nEdges++;
|
||
|
|
||
|
edgesStream >> lastToken;
|
||
|
}
|
||
|
edgesStream.putBack(lastToken);
|
||
|
|
||
|
// Read end of edges
|
||
|
edgesStream.readEnd("edges");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Info<< nl << "There are no non-linear edges" << endl;
|
||
|
}
|
||
|
|
||
|
|
||
|
Info<< nl << "Creating blocks" << endl;
|
||
|
{
|
||
|
ITstream& blockDescriptorStream(meshDescription.lookup("blocks"));
|
||
|
|
||
|
// read number of blocks in mesh
|
||
|
label nBlocks = 0;
|
||
|
|
||
|
token firstToken(blockDescriptorStream);
|
||
|
|
||
|
if (firstToken.isLabel())
|
||
|
{
|
||
|
nBlocks = firstToken.labelToken();
|
||
|
blocks.setSize(nBlocks);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
blockDescriptorStream.putBack(firstToken);
|
||
|
}
|
||
|
|
||
|
// Read beginning of blocks
|
||
|
blockDescriptorStream.readBegin("blocks");
|
||
|
|
||
|
nBlocks = 0;
|
||
|
|
||
|
token lastToken(blockDescriptorStream);
|
||
|
while
|
||
|
(
|
||
|
!(
|
||
|
lastToken.isPunctuation()
|
||
|
&& lastToken.pToken() == token::END_LIST
|
||
|
)
|
||
|
)
|
||
|
{
|
||
|
if (blocks.size() <= nBlocks)
|
||
|
{
|
||
|
blocks.setSize(nBlocks + 1);
|
||
|
}
|
||
|
|
||
|
blockDescriptorStream.putBack(lastToken);
|
||
|
|
||
|
blocks.set
|
||
|
(
|
||
|
nBlocks,
|
||
|
new block
|
||
|
(
|
||
|
blockDescriptor
|
||
|
(
|
||
|
tmpBlockPoints,
|
||
|
edges_,
|
||
|
blockDescriptorStream
|
||
|
)
|
||
|
)
|
||
|
);
|
||
|
|
||
|
topologyOK = topologyOK && blockLabelsOK
|
||
|
(
|
||
|
nBlocks,
|
||
|
tmpBlockPoints,
|
||
|
blocks[nBlocks].blockDef().blockShape()
|
||
|
);
|
||
|
|
||
|
nBlocks++;
|
||
|
|
||
|
blockDescriptorStream >> lastToken;
|
||
|
}
|
||
|
blockDescriptorStream.putBack(lastToken);
|
||
|
|
||
|
// Read end of blocks
|
||
|
blockDescriptorStream.readEnd("blocks");
|
||
|
}
|
||
|
|
||
|
|
||
|
Info<< nl << "Creating patches" << endl;
|
||
|
|
||
|
faceListList tmpBlocksPatches;
|
||
|
wordList patchNames;
|
||
|
wordList patchTypes;
|
||
|
|
||
|
{
|
||
|
ITstream& patchStream(meshDescription.lookup("patches"));
|
||
|
|
||
|
// read number of patches in mesh
|
||
|
label nPatches = 0;
|
||
|
|
||
|
token firstToken(patchStream);
|
||
|
|
||
|
if (firstToken.isLabel())
|
||
|
{
|
||
|
nPatches = firstToken.labelToken();
|
||
|
|
||
|
tmpBlocksPatches.setSize(nPatches);
|
||
|
patchNames.setSize(nPatches);
|
||
|
patchTypes.setSize(nPatches);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
patchStream.putBack(firstToken);
|
||
|
}
|
||
|
|
||
|
// Read beginning of blocks
|
||
|
patchStream.readBegin("patches");
|
||
|
|
||
|
nPatches = 0;
|
||
|
|
||
|
token lastToken(patchStream);
|
||
|
while
|
||
|
(
|
||
|
!(
|
||
|
lastToken.isPunctuation()
|
||
|
&& lastToken.pToken() == token::END_LIST
|
||
|
)
|
||
|
)
|
||
|
{
|
||
|
if (tmpBlocksPatches.size() <= nPatches)
|
||
|
{
|
||
|
tmpBlocksPatches.setSize(nPatches + 1);
|
||
|
patchNames.setSize(nPatches + 1);
|
||
|
patchTypes.setSize(nPatches + 1);
|
||
|
}
|
||
|
|
||
|
patchStream.putBack(lastToken);
|
||
|
|
||
|
patchStream
|
||
|
>> patchTypes[nPatches]
|
||
|
>> patchNames[nPatches]
|
||
|
>> tmpBlocksPatches[nPatches];
|
||
|
|
||
|
|
||
|
// Catch multiple patches asap.
|
||
|
for (label i = 0; i < nPatches; i++)
|
||
|
{
|
||
|
if (patchNames[nPatches] == patchNames[i])
|
||
|
{
|
||
|
FatalErrorIn
|
||
|
(
|
||
|
"blockMesh::createTopology(IOdictionary&)"
|
||
|
) << "Duplicate patch " << patchNames[nPatches]
|
||
|
<< " at line " << patchStream.lineNumber()
|
||
|
<< ". Exiting !" << nl
|
||
|
<< exit(FatalError);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
topologyOK = topologyOK && patchLabelsOK
|
||
|
(
|
||
|
nPatches,
|
||
|
tmpBlockPoints,
|
||
|
tmpBlocksPatches[nPatches]
|
||
|
);
|
||
|
|
||
|
nPatches++;
|
||
|
|
||
|
patchStream >> lastToken;
|
||
|
}
|
||
|
patchStream.putBack(lastToken);
|
||
|
|
||
|
// Read end of blocks
|
||
|
patchStream.readEnd("patches");
|
||
|
}
|
||
|
|
||
|
|
||
|
if (!topologyOK)
|
||
|
{
|
||
|
FatalErrorIn("blockMesh::createTopology(IOdictionary&)")
|
||
|
<< "Cannot create mesh due to errors in topology, exiting !" << nl
|
||
|
<< exit(FatalError);
|
||
|
}
|
||
|
|
||
|
|
||
|
Info<< nl << "Creating block mesh topology" << endl;
|
||
|
|
||
|
PtrList<cellShape> tmpBlockCells(blocks.size());
|
||
|
forAll(blocks, blockLabel)
|
||
|
{
|
||
|
tmpBlockCells.set
|
||
|
(
|
||
|
blockLabel,
|
||
|
new cellShape(blocks[blockLabel].blockDef().blockShape())
|
||
|
);
|
||
|
|
||
|
if (tmpBlockCells[blockLabel].mag(tmpBlockPoints) < 0.0)
|
||
|
{
|
||
|
WarningIn
|
||
|
(
|
||
|
"blockMesh::createTopology(IOdictionary&)"
|
||
|
) << "negative volume block : " << blockLabel
|
||
|
<< ", probably defined inside-out" << endl;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
wordList patchPhysicalTypes(tmpBlocksPatches.size());
|
||
|
|
||
|
preservePatchTypes
|
||
|
(
|
||
|
meshDescription.time(),
|
||
|
meshDescription.time().constant(),
|
||
|
polyMesh::meshSubDir,
|
||
|
patchNames,
|
||
|
patchTypes,
|
||
|
defaultPatchName,
|
||
|
defaultPatchType,
|
||
|
patchPhysicalTypes
|
||
|
);
|
||
|
|
||
|
polyMesh* blockMeshPtr = new polyMesh
|
||
|
(
|
||
|
IOobject
|
||
|
(
|
||
|
"blockMesh",
|
||
|
meshDescription.time().constant(),
|
||
|
meshDescription.time(),
|
||
|
IOobject::NO_READ,
|
||
|
IOobject::NO_WRITE,
|
||
|
false
|
||
|
),
|
||
|
tmpBlockPoints,
|
||
|
tmpBlockCells,
|
||
|
tmpBlocksPatches,
|
||
|
patchNames,
|
||
|
patchTypes,
|
||
|
defaultPatchName,
|
||
|
defaultPatchType,
|
||
|
patchPhysicalTypes
|
||
|
);
|
||
|
|
||
|
checkBlockMesh(*blockMeshPtr);
|
||
|
|
||
|
return blockMeshPtr;
|
||
|
}
|
||
|
|
||
|
|
||
|
// ************************************************************************* //
|
||
|
|