FLMAsurfaceFormat.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 "FLMAsurfaceFormat.H"
29 
30 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
31 
32 namespace
33 {
34 
35 // Output newline in ascii mode, no-op in binary mode
36 inline void newline(Foam::OSstream& os)
37 {
38  if (os.format() == Foam::IOstreamOption::ASCII)
39  {
40  os << '\n';
41  }
42 }
43 
44 
45 template<class Face>
46 inline int countFaces(const Face& f)
47 {
48  int n = (f.size() - 2); // number triangles can be determined directly
49  return n == 2 ? 1 : n; // quads don't need triangulation
50 }
51 
52 } // End anonymous namespace
53 
54 
55 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
56 
57 template<class Face>
59 (
60  OSstream& os,
61  const Face& f
62 )
63 {
64  if (os.format() == IOstreamOption::BINARY)
65  {
66  if (f.size() == 3 || f.size() == 4)
67  {
68  putFireLabel(os, f.size());
69  for (const label verti : f)
70  {
71  putFireLabel(os, verti);
72  }
73  }
74  else
75  {
76  // simple triangulation about f[0].
77  // better triangulation should have been done before
78  for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
79  {
80  const label fp2 = f.fcIndex(fp1);
81 
82  putFireLabel(os, 3);
83  putFireLabel(os, f[0]);
84  putFireLabel(os, f[fp1]);
85  putFireLabel(os, f[fp2]);
86  }
87  }
88  }
89  else
90  {
91  // ASCII
92  if (f.size() == 3 || f.size() == 4)
93  {
94  os << ' ' << f.size();
95  for (const label verti : f)
96  {
97  os << ' ' << verti;
98  }
99  os << nl;
100  }
101  else
102  {
103  for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
104  {
105  const label fp2 = f.fcIndex(fp1);
106  os << ' ' << 3 << ' '
107  << f[0] << ' ' << f[fp1] << ' ' << f[fp2]
108  << nl;
109  }
110  }
111  }
112 }
113 
114 
115 template<class Face>
117 (
118  OSstream& os,
119  const Face& f
120 )
121 {
122  if (os.format() == IOstreamOption::BINARY)
123  {
124  if (f.size() == 4)
125  {
126  putFireLabel(os, fireQuad);
127  }
128  else
129  {
130  const label n = countFaces(f);
131  for (label i=0; i < n; ++i)
132  {
133  putFireLabel(os, fireTri);
134  }
135  }
136  }
137  else
138  {
139  // ASCII
140  if (f.size() == 4)
141  {
142  os << ' ' << fireQuad;
143  }
144  else
145  {
146  const label n = countFaces(f);
147  for (label i=0; i < n; ++i)
148  {
149  os << ' ' << fireTri;
150  }
151  }
152  }
153 }
154 
155 
156 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
157 
158 template<class Face>
160 (
161  OSstream& os,
162  const MeshedSurfaceProxy<Face>& surf
163 )
164 {
165  if (!os.good())
166  {
168  << "bad output state "
169  << exit(FatalError);
170  }
171 
172  const UList<point>& pointLst = surf.points();
173  const UList<Face>& faceLst = surf.surfFaces();
174  const UList<label>& faceMap = surf.faceMap();
175 
176  // for no zones, suppress the group name
177  const surfZoneList zones =
178  (
179  surf.surfZones().empty()
180  ? surfaceFormatsCore::oneZone(faceLst, word::null)
181  : surf.surfZones()
182  );
183 
184  const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
185 
186 
187  // determine the number of faces by counting the
188  // tri/quads/triangulated) faces in each zone
189  label nFaces = 0;
190  labelList zoneCount(zones.size());
191 
192  {
193  label faceIndex = 0;
194  forAll(zones, zonei)
195  {
196  const surfZone& zone = zones[zonei];
197 
198  label selCount = 0;
199  for (label nLocal = zone.size(); nLocal--; ++faceIndex)
200  {
201  const label facei =
202  (useFaceMap ? faceMap[faceIndex] : faceIndex);
203 
204  const Face& f = faceLst[facei];
205 
206  selCount += countFaces(f);
207  }
208 
209  zoneCount[zonei] = selCount;
210  nFaces += selCount;
211  }
212  }
213 
214 
215  // Points
216  // ~~~~~~
217 
218  // Set the precision of the points data to 10
219  os.precision(10);
220 
221  Info<< nl << "points: " << pointLst.size() << endl;
222  putFireLabel(os, pointLst.size());
223  newline(os);
224 
225  for (const point& pt : pointLst)
226  {
227  // scaling is normally 1
228  putFirePoint(os, pt);
229  }
230  newline(os); // readability
231 
232  // Faces indices
233  {
234  Info<< "faces: " << nFaces << endl;
235  putFireLabel(os, nFaces);
236  newline(os);
237 
238  label faceIndex = 0;
239  for (const surfZone& zone : zones)
240  {
241  for (label nLocal = zone.size(); nLocal--; ++faceIndex)
242  {
243  const label facei =
244  (useFaceMap ? faceMap[faceIndex] : faceIndex);
245 
246  const Face& f = faceLst[facei];
247 
248  writeShell(os, f);
249  }
250  }
251  newline(os);
252  newline(os); // readability
253  }
254 
255 
256  // Face types
257  {
258  putFireLabel(os, nFaces);
259  newline(os);
260 
261  label faceIndex = 0;
262  for (const surfZone& zone : zones)
263  {
264  for (label nLocal = zone.size(); nLocal--; ++faceIndex)
265  {
266  const label facei =
267  (useFaceMap ? faceMap[faceIndex] : faceIndex);
268 
269  const Face& f = faceLst[facei];
270 
271  writeType(os, f);
272  }
273  }
274  newline(os);
275  newline(os); // readability
276  }
277 
278  // Selections (cell)
279  {
280  putFireLabel(os, zones.size());
281  newline(os);
282 
283  label faceIndex = 0;
284  forAll(zones, zonei)
285  {
286  const surfZone& zone = zones[zonei];
287  const label selCount = zoneCount[zonei];
288 
289  putFireString(os, zone.name());
290  putFireLabel(os, static_cast<int>(FIRECore::cellSelection));
291  newline(os);
292 
293  putFireLabels(os, selCount, faceIndex);
294  faceIndex += selCount;
295 
296  newline(os); // readability
297  }
298  }
299 }
300 
301 
302 template<class Face>
304 (
305  IOstreamOption::compressionType comp,
306  const fileName& filename,
307  const MeshedSurfaceProxy<Face>& surf
308 )
309 {
310  // ASCII only, allow output compression
311  autoPtr<OFstream> osPtr
312  (
313  new OFstream(filename, IOstreamOption(IOstreamOption::ASCII, comp))
314  );
315 
316  if (osPtr->good())
317  {
318  FLMAsurfaceFormat<Face>::write(*osPtr, surf);
319 
320  if (comp == IOstreamOption::COMPRESSED)
321  {
322  // Close the file
323  osPtr.clear();
324 
325  // Rename .flmaz.gz -> .flmaz
326  // The '.gz' is automatically added by OFstream in compression mode
327  Foam::mv(filename + ".gz", filename);
328  }
329  }
330  else
331  {
333  << "Cannot write file " << filename << nl
334  << exit(FatalError);
335  }
336 }
337 
338 
339 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
340 
341 template<class Face>
343 (
344  const fileName& filename,
345  const MeshedSurfaceProxy<Face>& surf,
347  const dictionary&
348 )
349 {
351  (
352  IOstreamOption::UNCOMPRESSED,
353  filename,
354  surf
355  );
356 }
357 
358 
359 template<class Face>
361 (
362  const fileName& filename,
363  const MeshedSurfaceProxy<Face>& surf,
365  const dictionary&
366 )
367 {
369  (
370  IOstreamOption::COMPRESSED,
371  filename,
372  surf
373  );
374 }
375 
376 
377 // ************************************************************************* //
Generic output stream using a standard (STL) stream.
Definition: OSstream.H:50
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
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
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
A surface zone on a MeshedSurface.
Definition: surfZone.H:52
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
A simple container for options an IOstream can normally have.
const pointField & points() const noexcept
Return const access to the points.
const labelUList & faceMap() const noexcept
Const access to the faceMap, zero-sized when unused.
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
void write(vtk::formatter &fmt, const Type &val, const label n=1)
Component-wise write of a value (N times)
bool useFaceMap() const noexcept
Can/should use faceMap?
Base class for mesh zones.
Definition: zone.H:59
const UList< surfZone > & surfZones() const noexcept
Const access to the surface zones.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:105
OBJstream os(runTime.globalPath()/outputName)
A proxy for writing MeshedSurface, UnsortedMeshedSurface and surfMesh to various file formats...
Definition: MeshedSurface.H:75
labelList f(nPoints)
static void write(const fileName &filename, const MeshedSurfaceProxy< Face > &surf, IOstreamOption=IOstreamOption(), const dictionary &=dictionary::null)
Write surface mesh components by proxy.
vector point
Point is a vector.
Definition: point.H:37
messageStream Info
Information stream (stdout output on master, null elsewhere)
label n
Provide a means of writing AVL/FIRE FLMA format.
const UList< Face > & surfFaces() const noexcept
Return const access to the faces.
static void write(OSstream &os, const MeshedSurfaceProxy< Face > &surf)
Write surface mesh components by proxy.