1 /*--------------------------------*- C++ -*----------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
28 Converts an ANSYS input mesh file, exported from I-DEAS,
31 \*---------------------------------------------------------------------------*/
37 /* ------------------------------------------------------------------------- *\
38 ------ local definitions
39 \* ------------------------------------------------------------------------- */
46 #include "IStringStream.H"
53 #include "emptyPolyPatch.H"
54 #include "preservePatchTypes.H"
55 #include "cellShape.H"
56 #include "cellModeller.H"
58 #include "SLPtrList.H"
60 SLList<point> slPoints;
61 SLList<label> slPointMap;
64 SLPtrList<labelList> slCellLabels;
65 SLList<label> slCellMap;
66 SLList<label> slCellType;
69 PtrList<SLList<label> > slPatchCells;
70 PtrList<SLList<label> > slPatchCellFaces;
74 label currentTypei = -1;
77 // Dummy yywrap to keep yylex happy at compile time.
78 // It is called by yylex but is not used as the mechanism to change file.
80 #if YY_FLEX_SUBMINOR_VERSION < 34
81 extern "C" int yywrap()
83 int yyFlexLexer::yywrap()
93 some_space {one_space}+
99 identifier {alpha}({alpha}|{digit})*
103 exponent_part [eE][-+]?{digit}+
104 fractional_constant [-+]?(({digit}*"."{digit}+)|({digit}+"."?))
106 floatNum (({fractional_constant}{exponent_part}?)|({digit}+{exponent_part}))
113 node ^{space}"N"{cspace}
114 element ^{space}"EN"{cspace}
115 bface ^{space}"SFE"{cspace}
116 elementTypeName ^{space}"ET"{cspace}
117 elementType ^{space}"TYPE"{cspace}
127 /* ------------------------------------------------------------------------- *\
128 ------ Start Lexing ------
129 \* ------------------------------------------------------------------------- */
131 {node}{label}{cspace}{x}{cspace}{y}{cspace}{z}{space}\n {
132 IStringStream nodeStream(YYText());
143 if (nodei > maxNodei) maxNodei = nodei;
145 slPointMap.append(nodei);
146 slPoints.append(node);
150 {element}{label}{cspace}{label}{cspace}{label}{cspace}{label}{cspace}{label}{cspace}{label}{cspace}{label}{cspace}{label}{cspace}{label}{space}\n {
151 IStringStream elementStream(YYText());
166 if (celli > maxCelli) maxCelli = celli;
168 slCellMap.append(celli);
169 slCellLabels.append(new labelList(labels));
170 slCellType.append(currentTypei);
174 {bface}{label}{cspace}{label}{cspace}{identifier}{cspace}{integer}{cspace}{value}{space}\n {
175 IStringStream bfaceStream(YYText());
179 scalar indexValue, unknown;
184 >> c >> tag >> tag >> tag >> tag
188 label patchi = label(indexValue);
190 if (patchi > slPatchCells.size())
192 slPatchCells.setSize(patchi);
194 forAll(slPatchCells, i)
196 if (!slPatchCells(i))
198 slPatchCells.set(i, new SLList<label>);
203 if (patchi > slPatchCellFaces.size())
205 slPatchCellFaces.setSize(patchi);
207 forAll(slPatchCells, i)
209 if (!slPatchCellFaces(i))
211 slPatchCellFaces.set(i, new SLList<label>);
216 slPatchCells[patchi-1].append(elementi);
217 slPatchCellFaces[patchi-1].append(facei);
221 {elementTypeName}{label}{cspace}{identifier}{space}\n {
223 IStringStream elementStream(YYText());
228 >> tag >> tag // skip 'ET'
230 >> c >> cellTypeName;
232 Info<< "Read typeName " << cellTypeName
233 << " for type " << cellTypei << endl;
235 cellTypes.insert(cellTypei, cellTypeName);
239 {elementType}{label}{space}\n {
240 IStringStream elementStream(YYText());
244 >> tag >> tag >> tag >> tag // skip 'TYPE'
247 currentTypei = cellTypei;
252 /* ------------------------------------------------------------------------- *\
253 ------ Ignore remaining space and \n s. Any other characters are errors.
254 \* ------------------------------------------------------------------------- */
259 /* ------------------------------------------------------------------------- *\
260 ------ On EOF return to previous file, if none exists terminate.
261 \* ------------------------------------------------------------------------- */
269 #include "fileName.H"
274 label findFace(const polyMesh& mesh, const face& f)
276 const labelList& pFaces = mesh.pointFaces()[f[0]];
280 label faceI = pFaces[i];
282 if (mesh.faces()[faceI] == f)
288 FatalErrorIn("findFace(const polyMesh&, const face&)")
289 << "Cannot find a face matching " << f
296 int main(int argc, char *argv[])
298 argList::noParallel();
299 argList::validArgs.append("ANSYS input file");
304 "geometry scaling factor - default is 1"
307 argList args(argc, argv);
314 const scalar scaleFactor = args.optionLookupOrDefault("scale", 1.0);
316 # include "createTime.H"
318 fileName ansysFile(args.additionalArgs()[0]);
319 ifstream ansysStream(ansysFile.c_str());
323 FatalErrorIn("ansysToFoam::main(int argc, char *argv[])")
325 << ": file " << ansysFile << " not found"
329 yyFlexLexer lexer(&ansysStream);
330 while (lexer.yylex() != 0)
333 Info<< "Creating points" << endl;
335 pointField points(slPoints.size());
338 forAllConstIter(SLList<point>, slPoints, pointIter)
340 // Scale points for the given scale factor
341 points[i++] = scaleFactor * pointIter();
345 labelList pointMap(maxNodei+1);
348 forAllConstIter(SLList<label>, slPointMap, pointMapIter)
350 pointMap[pointMapIter()] = i++;
353 Info<< "Creating cells" << endl;
355 labelList cellMap(maxCelli+1);
358 forAllConstIter(SLList<label>, slCellMap, cellMapIter)
360 cellMap[cellMapIter()] = i++;
364 const cellModel& hex = *(cellModeller::lookup("hex"));
365 const cellModel& prism = *(cellModeller::lookup("prism"));
366 const cellModel& pyr = *(cellModeller::lookup("pyr"));
367 const cellModel& tet = *(cellModeller::lookup("tet"));
369 labelList labelsHex(8);
370 labelList labelsPrism(6);
371 labelList labelsPyramid(5);
372 labelList labelsTet(4);
374 cellShapeList cellShapes(slCellLabels.size());
377 forAllConstIter(SLPtrList<labelList>, slCellLabels, cellIter)
381 cellIter()[2] == cellIter()[3]
382 && cellIter()[4] == cellIter()[5]
383 && cellIter()[5] == cellIter()[6]
384 && cellIter()[6] == cellIter()[7]
387 labelsTet[0] = pointMap[cellIter()[0] ];
388 labelsTet[1] = pointMap[cellIter()[1] ];
389 labelsTet[2] = pointMap[cellIter()[2] ];
390 labelsTet[3] = pointMap[cellIter()[4] ];
392 cellShapes[nCells++] = cellShape(tet, labelsTet);
395 else if // Square-based pyramid
397 cellIter()[4] == cellIter()[5]
398 && cellIter()[5] == cellIter()[6]
399 && cellIter()[6] == cellIter()[7]
402 labelsPyramid[0] = pointMap[cellIter()[0] ];
403 labelsPyramid[1] = pointMap[cellIter()[1] ];
404 labelsPyramid[2] = pointMap[cellIter()[2] ];
405 labelsPyramid[3] = pointMap[cellIter()[3] ];
406 labelsPyramid[4] = pointMap[cellIter()[4] ];
408 cellShapes[nCells++] = cellShape(pyr, labelsPyramid);
411 else if // Triangular prism
413 cellIter()[2] == cellIter()[3]
414 && cellIter()[6] == cellIter()[7]
417 labelsPrism[0] = pointMap[cellIter()[0] ];
418 labelsPrism[1] = pointMap[cellIter()[1] ];
419 labelsPrism[2] = pointMap[cellIter()[2] ];
420 labelsPrism[3] = pointMap[cellIter()[4] ];
421 labelsPrism[4] = pointMap[cellIter()[5] ];
422 labelsPrism[5] = pointMap[cellIter()[6] ];
424 cellShapes[nCells++] = cellShape(prism, labelsPrism);
429 labelsHex[0] = pointMap[cellIter()[0] ];
430 labelsHex[1] = pointMap[cellIter()[1] ];
431 labelsHex[2] = pointMap[cellIter()[2] ];
432 labelsHex[3] = pointMap[cellIter()[3] ];
433 labelsHex[4] = pointMap[cellIter()[4] ];
434 labelsHex[5] = pointMap[cellIter()[5] ];
435 labelsHex[6] = pointMap[cellIter()[6] ];
436 labelsHex[7] = pointMap[cellIter()[7] ];
438 cellShapes[nCells++] = cellShape(hex, labelsHex);
443 const word defaultFacesName = "defaultFaces";
444 word defaultFacesType = emptyPolyPatch::typeName;
446 // Create dummy mesh just to find out what are internal/external
448 autoPtr<polyMesh> dummyMesh
470 // Warning: tet face order has changed between version 1.9.6 and 2.0
472 label faceIndex[7][6] =
474 {-1, -1, -1, -1, -1, -1}, // 0
475 {-1, -1, -1, -1, -1, -1}, // 1
476 {-1, -1, -1, -1, -1, -1}, // 2
477 {-1, -1, -1, -1, -1, -1}, // 3
478 { 3, 2, 0, -1, 1, -1}, // tet (version 2.0)
479 { 0, 4, 3, -1, 2, 1}, // prism
480 { 4, 2, 1, 3, 0, 5}, // hex
483 Info<< "Creating boundary patches" << endl;
485 faceListList boundary(slPatchCells.size());
486 wordList patchNames(slPatchCells.size());
488 forAll(slPatchCells, patchI)
490 SLList<face> patchFaces;
492 SLList<label>::iterator cellIter(slPatchCells[patchI].begin());
493 SLList<label>::iterator faceIter(slPatchCellFaces[patchI].begin());
498 cellIter != slPatchCells[patchI].end()
499 && faceIter != slPatchCellFaces[patchI].end();
500 ++cellIter, ++faceIter
503 const cellShape& shape = cellShapes[cellMap[cellIter()]];
516 boundary[patchI] = patchFaces;
517 patchNames[patchI] = word("patch") + name(patchI + 1);
522 // Lookup the face labels for all the boundary faces
524 labelListList boundaryFaceLabels(boundary.size());
525 forAll(boundary, patchI)
527 const faceList& bFaces = boundary[patchI];
528 labelList& bFaceLabels = boundaryFaceLabels[patchI];
529 bFaceLabels.setSize(bFaces.size());
532 bFaceLabels[i] = findFace(dummyMesh(), bFaces[i]);
537 // Now split the boundary faces into external and internal faces. All
538 // faces go into faceZones and external faces go into patches.
539 List<faceList> patchFaces(slPatchCells.size());
540 labelList patchNFaces(slPatchCells.size(), 0);
541 forAll(boundary, patchI)
543 const faceList& bFaces = boundary[patchI];
544 const labelList& bFaceLabels = boundaryFaceLabels[patchI];
546 patchFaces[patchI].setSize(bFaces.size());
550 if (!dummyMesh().isInternalFace(bFaceLabels[i]))
552 patchFaces[patchI][patchNFaces[patchI]++] = bFaces[i];
555 patchFaces[patchI].setSize(patchNFaces[patchI]);
557 Info<< "Patch " << patchI << " named " << patchNames[patchI]
558 << ": " << boundary[patchI].size() << " faces" << endl;
561 // We no longer need the dummyMesh
565 Info<< "ansysToFoam: " << endl
566 << "Ansys file format does not provide information about the type of "
567 << "the patch (eg. wall, symmetry plane, cyclic etc)." << endl
568 << "All the patches have been created "
569 << "as type patch. Please reset after mesh conversion as necessary."
572 PtrList<dictionary> patchDicts;
578 polyMesh::meshSubDir,
585 // Add information to dictionary
586 forAll(patchNames, patchI)
588 if (!patchDicts.set(patchI))
590 patchDicts.set(patchI, new dictionary());
592 // Add but not overwrite
593 patchDicts[patchI].add("type", polyPatch::typeName, false);
601 polyMesh::defaultRegion,
615 if (cellTypes.size() > 0 || patchNames.size() > 0)
617 DynamicList<pointZone*> pz;
618 DynamicList<faceZone*> fz;
619 DynamicList<cellZone*> cz;
622 forAll(boundaryFaceLabels, patchI)
624 if (boundaryFaceLabels[patchI].size())
626 // Re-do the boundaryFaceLabels since the boundary face
627 // labels will be different on the pShapeMesh.
628 const faceList& bFaces = boundary[patchI];
629 labelList& bFaceLabels = boundaryFaceLabels[patchI];
630 forAll(bFaceLabels, i)
632 bFaceLabels[i] = findFace(pShapeMesh, bFaces[i]);
635 Info<< "Creating faceZone " << patchNames[patchI]
636 << " with " << bFaceLabels.size() << " faces" << endl;
644 boolList(bFaceLabels.size(), false),
646 pShapeMesh.faceZones()
654 labelList types = cellTypes.sortedToc();
658 label cellType = types[j];
660 // Pick up cells in zone
661 DynamicList<label> addr;
663 SLList<label>::iterator cellMapIter = slCellMap.begin();
664 SLList<label>::iterator typeIter = slCellType.begin();
669 typeIter != slCellType.end();
670 ++typeIter, ++cellMapIter
673 if (typeIter() == cellType)
675 addr.append(cellMap[cellMapIter()]);
679 Info<< "Creating cellZone " << cellTypes[cellType]
680 << " with " << addr.size() << " cells" << endl;
689 pShapeMesh.cellZones()
694 pShapeMesh.addZones(pz, fz, cz);
698 // Set the precision of the points data to 10
699 IOstream::defaultPrecision(10);
701 Info<< "Writing polyMesh" << endl;
704 Info<< nl << "end" << endl;
709 /* ------------------------------------------------------------------------- *\
710 ------ End of ansysToFoam.L
711 \* ------------------------------------------------------------------------- */