openfoam/applications/utilities/mesh/conversion/fluent3DMeshToFoam/fluent3DMeshToFoam.L
henry 8dc018bb53 Add flex version selection of the yywrap() function to support
the new and more correct version 2.5.34.
2008-05-29 23:29:28 +01:00

1250 lines
35 KiB
Plaintext

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
\\/ 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
Application
fluent3DMeshToFoam
Description
Converts a Fluent mesh to OpenFOAM format.
\*---------------------------------------------------------------------------*/
%{
#undef yyFlexLexer
/* ------------------------------------------------------------------------ *\
------ local definitions
\* ------------------------------------------------------------------------ */
#include "argList.H"
#include "Time.H"
#include "polyMesh.H"
#include "polyTopoChange.H"
#include "polyMeshZipUpCells.H"
#include "wallPolyPatch.H"
#include "symmetryPolyPatch.H"
#include "cyclicPolyPatch.H"
#include "Swap.H"
#include "IFstream.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Scalae factor used to scale points (optional command line argument)
scalar scaleFactor = 1.0;
label dimensionOfGrid = 0;
label nPoints = 0;
label nFaces = 0;
label nCells = 0;
bool hangingNodes = false;
pointField points(0);
faceList faces(0);
labelList owner(0);
labelList neighbour(0);
// Group type and name
Map<word> groupType(100);
Map<word> groupName(100);
// Point groups
DynamicList<label> pointGroupZoneID;
DynamicList<label> pointGroupStartIndex;
DynamicList<label> pointGroupEndIndex;
// Face groups
DynamicList<label> faceGroupZoneID;
DynamicList<label> faceGroupStartIndex;
DynamicList<label> faceGroupEndIndex;
// Cell groups
DynamicList<label> cellGroupZoneID;
DynamicList<label> cellGroupStartIndex;
DynamicList<label> cellGroupEndIndex;
DynamicList<label> cellGroupType;
void uniquify(word& name, HashSet<word>& patchNames)
{
if (!patchNames.found(name))
{
patchNames.insert(name);
}
else
{
Info<< " name " << name << " already used";
label i = 1;
word baseName = name;
do
{
name = baseName + "_" + Foam::name(i++);
} while (patchNames.found(name));
Info<< ", changing to " << name << endl;
}
}
// Dummy yywrap to keep yylex happy at compile time.
// It is called by yylex but is not used as the mechanism to change file.
// See <<EOF>>
#if YY_FLEX_SUBMINOR_VERSION < 34
extern "C" int yywrap()
#else
int yyFlexLexer::yywrap()
#endif
{
return 1;
}
%}
one_space [ \t\f]
space {one_space}*
some_space {one_space}+
cspace ","{space}
nl (\n|\r)
spaceNl ({space}|{nl})*
alpha [_[:alpha:]]
digit [[:digit:]]
decDigit [[:digit:]]
octalDigit [0-7]
hexDigit [[:xdigit:]]
lbrac "("
rbrac ")"
quote \"
dash "-"
dotColonDash [.:-]
schemeSpecialInitial [!$%&*/\\:<=>?~_^#.@]
schemeSpecialSubsequent [.+-]
schemeSymbol (({some_space}|{alpha}|{quote}|{schemeSpecialInitial})({alpha}|{quote}|{digit}|{schemeSpecialInitial}|{schemeSpecialSubsequent})*)
identifier {alpha}({alpha}|{digit})*
integer {decDigit}+
label [1-9]{decDigit}*
hexLabel {hexDigit}+
zeroLabel {digit}*
signedInteger [-+]?{integer}
word ({alpha}|{digit}|{dotColonDash})*
exponent_part [eE][-+]?{digit}+
fractional_constant [-+]?(({digit}*"."{digit}+)|({digit}+".")|({digit}))
double ((({fractional_constant}{exponent_part}?)|({digit}+{exponent_part}))|0)
x {double}
y {double}
z {double}
scalar {double}
labelListElement {space}{zeroLabel}
hexLabelListElement {space}{hexLabel}
scalarListElement {space}{double}
schemeSymbolListElement {space}{schemeSymbol}
labelList ({labelListElement}+{space})
hexLabelList ({hexLabelListElement}+{space})
scalarList ({scalarListElement}+{space})
schemeSymbolList ({schemeSymbolListElement}+{space})
starStar ("**")
text ({space}({word}*{space})*)
anythingInBlock ([^)]*)
dateDDMMYYYY ({digit}{digit}"/"{digit}{digit}"/"{digit}{digit}{digit}{digit})
dateDDMonYYYY ((({digit}{digit}{space})|({digit}{space})){alpha}*{space}{digit}{digit}{digit}{digit})
time ({digit}{digit}":"{digit}{digit}":"{digit}{digit})
versionNumber ({digit}|".")*
header {spaceNl}"(1"{some_space}
dimension {spaceNl}"(2"{some_space}
points {spaceNl}"(10"{some_space}
faces {spaceNl}"(13"{some_space}
cells {spaceNl}"(12"{some_space}
zoneVariant1 {spaceNl}"(39"{some_space}
zoneVariant2 {spaceNl}"(45"{some_space}
faceTree {spaceNl}"(59"{some_space}
comment "0"{some_space}
unknownPeriodicFace "17"{some_space}
periodicFace "18"{some_space}
cellTree "58"{some_space}
faceParents "61"{some_space}
ignoreBlocks ("4"|"37"|"38"|"41"|"60"|"64"){some_space}
redundantBlock {spaceNl}({comment}|{unknownPeriodicFace}|{periodicFace}|{cellTree}|{faceParents}|{ignoreBlocks}){space}
endOfSection {space}")"{space}
/* ------------------------------------------------------------------------ *\
----- Exclusive start states -----
\* ------------------------------------------------------------------------ */
%option stack
%x readHeader
%x readDimension
%x readPoint
%x readPointHeader
%x readNumberOfPoints
%x readPointGroupData
%x readPointData
%x readScalarList
%x fluentFace
%x readFaceHeader
%x readNumberOfFaces
%x readFaceGroupData
%x readFaceData
%x readFacesMixed
%x readFacesUniform
%x cell
%x readCellHeader
%x readNumberOfCells
%x readCellGroupData
%x readCellData
%x readCellsUniform
%x zone
%x readZoneHeader
%x readZoneGroupData
%x readZoneData
%x readZoneBlock
%x ignoreBlock
%x ignoreEmbeddedBlock
%%
%{
// End of read character pointer returned by strtol and strtod
char* endPtr;
// Point data
label pointGroupNumberOfComponents = 3;
label pointi = 0; // index used for reading points
label cmpt = 0; // component index used for reading points
// Face data
label faceGroupElementType = -1;
label facei = 0; // index used for reading faces
%}
/* ------------------------------------------------------------------------ *\
------ Start Lexing ------
\* ------------------------------------------------------------------------ */
/* ------ Reading control header ------ */
{header} {
BEGIN(readHeader);
}
<readHeader>{anythingInBlock} {
Info<< "Header: " << YYText() << endl;
}
{dimension} {
BEGIN(readDimension);
}
<readDimension>{space}{label}{space} {
dimensionOfGrid = atoi(YYText());
Info<< "Dimension of grid: " << dimensionOfGrid << endl;
}
{points} {
BEGIN(readPointHeader);
}
<readPointHeader>{spaceNl}{lbrac}{space}"0"{space}"1"{space} {
BEGIN(readNumberOfPoints);
}
<readNumberOfPoints>{hexLabel}{space}{labelList} {
nPoints = strtol(YYText(), &endPtr, 16);
Info<< "Number of points: " << nPoints << endl;
points.setSize(nPoints);
// Ignore rest of stream
}
<readPointHeader>{spaceNl}{lbrac} {
BEGIN(readPointGroupData);
}
<readPointGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{labelList} {
// Read point zone-ID, start and end-label
// the indices will be used for checking later.
pointGroupZoneID.append(strtol(YYText(), &endPtr, 16));
// In FOAM, indices start from zero - adjust
pointGroupStartIndex.append(strtol(endPtr, &endPtr, 16) - 1);
pointGroupEndIndex.append(strtol(endPtr, &endPtr, 16) - 1);
// point group type skipped
strtol(endPtr, &endPtr, 16);
pointi = pointGroupStartIndex[pointGroupStartIndex.size()-1];
// reset number of components to default
pointGroupNumberOfComponents = 3;
// read number of components in the vector
if (endPtr < &(YYText()[YYLeng()-1]))
{
pointGroupNumberOfComponents = strtol(endPtr, &endPtr, 16);
}
Info<< "PointGroup: "
<< pointGroupZoneID[pointGroupZoneID.size()-1]
<< " start: "
<< pointGroupStartIndex[pointGroupStartIndex.size()-1]
<< " end: "
<< pointGroupEndIndex[pointGroupEndIndex.size()-1] << flush;
}
<readNumberOfPoints,readPointGroupData>{endOfSection} {
BEGIN(readPointData);
}
<readPointData>{spaceNl}{lbrac}{spaceNl} {
Info<< ". Reading points..." << flush;
cmpt = 0;
yy_push_state(readScalarList);
}
<readScalarList>{signedInteger}{space} {
points[pointi][cmpt++] = scaleFactor*atol(YYText());
}
<readScalarList>{scalar}{space} {
points[pointi][cmpt++] = scaleFactor*atof(YYText());
}
<readScalarList>{spaceNl} {
if (pointGroupNumberOfComponents == 2)
{
points[pointi].z() = 0.0;
}
cmpt = 0;
pointi++;
}
<readScalarList>{endOfSection} {
Info<< "done." << endl;
// check read of points
if (pointi != pointGroupEndIndex[pointGroupEndIndex.size()-1]+1)
{
Warning
<< "Problem with reading points: "
<< "start index: "
<< pointGroupStartIndex[pointGroupStartIndex.size()-1]
<< " end index: "
<< pointGroupEndIndex[pointGroupEndIndex.size()-1]
<< " last points read: " << pointi << endl;
}
yy_pop_state();
}
{faces} {
BEGIN(readFaceHeader);
}
<readFaceHeader>{spaceNl}{lbrac}{space}"0"{space}"1"{space} {
BEGIN(readNumberOfFaces);
}
<readNumberOfFaces>{space}{hexLabel}{space}{labelListElement}+ {
nFaces = strtol(YYText(), &endPtr, 16);
Info<< "Number of faces: " << nFaces << endl;
faces.setSize(nFaces);
owner.setSize(nFaces);
neighbour.setSize(nFaces);
// Type and element type not read
}
<readFaceHeader>{spaceNl}{lbrac} {
BEGIN(readFaceGroupData);
}
<readFaceGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{hexLabelListElement}+ {
// read fluentFace zone-ID, start and end-label
faceGroupZoneID.append(strtol(YYText(), &endPtr, 16));
// In FOAM, indices start from zero - adjust
faceGroupStartIndex.append(strtol(endPtr, &endPtr, 16) - 1);
faceGroupEndIndex.append(strtol(endPtr, &endPtr, 16) - 1);
// face group type
strtol(endPtr, &endPtr, 16);
faceGroupElementType = strtol(endPtr, &endPtr, 16);
facei = faceGroupStartIndex[faceGroupStartIndex.size()-1];
Info<< "FaceGroup: "
<< faceGroupZoneID[faceGroupZoneID.size()-1]
<< " start: "
<< faceGroupStartIndex[faceGroupStartIndex.size()-1]
<< " end: "
<< faceGroupEndIndex[faceGroupEndIndex.size()-1] << flush;
}
<readNumberOfFaces,readFaceGroupData>{spaceNl}{endOfSection} {
BEGIN(readFaceData);
}
<readFaceData>{spaceNl}{lbrac} {
if (faceGroupElementType == 0)
{
Info<< ". Reading mixed faces..." << flush;
yy_push_state(readFacesMixed);
}
else
{
Info<< ". Reading uniform faces..." << flush;
yy_push_state(readFacesUniform);
}
}
<readFacesMixed>{spaceNl}{hexLabelList} {
face& curFaceLabels = faces[facei];
// set size of label list
curFaceLabels.setSize(strtol(YYText(), &endPtr, 16));
forAll (curFaceLabels, i)
{
curFaceLabels[i] = strtol(endPtr, &endPtr, 16) - 1;
}
// read neighbour and owner. Neighbour comes first
neighbour[facei] = strtol(endPtr, &endPtr, 16) - 1;
owner[facei] = strtol(endPtr, &endPtr, 16) - 1;
facei++;
}
<readFacesUniform>{spaceNl}{hexLabelList} {
face& curFaceLabels = faces[facei];
// Set size of label list.
curFaceLabels.setSize(faceGroupElementType);
curFaceLabels[0] = strtol(YYText(), &endPtr, 16) - 1;
for (int i=1; i<faceGroupElementType; i++)
{
curFaceLabels[i] = strtol(endPtr, &endPtr, 16) - 1;
}
// read neighbour and owner. Neighbour comes first
neighbour[facei] = strtol(endPtr, &endPtr, 16) - 1;
owner[facei] = strtol(endPtr, &endPtr, 16) - 1;
facei++;
}
<readFacesMixed,readFacesUniform>{spaceNl}{endOfSection} {
Info<< "done." << endl;
// check read of fluentFaces
if (facei != faceGroupEndIndex[faceGroupEndIndex.size()-1]+1)
{
Warning
<< "Problem with reading fluentFaces: "
<< "start index: "
<< faceGroupStartIndex[faceGroupStartIndex.size()-1]
<< " end index: "
<< faceGroupEndIndex[faceGroupEndIndex.size()-1]
<< " last fluentFaces read: " << facei << endl;
}
yy_pop_state();
}
{cells} {
BEGIN(readCellHeader);
}
<readCellHeader>{spaceNl}{lbrac}{space}"0"{space}"1"{space} {
BEGIN(readNumberOfCells);
}
<readNumberOfCells>{space}{hexLabel}{space}{labelListElement}+ {
nCells = strtol(YYText(), &endPtr, 16);
Info<< "Number of cells: " << nCells << endl;
}
<readCellHeader>{spaceNl}{lbrac} {
BEGIN(readCellGroupData);
}
<readCellGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{space}{hexLabel} {
// Warning. This entry must be above the next one because of the lexing
// rules. It is introduced to deal with the problem of reading
// non-standard cell definition from Tgrid, which misses the type label.
Warning
<< "Tgrid syntax problem: " << YYText() << endl;
// read cell zone-ID, start and end-label
cellGroupZoneID.append(strtol(YYText(), &endPtr, 16));
// the indices will be used for checking later.
cellGroupStartIndex.append(strtol(endPtr, &endPtr, 16) - 1);
cellGroupEndIndex.append(strtol(endPtr, &endPtr, 16) - 1);
cellGroupType.append(strtol(endPtr, &endPtr, 16));
Info<< "CellGroup: "
<< cellGroupZoneID[cellGroupZoneID.size()-1]
<< " start: "
<< cellGroupStartIndex[cellGroupStartIndex.size()-1]
<< " end: "
<< cellGroupEndIndex[cellGroupEndIndex.size()-1]
<< " type: "
<< cellGroupType[cellGroupType.size()-1]
<< endl;
}
<readCellGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{space}{hexLabel} {
// Warning. See above
// read cell zone-ID, start and end-label
cellGroupZoneID.append(strtol(YYText(), &endPtr, 16));
// the indices will be used for checking later.
cellGroupStartIndex.append(strtol(endPtr, &endPtr, 16) - 1);
cellGroupEndIndex.append(strtol(endPtr, &endPtr, 16) - 1);
cellGroupType.append(strtol(endPtr, &endPtr, 16));
// Note. Potentially skip cell set if type is zero.
strtol(endPtr, &endPtr, 16);
Info<< "CellGroup: "
<< cellGroupZoneID[cellGroupZoneID.size()-1]
<< " start: "
<< cellGroupStartIndex[cellGroupStartIndex.size()-1]
<< " end: "
<< cellGroupEndIndex[cellGroupEndIndex.size()-1]
<< " type: "
<< cellGroupType[cellGroupType.size()-1]
<< endl;
}
<readNumberOfCells,readCellGroupData>{endOfSection} {
BEGIN(readCellData);
}
<readCellData>{spaceNl}{lbrac} {
// Quickly scan to the end of the cell data block and discard
register int c;
while ((c = yyinput()) != 0 && c != ')');
}
{faceTree} {
// There are hanging nodes in the mesh so make sure it gets zipped-up
hangingNodes = true;
yy_push_state(ignoreBlock);
}
{zoneVariant1} {
BEGIN(readZoneHeader);
}
{zoneVariant2} {
BEGIN(readZoneHeader);
}
<readZoneHeader>{spaceNl}{lbrac} {
BEGIN(readZoneGroupData);
}
<readZoneGroupData>{space}{label}{space}{word}{space}{word}{space}{label}? {
IStringStream zoneDataStream(YYText());
// cell zone-ID not in hexadecimal!!! Inconsistency
label zoneID(readLabel(zoneDataStream));
groupType.insert(zoneID, word(zoneDataStream));
groupName.insert(zoneID, word(zoneDataStream));
Info<< "Zone: " << zoneID
<< " name: " << groupName[zoneID]
<< " type: " << groupType[zoneID] << flush;
}
<readZoneGroupData>{endOfSection} {
BEGIN(readZoneData);
}
<readZoneData>{spaceNl}{lbrac} {
Info<< ". Reading zone data..." << flush;
yy_push_state(readZoneBlock);
}
<readZoneBlock>{spaceNl}{schemeSymbolList} {
}
<readZoneBlock>{lbrac} {
Warning
<< "Found unknown block in zone: " << YYText() << endl;
yy_push_state(ignoreBlock);
}
<readZoneBlock>{endOfSection} {
Info<< "done." << endl;
yy_pop_state();
}
/* ------ Reading end of section and others ------ */
<readHeader,readDimension,readPointData,readFaceData,readCellData,readZoneData>{spaceNl}{endOfSection} {
BEGIN(INITIAL);
}
/* ------ Reading unknown type or non-standard comment ------ */
{lbrac}{label} {
Warning
<< "Found unknown block of type: "
<< Foam::string(YYText())(1, YYLeng()-1) << endl;
yy_push_state(ignoreBlock);
}
{lbrac}{redundantBlock} {
yy_push_state(ignoreBlock);
}
<ignoreBlock,ignoreEmbeddedBlock>{spaceNl}{quote}{text}{quote} {
}
<ignoreBlock,ignoreEmbeddedBlock>{spaceNl}{schemeSymbol} {
}
<ignoreBlock,ignoreEmbeddedBlock>{spaceNl}{lbrac} {
yy_push_state(ignoreEmbeddedBlock);
}
<ignoreBlock,ignoreEmbeddedBlock>{spaceNl}{endOfSection} {
yy_pop_state();
}
<ignoreBlock,ignoreEmbeddedBlock>{spaceNl}{labelList} {
}
<ignoreBlock,ignoreEmbeddedBlock>{spaceNl}{hexLabelList} {
}
<ignoreBlock,ignoreEmbeddedBlock>{spaceNl}{scalarList} {
}
<ignoreBlock,ignoreEmbeddedBlock>{spaceNl}{schemeSymbolList} {
}
<ignoreBlock,ignoreEmbeddedBlock>{spaceNl}{text} {
}
/* ------ Ignore remaining space and \n s. ------ */
<*>{some_space}|\n {
}
/* ------ Any other characters are errors. ------ */
<*>. {
// This is a catch all.
FatalErrorIn("fluentMeshToFoam::lexer")
<< "Do not understand characters: " << YYText()
<< exit(FatalError);
}
/* ------ On EOF return to previous file, if none exists terminate. ------ */
<<EOF>> {
yyterminate();
}
%%
int main(int argc, char *argv[])
{
argList::noParallel();
argList::validArgs.append("Fluent mesh file");
argList::validOptions.insert("scale", "scale factor");
argList::validOptions.insert("ignoreCellGroups", "cell group names");
argList::validOptions.insert("ignoreFaceGroups", "face group names");
argList args(argc, argv);
if (!args.check())
{
FatalError.exit();
}
if (args.options().found("scale"))
{
scaleFactor = atof(args.options()["scale"].c_str());
}
HashSet<word> ignoreCellGroups;
if (args.options().found("ignoreCellGroups"))
{
IStringStream(args.options()["ignoreCellGroups"])() >> ignoreCellGroups;
}
HashSet<word> ignoreFaceGroups;
if (args.options().found("ignoreFaceGroups"))
{
IStringStream(args.options()["ignoreFaceGroups"])() >> ignoreFaceGroups;
}
# include "createTime.H"
fileName fluentFile(args.additionalArgs()[0]);
IFstream fluentStream(fluentFile);
if (!fluentStream)
{
FatalErrorIn(args.executable())
<< ": file " << fluentFile << " not found"
<< exit(FatalError);
}
yyFlexLexer lexer(&fluentStream.stdStream());
while(lexer.yylex() != 0);
Info<< "\nFINISHED LEXING\n\n";
if (dimensionOfGrid != 3)
{
FatalErrorIn(args.executable())
<< "Mesh is not 3D, dimension of grid: " << dimensionOfGrid
<< exit(FatalError);
}
pointGroupZoneID.shrink();
pointGroupStartIndex.shrink();
pointGroupEndIndex.shrink();
faceGroupZoneID.shrink();
faceGroupStartIndex.shrink();
faceGroupEndIndex.shrink();
cellGroupZoneID.shrink();
cellGroupStartIndex.shrink();
cellGroupEndIndex.shrink();
cellGroupType.shrink();
// Pre-filtering: flip "owner" boundary or wrong oriented internal
// faces and move to neighbour
forAll (faces, facei)
{
if
(
owner[facei] == -1
|| (neighbour[facei] != -1 && owner[facei] > neighbour[facei])
)
{
faces[facei] = faces[facei].reverseFace();
Swap(owner[facei], neighbour[facei]);
}
}
// Foam type for Fluent type
// ~~~~~~~~~~~~~~~~~~~~~~~~~
HashTable<word> fluentToFoamType;
fluentToFoamType.insert("pressure", polyPatch::typeName);
fluentToFoamType.insert("pressure-inlet", polyPatch::typeName);
fluentToFoamType.insert("inlet-vent", polyPatch::typeName);
fluentToFoamType.insert("intake-fan", polyPatch::typeName);
fluentToFoamType.insert("pressure-outlet", polyPatch::typeName);
fluentToFoamType.insert("exhaust-fan", polyPatch::typeName);
fluentToFoamType.insert("outlet-vent", polyPatch::typeName);
fluentToFoamType.insert("pressure-far-field", polyPatch::typeName);
fluentToFoamType.insert("velocity-inlet", polyPatch::typeName);
fluentToFoamType.insert("mass-flow-inlet", polyPatch::typeName);
fluentToFoamType.insert("outflow", polyPatch::typeName);
fluentToFoamType.insert("wall" , wallPolyPatch::typeName);
fluentToFoamType.insert("symmetry", symmetryPolyPatch::typeName);
fluentToFoamType.insert("axis", symmetryPolyPatch::typeName);
fluentToFoamType.insert("interior", polyPatch::typeName);
fluentToFoamType.insert("interface", polyPatch::typeName);
fluentToFoamType.insert("internal", polyPatch::typeName);
fluentToFoamType.insert("solid", polyPatch::typeName);
fluentToFoamType.insert("fan", cyclicPolyPatch::typeName);
fluentToFoamType.insert("radiator", polyPatch::typeName);
fluentToFoamType.insert("porous-jump", polyPatch::typeName);
// Foam patch type for Fluent zone type
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
HashSet<word> fluentGroupToFoamPatch;
fluentGroupToFoamPatch.insert("wall");
fluentGroupToFoamPatch.insert("fan");
// Create intial empty polyMesh
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
polyMesh mesh
(
IOobject
(
polyMesh::defaultRegion,
runTime.constant(),
runTime
),
pointField(0),
faceList(0),
labelList(0),
labelList(0)
);
// Check the cell groups for zones ignoring those in ignoreCellGroups
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
label nCellZones = 0;
labelList cellZoneIDs(cellGroupZoneID.size());
forAll(cellGroupZoneID, cgi)
{
if (!ignoreCellGroups.found(groupName[cellGroupZoneID[cgi] ]))
{
cellZoneIDs[nCellZones++] = cgi;
}
}
cellZoneIDs.setSize(nCellZones);
// Check the face groups for boundary patches, baffles and faceZones
// ignoring the interior zones in ignoreCellGroups
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
label nPatches = 0;
labelList patchIDs(faceGroupZoneID.size());
label nFaceZones = 0;
labelList faceZoneIDs(faceGroupZoneID.size());
forAll(faceGroupZoneID, fgi)
{
label zoneID = faceGroupZoneID[fgi];
label start = faceGroupStartIndex[fgi];
if (groupType.found(zoneID))
{
const word& type = groupType[zoneID];
// Check the first element of neighbour for boundary group
if (neighbour[start] == -1 || fluentGroupToFoamPatch.found(type))
{
patchIDs[nPatches++] = fgi;
}
else
{
if (!ignoreFaceGroups.found(groupName[faceGroupZoneID[fgi] ]))
{
faceZoneIDs[nFaceZones++] = fgi;
}
}
}
else if (hangingNodes)
{
label end = faceGroupEndIndex[fgi];
Info<< "Unknown FaceGroup " << zoneID
<< " assumed to be parent faces of refinement "
"patterns and ignored."
<< endl;
// Set the owner of these faces to -1 so that they do not get
// added to the mesh
for(label facei = start; facei <= end; facei++)
{
owner[facei] = -1;
}
}
else
{
FatalErrorIn(args.executable())
<< "Unknown FaceGroup " << zoneID << " not in a zone"
<< exit(FatalError);
}
}
patchIDs.setSize(nPatches);
faceZoneIDs.setSize(nFaceZones);
// Add empty patches
// ~~~~~~~~~~~~~~~~~
List<polyPatch*> newPatches(nPatches);
HashSet<word> patchNames;
forAll(patchIDs, patchi)
{
label zoneID = faceGroupZoneID[patchIDs[patchi] ];
word name = groupName[zoneID];
const word& type = groupType[zoneID];
Info<< "Creating patch " << patchi
<< " for zone: " << zoneID
<< " name: " << name
<< " type: " << type
<< endl;
uniquify(name, patchNames);
HashTable<word>::const_iterator iter = fluentToFoamType.find(type);
if (iter != fluentToFoamType.end())
{
newPatches[patchi] = polyPatch::New
(
iter(),
name,
0,
0,
patchi,
mesh.boundaryMesh()
).ptr();
}
else
{
Info<< "Adding polyPatch for unknown Fluent type " << type
<< endl;
newPatches[patchi] = new polyPatch
(
name,
0,
0,
patchi,
mesh.boundaryMesh()
);
}
}
mesh.addPatches(newPatches);
// Add empty zones
// ~~~~~~~~~~~~~~~
// Cell zones
mesh.cellZones().setSize(cellZoneIDs.size());
HashSet<word> cellZoneNames;
forAll(cellZoneIDs, cellZonei)
{
label zoneID = cellGroupZoneID[cellZoneIDs[cellZonei] ];
word name = groupName[zoneID];
const word& type = groupType[zoneID];
Info<< "Creating cellZone " << cellZonei
<< " name: " << name
<< " type: " << type
<< endl;
uniquify(name, cellZoneNames);
mesh.cellZones().set
(
cellZonei,
new cellZone
(
name,
labelList(0),
cellZonei,
mesh.cellZones()
)
);
}
// Face zones
mesh.faceZones().setSize(nFaceZones);
HashSet<word> faceZoneNames;
forAll(faceZoneIDs, faceZonei)
{
label zoneID = faceGroupZoneID[faceZoneIDs[faceZonei] ];
word name = groupName[zoneID];
const word& type = groupType[zoneID];
Info<< "Creating faceZone " << faceZonei
<< " name: " << name
<< " type: " << type
<< endl;
uniquify(name, faceZoneNames);
mesh.faceZones().set
(
faceZonei,
new faceZone
(
name,
labelList(0),
boolList(0),
faceZonei,
mesh.faceZones()
)
);
}
// Modify mesh for points/cells/faces
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Mesh-change container
polyTopoChange meshMod(mesh, false);
// Add all points
forAll(points, pointi)
{
meshMod.addPoint(points[pointi], pointi, -1, true);
}
points.setSize(0);
// Add all cells
for (label celli = 0; celli < nCells; celli++)
{
meshMod.addCell
(
-1, // masterPointID
-1, // masterEdgeID
-1, // masterFaceID
celli, // masterCellID
-1 // zoneID
);
}
// Modify cells to be in zones as required
forAll(cellZoneIDs, cellZonei)
{
label cgi = cellZoneIDs[cellZonei];
for
(
label celli = cellGroupStartIndex[cgi];
celli <= cellGroupEndIndex[cgi];
celli++
)
{
meshMod.modifyCell(celli, cellZonei);
}
}
// Add faceZone faces
forAll(faceZoneIDs, faceZonei)
{
label fgi = faceZoneIDs[faceZonei];
label start = faceGroupStartIndex[fgi];
label end = faceGroupEndIndex[fgi];
label zoneID = faceGroupZoneID[fgi];
Info<< "faceZone from Fluent indices: " << start
<< " to: " << end
<< " type: " << groupType[zoneID]
<< endl;
for (label facei = start; facei <= end; facei++)
{
meshMod.addFace
(
faces[facei],
owner[facei],
neighbour[facei],
-1, // masterPointID
-1, // masterEdgeID
facei, // masterFace
false, // flipFaceFlux
-1, // patchID
faceZonei, // zoneID
false // zoneFlip
);
// Mark face as being done
owner[facei] = -1;
}
}
// Add patch faces
forAll(patchIDs, patchi)
{
label fgi = patchIDs[patchi];
label start = faceGroupStartIndex[fgi];
label end = faceGroupEndIndex[fgi];
label zoneID = faceGroupZoneID[fgi];
Info<< "patch " << patchi << " from Fluent indices: " << start
<< " to: " << end
<< " type: " << groupType[zoneID]
<< endl;
for (label facei = start; facei <= end; facei++)
{
meshMod.addFace
(
faces[facei],
owner[facei],
-1,
-1, // masterPointID
-1, // masterEdgeID
facei, // masterFace
false, // flipFaceFlux
patchi, // patchID
-1, // zoneID
false // zoneFlip
);
// For baffles create the opposite face
if (neighbour[start] != -1)
{
meshMod.addFace
(
faces[facei].reverseFace(),
neighbour[facei],
-1,
-1, // masterPointID
-1, // masterEdgeID
facei, // masterFace
false, // flipFaceFlux
patchi, // patchID
-1, // zoneID
false // zoneFlip
);
}
// Mark face as being done
owner[facei] = -1;
}
}
// Add remaining internal faces
forAll(owner, facei)
{
if (owner[facei] != -1)
{
// Check the face being added as an internal face actually is one
if (neighbour[facei] == -1)
{
FatalErrorIn(args.executable())
<< "Attempt of add internal face " << facei
<< " which is a boundary face"
<< exit(FatalError);
}
meshMod.addFace
(
faces[facei],
owner[facei],
neighbour[facei],
-1, //masterPointID
-1, //masterEdgeID
facei, //masterFace
false, //flipFaceFlux
-1, //patchID
-1, //zoneID
false //zoneFlip
);
}
}
// Reclaim storage
faces.setSize(0);
owner.setSize(0);
neighbour.setSize(0);
// Modify mesh
// ~~~~~~~~~~~
autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false);
// Zip-up the mesh if it contained hanging nodes
if (hangingNodes)
{
Info<< "Zipping mesh to remove hanging nodes" << endl;
polyMeshZipUpCells(mesh);
}
mesh.setInstance(runTime.constant());
// Set the precision of the points data to 10
IOstream::defaultPrecision(10);
Info<< nl << "Writing mesh to " << mesh.objectPath() << endl;
mesh.write();
Info<< nl << "End" << endl;
return 0;
}
/* ------------------------------------------------------------------------ *\
------ End of fluentMeshToFoam.L
\* ------------------------------------------------------------------------ */