FIREMeshWriter.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2016-2022 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "FIREMeshWriter.H"
29 #include "Time.H"
30 #include "Map.H"
31 #include "OFstream.H"
32 #include "processorPolyPatch.H"
33 
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35 
39 
40 
41 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
42 
43 namespace
44 {
45 
46 // Output newline in ascii mode, no-op in binary mode
47 inline void newline(Foam::OSstream& os)
48 {
49  if (os.format() == Foam::IOstreamOption::ASCII)
50  {
51  os << Foam::endl;
52  }
53 }
54 
55 } // End anonymous namespace
56 
57 
58 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
59 
60 
61 bool Foam::fileFormats::FIREMeshWriter::writeGeometry(OSstream& os) const
62 {
63  const faceList& faces = mesh_.faces();
64  const pointField& points = mesh_.points();
65  const cellList& cells = mesh_.cells();
66 
67  // Points
68  // ~~~~~~
69 
70  // Set the precision of the points data to 10
71  os.precision(10);
72 
73  Info<< "points: " << points.size() << endl;
74  putFireLabel(os, points.size());
75  newline(os);
76 
77  forAll(points, ptI)
78  {
79  // scaling is normally 1 (ie, none)
81  }
82  newline(os); // readability
83 
84 
85  // Faces
86  // ~~~~~
87  // OPENFOAM - faces normals are outward-facing.
88  // FIRE - faces normals are inward-facing.
89 
90  Info<< "faces: " << faces.size() << endl;
91  putFireLabel(os, faces.size());
92  newline(os);
93 
94  forAll(faces, faceI)
95  {
96  // flip face
97  putFireLabels(os, faces[faceI].reverseFace());
98  }
99  newline(os); // readability
100 
101 
102  // Cells
103  // ~~~~~
104 
105  Info<< "cells: " << cells.size() << endl;
106  putFireLabel(os, cells.size());
107  newline(os);
108 
110  {
112  }
113  newline(os); // readability
114 
115  return os.good();
116 }
117 
118 
119 bool Foam::fileFormats::FIREMeshWriter::writeSelections(OSstream& os) const
120 {
121  label nZones = 0;
122  label nPatches = 0;
123 
124  // remap name between patches and cell-zones conflicts!
125 
126  Map<word> patchNames;
127  Map<word> zoneNames;
128 
129  wordHashSet usedPatchNames;
130  wordHashSet usedZoneNames;
131 
132  // boundaries, skipping empty and processor patches
133  forAll(mesh_.boundaryMesh(), patchI)
134  {
135  const polyPatch& patch = mesh_.boundaryMesh()[patchI];
136  if (patch.size() && !isA<processorPolyPatch>(patch))
137  {
138  ++nPatches;
139 
140  const word oldName = patch.name();
141  word newName;
142  if (prefixBoundary)
143  {
144  newName = "BND_" + oldName;
145 
146  if (usedPatchNames.found(newName))
147  {
148  newName = "BND_patch" + ::Foam::name(patchI);
149  }
150  }
151  else
152  {
153  newName = oldName;
154 
155  if (usedPatchNames.found(newName))
156  {
157  newName = "patch" + ::Foam::name(patchI);
158  }
159  }
160 
161  usedPatchNames.set(newName);
162  patchNames.set(patchI, newName);
163  }
164  }
165 
166 
167  // cellzones, skipping empty zones
168  forAll(mesh_.cellZones(), zoneI)
169  {
170  const cellZone& cZone = mesh_.cellZones()[zoneI];
171  if (cZone.size())
172  {
173  ++nZones;
174 
175  const word oldName = cZone.name();
176  word newName = oldName;
177 
178  if (usedPatchNames.found(newName) || usedZoneNames.found(newName))
179  {
180  newName = "CEL_zone" + ::Foam::name(zoneI);
181  }
182 
183  usedZoneNames.set(newName);
184  zoneNames.set(zoneI, newName);
185  }
186  }
187 
188 
189  //
190  // actually write things
191  //
192 
193  putFireLabel(os, (nZones + nPatches));
194  newline(os);
195 
196  // do cell zones
197  forAll(mesh_.cellZones(), zoneI)
198  {
199  const cellZone& cZone = mesh_.cellZones()[zoneI];
200 
201  if (cZone.size())
202  {
203  Info<< "cellZone " << zoneI
204  << " (size: " << cZone.size()
205  << ") name: " << zoneNames[zoneI] << nl;
206 
207  putFireString(os, zoneNames[zoneI]);
208  putFireLabel(os, static_cast<int>(FIRECore::cellSelection));
209  newline(os);
210 
211  putFireLabels(os, cZone);
212  newline(os); // readability
213  }
214  }
215 
216  // do boundaries, skipping empty and processor patches
217  forAll(mesh_.boundaryMesh(), patchI)
218  {
219  const polyPatch& patch = mesh_.boundaryMesh()[patchI];
220  if (patch.size() && !isA<processorPolyPatch>(patch))
221  {
222  Info<< "patch " << patchI
223  << " (start: " << patch.start() << " size: " << patch.size()
224  << ") name: " << patchNames[patchI]
225  << endl;
226 
227  putFireString(os, patchNames[patchI]);
228  putFireLabel(os, static_cast<int>(FIRECore::faceSelection));
229  newline(os);
230 
231  putFireLabels(os, patch.size(), patch.start());
232  newline(os); // readability
233  }
234 
235  newline(os); // readability
236  }
237 
238  return os.good();
239 }
240 
241 
242 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
243 
244 Foam::fileFormats::FIREMeshWriter::FIREMeshWriter
245 (
246  const polyMesh& mesh,
247  const scalar scaleFactor
248 )
249 :
250  meshWriter(mesh, scaleFactor)
251 {}
252 
253 
254 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
255 
256 bool Foam::fileFormats::FIREMeshWriter::write(const fileName& meshName) const
257 {
258  IOstreamOption streamOpt;
259  if (binary)
260  {
261  streamOpt.format(IOstreamOption::BINARY);
262  }
263  if (compress)
264  {
266  }
267 
268  fileName baseName(meshName);
269  if (baseName.empty())
270  {
271  baseName = meshWriter::defaultMeshName;
272 
273  const Time& t = mesh_.time();
274 
275  if
276  (
277  t.timeName() != "0"
278  && t.timeName() != t.constant()
279  )
280  {
281  baseName += "_" + t.timeName();
282  }
283  }
284  else
285  {
286  const word ext(baseName.ext());
287 
289  {
291 
292  if (fireFileType == FIRECore::fileExt3d::POLY_ASCII)
293  {
294  streamOpt = IOstreamOption
295  (
298  );
299  }
300  else if (fireFileType == FIRECore::fileExt3d::POLY_BINARY)
301  {
302  streamOpt = IOstreamOption
303  (
306  );
307  }
308  else if (fireFileType == FIRECore::fileExt3d::POLY_ASCII_Z)
309  {
310  streamOpt = IOstreamOption
311  (
314  );
315  }
316  else if (fireFileType == FIRECore::fileExt3d::POLY_BINARY_Z)
317  {
318  streamOpt = IOstreamOption
319  (
322  );
323  }
324  }
325 
326  baseName.remove_ext();
327  }
328 
329 
330  // A slight hack. Cannot generate compressed files with the desired ending
331  // So create and rename later
332  const fileName filename = FIRECore::fireFileName
333  (
334  baseName,
335  (
336  streamOpt.format() == IOstreamOption::BINARY
339  )
340  );
341 
342  autoPtr<OFstream> osPtr(new OFstream(filename, streamOpt));
343 
344  if (osPtr->good())
345  {
346  Info<< "Writing output to ";
347  if (streamOpt.compression() == IOstreamOption::COMPRESSED)
348  {
349  // output .fpmaz instead of .fpma
350  Info<< '"' << osPtr().name().c_str() << "z\"" << endl;
351  }
352  else
353  {
354  Info<< osPtr().name() << endl;
355  }
356 
357  writeGeometry(osPtr());
358  writeSelections(osPtr());
359 
360  osPtr.clear(); // implicitly close the file
361 
362  if (streamOpt.compression() == IOstreamOption::COMPRESSED)
363  {
364  // rename .fpma.gz -> .fpmaz
365  // The '.gz' is automatically added by OFstream in compression mode
366  Foam::mv(filename + ".gz", filename + "z");
367  }
368  }
369  else
370  {
371  Info<<"could not open file for writing " << filename << endl;
372  return false;
373  }
374 
375  return true;
376 }
377 
378 
379 // ************************************************************************* //
label nPatches
Definition: readKivaGrid.H:396
fileExt3d
Enumeration defining the file extensions for 3D types.
Definition: FIRECore.H:87
Write OpenFOAM meshes and/or results to another CFD format.
Definition: meshWriter.H:78
Generic output stream using a standard (STL) stream.
Definition: OSstream.H:50
static string defaultMeshName
Specify a default mesh name.
Definition: meshWriter.H:129
bool mv(const fileName &src, const fileName &dst, const bool followLink=false)
Rename src to dst.
Definition: POSIX.C:1324
A class for handling file names.
Definition: fileName.H:72
writer writeGeometry()
List< cell > cellList
List of cell.
Definition: cellListFwd.H:39
virtual bool write(const fileName &meshName=fileName::null) const
Write volume mesh.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
"ascii" (normal default)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static bool prefixBoundary
Prefix patches with &#39;BND_&#39; before writing (default true)
const cellList & cells() const
A simple container for options an IOstream can normally have.
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1078
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
List< face > faceList
List of faces.
Definition: faceListFwd.H:39
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
const cellShapeList & cells
const pointField & points
wordList patchNames(nPatches)
HashSet< word, Hash< word > > wordHashSet
A HashSet of words, uses string hasher.
Definition: HashSet.H:73
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1103
scalar scaleFactor_
Scaling factor for points (eg, [m] -> [mm])
Definition: meshWriter.H:105
static bool compress
Write with compression (default false)
OBJstream os(runTime.globalPath()/outputName)
compressionType compression() const noexcept
Get the stream compression.
static void putFirePoint(OSstream &, const point &)
Write a point x/y/z (ascii or binary)
Definition: FIRECore.C:308
label cellId
const std::string patch
OpenFOAM patch number as a std::string.
messageStream Info
Information stream (stdout output on master, null elsewhere)
static const Enum< fileExt3d > file3dExtensions
Definition: FIRECore.H:111
static void putFireLabels(OSstream &, const labelUList &)
Write multiple integers (ascii or binary)
Definition: FIRECore.C:224
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
static bool binary
Write binary (default ascii)
static void putFireLabel(OSstream &, const label)
Write an integer (ascii or binary)
Definition: FIRECore.C:199
bool found
streamFormat format() const noexcept
Get the current stream format.
const polyMesh & mesh_
Mesh reference.
Definition: meshWriter.H:100
static fileName fireFileName(const fileName &baseName, const enum fileExt3d)
Resolve base file-name for the given file-type.
Definition: FIRECore.C:72