1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
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 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
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 \*---------------------------------------------------------------------------*/
27 #include "STARCDMeshWriter.H"
30 #include "SortableList.H"
33 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35 const char* Foam::meshWriters::STARCD::defaultBoundaryName =
36 "Default_Boundary_Region";
38 const Foam::label Foam::meshWriters::STARCD::foamToStarFaceAddr[4][6] =
40 { 4, 5, 2, 3, 0, 1 }, // 11 = pro-STAR hex
41 { 0, 1, 4, 5, 2, -1 }, // 12 = pro-STAR prism
42 { 5, 4, 2, 0, -1, -1 }, // 13 = pro-STAR tetra
43 { 0, 4, 3, 5, 2, -1 } // 14 = pro-STAR pyramid
47 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
49 Foam::label Foam::meshWriters::STARCD::findDefaultBoundary() const
51 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
55 // find Default_Boundary_Region if it exists
56 forAll(patches, patchI)
58 if (defaultBoundaryName == patches[patchI].name())
68 void Foam::meshWriters::STARCD::getCellTable()
70 // read constant/polyMesh/propertyName
79 IOobject::READ_IF_PRESENT,
85 bool useCellZones = false;
86 cellTableId_.setSize(mesh_.nCells(), -1);
88 // get information from constant/polyMesh/cellTableId if possible
89 if (ioList.headerOk())
91 if (ioList.size() == mesh_.nCells())
93 cellTableId_.transfer(ioList);
95 if (!cellTable_.size())
97 Info<< "no cellTable information available" << endl;
102 WarningIn("STARCD::getCellTable()")
103 << ioList.objectPath() << " has incorrect number of cells "
104 << " - use cellZone information"
119 if (!cellTable_.size())
121 Info<< "created cellTable from cellZones" << endl;
125 // track if there are unzoned cells
126 label nUnzoned = mesh_.nCells();
128 // get the cellZone <-> cellTable correspondence
129 Info<< "matching cellZones to cellTable" << endl;
131 forAll (mesh_.cellZones(), zoneI)
133 const cellZone& cZone = mesh_.cellZones()[zoneI];
136 nUnzoned -= cZone.size();
138 label tableId = cellTable_.findIndex(cZone.name());
143 dict.add("Label", cZone.name());
144 dict.add("MaterialType", "fluid");
145 tableId = cellTable_.append(dict);
150 cellTableId_[cZone[i]] = tableId;
159 dict.add("Label", "__unZonedCells__");
160 dict.add("MaterialType", "fluid");
161 label tableId = cellTable_.append(dict);
163 forAll (cellTableId_, i)
165 if (cellTableId_[i] < 0)
167 cellTableId_[i] = tableId;
175 void Foam::meshWriters::STARCD::writeHeader(Ostream& os, const char* filetype)
177 os << "PROSTAR_" << filetype << nl
190 void Foam::meshWriters::STARCD::writePoints(const fileName& prefix) const
192 OFstream os(prefix + ".vrt");
193 writeHeader(os, "VERTEX");
195 // Set the precision of the points data to 10
198 // force decimal point for Fortran input
199 os.setf(std::ios::showpoint);
201 const pointField& points = mesh_.points();
203 Info<< "Writing " << os.name() << " : "
204 << points.size() << " points" << endl;
208 // convert [m] -> [mm]
211 << scaleFactor_ * points[ptI].x() << " "
212 << scaleFactor_ * points[ptI].y() << " "
213 << scaleFactor_ * points[ptI].z() << nl;
220 void Foam::meshWriters::STARCD::writeCells(const fileName& prefix) const
222 OFstream os(prefix + ".cel");
223 writeHeader(os, "CELL");
225 // this is what we seem to need
226 // map foam cellModeller index -> star shape
227 Map<label> shapeLookupIndex;
228 shapeLookupIndex.insert(hexModel->index(), 11);
229 shapeLookupIndex.insert(prismModel->index(), 12);
230 shapeLookupIndex.insert(tetModel->index(), 13);
231 shapeLookupIndex.insert(pyrModel->index(), 14);
233 const cellShapeList& shapes = mesh_.cellShapes();
234 const cellList& cells = mesh_.cells();
235 const faceList& faces = mesh_.faces();
236 const labelList& owner = mesh_.faceOwner();
238 Info<< "Writing " << os.name() << " : "
239 << cells.size() << " cells" << endl;
241 forAll(cells, cellId)
243 label tableId = cellTableId_[cellId];
244 label materialType = 1; // 1(fluid)
245 if (cellTable_.found(tableId))
247 const dictionary& dict = cellTable_[tableId];
248 if (dict.found("MaterialType"))
251 dict.lookup("MaterialType") >> matType;
252 if (matType == "solid")
260 const cellShape& shape = shapes[cellId];
261 label mapIndex = shape.model().index();
263 // a registered primitive type
264 if (shapeLookupIndex.found(mapIndex))
266 label shapeId = shapeLookupIndex[mapIndex];
267 const labelList& vrtList = shapes[cellId];
271 << " " << vrtList.size()
273 << " " << materialType;
275 // primitives have <= 8 vertices, but prevent overrun anyhow
276 // indent following lines for ease of reading
280 if ((count % 8) == 0)
283 << " " << cellId + 1;
285 os << " " << vrtList[i] + 1;
293 label shapeId = 255; // treat as general polyhedral
294 const labelList& cFaces = cells[cellId];
296 // create (beg,end) indices
297 List<label> indices(cFaces.size() + 1);
298 indices[0] = indices.size();
300 label count = indices.size();
301 // determine the total number of vertices
302 forAll(cFaces, faceI)
304 count += faces[cFaces[faceI]].size();
305 indices[faceI+1] = count;
312 << " " << materialType;
314 // write indices - max 8 per line
315 // indent following lines for ease of reading
319 if ((count % 8) == 0)
322 << " " << cellId + 1;
324 os << " " << indices[i];
328 // write faces - max 8 per line
329 forAll(cFaces, faceI)
331 label meshFace = cFaces[faceI];
334 if (owner[meshFace] == cellId)
340 f = faces[meshFace].reverseFace();
345 if ((count % 8) == 0)
348 << " " << cellId + 1;
351 os << " " << f[i] + 1;
362 void Foam::meshWriters::STARCD::writeBoundary(const fileName& prefix) const
364 OFstream os(prefix + ".bnd");
365 writeHeader(os, "BOUNDARY");
367 const cellShapeList& shapes = mesh_.cellShapes();
368 const cellList& cells = mesh_.cells();
369 const faceList& faces = mesh_.faces();
370 const labelList& owner = mesh_.faceOwner();
371 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
373 // this is what we seem to need
374 // these MUST correspond to foamToStarFaceAddr
376 Map<label> faceLookupIndex;
377 faceLookupIndex.insert(hexModel->index(), 0);
378 faceLookupIndex.insert(prismModel->index(), 1);
379 faceLookupIndex.insert(tetModel->index(), 2);
380 faceLookupIndex.insert(pyrModel->index(), 3);
382 Info<< "Writing " << os.name() << " : "
383 << (mesh_.nFaces() - patches[0].start()) << " boundaries" << endl;
386 label defaultId = findDefaultBoundary();
389 // write boundary faces - skip Default_Boundary_Region entirely
392 forAll(patches, patchI)
394 label regionId = patchI;
395 if (regionId == defaultId)
397 continue; // skip - already written
399 else if (defaultId == -1 || regionId < defaultId)
404 label patchStart = patches[patchI].start();
405 label patchSize = patches[patchI].size();
406 word bndType = boundaryRegion_.boundaryType(patches[patchI].name());
410 label faceI = patchStart;
411 faceI < (patchStart + patchSize);
415 label cellId = owner[faceI];
416 const labelList& cFaces = cells[cellId];
417 const cellShape& shape = shapes[cellId];
418 label cellFaceId = findIndex(cFaces, faceI);
420 // Info<< "cell " << cellId + 1 << " face " << faceI
421 // << " == " << faces[faceI]
422 // << " is index " << cellFaceId << " from " << cFaces;
424 // Unfortunately, the order of faces returned by
425 // primitiveMesh::cells() is not necessarily the same
426 // as defined by primitiveMesh::cellShapes()
427 // Thus, for registered primitive types, do the lookup ourselves.
428 // Finally, the cellModel face number is re-mapped to the
429 // STAR-CD local face number
431 label mapIndex = shape.model().index();
433 // a registered primitive type
434 if (faceLookupIndex.found(mapIndex))
436 const faceList sFaces = shape.faces();
437 forAll(sFaces, sFaceI)
439 if (faces[faceI] == sFaces[sFaceI])
446 mapIndex = faceLookupIndex[mapIndex];
447 cellFaceId = foamToStarFaceAddr[mapIndex][cellFaceId];
456 << " " << cellFaceId + 1
459 << " " << bndType.c_str()
466 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
468 Foam::meshWriters::STARCD::STARCD
470 const polyMesh& mesh,
471 const scalar scaleFactor
474 meshWriter(mesh, scaleFactor)
476 boundaryRegion_.readDict(mesh_);
477 cellTable_.readDict(mesh_);
482 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
484 Foam::meshWriters::STARCD::~STARCD()
488 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
490 void Foam::meshWriters::STARCD::rmFiles(const fileName& baseName) const
492 rm(baseName + ".vrt");
493 rm(baseName + ".cel");
494 rm(baseName + ".bnd");
495 rm(baseName + ".inp");
499 bool Foam::meshWriters::STARCD::write(const fileName& meshName) const
501 fileName baseName(meshName);
503 if (!baseName.size())
505 baseName = meshWriter::defaultMeshName;
509 mesh_.time().timeName() != "0"
510 && mesh_.time().timeName() != "constant"
513 baseName += "_" + mesh_.time().timeName();
518 writePoints(baseName);
519 writeCells(baseName);
523 writeBoundary(baseName);
530 bool Foam::meshWriters::STARCD::writeSurface
532 const fileName& meshName,
533 const bool& triangulate
536 fileName baseName(meshName);
538 if (!baseName.size())
540 baseName = meshWriter::defaultSurfaceName;
544 mesh_.time().timeName() != "0"
545 && mesh_.time().timeName() != "constant"
548 baseName += "_" + mesh_.time().timeName();
554 OFstream celFile(baseName + ".cel");
555 writeHeader(celFile, "CELL");
557 Info << "Writing " << celFile.name() << endl;
559 // mesh and patch info
560 const pointField& points = mesh_.points();
561 const labelList& owner = mesh_.faceOwner();
562 const faceList& meshFaces = mesh_.faces();
563 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
565 label shapeId = 3; // shell/baffle element
566 label typeId = 4; // 4(shell)
568 // remember which points need to be written
569 labelHashSet pointHash;
571 // write boundary faces as normal STAR-CD mesh
574 // cell Id has no particular meaning - just increment
575 // use the cellTable id from the patch Number
578 forAll(patches, patchI)
580 label patchStart = patches[patchI].start();
581 label patchSize = patches[patchI].size();
583 label ctableId = patchI + 1;
587 label faceI = patchStart;
588 faceI < (patchStart + patchSize);
592 const face& f = meshFaces[faceI];
594 label nTri = f.nTriangles(points);
597 // triangulate polygons, but not quads
605 triFaces.setSize(nTri);
607 f.triangles(points, nTri, triFaces);
610 forAll(triFaces, faceI)
612 const labelList& vrtList = triFaces[faceI];
617 << vrtList.size() << " "
621 // must be 3 (triangle) but could be quad
625 if ((count % 8) == 0)
629 << " " << cellId + 1;
631 // remember which points we'll need to write
632 pointHash.insert(vrtList[i]);
633 celFile << " " << vrtList[i] + 1;
645 // cell Id is the OpenFOAM face Id
646 // use the cellTable id from the face owner
647 // - allows separation of parts
648 forAll(patches, patchI)
650 label patchStart = patches[patchI].start();
651 label patchSize = patches[patchI].size();
655 label faceI = patchStart;
656 faceI < (patchStart + patchSize);
660 const labelList& vrtList = meshFaces[faceI];
661 label cellId = faceI;
666 << vrtList.size() << " "
667 << cellTableId_[owner[faceI]] << " "
670 // likely <= 8 vertices, but prevent overrun anyhow
674 if ((count % 8) == 0)
678 << " " << cellId + 1;
680 // remember which points we'll need to write
681 pointHash.insert(vrtList[i]);
682 celFile << " " << vrtList[i] + 1;
690 OFstream vrtFile(baseName + ".vrt");
691 writeHeader(vrtFile, "VERTEX");
693 vrtFile.precision(10);
694 vrtFile.setf(std::ios::showpoint); // force decimal point for Fortran
696 Info << "Writing " << vrtFile.name() << endl;
698 // build sorted table of contents
699 SortableList<label> toc(pointHash.size());
702 forAllConstIter(labelHashSet, pointHash, iter)
704 toc[i++] = iter.key();
710 // write points in sorted order
713 label vrtId = toc[i];
716 << " " << scaleFactor_ * points[vrtId].x()
717 << " " << scaleFactor_ * points[vrtId].y()
718 << " " << scaleFactor_ * points[vrtId].z()
726 // ************************************************************************* //