ENH: autoLayerDriver: better layering information message
[OpenFOAM-2.0.x.git] / applications / utilities / mesh / conversion / fluent3DMeshToFoam / fluent3DMeshToFoam.L
blob5f6a49ab3b3c67724b69e25ffdd6d90eb22c3ba5
1 /*--------------------------------*- C++ -*----------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
9     This file is part of OpenFOAM.
11     OpenFOAM is free software: you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by
13     the Free Software Foundation, either version 3 of the License, or
14     (at your option) any later version.
16     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19     for more details.
21     You should have received a copy of the GNU General Public License
22     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
24 Application
25     fluent3DMeshToFoam
27 Description
28     Converts a Fluent mesh to OpenFOAM format.
30 \*---------------------------------------------------------------------------*/
33 #undef yyFlexLexer
35  /* ------------------------------------------------------------------------ *\
36    ------ local definitions
37  \* ------------------------------------------------------------------------ */
39 #include "cyclicPolyPatch.H"
40 #include "argList.H"
41 #include "Time.H"
42 #include "polyMesh.H"
43 #include "polyTopoChange.H"
44 #include "polyMeshZipUpCells.H"
45 #include "wallPolyPatch.H"
46 #include "symmetryPolyPatch.H"
47 #include "oldCyclicPolyPatch.H"
48 #include "Swap.H"
49 #include "IFstream.H"
50 #include "readHexLabel.H"
52 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
54 using namespace Foam;
56 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
58 // Line number
59 label lineNo = 1;
61 // Scale factor used to scale points (optional command line argument)
62 scalar scaleFactor = 1.0;
64 label dimensionOfGrid = 0;
65 label nPoints = 0;
66 label nFaces = 0;
67 label nCells = 0;
69 bool hangingNodes = false;
71 pointField points(0);
72 faceList faces(0);
73 labelList owner(0);
74 labelList neighbour(0);
76 // Group type and name
77 Map<word> groupType(100);
78 Map<word> groupName(100);
80 // Point groups
81 DynamicList<label> pointGroupZoneID;
82 DynamicList<label> pointGroupStartIndex;
83 DynamicList<label> pointGroupEndIndex;
85 // Face groups
86 DynamicList<label> faceGroupZoneID;
87 DynamicList<label> faceGroupStartIndex;
88 DynamicList<label> faceGroupEndIndex;
90 // Cell groups
91 DynamicList<label> cellGroupZoneID;
92 DynamicList<label> cellGroupStartIndex;
93 DynamicList<label> cellGroupEndIndex;
94 DynamicList<label> cellGroupType;
96 // Special parsing of (incorrect) Cubit files
97 bool cubitFile = false;
100 void uniquify(word& name, HashSet<word>& patchNames)
102     if (!patchNames.found(name))
103     {
104         patchNames.insert(name);
105     }
106     else
107     {
108         Info<< "    name " << name << " already used";
110         label i = 1;
111         word baseName = name;
113         do
114         {
115             name = baseName + "_" + Foam::name(i++);
116         } while (patchNames.found(name));
118         Info<< ", changing to " << name << endl;
119     }
123 // Dummy yywrap to keep yylex happy at compile time.
124 // It is called by yylex but is not used as the mechanism to change file.
125 // See <<EOF>>
126 #if YY_FLEX_SUBMINOR_VERSION < 34
127 extern "C" int yywrap()
128 #else
129 int yyFlexLexer::yywrap()
130 #endif
132     return 1;
137 one_space                  [ \t\f]
138 space                      {one_space}*
139 some_space                 {one_space}+
140 cspace                     ","{space}
142 alpha                      [_[:alpha:]]
143 digit                      [[:digit:]]
144 decDigit                   [[:digit:]]
145 octalDigit                 [0-7]
146 hexDigit                   [[:xdigit:]]
148 lbrac                      "("
149 rbrac                      ")"
150 quote                      \"
151 dash                       "-"
152 dotColonDash               [.:-]
154 schemeSpecialInitial       [!$%&*/\\:<=>?~_^#.@']
155 schemeSpecialSubsequent    [.+-]
156 schemeSymbol               (({some_space}|{alpha}|{quote}|{schemeSpecialInitial})({alpha}|{quote}|{digit}|{schemeSpecialInitial}|{schemeSpecialSubsequent})*)
159 identifier                 {alpha}({alpha}|{digit})*
160 integer                    {decDigit}+
161 label                      [1-9]{decDigit}*
162 hexLabel                   {hexDigit}+
163 zeroLabel                  {digit}*
164 signedInteger              [-+]?{integer}
165 word                       ({alpha}|{digit}|{dotColonDash})*
167 exponent_part              [eE][-+]?{digit}+
168 fractional_constant        [-+]?(({digit}*"."{digit}+)|({digit}+".")|({digit}))
170 double                     ((({fractional_constant}{exponent_part}?)|({digit}+{exponent_part}))|0)
172 x                          {double}
173 y                          {double}
174 z                          {double}
175 scalar                     {double}
176 labelListElement           {space}{zeroLabel}
177 hexLabelListElement        {space}{hexLabel}
178 scalarListElement          {space}{double}
179 schemeSymbolListElement    {space}{schemeSymbol}
180 labelList                  ({labelListElement}+{space})
181 hexLabelList               ({hexLabelListElement}+{space})
182 scalarList                 ({scalarListElement}+{space})
183 schemeSymbolList           ({schemeSymbolListElement}+{space})
185 starStar                   ("**")
186 text                       ({space}({word}*{space})*)
187 anythingInBlock            ([^)]*)
189 dateDDMMYYYY               ({digit}{digit}"/"{digit}{digit}"/"{digit}{digit}{digit}{digit})
190 dateDDMonYYYY              ((({digit}{digit}{space})|({digit}{space})){alpha}*{space}{digit}{digit}{digit}{digit})
191 time                       ({digit}{digit}":"{digit}{digit}":"{digit}{digit})
193 versionNumber              ({digit}|".")*
195 header                     {space}"(1"{space}
196 dimension                  {space}"(2"{space}
197 points                     {space}"(10"{space}
198 faces                      {space}"(13"{space}
199 cells                      {space}"(12"{space}
200 zoneVariant1               {space}"(39"{space}
201 zoneVariant2               {space}"(45"{space}
202 faceTree                   {space}"(59"{space}
204 comment                    "0"{space}
205 unknownPeriodicFace        "17"{space}
206 periodicFace               "18"{space}
207 cellTree                   "58"{space}
208 faceParents                "61"{space}
209 ignoreBlocks               ("4"|"37"|"38"|"40"|"41"|"60"|"64"){space}
211 redundantBlock             {space}({comment}|{unknownPeriodicFace}|{periodicFace}|{cellTree}|{faceParents}|{ignoreBlocks}){space}
213 endOfSection               {space}")"{space}
217  /* ------------------------------------------------------------------------ *\
218                       -----  Exclusive start states -----
219  \* ------------------------------------------------------------------------ */
221 %option stack
223 %x readHeader
224 %x readDimension
225 %x readPoint
226 %x readPointHeader
227 %x readNumberOfPoints
228 %x readPointGroupData
229 %x readPointData
230 %x readScalarList
231 %x fluentFace
232 %x readFaceHeader
233 %x readNumberOfFaces
234 %x readFaceGroupData
235 %x readFaceData
236 %x readFacesMixed
237 %x readFacesUniform
238 %x cell
239 %x readCellHeader
240 %x readNumberOfCells
241 %x readCellGroupData
242 %x readCellData
243 %x readCellsUniform
244 %x zone
245 %x readZoneHeader
246 %x readZoneGroupData
247 %x readZoneData
248 %x readZoneBlock
250 %x ignoreBlock
251 %x ignoreEmbeddedBlock
255     // End of read character pointer returned by strtol and strtod
256     char* endPtr;
258     // Point data
259     label pointGroupNumberOfComponents = 3;
260     label pointi = 0; // index used for reading points
261     label cmpt = 0;   // component index used for reading points
263     // Face data
264     label faceGroupElementType = -1;
265     label facei = 0;  // index used for reading faces
269  /* ------------------------------------------------------------------------ *\
270                             ------ Start Lexing ------
271  \* ------------------------------------------------------------------------ */
273  /*                      ------ Reading control header ------                */
275 {header} {
276         BEGIN(readHeader);
277     }
279 <readHeader>{anythingInBlock} {
280         Info<< "Header: " << YYText() << endl;
281     }
284 {dimension} {
285         BEGIN(readDimension);
286     }
288 <readDimension>{space}{label}{space} {
289         dimensionOfGrid = atoi(YYText());
290         Info<< "Dimension of grid: " << dimensionOfGrid << endl;
291     }
294 {points} {
295         BEGIN(readPointHeader);
296     }
298 <readPointHeader>{space}{lbrac}{space}"0"{space}"1"{space} {
299         BEGIN(readNumberOfPoints);
300     }
302 <readNumberOfPoints>{hexLabel}{space}{labelList} {
303         nPoints = strtol(YYText(), &endPtr, 16);
304         Info<< "Number of points: " << nPoints << endl;
305         points.setSize(nPoints);
307         // Ignore rest of stream
308     }
310 <readPointHeader>{space}{lbrac} {
311         BEGIN(readPointGroupData);
312     }
314 <readPointGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{labelList} {
315         // Read point zone-ID, start and end-label
316         // the indices will be used for checking later.
317         pointGroupZoneID.append(strtol(YYText(), &endPtr, 16));
319         // In FOAM, indices start from zero - adjust
320         pointGroupStartIndex.append(strtol(endPtr, &endPtr, 16) - 1);
322         pointGroupEndIndex.append(strtol(endPtr, &endPtr, 16) - 1);
324         // point group type skipped
325         (void)strtol(endPtr, &endPtr, 16);
327         pointi = pointGroupStartIndex.last();
329         // reset number of components to default
330         pointGroupNumberOfComponents = 3;
332         // read number of components in the vector
333         if (endPtr < &(YYText()[YYLeng()-1]))
334         {
335             pointGroupNumberOfComponents = strtol(endPtr, &endPtr, 16);
336         }
338         Info<< "PointGroup: "
339             << pointGroupZoneID.last()
340             << " start: "
341             << pointGroupStartIndex.last()
342             << " end: "
343             << pointGroupEndIndex.last() << flush;
344     }
346 <readNumberOfPoints,readPointGroupData>{endOfSection} {
347         BEGIN(readPointData);
348     }
350 <readPointData>{space}{lbrac}{space} {
351         Info<< ".  Reading points..." << flush;
352         cmpt = 0;
353         yy_push_state(readScalarList);
354     }
356 <readScalarList>{signedInteger}{space} {
357         points[pointi][cmpt++] = scaleFactor*atol(YYText());
359         if (cmpt == pointGroupNumberOfComponents)
360         {
361             if (pointGroupNumberOfComponents == 2)
362             {
363                 points[pointi].z() = 0.0;
364             }
366             cmpt = 0;
367             pointi++;
368         }
369     }
371 <readScalarList>{scalar}{space} {
372         points[pointi][cmpt++] = scaleFactor*atof(YYText());
374         if (cmpt == pointGroupNumberOfComponents)
375         {
376             if (pointGroupNumberOfComponents == 2)
377             {
378                 points[pointi].z() = 0.0;
379             }
381             cmpt = 0;
382             pointi++;
383         }
384     }
386 <readScalarList>{endOfSection} {
387         Info<< "done." << endl;
389         // check read of points
390         if (pointi != pointGroupEndIndex.last()+1)
391         {
392             Warning
393                 << "Problem with reading points: " << nl
394                 << "    start index: "
395                 << pointGroupStartIndex.last()
396                 << " end index: "
397                 << pointGroupEndIndex.last()
398                 << " last points read: " << pointi << nl
399                 << "    on line " << lineNo << endl;
400         }
402         yy_pop_state();
403     }
405 {faces} {
406         BEGIN(readFaceHeader);
407     }
409 <readFaceHeader>{space}{lbrac}{space}"0"{space}"1"{space} {
410         BEGIN(readNumberOfFaces);
411     }
413 <readNumberOfFaces>{space}{hexLabel}{space}{labelListElement}+ {
414         nFaces = strtol(YYText(), &endPtr, 16);
416         Info<< "Number of faces: " << nFaces << endl;
418         faces.setSize(nFaces);
419         owner.setSize(nFaces);
420         neighbour.setSize(nFaces);
422         // Type and element type not read
423     }
425 <readFaceHeader>{space}{lbrac} {
426         BEGIN(readFaceGroupData);
427     }
429 <readFaceGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{hexLabelListElement}+ {
430         // read fluentFace zone-ID, start and end-label
431         faceGroupZoneID.append(strtol(YYText(), &endPtr, 16));
433         // In FOAM, indices start from zero - adjust
434         faceGroupStartIndex.append(strtol(endPtr, &endPtr, 16) - 1);
436         faceGroupEndIndex.append(strtol(endPtr, &endPtr, 16) - 1);
438         // face group type
439         (void)strtol(endPtr, &endPtr, 16);
441         faceGroupElementType = strtol(endPtr, &endPtr, 16);
443         facei = faceGroupStartIndex.last();
445         Info<< "FaceGroup: "
446             << faceGroupZoneID.last()
447             << " start: "
448             << faceGroupStartIndex.last()
449             << " end: "
450             << faceGroupEndIndex.last() << flush;
451     }
453 <readNumberOfFaces,readFaceGroupData>{space}{endOfSection} {
454         BEGIN(readFaceData);
455     }
457 <readFaceData>{space}{lbrac} {
458         if (faceGroupElementType == 0 || faceGroupElementType > 4)
459         {
460             Info<< ".  Reading mixed faces..." << flush;
461             yy_push_state(readFacesMixed);
462         }
463         else
464         {
465             Info<< ".  Reading uniform faces..." << flush;
466             yy_push_state(readFacesUniform);
467         }
468     }
470 <readFacesMixed>{space}{hexLabelList} {
471         face& curFaceLabels = faces[facei];
473         // set size of label list
474         curFaceLabels.setSize(strtol(YYText(), &endPtr, 16));
476         forAll(curFaceLabels, i)
477         {
478             curFaceLabels[i] = strtol(endPtr, &endPtr, 16) - 1;
479         }
481         // read neighbour and owner. Neighbour comes first
482         neighbour[facei] = strtol(endPtr, &endPtr, 16) - 1;
483         owner[facei] = strtol(endPtr, &endPtr, 16) - 1;
484         facei++;
485     }
487 <readFacesUniform>{space}{hexLabelList} {
488         face& curFaceLabels = faces[facei];
490         // Set size of label list.
491         curFaceLabels.setSize(faceGroupElementType);
493         curFaceLabels[0] = strtol(YYText(), &endPtr, 16) - 1;
495         for (int i=1; i<faceGroupElementType; i++)
496         {
497             curFaceLabels[i] = strtol(endPtr, &endPtr, 16) - 1;
498         }
500         // read neighbour and owner. Neighbour comes first
501         neighbour[facei] = strtol(endPtr, &endPtr, 16) - 1;
502         owner[facei] = strtol(endPtr, &endPtr, 16) - 1;
503         facei++;
504     }
506 <readFacesMixed,readFacesUniform>{space}{endOfSection} {
507         Info<< "done." << endl;
509         // check read of fluentFaces
510         if (facei != faceGroupEndIndex.last()+1)
511         {
512             Warning
513                 << "Problem with reading fluentFaces: " << nl
514                 << "    start index: "
515                 << faceGroupStartIndex.last()
516                 << " end index: "
517                 << faceGroupEndIndex.last()
518                 << " last fluentFaces read: " << facei << nl
519                 << "    on line " << lineNo << endl;
520         }
522         yy_pop_state();
523     }
526 {cells} {
527         BEGIN(readCellHeader);
528     }
530 <readCellHeader>{space}{lbrac}{space}"0"{space}"1"{space} {
531         BEGIN(readNumberOfCells);
532     }
534 <readNumberOfCells>{space}{hexLabel}{space}{labelListElement}+ {
535         nCells = strtol(YYText(), &endPtr, 16);
536         Info<< "Number of cells: " << nCells << endl;
537     }
539 <readCellHeader>{space}{lbrac} {
540         BEGIN(readCellGroupData);
541     }
543 <readCellGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{space}{hexLabel} {
544         // Warning. This entry must be above the next one because of the lexing
545         // rules. It is introduced to deal with the problem of reading
546         // non-standard cell definition from Tgrid, which misses the type label.
548         Warning
549             << "Tgrid syntax problem: " << YYText() << nl
550             << "    on line " << lineNo << endl;
552         // read cell zone-ID, start and end-label
553         cellGroupZoneID.append(strtol(YYText(), &endPtr, 16));
555         // the indices will be used for checking later.
556         cellGroupStartIndex.append(strtol(endPtr, &endPtr, 16) - 1);
558         cellGroupEndIndex.append(strtol(endPtr, &endPtr, 16) - 1);
560         cellGroupType.append(strtol(endPtr, &endPtr, 16));
562         Info<< "CellGroup: "
563             << cellGroupZoneID.last()
564             << " start: "
565             << cellGroupStartIndex.last()
566             << " end: "
567             << cellGroupEndIndex.last()
568             << " type: "
569             << cellGroupType.last()
570             << endl;
571     }
573 <readCellGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{space}{hexLabel} {
574         // Warning. See above
576         // read cell zone-ID, start and end-label
577         cellGroupZoneID.append(strtol(YYText(), &endPtr, 16));
579         // the indices will be used for checking later.
580         cellGroupStartIndex.append(strtol(endPtr, &endPtr, 16) - 1);
582         cellGroupEndIndex.append(strtol(endPtr, &endPtr, 16) - 1);
584         cellGroupType.append(strtol(endPtr, &endPtr, 16));
586         // Note. Potentially skip cell set if type is zero.
587         (void)strtol(endPtr, &endPtr, 16);
589         Info<< "CellGroup: "
590             << cellGroupZoneID.last()
591             << " start: "
592             << cellGroupStartIndex.last()
593             << " end: "
594             << cellGroupEndIndex.last()
595             << " type: "
596             << cellGroupType.last()
597             << endl;
598     }
600 <readNumberOfCells,readCellGroupData>{endOfSection} {
601         BEGIN(readCellData);
602     }
604 <readCellData>{space}{lbrac} {
605         // Quickly scan to the end of the cell data block and discard
606         register int c;
607         while ((c = yyinput()) != 0 && c != ')')
608         {}
609     }
611 {faceTree} {
612         // There are hanging nodes in the mesh so make sure it gets zipped-up
613         hangingNodes = true;
614         yy_push_state(ignoreBlock);
615     }
617 {zoneVariant1} {
618         BEGIN(readZoneHeader);
619     }
621 {zoneVariant2} {
622         BEGIN(readZoneHeader);
623     }
625 <readZoneHeader>{space}{lbrac} {
626         BEGIN(readZoneGroupData);
627     }
629 <readZoneGroupData>{space}{hexLabel}{space}{word}{space}{word}{space}{label}? {
630         IStringStream zoneDataStream(YYText());
632         // cell zone-ID not in hexadecimal!!! Inconsistency
633         label zoneID = -1;
635         if (cubitFile)
636         {
637             zoneID = readHexLabel(zoneDataStream);
638         }
639         else
640         {
641             zoneID = readLabel(zoneDataStream);
642         }
644         groupType.insert(zoneID, word(zoneDataStream));
645         groupName.insert(zoneID, word(zoneDataStream));
647         Info<< "Zone: " << zoneID
648             << " name: " << groupName[zoneID]
649             << " type: " << groupType[zoneID] << flush;
650     }
652 <readZoneGroupData>{endOfSection} {
653         BEGIN(readZoneData);
654     }
656 <readZoneData>{space}{lbrac} {
657         Info<< ".  Reading zone data..." << flush;
658         yy_push_state(readZoneBlock);
659     }
661 <readZoneBlock>{space}{schemeSymbolList} {
662     }
664 <readZoneBlock>{lbrac} {
665         //Warning
666         //    << "Found unknown block in zone: " << YYText() << nl
667         //    << "    on line " << lineNo << endl;
668         yy_push_state(ignoreBlock);
669     }
671 <readZoneBlock>{endOfSection} {
672         Info<< "done." << endl;
673         yy_pop_state();
674     }
678  /*             ------ Reading end of section and others ------              */
680 <readHeader,readDimension,readPointData,readFaceData,readCellData,readZoneData>{space}{endOfSection} {
681         BEGIN(INITIAL);
682     }
684  /*    ------ Reading unknown type or non-standard comment ------            */
686 {lbrac}{label} {
687         Warning
688             << "Found unknown block of type: "
689             << Foam::string(YYText())(1, YYLeng()-1) << nl
690             << "    on line " << lineNo << endl;
692         yy_push_state(ignoreBlock);
693     }
695 {lbrac}{redundantBlock} {
696         yy_push_state(ignoreBlock);
697     }
699 <ignoreBlock,ignoreEmbeddedBlock>{space}{quote}{text}{quote} {
700     }
702 <ignoreBlock,ignoreEmbeddedBlock>{space}{schemeSymbol} {
703     }
705 <ignoreBlock,ignoreEmbeddedBlock>{space}{lbrac} {
706         yy_push_state(ignoreEmbeddedBlock);
708     }
710 <ignoreBlock,ignoreEmbeddedBlock>{space}{endOfSection} {
711         yy_pop_state();
712     }
714 <ignoreBlock,ignoreEmbeddedBlock>{space}{labelList} {
715     }
717 <ignoreBlock,ignoreEmbeddedBlock>{space}{hexLabelList} {
718     }
720 <ignoreBlock,ignoreEmbeddedBlock>{space}{scalarList} {
721     }
723 <ignoreBlock,ignoreEmbeddedBlock>{space}{schemeSymbolList} {
724     }
726 <ignoreBlock,ignoreEmbeddedBlock>{space}{text} {
727     }
730  /* ------              Count newlines.                              ------  */
732 <*>\n {
733         lineNo++;
734     }
737  /* ------              Ignore remaining space.                      ------  */
739 <*>{some_space}|\r {
740     }
743  /* ------              Any other characters are errors.              ------ */
745 <*>. {
746         // This is a catch all.
747         FatalErrorIn("fluentMeshToFoam::lexer")
748             << "Do not understand characters: " << YYText() << nl
749             << "    on line " << lineNo
750             << exit(FatalError);
751     }
754  /*  ------ On EOF return to previous file, if none exists terminate. ------ */
756 <<EOF>> {
757             yyterminate();
758     }
761 int main(int argc, char *argv[])
763     argList::noParallel();
764     argList::validArgs.append("Fluent mesh file");
765     argList::addOption
766     (
767         "scale",
768         "factor",
769         "geometry scaling factor - default is 1"
770     );
771     argList::addOption
772     (
773         "ignoreCellGroups",
774         "names",
775         "specify cell groups to ignore"
776     );
777     argList::addOption
778     (
779         "ignoreFaceGroups",
780         "names",
781         "specify face groups to ignore"
782     );
784     argList::addBoolOption
785     (
786         "cubit",
787         "special parsing of (incorrect) cubit files"
788     );
790     argList args(argc, argv);
792     if (!args.check())
793     {
794         FatalError.exit();
795     }
797     args.optionReadIfPresent("scale", scaleFactor);
799     wordHashSet ignoreCellGroups;
800     wordHashSet ignoreFaceGroups;
802     args.optionReadIfPresent("ignoreCellGroups", ignoreCellGroups);
803     args.optionReadIfPresent("ignoreFaceGroups", ignoreFaceGroups);
805     cubitFile = args.options().found("cubit");
807     if (cubitFile)
808     {
809         Info<< nl
810             << "Assuming Cubit generated file"
811             << " (incorrect face orientation; hexadecimal zoneIDs)."
812             << nl << endl;
813     }
816 #   include "createTime.H"
818     const fileName fluentFile = args[1];
819     IFstream fluentStream(fluentFile);
821     if (!fluentStream)
822     {
823         FatalErrorIn(args.executable())
824             << ": file " << fluentFile << " not found"
825             << exit(FatalError);
826     }
828     yyFlexLexer lexer(&fluentStream.stdStream());
830     while (lexer.yylex() != 0)
831     {}
833     Info<< "\nFINISHED LEXING\n\n";
835     if (dimensionOfGrid != 3)
836     {
837         FatalErrorIn(args.executable())
838             << "Mesh is not 3D, dimension of grid: " << dimensionOfGrid
839             << exit(FatalError);
840     }
842     pointGroupZoneID.shrink();
843     pointGroupStartIndex.shrink();
844     pointGroupEndIndex.shrink();
846     faceGroupZoneID.shrink();
847     faceGroupStartIndex.shrink();
848     faceGroupEndIndex.shrink();
850     cellGroupZoneID.shrink();
851     cellGroupStartIndex.shrink();
852     cellGroupEndIndex.shrink();
853     cellGroupType.shrink();
856     // Pre-filtering: flip "owner" boundary or wrong oriented internal
857     // faces and move to neighbour
859     boolList fm(faces.size(), false);
860     forAll(faces, facei)
861     {
862         if
863         (
864             owner[facei] == -1
865          || (neighbour[facei] != -1 && owner[facei] > neighbour[facei])
866         )
867         {
868             fm[facei] = true;
869             if (!cubitFile)
870             {
871                 faces[facei].flip();
872             }
873             Swap(owner[facei], neighbour[facei]);
874         }
875     }
878     // Foam type for Fluent type
879     // ~~~~~~~~~~~~~~~~~~~~~~~~~
881     HashTable<word> fluentToFoamType;
883     fluentToFoamType.insert("pressure", polyPatch::typeName);
884     fluentToFoamType.insert("pressure-inlet", polyPatch::typeName);
885     fluentToFoamType.insert("inlet-vent", polyPatch::typeName);
886     fluentToFoamType.insert("intake-fan", polyPatch::typeName);
887     fluentToFoamType.insert("pressure-outlet", polyPatch::typeName);
888     fluentToFoamType.insert("exhaust-fan", polyPatch::typeName);
889     fluentToFoamType.insert("outlet-vent", polyPatch::typeName);
890     fluentToFoamType.insert("pressure-far-field", polyPatch::typeName);
891     fluentToFoamType.insert("velocity-inlet", polyPatch::typeName);
892     fluentToFoamType.insert("mass-flow-inlet", polyPatch::typeName);
893     fluentToFoamType.insert("outflow", polyPatch::typeName);
895     fluentToFoamType.insert("wall" , wallPolyPatch::typeName);
897     fluentToFoamType.insert("symmetry",  symmetryPolyPatch::typeName);
898     fluentToFoamType.insert("axis",  symmetryPolyPatch::typeName);
900     fluentToFoamType.insert("interior", polyPatch::typeName);
901     fluentToFoamType.insert("interface", polyPatch::typeName);
902     fluentToFoamType.insert("internal", polyPatch::typeName);
903     fluentToFoamType.insert("solid", polyPatch::typeName);
904     fluentToFoamType.insert("fan", oldCyclicPolyPatch::typeName);
905     fluentToFoamType.insert("radiator", polyPatch::typeName);
906     fluentToFoamType.insert("porous-jump", polyPatch::typeName);
908     //- Periodic halves map directly into split cyclics. The problem is the
909     //  initial matching since we require knowledge of the transformation.
910     //  It is ok if the periodics are already ordered. We should read the
911     //  periodic shadow faces section (section 18) to give use the ordering
912     //  For now just disable.
913     //fluentToFoamType.insert("periodic", cyclicPolyPatch::typeName);
916     // Foam patch type for Fluent zone type
917     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
919     HashSet<word> fluentGroupToFoamPatch;
920     fluentGroupToFoamPatch.insert("wall");
921     fluentGroupToFoamPatch.insert("fan");
924     // Create intial empty polyMesh
925     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
927     polyMesh mesh
928     (
929         IOobject
930         (
931             polyMesh::defaultRegion,
932             runTime.constant(),
933             runTime
934         ),
935         xferCopy(pointField()),
936         xferCopy(faceList()),
937         xferCopy(labelList()),
938         xferCopy(labelList())
939     );
942     // Check the cell groups for zones ignoring those in ignoreCellGroups
943     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
944     label nCellZones = 0;
945     labelList cellZoneIDs(cellGroupZoneID.size());
947     forAll(cellGroupZoneID, cgi)
948     {
949         if (!ignoreCellGroups.found(groupName[cellGroupZoneID[cgi] ]))
950         {
951             cellZoneIDs[nCellZones++] = cgi;
952         }
953     }
955     cellZoneIDs.setSize(nCellZones);
958     // Check the face groups for boundary patches, baffles and faceZones
959     // ignoring the interior zones in ignoreCellGroups
960     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
961     DynamicList<label> patchIDs(faceGroupZoneID.size());
962     DynamicList<label> faceZoneIDs(faceGroupZoneID.size());
964     forAll(faceGroupZoneID, fgi)
965     {
966         label zoneID = faceGroupZoneID[fgi];
967         label start = faceGroupStartIndex[fgi];
969         if (groupType.found(zoneID))
970         {
971             const word& type = groupType[zoneID];
973             // Check the first element of neighbour for boundary group
974             if (neighbour[start] == -1 || fluentGroupToFoamPatch.found(type))
975             {
976                 patchIDs.append(fgi);
977             }
978             else
979             {
980                 if (!ignoreFaceGroups.found(groupName[faceGroupZoneID[fgi] ]))
981                 {
982                     faceZoneIDs.append(fgi);
983                 }
984             }
985         }
986         else if (hangingNodes)
987         {
988             label end = faceGroupEndIndex[fgi];
990             Info<< "Unknown FaceGroup " << zoneID
991                 << " assumed to be parent faces of refinement "
992                    "patterns and ignored."
993                 << endl;
995             // Set the owner of these faces to -1 so that they do not get
996             // added to the mesh
997             for (label facei = start; facei <= end; facei++)
998             {
999                 owner[facei] = -1;
1000             }
1001         }
1002         else
1003         {
1004             if (neighbour[start] == -1)
1005             {
1006                 // Boundary face in unknown group. Create a patch for it.
1007                 groupType.insert(zoneID, "unknown");
1008                 groupName.insert(zoneID, "FaceGroup" + Foam::name(zoneID));
1009                 patchIDs.append(fgi);
1010                 Info<< "Created patch " << fgi << " for unknown FaceGroup "
1011                     << zoneID << '.' << endl;
1012             }
1013             else
1014             {
1015                 WarningIn(args.executable())
1016                     << "Unknown FaceGroup " << zoneID << " not in a zone"
1017                     << endl;
1018             }
1019         }
1020     }
1022     patchIDs.shrink();
1023     faceZoneIDs.shrink();
1026     // Add empty patches
1027     // ~~~~~~~~~~~~~~~~~
1029     List<polyPatch*> newPatches(patchIDs.size());
1030     HashSet<word> patchNames;
1032     forAll(patchIDs, patchi)
1033     {
1034         label zoneID = faceGroupZoneID[patchIDs[patchi] ];
1035         word name = groupName[zoneID];
1036         const word& type = groupType[zoneID];
1038         Info<< "Creating patch " << patchi
1039             << " for zone: " << zoneID
1040             << " name: " << name
1041             << " type: " << type
1042             << endl;
1044         uniquify(name, patchNames);
1046         HashTable<word>::const_iterator iter = fluentToFoamType.find(type);
1048         if (iter != fluentToFoamType.end())
1049         {
1050             // See if we have a periodic and can derive the other side.
1051             word neighbPatchName;
1052             if (iter() == cyclicPolyPatch::typeName)
1053             {
1054                 // Periodic
1055                 size_t n = name.rfind("-SIDE-1");
1057                 if (n != string::npos)
1058                 {
1059                     neighbPatchName = name.substr(0, n) + "-SIDE-2";
1060                 }
1061                 else
1062                 {
1063                     n = name.rfind("-SIDE-2");
1064                     if (n != string::npos)
1065                     {
1066                         neighbPatchName = name.substr(0, n) + "-SIDE-1";
1067                     }
1068                 }
1069             }
1071             if (neighbPatchName.size())
1072             {
1073                 Info<< "Adding cyclicPolyPatch for Fluent zone " << name
1074                     << " with neighbour patch " << neighbPatchName
1075                     << endl;
1077                 newPatches[patchi] = new cyclicPolyPatch
1078                 (
1079                     name,
1080                     0,
1081                     0,
1082                     patchi,
1083                     mesh.boundaryMesh(),
1084                     neighbPatchName,
1085                     cyclicPolyPatch::NOORDERING,
1086                     vector::zero,
1087                     vector::zero,
1088                     vector::zero
1089                 );
1090             }
1091             else
1092             {
1093                 newPatches[patchi] = polyPatch::New
1094                 (
1095                     iter(),
1096                     name,
1097                     0,
1098                     0,
1099                     patchi,
1100                     mesh.boundaryMesh()
1101                 ).ptr();
1102             }
1103         }
1104         else
1105         {
1106             Info<< "Adding polyPatch for unknown Fluent type " << type
1107                 << endl;
1109             newPatches[patchi] = new polyPatch
1110             (
1111                 name,
1112                 0,
1113                 0,
1114                 patchi,
1115                 mesh.boundaryMesh()
1116             );
1117         }
1118     }
1119     mesh.addPatches(newPatches);
1122     // Add empty zones
1123     // ~~~~~~~~~~~~~~~
1125     // Cell zones
1126     mesh.cellZones().setSize(cellZoneIDs.size());
1127     HashSet<word> cellZoneNames;
1129     forAll(cellZoneIDs, cellZonei)
1130     {
1131         label zoneID = cellGroupZoneID[cellZoneIDs[cellZonei] ];
1132         word name = groupName[zoneID];
1133         const word& type = groupType[zoneID];
1135         Info<< "Creating cellZone " << cellZonei
1136             << " name: " << name
1137             << " type: " << type
1138             << endl;
1140         uniquify(name, cellZoneNames);
1142         mesh.cellZones().set
1143         (
1144             cellZonei,
1145             new cellZone
1146             (
1147                 name,
1148                 labelList(0),
1149                 cellZonei,
1150                 mesh.cellZones()
1151             )
1152         );
1153     }
1155     // Face zones
1156     mesh.faceZones().setSize(faceZoneIDs.size());
1157     HashSet<word> faceZoneNames;
1159     forAll(faceZoneIDs, faceZonei)
1160     {
1161         label zoneID = faceGroupZoneID[faceZoneIDs[faceZonei] ];
1162         word name = groupName[zoneID];
1163         const word& type = groupType[zoneID];
1165         Info<< "Creating faceZone " << faceZonei
1166             << " name: " << name
1167             << " type: " << type
1168             << endl;
1170         uniquify(name, faceZoneNames);
1172         mesh.faceZones().set
1173         (
1174             faceZonei,
1175             new faceZone
1176             (
1177                 name,
1178                 labelList(0),
1179                 boolList(0),
1180                 faceZonei,
1181                 mesh.faceZones()
1182             )
1183         );
1184     }
1187     // Modify mesh for points/cells/faces
1188     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1190     // Mesh-change container
1191     polyTopoChange meshMod(mesh, false);
1193     // Add all points
1194     forAll(points, pointi)
1195     {
1196         meshMod.addPoint(points[pointi], pointi, -1, true);
1197     }
1198     points.setSize(0);
1200     // Add all cells
1201     for (label celli = 0; celli < nCells; celli++)
1202     {
1203         meshMod.addCell
1204         (
1205             -1,         // masterPointID
1206             -1,         // masterEdgeID
1207             -1,         // masterFaceID
1208             celli,      // masterCellID
1209             -1          // zoneID
1210         );
1211     }
1213     // Modify cells to be in zones as required
1214     forAll(cellZoneIDs, cellZonei)
1215     {
1216         label cgi = cellZoneIDs[cellZonei];
1218         for
1219         (
1220             label celli = cellGroupStartIndex[cgi];
1221             celli <= cellGroupEndIndex[cgi];
1222             celli++
1223         )
1224         {
1225             meshMod.modifyCell(celli, cellZonei);
1226         }
1227     }
1230     bool doneWarning = false;
1232     // Add faceZone faces
1233     forAll(faceZoneIDs, faceZonei)
1234     {
1235         label fgi = faceZoneIDs[faceZonei];
1236         label start = faceGroupStartIndex[fgi];
1237         label end = faceGroupEndIndex[fgi];
1238         label zoneID = faceGroupZoneID[fgi];
1240         Info<< "faceZone from Fluent indices: " << start
1241             << " to: " << end
1242             << " type: " << groupType[zoneID]
1243             << endl;
1245         for (label facei = start; facei <= end; facei++)
1246         {
1247             if (owner[facei] >= nCells || neighbour[facei] >= nCells)
1248             {
1249                 if (!doneWarning)
1250                 {
1251                     WarningIn(args.executable())
1252                         << "Ignoring internal face " << facei
1253                         << " on FaceZone " << zoneID
1254                         << " since owner " << owner[facei] << " or neighbour "
1255                         << neighbour[facei] << " outside range of cells 0.."
1256                         << nCells-1 << endl
1257                         << "    Suppressing future warnings." << endl;
1258                     doneWarning = true;
1259                 }
1260             }
1261             else
1262             {
1263                 meshMod.addFace
1264                 (
1265                     faces[facei],
1266                     owner[facei],
1267                     neighbour[facei],
1268                     -1,                 // masterPointID
1269                     -1,                 // masterEdgeID
1270                     facei,              // masterFace
1271                     false,              // flipFaceFlux
1272                     -1,                 // patchID
1273                     faceZonei,          // zoneID
1274                     fm[facei]           // zoneFlip
1275                 );
1276             }
1278             // Mark face as being done
1279             owner[facei] = -1;
1280         }
1281     }
1283     // Add patch faces
1284     forAll(patchIDs, patchi)
1285     {
1286         label fgi = patchIDs[patchi];
1287         label start = faceGroupStartIndex[fgi];
1288         label end = faceGroupEndIndex[fgi];
1289         label zoneID = faceGroupZoneID[fgi];
1291         Info<< "patch " << patchi << " from Fluent indices: " << start
1292             << " to: " << end
1293             << " type: " << groupType[zoneID]
1294             << endl;
1296         for (label facei = start; facei <= end; facei++)
1297         {
1298             if (owner[facei] >= nCells || neighbour[facei] >= nCells)
1299             {
1300                 if (!doneWarning)
1301                 {
1302                     WarningIn(args.executable())
1303                         << "Ignoring patch face " << facei
1304                         << " on FaceZone " << zoneID
1305                         << " since owner " << owner[facei] << " or neighbour "
1306                         << neighbour[facei] << " outside range of cells 0.."
1307                         << nCells-1 << endl
1308                         << "    Suppressing future warnings." << endl;
1309                     doneWarning = true;
1310                 }
1311             }
1312             else
1313             {
1314                 meshMod.addFace
1315                 (
1316                     faces[facei],
1317                     owner[facei],
1318                     -1,
1319                     -1,                 // masterPointID
1320                     -1,                 // masterEdgeID
1321                     facei,              // masterFace
1322                     false,              // flipFaceFlux
1323                     patchi,             // patchID
1324                     -1,                 // zoneID
1325                     false               // zoneFlip
1326                 );
1328                 // For baffles create the opposite face
1329                 if (neighbour[start] != -1)
1330                 {
1331                     meshMod.addFace
1332                     (
1333                         faces[facei].reverseFace(),
1334                         neighbour[facei],
1335                         -1,
1336                         -1,                 // masterPointID
1337                         -1,                 // masterEdgeID
1338                         facei,              // masterFace
1339                         false,              // flipFaceFlux
1340                         patchi,             // patchID
1341                         -1,                 // zoneID
1342                         false               // zoneFlip
1343                     );
1344                 }
1345             }
1346             // Mark face as being done
1347             owner[facei] = -1;
1348         }
1349     }
1351     // Add remaining internal faces
1352     forAll(owner, facei)
1353     {
1354         if (owner[facei] != -1)
1355         {
1356             // Check the face being added as an internal face actually is one
1357             if (neighbour[facei] == -1)
1358             {
1359                 FatalErrorIn(args.executable())
1360                     << "Attempt of add internal face " << facei
1361                     << " which is a boundary face"
1362                     << exit(FatalError);
1363             }
1365             if (owner[facei] >= nCells || neighbour[facei] >= nCells)
1366             {
1367                 if (!doneWarning)
1368                 {
1369                     WarningIn(args.executable())
1370                         << "Ignoring internal face " << facei
1371                         << " since owner " << owner[facei] << " or neighbour "
1372                         << neighbour[facei] << " outside range of cells 0.."
1373                         << nCells-1 << endl
1374                         << "    Suppressing future warnings." << endl;
1375                     doneWarning = true;
1376                 }
1377             }
1378             else
1379             {
1380                 meshMod.addFace
1381                 (
1382                     faces[facei],
1383                     owner[facei],
1384                     neighbour[facei],
1385                     -1,                 //masterPointID
1386                     -1,                 //masterEdgeID
1387                     facei,              //masterFace
1388                     false,              //flipFaceFlux
1389                     -1,                 //patchID
1390                     -1,                 //zoneID
1391                     false               //zoneFlip
1392                 );
1393             }
1394         }
1395     }
1397     // Reclaim storage
1398     faces.setSize(0);
1399     owner.setSize(0);
1400     neighbour.setSize(0);
1403     // Modify mesh
1404     // ~~~~~~~~~~~
1406     autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false);
1408     // Zip-up the mesh if it contained hanging nodes
1409     if (hangingNodes)
1410     {
1411         Info<< "Zipping mesh to remove hanging nodes" << endl;
1412         polyMeshZipUpCells(mesh);
1413     }
1415     mesh.setInstance(runTime.constant());
1417     // Set the precision of the points data to 10
1418     IOstream::defaultPrecision(10);
1420     Info<< nl << "Writing mesh to " << mesh.objectPath() << endl;
1421     mesh.write();
1424     Info<< "\nEnd\n" << endl;
1425     return 0;
1429  /* ------------------------------------------------------------------------ *\
1430     ------ End of fluentMeshToFoam.L
1431  \* ------------------------------------------------------------------------ */