intersection with triangle plane for miss
[OpenFOAM-1.5.x.git] / applications / utilities / mesh / conversion / fluent3DMeshToFoam / fluent3DMeshToFoam.L
blobadf80c9210cfc9c7bcae7db256541a7dc26091cb
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2008 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     fluent3DMeshToFoam
28 Description
29     Converts a Fluent mesh to OpenFOAM format.
31 \*---------------------------------------------------------------------------*/
34 #undef yyFlexLexer
36  /* ------------------------------------------------------------------------ *\
37    ------ local definitions
38  \* ------------------------------------------------------------------------ */
40 #include "argList.H"
41 #include "Time.H"
42 #include "polyMesh.H"
43 #include "polyTopoChange.H"
44 #include "polyMeshZipUpCells.H"
45 #include "wallPolyPatch.H"
46 #include "symmetryPolyPatch.H"
47 #include "cyclicPolyPatch.H"
48 #include "Swap.H"
49 #include "IFstream.H"
51 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
53 using namespace Foam;
55 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
57 // Line number
58 label lineNo = 1;
60 // Scale factor used to scale points (optional command line argument)
61 scalar scaleFactor = 1.0;
63 label dimensionOfGrid = 0;
64 label nPoints = 0;
65 label nFaces = 0;
66 label nCells = 0;
68 bool hangingNodes = false;
70 pointField points(0);
71 faceList faces(0);
72 labelList owner(0);
73 labelList neighbour(0);
75 // Group type and name
76 Map<word> groupType(100);
77 Map<word> groupName(100);
79 // Point groups
80 DynamicList<label> pointGroupZoneID;
81 DynamicList<label> pointGroupStartIndex;
82 DynamicList<label> pointGroupEndIndex;
84 // Face groups
85 DynamicList<label> faceGroupZoneID;
86 DynamicList<label> faceGroupStartIndex;
87 DynamicList<label> faceGroupEndIndex;
89 // Cell groups
90 DynamicList<label> cellGroupZoneID;
91 DynamicList<label> cellGroupStartIndex;
92 DynamicList<label> cellGroupEndIndex;
93 DynamicList<label> cellGroupType;
96 void uniquify(word& name, HashSet<word>& patchNames)
98     if (!patchNames.found(name))
99     {
100         patchNames.insert(name);
101     }
102     else
103     {
104         Info<< "    name " << name << " already used";
106         label i = 1;
107         word baseName = name;
109         do
110         {
111             name = baseName + "_" + Foam::name(i++);
112         } while (patchNames.found(name));
114         Info<< ", changing to " << name << endl;
115     }
119 // Dummy yywrap to keep yylex happy at compile time.
120 // It is called by yylex but is not used as the mechanism to change file.
121 // See <<EOF>>
122 #if YY_FLEX_SUBMINOR_VERSION < 34
123 extern "C" int yywrap()
124 #else
125 int yyFlexLexer::yywrap()
126 #endif
128     return 1;
133 one_space                  [ \t\f]
134 space                      {one_space}*
135 some_space                 {one_space}+
136 cspace                     ","{space}
138 alpha                      [_[:alpha:]]
139 digit                      [[:digit:]]
140 decDigit                   [[:digit:]]
141 octalDigit                 [0-7]
142 hexDigit                   [[:xdigit:]]
144 lbrac                      "("
145 rbrac                      ")"
146 quote                      \"
147 dash                       "-"
148 dotColonDash               [.:-]
150 schemeSpecialInitial       [!$%&*/\\:<=>?~_^#.@']
151 schemeSpecialSubsequent    [.+-]
152 schemeSymbol               (({some_space}|{alpha}|{quote}|{schemeSpecialInitial})({alpha}|{quote}|{digit}|{schemeSpecialInitial}|{schemeSpecialSubsequent})*)
155 identifier                 {alpha}({alpha}|{digit})*
156 integer                    {decDigit}+
157 label                      [1-9]{decDigit}*
158 hexLabel                   {hexDigit}+
159 zeroLabel                  {digit}*
160 signedInteger              [-+]?{integer}
161 word                       ({alpha}|{digit}|{dotColonDash})*
163 exponent_part              [eE][-+]?{digit}+
164 fractional_constant        [-+]?(({digit}*"."{digit}+)|({digit}+".")|({digit}))
166 double                     ((({fractional_constant}{exponent_part}?)|({digit}+{exponent_part}))|0)
168 x                          {double}
169 y                          {double}
170 z                          {double}
171 scalar                     {double}
172 labelListElement           {space}{zeroLabel}
173 hexLabelListElement        {space}{hexLabel}
174 scalarListElement          {space}{double}
175 schemeSymbolListElement    {space}{schemeSymbol}
176 labelList                  ({labelListElement}+{space})
177 hexLabelList               ({hexLabelListElement}+{space})
178 scalarList                 ({scalarListElement}+{space})
179 schemeSymbolList           ({schemeSymbolListElement}+{space})
181 starStar                   ("**")
182 text                       ({space}({word}*{space})*)
183 anythingInBlock            ([^)]*)
185 dateDDMMYYYY               ({digit}{digit}"/"{digit}{digit}"/"{digit}{digit}{digit}{digit})
186 dateDDMonYYYY              ((({digit}{digit}{space})|({digit}{space})){alpha}*{space}{digit}{digit}{digit}{digit})
187 time                       ({digit}{digit}":"{digit}{digit}":"{digit}{digit})
189 versionNumber              ({digit}|".")*
191 header                     {space}"(1"{space}
192 dimension                  {space}"(2"{space}
193 points                     {space}"(10"{space}
194 faces                      {space}"(13"{space}
195 cells                      {space}"(12"{space}
196 zoneVariant1               {space}"(39"{space}
197 zoneVariant2               {space}"(45"{space}
198 faceTree                   {space}"(59"{space}
200 comment                    "0"{space}
201 unknownPeriodicFace        "17"{space}
202 periodicFace               "18"{space}
203 cellTree                   "58"{space}
204 faceParents                "61"{space}
205 ignoreBlocks               ("4"|"37"|"38"|"40"|"41"|"60"|"64"){space}
207 redundantBlock             {space}({comment}|{unknownPeriodicFace}|{periodicFace}|{cellTree}|{faceParents}|{ignoreBlocks}){space}
209 endOfSection               {space}")"{space}
213  /* ------------------------------------------------------------------------ *\
214                       -----  Exclusive start states -----
215  \* ------------------------------------------------------------------------ */
217 %option stack
219 %x readHeader
220 %x readDimension
221 %x readPoint
222 %x readPointHeader
223 %x readNumberOfPoints
224 %x readPointGroupData
225 %x readPointData
226 %x readScalarList
227 %x fluentFace
228 %x readFaceHeader
229 %x readNumberOfFaces
230 %x readFaceGroupData
231 %x readFaceData
232 %x readFacesMixed
233 %x readFacesUniform
234 %x cell
235 %x readCellHeader
236 %x readNumberOfCells
237 %x readCellGroupData
238 %x readCellData
239 %x readCellsUniform
240 %x zone
241 %x readZoneHeader
242 %x readZoneGroupData
243 %x readZoneData
244 %x readZoneBlock
246 %x ignoreBlock
247 %x ignoreEmbeddedBlock
251     // End of read character pointer returned by strtol and strtod
252     char* endPtr;
254     // Point data
255     label pointGroupNumberOfComponents = 3;
256     label pointi = 0; // index used for reading points
257     label cmpt = 0;   // component index used for reading points
259     // Face data
260     label faceGroupElementType = -1;
261     label facei = 0;  // index used for reading faces
265  /* ------------------------------------------------------------------------ *\
266                             ------ Start Lexing ------
267  \* ------------------------------------------------------------------------ */
269  /*                      ------ Reading control header ------                */
271 {header} {
272         BEGIN(readHeader);
273     }
275 <readHeader>{anythingInBlock} {
276         Info<< "Header: " << YYText() << endl;
277     }
280 {dimension} {
281         BEGIN(readDimension);
282     }
284 <readDimension>{space}{label}{space} {
285         dimensionOfGrid = atoi(YYText());
286         Info<< "Dimension of grid: " << dimensionOfGrid << endl;
287     }
290 {points} {
291         BEGIN(readPointHeader);
292     }
294 <readPointHeader>{space}{lbrac}{space}"0"{space}"1"{space} {
295         BEGIN(readNumberOfPoints);
296     }
298 <readNumberOfPoints>{hexLabel}{space}{labelList} {
299         nPoints = strtol(YYText(), &endPtr, 16);
300         Info<< "Number of points: " << nPoints << endl;
301         points.setSize(nPoints);
303         // Ignore rest of stream
304     }
306 <readPointHeader>{space}{lbrac} {
307         BEGIN(readPointGroupData);
308     }
310 <readPointGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{labelList} {
311         // Read point zone-ID, start and end-label
312         // the indices will be used for checking later.
313         pointGroupZoneID.append(strtol(YYText(), &endPtr, 16));
315         // In FOAM, indices start from zero - adjust
316         pointGroupStartIndex.append(strtol(endPtr, &endPtr, 16) - 1);
318         pointGroupEndIndex.append(strtol(endPtr, &endPtr, 16) - 1);
320         // point group type skipped
321         strtol(endPtr, &endPtr, 16);
323         pointi = pointGroupStartIndex[pointGroupStartIndex.size()-1];
325         // reset number of components to default
326         pointGroupNumberOfComponents = 3;
328         // read number of components in the vector
329         if (endPtr < &(YYText()[YYLeng()-1]))
330         {
331             pointGroupNumberOfComponents = strtol(endPtr, &endPtr, 16);
332         }
334         Info<< "PointGroup: "
335             << pointGroupZoneID[pointGroupZoneID.size()-1]
336             << " start: "
337             << pointGroupStartIndex[pointGroupStartIndex.size()-1]
338             << " end: "
339             << pointGroupEndIndex[pointGroupEndIndex.size()-1] << flush;
340     }
342 <readNumberOfPoints,readPointGroupData>{endOfSection} {
343         BEGIN(readPointData);
344     }
346 <readPointData>{space}{lbrac}{space} {
347         Info<< ".  Reading points..." << flush;
348         cmpt = 0;
349         yy_push_state(readScalarList);
350     }
352 <readScalarList>{signedInteger}{space} {
353         points[pointi][cmpt++] = scaleFactor*atol(YYText());
355         if (cmpt == pointGroupNumberOfComponents)
356         {
357             if (pointGroupNumberOfComponents == 2)
358             {
359                 points[pointi].z() = 0.0;
360             }
362             cmpt = 0;
363             pointi++;
364         }
365     }
367 <readScalarList>{scalar}{space} {
368         points[pointi][cmpt++] = scaleFactor*atof(YYText());
370         if (cmpt == pointGroupNumberOfComponents)
371         {
372             if (pointGroupNumberOfComponents == 2)
373             {
374                 points[pointi].z() = 0.0;
375             }
377             cmpt = 0;
378             pointi++;
379         }
380     }
382 <readScalarList>{endOfSection} {
383         Info<< "done." << endl;
385         // check read of points
386         if (pointi != pointGroupEndIndex[pointGroupEndIndex.size()-1]+1)
387         {
388             Warning
389                 << "Problem with reading points: " << nl
390                 << "    start index: "
391                 << pointGroupStartIndex[pointGroupStartIndex.size()-1]
392                 << " end index: "
393                 << pointGroupEndIndex[pointGroupEndIndex.size()-1]
394                 << " last points read: " << pointi << nl
395                 << "    on line " << lineNo << endl;
396         }
398         yy_pop_state();
399     }
401 {faces} {
402         BEGIN(readFaceHeader);
403     }
405 <readFaceHeader>{space}{lbrac}{space}"0"{space}"1"{space} {
406         BEGIN(readNumberOfFaces);
407     }
409 <readNumberOfFaces>{space}{hexLabel}{space}{labelListElement}+ {
410         nFaces = strtol(YYText(), &endPtr, 16);
412         Info<< "Number of faces: " << nFaces << endl;
414         faces.setSize(nFaces);
415         owner.setSize(nFaces);
416         neighbour.setSize(nFaces);
418         // Type and element type not read
419     }
421 <readFaceHeader>{space}{lbrac} {
422         BEGIN(readFaceGroupData);
423     }
425 <readFaceGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{hexLabelListElement}+ {
426         // read fluentFace zone-ID, start and end-label
427         faceGroupZoneID.append(strtol(YYText(), &endPtr, 16));
429         // In FOAM, indices start from zero - adjust
430         faceGroupStartIndex.append(strtol(endPtr, &endPtr, 16) - 1);
432         faceGroupEndIndex.append(strtol(endPtr, &endPtr, 16) - 1);
434         // face group type
435         strtol(endPtr, &endPtr, 16);
437         faceGroupElementType = strtol(endPtr, &endPtr, 16);
439         facei = faceGroupStartIndex[faceGroupStartIndex.size()-1];
441         Info<< "FaceGroup: "
442             << faceGroupZoneID[faceGroupZoneID.size()-1]
443             << " start: "
444             << faceGroupStartIndex[faceGroupStartIndex.size()-1]
445             << " end: "
446             << faceGroupEndIndex[faceGroupEndIndex.size()-1] << flush;
447     }
449 <readNumberOfFaces,readFaceGroupData>{space}{endOfSection} {
450         BEGIN(readFaceData);
451     }
453 <readFaceData>{space}{lbrac} {
454         if (faceGroupElementType == 0 || faceGroupElementType > 4)
455         {
456             Info<< ".  Reading mixed faces..." << flush;
457             yy_push_state(readFacesMixed);
458         }
459         else
460         {
461             Info<< ".  Reading uniform faces..." << flush;
462             yy_push_state(readFacesUniform);
463         }
464     }
466 <readFacesMixed>{space}{hexLabelList} {
467         face& curFaceLabels = faces[facei];
469         // set size of label list
470         curFaceLabels.setSize(strtol(YYText(), &endPtr, 16));
472         forAll (curFaceLabels, i)
473         {
474             curFaceLabels[i] = strtol(endPtr, &endPtr, 16) - 1;
475         }
477         // read neighbour and owner. Neighbour comes first
478         neighbour[facei] = strtol(endPtr, &endPtr, 16) - 1;
479         owner[facei] = strtol(endPtr, &endPtr, 16) - 1;
480         facei++;
481     }
483 <readFacesUniform>{space}{hexLabelList} {
484         face& curFaceLabels = faces[facei];
486         // Set size of label list.
487         curFaceLabels.setSize(faceGroupElementType);
489         curFaceLabels[0] = strtol(YYText(), &endPtr, 16) - 1;
491         for (int i=1; i<faceGroupElementType; i++)
492         {
493             curFaceLabels[i] = strtol(endPtr, &endPtr, 16) - 1;
494         }
496         // read neighbour and owner. Neighbour comes first
497         neighbour[facei] = strtol(endPtr, &endPtr, 16) - 1;
498         owner[facei] = strtol(endPtr, &endPtr, 16) - 1;
499         facei++;
500     }
502 <readFacesMixed,readFacesUniform>{space}{endOfSection} {
503         Info<< "done." << endl;
505         // check read of fluentFaces
506         if (facei != faceGroupEndIndex[faceGroupEndIndex.size()-1]+1)
507         {
508             Warning
509                 << "Problem with reading fluentFaces: " << nl
510                 << "    start index: "
511                 << faceGroupStartIndex[faceGroupStartIndex.size()-1]
512                 << " end index: "
513                 << faceGroupEndIndex[faceGroupEndIndex.size()-1]
514                 << " last fluentFaces read: " << facei << nl
515                 << "    on line " << lineNo << endl;
516         }
518         yy_pop_state();
519     }
522 {cells} {
523         BEGIN(readCellHeader);
524     }
526 <readCellHeader>{space}{lbrac}{space}"0"{space}"1"{space} {
527         BEGIN(readNumberOfCells);
528     }
530 <readNumberOfCells>{space}{hexLabel}{space}{labelListElement}+ {
531         nCells = strtol(YYText(), &endPtr, 16);
532         Info<< "Number of cells: " << nCells << endl;
533     }
535 <readCellHeader>{space}{lbrac} {
536         BEGIN(readCellGroupData);
537     }
539 <readCellGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{space}{hexLabel} {
540         // Warning. This entry must be above the next one because of the lexing
541         // rules. It is introduced to deal with the problem of reading
542         // non-standard cell definition from Tgrid, which misses the type label.
544         Warning
545             << "Tgrid syntax problem: " << YYText() << nl
546             << "    on line " << lineNo << endl;
548         // read cell zone-ID, start and end-label
549         cellGroupZoneID.append(strtol(YYText(), &endPtr, 16));
551         // the indices will be used for checking later.
552         cellGroupStartIndex.append(strtol(endPtr, &endPtr, 16) - 1);
554         cellGroupEndIndex.append(strtol(endPtr, &endPtr, 16) - 1);
556         cellGroupType.append(strtol(endPtr, &endPtr, 16));
558         Info<< "CellGroup: "
559             << cellGroupZoneID[cellGroupZoneID.size()-1]
560             << " start: "
561             << cellGroupStartIndex[cellGroupStartIndex.size()-1]
562             << " end: "
563             << cellGroupEndIndex[cellGroupEndIndex.size()-1]
564             << " type: "
565             << cellGroupType[cellGroupType.size()-1]
566             << endl;
567     }
569 <readCellGroupData>{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{space}{hexLabel}{space}{hexLabel} {
570         // Warning. See above
572         // read cell zone-ID, start and end-label
573         cellGroupZoneID.append(strtol(YYText(), &endPtr, 16));
575         // the indices will be used for checking later.
576         cellGroupStartIndex.append(strtol(endPtr, &endPtr, 16) - 1);
578         cellGroupEndIndex.append(strtol(endPtr, &endPtr, 16) - 1);
580         cellGroupType.append(strtol(endPtr, &endPtr, 16));
582         // Note. Potentially skip cell set if type is zero.
583         strtol(endPtr, &endPtr, 16);
585         Info<< "CellGroup: "
586             << cellGroupZoneID[cellGroupZoneID.size()-1]
587             << " start: "
588             << cellGroupStartIndex[cellGroupStartIndex.size()-1]
589             << " end: "
590             << cellGroupEndIndex[cellGroupEndIndex.size()-1]
591             << " type: "
592             << cellGroupType[cellGroupType.size()-1]
593             << endl;
594     }
596 <readNumberOfCells,readCellGroupData>{endOfSection} {
597         BEGIN(readCellData);
598     }
600 <readCellData>{space}{lbrac} {
601         // Quickly scan to the end of the cell data block and discard
602         register int c;
603         while ((c = yyinput()) != 0 && c != ')')
604         {}
605     }
607 {faceTree} {
608         // There are hanging nodes in the mesh so make sure it gets zipped-up
609         hangingNodes = true;
610         yy_push_state(ignoreBlock);
611     }
613 {zoneVariant1} {
614         BEGIN(readZoneHeader);
615     }
617 {zoneVariant2} {
618         BEGIN(readZoneHeader);
619     }
621 <readZoneHeader>{space}{lbrac} {
622         BEGIN(readZoneGroupData);
623     }
625 <readZoneGroupData>{space}{label}{space}{word}{space}{word}{space}{label}? {
626         IStringStream zoneDataStream(YYText());
628         // cell zone-ID not in hexadecimal!!! Inconsistency
629         label zoneID(readLabel(zoneDataStream));
631         groupType.insert(zoneID, word(zoneDataStream));
632         groupName.insert(zoneID, word(zoneDataStream));
634         Info<< "Zone: " << zoneID
635             << " name: " << groupName[zoneID]
636             << " type: " << groupType[zoneID] << flush;
637     }
639 <readZoneGroupData>{endOfSection} {
640         BEGIN(readZoneData);
641     }
643 <readZoneData>{space}{lbrac} {
644         Info<< ".  Reading zone data..." << flush;
645         yy_push_state(readZoneBlock);
646     }
648 <readZoneBlock>{space}{schemeSymbolList} {
649     }
651 <readZoneBlock>{lbrac} {
652         //Warning
653         //    << "Found unknown block in zone: " << YYText() << nl
654         //    << "    on line " << lineNo << endl;
655         yy_push_state(ignoreBlock);
656     }
658 <readZoneBlock>{endOfSection} {
659         Info<< "done." << endl;
660         yy_pop_state();
661     }
665  /*             ------ Reading end of section and others ------              */
667 <readHeader,readDimension,readPointData,readFaceData,readCellData,readZoneData>{space}{endOfSection} {
668         BEGIN(INITIAL);
669     }
671  /*    ------ Reading unknown type or non-standard comment ------            */
673 {lbrac}{label} {
674         Warning
675             << "Found unknown block of type: "
676             << Foam::string(YYText())(1, YYLeng()-1) << nl
677             << "    on line " << lineNo << endl;
679         yy_push_state(ignoreBlock);
680     }
682 {lbrac}{redundantBlock} {
683         yy_push_state(ignoreBlock);
684     }
686 <ignoreBlock,ignoreEmbeddedBlock>{space}{quote}{text}{quote} {
687     }
689 <ignoreBlock,ignoreEmbeddedBlock>{space}{schemeSymbol} {
690     }
692 <ignoreBlock,ignoreEmbeddedBlock>{space}{lbrac} {
693         yy_push_state(ignoreEmbeddedBlock);
695     }
697 <ignoreBlock,ignoreEmbeddedBlock>{space}{endOfSection} {
698         yy_pop_state();
699     }
701 <ignoreBlock,ignoreEmbeddedBlock>{space}{labelList} {
702     }
704 <ignoreBlock,ignoreEmbeddedBlock>{space}{hexLabelList} {
705     }
707 <ignoreBlock,ignoreEmbeddedBlock>{space}{scalarList} {
708     }
710 <ignoreBlock,ignoreEmbeddedBlock>{space}{schemeSymbolList} {
711     }
713 <ignoreBlock,ignoreEmbeddedBlock>{space}{text} {
714     }
717  /* ------              Count newlines.                              ------  */
719 <*>\n {
720         lineNo++;
721     }
724  /* ------              Ignore remaining space.                      ------  */
726 <*>{some_space}|\r {
727     }
730  /* ------              Any other characters are errors.              ------ */
732 <*>. {
733         // This is a catch all.
734         FatalErrorIn("fluentMeshToFoam::lexer")
735             << "Do not understand characters: " << YYText() << nl
736             << "    on line " << lineNo
737             << exit(FatalError);
738     }
741  /*  ------ On EOF return to previous file, if none exists terminate. ------ */
743 <<EOF>> {
744             yyterminate();
745     }
748 int main(int argc, char *argv[])
750     argList::noParallel();
751     argList::validArgs.append("Fluent mesh file");
752     argList::validOptions.insert("scale", "scale factor");
753     argList::validOptions.insert("ignoreCellGroups", "cell group names");
754     argList::validOptions.insert("ignoreFaceGroups", "face group names");
756     argList args(argc, argv);
758     if (!args.check())
759     {
760         FatalError.exit();
761     }
763     if (args.options().found("scale"))
764     {
765         scaleFactor = atof(args.options()["scale"].c_str());
766     }
768     HashSet<word> ignoreCellGroups;
769     if (args.options().found("ignoreCellGroups"))
770     {
771         IStringStream(args.options()["ignoreCellGroups"])() >> ignoreCellGroups;
772     }
774     HashSet<word> ignoreFaceGroups;
775     if (args.options().found("ignoreFaceGroups"))
776     {
777         IStringStream(args.options()["ignoreFaceGroups"])() >> ignoreFaceGroups;
778     }
780 #   include "createTime.H"
782     fileName fluentFile(args.additionalArgs()[0]);
783     IFstream fluentStream(fluentFile);
785     if (!fluentStream)
786     {
787         FatalErrorIn(args.executable())
788             << ": file " << fluentFile << " not found"
789             << exit(FatalError);
790     }
792     yyFlexLexer lexer(&fluentStream.stdStream());
794     while(lexer.yylex() != 0)
795     {}
797     Info<< "\nFINISHED LEXING\n\n";
799     if (dimensionOfGrid != 3)
800     {
801         FatalErrorIn(args.executable())
802             << "Mesh is not 3D, dimension of grid: " << dimensionOfGrid
803             << exit(FatalError);
804     }
806     pointGroupZoneID.shrink();
807     pointGroupStartIndex.shrink();
808     pointGroupEndIndex.shrink();
810     faceGroupZoneID.shrink();
811     faceGroupStartIndex.shrink();
812     faceGroupEndIndex.shrink();
814     cellGroupZoneID.shrink();
815     cellGroupStartIndex.shrink();
816     cellGroupEndIndex.shrink();
817     cellGroupType.shrink();
820     // Pre-filtering: flip "owner" boundary or wrong oriented internal
821     // faces and move to neighbour
822     forAll (faces, facei)
823     {
824         if
825         (
826             owner[facei] == -1
827          || (neighbour[facei] != -1 && owner[facei] > neighbour[facei])
828         )
829         {
830             faces[facei] = faces[facei].reverseFace();
831             Swap(owner[facei], neighbour[facei]);
832         }
833     }
836     // Foam type for Fluent type
837     // ~~~~~~~~~~~~~~~~~~~~~~~~~
839     HashTable<word> fluentToFoamType;
841     fluentToFoamType.insert("pressure", polyPatch::typeName);
842     fluentToFoamType.insert("pressure-inlet", polyPatch::typeName);
843     fluentToFoamType.insert("inlet-vent", polyPatch::typeName);
844     fluentToFoamType.insert("intake-fan", polyPatch::typeName);
845     fluentToFoamType.insert("pressure-outlet", polyPatch::typeName);
846     fluentToFoamType.insert("exhaust-fan", polyPatch::typeName);
847     fluentToFoamType.insert("outlet-vent", polyPatch::typeName);
848     fluentToFoamType.insert("pressure-far-field", polyPatch::typeName);
849     fluentToFoamType.insert("velocity-inlet", polyPatch::typeName);
850     fluentToFoamType.insert("mass-flow-inlet", polyPatch::typeName);
851     fluentToFoamType.insert("outflow", polyPatch::typeName);
853     fluentToFoamType.insert("wall" , wallPolyPatch::typeName);
855     fluentToFoamType.insert("symmetry",  symmetryPolyPatch::typeName);
856     fluentToFoamType.insert("axis",  symmetryPolyPatch::typeName);
858     fluentToFoamType.insert("interior", polyPatch::typeName);
859     fluentToFoamType.insert("interface", polyPatch::typeName);
860     fluentToFoamType.insert("internal", polyPatch::typeName);
861     fluentToFoamType.insert("solid", polyPatch::typeName);
862     fluentToFoamType.insert("fan", cyclicPolyPatch::typeName);
863     fluentToFoamType.insert("radiator", polyPatch::typeName);
864     fluentToFoamType.insert("porous-jump", polyPatch::typeName);
867     // Foam patch type for Fluent zone type
868     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
870     HashSet<word> fluentGroupToFoamPatch;
871     fluentGroupToFoamPatch.insert("wall");
872     fluentGroupToFoamPatch.insert("fan");
875     // Create intial empty polyMesh
876     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
878     polyMesh mesh
879     (
880         IOobject
881         (
882             polyMesh::defaultRegion,
883             runTime.constant(),
884             runTime
885         ),
886         pointField(0),
887         faceList(0),
888         labelList(0),
889         labelList(0)
890     );
893     // Check the cell groups for zones ignoring those in ignoreCellGroups
894     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
895     label nCellZones = 0;
896     labelList cellZoneIDs(cellGroupZoneID.size());
898     forAll(cellGroupZoneID, cgi)
899     {
900         if (!ignoreCellGroups.found(groupName[cellGroupZoneID[cgi] ]))
901         {
902             cellZoneIDs[nCellZones++] = cgi;
903         }
904     }
906     cellZoneIDs.setSize(nCellZones);
909     // Check the face groups for boundary patches, baffles and faceZones
910     // ignoring the interior zones in ignoreCellGroups
911     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
912     DynamicList<label> patchIDs(faceGroupZoneID.size());
913     DynamicList<label> faceZoneIDs(faceGroupZoneID.size());
915     forAll(faceGroupZoneID, fgi)
916     {
917         label zoneID = faceGroupZoneID[fgi];
918         label start = faceGroupStartIndex[fgi];
920         if (groupType.found(zoneID))
921         {
922             const word& type = groupType[zoneID];
924             // Check the first element of neighbour for boundary group
925             if (neighbour[start] == -1 || fluentGroupToFoamPatch.found(type))
926             {
927                 patchIDs.append(fgi);
928             }
929             else
930             {
931                 if (!ignoreFaceGroups.found(groupName[faceGroupZoneID[fgi] ]))
932                 {
933                     faceZoneIDs.append(fgi);
934                 }
935             }
936         }
937         else if (hangingNodes)
938         {
939             label end = faceGroupEndIndex[fgi];
941             Info<< "Unknown FaceGroup " << zoneID
942                 << " assumed to be parent faces of refinement "
943                    "patterns and ignored."
944                 << endl;
946             // Set the owner of these faces to -1 so that they do not get
947             // added to the mesh
948             for(label facei = start; facei <= end; facei++)
949             {
950                 owner[facei] = -1;
951             }
952         }
953         else
954         {
955             if (neighbour[start] == -1)
956             {
957                 // Boundary face in unknown group. Create a patch for it.
958                 groupType.insert(zoneID, "unknown");
959                 groupName.insert(zoneID, "FaceGroup" + Foam::name(zoneID));
960                 patchIDs.append(fgi);
961                 Info<< "Created patch " << fgi << " for unknown FaceGroup "
962                     << zoneID << '.' << endl;
963             }
964             else
965             {
966                 WarningIn(args.executable())
967                     << "Unknown FaceGroup " << zoneID << " not in a zone"
968                     << endl;
969             }
970         }
971     }
973     patchIDs.shrink();
974     faceZoneIDs.shrink();
977     // Add empty patches
978     // ~~~~~~~~~~~~~~~~~
980     List<polyPatch*> newPatches(patchIDs.size());
981     HashSet<word> patchNames;
983     forAll(patchIDs, patchi)
984     {
985         label zoneID = faceGroupZoneID[patchIDs[patchi] ];
986         word name = groupName[zoneID];
987         const word& type = groupType[zoneID];
989         Info<< "Creating patch " << patchi
990             << " for zone: " << zoneID
991             << " name: " << name
992             << " type: " << type
993             << endl;
995         uniquify(name, patchNames);
997         HashTable<word>::const_iterator iter = fluentToFoamType.find(type);
999         if (iter != fluentToFoamType.end())
1000         {
1001             newPatches[patchi] = polyPatch::New
1002             (
1003                 iter(),
1004                 name,
1005                 0,
1006                 0,
1007                 patchi,
1008                 mesh.boundaryMesh()
1009             ).ptr();
1010         }
1011         else
1012         {
1013             Info<< "Adding polyPatch for unknown Fluent type " << type
1014                 << endl;
1016             newPatches[patchi] = new polyPatch
1017             (
1018                 name,
1019                 0,
1020                 0,
1021                 patchi,
1022                 mesh.boundaryMesh()
1023             );
1024         }
1025     }
1026     mesh.addPatches(newPatches);
1029     // Add empty zones
1030     // ~~~~~~~~~~~~~~~
1032     // Cell zones
1033     mesh.cellZones().setSize(cellZoneIDs.size());
1034     HashSet<word> cellZoneNames;
1036     forAll(cellZoneIDs, cellZonei)
1037     {
1038         label zoneID = cellGroupZoneID[cellZoneIDs[cellZonei] ];
1039         word name = groupName[zoneID];
1040         const word& type = groupType[zoneID];
1042         Info<< "Creating cellZone " << cellZonei
1043             << " name: " << name
1044             << " type: " << type
1045             << endl;
1047         uniquify(name, cellZoneNames);
1049         mesh.cellZones().set
1050         (
1051             cellZonei,
1052             new cellZone
1053             (
1054                 name,
1055                 labelList(0),
1056                 cellZonei,
1057                 mesh.cellZones()
1058             )
1059         );
1060     }
1062     // Face zones
1063     mesh.faceZones().setSize(faceZoneIDs.size());
1064     HashSet<word> faceZoneNames;
1066     forAll(faceZoneIDs, faceZonei)
1067     {
1068         label zoneID = faceGroupZoneID[faceZoneIDs[faceZonei] ];
1069         word name = groupName[zoneID];
1070         const word& type = groupType[zoneID];
1072         Info<< "Creating faceZone " << faceZonei
1073             << " name: " << name
1074             << " type: " << type
1075             << endl;
1077         uniquify(name, faceZoneNames);
1079         mesh.faceZones().set
1080         (
1081             faceZonei,
1082             new faceZone
1083             (
1084                 name,
1085                 labelList(0),
1086                 boolList(0),
1087                 faceZonei,
1088                 mesh.faceZones()
1089             )
1090         );
1091     }
1094     // Modify mesh for points/cells/faces
1095     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1097     // Mesh-change container
1098     polyTopoChange meshMod(mesh, false);
1100     // Add all points
1101     forAll(points, pointi)
1102     {
1103         meshMod.addPoint(points[pointi], pointi, -1, true);
1104     }
1105     points.setSize(0);
1107     // Add all cells
1108     for (label celli = 0; celli < nCells; celli++)
1109     {
1110         meshMod.addCell
1111         (
1112             -1,         // masterPointID
1113             -1,         // masterEdgeID
1114             -1,         // masterFaceID
1115             celli,      // masterCellID
1116             -1          // zoneID
1117         );
1118     }
1120     // Modify cells to be in zones as required
1121     forAll(cellZoneIDs, cellZonei)
1122     {
1123         label cgi = cellZoneIDs[cellZonei];
1125         for
1126         (
1127             label celli = cellGroupStartIndex[cgi];
1128             celli <= cellGroupEndIndex[cgi];
1129             celli++
1130         )
1131         {
1132             meshMod.modifyCell(celli, cellZonei);
1133         }
1134     }
1137     bool doneWarning = false;
1139     // Add faceZone faces
1140     forAll(faceZoneIDs, faceZonei)
1141     {
1142         label fgi = faceZoneIDs[faceZonei];
1143         label start = faceGroupStartIndex[fgi];
1144         label end = faceGroupEndIndex[fgi];
1145         label zoneID = faceGroupZoneID[fgi];
1147         Info<< "faceZone from Fluent indices: " << start
1148             << " to: " << end
1149             << " type: " << groupType[zoneID]
1150             << endl;
1152         for (label facei = start; facei <= end; facei++)
1153         {
1154             if (owner[facei] >= nCells || neighbour[facei] >= nCells)
1155             {
1156                 if (!doneWarning)
1157                 {
1158                     WarningIn(args.executable())
1159                         << "Ignoring internal face " << facei
1160                         << " on FaceZone " << zoneID
1161                         << " since owner " << owner[facei] << " or neighbour "
1162                         << neighbour[facei] << " outside range of cells 0.."
1163                         << nCells-1 << endl
1164                         << "    Suppressing future warnings." << endl;
1165                     doneWarning = true;
1166                 }
1167             }
1168             else
1169             {
1170                 meshMod.addFace
1171                 (
1172                     faces[facei],
1173                     owner[facei],
1174                     neighbour[facei],
1175                     -1,                 // masterPointID
1176                     -1,                 // masterEdgeID
1177                     facei,              // masterFace
1178                     false,              // flipFaceFlux
1179                     -1,                 // patchID
1180                     faceZonei,          // zoneID
1181                     false               // zoneFlip
1182                 );
1183             }
1185             // Mark face as being done
1186             owner[facei] = -1;
1187         }
1188     }
1190     // Add patch faces
1191     forAll(patchIDs, patchi)
1192     {
1193         label fgi = patchIDs[patchi];
1194         label start = faceGroupStartIndex[fgi];
1195         label end = faceGroupEndIndex[fgi];
1196         label zoneID = faceGroupZoneID[fgi];
1198         Info<< "patch " << patchi << " from Fluent indices: " << start
1199             << " to: " << end
1200             << " type: " << groupType[zoneID]
1201             << endl;
1203         for (label facei = start; facei <= end; facei++)
1204         {
1205             if (owner[facei] >= nCells || neighbour[facei] >= nCells)
1206             {
1207                 if (!doneWarning)
1208                 {
1209                     WarningIn(args.executable())
1210                         << "Ignoring patch face " << facei
1211                         << " on FaceZone " << zoneID
1212                         << " since owner " << owner[facei] << " or neighbour "
1213                         << neighbour[facei] << " outside range of cells 0.."
1214                         << nCells-1 << endl
1215                         << "    Suppressing future warnings." << endl;
1216                     doneWarning = true;
1217                 }
1218             }
1219             else
1220             {
1221                 meshMod.addFace
1222                 (
1223                     faces[facei],
1224                     owner[facei],
1225                     -1,
1226                     -1,                 // masterPointID
1227                     -1,                 // masterEdgeID
1228                     facei,              // masterFace
1229                     false,              // flipFaceFlux
1230                     patchi,             // patchID
1231                     -1,                 // zoneID
1232                     false               // zoneFlip
1233                 );
1235                 // For baffles create the opposite face
1236                 if (neighbour[start] != -1)
1237                 {
1238                     meshMod.addFace
1239                     (
1240                         faces[facei].reverseFace(),
1241                         neighbour[facei],
1242                         -1,
1243                         -1,                 // masterPointID
1244                         -1,                 // masterEdgeID
1245                         facei,              // masterFace
1246                         false,              // flipFaceFlux
1247                         patchi,             // patchID
1248                         -1,                 // zoneID
1249                         false               // zoneFlip
1250                     );
1251                 }
1252             }
1253             // Mark face as being done
1254             owner[facei] = -1;
1255         }
1256     }
1258     // Add remaining internal faces
1259     forAll(owner, facei)
1260     {
1261         if (owner[facei] != -1)
1262         {
1263             // Check the face being added as an internal face actually is one
1264             if (neighbour[facei] == -1)
1265             {
1266                 FatalErrorIn(args.executable())
1267                     << "Attempt of add internal face " << facei
1268                     << " which is a boundary face"
1269                     << exit(FatalError);
1270             }
1272             if (owner[facei] >= nCells || neighbour[facei] >= nCells)
1273             {
1274                 if (!doneWarning)
1275                 {
1276                     WarningIn(args.executable())
1277                         << "Ignoring internal face " << facei
1278                         << " since owner " << owner[facei] << " or neighbour "
1279                         << neighbour[facei] << " outside range of cells 0.."
1280                         << nCells-1 << endl
1281                         << "    Suppressing future warnings." << endl;
1282                     doneWarning = true;
1283                 }
1284             }
1285             else
1286             {
1287                 meshMod.addFace
1288                 (
1289                     faces[facei],
1290                     owner[facei],
1291                     neighbour[facei],
1292                     -1,                 //masterPointID
1293                     -1,                 //masterEdgeID
1294                     facei,              //masterFace
1295                     false,              //flipFaceFlux
1296                     -1,                 //patchID
1297                     -1,                 //zoneID
1298                     false               //zoneFlip
1299                 );
1300             }
1301         }
1302     }
1304     // Reclaim storage
1305     faces.setSize(0);
1306     owner.setSize(0);
1307     neighbour.setSize(0);
1310     // Modify mesh
1311     // ~~~~~~~~~~~
1313     autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false);
1315     // Zip-up the mesh if it contained hanging nodes
1316     if (hangingNodes)
1317     {
1318         Info<< "Zipping mesh to remove hanging nodes" << endl;
1319         polyMeshZipUpCells(mesh);
1320     }
1322     mesh.setInstance(runTime.constant());
1324     // Set the precision of the points data to 10
1325     IOstream::defaultPrecision(10);
1327     Info<< nl << "Writing mesh to " << mesh.objectPath() << endl;
1328     mesh.write();
1331     Info<< nl << "End" << endl;
1332     return 0;
1336  /* ------------------------------------------------------------------------ *\
1337     ------ End of fluentMeshToFoam.L
1338  \* ------------------------------------------------------------------------ */