ENH: autoLayerDriver: better layering information message
[OpenFOAM-2.0.x.git] / applications / utilities / mesh / conversion / fluentMeshToFoam / fluentMeshToFoam.L
blobe99ddaccf6d525036a7a915be1efe65aadb8e0e6
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     fluentMeshToFoam
27 Description
28     Converts a Fluent mesh to OpenFOAM format
29     including multiple region and region boundary handling.
31 \*---------------------------------------------------------------------------*/
35 #undef yyFlexLexer
37  /* ------------------------------------------------------------------------- *\
38    ------ local definitions
39  \* ------------------------------------------------------------------------- */
41 #include "argList.H"
42 #include "Time.H"
43 #include "IStringStream.H"
44 #include "polyMesh.H"
45 #include "emptyPolyPatch.H"
46 #include "wallPolyPatch.H"
47 #include "symmetryPolyPatch.H"
48 #include "cellShape.H"
49 #include "faceSet.H"
50 #include "cellSet.H"
51 #include "meshTools.H"
52 #include "OFstream.H"
54 #include "readHexLabel.H"
55 #include "cellShapeRecognition.H"
56 #include "repatchPolyTopoChanger.H"
59 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
61 using namespace Foam;
63 const scalar convertToMeters = 1.0;
65 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
68 label dimensionOfGrid = 0;
70 label nPoints = 0;
71 label nFaces = 0;
72 label nCells = 0;
74 pointField points(0);
75 SLList<label> pointGroupZoneID;
76 SLList<label> pointGroupStartIndex;
77 SLList<label> pointGroupEndIndex;
80 faceList faces(0);
81 labelList owner(0);
82 labelList neighbour(0);
83 SLList<label> faceGroupZoneID;
84 SLList<label> faceGroupStartIndex;
85 SLList<label> faceGroupEndIndex;
87 labelList fluentCellModelID(0);
88 SLList<label> cellGroupZoneID;
89 SLList<label> cellGroupStartIndex;
90 SLList<label> cellGroupEndIndex;
91 SLList<label> cellGroupType;
93 // number of zones adjusted at run-time if necessary
94 label maxZoneID = 100;
95 label zoneIDBuffer = 10;
97 wordList patchTypeIDs(maxZoneID);
98 wordList patchNameIDs(maxZoneID);
100 // Dummy yywrap to keep yylex happy at compile time.
101 // It is called by yylex but is not used as the mechanism to change file.
102 // See <<EOF>>
103 #if YY_FLEX_SUBMINOR_VERSION < 34
104 extern "C" int yywrap()
105 #else
106 int yyFlexLexer::yywrap()
107 #endif
109     return 1;
114 one_space                  [ \t\f]
115 space                      {one_space}*
116 some_space                 {one_space}+
117 cspace                     ","{space}
118 spaceNl                    ({space}|\n|\r)*
120 alpha                      [_[:alpha:]]
121 digit                      [[:digit:]]
122 decDigit                   [[:digit:]]
123 octalDigit                 [0-7]
124 hexDigit                   [[:xdigit:]]
126 lbrac                      "("
127 rbrac                      ")"
128 quote                      \"
129 dash                       "-"
130 dotColonDash               [.:-]
132 schemeSpecialInitial       [!$%&*/:<=>?~_^#.]
133 schemeSpecialSubsequent    [.+-]
134 schemeSymbol               (({some_space}|{alpha}|{quote}|{schemeSpecialInitial})({alpha}|{quote}|{digit}|{schemeSpecialInitial}|{schemeSpecialSubsequent})*)
137 identifier                 {alpha}({alpha}|{digit})*
138 integer                    {decDigit}+
139 label                      [1-9]{decDigit}*
140 hexLabel                   {hexDigit}+
141 zeroLabel                  {digit}*
143 word                       ({alpha}|{digit}|{dotColonDash})*
145 exponent_part              [eE][-+]?{digit}+
146 fractional_constant        [-+]?(({digit}*"."{digit}+)|({digit}+".")|({digit}))
148 double                     ((({fractional_constant}{exponent_part}?)|({digit}+{exponent_part}))|0)
150 x                          {double}
151 y                          {double}
152 z                          {double}
153 scalar                     {double}
154 labelListElement           {space}{zeroLabel}
155 hexLabelListElement        {space}{hexLabel}
156 scalarListElement          {space}{double}
157 schemeSymbolListElement    {space}{schemeSymbol}
158 labelList                  ({labelListElement}+{space})
159 hexLabelList               ({hexLabelListElement}+{space})
160 scalarList                 ({scalarListElement}+{space})
161 schemeSymbolList           ({schemeSymbolListElement}+{space})
163 starStar                   ("**")
164 text                       ({space}({word}*{space})*)
166 dateDDMMYYYY               ({digit}{digit}"/"{digit}{digit}"/"{digit}{digit}{digit}{digit})
167 dateDDMonYYYY              ((({digit}{digit}{space})|({digit}{space})){alpha}*{space}{digit}{digit}{digit}{digit})
168 time                       ({digit}{digit}":"{digit}{digit}":"{digit}{digit})
170 versionNumber              ({digit}|".")*
172 comment                    {spaceNl}"(0"{space}
173 header                     {spaceNl}"(1"{space}
174 dimension                  {spaceNl}"(2"{space}
175 point                      {spaceNl}"(10"{space}
176 fluentFace                 {spaceNl}"(13"{space}
177 cell                       {spaceNl}"(12"{space}
178 zoneVariant1               {spaceNl}"(39"{space}
179 zoneVariant2               {spaceNl}"(45"{space}
181 unknownPeriodicFace        {spaceNl}"(17"{space}
182 periodicFace               {spaceNl}"(18"{space}
183 cellTree                   {spaceNl}"(58"{space}
184 faceTree                   {spaceNl}"(59"{space}
185 faceParents                {spaceNl}"(61"{space}
187 endOfSection               {space}")"{space}
191  /* ------------------------------------------------------------------------- *\
192                       -----  Exclusive start states -----
193  \* ------------------------------------------------------------------------- */
195 %option stack
197 %x readComment
198 %x embeddedCommentState
199 %x readHeader
200 %x readDimension
201 %x readPoint
202 %x readPointHeader
203 %x readNumberOfPoints
204 %x readPointGroupData
205 %x readPointData
206 %x readPoints2D
207 %x readPoints3D
208 %x fluentFace
209 %x readFaceHeader
210 %x readNumberOfFaces
211 %x readFaceGroupData
212 %x readFaceData
213 %x readFacesMixed
214 %x readFacesUniform
215 %x cell
216 %x readCellHeader
217 %x readNumberOfCells
218 %x readCellGroupData
219 %x readCellData
220 %x readCellsMixed
221 %x readCellsUniform
222 %x zone
223 %x readZoneHeader
224 %x readZoneGroupData
225 %x readZoneData
226 %x readZoneBlock
228 %x periodicFace
229 %x cellTree
230 %x faceTree
231 %x faceParents
233 %x unknownBlock
234 %x embeddedUnknownBlock
238     // Point data
239     label pointGroupNumberOfComponents = 3;
240     label pointI = 0; // index used for reading points
242     // Face data
243     label faceGroupElementType = -1;
244     label faceI = 0;
246     // Cell data
247     label cellGroupElementType = -1;
248     label celli = 0;
252  /* ------------------------------------------------------------------------- *\
253                             ------ Start Lexing ------
254  \* ------------------------------------------------------------------------- */
256  /*                      ------ Reading control header ------                 */
258 {comment} {
259         yy_push_state(readComment);
260     }
263 <readComment>{quote}{text}{quote} {
264     }
267 <readComment>{spaceNl}{endOfSection} {
268         yy_pop_state();
269     }
271 {header} {
272         BEGIN(readHeader);
273     }
275 <readHeader>{quote}{text}{quote} {
276         Info<< "Reading header: " << YYText() << endl;
277     }
280 {dimension} {
281         BEGIN(readDimension);
282     }
284 <readDimension>{space}{label}{space} {
285         IStringStream dimOfGridStream(YYText());
287         dimensionOfGrid = readLabel(dimOfGridStream);
289         Info<< "Dimension of grid: " << dimensionOfGrid << endl;
290     }
293 {point} {
294         BEGIN(readPointHeader);
295     }
297 <readPointHeader>{spaceNl}{lbrac}{space}"0"{space}"1"{space} {
298         BEGIN(readNumberOfPoints);
299     }
301 <readNumberOfPoints>{space}{hexLabel}{space}{labelList} {
303         IStringStream numberOfPointsStream(YYText());
305         nPoints = readHexLabel(numberOfPointsStream);
307         Info<< "Number of points: " << nPoints << endl;
309         // set the size of the points list
310         points.setSize(nPoints);
312         // meaningless type skipped
313         readLabel(numberOfPointsStream);
315         // this dimension of grid may be checked against global dimension
316         if (numberOfPointsStream)
317         {
318             // check dimension of grid
319             readLabel(numberOfPointsStream);
320         }
321         else
322         {
323             Info<< endl;
324         }
325     }
327 <readPointHeader>{spaceNl}{lbrac} {
328         BEGIN(readPointGroupData);
329     }
331 <readPointGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{labelList} {
332         IStringStream pointGroupDataStream(YYText());
334         // read point zone-ID, start and end-label
335         // the indices will be used for checking later.
336         pointGroupZoneID.append(readHexLabel(pointGroupDataStream));
338         pointGroupStartIndex.append(readHexLabel(pointGroupDataStream));
340         pointGroupEndIndex.append(readHexLabel(pointGroupDataStream));
342         // point group type skipped
343         readHexLabel(pointGroupDataStream);
345         // In FOAM, indices start from zero - adjust
346         pointI = pointGroupStartIndex.last() - 1;
348         // reset number of components to default
349         pointGroupNumberOfComponents = 3;
351         // read number of components in the vector
352         if (pointGroupDataStream)
353         {
354             pointGroupNumberOfComponents = readLabel(pointGroupDataStream);
355         }
356     }
358 <readNumberOfPoints,readPointGroupData>{endOfSection} {
359         BEGIN(readPointData);
360     }
362 <readPointData>{spaceNl}{lbrac} {
364         Info<< "Reading points" << endl;
366         if (pointGroupNumberOfComponents == 2)
367         {
368             yy_push_state(readPoints2D);
369         }
370         else
371         {
372             yy_push_state(readPoints3D);
373         }
374     }
376 <readPoints2D>{spaceNl}{scalarList} {
378         IStringStream vertexXyzStream(YYText());
380         // Note: coordinates must be read one at the time.
381         scalar x = readScalar(vertexXyzStream);
382         scalar y = readScalar(vertexXyzStream);
384         points[pointI] = point(x, y, 0);
385         pointI++;
386     }
388 <readPoints3D>{spaceNl}{scalarList} {
390         IStringStream vertexXyzStream(YYText());
392         // Note: coordinates must be read one at the time.
393         scalar x = readScalar(vertexXyzStream);
394         scalar y = readScalar(vertexXyzStream);
395         scalar z = readScalar(vertexXyzStream);
397         points[pointI] = convertToMeters*point(x, y, z);
398         pointI++;
399     }
401 <readPoints2D,readPoints3D>{spaceNl}{endOfSection} {
403         // check read of points
404         if (pointI != pointGroupEndIndex.last())
405         {
406             Info<< "problem with reading points: "
407                 << "start index: " << pointGroupStartIndex.last()
408                 << " end index: " << pointGroupEndIndex.last()
409                 << " last points read: " << pointI << endl;
410         }
412         yy_pop_state();
413     }
416 {fluentFace} {
417         BEGIN(readFaceHeader);
418     }
420 <readFaceHeader>{spaceNl}{lbrac}{space}"0"{space}"1"{space} {
421         BEGIN(readNumberOfFaces);
422     }
424 <readNumberOfFaces>{space}{hexLabel}{space}{labelListElement}+ {
426         IStringStream numberOfFacesStream(YYText());
428         nFaces = readHexLabel(numberOfFacesStream);
430         Info<< "number of faces: " << nFaces << endl;
432         faces.setSize(nFaces);
433         owner.setSize(nFaces);
434         neighbour.setSize(nFaces);
436         // Meaningless type and element type not read
437     }
439 <readFaceHeader>{spaceNl}{lbrac} {
440         BEGIN(readFaceGroupData);
441     }
443 <readFaceGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{hexLabelListElement}+ {
445         IStringStream faceGroupDataStream(YYText());
447         // read fluentFace zone-ID, start and end-label
448         faceGroupZoneID.append(readHexLabel(faceGroupDataStream));
450         // the indices will be used for checking later.
451         faceGroupStartIndex.append(readHexLabel(faceGroupDataStream));
453         faceGroupEndIndex.append(readHexLabel(faceGroupDataStream));
455         // face group type
456         readHexLabel(faceGroupDataStream);
458         faceGroupElementType = readHexLabel(faceGroupDataStream);
460         // In FOAM, indices start from zero - adjust
461         faceI = faceGroupStartIndex.last() - 1;
462     }
464 <readNumberOfFaces,readFaceGroupData>{spaceNl}{endOfSection} {
465         BEGIN(readFaceData);
466     }
468 <readFaceData>{spaceNl}{lbrac} {
470         if (faceGroupElementType == 0)
471         {
472             Info<< "Reading mixed faces" << endl;
473             yy_push_state(readFacesMixed);
474         }
475         else
476         {
477             Info<< "Reading uniform faces" << endl;
478             yy_push_state(readFacesUniform);
479         }
480     }
482 <readFacesMixed>{spaceNl}{hexLabelList} {
484         IStringStream mixedFaceStream(YYText());
486         face& curFaceLabels = faces[faceI];
488         // set size of label list
489         curFaceLabels.setSize(readLabel(mixedFaceStream));
491         forAll(curFaceLabels, i)
492         {
493             curFaceLabels[i] = readHexLabel(mixedFaceStream) - 1;
494         }
496         // read neighbour and owner. Neighbour comes first
497         neighbour[faceI] = readHexLabel(mixedFaceStream) - 1;
498         owner[faceI] = readHexLabel(mixedFaceStream) - 1;
499         faceI++;
500     }
502 <readFacesUniform>{spaceNl}{hexLabelList} {
504         IStringStream mixedFaceStream(YYText());
506         face& curFaceLabels = faces[faceI];
508         // set size of label list. This is OK because in Fluent the type
509         // for edge is 2, for triangle is 3 and for quad is 4
510         curFaceLabels.setSize(faceGroupElementType);
512         forAll(curFaceLabels, i)
513         {
514             curFaceLabels[i] = readHexLabel(mixedFaceStream) - 1;
515         }
517         // read neighbour and owner. Neighbour comes first
518         neighbour[faceI] = readHexLabel(mixedFaceStream) - 1;
519         owner[faceI] = readHexLabel(mixedFaceStream) - 1;
520         faceI++;
521     }
523 <readFacesMixed,readFacesUniform>{spaceNl}{endOfSection} {
525         // check read of fluentFaces
526         if (faceI != faceGroupEndIndex.last())
527         {
528             Info<< "problem with reading fluentFaces: "
529                 << "start index: " << faceGroupStartIndex.last()
530                 << " end index: " << faceGroupEndIndex.last()
531                 << " last fluentFaces read: " << faceI << endl;
532         }
534         yy_pop_state();
535     }
538 {cell} {
539         BEGIN(readCellHeader);
540     }
542 <readCellHeader>{spaceNl}{lbrac}{space}"0"{space}"1"{space} {
543         BEGIN(readNumberOfCells);
544     }
546 <readNumberOfCells>{space}{hexLabel}{space}{labelListElement}+ {
548         IStringStream numberOfCellsStream(YYText());
550         nCells = readHexLabel(numberOfCellsStream);
552         Info<< "Number of cells: " << nCells << endl;
554         fluentCellModelID.setSize(nCells);
556         // Meaningless type and element type not read
557     }
559 <readCellHeader>{spaceNl}{lbrac} {
560         BEGIN(readCellGroupData);
561     }
563 <readCellGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{space}{hexLabel} {
564         // Warning. This entry must be above the next one because of the lexing
565         // rules. It is introduced to deal with the problem of reading
566         // non-standard cell definition from Tgrid, which misses the type label.
568         Info<< "Tgrid syntax problem: " << YYText() << endl;
569         IStringStream cellGroupDataStream(YYText());
571         // read cell zone-ID, start and end-label
572         cellGroupZoneID.append(readHexLabel(cellGroupDataStream));
574         // the indices will be used for checking later.
575         cellGroupStartIndex.append(readHexLabel(cellGroupDataStream));
577         cellGroupEndIndex.append(readHexLabel(cellGroupDataStream));
579         cellGroupType.append(readHexLabel(cellGroupDataStream));
581         Info<< "cellGroupZoneID:" << cellGroupZoneID.last()
582             << endl;
583         Info<< "cellGroupStartIndex:" << cellGroupStartIndex.last()
584             << endl;
585         Info<< "cellGroupEndIndex:" << cellGroupEndIndex.last()
586             << endl;
587         Info<< "cellGroupType:" << cellGroupType.last()
588             << endl;
591         // Note. Potentially skip cell set if type is zero.
592         // This entry does not exist in Tgrid files.
593         if (dimensionOfGrid == 2)
594         {
595             // Tgrid creating triangles
596             cellGroupElementType = 1;
597         }
598         else
599         {
600             cellGroupElementType = 2;
601         }
603         // In FOAM, indices start from zero - adjust
604         celli = cellGroupStartIndex.last() - 1;
606         if (cellGroupElementType != 0)
607         {
608             label lastIndex = cellGroupEndIndex.last();
610             for (; celli < lastIndex; celli++)
611             {
612                 fluentCellModelID[celli] = cellGroupElementType;
613             }
614         }
615     }
617 <readCellGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{space}{hexLabel} {
618         // Warning. See above
620         Info<< "Other readCellGroupData: " << YYText() << endl;
623         IStringStream cellGroupDataStream(YYText());
625         // read cell zone-ID, start and end-label
626         cellGroupZoneID.append(readHexLabel(cellGroupDataStream));
628         // the indices will be used for checking later.
629         cellGroupStartIndex.append(readHexLabel(cellGroupDataStream));
631         cellGroupEndIndex.append(readHexLabel(cellGroupDataStream));
633         cellGroupType.append(readHexLabel(cellGroupDataStream));
635         // Note. Potentially skip cell set if type is zero.
637         cellGroupElementType = readHexLabel(cellGroupDataStream);
639         // In FOAM, indices start from zero - adjust
640         celli = cellGroupStartIndex.last() - 1;
642         if (cellGroupElementType != 0)
643         {
644             Info<< "Reading uniform cells" << endl;
645             label lastIndex = cellGroupEndIndex.last();
647             for (; celli < lastIndex; celli++)
648             {
649                 fluentCellModelID[celli] = cellGroupElementType;
650             }
651         }
652     }
654 <readNumberOfCells,readCellGroupData>{endOfSection} {
655         BEGIN(readCellData);
656     }
658 <readCellData>{spaceNl}{lbrac} {
659         Info<< "Reading mixed cells" << endl;
660         yy_push_state(readCellsMixed);
661     }
663 <readCellsMixed>{spaceNl}{labelList} {
665         IStringStream fluentCellModelIDStream(YYText());
667         label celliD;
668         while (fluentCellModelIDStream.read(celliD))
669         {
670             fluentCellModelID[celli] = celliD;
671             celli++;
672         }
673     }
675 <readCellsMixed>{spaceNl}{endOfSection} {
677         // check read of cells
678         if (celli != cellGroupEndIndex.last())
679         {
680             Info<< "problem with reading cells: "
681                 << "start index: " << cellGroupStartIndex.last()
682                 << " end index: " << cellGroupEndIndex.last()
683                 << " last cells read: " << celli << endl;
684         }
686         yy_pop_state();
687     }
691 {zoneVariant1} {
692         BEGIN(readZoneHeader);
693     }
695 {zoneVariant2} {
696         BEGIN(readZoneHeader);
697     }
699 <readZoneHeader>{spaceNl}{lbrac} {
700         BEGIN(readZoneGroupData);
701     }
703 <readZoneGroupData>{space}{label}{space}{word}{space}{word} {
705         IStringStream zoneDataStream(YYText());
707         // cell zone-ID not in hexadecimal!!! Inconsistency
708         label zoneID(readLabel(zoneDataStream));
710         if (zoneID > maxZoneID - 1)
711         {
712             // resize the container
713             maxZoneID = zoneID + zoneIDBuffer;
715             patchTypeIDs.setSize(maxZoneID);
716             patchNameIDs.setSize(maxZoneID);
717         }
719         zoneDataStream >> patchTypeIDs[zoneID];
720         zoneDataStream >> patchNameIDs[zoneID];
722         Info<< "Read zone1:" << zoneID
723             << " name:" << patchNameIDs[zoneID]
724             << " patchTypeID:" << patchTypeIDs[zoneID]
725             << endl;
726     }
728 <readZoneGroupData>{space}{label}{space}{word}{space}{word}{space}{label} {
729         // Fluent manual inconsistency, version 6.1.22
730         IStringStream zoneDataStream(YYText());
732         // cell zone-ID not in hexadecimal!!! Inconsistency
733         label zoneID(readLabel(zoneDataStream));
735         if (zoneID > maxZoneID - 1)
736         {
737             // resize the container
738             maxZoneID = zoneID + zoneIDBuffer;
740             patchTypeIDs.setSize(maxZoneID);
741             patchNameIDs.setSize(maxZoneID);
742         }
744         zoneDataStream >> patchTypeIDs[zoneID];
745         zoneDataStream >> patchNameIDs[zoneID];
747         Info<< "Read zone2:" << zoneID
748             << " name:" << patchNameIDs[zoneID]
749             << " patchTypeID:" << patchTypeIDs[zoneID]
750             << endl;
751     }
753 <readZoneGroupData>{endOfSection} {
754         BEGIN(readZoneData);
755     }
757 <readZoneData>{spaceNl}{lbrac} {
758         Info<< "Reading zone data" << endl;
759         yy_push_state(readZoneBlock);
760     }
762 <readZoneBlock>{spaceNl}{schemeSymbolList} {
763     }
765 <readZoneBlock>{lbrac} {
766         Info<< "Found unknown block in zone:" << YYText() << endl;
767         yy_push_state(unknownBlock);
768     }
770 <readZoneBlock>{endOfSection} {
771         yy_pop_state();
772     }
776  /*             ------ Reading end of section and others ------               */
778 <readHeader,readDimension,readPointData,readFaceData,readCellData,readZoneData>{spaceNl}{endOfSection} {
779         BEGIN(INITIAL);
780     }
782  /*    ------ Reading unknown type or non-standard comment ------             */
785 {lbrac}{label} {
786         Info<< "Found unknown block:" << YYText() << endl;
787         yy_push_state(unknownBlock);
788     }
790 <readComment,unknownBlock,embeddedUnknownBlock>{spaceNl}{schemeSymbol} {
791     }
793 <readComment,unknownBlock,embeddedUnknownBlock>{spaceNl}{lbrac} {
794         Info<< "Embedded blocks in comment or unknown:" << YYText() << endl;
795         yy_push_state(embeddedUnknownBlock);
797     }
799 <readComment,unknownBlock,embeddedUnknownBlock>{spaceNl}{endOfSection} {
800         Info<< "Found end of section in unknown:" << YYText() << endl;
801         yy_pop_state();
802     }
804 <unknownBlock,embeddedUnknownBlock>{spaceNl}{labelList} {
805     }
807 <unknownBlock,embeddedUnknownBlock>{spaceNl}{hexLabelList} {
808     }
810 <unknownBlock,embeddedUnknownBlock>{spaceNl}{scalarList} {
811     }
813 <unknownBlock,embeddedUnknownBlock>{spaceNl}{schemeSymbolList} {
814     }
816 <unknownBlock,embeddedUnknownBlock>{spaceNl}{text} {
817     }
820  /* ------ Ignore remaining space and \n s.  Any other characters are errors. */
822 <readPoints2D,readPoints3D>.|\n {
823     Info<< "ERROR! Do not understand characters: " << YYText() << endl;
824     }
825 .|\n {}
828  /*  ------ On EOF return to previous file, if none exists terminate. ------  */
830 <<EOF>> {
831             yyterminate();
832     }
836 #include "fileName.H"
837 #include <fstream>
839 // Find label of face.
840 label findFace(const primitiveMesh& mesh, const face& f)
842     // Get faces using zeroth vertex of face.
843     const labelList& pFaces = mesh.pointFaces()[f[0] ];
845     forAll(pFaces, i)
846     {
847         label faceI = pFaces[i];
849         if (f == mesh.faces()[faceI])
850         {
851             return faceI;
852         }
853     }
855     // Didn't find face. Do what?
856     FatalErrorIn("findFace(const primitiveMesh&, const face&)")
857         << "Problem : cannot find a single face in the mesh which uses"
858         << " vertices " << f << exit(FatalError);
860     return -1;
864 int main(int argc, char *argv[])
866     argList::noParallel();
867     argList::validArgs.append("Fluent mesh file");
868     argList::addOption
869     (
870         "scale",
871         "factor",
872         "geometry scaling factor - default is 1"
873     );
874     argList::addBoolOption
875     (
876         "writeSets",
877         "write cell zones and patches as sets"
878     );
879     argList::addBoolOption
880     (
881         "writeZones",
882         "write cell zones as zones"
883     );
885     argList args(argc, argv);
887     if (!args.check())
888     {
889         FatalError.exit();
890     }
892     const scalar scaleFactor = args.optionLookupOrDefault("scale", 1.0);
894     const bool writeSets  = args.optionFound("writeSets");
895     const bool writeZones = args.optionFound("writeZones");
897 #   include "createTime.H"
899     const fileName fluentFile = args[1];
900     std::ifstream fluentStream(fluentFile.c_str());
902     if (!fluentStream)
903     {
904         FatalErrorIn("fluentToFoam::main(int argc, char *argv[])")
905             << args.executable()
906             << ": file " << fluentFile << " not found"
907             << exit(FatalError);
908     }
910     yyFlexLexer lexer(&fluentStream);
911     while (lexer.yylex() != 0)
912     {}
914     Info<< "\n\nFINISHED LEXING\n\n\n";
915     // Lookup table giving number of vertices given a fluent cell type ID
916     // Currently not used.
917     // label fluentModelNVertices[7] = {-1, 3, 4, 4, 8, 5, 6};
919     // Lookup table giving number of vertices given a fluent cell type ID
920     label fluentModelNFaces[7] = {-1, 3, 4, 4, 6, 5, 5};
922     // Make a list of cell faces to be filled in for owner and neighbour
924     labelListList cellFaces(nCells);
926     labelList nFacesInCell(nCells, 0);
928     forAll(cellFaces, celli)
929     {
930         cellFaces[celli].setSize(fluentModelNFaces[fluentCellModelID[celli] ]);
931     }
933     // fill in owner and neighbour
935     forAll(owner, faceI)
936     {
937         if (owner[faceI] > -1)
938         {
939             label curCell = owner[faceI];
940             cellFaces[curCell][nFacesInCell[curCell] ] = faceI;
942             nFacesInCell[curCell]++;
943         }
944     }
946     forAll(neighbour, faceI)
947     {
948         if (neighbour[faceI] > -1)
949         {
950             label curCell = neighbour[faceI];
951             cellFaces[curCell][nFacesInCell[curCell] ] = faceI;
953             nFacesInCell[curCell]++;
954         }
955     }
957     // Construct shapes from face lists
958     cellShapeList cellShapes(nCells);
960     // Extrude 2-D mesh into 3-D
962     Info<< "dimension of grid: " << dimensionOfGrid << endl;
963     faceList frontAndBackFaces;
965     if (dimensionOfGrid == 2)
966     {
967         const scalar extrusionFactor = 0.01;
969         boundBox box(max(points), min(points));
971         const scalar zOffset = extrusionFactor*box.mag();
973         // two-dimensional grid. Extrude in z-direction
974         Info<< "Grid is 2-D. Extruding in z-direction by: "
975             << 2*zOffset << endl;
977         pointField oldPoints = points;
979         const label pointOffset = oldPoints.size();
981         points.setSize(2*pointOffset);
983         label nNewPoints = 0;
985         // Note: In order for the owner-neighbour rules to be right, the
986         // points given by Fluent need to represent the FRONT plane of the
987         // geometry. Therefore, the extrusion will be in -z direction
988         //
989         forAll(oldPoints, pointI)
990         {
991             points[nNewPoints] = oldPoints[pointI];
993             points[nNewPoints].z() = zOffset;
995             nNewPoints++;
996         }
998         forAll(oldPoints, pointI)
999         {
1000             points[nNewPoints] = oldPoints[pointI];
1002             points[nNewPoints].z() = -zOffset;
1004             nNewPoints++;
1005         }
1007         // 2-D shape recognition
1008         Info<< "Creating shapes for 2-D cells"<< endl;
1010         // Set the number of empty faces
1011         frontAndBackFaces.setSize(2*nCells);
1013         forAll(fluentCellModelID, celli)
1014         {
1015             switch (fluentCellModelID[celli])
1016             {
1017                 case 1:
1018                 {
1019                     cellShapes[celli] =
1020                         cellShape
1021                         (
1022                             extrudedTriangleCellShape
1023                             (
1024                                 celli,
1025                                 cellFaces[celli],
1026                                 faces,
1027                                 owner,
1028                                 neighbour,
1029                                 pointOffset,
1030                                 frontAndBackFaces
1031                             )
1032                         );
1033                 }
1034                 break;
1036                 case 3:
1037                 {
1038                     cellShapes[celli] =
1039                         cellShape
1040                         (
1041                             extrudedQuadCellShape
1042                             (
1043                                 celli,
1044                                 cellFaces[celli],
1045                                 faces,
1046                                 owner,
1047                                 neighbour,
1048                                 pointOffset,
1049                                 frontAndBackFaces
1050                             )
1051                         );
1052                 }
1053                 break;
1055                 default:
1056                 {
1057                     FatalErrorIn("fluentToFoam::main(int argc, char *argv[])")
1058                         << "unrecognised  2-D cell shape: "
1059                         << fluentCellModelID[celli]
1060                         << abort(FatalError);
1061                 }
1062             }
1063         }
1065         // Create new faces
1066         forAll(faces, faceI)
1067         {
1069             if (faces[faceI].size() != 2)
1070             {
1071                 FatalErrorIn("fluentToFoam::main(int argc, char *argv[])")
1072                     << "fluentMeshToFoam: a 2-D face defined with "
1073                     << faces[faceI].size() << " points." << endl;
1074             }
1076             labelList& newFace = faces[faceI];
1078             newFace.setSize(4);
1080             newFace[2] = newFace[1] + pointOffset;
1082             newFace[3] = newFace[0] + pointOffset;
1083         }
1085         // Create new cells from 2-D shapes
1086     }
1087     else
1088     {
1089         // 3-D shape recognition
1090         Info<< "Creating shapes for 3-D cells"<< endl;
1091         forAll(fluentCellModelID, celli)
1092         {
1093             if
1094             (
1095                 fluentCellModelID[celli] == 2    // tet
1096              || fluentCellModelID[celli] == 4    // hex
1097              || fluentCellModelID[celli] == 5    // pyramid
1098              || fluentCellModelID[celli] == 6    // prism
1099             )
1100             {
1101                 cellShapes[celli] =
1102                     cellShape
1103                     (
1104                         create3DCellShape
1105                         (
1106                             celli,
1107                             cellFaces[celli],
1108                             faces,
1109                             owner,
1110                             neighbour,
1111                             fluentCellModelID[celli]
1112                         )
1113                     );
1114             }
1115             else
1116             {
1117                 FatalErrorIn("fluentToFoam::main(int argc, char *argv[])")
1118                     << "unrecognised 3-D cell shape: "
1119                     << fluentCellModelID[celli]
1120                     << abort(FatalError);
1121             }
1122         }
1123     }
1125     // boundary faces are oriented such that the owner is zero and the face
1126     // area vector points into the domain. Turn them round before making patches
1127     // for Foam compatibility
1129     forAll(faces, faceI)
1130     {
1131         if (owner[faceI] == -1)
1132         {
1133             // reverse face
1134             labelList oldFace = faces[faceI];
1136             forAllReverse(oldFace, i)
1137             {
1138                 faces[faceI][oldFace.size() - i - 1] =
1139                     oldFace[i];
1140             }
1141         }
1142     }
1145     //make patchless mesh before analysing boundaries
1147     faceListList patches(0);
1148     wordList patchNames(0);
1149     wordList patchTypes(0);
1150     word defaultFacesName = "defaultFaces";
1151     word defaultFacesType = emptyPolyPatch::typeName;
1152     wordList patchPhysicalTypes(0);
1154     // Scale the points
1156     points *= scaleFactor;
1158     Info<< "Building patch-less mesh..." << flush;
1160     polyMesh pShapeMesh
1161     (
1162         IOobject
1163         (
1164             polyMesh::defaultRegion,
1165             runTime.constant(),
1166             runTime
1167         ),
1168         xferMove(points),
1169         cellShapes,
1170         patches,
1171         patchNames,
1172         patchTypes,
1173         defaultFacesName,
1174         defaultFacesType,
1175         patchPhysicalTypes
1176     );
1178     //dont write mesh yet, otherwise preservePatchTypes will be broken
1179     //and zones wont be written
1180     //checkmesh done after patch addition as well
1181     Info<< "done." << endl;
1184     Info<< endl << "Building boundary and internal patches." << endl;
1185     //adding patches after mesh construction allows topological checks
1186     //on whether a patch is internal or external, something fluent
1187     //doesnt seem to mind
1189     // Make boundary patches
1191     SLList<label>::iterator faceGroupZoneIDIter = faceGroupZoneID.begin();
1192     SLList<label>::iterator faceGroupStartIndexIter =
1193         faceGroupStartIndex.begin();
1194     SLList<label>::iterator faceGroupEndIndexIter = faceGroupEndIndex.begin();
1196     // Note. Not all groups of faces will be boundary patches.
1197     // Take care on construction
1199     //2D needs extra space for frontAndBack faces
1200     if (dimensionOfGrid == 2)
1201     {
1202         patches.setSize(faceGroupZoneID.size()+1);
1203         patchNames.setSize(faceGroupZoneID.size()+1);
1204         patchTypes.setSize(faceGroupZoneID.size()+1);
1205         patchPhysicalTypes.setSize(faceGroupZoneID.size()+1);
1206     }
1207     else
1208     {
1209         patches.setSize(faceGroupZoneID.size());
1210         patchNames.setSize(faceGroupZoneID.size());
1211         patchTypes.setSize(faceGroupZoneID.size());
1212         patchPhysicalTypes.setSize(faceGroupZoneID.size());
1213     }
1215     label nPatches = 0;
1217     //colate information for all patches (internal and external)
1218     for
1219     (
1220         ;
1221         faceGroupZoneIDIter != faceGroupZoneID.end()
1222      && faceGroupStartIndexIter != faceGroupStartIndex.end()
1223      && faceGroupEndIndexIter != faceGroupEndIndex.end();
1224         ++faceGroupZoneIDIter,
1225         ++faceGroupStartIndexIter,
1226         ++faceGroupEndIndexIter
1227     )
1228     {
1229         // get face type and name
1230         const word& curPatchType = patchTypeIDs[faceGroupZoneIDIter()];
1232         const word& curPatchName = patchNameIDs[faceGroupZoneIDIter()];
1234         Info<< "Creating patch " << nPatches
1235             << " for zone: " << faceGroupZoneIDIter()
1236             << " start: " << faceGroupStartIndexIter()
1237             << " end: " << faceGroupEndIndexIter()
1238             << " type: " << curPatchType << " name: " << curPatchName << endl;
1240         // make patch labels
1241         label faceLabel = faceGroupStartIndexIter() - 1;
1243         faceList patchFaces(faceGroupEndIndexIter() - faceLabel);
1245         forAll(patchFaces, faceI)
1246         {
1247             if
1248             (
1249                 faces[faceLabel].size() == 3
1250              || faces[faceLabel].size() == 4
1251             )
1252             {
1253                 patchFaces[faceI] = face(faces[faceLabel]);
1254                 faceLabel++;
1255             }
1256             else
1257             {
1258                 FatalErrorIn("fluentToFoam::main(int argc, char *argv[])")
1259                     << "unrecognised face shape with "
1260                     << patchFaces[faceI].size() << " vertices"
1261                     << abort(FatalError);
1262             }
1263         }
1265         //inlets and outlets
1266         if
1267         (
1268             curPatchType == "pressure"
1269          || curPatchType == "pressure-inlet"
1270          || curPatchType == "inlet-vent"
1271          || curPatchType == "intake-fan"
1272          || curPatchType == "pressure-outlet"
1273          || curPatchType == "exhaust-fan"
1274          || curPatchType == "outlet-vent"
1275          || curPatchType == "pressure-far-field"
1276          || curPatchType == "velocity-inlet"
1277          || curPatchType == "mass-flow-inlet"
1278          || curPatchType == "outflow"
1279         )
1280         {
1281             patches[nPatches] = patchFaces;
1282             patchTypes[nPatches] = polyPatch::typeName;
1283             patchNames[nPatches] = curPatchName;
1285             nPatches++;
1286         }
1287         else if (curPatchType == "wall" ) //wall boundaries
1288         {
1289             patches[nPatches] = patchFaces;
1290             patchTypes[nPatches] = wallPolyPatch::typeName;
1291             patchNames[nPatches] = curPatchName;
1293             nPatches++;
1294         }
1295         else if
1296         (
1297             curPatchType == "symmetry"
1298          || curPatchType == "axis"
1299         ) //symmetry planes
1300         {
1301             patches[nPatches] = patchFaces;
1302             patchTypes[nPatches] = symmetryPolyPatch::typeName;
1303             patchNames[nPatches] = curPatchName;
1305             nPatches++;
1306         }
1307         else if
1308         (
1309             curPatchType == "interior"
1310          || curPatchType == "interface"
1311          || curPatchType == "internal"
1312          || curPatchType == "solid"
1313          || curPatchType == "fan"
1314          || curPatchType == "radiator"
1315          || curPatchType == "porous-jump"
1316         ) //interior boundaries - will not be added as patches
1317         {
1318             patches[nPatches] = patchFaces;
1319             patchTypes[nPatches] = "internal";
1320             patchNames[nPatches] = curPatchName;
1322             nPatches++;
1323         }
1324         else if
1325         (
1326             curPatchType == ""
1327         ) //unnamed face regions default to interior patches
1328         {
1329             Info<< "Patch " << faceGroupZoneIDIter()
1330                 << ": Faces are defined but "
1331                 << "not created as a zone." << endl
1332                 << "Null specification is only valid for internal faces."
1333                 << endl;
1335             patches[nPatches] = patchFaces;
1336             patchTypes[nPatches] = "internal";
1337             patchNames[nPatches] = curPatchName;
1339             nPatches++;
1340         }
1341         else //unknown face regions are not handled
1342         {
1343             FatalErrorIn("fluentToFoam::main(int argc, char *argv[])")
1344                 << "fluent patch type " << curPatchType << " not recognised."
1345                 << abort(FatalError);
1346         }
1347     }
1349     //add front and back boundaries for 2D meshes
1350     if (dimensionOfGrid == 2)
1351     {
1352         Info<< "Creating patch for front and back planes" << endl << endl;
1354         patches[nPatches] = frontAndBackFaces;
1355         patchTypes[nPatches] = emptyPolyPatch::typeName;
1356         patchNames[nPatches] = "frontAndBackPlanes";
1358         nPatches++;
1359     }
1361     //Now have all patch information,
1362     //check whether each patch is internal or external
1363     //and add boundaries to mesh
1364     //also write face sets of all patches
1365     patches.setSize(nPatches);
1366     patchTypes.setSize(nPatches);
1367     patchNames.setSize(nPatches);
1370     //old polyBoundary
1371     const polyBoundaryMesh& oPatches = pShapeMesh.boundaryMesh();
1372     // new patches.
1373     DynamicList<polyPatch*> newPatches(nPatches);
1375     // For every boundary face the old patch.
1376     labelList facePatchID(pShapeMesh.nFaces()-pShapeMesh.nInternalFaces(), -1);
1377     label cMeshFace = pShapeMesh.nInternalFaces();
1378     label nBoundaries = 0;
1381     forAll(patches, patchI)
1382     {
1383         const faceList& bFaces = patches[patchI];
1385         label sz = bFaces.size();
1386         labelList meshFaces(sz,-1);
1389         //make face set and write (seperate from rest for clarity)
1390         //internal and external Fluent boundaries
1391         {
1392             faceSet pFaceSet(pShapeMesh, patchNames[patchI], sz);
1394             forAll(bFaces, j)
1395             {
1396                 const face& f = bFaces[j];
1397                 label cMeshFace = findFace(pShapeMesh, f);
1398                 meshFaces[j] = cMeshFace;
1399                 pFaceSet.insert(cMeshFace);
1400             }
1401             if (writeSets)
1402             {
1403                 Info<< "Writing patch " << patchNames[patchI]
1404                     << " of size " << sz << " to faceSet." << endl;
1405                 pFaceSet.write();
1406             }
1407         }
1410         //check if patch is internal
1411         //also check internal/external-ness of first patch face
1412         //internal faces cannot become foam boundaries
1413         //if a face is defined as internal but is actually external
1414         //it will be put in a default wall boundary
1415         //internal boundaries are simply ignored
1417         if
1418         (
1419             patchTypes[patchI] != "internal"
1420          && !pShapeMesh.isInternalFace(meshFaces[0])
1421         )
1422         {
1423             //first face is external and has valid non-internal type
1425             //check all faces for externalness just to be sure
1426             //and mark patch number to global list
1427             forAll(meshFaces, i)
1428             {
1429                 label faceI = meshFaces[i];
1431                 if (pShapeMesh.isInternalFace(faceI))
1432                 {
1433                     FatalErrorIn(args.executable())
1434                         << "Face " << faceI << " on new patch "
1435                         << patchNames[patchI]
1436                         << " is not an external face of the mesh." << endl
1437                         << exit(FatalError);
1438                 }
1440                 if (facePatchID[faceI - pShapeMesh.nInternalFaces()]!= -1)
1441                 {
1442                     FatalErrorIn(args.executable())
1443                         << "Face " << faceI << " on new patch "
1444                         << patchNames[patchI]
1445                         << " has already been marked for repatching to"
1446                         << " patch "
1447                         << facePatchID[faceI - pShapeMesh.nInternalFaces()]
1448                         << exit(FatalError);
1449                 }
1450                 facePatchID[faceI - pShapeMesh.nInternalFaces()] = nBoundaries;
1451             }
1453             //add to boundary patch
1455             Info<< "Adding new patch " << patchNames[patchI]
1456                 << " of type " << patchTypes[patchI]
1457                 << " as patch " << nBoundaries << endl;
1459             // Add patch to new patch list
1460             newPatches.append
1461             (
1462                 polyPatch::New
1463                 (
1464                     patchTypes[patchI],
1465                     patchNames[patchI],
1466                     sz,
1467                     cMeshFace,
1468                     nBoundaries,
1469                     oPatches
1470                 ).ptr()
1471             );
1472             nBoundaries++;
1473             cMeshFace += sz;
1474         }
1475         else
1476         {
1477             Info<< "Patch " << patchNames[patchI]
1478                  << " is internal to the mesh "
1479                  << " and is not being added to the boundary."
1480                  << endl;
1482         }
1483     }
1485     // Check for any remaining boundary faces
1486     // and add them to a default wall patch
1487     // this routine should generally not be invoked
1488     {
1489         DynamicList<label> defaultBoundaryFaces(facePatchID.size());
1490         forAll(facePatchID, idI)
1491         {
1492             if (facePatchID[idI] == -1)
1493             {
1494                 defaultBoundaryFaces.append(idI);
1495                 facePatchID[idI] = nBoundaries;
1496             }
1497         }
1498         defaultBoundaryFaces.shrink();
1500         if (defaultBoundaryFaces.size())
1501         {
1502             Warning << " fluent mesh has " << defaultBoundaryFaces.size()
1503                     << " undefined boundary faces." << endl
1504                     << " Adding undefined faces to new patch `default_wall`"
1505                     << endl;
1507             // Add patch to new patch list
1509             newPatches.append
1510             (
1511                 polyPatch::New
1512                 (
1513                     wallPolyPatch::typeName,
1514                     "default_wall",
1515                     defaultBoundaryFaces.size(),
1516                     cMeshFace,
1517                     nBoundaries,
1518                     oPatches
1519                 ).ptr()
1520             );
1521             nBoundaries++;
1522             cMeshFace += defaultBoundaryFaces.size();
1523         }
1524     }
1526     newPatches.shrink();
1528     // Use facePatchIDs map to reorder boundary faces into compact regions
1530     repatchPolyTopoChanger repatcher(pShapeMesh);
1532     // Add new list of patches
1533     repatcher.changePatches(newPatches);
1535     // Change patch ids
1536     forAll(facePatchID, idI)
1537     {
1538         label faceI = idI + pShapeMesh.nInternalFaces();
1540         repatcher.changePatchID(faceI, facePatchID[idI]);
1541     }
1542     repatcher.repatch();
1545     // Set the precision of the points data to 10
1546     IOstream::defaultPrecision(10);
1549     // Zones
1550     // will write out cell zones and internal faces for those zones
1551     // note: zone boundary faces are not added to face zones
1552     // the names of boundaries bordering on cell zones are written to
1553     // a list containing the boundary name and cellzone it borders on
1554     // interior boundaries are handled via faceSets
1555     // cell zones will only be written if there is more than one
1557     if (writeZones && cellGroupZoneID.size() > 1)
1558     {
1559         Info<< "Adding Zones" << endl;
1560         List<pointZone*> pz(0);
1562         label nrCellZones = cellGroupZoneID.size();
1563         List<cellZone*> cz(nrCellZones);
1565         // Make face zones for cell zones
1566         List<faceZone*> fz(nrCellZones);
1568         // List of patch names and the cellZone(s) they border
1569         // this is just an info file to make MRF easier to setup
1570         List<DynamicList<word> > boundaryZones
1571         (
1572             pShapeMesh.boundaryMesh().size()
1573         );
1575         const polyBoundaryMesh& bPatches = pShapeMesh.boundaryMesh();
1576         forAll(bPatches, pI)
1577         {
1578             boundaryZones[pI].append(bPatches[pI].name());
1579         }
1581         label cnt=0;
1582         SLList<label>::iterator cg = cellGroupZoneID.begin();
1583         SLList<label>::iterator start = cellGroupStartIndex.begin();
1584         SLList<label>::iterator end = cellGroupEndIndex.begin();
1586         for (; cg != cellGroupZoneID.end(); ++cg, ++start, ++end)
1587         {
1588             const word& name = patchNameIDs[cg()];
1589             const word& type = patchTypeIDs[cg()];
1591             Info<< "Writing cell zone: " << name
1592                 << " of type " << type << " starting at " << start() - 1
1593                 << " ending at " << end() - 1 << " to cellSet." << endl;
1595             labelList cls(end() - start() + 1);
1597             // Mark zone cells, used for finding faces
1598             boolList zoneCell(pShapeMesh.nCells(), false);
1600             // shift cell indizes by 1
1601             label nr=0;
1602             for (label celli = (start() - 1); celli < end(); celli++)
1603             {
1604                 cls[nr]=celli;
1605                 zoneCell[celli] = true;
1606                 nr++;
1607             }
1609             cz[cnt] = new cellZone
1610             (
1611                 name,
1612                 cls,
1613                 cnt,
1614                 pShapeMesh.cellZones()
1615             );
1617             DynamicList<label> zoneFaces(pShapeMesh.nFaces());
1618             forAll(pShapeMesh.faceNeighbour(), faceI)
1619             {
1620                 label nei = pShapeMesh.faceNeighbour()[faceI];
1621                 label own = pShapeMesh.faceOwner()[faceI];
1622                 if (nei != -1)
1623                 {
1624                     if (zoneCell[nei] && zoneCell[own])
1625                     {
1626                         zoneFaces.append(faceI);
1627                     }
1628                 }
1629             }
1630             zoneFaces.shrink();
1632             fz[cnt] = new faceZone
1633             (
1634                 name,
1635                 zoneFaces,
1636                 boolList(zoneFaces.size(), false),
1637                 cnt,
1638                 pShapeMesh.faceZones()
1639             );
1641             // Add cell zones to patch zone list
1642             forAll(bPatches, pI)
1643             {
1644                 const labelList& faceCells = bPatches[pI].faceCells();
1645                 forAll(faceCells, fcI)
1646                 {
1647                     if (zoneCell[faceCells[fcI] ])
1648                     {
1649                         boundaryZones[pI].append(name);
1650                         break;
1651                     }
1652                 }
1653             }
1655             cnt++;
1656         }
1658         pShapeMesh.addZones(pz, fz, cz);
1660         forAll(bPatches, pI)
1661         {
1662             boundaryZones[pI].shrink();
1663         }
1665         fileName bczf
1666         (
1667             runTime.path()/runTime.constant()
1668            /"polyMesh"/"boundaryAdjacentCellZones"
1669         );
1671         OFstream boundaryCellZonesFile(bczf);
1672         forAll(boundaryZones, bzI)
1673         {
1674             forAll(boundaryZones[bzI], bzII)
1675             {
1676                 boundaryCellZonesFile << boundaryZones[bzI][bzII] << " ";
1677             }
1679             boundaryCellZonesFile << endl;
1680         }
1681     }
1683     Info<< endl << "Writing mesh..." << flush;
1685     Info<< " to " << pShapeMesh.instance()/pShapeMesh.meshDir()
1686         << "  " << flush;
1688     pShapeMesh.setInstance(pShapeMesh.instance());
1689     pShapeMesh.write();
1690     Info<< "done." << endl << endl;
1692     // Write cellSets for Fluent regions
1693     // allows easy post-processing
1694     // set and zone functionality will be integrated some time
1695     // soon negating the need for double output
1696     if (writeSets)
1697     {
1698         if (cellGroupZoneID.size() > 1)
1699         {
1700             Info<< "Writing cell sets" << endl;
1702             SLList<label>::iterator cg = cellGroupZoneID.begin();
1703             SLList<label>::iterator start = cellGroupStartIndex.begin();
1704             SLList<label>::iterator end = cellGroupEndIndex.begin();
1706             // Note: cellGroupXXX are all Fluent indices (starting at 1)
1707             // so offset before using.
1709             for (; cg != cellGroupZoneID.end(); ++cg, ++start, ++end)
1710             {
1711                 const word& name=patchNameIDs[cg()];
1712                 const word& type=patchTypeIDs[cg()];
1714                 Info<< "Writing cell set: " << name
1715                     << " of type " << type << " starting at " << start() - 1
1716                     << " ending at " << end() - 1 << " to cellSet." << endl;
1718                 cellSet internal(pShapeMesh, name, end() - start());
1720                 // shift cell indizes by 1
1721                 for (label celli = start() - 1; celli <= end() - 1; celli++)
1722                 {
1723                     internal.insert(celli);
1724                 }
1726                 internal.write();
1727             }
1728         }
1729         else
1730         {
1731             Info<< "Only one cell group: no set written\n";
1732         }
1733     }
1735     Info<< "\nEnd\n" << endl;
1736     return 0;
1740  /* ------------------------------------------------------------------------- *\
1741     ------ End of fluentMeshToFoam.L
1742  \* ------------------------------------------------------------------------- */