1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2004-2010 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
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/>.
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 // ************************************************************************* //