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 an ANSYS input mesh file, exported from I-DEAS, to FOAM format.
30 \*---------------------------------------------------------------------------*/
36 /* ------------------------------------------------------------------------ *\
37 ------ local definitions
38 \* ------------------------------------------------------------------------ */
45 #include "IStringStream.H"
50 #include "objectRegistry.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_MINOR_VERSION < 6 && 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"
273 label findFace(const polyMesh& mesh, const face& f)
277 FatalErrorIn("findFace(const polyMesh&, const face&)")
278 << "Empty face found: " << f
282 const faceList& faces = mesh.faces();
284 const labelList& pFaces = mesh.pointFaces()[f[0]];
288 label faceI = pFaces[i];
290 if (faces[faceI] == f)
296 FatalErrorIn("findFace(const polyMesh&, const face&)")
297 << "Cannot find a face matching " << f
304 int main(int argc, char *argv[])
306 argList::noParallel();
307 argList::validArgs.append("ANSYS input file");
308 argList::validOptions.insert("scale", "scale factor");
310 argList args(argc, argv);
317 scalar scaleFactor = 1.0;
318 args.optionReadIfPresent("scale", scaleFactor);
320 # include "createTime.H"
322 fileName ansysFile(args.additionalArgs()[0]);
323 ifstream ansysStream(ansysFile.c_str());
327 FatalErrorIn("ansysToFoam::main(int argc, char *argv[])")
329 << ": file " << ansysFile << " not found"
333 yyFlexLexer lexer(&ansysStream);
334 while (lexer.yylex() != 0)
337 Info<< "Creating points" << endl;
339 pointField points(slPoints.size());
342 forAllConstIter(SLList<point>, slPoints, pointIter)
344 // Scale points for the given scale factor
345 points[i++] = scaleFactor * pointIter();
349 labelList pointMap(maxNodei+1);
352 forAllConstIter(SLList<label>, slPointMap, pointMapIter)
354 pointMap[pointMapIter()] = i++;
357 Info<< "Creating cells" << endl;
359 labelList cellMap(maxCelli+1);
362 forAllConstIter(SLList<label>, slCellMap, cellMapIter)
364 cellMap[cellMapIter()] = i++;
368 const cellModel& hex = *(cellModeller::lookup("hex"));
369 const cellModel& prism = *(cellModeller::lookup("prism"));
370 const cellModel& pyr = *(cellModeller::lookup("pyr"));
371 const cellModel& tet = *(cellModeller::lookup("tet"));
373 labelList labelsHex(8);
374 labelList labelsPrism(6);
375 labelList labelsPyramid(5);
376 labelList labelsTet(4);
378 cellShapeList cellShapes(slCellLabels.size());
381 forAllConstIter(SLPtrList<labelList>, slCellLabels, cellIter)
385 cellIter()[2] == cellIter()[3]
386 && cellIter()[4] == cellIter()[5]
387 && cellIter()[5] == cellIter()[6]
388 && cellIter()[6] == cellIter()[7]
391 labelsTet[0] = pointMap[cellIter()[0] ];
392 labelsTet[1] = pointMap[cellIter()[1] ];
393 labelsTet[2] = pointMap[cellIter()[2] ];
394 labelsTet[3] = pointMap[cellIter()[4] ];
396 cellShapes[nCells++] = cellShape(tet, labelsTet);
399 else if // Square-based pyramid
401 cellIter()[4] == cellIter()[5]
402 && cellIter()[5] == cellIter()[6]
403 && cellIter()[6] == cellIter()[7]
406 labelsPyramid[0] = pointMap[cellIter()[0] ];
407 labelsPyramid[1] = pointMap[cellIter()[1] ];
408 labelsPyramid[2] = pointMap[cellIter()[2] ];
409 labelsPyramid[3] = pointMap[cellIter()[3] ];
410 labelsPyramid[4] = pointMap[cellIter()[4] ];
412 cellShapes[nCells++] = cellShape(pyr, labelsPyramid);
415 else if // Triangular prism
417 cellIter()[2] == cellIter()[3]
418 && cellIter()[6] == cellIter()[7]
421 labelsPrism[0] = pointMap[cellIter()[0] ];
422 labelsPrism[1] = pointMap[cellIter()[1] ];
423 labelsPrism[2] = pointMap[cellIter()[2] ];
424 labelsPrism[3] = pointMap[cellIter()[4] ];
425 labelsPrism[4] = pointMap[cellIter()[5] ];
426 labelsPrism[5] = pointMap[cellIter()[6] ];
428 cellShapes[nCells++] = cellShape(prism, labelsPrism);
433 labelsHex[0] = pointMap[cellIter()[0] ];
434 labelsHex[1] = pointMap[cellIter()[1] ];
435 labelsHex[2] = pointMap[cellIter()[2] ];
436 labelsHex[3] = pointMap[cellIter()[3] ];
437 labelsHex[4] = pointMap[cellIter()[4] ];
438 labelsHex[5] = pointMap[cellIter()[5] ];
439 labelsHex[6] = pointMap[cellIter()[6] ];
440 labelsHex[7] = pointMap[cellIter()[7] ];
442 cellShapes[nCells++] = cellShape(hex, labelsHex);
447 const word defaultFacesName = "defaultFaces";
448 word defaultFacesType = emptyPolyPatch::typeName;
450 // Create dummy mesh just to find out what are internal/external
452 autoPtr<polyMesh> dummyMesh
474 // Warning: tet face order has changed between version 1.9.6 and 2.0
476 label faceIndex[7][6] =
478 {-1, -1, -1, -1, -1, -1}, // 0
479 {-1, -1, -1, -1, -1, -1}, // 1
480 {-1, -1, -1, -1, -1, -1}, // 2
481 {-1, -1, -1, -1, -1, -1}, // 3
482 {-1, 2, 0, 3, 1, -1}, // tet (version 2.0)
483 { 0, 4, 3, -1, 2, 1}, // prism
484 { 4, 2, 1, 3, 0, 5}, // hex
487 Info<< "Creating boundary patches" << endl;
489 faceListList boundary(slPatchCells.size());
490 wordList patchNames(slPatchCells.size());
492 forAll(slPatchCells, patchI)
494 SLList<face> patchFaces;
496 SLList<label>::iterator cellIter(slPatchCells[patchI].begin());
497 SLList<label>::iterator faceIter(slPatchCellFaces[patchI].begin());
502 cellIter != slPatchCells[patchI].end()
503 && faceIter != slPatchCellFaces[patchI].end();
504 ++cellIter, ++faceIter
507 const cellShape& shape = cellShapes[cellMap[cellIter()]];
520 boundary[patchI] = patchFaces;
521 patchNames[patchI] = word("patch") + name(patchI + 1);
526 // Lookup the face labels for all the boundary faces
528 labelListList boundaryFaceLabels(boundary.size());
529 forAll(boundary, patchI)
531 const faceList& bFaces = boundary[patchI];
532 labelList& bFaceLabels = boundaryFaceLabels[patchI];
533 bFaceLabels.setSize(bFaces.size());
536 bFaceLabels[i] = findFace(dummyMesh(), bFaces[i]);
541 // Now split the boundary faces into external and internal faces. All
542 // faces go into faceZones and external faces go into patches.
543 List<faceList> patchFaces(slPatchCells.size());
544 labelList patchNFaces(slPatchCells.size(), 0);
545 forAll(boundary, patchI)
547 const faceList& bFaces = boundary[patchI];
548 const labelList& bFaceLabels = boundaryFaceLabels[patchI];
550 patchFaces[patchI].setSize(bFaces.size());
554 if (!dummyMesh().isInternalFace(bFaceLabels[i]))
556 patchFaces[patchI][patchNFaces[patchI]++] = bFaces[i];
559 patchFaces[patchI].setSize(patchNFaces[patchI]);
561 Info<< "Patch " << patchI << " named " << patchNames[patchI]
562 << ": " << boundary[patchI].size() << " faces" << endl;
565 // We no longer need the dummyMesh
569 Info<< "ansysToFoam: " << endl
570 << "Ansys file format does not provide information about the type of "
571 << "the patch (eg. wall, symmetry plane, cyclic etc)." << endl
572 << "All the patches have been created "
573 << "as type patch. Please reset after mesh conversion as necessary."
576 PtrList<dictionary> patchDicts;
582 polyMesh::meshSubDir,
589 // Add information to dictionary
590 forAll(patchNames, patchI)
592 if (!patchDicts.set(patchI))
594 patchDicts.set(patchI, new dictionary());
596 // Add but not overwrite
597 patchDicts[patchI].add("type", polyPatch::typeName, false);
605 polyMesh::defaultRegion,
619 if (cellTypes.size() > 0 || patchNames.size() > 0)
621 DynamicList<pointZone*> pz;
622 DynamicList<faceZone*> fz;
623 DynamicList<cellZone*> cz;
626 forAll(boundaryFaceLabels, patchI)
628 if (boundaryFaceLabels[patchI].size())
630 // Re-do the boundaryFaceLabels since the boundary face
631 // labels will be different on the pShapeMesh.
632 const faceList& bFaces = boundary[patchI];
633 labelList& bFaceLabels = boundaryFaceLabels[patchI];
634 forAll(bFaceLabels, i)
636 bFaceLabels[i] = findFace(pShapeMesh, bFaces[i]);
639 Info<< "Creating faceZone " << patchNames[patchI]
640 << " with " << bFaceLabels.size() << " faces" << endl;
648 boolList(bFaceLabels.size(), false),
650 pShapeMesh.faceZones()
658 labelList types = cellTypes.toc();
662 label cellType = types[j];
664 // Pick up cells in zone
665 DynamicList<label> addr;
667 SLList<label>::iterator cellMapIter = slCellMap.begin();
668 SLList<label>::iterator typeIter = slCellType.begin();
673 typeIter != slCellType.end();
674 ++typeIter, ++cellMapIter
677 if (typeIter() == cellType)
679 addr.append(cellMap[cellMapIter()]);
683 Info<< "Creating cellZone " << cellTypes[cellType]
684 << " with " << addr.size() << " cells" << endl;
693 pShapeMesh.cellZones()
698 pShapeMesh.addZones(pz, fz, cz);
702 // Set the precision of the points data to 10
703 IOstream::defaultPrecision(max(10u, IOstream::defaultPrecision()));
705 Info<< "Writing polyMesh" << endl;
708 Info<< nl << "end" << endl;
713 /* ------------------------------------------------------------------------- *\
714 ------ End of ansysToFoam.L
715 \* ------------------------------------------------------------------------- */