FIREMeshReader.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-2021 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 "FIREMeshReader.H"
29 #include "wallPolyPatch.H"
30 #include "ListOps.H"
31 #include "IFstream.H"
32 
33 
34 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
35 
37 (
38  ISstream& is,
39  const scalar scaleFactor
40 )
41 {
42  const label n = FIRECore::readPoints(is, points_);
43  // the above has FatalError if there are no points
44 
45  Info<< "Number of points = " << n << endl;
46  if (scaleFactor > 1.0 + SMALL || scaleFactor < 1.0 - SMALL)
47  {
48  points_ *= scaleFactor;
49  }
50 }
51 
52 
54 {
55  const label nFaces = getFireLabel(is);
56  Info<< "Number of faces = " << nFaces << endl;
57  meshFaces_.setSize(nFaces);
58 
59  if (nFaces > 0)
60  {
61  forAll(meshFaces_, faceI)
62  {
63  const label size = getFireLabel(is);
64 
65  face& f = meshFaces_[faceI];
66  f.setSize(size);
67  forAll(f, fp)
68  {
69  f[fp] = getFireLabel(is);
70  }
71 
72  // flip in-place
73  f.flip();
74  }
75  }
76  else
77  {
79  << "no faces in file " << is.name()
80  << abort(FatalError);
81  }
82 }
83 
84 
86 {
87  const label nCells = getFireLabel(is);
88  Info<< "Number of cells = " << nCells << endl;
89 
90  owner_.setSize(meshFaces_.size());
91  neigh_.setSize(meshFaces_.size());
92 
93  owner_ = -1;
94  neigh_ = -1;
95 
96  if (nCells > 0)
97  {
98  for (label cellI = 0; cellI < nCells; ++cellI)
99  {
100  const label nface = getFireLabel(is);
101 
102  for (label i = 0; i < nface; ++i)
103  {
104  const label faceI = getFireLabel(is);
105 
106  if (owner_[faceI] == -1)
107  {
108  owner_[faceI] = cellI;
109  }
110  else if (neigh_[faceI] == -1)
111  {
112  neigh_[faceI] = cellI;
113  }
114  else
115  {
116  Warning
117  << "bad cell connectivity for face " << faceI
118  << " on cell " << cellI
119  << endl;
120  }
121  }
122  }
123  }
124  else
125  {
127  << "no cells in file " << is.name()
128  << abort(FatalError);
129  }
130 
131  cellTableId_.setSize(nCells);
132  cellTableId_ = -1;
133 }
134 
135 
137 {
138  const label nSelect = getFireLabel(is);
139  Info<< "Number of select = " << nSelect << endl;
140 
141  label nCellSelections = 0;
142  label nFaceSelections = 0;
143 
144  faceZoneId_.setSize(meshFaces_.size());
145  faceZoneId_ = -1;
146 
147  DynamicList<word> faceNames(32);
148 
149  for (label selI = 0; selI < nSelect; ++selI)
150  {
151  std::string name = getFireString(is);
152  const label selType = getFireLabel(is);
153  const label count = getFireLabel(is);
154 
155  if (selType == FIRECore::cellSelection)
156  {
157  // index starting at 1
158  const label selId = ++nCellSelections;
159 
160  cellTable_.setName(selId, word::validate(name, true));
161  cellTable_.setMaterial(selId, "fluid");
162 
163  for (label i = 0; i < count; ++i)
164  {
165  const label cellId = getFireLabel(is);
166 
167  cellTableId_[cellId] = selId;
168  }
169  }
170  else if (selType == FIRECore::faceSelection)
171  {
172  // index starting at 0
173  const label selId = nFaceSelections++;
174 
175  faceNames.append(word::validate(name, true));
176 
177  for (label i = 0; i < count; ++i)
178  {
179  const label faceId = getFireLabel(is);
180 
181  faceZoneId_[faceId] = selId;
182  }
183  }
184  else
185  {
186  // discard other selection types (eg, nodes)
187  for (label i = 0; i < count; ++i)
188  {
189  getFireLabel(is);
190  }
191  }
192  }
193 
194  Info<< nFaceSelections << " face selections" << endl;
195  Info<< nCellSelections << " cell selections" << endl;
196 
197  // add extra for missed boundary faces
198  faceNames.append("__MISSED_FACES__");
199  faceNames_.transfer(faceNames);
200 }
201 
202 
204 {
205  nInternalFaces_ = 0;
206 
207  // pass 1:
208  // count internal faces and also swap owner <-> neigh as required
209  forAll(meshFaces_, faceI)
210  {
211  if (neigh_[faceI] != -1)
212  {
213  ++nInternalFaces_;
214 
215  if (owner_[faceI] > neigh_[faceI])
216  {
217  std::swap(owner_[faceI], neigh_[faceI]);
218  }
219  }
220  }
221 
222  label posInternal = 0;
223  label posExternal = nInternalFaces_;
224 
225  labelList oldToNew(meshFaces_.size(), -1);
226 
227  // pass 2:
228  // mapping to ensure proper division of internal / external
229  forAll(meshFaces_, faceI)
230  {
231  if (neigh_[faceI] == -1)
232  {
233  oldToNew[faceI] = posExternal++;
234  }
235  else
236  {
237  oldToNew[faceI] = posInternal++;
238  }
239  }
240 
241  inplaceReorder(oldToNew, meshFaces_);
242  inplaceReorder(oldToNew, owner_);
243  inplaceReorder(oldToNew, neigh_);
244  inplaceReorder(oldToNew, faceZoneId_);
245 
246  // Determine the patch sizes
247  // - faceNames_ already has extra place for missed faces
248  const label zoneMissed = faceNames_.size() - 1;
249  patchSizes_.setSize(faceNames_.size());
250  patchSizes_ = 0;
251 
252  patchStarts_.setSize(patchSizes_.size());
253  patchStarts_ = 0;
254 
255  for (label faceI = nInternalFaces_; faceI < meshFaces_.size(); ++faceI)
256  {
257  label zoneI = faceZoneId_[faceI];
258  if (zoneI == -1)
259  {
260  ++patchSizes_[zoneMissed];
261  }
262  else
263  {
264  ++patchSizes_[zoneI];
265  }
266  }
267 
268  if (patchSizes_[zoneMissed])
269  {
270  Info<<"collecting " << patchSizes_[zoneMissed]
271  << " missed boundary faces to final patch" << endl;
272  }
273 
274  oldToNew = -1;
275 
276  // calculate the patch starts
277  {
278  label pos = nInternalFaces_;
279 
280  forAll(patchStarts_, patchI)
281  {
282  patchStarts_[patchI] = pos;
283  pos += patchSizes_[patchI];
284  }
285 
286  forAll(patchSizes_, patchI)
287  {
288  patchSizes_[patchI] = 0;
289  }
290  }
291 
292  // reordering
293  for (label faceI = nInternalFaces_; faceI < meshFaces_.size(); ++faceI)
294  {
295  label patchI = faceZoneId_[faceI];
296  if (patchI == -1)
297  {
298  oldToNew[faceI] =
299  patchStarts_[zoneMissed] + patchSizes_[zoneMissed];
300  ++patchSizes_[zoneMissed];
301  }
302  else
303  {
304  oldToNew[faceI] = patchStarts_[patchI] + patchSizes_[patchI];
305  ++patchSizes_[patchI];
306  }
307  }
308 
309  // discard old information
310  faceZoneId_.clear();
311 
312  inplaceReorder(oldToNew, meshFaces_);
313  inplaceReorder(oldToNew, owner_);
314  inplaceReorder(oldToNew, neigh_);
315 
316  //--- neigh_.setSize(nInternalFaces_);
317 
318  // finally reduce to the number of patches actually used
319  patchNames_.setSize(patchSizes_.size());
320  oldToNew = -1;
321 
322  label nPatches = 0;
323  forAll(patchSizes_, patchI)
324  {
325  if (patchSizes_[patchI])
326  {
327  patchNames_[nPatches] = faceNames_[patchI];
328 
329  oldToNew[patchI] = nPatches;
330  ++nPatches;
331  }
332  }
333 
334  inplaceReorder(oldToNew, patchStarts_);
335  inplaceReorder(oldToNew, patchSizes_);
336 
337  patchStarts_.setSize(nPatches);
338  patchSizes_.setSize(nPatches);
339  patchNames_.setSize(nPatches);
340 }
341 
342 
344 {
345  // create patches
346  List<polyPatch*> newPatches(patchSizes_.size());
347 
348  label meshFaceI = nInternalFaces_;
349 
350  forAll(patchStarts_, patchI)
351  {
352  Info<< "patch " << patchI
353  << " (start: " << meshFaceI << " size: " << patchSizes_[patchI]
354  << ") name: " << patchNames_[patchI]
355  << endl;
356 
357  // don't know anything better - just make it a wall
358  newPatches[patchI] = new polyPatch
359  (
360  patchNames_[patchI],
361  patchSizes_[patchI],
362  meshFaceI,
363  patchI,
364  mesh.boundaryMesh(),
365  word::null
366  );
367 
368  meshFaceI += patchSizes_[patchI];
369  }
370 
371  mesh.addPatches(newPatches);
372 }
373 
374 
375 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
376 
378 {
380 
381  const word ext(geometryFile_.ext());
382 
383  bool supported = FIRECore::file3dExtensions.found(ext);
384 
385  if (supported)
386  {
388  if (fireFileType == FIRECore::POLY_ASCII)
389  {
390  fmt = IOstream::ASCII;
391  }
392  else if (fireFileType == FIRECore::POLY_BINARY)
393  {
394  fmt = IOstream::BINARY;
395  }
396  else
397  {
398  // compressed or something
399  supported = false;
400  }
401  }
402 
403  if (!supported)
404  {
406  << "File-type '" << ext
407  << "' is not supported for reading as a FIRE mesh." << nl
408  << "If it is a compressed file, use gunzip first."
409  << abort(FatalError);
410  }
411 
412  IFstream is(geometryFile_, fmt);
413 
414  readPoints(is, scaleFactor);
415  readFaces(is);
416  readCells(is);
417  readSelections(is);
418 
419  return true;
420 }
421 
423 (
424  const objectRegistry& registry
425 )
426 {
427  readGeometry(scaleFactor_);
428  reorganize();
429 
430  Info<< "Creating a polyMesh" << endl;
431 
433  (
434  IOobject
435  (
437  "constant",
438  registry,
441  ),
442  std::move(points_),
443  std::move(meshFaces_),
444  std::move(owner_),
445  std::move(neigh_)
446  );
447  polyMesh& mesh = *meshPtr;
448 
449  // adding patches also checks the mesh
450  addPatches(mesh);
451 
452  cellTable_.addCellZones(mesh, cellTableId_);
453 
454  // addFaceZones(mesh);
455 
456  return meshPtr;
457 }
458 
459 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
460 
462 (
463  const fileName& name,
464  const scalar scaleFactor
465 )
466 :
467  meshReader(name, scaleFactor),
468  owner_(),
469  neigh_(),
470  faceZoneId_(),
471  faceNames_()
472 {}
473 
474 
475 // ************************************************************************* //
Foam::fileFormats::FIREMeshReader::readFaces
void readFaces(ISstream &)
Read points from file.
Definition: FIREMeshReader.C:53
Foam::fileFormats::FIREMeshReader::reorganize
void reorganize()
Definition: FIREMeshReader.C:203
Foam::autoPtr::New
static autoPtr< T > New(Args &&... args)
Construct autoPtr of T with forwarding arguments.
Foam::fileFormats::FIREMeshReader::readGeometry
virtual bool readGeometry(const scalar scaleFactor=1.0)
Read the mesh from the file(s)
Definition: FIREMeshReader.C:377
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:169
meshPtr
Foam::autoPtr< Foam::fvMesh > meshPtr(nullptr)
Foam::IOobject::AUTO_WRITE
Definition: IOobject.H:194
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::fileName
A class for handling file names.
Definition: fileName.H:73
Foam::fileFormats::FIREMeshReader::FIREMeshReader
FIREMeshReader(const FIREMeshReader &)=delete
No copy construct.
Foam::Enum::found
bool found(const word &enumName) const
True if there is an enumeration corresponding to the given name.
Definition: EnumI.H:103
Foam::polyMesh::defaultRegion
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:318
Foam::IFstream
Input from file stream, using an ISstream.
Definition: IFstream.H:53
Foam::DynamicList< word >
Foam::fileFormats::FIRECore::POLY_BINARY
Definition: FIRECore.H:89
Foam::Warning
messageStream Warning
Foam::fileFormats::FIRECore::faceSelection
Definition: FIRECore.H:70
Foam::fileFormats::FIRECore::cellSelection
Definition: FIRECore.H:69
wallPolyPatch.H
Foam::ISstream
Generic input stream using a standard (STL) stream.
Definition: ISstream.H:55
Foam::word::validate
static word validate(const std::string &s, const bool prefix=false)
Construct validated word (no invalid characters).
Definition: word.C:45
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::objectRegistry
Registry of regIOobjects.
Definition: objectRegistry.H:60
n
label n
Definition: TABSMDCalcMethod2.H:31
FIREMeshReader.H
nPatches
const label nPatches
Definition: printMeshSummary.H:30
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:68
faceId
label faceId(-1)
Foam::List::setSize
void setSize(const label n)
Alias for resize()
Definition: List.H:222
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:511
IFstream.H
Foam::ISstream::name
virtual const fileName & name() const
Return the name of the stream.
Definition: ISstream.H:113
Foam::IOstreamOption::streamFormat
streamFormat
Data format (ascii | binary)
Definition: IOstreamOption.H:70
Foam::FatalError
error FatalError
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::fileFormats::FIREMeshReader::readCells
void readCells(ISstream &)
Read cell connectivities from file.
Definition: FIREMeshReader.C:85
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
cellId
label cellId
Definition: interrogateWallPatches.H:67
Foam::meshReader::meshFaces_
faceList meshFaces_
Global face list for polyMesh.
Definition: meshReader.H:242
Foam::autoPtr< Foam::polyMesh >
Foam::fileFormats::FIRECore::POLY_ASCII
Definition: FIRECore.H:88
Foam::meshReader
This class supports creating polyMeshes with baffles.
Definition: meshReader.H:68
Foam::IOstreamOption::BINARY
"binary"
Definition: IOstreamOption.H:73
Foam::IOstreamOption::ASCII
"ascii" (normal default)
Definition: IOstreamOption.H:72
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::nl
constexpr char nl
Definition: Ostream.H:404
f
labelList f(nPoints)
Foam::BitOps::count
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of 'true' entries.
Definition: BitOps.H:77
Foam::fileFormats::FIREMeshReader::addPatches
void addPatches(polyMesh &) const
Definition: FIREMeshReader.C:343
Foam::List< label >
Foam::fileFormats::FIRECore::fileExt3d
fileExt3d
Enumeration defining the file extensions for 3D types.
Definition: FIRECore.H:86
Foam::word::null
static const word null
An empty word.
Definition: word.H:80
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
Foam::inplaceReorder
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
Inplace reorder the elements of a list.
Definition: ListOpsTemplates.C:124
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:72
Foam::fileFormats::FIRECore::getFireLabel
static label getFireLabel(ISstream &)
Get an integer (ascii or binary)
Definition: FIRECore.C:88
ListOps.H
Various functions to operate on Lists.
Foam::fileFormats::FIREMeshReader::readSelections
void readSelections(ISstream &)
Read cell/face selections from file.
Definition: FIREMeshReader.C:136
Foam::IOobject::NO_READ
Definition: IOobject.H:188
Foam::fileFormats::FIRECore::file3dExtensions
static const Enum< fileExt3d > file3dExtensions
Definition: FIRECore.H:106
Foam::fileFormats::FIREMeshReader::mesh
virtual autoPtr< polyMesh > mesh(const objectRegistry &)
Create and return polyMesh.
Definition: FIREMeshReader.C:423
Foam::fileFormats::FIREMeshReader::readPoints
void readPoints(ISstream &, const scalar scaleFactor=1.0)
Read points from file.
Definition: FIREMeshReader.C:37
Foam::pos
dimensionedScalar pos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:177