1 /*--------------------------------*- C++ -*----------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation, either version 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
28 Converts a GAMBIT mesh to FOAM format.
30 \*---------------------------------------------------------------------------*/
36 /* ------------------------------------------------------------------------- *\
37 ------ local definitions
38 \* ------------------------------------------------------------------------- */
40 #include "scalarList.H"
41 #include "IStringStream.H"
49 #include "objectRegistry.H"
52 #include "emptyPolyPatch.H"
53 #include "preservePatchTypes.H"
54 #include "cellModeller.H"
55 #include "cellShape.H"
57 #include "SLPtrList.H"
61 label nCellStreams = 0;
64 label nCoordDirections = 0;
65 label nVectorComponents = 0;
69 labelList pointMap(0);
71 PtrList<labelList> cellLabels(0);
73 labelList cellTypes(0);
74 labelList cellStreamIDs(0);
76 wordList patchNames(0);
77 labelListList patchCells(0);
78 labelListList patchCellFaces(0);
79 label nValuesForPatchFaces = 0;
81 // Dummy yywrap to keep yylex happy at compile time.
82 // It is called by yylex but is not used as the mechanism to change file.
84 #if YY_FLEX_MINOR_VERSION < 6 && YY_FLEX_SUBMINOR_VERSION < 34
85 extern "C" int yywrap()
87 int yyFlexLexer::yywrap()
97 some_space {one_space}+
108 word ({alpha}|{digit}|{dotColonDash})*
110 exponent_part [eE][-+]?{digit}+
111 fractional_constant [-+]?(({digit}*"."{digit}+)|({digit}+"."?))
113 floatNum ((({fractional_constant}{exponent_part}?)|({digit}+{exponent_part}))|0)
119 labelListElement {space}{zeroLabel}
120 scalarListElement {space}{floatNum}
121 labelList ({labelListElement}+{space})
122 scalarList ({scalarListElement}+{space})
125 text ({space}({word}*{space})*\n)
127 dateDDMMYYYY ({digit}{digit}"/"{digit}{digit}"/"{digit}{digit}{digit}{digit})
128 dateDDMonYYYY ((({digit}{digit}{space})|({digit}{space})){alpha}*{space}{digit}{digit}{digit}{digit})
129 time ({digit}{digit}":"{digit}{digit}":"{digit}{digit})
131 versionNumber ({digit}|".")*
133 controlInfo ^{space}"CONTROL INFO"{space}{versionNumber}
134 applicationData ^{space}"APPLICATION DATA"{space}{versionNumber}
135 nodalCoords ^{space}"NODAL COORDINATES"{space}{versionNumber}
136 cellsAndElements ^{space}"ELEMENTS/CELLS"{space}{versionNumber}
137 cellStreams ^{space}"ELEMENT GROUP"{space}{versionNumber}
138 boundaryPatch ^{space}"BOUNDARY CONDITIONS"{space}{versionNumber}
139 faceConnectivity ^{space}"FACE CONNECTIVITY"{space}{versionNumber}
141 endOfSection ^{space}"ENDOFSECTION"{space}
143 program {space}"PROGRAM:"{space}
144 version {space}"VERSION:"{space}
146 group {space}"GROUP:"{space}
147 elements {space}"ELEMENTS:"{space}
148 material {space}"MATERIAL:"{space}
149 nFlags {space}"NFLAGS:"{space}
150 mtype {space}"MTYPE:"{space}
153 /* ------------------------------------------------------------------------- *\
154 ----- Exclusive start states -----
155 \* ------------------------------------------------------------------------- */
171 %x readCellStreamGroupID
172 %x readCellStreamNElements
173 %x readCellStreamMaterial
174 %x readCellStreamNFlags
176 %x boundaryPatchParams
177 %x boundaryPatchFaces
186 label nCellContinuationLines = 0;
187 label curNumberOfNodes = 0;
188 label curNumberOfCells = 0;
189 label curGroupID = 0;
190 label nFlagsForStream = 0;
191 label curBoundaryPatch = 0;
192 label curPatchFace = 0;
196 /* ------------------------------------------------------------------------- *\
197 ------ Start Lexing ------
198 \* ------------------------------------------------------------------------- */
200 /* ------ Reading control header ------ */
203 BEGIN(readControlHeader);
207 <readControlHeader>{starStar}{space}{text} {
214 Info << "Title: " << YYText();
219 <controlInfo>{spaceNl}{program} {
220 BEGIN(readProgramID);
224 <readProgramID>{space}{word} {
226 Info<< "Written by " << YYText() << " ";
231 <controlInfo>{spaceNl}{version} {
232 BEGIN(readVersionID);
236 <readVersionID>{space}{versionNumber} {
238 Info<< " version " << YYText() << endl;
243 <controlInfo>{space}{dateDDMonYYYY}{space}{time} {
245 Info<< "File written on " << YYText() << endl;
249 <controlInfo>{space}{dateDDMMYYYY}{space}{time} {
251 Info<< "File written on " << YYText() << endl;
255 <controlInfo>{spaceNl}"NUMNP"{space}"NELEM"{space}"NGRPS"{space}"NBSETS"{space}("NDFCD"|"NDCFD"){space}"NDFVL"{space}\n {
256 BEGIN(globalMeshData);
260 <globalMeshData>{spaceNl}{label}{space}{label}{space}{label}{space}{label}{space}{label}{space}{label}{space}\n {
262 IStringStream nodeStream(YYText());
264 nPoints = readLabel(nodeStream);
265 nCells = readLabel(nodeStream);
266 nCellStreams = readLabel(nodeStream);
267 nPatches = readLabel(nodeStream);
268 nCoordDirections = readLabel(nodeStream);
269 nVectorComponents = readLabel(nodeStream);
271 // reset list sizes - now known!
272 points.setSize(nPoints);
273 pointMap.setSize(nPoints);
275 cellLabels.setSize(nCells);
276 cellMap.setSize(nCells);
277 cellTypes.setSize(nCells);
278 cellStreamIDs.setSize(nCells);
280 patchNames.setSize(nPatches);
281 patchCells.setSize(nPatches);
282 patchCellFaces.setSize(nPatches);
284 Info<< " number of points: " << nPoints << endl
285 << " number of cells: " << nCells << endl
286 << " number of patches: " << nPatches << endl;
292 /* ------ Reading nodal coordinates ------ */
294 {nodalCoords}{spaceNl} {
296 curNumberOfNodes = 0;
297 Info<< "Reading nodal coordinates" << endl;
302 <nodalCoords>{spaceNl}{label}{space}{x}{space}{y}{space}{z}{space}\n {
304 IStringStream nodeStream(YYText());
306 label nodeI(readLabel(nodeStream));
308 // Note: coordinates must be read one at the time.
309 scalar x = readScalar(nodeStream);
310 scalar y = readScalar(nodeStream);
311 scalar z = readScalar(nodeStream);
313 // add mapping and scalced node to the list
314 pointMap[curNumberOfNodes] = nodeI;
315 points[curNumberOfNodes] = point(x, y, z);
320 /* ------ Reading cells and elements ------ */
322 {cellsAndElements}{spaceNl} {
324 curNumberOfCells = 0;
325 Info<< "Reading cells" << endl;
326 BEGIN(cellsAndElements);
329 <cellsAndElements>{spaceNl}{label}{space}{label}{space}{label}{labelList} {
331 IStringStream elementStream(YYText());
333 label cellI(readLabel(elementStream));
334 label cellType(readLabel(elementStream));
335 label nVertices(readLabel(elementStream));
337 // reset number of continuation lines
338 nCellContinuationLines = 0;
340 cellMap[curNumberOfCells] = cellI;
341 cellTypes[curNumberOfCells] = cellType;
342 cellLabels.set(curNumberOfCells, new labelList(nVertices));
344 labelList& curLabels = cellLabels[curNumberOfCells];
346 // Find out how many labels are expected. If less or equal to
347 // seven, read them all and finish with it. If there is more,
348 // set read of the next line
349 label labelsToRead = min(8, nVertices);
351 for (; labelI < labelsToRead; labelI++)
353 if (elementStream.eof()) break;
355 // Check token to avoid trailing space.
356 token curLabelTok(elementStream);
357 if (curLabelTok.isLabel())
359 curLabels[labelI] = curLabelTok.labelToken();
367 if (labelI < nVertices)
378 <cellContLine>{spaceNl}{labelList} {
380 IStringStream elementStream(YYText());
382 nCellContinuationLines++;
384 labelList& curLabels = cellLabels[curNumberOfCells];
386 label labelsToRead = min
388 (nCellContinuationLines + 1)*7,
394 label labelI = nCellContinuationLines*7;
395 labelI < labelsToRead;
399 curLabels[labelI] = readLabel(elementStream);
402 // if read is finished, go back to reading cells
403 if (curLabels.size() < (nCellContinuationLines + 1)*7)
407 BEGIN(cellsAndElements);
412 /* ------ Reading element group information ------ */
414 {cellStreams}{spaceNl} {
415 Info<< "Reading cell streams" << endl;
420 <cellStreams>{spaceNl}{group} {
421 BEGIN(readCellStreamGroupID);
425 <readCellStreamGroupID>{space}{label} {
426 IStringStream groupStream(YYText());
430 FatalErrorIn("gambitToFoam::main")
431 << "<readCellStreamGroupID>{space}{label} : "
432 << "trying to reset group ID while active"
433 << abort(FatalError);
437 curGroupID = readLabel(groupStream);
444 <cellStreams>{spaceNl}{elements} {
445 BEGIN(readCellStreamNElements);
449 <readCellStreamNElements>{space}{label} {
451 IStringStream nElementsStream(YYText());
453 readLabel(nElementsStream);
458 <cellStreams>{spaceNl}{material} {
459 BEGIN(readCellStreamMaterial);
463 <readCellStreamMaterial>{space}{label} {
465 IStringStream materialIDstream(YYText());
467 readLabel(materialIDstream);
473 <cellStreams>{spaceNl}{nFlags} {
474 BEGIN(readCellStreamNFlags);
478 <readCellStreamNFlags>{space}{label} {
480 IStringStream nFlagsStream(YYText());
482 nFlagsForStream = readLabel(nFlagsStream);
484 BEGIN(cellStreamTitle);
488 <cellStreamTitle>{spaceNl}{word}{spaceNl} {
490 word streamName(Foam::string::validate<word>(YYText()));
492 BEGIN(cellStreamFlags);
496 <cellStreamFlags>{labelList} {
497 Info<< "Reading cell stream labels" << endl;
498 BEGIN(cellStreamLabels);
502 <cellStreamLabels>{spaceNl}{labelList} {
504 IStringStream nFlagsStream(YYText());
507 while (nFlagsStream.read(cellLabel))
509 cellStreamIDs[cellLabel - 1] = curGroupID;
512 // reset current group ID and a number of flags
518 /* ------ Reading end of section and others ------ */
520 <cellStreamLabels>{endOfSection}\n {
522 Info<< "Finished reading cell stream labels" << endl;
524 // reset current group ID and a number of flags
532 {boundaryPatch}{spaceNl} {
534 Info<< "Reading patches" << endl;
535 BEGIN(boundaryPatchParams);
539 <boundaryPatchParams>{spaceNl}{word}{labelList} {
541 IStringStream patchParamsStream(YYText());
543 patchParamsStream.read(patchNames[curBoundaryPatch]);
545 readLabel(patchParamsStream);
546 label nEntry(readLabel(patchParamsStream));
547 nValuesForPatchFaces = readLabel(patchParamsStream);
549 patchCells[curBoundaryPatch].setSize(nEntry);
550 patchCellFaces[curBoundaryPatch].setSize(nEntry);
552 Info<< "patch " << curBoundaryPatch
553 << ": name: " << patchNames[curBoundaryPatch]
556 BEGIN(boundaryPatchFaces);
560 <boundaryPatchFaces>{spaceNl}{label}{space}{label}{space}{label}({scalarList}|{space}\n) {
562 // Face-based boundary condition
563 IStringStream patchFacesStream(YYText());
565 patchCells[curBoundaryPatch][curPatchFace] =
566 readLabel(patchFacesStream);
567 readLabel(patchFacesStream);
568 patchCellFaces[curBoundaryPatch][curPatchFace] =
569 readLabel(patchFacesStream);
571 // patch face values currently discarded
572 if (nValuesForPatchFaces > 0)
574 scalarList patchFaceValues(nValuesForPatchFaces);
576 forAll(patchFaceValues, fI)
578 patchFaceValues[fI] = readScalar(patchFacesStream);
586 <boundaryPatchFaces>{spaceNl}{label}({scalarList}|\n) {
588 // Vertex-based boundary condition
589 FatalErrorIn("gambitToFoam::main")
590 << "<boundaryPatchFaces>{spaceNl}{label}{scalarList} : "
591 << "boundary condition specified on vertices not supported"
592 << abort(FatalError);
596 <boundaryPatchFaces>{endOfSection}\n {
604 /* ------ Reading end of section and others ------ */
606 <controlInfo,nodalCoords,cellsAndElements>{endOfSection}\n {
611 /* ------ Ignore remaining space and \n s. Any other characters are errors. */
616 /* ------ On EOF return to previous file, if none exists terminate. ------ */
624 #include "fileName.H"
628 int main(int argc, char *argv[])
630 argList::noParallel();
631 argList::validArgs.append("GAMBIT file");
632 argList::validOptions.insert("scale", "scale factor");
634 argList args(argc, argv);
641 scalar scaleFactor = 1.0;
642 args.optionReadIfPresent("scale", scaleFactor);
644 # include "createTime.H"
646 fileName gambitFile(args.additionalArgs()[0]);
647 ifstream gambitStream(gambitFile.c_str());
651 FatalErrorIn("gambitToFoam::main")
653 << ": file " << gambitFile << " not found"
654 << abort(FatalError);
657 yyFlexLexer lexer(&gambitStream);
658 while (lexer.yylex() != 0)
661 Info<< "Finished lexing" << endl;
663 // make a point mapping array
664 label maxPointIndex = 0;
666 forAll(pointMap, pointI)
668 if (pointMap[pointI] > maxPointIndex)
670 maxPointIndex = pointMap[pointI];
675 labelList pointLookup(maxPointIndex + 1, -1);
677 forAll(pointMap, pointI)
679 pointLookup[pointMap[pointI] ] = pointI;
682 // make a cell mapping array
683 label maxCellIndex = 0;
685 forAll(cellMap, cellI)
687 if (cellMap[cellI] > maxCellIndex)
689 maxCellIndex = cellMap[cellI];
693 labelList cellLookup(maxCellIndex + 1);
695 forAll(cellMap, cellI)
697 cellLookup[cellMap[cellI] ] = cellI;
700 const cellModel& hex = *(cellModeller::lookup("hex"));
701 const cellModel& prism = *(cellModeller::lookup("prism"));
702 const cellModel& pyr = *(cellModeller::lookup("pyr"));
703 const cellModel& tet = *(cellModeller::lookup("tet"));
705 labelList labelsHex(8);
706 labelList labelsPrism(6);
707 labelList labelsPyramid(5);
708 labelList labelsTet(4);
710 cellShapeList cells(cellLabels.size());
712 forAll(cellTypes, cellI)
714 const labelList& curCellLabels = cellLabels[cellI];
717 if (cellTypes[cellI] == 6)
719 labelsTet[0] = pointLookup[curCellLabels[0] ];
720 labelsTet[1] = pointLookup[curCellLabels[2] ];
721 labelsTet[2] = pointLookup[curCellLabels[3] ];
722 labelsTet[3] = pointLookup[curCellLabels[1] ];
724 cells[cellI] = cellShape(tet, labelsTet);
727 // Square-based pyramid
728 else if (cellTypes[cellI] == 7)
730 labelsPyramid[0] = pointLookup[curCellLabels[0] ];
731 labelsPyramid[1] = pointLookup[curCellLabels[1] ];
732 labelsPyramid[2] = pointLookup[curCellLabels[3] ];
733 labelsPyramid[3] = pointLookup[curCellLabels[2] ];
734 labelsPyramid[4] = pointLookup[curCellLabels[4] ];
736 cells[cellI] = cellShape(pyr, labelsPyramid);
740 else if (cellTypes[cellI] == 5)
742 labelsPrism[0] = pointLookup[curCellLabels[0] ];
743 labelsPrism[1] = pointLookup[curCellLabels[1] ];
744 labelsPrism[2] = pointLookup[curCellLabels[2] ];
745 labelsPrism[3] = pointLookup[curCellLabels[3] ];
746 labelsPrism[4] = pointLookup[curCellLabels[4] ];
747 labelsPrism[5] = pointLookup[curCellLabels[5] ];
749 cells[cellI] = cellShape(prism, labelsPrism);
753 else if (cellTypes[cellI] == 4)
755 labelsHex[0] = pointLookup[curCellLabels[0] ];
756 labelsHex[1] = pointLookup[curCellLabels[1] ];
757 labelsHex[2] = pointLookup[curCellLabels[3] ];
758 labelsHex[3] = pointLookup[curCellLabels[2] ];
759 labelsHex[4] = pointLookup[curCellLabels[4] ];
760 labelsHex[5] = pointLookup[curCellLabels[5] ];
761 labelsHex[6] = pointLookup[curCellLabels[7] ];
762 labelsHex[7] = pointLookup[curCellLabels[6] ];
764 cells[cellI] = cellShape(hex, labelsHex);
768 // give foam model face number given a fluent model face number
769 label faceIndex[8][6] =
771 {-1, -1, -1, -1, -1, -1}, // 0
772 {-1, -1, -1, -1, -1, -1}, // 1
773 {-1, -1, -1, -1, -1, -1}, // 2
774 { 2, 1, 3, 0, 4, 5}, // Hex (3)
775 {-1, -1, -1, -1, -1, -1}, // 4
776 { 4, 3, 2, 0, 1, -1}, // Triangular prism (5)
777 { 0, 4, 3, 2, 1, -1}, // Pyramid (6)
778 { 2, 1, 0, 3, -1, -1} // Tet (7)
781 faceListList boundary(patchCells.size());
783 forAll(patchCells, patchI)
785 labelList& curCells = patchCells[patchI];
786 labelList& curFaces = patchCellFaces[patchI];
788 faceList& patchFaces = boundary[patchI];
789 patchFaces.setSize(curCells.size());
791 forAll(curCells, faceI)
794 cells[cellLookup[curCells[faceI] ] ].faces()
798 // this picks a cell type
799 cells[cellLookup[curCells[faceI] ] ]
802 [curFaces[faceI] - 1] // this gives a fluent face - 1
808 Info<< "gambitToFoam: " << endl
809 << "Gambit file format does not provide information about the type of "
810 << "the patch (eg. wall, symmetry plane, cyclic etc)." << endl
811 << "All the patches have been created "
812 << "as type patch. Please reset after mesh conversion as necessary."
816 points *= scaleFactor;
818 PtrList<dictionary> patchDicts(boundary.size());
819 word defaultFacesName = "defaultFaces";
820 word defaultFacesType = emptyPolyPatch::typeName;
826 polyMesh::meshSubDir,
833 // Add information to dictionary
834 forAll(patchNames, patchI)
836 if (!patchDicts.set(patchI))
838 patchDicts.set(patchI, new dictionary());
840 // Add but not overwrite
841 patchDicts[patchI].add("type", polyPatch::typeName, false);
848 polyMesh::defaultRegion,
861 // Set the precision of the points data to 10
862 IOstream::defaultPrecision(max(10u, IOstream::defaultPrecision()));
864 Info<< "Writing polyMesh" << endl;
867 Info<< "\nEnd\n" << endl;
872 /* ------------------------------------------------------------------------- *\
873 ------ End of gambitToFoam.L
874 \* ------------------------------------------------------------------------- */