1 /*---------------------------------------------------------------------------*\
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/>.
24 \*---------------------------------------------------------------------------*/
26 #include "STARCDMeshWriter.H"
29 #include "SortableList.H"
32 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 const char* Foam::meshWriters::STARCD::defaultBoundaryName =
35 "Default_Boundary_Region";
37 const Foam::label Foam::meshWriters::STARCD::foamToStarFaceAddr[4][6] =
39 { 4, 5, 2, 3, 0, 1 }, // 11 = pro-STAR hex
40 { 0, 1, 4, 5, 2, -1 }, // 12 = pro-STAR prism
41 { 5, 4, 2, 0, -1, -1 }, // 13 = pro-STAR tetra
42 { 0, 4, 3, 5, 2, -1 } // 14 = pro-STAR pyramid
46 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
48 Foam::label Foam::meshWriters::STARCD::findDefaultBoundary() const
50 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
54 // find Default_Boundary_Region if it exists
55 forAll(patches, patchI)
57 if (defaultBoundaryName == patches[patchI].name())
67 void Foam::meshWriters::STARCD::getCellTable()
69 // read constant/polyMesh/propertyName
78 IOobject::READ_IF_PRESENT,
84 bool useCellZones = false;
85 cellTableId_.setSize(mesh_.nCells(), -1);
87 // get information from constant/polyMesh/cellTableId if possible
88 if (ioList.headerOk())
90 if (ioList.size() == mesh_.nCells())
92 cellTableId_.transfer(ioList);
94 if (cellTable_.empty())
96 Info<< "no cellTable information available" << endl;
101 WarningIn("STARCD::getCellTable()")
102 << ioList.objectPath() << " has incorrect number of cells "
103 << " - use cellZone information"
118 if (cellTable_.empty())
120 Info<< "created cellTable from cellZones" << endl;
124 // track if there are unzoned cells
125 label nUnzoned = mesh_.nCells();
127 // get the cellZone <-> cellTable correspondence
128 Info<< "matching cellZones to cellTable" << endl;
130 forAll (mesh_.cellZones(), zoneI)
132 const cellZone& cZone = mesh_.cellZones()[zoneI];
135 nUnzoned -= cZone.size();
137 label tableId = cellTable_.findIndex(cZone.name());
142 dict.add("Label", cZone.name());
143 dict.add("MaterialType", "fluid");
144 tableId = cellTable_.append(dict);
149 cellTableId_[cZone[i]] = tableId;
158 dict.add("Label", "__unZonedCells__");
159 dict.add("MaterialType", "fluid");
160 label tableId = cellTable_.append(dict);
162 forAll (cellTableId_, i)
164 if (cellTableId_[i] < 0)
166 cellTableId_[i] = tableId;
174 void Foam::meshWriters::STARCD::writeHeader(Ostream& os, const char* filetype)
176 os << "PROSTAR_" << filetype << nl
189 void Foam::meshWriters::STARCD::writePoints(const fileName& prefix) const
191 OFstream os(prefix + ".vrt");
192 writeHeader(os, "VERTEX");
194 // Set the precision of the points data to 10
197 // force decimal point for Fortran input
198 os.setf(std::ios::showpoint);
200 const pointField& points = mesh_.points();
202 Info<< "Writing " << os.name() << " : "
203 << points.size() << " points" << endl;
207 // convert [m] -> [mm]
210 << scaleFactor_ * points[ptI].x() << " "
211 << scaleFactor_ * points[ptI].y() << " "
212 << scaleFactor_ * points[ptI].z() << nl;
219 void Foam::meshWriters::STARCD::writeCells(const fileName& prefix) const
221 OFstream os(prefix + ".cel");
222 writeHeader(os, "CELL");
224 // this is what we seem to need
225 // map foam cellModeller index -> star shape
226 Map<label> shapeLookupIndex;
227 shapeLookupIndex.insert(hexModel->index(), 11);
228 shapeLookupIndex.insert(prismModel->index(), 12);
229 shapeLookupIndex.insert(tetModel->index(), 13);
230 shapeLookupIndex.insert(pyrModel->index(), 14);
232 const cellShapeList& shapes = mesh_.cellShapes();
233 const cellList& cells = mesh_.cells();
234 const faceList& faces = mesh_.faces();
235 const labelList& owner = mesh_.faceOwner();
237 Info<< "Writing " << os.name() << " : "
238 << cells.size() << " cells" << endl;
240 forAll(cells, cellId)
242 label tableId = cellTableId_[cellId];
243 label materialType = 1; // 1(fluid)
244 if (cellTable_.found(tableId))
246 const dictionary& dict = cellTable_[tableId];
247 if (dict.found("MaterialType"))
250 dict.lookup("MaterialType") >> matType;
251 if (matType == "solid")
259 const cellShape& shape = shapes[cellId];
260 label mapIndex = shape.model().index();
262 // a registered primitive type
263 if (shapeLookupIndex.found(mapIndex))
265 label shapeId = shapeLookupIndex[mapIndex];
266 const labelList& vrtList = shapes[cellId];
270 << " " << vrtList.size()
272 << " " << materialType;
274 // primitives have <= 8 vertices, but prevent overrun anyhow
275 // indent following lines for ease of reading
279 if ((count % 8) == 0)
282 << " " << cellId + 1;
284 os << " " << vrtList[i] + 1;
292 label shapeId = 255; // treat as general polyhedral
293 const labelList& cFaces = cells[cellId];
295 // create (beg,end) indices
296 List<label> indices(cFaces.size() + 1);
297 indices[0] = indices.size();
299 label count = indices.size();
300 // determine the total number of vertices
301 forAll(cFaces, faceI)
303 count += faces[cFaces[faceI]].size();
304 indices[faceI+1] = count;
311 << " " << materialType;
313 // write indices - max 8 per line
314 // indent following lines for ease of reading
318 if ((count % 8) == 0)
321 << " " << cellId + 1;
323 os << " " << indices[i];
327 // write faces - max 8 per line
328 forAll(cFaces, faceI)
330 label meshFace = cFaces[faceI];
333 if (owner[meshFace] == cellId)
339 f = faces[meshFace].reverseFace();
344 if ((count % 8) == 0)
347 << " " << cellId + 1;
350 os << " " << f[i] + 1;
361 void Foam::meshWriters::STARCD::writeBoundary(const fileName& prefix) const
363 OFstream os(prefix + ".bnd");
364 writeHeader(os, "BOUNDARY");
366 const cellShapeList& shapes = mesh_.cellShapes();
367 const cellList& cells = mesh_.cells();
368 const faceList& faces = mesh_.faces();
369 const labelList& owner = mesh_.faceOwner();
370 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
372 // this is what we seem to need
373 // these MUST correspond to foamToStarFaceAddr
375 Map<label> faceLookupIndex;
376 faceLookupIndex.insert(hexModel->index(), 0);
377 faceLookupIndex.insert(prismModel->index(), 1);
378 faceLookupIndex.insert(tetModel->index(), 2);
379 faceLookupIndex.insert(pyrModel->index(), 3);
381 Info<< "Writing " << os.name() << " : "
382 << (mesh_.nFaces() - patches[0].start()) << " boundaries" << endl;
385 label defaultId = findDefaultBoundary();
388 // write boundary faces - skip Default_Boundary_Region entirely
391 forAll(patches, patchI)
393 label regionId = patchI;
394 if (regionId == defaultId)
396 continue; // skip - already written
398 else if (defaultId == -1 || regionId < defaultId)
403 label patchStart = patches[patchI].start();
404 label patchSize = patches[patchI].size();
405 word bndType = boundaryRegion_.boundaryType(patches[patchI].name());
409 label faceI = patchStart;
410 faceI < (patchStart + patchSize);
414 label cellId = owner[faceI];
415 const labelList& cFaces = cells[cellId];
416 const cellShape& shape = shapes[cellId];
417 label cellFaceId = findIndex(cFaces, faceI);
419 // Info<< "cell " << cellId + 1 << " face " << faceI
420 // << " == " << faces[faceI]
421 // << " is index " << cellFaceId << " from " << cFaces;
423 // Unfortunately, the order of faces returned by
424 // primitiveMesh::cells() is not necessarily the same
425 // as defined by primitiveMesh::cellShapes()
426 // Thus, for registered primitive types, do the lookup ourselves.
427 // Finally, the cellModel face number is re-mapped to the
428 // STAR-CD local face number
430 label mapIndex = shape.model().index();
432 // a registered primitive type
433 if (faceLookupIndex.found(mapIndex))
435 const faceList sFaces = shape.faces();
436 forAll(sFaces, sFaceI)
438 if (faces[faceI] == sFaces[sFaceI])
445 mapIndex = faceLookupIndex[mapIndex];
446 cellFaceId = foamToStarFaceAddr[mapIndex][cellFaceId];
455 << " " << cellFaceId + 1
458 << " " << bndType.c_str()
465 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
467 Foam::meshWriters::STARCD::STARCD
469 const polyMesh& mesh,
470 const scalar scaleFactor
473 meshWriter(mesh, scaleFactor)
475 boundaryRegion_.readDict(mesh_);
476 cellTable_.readDict(mesh_);
481 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
483 Foam::meshWriters::STARCD::~STARCD()
487 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
489 void Foam::meshWriters::STARCD::rmFiles(const fileName& baseName) const
491 rm(baseName + ".vrt");
492 rm(baseName + ".cel");
493 rm(baseName + ".bnd");
494 rm(baseName + ".inp");
498 bool Foam::meshWriters::STARCD::write(const fileName& meshName) const
500 fileName baseName(meshName);
502 if (baseName.empty())
504 baseName = meshWriter::defaultMeshName;
508 mesh_.time().timeName() != "0"
509 && mesh_.time().timeName() != "constant"
512 baseName += "_" + mesh_.time().timeName();
517 writePoints(baseName);
518 writeCells(baseName);
522 writeBoundary(baseName);
529 bool Foam::meshWriters::STARCD::writeSurface
531 const fileName& meshName,
532 const bool& triangulate
535 fileName baseName(meshName);
537 if (baseName.empty())
539 baseName = meshWriter::defaultSurfaceName;
543 mesh_.time().timeName() != "0"
544 && mesh_.time().timeName() != "constant"
547 baseName += "_" + mesh_.time().timeName();
553 OFstream celFile(baseName + ".cel");
554 writeHeader(celFile, "CELL");
556 Info << "Writing " << celFile.name() << endl;
558 // mesh and patch info
559 const pointField& points = mesh_.points();
560 const labelList& owner = mesh_.faceOwner();
561 const faceList& meshFaces = mesh_.faces();
562 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
564 label shapeId = 3; // shell/baffle element
565 label typeId = 4; // 4(shell)
567 // remember which points need to be written
568 labelHashSet pointHash;
570 // write boundary faces as normal STAR-CD mesh
573 // cell Id has no particular meaning - just increment
574 // use the cellTable id from the patch Number
577 forAll(patches, patchI)
579 label patchStart = patches[patchI].start();
580 label patchSize = patches[patchI].size();
582 label ctableId = patchI + 1;
586 label faceI = patchStart;
587 faceI < (patchStart + patchSize);
591 const face& f = meshFaces[faceI];
593 label nTri = f.nTriangles(points);
596 // triangulate polygons, but not quads
604 triFaces.setSize(nTri);
606 f.triangles(points, nTri, triFaces);
609 forAll(triFaces, faceI)
611 const labelList& vrtList = triFaces[faceI];
616 << vrtList.size() << " "
620 // must be 3 (triangle) but could be quad
624 if ((count % 8) == 0)
628 << " " << cellId + 1;
630 // remember which points we'll need to write
631 pointHash.insert(vrtList[i]);
632 celFile << " " << vrtList[i] + 1;
644 // cell Id is the foam face Id
645 // use the cellTable id from the face owner
646 // - allows separation of parts
647 forAll(patches, patchI)
649 label patchStart = patches[patchI].start();
650 label patchSize = patches[patchI].size();
654 label faceI = patchStart;
655 faceI < (patchStart + patchSize);
659 const labelList& vrtList = meshFaces[faceI];
660 label cellId = faceI;
665 << vrtList.size() << " "
666 << cellTableId_[owner[faceI]] << " "
669 // likely <= 8 vertices, but prevent overrun anyhow
673 if ((count % 8) == 0)
677 << " " << cellId + 1;
679 // remember which points we'll need to write
680 pointHash.insert(vrtList[i]);
681 celFile << " " << vrtList[i] + 1;
689 OFstream vrtFile(baseName + ".vrt");
690 writeHeader(vrtFile, "VERTEX");
692 vrtFile.precision(10);
693 vrtFile.setf(std::ios::showpoint); // force decimal point for Fortran
695 Info << "Writing " << vrtFile.name() << endl;
697 // build sorted table of contents
698 SortableList<label> toc(pointHash.size());
701 forAllConstIter(labelHashSet, pointHash, iter)
703 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 // ************************************************************************* //