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 "ElmerMeshWriter.H"
29 #include "SortableList.H"
32 #include "hexMatcher.H"
33 #include "wedgeMatcher.H"
34 #include "prismMatcher.H"
35 #include "pyrMatcher.H"
36 #include "tetWedgeMatcher.H"
37 #include "tetMatcher.H"
40 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
42 void Foam::meshWriters::Elmer::getCellTable()
44 // read constant/polyMesh/propertyName
53 IOobject::READ_IF_PRESENT,
59 bool useCellZones = false;
60 cellTableId_.setSize(mesh_.nCells(), -1);
62 // get information from constant/polyMesh/cellTableId if possible
63 if (ioList.headerOk())
65 if (ioList.size() == mesh_.nCells())
67 cellTableId_.transfer(ioList);
69 if (cellTable_.empty())
71 Info<< "No cellTable information available" << endl;
76 WarningIn("Elmer::getCellTable()")
77 << ioList.objectPath() << " has incorrect number of cells "
78 << " - use cellZone information"
93 if (cellTable_.empty())
95 Info<< "Created cellTable from cellZones" << endl;
99 // track if there are unzoned cells
100 label nUnzoned = mesh_.nCells();
102 // get the cellZone <-> cellTable correspondence
103 Info<< "Matching cellZones to cellTable" << endl;
105 forAll (mesh_.cellZones(), zoneI)
107 const cellZone& cZone = mesh_.cellZones()[zoneI];
110 nUnzoned -= cZone.size();
112 label tableId = cellTable_.findIndex(cZone.name());
117 dict.add("Label", cZone.name());
118 dict.add("MaterialType", "fluid");
119 tableId = cellTable_.append(dict);
124 cellTableId_[cZone[i]] = tableId;
133 dict.add("Label", "__unZonedCells__");
134 dict.add("MaterialType", "fluid");
135 label tableId = cellTable_.append(dict);
137 forAll (cellTableId_, i)
139 if (cellTableId_[i] < 0)
141 cellTableId_[i] = tableId;
149 Foam::label Foam::meshWriters::Elmer::getFaceType
158 return ELMER_ETYPE_TRIA;
161 return ELMER_ETYPE_QUAD;
164 Info<< "Found a bad face with " << nvert
165 << " vertices on zone " << zname
167 return ELMER_ETYPE_BAD;
172 void Foam::meshWriters::Elmer::writeNames() const
174 OFstream os("mesh.names");
176 const cellZoneMesh& czones = mesh_.cellZones();
177 const faceZoneMesh& fzones = mesh_.faceZones();
178 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
179 label boundaryID = 0;
182 Info<< "Writing " << os.name() << "." << endl;
184 os << "! ----- Names for bodies -----" << nl;
185 forAll (czones, zoneI)
187 os << "$ " << czones[zoneI].name() << " = " << zoneI+1 << nl;
190 os << "! ----- Names for exterior boundaries -----" << nl;
191 forAll(patches, patchI)
193 os << "$ " << patches[patchI].name() << " = " << ++boundaryID << nl;
196 os << "! ----- Names for interior boundaries -----" << nl;
197 forAll(fzones, fzoneI)
199 if (!faceZoneExcludePattern.match(fzones[fzoneI].name()))
201 os << "$ " << fzones[fzoneI].name() << " = " << ++boundaryID << nl;
207 bool Foam::meshWriters::Elmer::writeHeader() const
209 const pointField& points = mesh_.points();
210 const cellList& cells = mesh_.cells();
211 const faceList& faces = mesh_.faces();
212 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
213 const faceZoneMesh& fzones = mesh_.faceZones();
214 label extZones = 0; // Count exterior boundary zones
215 label extFaces = 0; // Count exterior boundary faces
216 label intZones = 0; // Used interior boundary zones
217 label intFaces = 0; // Used interior boundary faces
219 // Count the different cell types
234 // Count all exterior boundary zone + faces + the types
235 forAll(patches, patchI)
237 const label patchStart = patches[patchI].start();
238 const label patchEnd = patchStart + patches[patchI].size();
241 extFaces += patches[patchI].size();
243 // Count triangles and quads
244 for(label faceI = patchStart; faceI < patchEnd; ++faceI)
246 if (faces[faceI].size() == 4)
257 // Count all interior boundary zones + faces with names not matching
258 // the exclude pattern
259 forAll(fzones, fzoneI)
261 if (faceZoneExcludePattern.match(fzones[fzoneI].name()))
266 const faceZone& fzone = fzones[fzoneI];
269 intFaces += fzone.size();
271 // Count triangles and quads
274 if (faces[fzone[i]].size() == 4)
285 // Count the volume element types
286 for(label cellI = 0; cellI < mesh_.nCells(); cellI++)
288 if (hex.isA(mesh_, cellI))
292 else if (tet.isA(mesh_, cellI))
296 else if (pyr.isA(mesh_, cellI))
300 else if (pri.isA(mesh_, cellI))
306 nBad++; // Not a valid element type for Elmer
310 OFstream os("mesh.header");
312 os << points.size() << " "
313 << cells.size() << " "
314 << extFaces+intFaces << nl;
316 Info<< "Writing " << os.name() << "." << endl;
318 // Save the number of different element types used
319 os << (nTet>0) + (nPri>0) + (nPyr>0) +
320 (nHex>0) + (nQua>0) + (nTri>0) + (nBad>0) << endl;
322 // Save type and count if count > 0
323 if (nTet > 0) os << ELMER_ETYPE_TET << " " << nTet << endl;
324 if (nPri > 0) os << ELMER_ETYPE_PRISM << " " << nPri << endl;
325 if (nPyr > 0) os << ELMER_ETYPE_PYRAM << " " << nPyr << endl;
326 if (nHex > 0) os << ELMER_ETYPE_HEX << " " << nHex << endl;
327 if (nQua > 0) os << ELMER_ETYPE_QUAD << " " << nQua << endl;
328 if (nTri > 0) os << ELMER_ETYPE_TRIA << " " << nTri << endl;
329 if (nBad > 0) os << ELMER_ETYPE_BAD << " " << nBad << endl;
331 Info<< "Mesh statistics:" << nl
332 << " Nodes : " << points.size() << nl
333 << " Elements : " << cells.size() << nl
334 << " Hexahedra : " << nHex << nl
335 << " Wedges : " << nPri << nl
336 << " Pyramids : " << nPyr << nl
337 << " Tetrahedra : " << nTet << nl
338 << " Polyhedra : " << nBad << nl
339 << " Regions : " << mesh_.cellZones().size() << nl
340 << " Ext. boundaries: " << extZones << ", "
341 << extFaces << " faces" << nl
342 << " Int. boundaries: " << intZones << ", "
343 << intFaces << " faces" << nl
344 << " Tri faces : " << nTri << nl
345 << " Quad faces : " << nQua << nl
352 void Foam::meshWriters::Elmer::writeNodes() const
354 OFstream os("mesh.nodes");
356 // Set the precision of the points data to 10
359 // Force decimal point for Fortran90 input style
360 os.setf(std::ios::showpoint);
362 const pointField& points = mesh_.points();
364 Info<< "Writing " << os.name() << ": scale=" << scaleFactor_ << endl;
368 os << ptI + 1 << " -1 "
369 << scaleFactor_ * points[ptI].x() << " "
370 << scaleFactor_ * points[ptI].y() << " "
371 << scaleFactor_ * points[ptI].z() << nl;
376 void Foam::meshWriters::Elmer::writeElements() const
378 OFstream os("mesh.elements");
380 // map foam cellModeller index -> Elmer element types
381 Map<label> shapeLookupIndex;
382 shapeLookupIndex.insert(tetModel->index(), ELMER_ETYPE_TET );
383 shapeLookupIndex.insert(prismModel->index(), ELMER_ETYPE_PRISM);
384 shapeLookupIndex.insert(pyrModel->index(), ELMER_ETYPE_PYRAM);
385 shapeLookupIndex.insert(hexModel->index(), ELMER_ETYPE_HEX );
387 const cellShapeList& shapes = mesh_.cellShapes();
388 const cellList& cells = mesh_.cells();
390 Info<< "Writing " << os.name() << "." << endl;
392 forAll(cells, cellId)
394 const cellShape& shape = shapes[cellId];
395 label mapIndex = shape.model().index();
397 // a registered primitive type
398 if (shapeLookupIndex.found(mapIndex))
400 os << cellId+1 << " "
401 << cellTableId_[cellId] << " "
402 << shapeLookupIndex[mapIndex];
404 const labelList& vrtList = shapes[cellId];
407 os << " " << vrtList[i] + 1;
413 Info<< "***WARNING: polyhedron " << cellId << " ignored." << endl;
419 void Foam::meshWriters::Elmer::writeBoundary() const
421 OFstream os("mesh.boundary");
423 const faceList& faces = mesh_.faces();
424 const labelList& owner = mesh_.faceOwner();
425 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
427 label boundaryID = 0;
430 Info<< "Writing " << os.name() << "." << endl;
432 // Write all patches == exterior boundary faces
433 forAll(patches, patchI)
435 const word& pname = patches[patchI].name();
436 const label patchStart = patches[patchI].start();
437 const label patchEnd = patchStart + patches[patchI].size();
440 for(label faceI = patchStart; faceI < patchEnd; ++faceI)
442 const labelList& vrtList = faces[faceI];
446 << " " << owner[faceI] + 1 // ID of parent cell
447 << " 0 " // 0 == exterior boundary face
448 << getFaceType(vrtList.size(),pname);
452 os << " " << vrtList[i] + 1;
459 // Write face zones (== interior boundary faces) with names not matching
460 // the exclude pattern
461 const faceZoneMesh& fzones = mesh_.faceZones();
462 forAll(fzones, fzoneI)
464 if(faceZoneExcludePattern.match(fzones[fzoneI].name()))
469 const faceZone& fzone = fzones[fzoneI];
470 const labelList& master = fzone.masterCells();
471 const labelList& slave = fzone.slaveCells();
472 const word& zname = fzone.name();
477 const labelList& vrtList = faces[fzone[i]];
481 << " " << master[i] + 1 // ID of parent cell
482 << " " << slave[i] + 1 // ID of neigbour cell
483 << " " << getFaceType(vrtList.size(),zname);
487 os << " " << vrtList[j] + 1;
495 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
497 Foam::meshWriters::Elmer::Elmer
499 const polyMesh& mesh,
500 const wordRe& excludePattern,
501 const scalar scaleFactor
504 meshWriter(mesh, scaleFactor),
505 faceZoneExcludePattern(excludePattern)
507 boundaryRegion_.readDict(mesh_);
508 cellTable_.readDict(mesh_);
513 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
515 Foam::meshWriters::Elmer::~Elmer()
520 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
522 bool Foam::meshWriters::Elmer::write(const fileName& dirName) const
524 fileName baseName(dirName);
526 if (baseName.empty())
528 baseName = meshWriter::defaultMeshName;
532 mesh_.time().timeName() != "0"
533 && mesh_.time().timeName() != "constant"
536 baseName += "_" + mesh_.time().timeName();
540 // Create the mesh directory (elemerMesh), chdir into and cleanup
549 bool success = writeHeader();
567 // ************************************************************************* //