initial commit for version 1.6.x patch release
[OpenFOAM-1.6.x.git] / applications / utilities / mesh / conversion / fluentMeshToFoam / fluentMeshToFoam.L
blobd1afc4523a5e0ba97cacaa6abd9a4eeecdeebfa7
1 /*--------------------------------*- C++ -*----------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2009 OpenCFD Ltd.
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 the
13     Free Software Foundation; either version 2 of the License, or (at your
14     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, write to the Free Software Foundation,
23     Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 Application
26     fluentMeshToFoam
28 Description
29     Converts a Fluent mesh to FOAM format
30     including multiple region and region boundary handling.
32 \*---------------------------------------------------------------------------*/
36 #undef yyFlexLexer
38  /* ------------------------------------------------------------------------- *\
39    ------ local definitions
40  \* ------------------------------------------------------------------------- */
42 #include "argList.H"
43 #include "Time.H"
44 #include "IStringStream.H"
45 #include "polyMesh.H"
46 #include "emptyPolyPatch.H"
47 #include "wallPolyPatch.H"
48 #include "symmetryPolyPatch.H"
49 #include "preservePatchTypes.H"
50 #include "cellShape.H"
51 #include "faceSet.H"
52 #include "cellSet.H"
53 #include "meshTools.H"
54 #include "OFstream.H"
56 #include "readHexLabel.H"
57 #include "cellShapeRecognition.H"
58 #include "repatchPolyTopoChanger.H"
61 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
63 using namespace Foam;
65 const scalar convertToMeters = 1.0;
67 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
70 label dimensionOfGrid = 0;
72 label nPoints = 0;
73 label nFaces = 0;
74 label nCells = 0;
76 pointField points(0);
77 SLList<label> pointGroupZoneID;
78 SLList<label> pointGroupStartIndex;
79 SLList<label> pointGroupEndIndex;
82 faceList faces(0);
83 labelList owner(0);
84 labelList neighbour(0);
85 SLList<label> faceGroupZoneID;
86 SLList<label> faceGroupStartIndex;
87 SLList<label> faceGroupEndIndex;
89 labelList fluentCellModelID(0);
90 SLList<label> cellGroupZoneID;
91 SLList<label> cellGroupStartIndex;
92 SLList<label> cellGroupEndIndex;
93 SLList<label> cellGroupType;
95 // number of zones adjusted at run-time if necessary
96 label maxZoneID = 100;
97 label zoneIDBuffer = 10;
99 wordList patchTypeIDs(maxZoneID);
100 wordList patchNameIDs(maxZoneID);
102 // Dummy yywrap to keep yylex happy at compile time.
103 // It is called by yylex but is not used as the mechanism to change file.
104 // See <<EOF>>
105 #if YY_FLEX_SUBMINOR_VERSION < 34
106 extern "C" int yywrap()
107 #else
108 int yyFlexLexer::yywrap()
109 #endif
111     return 1;
116 one_space                  [ \t\f]
117 space                      {one_space}*
118 some_space                 {one_space}+
119 cspace                     ","{space}
120 spaceNl                    ({space}|\n|\r)*
122 alpha                      [_[:alpha:]]
123 digit                      [[:digit:]]
124 decDigit                   [[:digit:]]
125 octalDigit                 [0-7]
126 hexDigit                   [[:xdigit:]]
128 lbrac                      "("
129 rbrac                      ")"
130 quote                      \"
131 dash                       "-"
132 dotColonDash               [.:-]
134 schemeSpecialInitial       [!$%&*/:<=>?~_^#.]
135 schemeSpecialSubsequent    [.+-]
136 schemeSymbol               (({some_space}|{alpha}|{quote}|{schemeSpecialInitial})({alpha}|{quote}|{digit}|{schemeSpecialInitial}|{schemeSpecialSubsequent})*)
139 identifier                 {alpha}({alpha}|{digit})*
140 integer                    {decDigit}+
141 label                      [1-9]{decDigit}*
142 hexLabel                   {hexDigit}+
143 zeroLabel                  {digit}*
145 word                       ({alpha}|{digit}|{dotColonDash})*
147 exponent_part              [eE][-+]?{digit}+
148 fractional_constant        [-+]?(({digit}*"."{digit}+)|({digit}+".")|({digit}))
150 double                     ((({fractional_constant}{exponent_part}?)|({digit}+{exponent_part}))|0)
152 x                          {double}
153 y                          {double}
154 z                          {double}
155 scalar                     {double}
156 labelListElement           {space}{zeroLabel}
157 hexLabelListElement        {space}{hexLabel}
158 scalarListElement          {space}{double}
159 schemeSymbolListElement    {space}{schemeSymbol}
160 labelList                  ({labelListElement}+{space})
161 hexLabelList               ({hexLabelListElement}+{space})
162 scalarList                 ({scalarListElement}+{space})
163 schemeSymbolList           ({schemeSymbolListElement}+{space})
165 starStar                   ("**")
166 text                       ({space}({word}*{space})*)
168 dateDDMMYYYY               ({digit}{digit}"/"{digit}{digit}"/"{digit}{digit}{digit}{digit})
169 dateDDMonYYYY              ((({digit}{digit}{space})|({digit}{space})){alpha}*{space}{digit}{digit}{digit}{digit})
170 time                       ({digit}{digit}":"{digit}{digit}":"{digit}{digit})
172 versionNumber              ({digit}|".")*
174 comment                    {spaceNl}"(0"{space}
175 header                     {spaceNl}"(1"{space}
176 dimension                  {spaceNl}"(2"{space}
177 point                      {spaceNl}"(10"{space}
178 fluentFace                 {spaceNl}"(13"{space}
179 cell                       {spaceNl}"(12"{space}
180 zoneVariant1               {spaceNl}"(39"{space}
181 zoneVariant2               {spaceNl}"(45"{space}
183 unknownPeriodicFace        {spaceNl}"(17"{space}
184 periodicFace               {spaceNl}"(18"{space}
185 cellTree                   {spaceNl}"(58"{space}
186 faceTree                   {spaceNl}"(59"{space}
187 faceParents                {spaceNl}"(61"{space}
189 endOfSection               {space}")"{space}
193  /* ------------------------------------------------------------------------- *\
194                       -----  Exclusive start states -----
195  \* ------------------------------------------------------------------------- */
197 %option stack
199 %x readComment
200 %x embeddedCommentState
201 %x readHeader
202 %x readDimension
203 %x readPoint
204 %x readPointHeader
205 %x readNumberOfPoints
206 %x readPointGroupData
207 %x readPointData
208 %x readPoints2D
209 %x readPoints3D
210 %x fluentFace
211 %x readFaceHeader
212 %x readNumberOfFaces
213 %x readFaceGroupData
214 %x readFaceData
215 %x readFacesMixed
216 %x readFacesUniform
217 %x cell
218 %x readCellHeader
219 %x readNumberOfCells
220 %x readCellGroupData
221 %x readCellData
222 %x readCellsMixed
223 %x readCellsUniform
224 %x zone
225 %x readZoneHeader
226 %x readZoneGroupData
227 %x readZoneData
228 %x readZoneBlock
230 %x periodicFace
231 %x cellTree
232 %x faceTree
233 %x faceParents
235 %x unknownBlock
236 %x embeddedUnknownBlock
240     // Point data
241     label pointGroupNumberOfComponents = 3;
242     label pointI = 0; // index used for reading points
244     // Face data
245     label faceGroupElementType = -1;
246     label faceI = 0;
248     // Cell data
249     label cellGroupElementType = -1;
250     label celli = 0;
254  /* ------------------------------------------------------------------------- *\
255                             ------ Start Lexing ------
256  \* ------------------------------------------------------------------------- */
258  /*                      ------ Reading control header ------                 */
260 {comment} {
261         yy_push_state(readComment);
262     }
265 <readComment>{quote}{text}{quote} {
266     }
269 <readComment>{spaceNl}{endOfSection} {
270         yy_pop_state();
271     }
273 {header} {
274         BEGIN(readHeader);
275     }
277 <readHeader>{quote}{text}{quote} {
278         Info<< "Reading header: " << YYText() << endl;
279     }
282 {dimension} {
283         BEGIN(readDimension);
284     }
286 <readDimension>{space}{label}{space} {
287         IStringStream dimOfGridStream(YYText());
289         dimensionOfGrid = readLabel(dimOfGridStream);
291         Info<< "Dimension of grid: " << dimensionOfGrid << endl;
292     }
295 {point} {
296         BEGIN(readPointHeader);
297     }
299 <readPointHeader>{spaceNl}{lbrac}{space}"0"{space}"1"{space} {
300         BEGIN(readNumberOfPoints);
301     }
303 <readNumberOfPoints>{space}{hexLabel}{space}{labelList} {
305         IStringStream numberOfPointsStream(YYText());
307         nPoints = readHexLabel(numberOfPointsStream);
309         Info<< "Number of points: " << nPoints << endl;
311         // set the size of the points list
312         points.setSize(nPoints);
314         // meaningless type skipped
315         readLabel(numberOfPointsStream);
317         // this dimension of grid may be checked against global dimension
318         if (numberOfPointsStream)
319         {
320             // check dimension of grid
321             readLabel(numberOfPointsStream);
322         }
323         else
324         {
325             Info<< endl;
326         }
327     }
329 <readPointHeader>{spaceNl}{lbrac} {
330         BEGIN(readPointGroupData);
331     }
333 <readPointGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{labelList} {
334         IStringStream pointGroupDataStream(YYText());
336         // read point zone-ID, start and end-label
337         // the indices will be used for checking later.
338         pointGroupZoneID.append(readHexLabel(pointGroupDataStream));
340         pointGroupStartIndex.append(readHexLabel(pointGroupDataStream));
342         pointGroupEndIndex.append(readHexLabel(pointGroupDataStream));
344         // point group type skipped
345         readHexLabel(pointGroupDataStream);
347         // In FOAM, indices start from zero - adjust
348         pointI = pointGroupStartIndex.last() - 1;
350         // reset number of components to default
351         pointGroupNumberOfComponents = 3;
353         // read number of components in the vector
354         if (pointGroupDataStream)
355         {
356             pointGroupNumberOfComponents = readLabel(pointGroupDataStream);
357         }
358     }
360 <readNumberOfPoints,readPointGroupData>{endOfSection} {
361         BEGIN(readPointData);
362     }
364 <readPointData>{spaceNl}{lbrac} {
366         Info<< "Reading points" << endl;
368         if (pointGroupNumberOfComponents == 2)
369         {
370             yy_push_state(readPoints2D);
371         }
372         else
373         {
374             yy_push_state(readPoints3D);
375         }
376     }
378 <readPoints2D>{spaceNl}{scalarList} {
380         IStringStream vertexXyzStream(YYText());
382         // Note: coordinates must be read one at the time.
383         scalar x = readScalar(vertexXyzStream);
384         scalar y = readScalar(vertexXyzStream);
386         points[pointI] = point(x, y, 0);
387         pointI++;
388     }
390 <readPoints3D>{spaceNl}{scalarList} {
392         IStringStream vertexXyzStream(YYText());
394         // Note: coordinates must be read one at the time.
395         scalar x = readScalar(vertexXyzStream);
396         scalar y = readScalar(vertexXyzStream);
397         scalar z = readScalar(vertexXyzStream);
399         points[pointI] = convertToMeters*point(x, y, z);
400         pointI++;
401     }
403 <readPoints2D,readPoints3D>{spaceNl}{endOfSection} {
405         // check read of points
406         if (pointI != pointGroupEndIndex.last())
407         {
408             Info<< "problem with reading points: "
409                 << "start index: " << pointGroupStartIndex.last()
410                 << " end index: " << pointGroupEndIndex.last()
411                 << " last points read: " << pointI << endl;
412         }
414         yy_pop_state();
415     }
418 {fluentFace} {
419         BEGIN(readFaceHeader);
420     }
422 <readFaceHeader>{spaceNl}{lbrac}{space}"0"{space}"1"{space} {
423         BEGIN(readNumberOfFaces);
424     }
426 <readNumberOfFaces>{space}{hexLabel}{space}{labelListElement}+ {
428         IStringStream numberOfFacesStream(YYText());
430         nFaces = readHexLabel(numberOfFacesStream);
432         Info<< "number of faces: " << nFaces << endl;
434         faces.setSize(nFaces);
435         owner.setSize(nFaces);
436         neighbour.setSize(nFaces);
438         // Meaningless type and element type not read
439     }
441 <readFaceHeader>{spaceNl}{lbrac} {
442         BEGIN(readFaceGroupData);
443     }
445 <readFaceGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{hexLabelListElement}+ {
447         IStringStream faceGroupDataStream(YYText());
449         // read fluentFace zone-ID, start and end-label
450         faceGroupZoneID.append(readHexLabel(faceGroupDataStream));
452         // the indices will be used for checking later.
453         faceGroupStartIndex.append(readHexLabel(faceGroupDataStream));
455         faceGroupEndIndex.append(readHexLabel(faceGroupDataStream));
457         // face group type
458         readHexLabel(faceGroupDataStream);
460         faceGroupElementType = readHexLabel(faceGroupDataStream);
462         // In FOAM, indices start from zero - adjust
463         faceI = faceGroupStartIndex.last() - 1;
464     }
466 <readNumberOfFaces,readFaceGroupData>{spaceNl}{endOfSection} {
467         BEGIN(readFaceData);
468     }
470 <readFaceData>{spaceNl}{lbrac} {
472         if (faceGroupElementType == 0)
473         {
474             Info<< "Reading mixed faces" << endl;
475             yy_push_state(readFacesMixed);
476         }
477         else
478         {
479             Info<< "Reading uniform faces" << endl;
480             yy_push_state(readFacesUniform);
481         }
482     }
484 <readFacesMixed>{spaceNl}{hexLabelList} {
486         IStringStream mixedFaceStream(YYText());
488         face& curFaceLabels = faces[faceI];
490         // set size of label list
491         curFaceLabels.setSize(readLabel(mixedFaceStream));
493         forAll (curFaceLabels, i)
494         {
495             curFaceLabels[i] = readHexLabel(mixedFaceStream) - 1;
496         }
498         // read neighbour and owner. Neighbour comes first
499         neighbour[faceI] = readHexLabel(mixedFaceStream) - 1;
500         owner[faceI] = readHexLabel(mixedFaceStream) - 1;
501         faceI++;
502     }
504 <readFacesUniform>{spaceNl}{hexLabelList} {
506         IStringStream mixedFaceStream(YYText());
508         face& curFaceLabels = faces[faceI];
510         // set size of label list. This is OK because in Fluent the type
511         // for edge is 2, for triangle is 3 and for quad is 4
512         curFaceLabels.setSize(faceGroupElementType);
514         forAll (curFaceLabels, i)
515         {
516             curFaceLabels[i] = readHexLabel(mixedFaceStream) - 1;
517         }
519         // read neighbour and owner. Neighbour comes first
520         neighbour[faceI] = readHexLabel(mixedFaceStream) - 1;
521         owner[faceI] = readHexLabel(mixedFaceStream) - 1;
522         faceI++;
523     }
525 <readFacesMixed,readFacesUniform>{spaceNl}{endOfSection} {
527         // check read of fluentFaces
528         if (faceI != faceGroupEndIndex.last())
529         {
530             Info<< "problem with reading fluentFaces: "
531                 << "start index: " << faceGroupStartIndex.last()
532                 << " end index: " << faceGroupEndIndex.last()
533                 << " last fluentFaces read: " << faceI << endl;
534         }
536         yy_pop_state();
537     }
540 {cell} {
541         BEGIN(readCellHeader);
542     }
544 <readCellHeader>{spaceNl}{lbrac}{space}"0"{space}"1"{space} {
545         BEGIN(readNumberOfCells);
546     }
548 <readNumberOfCells>{space}{hexLabel}{space}{labelListElement}+ {
550         IStringStream numberOfCellsStream(YYText());
552         nCells = readHexLabel(numberOfCellsStream);
554         Info<< "Number of cells: " << nCells << endl;
556         fluentCellModelID.setSize(nCells);
558         // Meaningless type and element type not read
559     }
561 <readCellHeader>{spaceNl}{lbrac} {
562         BEGIN(readCellGroupData);
563     }
565 <readCellGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{space}{hexLabel} {
566         // Warning. This entry must be above the next one because of the lexing
567         // rules. It is introduced to deal with the problem of reading
568         // non-standard cell definition from Tgrid, which misses the type label.
570         Info<< "Tgrid syntax problem: " << YYText() << endl;
571         IStringStream cellGroupDataStream(YYText());
573         // read cell zone-ID, start and end-label
574         cellGroupZoneID.append(readHexLabel(cellGroupDataStream));
576         // the indices will be used for checking later.
577         cellGroupStartIndex.append(readHexLabel(cellGroupDataStream));
579         cellGroupEndIndex.append(readHexLabel(cellGroupDataStream));
581         cellGroupType.append(readHexLabel(cellGroupDataStream));
583         Info<< "cellGroupZoneID:" << cellGroupZoneID.last()
584             << endl;
585         Info<< "cellGroupStartIndex:" << cellGroupStartIndex.last()
586             << endl;
587         Info<< "cellGroupEndIndex:" << cellGroupEndIndex.last()
588             << endl;
589         Info<< "cellGroupType:" << cellGroupType.last()
590             << endl;
593         // Note. Potentially skip cell set if type is zero.
594         // This entry does not exist in Tgrid files.
595         if (dimensionOfGrid == 2)
596         {
597             // Tgrid creating triangles
598             cellGroupElementType = 1;
599         }
600         else
601         {
602             cellGroupElementType = 2;
603         }
605         // In FOAM, indices start from zero - adjust
606         celli = cellGroupStartIndex.last() - 1;
608         if (cellGroupElementType != 0)
609         {
610             label lastIndex = cellGroupEndIndex.last();
612             for (; celli < lastIndex; celli++)
613             {
614                 fluentCellModelID[celli] = cellGroupElementType;
615             }
616         }
617     }
619 <readCellGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{space}{hexLabel} {
620         // Warning. See above
622         Info<< "Other readCellGroupData: " << YYText() << endl;
625         IStringStream cellGroupDataStream(YYText());
627         // read cell zone-ID, start and end-label
628         cellGroupZoneID.append(readHexLabel(cellGroupDataStream));
630         // the indices will be used for checking later.
631         cellGroupStartIndex.append(readHexLabel(cellGroupDataStream));
633         cellGroupEndIndex.append(readHexLabel(cellGroupDataStream));
635         cellGroupType.append(readHexLabel(cellGroupDataStream));
637         // Note. Potentially skip cell set if type is zero.
639         cellGroupElementType = readHexLabel(cellGroupDataStream);
641         // In FOAM, indices start from zero - adjust
642         celli = cellGroupStartIndex.last() - 1;
644         if (cellGroupElementType != 0)
645         {
646             Info<< "Reading uniform cells" << endl;
647             label lastIndex = cellGroupEndIndex.last();
649             for (; celli < lastIndex; celli++)
650             {
651                 fluentCellModelID[celli] = cellGroupElementType;
652             }
653         }
654     }
656 <readNumberOfCells,readCellGroupData>{endOfSection} {
657         BEGIN(readCellData);
658     }
660 <readCellData>{spaceNl}{lbrac} {
661         Info<< "Reading mixed cells" << endl;
662         yy_push_state(readCellsMixed);
663     }
665 <readCellsMixed>{spaceNl}{labelList} {
667         IStringStream fluentCellModelIDStream(YYText());
669         label celliD;
670         while (fluentCellModelIDStream.read(celliD))
671         {
672             fluentCellModelID[celli] = celliD;
673             celli++;
674         }
675     }
677 <readCellsMixed>{spaceNl}{endOfSection} {
679         // check read of cells
680         if (celli != cellGroupEndIndex.last())
681         {
682             Info<< "problem with reading cells: "
683                 << "start index: " << cellGroupStartIndex.last()
684                 << " end index: " << cellGroupEndIndex.last()
685                 << " last cells read: " << celli << endl;
686         }
688         yy_pop_state();
689     }
693 {zoneVariant1} {
694         BEGIN(readZoneHeader);
695     }
697 {zoneVariant2} {
698         BEGIN(readZoneHeader);
699     }
701 <readZoneHeader>{spaceNl}{lbrac} {
702         BEGIN(readZoneGroupData);
703     }
705 <readZoneGroupData>{space}{label}{space}{word}{space}{word} {
707         IStringStream zoneDataStream(YYText());
709         // cell zone-ID not in hexadecimal!!! Inconsistency
710         label zoneID(readLabel(zoneDataStream));
712         if (zoneID > maxZoneID - 1)
713         {
714             // resize the container
715             maxZoneID = zoneID + zoneIDBuffer;
717             patchTypeIDs.setSize(maxZoneID);
718             patchNameIDs.setSize(maxZoneID);
719         }
721         zoneDataStream >> patchTypeIDs[zoneID];
722         zoneDataStream >> patchNameIDs[zoneID];
724         Info<< "Read zone1:" << zoneID
725             << " name:" << patchNameIDs[zoneID]
726             << " patchTypeID:" << patchTypeIDs[zoneID]
727             << endl;
728     }
730 <readZoneGroupData>{space}{label}{space}{word}{space}{word}{space}{label} {
731         // Fluent manual inconsistency, version 6.1.22
732         IStringStream zoneDataStream(YYText());
734         // cell zone-ID not in hexadecimal!!! Inconsistency
735         label zoneID(readLabel(zoneDataStream));
737         if (zoneID > maxZoneID - 1)
738         {
739             // resize the container
740             maxZoneID = zoneID + zoneIDBuffer;
742             patchTypeIDs.setSize(maxZoneID);
743             patchNameIDs.setSize(maxZoneID);
744         }
746         zoneDataStream >> patchTypeIDs[zoneID];
747         zoneDataStream >> patchNameIDs[zoneID];
749         Info<< "Read zone2:" << zoneID
750             << " name:" << patchNameIDs[zoneID]
751             << " patchTypeID:" << patchTypeIDs[zoneID]
752             << endl;
753     }
755 <readZoneGroupData>{endOfSection} {
756         BEGIN(readZoneData);
757     }
759 <readZoneData>{spaceNl}{lbrac} {
760         Info<< "Reading zone data" << endl;
761         yy_push_state(readZoneBlock);
762     }
764 <readZoneBlock>{spaceNl}{schemeSymbolList} {
765     }
767 <readZoneBlock>{lbrac} {
768         Info<< "Found unknown block in zone:" << YYText() << endl;
769         yy_push_state(unknownBlock);
770     }
772 <readZoneBlock>{endOfSection} {
773         yy_pop_state();
774     }
778  /*             ------ Reading end of section and others ------               */
780 <readHeader,readDimension,readPointData,readFaceData,readCellData,readZoneData>{spaceNl}{endOfSection} {
781         BEGIN(INITIAL);
782     }
784  /*    ------ Reading unknown type or non-standard comment ------             */
787 {lbrac}{label} {
788         Info<< "Found unknown block:" << YYText() << endl;
789         yy_push_state(unknownBlock);
790     }
792 <readComment,unknownBlock,embeddedUnknownBlock>{spaceNl}{schemeSymbol} {
793     }
795 <readComment,unknownBlock,embeddedUnknownBlock>{spaceNl}{lbrac} {
796         Info<< "Embedded blocks in comment or unknown:" << YYText() << endl;
797         yy_push_state(embeddedUnknownBlock);
799     }
801 <readComment,unknownBlock,embeddedUnknownBlock>{spaceNl}{endOfSection} {
802         Info<< "Found end of section in unknown:" << YYText() << endl;
803         yy_pop_state();
804     }
806 <unknownBlock,embeddedUnknownBlock>{spaceNl}{labelList} {
807     }
809 <unknownBlock,embeddedUnknownBlock>{spaceNl}{hexLabelList} {
810     }
812 <unknownBlock,embeddedUnknownBlock>{spaceNl}{scalarList} {
813     }
815 <unknownBlock,embeddedUnknownBlock>{spaceNl}{schemeSymbolList} {
816     }
818 <unknownBlock,embeddedUnknownBlock>{spaceNl}{text} {
819     }
822  /* ------ Ignore remaining space and \n s.  Any other characters are errors. */
824 <readPoints2D,readPoints3D>.|\n {
825     Info<< "ERROR! Do not understand characters: " << YYText() << endl;
826     }
827 .|\n {}
830  /*  ------ On EOF return to previous file, if none exists terminate. ------  */
832 <<EOF>> {
833             yyterminate();
834     }
838 #include "fileName.H"
839 #include <fstream>
841 // Find label of face.
842 label findFace(const primitiveMesh& mesh, const face& f)
844     // Get faces using zeroth vertex of face.
845     const labelList& pFaces = mesh.pointFaces()[f[0] ];
847     forAll(pFaces, i)
848     {
849         label faceI = pFaces[i];
851         if (f == mesh.faces()[faceI])
852         {
853             return faceI;
854         }
855     }
857     // Didn't find face. Do what?
858     FatalErrorIn("findFace(const primitiveMesh&, const face&)")
859         << "Problem : cannot find a single face in the mesh which uses"
860         << " vertices " << f << exit(FatalError);
862     return -1;
866 int main(int argc, char *argv[])
868     argList::noParallel();
869     argList::validArgs.append("Fluent mesh file");
870     argList::validOptions.insert("scale", "scale factor");
871     argList::validOptions.insert("writeSets", "");
872     argList::validOptions.insert("writeZones", "");
874     argList args(argc, argv);
876     if (!args.check())
877     {
878         FatalError.exit();
879     }
881     scalar scaleFactor = 1.0;
882     args.optionReadIfPresent("scale", scaleFactor);
884     bool writeSets  = args.optionFound("writeSets");
885     bool writeZones = args.optionFound("writeZones");
887 #   include "createTime.H"
889     fileName fluentFile(args.additionalArgs()[0]);
890     std::ifstream fluentStream(fluentFile.c_str());
892     if (!fluentStream)
893     {
894         FatalErrorIn("fluentToFoam::main(int argc, char *argv[])")
895             << args.executable()
896             << ": file " << fluentFile << " not found"
897             << exit(FatalError);
898     }
900     yyFlexLexer lexer(&fluentStream);
901     while(lexer.yylex() != 0)
902     {}
904     Info<< "\n\nFINISHED LEXING\n\n\n";
905     // Lookup table giving number of vertices given a fluent cell type ID
906     // Currently not used.
907     // label fluentModelNVertices[7] = {-1, 3, 4, 4, 8, 5, 6};
909     // Lookup table giving number of vertices given a fluent cell type ID
910     label fluentModelNFaces[7] = {-1, 3, 4, 4, 6, 5, 5};
912     // Make a list of cell faces to be filled in for owner and neighbour
914     labelListList cellFaces(nCells);
916     labelList nFacesInCell(nCells, 0);
918     forAll (cellFaces, celli)
919     {
920         cellFaces[celli].setSize(fluentModelNFaces[fluentCellModelID[celli] ]);
921     }
923     // fill in owner and neighbour
925     forAll (owner, faceI)
926     {
927         if (owner[faceI] > -1)
928         {
929             label curCell = owner[faceI];
930             cellFaces[curCell][nFacesInCell[curCell] ] = faceI;
932             nFacesInCell[curCell]++;
933         }
934     }
936     forAll (neighbour, faceI)
937     {
938         if (neighbour[faceI] > -1)
939         {
940             label curCell = neighbour[faceI];
941             cellFaces[curCell][nFacesInCell[curCell] ] = faceI;
943             nFacesInCell[curCell]++;
944         }
945     }
947     // Construct shapes from face lists
948     cellShapeList cellShapes(nCells);
950     // Extrude 2-D mesh into 3-D
952     Info<< "dimension of grid: " << dimensionOfGrid << endl;
953     faceList frontAndBackFaces;
955     if (dimensionOfGrid == 2)
956     {
957         const scalar extrusionFactor = 0.01;
959         boundBox box(max(points), min(points));
961         const scalar zOffset = extrusionFactor*box.mag();
963         // two-dimensional grid. Extrude in z-direction
964         Info<< "Grid is 2-D. Extruding in z-direction by: "
965             << 2*zOffset << endl;
967         pointField oldPoints = points;
969         const label pointOffset = oldPoints.size();
971         points.setSize(2*pointOffset);
973         label nNewPoints = 0;
975         // Note: In order for the owner-neighbour rules to be right, the
976         // points given by Fluent need to represent the FRONT plane of the
977         // geometry. Therefore, the extrusion will be in -z direction
978         //
979         forAll (oldPoints, pointI)
980         {
981             points[nNewPoints] = oldPoints[pointI];
983             points[nNewPoints].z() = zOffset;
985             nNewPoints++;
986         }
988         forAll (oldPoints, pointI)
989         {
990             points[nNewPoints] = oldPoints[pointI];
992             points[nNewPoints].z() = -zOffset;
994             nNewPoints++;
995         }
997         // 2-D shape recognition
998         Info<< "Creating shapes for 2-D cells"<< endl;
1000         // Set the number of empty faces
1001         frontAndBackFaces.setSize(2*nCells);
1003         forAll (fluentCellModelID, celli)
1004         {
1005             switch (fluentCellModelID[celli])
1006             {
1007                 case 1:
1008                 {
1009                     cellShapes[celli] =
1010                         cellShape
1011                         (
1012                             extrudedTriangleCellShape
1013                             (
1014                                 celli,
1015                                 cellFaces[celli],
1016                                 faces,
1017                                 owner,
1018                                 neighbour,
1019                                 pointOffset,
1020                                 frontAndBackFaces
1021                             )
1022                         );
1023                 }
1024                 break;
1026                 case 3:
1027                 {
1028                     cellShapes[celli] =
1029                         cellShape
1030                         (
1031                             extrudedQuadCellShape
1032                             (
1033                                 celli,
1034                                 cellFaces[celli],
1035                                 faces,
1036                                 owner,
1037                                 neighbour,
1038                                 pointOffset,
1039                                 frontAndBackFaces
1040                             )
1041                         );
1042                 }
1043                 break;
1045                 default:
1046                 {
1047                     FatalErrorIn("fluentToFoam::main(int argc, char *argv[])")
1048                         << "unrecognised  2-D cell shape: "
1049                         << fluentCellModelID[celli]
1050                         << abort(FatalError);
1051                 }
1052             }
1053         }
1055         // Create new faces
1056         forAll (faces, faceI)
1057         {
1059             if (faces[faceI].size() != 2)
1060             {
1061                 FatalErrorIn("fluentToFoam::main(int argc, char *argv[])")
1062                     << "fluentMeshToFoam: a 2-D face defined with "
1063                     << faces[faceI].size() << " points." << endl;
1064             }
1066             labelList& newFace = faces[faceI];
1068             newFace.setSize(4);
1070             newFace[2] = newFace[1] + pointOffset;
1072             newFace[3] = newFace[0] + pointOffset;
1073         }
1075         // Create new cells from 2-D shapes
1076     }
1077     else
1078     {
1079         // 3-D shape recognition
1080         Info<< "Creating shapes for 3-D cells"<< endl;
1081         forAll (fluentCellModelID, celli)
1082         {
1083             if
1084             (
1085                 fluentCellModelID[celli] == 2    // tet
1086              || fluentCellModelID[celli] == 4    // hex
1087              || fluentCellModelID[celli] == 5    // pyramid
1088              || fluentCellModelID[celli] == 6    // prism
1089             )
1090             {
1091                 cellShapes[celli] =
1092                     cellShape
1093                     (
1094                         create3DCellShape
1095                         (
1096                             celli,
1097                             cellFaces[celli],
1098                             faces,
1099                             owner,
1100                             neighbour,
1101                             fluentCellModelID[celli]
1102                         )
1103                     );
1104             }
1105             else
1106             {
1107                 FatalErrorIn("fluentToFoam::main(int argc, char *argv[])")
1108                     << "unrecognised 3-D cell shape: "
1109                     << fluentCellModelID[celli]
1110                     << abort(FatalError);
1111             }
1112         }
1113     }
1115     // boundary faces are oriented such that the owner is zero and the face
1116     // area vector points into the domain. Turn them round before making patches
1117     // for Foam compatibility
1119     forAll (faces, faceI)
1120     {
1121         if (owner[faceI] == -1)
1122         {
1123             // reverse face
1124             labelList oldFace = faces[faceI];
1126             forAllReverse(oldFace, i)
1127             {
1128                 faces[faceI][oldFace.size() - i - 1] =
1129                     oldFace[i];
1130             }
1131         }
1132     }
1135     //make patchless mesh before analysing boundaries
1137     faceListList patches(0);
1138     wordList patchNames(0);
1139     wordList patchTypes(0);
1140     word defaultFacesName = "defaultFaces";
1141     word defaultFacesType = emptyPolyPatch::typeName;
1142     wordList patchPhysicalTypes(0);
1144     // Scale the points
1146     points *= scaleFactor;
1148     Info<< "Building patch-less mesh..." << flush;
1150     polyMesh pShapeMesh
1151     (
1152         IOobject
1153         (
1154             polyMesh::defaultRegion,
1155             runTime.constant(),
1156             runTime
1157         ),
1158         xferMove(points),
1159         cellShapes,
1160         patches,
1161         patchNames,
1162         patchTypes,
1163         defaultFacesName,
1164         defaultFacesType,
1165         patchPhysicalTypes
1166     );
1168     //dont write mesh yet, otherwise preservePatchTypes will be broken
1169     //and zones wont be written
1170     //checkmesh done after patch addition as well
1171     Info<< "done." << endl;
1174     Info<< endl << "Building boundary and internal patches." << endl;
1175     //adding patches after mesh construction allows topological checks
1176     //on whether a patch is internal or external, something fluent
1177     //doesnt seem to mind
1179     // Make boundary patches
1181     SLList<label>::iterator faceGroupZoneIDIter = faceGroupZoneID.begin();
1182     SLList<label>::iterator faceGroupStartIndexIter =
1183         faceGroupStartIndex.begin();
1184     SLList<label>::iterator faceGroupEndIndexIter = faceGroupEndIndex.begin();
1186     // Note. Not all groups of faces will be boundary patches.
1187     // Take care on construction
1189     //2D needs extra space for frontAndBack faces
1190     if (dimensionOfGrid == 2)
1191     {
1192         patches.setSize(faceGroupZoneID.size()+1);
1193         patchNames.setSize(faceGroupZoneID.size()+1);
1194         patchTypes.setSize(faceGroupZoneID.size()+1);
1195         patchPhysicalTypes.setSize(faceGroupZoneID.size()+1);
1196     }
1197     else
1198     {
1199         patches.setSize(faceGroupZoneID.size());
1200         patchNames.setSize(faceGroupZoneID.size());
1201         patchTypes.setSize(faceGroupZoneID.size());
1202         patchPhysicalTypes.setSize(faceGroupZoneID.size());
1203     }
1205     label nPatches = 0;
1207     //colate information for all patches (internal and external)
1208     for
1209     (
1210         ;
1211         faceGroupZoneIDIter != faceGroupZoneID.end()
1212      && faceGroupStartIndexIter != faceGroupStartIndex.end()
1213      && faceGroupEndIndexIter != faceGroupEndIndex.end();
1214         ++faceGroupZoneIDIter,
1215         ++faceGroupStartIndexIter,
1216         ++faceGroupEndIndexIter
1217     )
1218     {
1219         // get face type and name
1220         const word& curPatchType = patchTypeIDs[faceGroupZoneIDIter()];
1222         const word& curPatchName = patchNameIDs[faceGroupZoneIDIter()];
1224         Info<< "Creating patch " << nPatches
1225             << " for zone: " << faceGroupZoneIDIter()
1226             << " start: " << faceGroupStartIndexIter()
1227             << " end: " << faceGroupEndIndexIter()
1228             << " type: " << curPatchType << " name: " << curPatchName << endl;
1230         // make patch labels
1231         label faceLabel = faceGroupStartIndexIter() - 1;
1233         faceList patchFaces(faceGroupEndIndexIter() - faceLabel);
1235         forAll (patchFaces, faceI)
1236         {
1237             if
1238             (
1239                 faces[faceLabel].size() == 3
1240              || faces[faceLabel].size() == 4
1241             )
1242             {
1243                 patchFaces[faceI] = face(faces[faceLabel]);
1244                 faceLabel++;
1245             }
1246             else
1247             {
1248                 FatalErrorIn("fluentToFoam::main(int argc, char *argv[])")
1249                     << "unrecognised face shape with "
1250                     << patchFaces[faceI].size() << " vertices"
1251                     << abort(FatalError);
1252             }
1253         }
1255         //inlets and outlets
1256         if
1257         (
1258             curPatchType == "pressure"
1259          || curPatchType == "pressure-inlet"
1260          || curPatchType == "inlet-vent"
1261          || curPatchType == "intake-fan"
1262          || curPatchType == "pressure-outlet"
1263          || curPatchType == "exhaust-fan"
1264          || curPatchType == "outlet-vent"
1265          || curPatchType == "pressure-far-field"
1266          || curPatchType == "velocity-inlet"
1267          || curPatchType == "mass-flow-inlet"
1268          || curPatchType == "outflow"
1269         )
1270         {
1271             patches[nPatches] = patchFaces;
1272             patchTypes[nPatches] = polyPatch::typeName;
1273             patchNames[nPatches] = curPatchName;
1275             nPatches++;
1276         }
1277         else if (curPatchType == "wall" ) //wall boundaries
1278         {
1279             patches[nPatches] = patchFaces;
1280             patchTypes[nPatches] = wallPolyPatch::typeName;
1281             patchNames[nPatches] = curPatchName;
1283             nPatches++;
1284         }
1285         else if
1286         (
1287             curPatchType == "symmetry"
1288          || curPatchType == "axis"
1289         ) //symmetry planes
1290         {
1291             patches[nPatches] = patchFaces;
1292             patchTypes[nPatches] = symmetryPolyPatch::typeName;
1293             patchNames[nPatches] = curPatchName;
1295             nPatches++;
1296         }
1297         else if
1298         (
1299             curPatchType == "interior"
1300          || curPatchType == "interface"
1301          || curPatchType == "internal"
1302          || curPatchType == "solid"
1303          || curPatchType == "fan"
1304          || curPatchType == "radiator"
1305          || curPatchType == "porous-jump"
1306         ) //interior boundaries - will not be added as patches
1307         {
1308             patches[nPatches] = patchFaces;
1309             patchTypes[nPatches] = "internal";
1310             patchNames[nPatches] = curPatchName;
1312             nPatches++;
1313         }
1314         else if
1315         (
1316             curPatchType == ""
1317         ) //unnamed face regions default to interior patches
1318         {
1319             Info<< "Patch " << faceGroupZoneIDIter()
1320                 << ": Faces are defined but "
1321                 << "not created as a zone." << endl
1322                 << "Null specification is only valid for internal faces."
1323                 << endl;
1325             patches[nPatches] = patchFaces;
1326             patchTypes[nPatches] = "internal";
1327             patchNames[nPatches] = curPatchName;
1329             nPatches++;
1330         }
1331         else //unknown face regions are not handled
1332         {
1333             FatalErrorIn("fluentToFoam::main(int argc, char *argv[])")
1334                 << "fluent patch type " << curPatchType << " not recognised."
1335                 << abort(FatalError);
1336         }
1337     }
1339     //add front and back boundaries for 2D meshes
1340     if (dimensionOfGrid == 2)
1341     {
1342         Info<< "Creating patch for front and back planes" << endl << endl;
1344         patches[nPatches] = frontAndBackFaces;
1345         patchTypes[nPatches] = emptyPolyPatch::typeName;
1346         patchNames[nPatches] = "frontAndBackPlanes";
1348         nPatches++;
1349     }
1351     //Now have all patch information,
1352     //check whether each patch is internal or external
1353     //and add boundaries to mesh
1354     //also write face sets of all patches
1355     patches.setSize(nPatches);
1356     patchTypes.setSize(nPatches);
1357     patchNames.setSize(nPatches);
1360     //old polyBoundary
1361     const polyBoundaryMesh& oPatches = pShapeMesh.boundaryMesh();
1362     // new patches.
1363     DynamicList<polyPatch*> newPatches(nPatches);
1365     // For every boundary face the old patch.
1366     labelList facePatchID(pShapeMesh.nFaces()-pShapeMesh.nInternalFaces(), -1);
1367     label cMeshFace = pShapeMesh.nInternalFaces();
1368     label nBoundaries = 0;
1371     forAll(patches, patchI)
1372     {
1373         const faceList& bFaces = patches[patchI];
1375         label sz = bFaces.size();
1376         labelList meshFaces(sz,-1);
1379         //make face set and write (seperate from rest for clarity)
1380         //internal and external Fluent boundaries
1381         {
1382             faceSet pFaceSet(pShapeMesh, patchNames[patchI], sz);
1384             forAll(bFaces, j)
1385             {
1386                 const face& f = bFaces[j];
1387                 label cMeshFace = findFace(pShapeMesh, f);
1388                 meshFaces[j] = cMeshFace;
1389                 pFaceSet.insert(cMeshFace);
1390             }
1391             if(writeSets)
1392             {
1393                 Info<< "Writing patch " << patchNames[patchI]
1394                     << " of size " << sz << " to faceSet." << endl;
1395                 pFaceSet.write();
1396             }
1397         }
1400         //check if patch is internal
1401         //also check internal/external-ness of first patch face
1402         //internal faces cannot become foam boundaries
1403         //if a face is defined as internal but is actually external
1404         //it will be put in a default wall boundary
1405         //internal boundaries are simply ignored
1407         if(patchTypes[patchI] != "internal" && !pShapeMesh.isInternalFace(meshFaces[0]))
1408         {
1409             //first face is external and has valid non-internal type
1411             //check all faces for externalness just to be sure
1412             //and mark patch number to global list
1413             forAll(meshFaces, i)
1414             {
1415                 label faceI = meshFaces[i];
1417                 if (pShapeMesh.isInternalFace(faceI))
1418                 {
1419                     FatalErrorIn(args.executable())
1420                         << "Face " << faceI << " on new patch "
1421                         << patchNames[patchI]
1422                         << " is not an external face of the mesh." << endl
1423                         << exit(FatalError);
1424                 }
1426                 if(facePatchID[faceI - pShapeMesh.nInternalFaces()]!= -1)
1427                 {
1428                     FatalErrorIn(args.executable())
1429                         << "Face " << faceI << " on new patch "
1430                         << patchNames[patchI]
1431                         << " has already been marked for repatching to"
1432                         << " patch "
1433                         << facePatchID[faceI - pShapeMesh.nInternalFaces()]
1434                         << exit(FatalError);
1435                 }
1436                 facePatchID[faceI - pShapeMesh.nInternalFaces()] = nBoundaries;
1437             }
1439             //add to boundary patch
1441             Info<< "Adding new patch " << patchNames[patchI]
1442                 << " of type " << patchTypes[patchI]
1443                 << " as patch " << nBoundaries << endl;
1445             // Add patch to new patch list
1446             newPatches.append
1447             (
1448                 polyPatch::New
1449                 (
1450                     patchTypes[patchI],
1451                     patchNames[patchI],
1452                     sz,
1453                     cMeshFace,
1454                     nBoundaries,
1455                     oPatches
1456                 ).ptr()
1457             );
1458             nBoundaries++;
1459             cMeshFace += sz;
1460         }
1461         else
1462         {
1463             Info<< "Patch " << patchNames[patchI]
1464                  << " is internal to the mesh "
1465                  << " and is not being added to the boundary."
1466                  << endl;
1468         }
1469     }
1471     // Check for any remaining boundary faces
1472     // and add them to a default wall patch
1473     // this routine should generally not be invoked
1474     {
1475         DynamicList<label> defaultBoundaryFaces(facePatchID.size());
1476         forAll(facePatchID, idI)
1477         {
1478             if(facePatchID[idI] == -1)
1479             {
1480                 defaultBoundaryFaces.append(idI);
1481                 facePatchID[idI] = nBoundaries;
1482             }
1483         }
1484         defaultBoundaryFaces.shrink();
1486         if (defaultBoundaryFaces.size())
1487         {
1488             Warning << " fluent mesh has " << defaultBoundaryFaces.size()
1489                     << " undefined boundary faces." << endl
1490                     << " Adding undefined faces to new patch `default_wall`"
1491                     << endl;
1493             // Add patch to new patch list
1495             newPatches.append
1496             (
1497                 polyPatch::New
1498                 (
1499                     wallPolyPatch::typeName,
1500                     "default_wall",
1501                     defaultBoundaryFaces.size(),
1502                     cMeshFace,
1503                     nBoundaries,
1504                     oPatches
1505                 ).ptr()
1506             );
1507             nBoundaries++;
1508             cMeshFace += defaultBoundaryFaces.size();
1509         }
1510     }
1512     newPatches.shrink();
1514     // Use facePatchIDs map to reorder boundary faces into compact regions
1516     repatchPolyTopoChanger repatcher(pShapeMesh);
1518     // Add new list of patches
1519     repatcher.changePatches(newPatches);
1521     // Change patch ids
1522     forAll(facePatchID, idI)
1523     {
1524         label faceI = idI + pShapeMesh.nInternalFaces();
1526         repatcher.changePatchID(faceI, facePatchID[idI]);
1527     }
1528     repatcher.repatch();
1530     preservePatchTypes
1531     (
1532         runTime,
1533         runTime.constant(),
1534         polyMesh::defaultRegion,
1535         patchNames,
1536         patchTypes,
1537         defaultFacesName,
1538         defaultFacesType,
1539         patchPhysicalTypes
1540     );
1542     // Set the precision of the points data to 10
1543     IOstream::defaultPrecision(10);
1546     // Zones
1547     // will write out cell zones and internal faces for those zones
1548     // note: zone boundary faces are not added to face zones
1549     // the names of boundaries bordering on cell zones are written to
1550     // a list containing the boundary name and cellzone it borders on
1551     // interior boundaries are handled via faceSets
1552     // cell zones will only be written if there is more than one
1554     if (writeZones && cellGroupZoneID.size()>1)
1555     {
1556         Info<< "Adding Zones" << endl;
1557         List<pointZone*> pz(0);
1559         label nrCellZones = cellGroupZoneID.size();
1560         List<cellZone*> cz(nrCellZones);
1562         // Make face zones for cell zones
1563         List<faceZone*> fz(nrCellZones);
1565         // List of patch names and the cellZone(s) they border
1566         // this is just an info file to make MRF easier to setup
1567         List<DynamicList<word> > boundaryZones
1568         (
1569             pShapeMesh.boundaryMesh().size()
1570         );
1572         const polyBoundaryMesh& bPatches = pShapeMesh.boundaryMesh();
1573         forAll(bPatches, pI)
1574         {
1575             boundaryZones[pI].append(bPatches[pI].name());
1576         }
1578             label cnt=0;
1579             SLList<label>::iterator cg = cellGroupZoneID.begin();
1580             SLList<label>::iterator start = cellGroupStartIndex.begin();
1581             SLList<label>::iterator end = cellGroupEndIndex.begin();
1583             for (; cg != cellGroupZoneID.end(); ++cg, ++start, ++end)
1584             {
1585                 const word& name = patchNameIDs[cg()];
1586                 const word& type = patchTypeIDs[cg()];
1588                 Info<< "Writing cell zone: " << name
1589                 << " of type " << type << " starting at " << start() - 1
1590                 << " ending at " << end() - 1 << " to cellSet." << endl;
1592                 labelList cls(end() - start() + 1);
1594             // Mark zone cells, used for finding faces
1595             boolList zoneCell(pShapeMesh.nCells(), false);
1597                 // shift cell indizes by 1
1598                 label nr=0;
1599                 for (label celli = (start() - 1); celli < end(); celli++)
1600             {
1601                 cls[nr]=celli;
1602                 zoneCell[celli] = true;
1603                 nr++;
1604                 }
1606                 cz[cnt] = new cellZone
1607                 (
1608                 name,
1609                 cls,
1610                 cnt,
1611                 pShapeMesh.cellZones()
1612                 );
1614             DynamicList<label> zoneFaces(pShapeMesh.nFaces());
1615             forAll(pShapeMesh.faceNeighbour(), faceI)
1616             {
1617                 label nei = pShapeMesh.faceNeighbour()[faceI];
1618                 label own = pShapeMesh.faceOwner()[faceI];
1619                 if(nei != -1)
1620                 {
1621                     if(zoneCell[nei] && zoneCell[own])
1622                     {
1623                         zoneFaces.append(faceI);
1624                     }
1625                 }
1626             }
1627             zoneFaces.shrink();
1629             fz[cnt] = new faceZone
1630             (
1631                 name,
1632                 zoneFaces,
1633                 boolList(zoneFaces.size(), false),
1634                 cnt,
1635                 pShapeMesh.faceZones()
1636             );
1638             // Add cell zones to patch zone list
1639             forAll(bPatches, pI)
1640             {
1641                 const labelList& faceCells = bPatches[pI].faceCells();
1642                 forAll(faceCells, fcI)
1643                 {
1644                     if(zoneCell[faceCells[fcI] ])
1645                     {
1646                         boundaryZones[pI].append(name);
1647                         break;
1648                     }
1649                 }
1650             }
1652                 cnt++;
1653             }
1655         pShapeMesh.addZones(pz, fz, cz);
1657         forAll(bPatches, pI)
1658         {
1659             boundaryZones[pI].shrink();
1660         }
1662         fileName bczf
1663         (
1664             runTime.path()/runTime.constant()
1665            /"polyMesh"/"boundaryAdjacentCellZones"
1666         );
1668         OFstream boundaryCellZonesFile(bczf);
1669         forAll(boundaryZones, bzI)
1670         {
1671             forAll(boundaryZones[bzI], bzII)
1672             {
1673                 boundaryCellZonesFile << boundaryZones[bzI][bzII] << " ";
1674             }
1676             boundaryCellZonesFile << endl;
1677         }
1678     }
1680     Info<< endl << "Writing mesh..." << flush;
1682     Info<< " to " << pShapeMesh.instance()/pShapeMesh.meshDir()
1683         << "  " << flush;
1685     pShapeMesh.setInstance(pShapeMesh.instance());
1686     pShapeMesh.write();
1687     Info<< "done." << endl << endl;
1689     // Write cellSets for Fluent regions
1690     // allows easy post-processing
1691     // set and zone functionality will be integrated some time
1692     // soon negating the need for double output
1693     if (writeSets)
1694     {
1695         if (cellGroupZoneID.size() > 1)
1696         {
1697             Info<< "Writing cell sets" << endl;
1699             SLList<label>::iterator cg = cellGroupZoneID.begin();
1700             SLList<label>::iterator start = cellGroupStartIndex.begin();
1701             SLList<label>::iterator end = cellGroupEndIndex.begin();
1703             // Note: cellGroupXXX are all Fluent indices (starting at 1)
1704             // so offset before using.
1706             for (; cg != cellGroupZoneID.end(); ++cg, ++start, ++end)
1707             {
1708                 const word& name=patchNameIDs[cg()];
1709                 const word& type=patchTypeIDs[cg()];
1711                 Info<< "Writing cell set: " << name
1712                     << " of type " << type << " starting at " << start() - 1
1713                     << " ending at " << end() - 1 << " to cellSet." << endl;
1715                 cellSet internal(pShapeMesh, name, end() - start());
1717                 // shift cell indizes by 1
1718                 for(label celli=start() - 1; celli<=end() - 1; celli++)
1719                 {
1720                     internal.insert(celli);
1721                 }
1723                 internal.write();
1724             }
1725         }
1726         else
1727         {
1728             Info<< "Only one cell group: no set written\n";
1729         }
1730     }
1732     Info<< nl << "End" << endl;
1733     return 0;
1737  /* ------------------------------------------------------------------------- *\
1738     ------ End of fluentMeshToFoam.L
1739  \* ------------------------------------------------------------------------- */