Forward compatibility: flex
[foam-extend-3.2.git] / applications / utilities / mesh / conversion / fluent3DMeshToFoam / fluent3DMeshToFoam.L
blob8ec08bbeecb5fc6e366ef29ea69ed8e13a92871a
1 /*--------------------------------*- C++ -*----------------------------------*\
2   =========                 |
3   \\      /  F ield         | foam-extend: Open Source CFD
4    \\    /   O peration     | Version:     3.2
5     \\  /    A nd           | Web:         http://www.foam-extend.org
6      \\/     M anipulation  | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
8 License
9     This file is part of foam-extend.
11     foam-extend is free software: you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by the
13     Free Software Foundation, either version 3 of the License, or (at your
14     option) any later version.
16     foam-extend is distributed in the hope that it will be useful, but
17     WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19     General Public License for more details.
21     You should have received a copy of the GNU General Public License
22     along with foam-extend.  If not, see <http://www.gnu.org/licenses/>.
24 Application
25     fluent3DMeshToFoam
27 Description
28     Converts a Fluent mesh to FOAM format.
30 \*---------------------------------------------------------------------------*/
33 #undef yyFlexLexer
35  /* ------------------------------------------------------------------------ *\
36    ------ local definitions
37  \* ------------------------------------------------------------------------ */
39 #include "argList.H"
40 #include "objectRegistry.H"
41 #include "foamTime.H"
42 #include "polyMesh.H"
43 #include "directTopoChange.H"
44 #include "polyMeshZipUpCells.H"
45 #include "wallPolyPatch.H"
46 #include "symmetryPolyPatch.H"
47 #include "cyclicPolyPatch.H"
48 #include "Swap.H"
49 #include "IFstream.H"
50 #include "wordIOList.H"
51 #include "readHexLabel.H"
53 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
55 using namespace Foam;
57 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
59 // Line number
60 label lineNo = 1;
62 // Scale factor used to scale points (optional command line argument)
63 scalar scaleFactor = 1.0;
65 label dimensionOfGrid = 0;
66 label nPoints = 0;
67 label nFaces = 0;
68 label nCells = 0;
70 bool hangingNodes = false;
72 pointField points(0);
73 faceList faces(0);
74 labelList owner(0);
75 labelList neighbour(0);
77 // Group type and name
78 Map<word> groupType(100);
79 Map<word> groupName(100);
81 // Point groups
82 DynamicList<label> pointGroupZoneID;
83 DynamicList<label> pointGroupStartIndex;
84 DynamicList<label> pointGroupEndIndex;
86 // Face groups
87 DynamicList<label> faceGroupZoneID;
88 DynamicList<label> faceGroupStartIndex;
89 DynamicList<label> faceGroupEndIndex;
91 // Cell groups
92 DynamicList<label> cellGroupZoneID;
93 DynamicList<label> cellGroupStartIndex;
94 DynamicList<label> cellGroupEndIndex;
95 DynamicList<label> cellGroupType;
97 // Special parsing of (incorrect) Cubit files
98 bool cubitFile = false;
101 void uniquify(word& name, HashSet<word>& patchNames)
103     if (!patchNames.found(name))
104     {
105         patchNames.insert(name);
106     }
107     else
108     {
109         Info<< "    name " << name << " already used";
111         label i = 1;
112         word baseName = name;
114         do
115         {
116             name = baseName + "_" + Foam::name(i++);
117         } while (patchNames.found(name));
119         Info<< ", changing to " << name << endl;
120     }
124 // Dummy yywrap to keep yylex happy at compile time.
125 // It is called by yylex but is not used as the mechanism to change file.
126 // See <<EOF>>
127 #if YY_FLEX_MINOR_VERSION < 6 && YY_FLEX_SUBMINOR_VERSION < 34
128 extern "C" int yywrap()
129 #else
130 int yyFlexLexer::yywrap()
131 #endif
133     return 1;
138 one_space                  [ \t\f]
139 space                      {one_space}*
140 some_space                 {one_space}+
141 cspace                     ","{space}
143 alpha                      [_[:alpha:]]
144 digit                      [[:digit:]]
145 decDigit                   [[:digit:]]
146 octalDigit                 [0-7]
147 hexDigit                   [[:xdigit:]]
149 lbrac                      "("
150 rbrac                      ")"
151 quote                      \"
152 dash                       "-"
153 dotColonDash               [.:-]
155 schemeSpecialInitial       [!$%&*/\\:<=>?~_^#.@']
156 schemeSpecialSubsequent    [.+-]
157 schemeSymbol               (({some_space}|{alpha}|{quote}|{schemeSpecialInitial})({alpha}|{quote}|{digit}|{schemeSpecialInitial}|{schemeSpecialSubsequent})*)
160 identifier                 {alpha}({alpha}|{digit})*
161 integer                    {decDigit}+
162 label                      [1-9]{decDigit}*
163 hexLabel                   {hexDigit}+
164 zeroLabel                  {digit}*
165 signedInteger              [-+]?{integer}
166 word                       ({alpha}|{digit}|{dotColonDash})*
168 exponent_part              [eE][-+]?{digit}+
169 fractional_constant        [-+]?(({digit}*"."{digit}+)|({digit}+".")|({digit}))
171 double                     ((({fractional_constant}{exponent_part}?)|({digit}+{exponent_part}))|0)
173 x                          {double}
174 y                          {double}
175 z                          {double}
176 scalar                     {double}
177 labelListElement           {space}{zeroLabel}
178 hexLabelListElement        {space}{hexLabel}
179 scalarListElement          {space}{double}
180 schemeSymbolListElement    {space}{schemeSymbol}
181 labelList                  ({labelListElement}+{space})
182 hexLabelList               ({hexLabelListElement}+{space})
183 scalarList                 ({scalarListElement}+{space})
184 schemeSymbolList           ({schemeSymbolListElement}+{space})
186 starStar                   ("**")
187 text                       ({space}({word}*{space})*)
188 anythingInBlock            ([^)]*)
189 gridgenComment             (({space}|{cspace})({word}*{space})*)
191 dateDDMMYYYY               ({digit}{digit}"/"{digit}{digit}"/"{digit}{digit}{digit}{digit})
192 dateDDMonYYYY              ((({digit}{digit}{space})|({digit}{space})){alpha}*{space}{digit}{digit}{digit}{digit})
193 time                       ({digit}{digit}":"{digit}{digit}":"{digit}{digit})
195 versionNumber              ({digit}|".")*
197 header                     {space}"(1"{space}
198 dimension                  {space}"(2"{space}
199 points                     {space}"(10"{space}
200 faces                      {space}"(13"{space}
201 cells                      {space}"(12"{space}
202 zoneVariant1               {space}"(39"{space}
203 zoneVariant2               {space}"(45"{space}
204 faceTree                   {space}"(59"{space}
206 comment                    "0"{space}
207 unknownPeriodicFace        "17"{space}
208 periodicFace               "18"{space}
209 cellTree                   "58"{space}
210 faceParents                "61"{space}
211 ignoreBlocks               ("4"|"37"|"38"|"40"|"41"|"60"|"64"){space}
213 redundantBlock             {space}({comment}|{unknownPeriodicFace}|{periodicFace}|{cellTree}|{faceParents}|{ignoreBlocks}){space}
215 endOfSection               {space}")"{space}
219  /* ------------------------------------------------------------------------ *\
220                       -----  Exclusive start states -----
221  \* ------------------------------------------------------------------------ */
223 %option stack
225 %x readHeader
226 %x readDimension
227 %x readPoint
228 %x readPointHeader
229 %x readNumberOfPoints
230 %x readPointGroupData
231 %x readPointData
232 %x readScalarList
233 %x fluentFace
234 %x readFaceHeader
235 %x readNumberOfFaces
236 %x readFaceGroupData
237 %x readFaceData
238 %x readFacesMixed
239 %x readFacesUniform
240 %x cell
241 %x readCellHeader
242 %x readNumberOfCells
243 %x readCellGroupData
244 %x readCellData
245 %x readCellsUniform
246 %x zone
247 %x readZoneHeader
248 %x readZoneGroupData
249 %x readZoneData
250 %x readZoneBlock
252 %x ignoreBlock
253 %x ignoreEmbeddedBlock
257     // End of read character pointer returned by strtol and strtod
258     char* endPtr;
260     // Point data
261     label pointGroupNumberOfComponents = 3;
262     label pointi = 0; // index used for reading points
263     label cmpt = 0;   // component index used for reading points
265     // Face data
266     label faceGroupElementType = -1;
267     label facei = 0;  // index used for reading faces
271  /* ------------------------------------------------------------------------ *\
272                             ------ Start Lexing ------
273  \* ------------------------------------------------------------------------ */
275  /*                      ------ Reading control header ------                */
277 {header} {
278         BEGIN(readHeader);
279     }
281 <readHeader>{anythingInBlock} {
282         Info<< "Header: " << YYText() << endl;
283     }
286 {dimension} {
287         BEGIN(readDimension);
288     }
290 <readDimension>{space}{label}{space} {
291         dimensionOfGrid = atoi(YYText());
292         Info<< "Dimension of grid: " << dimensionOfGrid << endl;
293     }
296 {points} {
297         BEGIN(readPointHeader);
298     }
300 <readPointHeader>{space}{lbrac}{space}"0"{space}"1"{space} {
301         BEGIN(readNumberOfPoints);
302     }
304 <readNumberOfPoints>{hexLabel}{space}{labelList} {
305         nPoints = strtol(YYText(), &endPtr, 16);
306         Info<< "Number of points: " << nPoints << endl;
307         points.setSize(nPoints);
309         // Ignore rest of stream
310     }
312 <readPointHeader>{space}{lbrac} {
313         BEGIN(readPointGroupData);
314     }
316 <readPointGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{labelList} {
317         // Read point zone-ID, start and end-label
318         // the indices will be used for checking later.
319         pointGroupZoneID.append(strtol(YYText(), &endPtr, 16));
321         // In FOAM, indices start from zero - adjust
322         pointGroupStartIndex.append(strtol(endPtr, &endPtr, 16) - 1);
324         pointGroupEndIndex.append(strtol(endPtr, &endPtr, 16) - 1);
326         // point group type skipped
327         strtol(endPtr, &endPtr, 16);
329         pointi = pointGroupStartIndex[pointGroupStartIndex.size()-1];
331         // reset number of components to default
332         pointGroupNumberOfComponents = 3;
334         // read number of components in the vector
335         if (endPtr < &(YYText()[YYLeng()-1]))
336         {
337             pointGroupNumberOfComponents = strtol(endPtr, &endPtr, 16);
338         }
340         Info<< "PointGroup: "
341             << pointGroupZoneID[pointGroupZoneID.size()-1]
342             << " start: "
343             << pointGroupStartIndex[pointGroupStartIndex.size()-1]
344             << " end: "
345             << pointGroupEndIndex[pointGroupEndIndex.size()-1]
346             << " nComponents: " << pointGroupNumberOfComponents << flush;
347     }
349 <readNumberOfPoints,readPointGroupData>{endOfSection} {
350         BEGIN(readPointData);
351     }
353 <readPointData>{space}{lbrac}{space} {
354         Info<< ".  Reading points..." << flush;
355         cmpt = 0;
356         yy_push_state(readScalarList);
357     }
359 <readScalarList>{signedInteger}{space} {
360         points[pointi][cmpt++] = scaleFactor*atol(YYText());
362         if (cmpt == pointGroupNumberOfComponents)
363         {
364             if (pointGroupNumberOfComponents == 2)
365             {
366                 points[pointi].z() = 0.0;
367             }
369             cmpt = 0;
370             pointi++;
371         }
372     }
374 <readScalarList>{scalar}{space} {
375         points[pointi][cmpt++] = scaleFactor*atof(YYText());
377         if (cmpt == pointGroupNumberOfComponents)
378         {
379             if (pointGroupNumberOfComponents == 2)
380             {
381                 points[pointi].z() = 0.0;
382             }
384             cmpt = 0;
385             pointi++;
386         }
387     }
389 <readScalarList>{endOfSection} {
390         Info<< "done." << endl;
392         // check read of points
393         if (pointi != pointGroupEndIndex[pointGroupEndIndex.size()-1]+1)
394         {
395             Warning
396                 << "Problem with reading points: " << nl
397                 << "    start index: "
398                 << pointGroupStartIndex[pointGroupStartIndex.size()-1]
399                 << " end index: "
400                 << pointGroupEndIndex[pointGroupEndIndex.size()-1]
401                 << " last points read: " << pointi << nl
402                 << "    on line " << lineNo << endl;
403         }
405         yy_pop_state();
406     }
408 {faces} {
409         BEGIN(readFaceHeader);
410     }
412 <readFaceHeader>{space}{lbrac}{space}"0"{space}"1"{space} {
413         BEGIN(readNumberOfFaces);
414     }
416 <readNumberOfFaces>{space}{hexLabel}{space}{labelListElement}+ {
417         nFaces = strtol(YYText(), &endPtr, 16);
419         Info<< "Number of faces: " << nFaces << endl;
421         faces.setSize(nFaces);
422         owner.setSize(nFaces);
423         neighbour.setSize(nFaces);
425         // Type and element type not read
426     }
428 <readFaceHeader>{space}{lbrac} {
429         BEGIN(readFaceGroupData);
430     }
432 <readFaceGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{hexLabelListElement}+ {
433         // read fluentFace zone-ID, start and end-label
434         faceGroupZoneID.append(strtol(YYText(), &endPtr, 16));
436         // In FOAM, indices start from zero - adjust
437         faceGroupStartIndex.append(strtol(endPtr, &endPtr, 16) - 1);
439         faceGroupEndIndex.append(strtol(endPtr, &endPtr, 16) - 1);
441         // face group type
442         strtol(endPtr, &endPtr, 16);
444         faceGroupElementType = strtol(endPtr, &endPtr, 16);
446         facei = faceGroupStartIndex[faceGroupStartIndex.size()-1];
448         Info<< "FaceGroup: "
449             << faceGroupZoneID[faceGroupZoneID.size()-1]
450             << " start: "
451             << faceGroupStartIndex[faceGroupStartIndex.size()-1]
452             << " end: "
453             << faceGroupEndIndex[faceGroupEndIndex.size()-1] << flush;
454     }
456 <readNumberOfFaces,readFaceGroupData>{space}{endOfSection} {
457         BEGIN(readFaceData);
458     }
460 <readFaceData>{space}{lbrac} {
461         if (faceGroupElementType == 0 || faceGroupElementType > 4)
462         {
463             Info<< ".  Reading mixed faces..." << flush;
464             yy_push_state(readFacesMixed);
465         }
466         else
467         {
468             Info<< ".  Reading uniform faces..." << flush;
469             yy_push_state(readFacesUniform);
470         }
471     }
473 <readFacesMixed>{space}{hexLabelList} {
474         face& curFaceLabels = faces[facei];
476         // set size of label list
477         curFaceLabels.setSize(strtol(YYText(), &endPtr, 16));
479         forAll (curFaceLabels, i)
480         {
481             curFaceLabels[i] = strtol(endPtr, &endPtr, 16) - 1;
482         }
484         // read neighbour and owner. Neighbour comes first
485         neighbour[facei] = strtol(endPtr, &endPtr, 16) - 1;
486         owner[facei] = strtol(endPtr, &endPtr, 16) - 1;
487         facei++;
488     }
490 <readFacesUniform>{space}{hexLabelList} {
491         face& curFaceLabels = faces[facei];
493         // Set size of label list.
494         curFaceLabels.setSize(faceGroupElementType);
496         curFaceLabels[0] = strtol(YYText(), &endPtr, 16) - 1;
498         for (int i=1; i<faceGroupElementType; i++)
499         {
500             curFaceLabels[i] = strtol(endPtr, &endPtr, 16) - 1;
501         }
503         // read neighbour and owner. Neighbour comes first
504         neighbour[facei] = strtol(endPtr, &endPtr, 16) - 1;
505         owner[facei] = strtol(endPtr, &endPtr, 16) - 1;
506         facei++;
507     }
509 <readFacesMixed,readFacesUniform>{space}{endOfSection} {
510         Info<< "done." << endl;
512         // check read of fluentFaces
513         if (facei != faceGroupEndIndex[faceGroupEndIndex.size()-1]+1)
514         {
515             Warning
516                 << "Problem with reading fluentFaces: " << nl
517                 << "    start index: "
518                 << faceGroupStartIndex[faceGroupStartIndex.size()-1]
519                 << " end index: "
520                 << faceGroupEndIndex[faceGroupEndIndex.size()-1]
521                 << " last fluentFaces read: " << facei << nl
522                 << "    on line " << lineNo << endl;
523         }
525         yy_pop_state();
526     }
529 {cells} {
530         BEGIN(readCellHeader);
531     }
533 <readCellHeader>{space}{lbrac}{space}"0"{space}"1"{space} {
534         BEGIN(readNumberOfCells);
535     }
537 <readNumberOfCells>{space}{hexLabel}{space}{labelListElement}+ {
538         nCells = strtol(YYText(), &endPtr, 16);
539         Info<< "Number of cells: " << nCells << endl;
540     }
542 <readCellHeader>{space}{lbrac} {
543         BEGIN(readCellGroupData);
544     }
546 <readCellGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{space}{hexLabel} {
547         // Warning. This entry must be above the next one because of the lexing
548         // rules. It is introduced to deal with the problem of reading
549         // non-standard cell definition from Tgrid, which misses the type label.
551         Warning
552             << "Tgrid syntax problem: " << YYText() << nl
553             << "    on line " << lineNo << endl;
555         // read cell zone-ID, start and end-label
556         cellGroupZoneID.append(strtol(YYText(), &endPtr, 16));
558         // the indices will be used for checking later.
559         cellGroupStartIndex.append(strtol(endPtr, &endPtr, 16) - 1);
561         cellGroupEndIndex.append(strtol(endPtr, &endPtr, 16) - 1);
563         cellGroupType.append(strtol(endPtr, &endPtr, 16));
565         Info<< "CellGroup: "
566             << cellGroupZoneID[cellGroupZoneID.size()-1]
567             << " start: "
568             << cellGroupStartIndex[cellGroupStartIndex.size()-1]
569             << " end: "
570             << cellGroupEndIndex[cellGroupEndIndex.size()-1]
571             << " type: "
572             << cellGroupType[cellGroupType.size()-1]
573             << endl;
574     }
576 <readCellGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{space}{hexLabel} {
577         // Warning. See above
579         // read cell zone-ID, start and end-label
580         cellGroupZoneID.append(strtol(YYText(), &endPtr, 16));
582         // the indices will be used for checking later.
583         cellGroupStartIndex.append(strtol(endPtr, &endPtr, 16) - 1);
585         cellGroupEndIndex.append(strtol(endPtr, &endPtr, 16) - 1);
587         cellGroupType.append(strtol(endPtr, &endPtr, 16));
589         // Note. Potentially skip cell set if type is zero.
590         strtol(endPtr, &endPtr, 16);
592         Info<< "CellGroup: "
593             << cellGroupZoneID[cellGroupZoneID.size()-1]
594             << " start: "
595             << cellGroupStartIndex[cellGroupStartIndex.size()-1]
596             << " end: "
597             << cellGroupEndIndex[cellGroupEndIndex.size()-1]
598             << " type: "
599             << cellGroupType[cellGroupType.size()-1]
600             << endl;
601     }
603 <readNumberOfCells,readCellGroupData>{endOfSection} {
604         BEGIN(readCellData);
605     }
607 <readCellData>{space}{lbrac} {
608         // Quickly scan to the end of the cell data block and discard
609         register int c;
610         while ((c = yyinput()) != 0 && c != ')')
611         {}
612     }
614 {faceTree} {
615         // There are hanging nodes in the mesh so make sure it gets zipped-up
616         hangingNodes = true;
617         yy_push_state(ignoreBlock);
618     }
620 {zoneVariant1} {
621         BEGIN(readZoneHeader);
622     }
624 {zoneVariant2} {
625         BEGIN(readZoneHeader);
626     }
628 <readZoneHeader>{space}{lbrac} {
629         BEGIN(readZoneGroupData);
630     }
632 <readZoneGroupData>{space}{hexLabel}{space}{word}{space}{word}{space}{label}? {
633         IStringStream zoneDataStream(YYText());
635         // cell zone-ID not in hexadecimal!!! Inconsistency
636         label zoneID = -1;
638         if (cubitFile)
639         {
640             zoneID = readHexLabel(zoneDataStream);
641         }
642         else
643         {
644             zoneID = readLabel(zoneDataStream);
645         }
647         groupType.insert(zoneID, word(zoneDataStream));
648         groupName.insert(zoneID, word(zoneDataStream));
650         Info<< "Zone: " << zoneID
651             << " name: " << groupName[zoneID]
652             << " type: " << groupType[zoneID] << flush;
653     }
655 <readZoneGroupData>{endOfSection} {
656         BEGIN(readZoneData);
657     }
659 <readZoneData>{space}{lbrac} {
660         Info<< ".  Reading zone data..." << flush;
661         yy_push_state(readZoneBlock);
662     }
664 <readZoneBlock>{space}{schemeSymbolList} {
665     }
667 <readZoneBlock>{lbrac} {
668         //Warning
669         //    << "Found unknown block in zone: " << YYText() << nl
670         //    << "    on line " << lineNo << endl;
671         yy_push_state(ignoreBlock);
672     }
674 <readZoneBlock>{endOfSection} {
675         Info<< "done." << endl;
676         yy_pop_state();
677     }
681  /*             ------ Reading end of section and others ------              */
683 <readHeader,readDimension,readPointData,readFaceData,readCellData,readZoneData>{space}{endOfSection} {
684         BEGIN(INITIAL);
685     }
687  /*    ------ Reading unknown type or non-standard comment ------            */
689 {lbrac}{label} {
690         Warning
691             << "Found unknown block of type: "
692             << Foam::string(YYText())(1, YYLeng()-1) << nl
693             << "    on line " << lineNo << endl;
695         yy_push_state(ignoreBlock);
696     }
698 {lbrac}{redundantBlock} {
699         yy_push_state(ignoreBlock);
700     }
702 <ignoreBlock,ignoreEmbeddedBlock>{space}{quote}{text}{quote} {
703     }
705 <ignoreBlock,ignoreEmbeddedBlock>{space}{schemeSymbol} {
706     }
708 <ignoreBlock,ignoreEmbeddedBlock>{space}{lbrac} {
709         yy_push_state(ignoreEmbeddedBlock);
711     }
713 <ignoreBlock,ignoreEmbeddedBlock>{space}{endOfSection} {
714         yy_pop_state();
715     }
717 <ignoreBlock,ignoreEmbeddedBlock>{space}{labelList} {
718     }
720 <ignoreBlock,ignoreEmbeddedBlock>{space}{hexLabelList} {
721     }
723 <ignoreBlock,ignoreEmbeddedBlock>{space}{scalarList} {
724     }
726 <ignoreBlock,ignoreEmbeddedBlock>{space}{schemeSymbolList} {
727     }
729 <ignoreBlock,ignoreEmbeddedBlock>{space}{text} {
730     }
732 <ignoreBlock,ignoreEmbeddedBlock>{gridgenComment} {
733     }
736  /* ------              Count newlines.                              ------  */
738 <*>\n {
739         lineNo++;
740     }
743  /* ------              Ignore remaining space.                      ------  */
745 <*>{some_space}|\r {
746     }
749  /* ------              Any other characters are errors.              ------ */
751 <*>. {
752         // This is a catch all.
753         FatalErrorIn("fluentMeshToFoam::lexer")
754             << "Do not understand characters: " << YYText() << nl
755             << "    on line " << lineNo
756             << exit(FatalError);
757     }
760  /*  ------ On EOF return to previous file, if none exists terminate. ------ */
762 <<EOF>> {
763             yyterminate();
764     }
767 int main(int argc, char *argv[])
769     argList::noParallel();
770     argList::validArgs.append("Fluent mesh file");
771     argList::validOptions.insert("scale", "scale factor");
772     argList::validOptions.insert("ignoreCellGroups", "cell group names");
773     argList::validOptions.insert("ignoreFaceGroups", "face group names");
774     argList::validOptions.insert("cubit", "");
776     argList args(argc, argv);
778     if (!args.check())
779     {
780         FatalError.exit();
781     }
783     args.optionReadIfPresent("scale", scaleFactor);
785     HashSet<word> ignoreCellGroups;
786     if (args.optionFound("ignoreCellGroups"))
787     {
788         args.optionLookup("ignoreCellGroups")() >> ignoreCellGroups;
789     }
791     HashSet<word> ignoreFaceGroups;
792     if (args.optionFound("ignoreFaceGroups"))
793     {
794         args.optionLookup("ignoreFaceGroups")() >> ignoreFaceGroups;
795     }
797     cubitFile = args.options().found("cubit");
799     if (cubitFile)
800     {
801         Info<< nl
802             << "Assuming Cubit generated file"
803             << " (incorrect face orientation; hexadecimal zoneIDs)."
804             << nl << endl;
805     }
807 #   include "createTime.H"
809     fileName fluentFile(args.additionalArgs()[0]);
810     IFstream fluentStream(fluentFile);
812     if (!fluentStream)
813     {
814         FatalErrorIn(args.executable())
815             << ": file " << fluentFile << " not found"
816             << exit(FatalError);
817     }
819     yyFlexLexer lexer(&fluentStream.stdStream());
821     while(lexer.yylex() != 0)
822     {}
824     Info<< "\nFINISHED LEXING\n\n";
826     if (dimensionOfGrid != 3)
827     {
828         FatalErrorIn(args.executable())
829             << "Mesh is not 3D, dimension of grid: " << dimensionOfGrid
830             << exit(FatalError);
831     }
833     pointGroupZoneID.shrink();
834     pointGroupStartIndex.shrink();
835     pointGroupEndIndex.shrink();
837     faceGroupZoneID.shrink();
838     faceGroupStartIndex.shrink();
839     faceGroupEndIndex.shrink();
841     cellGroupZoneID.shrink();
842     cellGroupStartIndex.shrink();
843     cellGroupEndIndex.shrink();
844     cellGroupType.shrink();
847     // Pre-filtering: flip "owner" boundary or wrong oriented internal
848     // faces and move to neighbour
850     boolList fm(faces.size(), false);
851     forAll (faces, facei)
852     {
853         if
854         (
855             owner[facei] == -1
856          || (neighbour[facei] != -1 && owner[facei] > neighbour[facei])
857         )
858         {
859             fm[facei] = true;
860             if (!cubitFile)
861             {
862                 faces[facei] = faces[facei].reverseFace();
863             }
864             Swap(owner[facei], neighbour[facei]);
865         }
866     }
869     // Foam type for Fluent type
870     // ~~~~~~~~~~~~~~~~~~~~~~~~~
872     HashTable<word> fluentToFoamType;
874     fluentToFoamType.insert("pressure", polyPatch::typeName);
875     fluentToFoamType.insert("pressure-inlet", polyPatch::typeName);
876     fluentToFoamType.insert("inlet-vent", polyPatch::typeName);
877     fluentToFoamType.insert("intake-fan", polyPatch::typeName);
878     fluentToFoamType.insert("pressure-outlet", polyPatch::typeName);
879     fluentToFoamType.insert("exhaust-fan", polyPatch::typeName);
880     fluentToFoamType.insert("outlet-vent", polyPatch::typeName);
881     fluentToFoamType.insert("pressure-far-field", polyPatch::typeName);
882     fluentToFoamType.insert("velocity-inlet", polyPatch::typeName);
883     fluentToFoamType.insert("mass-flow-inlet", polyPatch::typeName);
884     fluentToFoamType.insert("outflow", polyPatch::typeName);
886     fluentToFoamType.insert("wall" , wallPolyPatch::typeName);
888     fluentToFoamType.insert("symmetry",  symmetryPolyPatch::typeName);
889     fluentToFoamType.insert("axis",  symmetryPolyPatch::typeName);
891     fluentToFoamType.insert("interior", polyPatch::typeName);
892     fluentToFoamType.insert("interface", polyPatch::typeName);
893     fluentToFoamType.insert("internal", polyPatch::typeName);
894     fluentToFoamType.insert("solid", polyPatch::typeName);
895     fluentToFoamType.insert("fan", cyclicPolyPatch::typeName);
896     fluentToFoamType.insert("radiator", polyPatch::typeName);
897     fluentToFoamType.insert("porous-jump", polyPatch::typeName);
900     // Foam patch type for Fluent zone type
901     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
903     HashSet<word> fluentGroupToFoamPatch;
904     fluentGroupToFoamPatch.insert("wall");
905     fluentGroupToFoamPatch.insert("fan");
908     // Create intial empty polyMesh
909     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
911     polyMesh mesh
912     (
913         IOobject
914         (
915             polyMesh::defaultRegion,
916             runTime.constant(),
917             runTime
918         ),
919         xferCopy(pointField()),
920         xferCopy(faceList()),
921         xferCopy(labelList()),
922         xferCopy(labelList())
923     );
926     // Check the cell groups for zones ignoring those in ignoreCellGroups
927     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
928     label nCellZones = 0;
929     labelList cellZoneIDs(cellGroupZoneID.size());
931     forAll(cellGroupZoneID, cgi)
932     {
933         if (!ignoreCellGroups.found(groupName[cellGroupZoneID[cgi] ]))
934         {
935             cellZoneIDs[nCellZones++] = cgi;
936         }
937     }
939     cellZoneIDs.setSize(nCellZones);
942     // Check the face groups for boundary patches, baffles and faceZones
943     // ignoring the interior zones in ignoreCellGroups
944     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
945     DynamicList<label> patchIDs(faceGroupZoneID.size());
946     DynamicList<label> faceZoneIDs(faceGroupZoneID.size());
948     forAll(faceGroupZoneID, fgi)
949     {
950         label zoneID = faceGroupZoneID[fgi];
951         label start = faceGroupStartIndex[fgi];
953         if (groupType.found(zoneID))
954         {
955             const word& type = groupType[zoneID];
957             // Check the first element of neighbour for boundary group
958             if (neighbour[start] == -1 || fluentGroupToFoamPatch.found(type))
959             {
960                 patchIDs.append(fgi);
961             }
962             else
963             {
964                 if (!ignoreFaceGroups.found(groupName[faceGroupZoneID[fgi] ]))
965                 {
966                     faceZoneIDs.append(fgi);
967                 }
968             }
969         }
970         else if (hangingNodes)
971         {
972             label end = faceGroupEndIndex[fgi];
974             Info<< "Unknown FaceGroup " << zoneID
975                 << " assumed to be parent faces of refinement "
976                    "patterns and ignored."
977                 << endl;
979             // Set the owner of these faces to -1 so that they do not get
980             // added to the mesh
981             for(label facei = start; facei <= end; facei++)
982             {
983                 owner[facei] = -1;
984             }
985         }
986         else
987         {
988             if (neighbour[start] == -1)
989             {
990                 // Boundary face in unknown group. Create a patch for it.
991                 groupType.insert(zoneID, "unknown");
992                 groupName.insert(zoneID, "FaceGroup" + Foam::name(zoneID));
993                 patchIDs.append(fgi);
994                 Info<< "Created patch " << fgi << " for unknown FaceGroup "
995                     << zoneID << '.' << endl;
996             }
997             else
998             {
999                 WarningIn(args.executable())
1000                     << "Unknown FaceGroup " << zoneID << " not in a zone"
1001                     << endl;
1002             }
1003         }
1004     }
1006     patchIDs.shrink();
1007     faceZoneIDs.shrink();
1010     // Add empty patches
1011     // ~~~~~~~~~~~~~~~~~
1013     List<polyPatch*> newPatches(patchIDs.size());
1014     HashSet<word> patchNames;
1016     wordIOList zoneToPatchName
1017     (
1018         IOobject
1019         (
1020             "zoneToPatchName",
1021             runTime.constant(),
1022             mesh.meshSubDir,
1023             mesh,
1024             IOobject::NO_READ,
1025             IOobject::NO_WRITE
1026         ),
1027         wordList(max(faceGroupZoneID) + 1, "unknown")
1028     );
1030     forAll(patchIDs, patchi)
1031     {
1032         label zoneID = faceGroupZoneID[patchIDs[patchi] ];
1033         word name = groupName[zoneID];
1034         const word& type = groupType[zoneID];
1036         Info<< "Creating patch " << patchi
1037             << " for zone: " << zoneID
1038             << " name: " << name
1039             << " type: " << type
1040             << endl;
1042         zoneToPatchName[zoneID] = name;
1044         uniquify(name, patchNames);
1046         HashTable<word>::const_iterator iter = fluentToFoamType.find(type);
1048         if (iter != fluentToFoamType.end())
1049         {
1050             newPatches[patchi] = polyPatch::New
1051             (
1052                 iter(),
1053                 name,
1054                 0,
1055                 0,
1056                 patchi,
1057                 mesh.boundaryMesh()
1058             ).ptr();
1059         }
1060         else
1061         {
1062             Info<< "Adding polyPatch for unknown Fluent type " << type
1063                 << endl;
1065             newPatches[patchi] = new polyPatch
1066             (
1067                 name,
1068                 0,
1069                 0,
1070                 patchi,
1071                 mesh.boundaryMesh()
1072             );
1073         }
1074     }
1075     mesh.addPatches(newPatches);
1078     // Add empty zones
1079     // ~~~~~~~~~~~~~~~
1081     // Cell zones
1082     mesh.cellZones().setSize(cellZoneIDs.size());
1083     HashSet<word> cellZoneNames;
1085     forAll(cellZoneIDs, cellZonei)
1086     {
1087         label zoneID = cellGroupZoneID[cellZoneIDs[cellZonei] ];
1088         word name = groupName[zoneID];
1089         const word& type = groupType[zoneID];
1091         Info<< "Creating cellZone " << cellZonei
1092             << " name: " << name
1093             << " type: " << type
1094             << endl;
1096         uniquify(name, cellZoneNames);
1098         mesh.cellZones().set
1099         (
1100             cellZonei,
1101             new cellZone
1102             (
1103                 name,
1104                 labelList(0),
1105                 cellZonei,
1106                 mesh.cellZones()
1107             )
1108         );
1109     }
1111     // Face zones
1112     mesh.faceZones().setSize(faceZoneIDs.size());
1113     HashSet<word> faceZoneNames;
1115     forAll(faceZoneIDs, faceZonei)
1116     {
1117         label zoneID = faceGroupZoneID[faceZoneIDs[faceZonei] ];
1118         word name = groupName[zoneID];
1119         const word& type = groupType[zoneID];
1121         Info<< "Creating faceZone " << faceZonei
1122             << " name: " << name
1123             << " type: " << type
1124             << endl;
1126         uniquify(name, faceZoneNames);
1128         mesh.faceZones().set
1129         (
1130             faceZonei,
1131             new faceZone
1132             (
1133                 name,
1134                 labelList(0),
1135                 boolList(0),
1136                 faceZonei,
1137                 mesh.faceZones()
1138             )
1139         );
1140     }
1143     // Modify mesh for points/cells/faces
1144     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1146     // Mesh-change container
1147     directTopoChange meshMod(mesh, false);
1149     // Add all points
1150     forAll(points, pointi)
1151     {
1152         meshMod.addPoint(points[pointi], pointi, -1, true);
1153     }
1154     points.setSize(0);
1156     // Add all cells
1157     for (label celli = 0; celli < nCells; celli++)
1158     {
1159         meshMod.addCell
1160         (
1161             -1,         // masterPointID
1162             -1,         // masterEdgeID
1163             -1,         // masterFaceID
1164             celli,      // masterCellID
1165             -1          // zoneID
1166         );
1167     }
1169     // Modify cells to be in zones as required
1170     forAll(cellZoneIDs, cellZonei)
1171     {
1172         label cgi = cellZoneIDs[cellZonei];
1174         for
1175         (
1176             label celli = cellGroupStartIndex[cgi];
1177             celli <= cellGroupEndIndex[cgi];
1178             celli++
1179         )
1180         {
1181             meshMod.modifyCell(celli, cellZonei);
1182         }
1183     }
1186     bool doneWarning = false;
1188     // Add faceZone faces
1189     forAll(faceZoneIDs, faceZonei)
1190     {
1191         label fgi = faceZoneIDs[faceZonei];
1192         label start = faceGroupStartIndex[fgi];
1193         label end = faceGroupEndIndex[fgi];
1194         label zoneID = faceGroupZoneID[fgi];
1196         Info<< "faceZone from Fluent indices: " << start
1197             << " to: " << end
1198             << " type: " << groupType[zoneID]
1199             << endl;
1201         for (label facei = start; facei <= end; facei++)
1202         {
1203             if (owner[facei] >= nCells || neighbour[facei] >= nCells)
1204             {
1205                 if (!doneWarning)
1206                 {
1207                     WarningIn(args.executable())
1208                         << "Ignoring internal face " << facei
1209                         << " on FaceZone " << zoneID
1210                         << " since owner " << owner[facei] << " or neighbour "
1211                         << neighbour[facei] << " outside range of cells 0.."
1212                         << nCells-1 << endl
1213                         << "    Suppressing future warnings." << endl;
1214                     doneWarning = true;
1215                 }
1216             }
1217             else
1218             {
1219                 meshMod.addFace
1220                 (
1221                     faces[facei],
1222                     owner[facei],
1223                     neighbour[facei],
1224                     -1,                 // masterPointID
1225                     -1,                 // masterEdgeID
1226                     facei,              // masterFace
1227                     false,              // flipFaceFlux
1228                     -1,                 // patchID
1229                     faceZonei,          // zoneID
1230                     false               // zoneFlip
1231                 );
1232             }
1234             // Mark face as being done
1235             owner[facei] = -1;
1236         }
1237     }
1239     // Add patch faces
1240     forAll(patchIDs, patchi)
1241     {
1242         label fgi = patchIDs[patchi];
1243         label start = faceGroupStartIndex[fgi];
1244         label end = faceGroupEndIndex[fgi];
1245         label zoneID = faceGroupZoneID[fgi];
1247         Info<< "patch " << patchi << " from Fluent indices: " << start
1248             << " to: " << end
1249             << " type: " << groupType[zoneID]
1250             << endl;
1252         for (label facei = start; facei <= end; facei++)
1253         {
1254             if (owner[facei] >= nCells || neighbour[facei] >= nCells)
1255             {
1256                 if (!doneWarning)
1257                 {
1258                     WarningIn(args.executable())
1259                         << "Ignoring patch face " << facei
1260                         << " on FaceZone " << zoneID
1261                         << " since owner " << owner[facei] << " or neighbour "
1262                         << neighbour[facei] << " outside range of cells 0.."
1263                         << nCells-1 << endl
1264                         << "    Suppressing future warnings." << endl;
1265                     doneWarning = true;
1266                 }
1267             }
1268             else
1269             {
1270                 meshMod.addFace
1271                 (
1272                     faces[facei],
1273                     owner[facei],
1274                     -1,
1275                     -1,                 // masterPointID
1276                     -1,                 // masterEdgeID
1277                     facei,              // masterFace
1278                     false,              // flipFaceFlux
1279                     patchi,             // patchID
1280                     -1,                 // zoneID
1281                     false               // zoneFlip
1282                 );
1284                 // For baffles create the opposite face
1285                 if (neighbour[start] != -1)
1286                 {
1287                     meshMod.addFace
1288                     (
1289                         faces[facei].reverseFace(),
1290                         neighbour[facei],
1291                         -1,
1292                         -1,                 // masterPointID
1293                         -1,                 // masterEdgeID
1294                         facei,              // masterFace
1295                         false,              // flipFaceFlux
1296                         patchi,             // patchID
1297                         -1,                 // zoneID
1298                         false               // zoneFlip
1299                     );
1300                 }
1301             }
1302             // Mark face as being done
1303             owner[facei] = -1;
1304         }
1305     }
1307     // Add remaining internal faces
1308     forAll(owner, facei)
1309     {
1310         if (owner[facei] != -1)
1311         {
1312             // Check the face being added as an internal face actually is one
1313             if (neighbour[facei] == -1)
1314             {
1315                 FatalErrorIn(args.executable())
1316                     << "Attempt of add internal face " << facei
1317                     << " which is a boundary face"
1318                     << exit(FatalError);
1319             }
1321             if (owner[facei] >= nCells || neighbour[facei] >= nCells)
1322             {
1323                 if (!doneWarning)
1324                 {
1325                     WarningIn(args.executable())
1326                         << "Ignoring internal face " << facei
1327                         << " since owner " << owner[facei] << " or neighbour "
1328                         << neighbour[facei] << " outside range of cells 0.."
1329                         << nCells-1 << endl
1330                         << "    Suppressing future warnings." << endl;
1331                     doneWarning = true;
1332                 }
1333             }
1334             else
1335             {
1336                 meshMod.addFace
1337                 (
1338                     faces[facei],
1339                     owner[facei],
1340                     neighbour[facei],
1341                     -1,                 //masterPointID
1342                     -1,                 //masterEdgeID
1343                     facei,              //masterFace
1344                     false,              //flipFaceFlux
1345                     -1,                 //patchID
1346                     -1,                 //zoneID
1347                     false               //zoneFlip
1348                 );
1349             }
1350         }
1351     }
1353     // Reclaim storage
1354     faces.setSize(0);
1355     owner.setSize(0);
1356     neighbour.setSize(0);
1359     // Modify mesh
1360     // ~~~~~~~~~~~
1362     autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false);
1364     // Zip-up the mesh if it contained hanging nodes
1365     if (hangingNodes)
1366     {
1367         Info<< "Zipping mesh to remove hanging nodes" << endl;
1368         polyMeshZipUpCells(mesh);
1369     }
1371     mesh.setInstance(runTime.constant());
1373     // Set the precision of the points data to 10
1374     IOstream::defaultPrecision(10);
1376     Info<< nl << "Writing mesh to " << mesh.objectPath() << endl;
1377     mesh.write();
1378     zoneToPatchName.write();
1381     Info<< nl << "End" << endl;
1382     return 0;
1386  /* ------------------------------------------------------------------------ *\
1387     ------ End of fluentMeshToFoam.L
1388  \* ------------------------------------------------------------------------ */