Loading...
Searching...
No Matches
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-2022 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
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"
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);
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;
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);
339 patchNames_.setSize(nPatches);
340}
341
342
344{
345 // Create patches
346 polyPatchList 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.set
359 (
360 patchI,
361 new polyPatch
362 (
363 patchNames_[patchI],
364 patchSizes_[patchI],
365 meshFaceI,
366 patchI,
367 mesh.boundaryMesh(),
369 )
370 );
371
372 meshFaceI += patchSizes_[patchI];
373 }
374
375 mesh.addPatches(newPatches);
377
378
379// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
380
381bool Foam::fileFormats::FIREMeshReader::readGeometry(const scalar scaleFactor)
382{
384
385 const word ext(geometryFile_.ext());
386
387 bool supported = FIRECore::file3dExtensions.found(ext);
388
389 if (supported)
390 {
392 if (fireFileType == FIRECore::POLY_ASCII)
393 {
395 }
396 else if (fireFileType == FIRECore::POLY_BINARY)
397 {
399 }
400 else
401 {
402 // compressed or something
403 supported = false;
404 }
405 }
406
407 if (!supported)
408 {
410 << "File-type '" << ext
411 << "' is not supported for reading as a FIRE mesh." << nl
412 << "If it is a compressed file, use gunzip first."
413 << abort(FatalError);
414 }
415
416 IFstream is(geometryFile_, fmt);
417
418 readPoints(is, scaleFactor);
419 readFaces(is);
420 readCells(is);
422
423 return true;
424}
425
427(
428 const objectRegistry& registry
429)
430{
431 readGeometry(scaleFactor_);
432 reorganize();
433
434 Info<< "Creating a polyMesh" << endl;
435
437 (
439 (
441 "constant",
442 registry,
445 ),
446 std::move(points_),
447 std::move(meshFaces_),
448 std::move(owner_),
449 std::move(neigh_)
450 );
452
453 // adding patches also checks the mesh
454 addPatches(mesh);
455
456 cellTable_.addCellZones(mesh, cellTableId_);
457
458 // addFaceZones(mesh);
459
460 return meshPtr;
461}
462
463// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
464
466(
467 const fileName& name,
468 const scalar scaleFactor
469)
470:
471 meshReader(name, scaleFactor),
472 owner_(),
473 neigh_(),
474 faceZoneId_(),
475 faceNames_()
476{}
477
478
479// ************************************************************************* //
Various functions to operate on Lists.
label n
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
void append(const T &val)
Copy append an element to the end of this list.
Input from file stream as an ISstream, normally using std::ifstream for the actual input.
Definition IFstream.H:55
@ NO_READ
Nothing to be read.
@ AUTO_WRITE
Automatically write from objectRegistry::writeObject().
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
streamFormat
Data format (ascii | binary | coherent).
@ ASCII
"ascii" (normal default)
Generic input stream using a standard (STL) stream.
Definition ISstream.H:54
virtual const fileName & name() const override
The name of the input serial stream. (eg, the name of the Fstream file name).
Definition ISstream.H:147
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie,...
Definition PtrList.H:171
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
static autoPtr< T > New(Args &&... args)
Construct autoPtr with forwarding arguments.
Definition autoPtr.H:178
A face is a list of labels corresponding to mesh vertices.
Definition face.H:71
static const Enum< fileExt3d > file3dExtensions
Definition FIRECore.H:111
static std::string getFireString(ISstream &)
Extract a string (ascii or binary).
Definition FIRECore.C:133
fileExt3d
Enumeration defining the file extensions for 3D types.
Definition FIRECore.H:88
static label readPoints(ISstream &, pointField &)
Read points.
Definition FIRECore.C:41
static label getFireLabel(ISstream &)
Get an integer (ascii or binary).
Definition FIRECore.C:81
void readFaces(ISstream &)
Read points from file.
void readCells(ISstream &)
Read cell connectivities from file.
virtual autoPtr< polyMesh > mesh(const objectRegistry &)
Create and return polyMesh.
void readSelections(ISstream &)
Read cell/face selections from file.
void addPatches(polyMesh &) const
FIREMeshReader(const FIREMeshReader &)=delete
No copy construct.
virtual bool readGeometry(const scalar scaleFactor=1.0)
Read the mesh from the file(s).
void readPoints(ISstream &, const scalar scaleFactor=1.0)
Read points from file.
A class for handling file names.
Definition fileName.H:75
This class supports creating polyMeshes with baffles.
Definition meshReader.H:65
scalar scaleFactor_
Geometry scaling.
Definition meshReader.H:266
faceList meshFaces_
Global face list for polyMesh.
Definition meshReader.H:314
wordList patchNames_
Boundary patch names.
Definition meshReader.H:293
label nInternalFaces_
Number of internal faces for polyMesh.
Definition meshReader.H:309
cellTable cellTable_
Cell table persistent data saved as a dictionary.
Definition meshReader.H:334
labelList cellTableId_
Cell table id for each cell.
Definition meshReader.H:329
pointField points_
Points supporting the mesh.
Definition meshReader.H:271
labelList patchSizes_
Definition meshReader.H:304
labelList patchStarts_
Polyhedral mesh boundary patch start indices and dimensions.
Definition meshReader.H:303
fileName geometryFile_
Referenced filename.
Definition meshReader.H:261
Registry of regIOobjects.
Mesh consisting of general polyhedral cells.
Definition polyMesh.H:79
static word defaultRegion
Return the default region name.
Definition polyMesh.H:406
A patch is a list of labels that address the faces in the global face list.
Definition polyPatch.H:73
A class for handling words, derived from Foam::string.
Definition word.H:66
static word validate(const std::string &s, const bool prefix=false)
Construct validated word (no invalid characters).
Definition word.C:39
static const word null
An empty word.
Definition word.H:84
dynamicFvMesh & mesh
Foam::autoPtr< Foam::dynamicFvMesh > meshPtr
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
auto & name
label cellId
label faceId(-1)
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of 'true' entries.
Definition BitOps.H:73
dimensionedScalar pos(const dimensionedScalar &ds)
PtrList< polyPatch > polyPatchList
Store lists of polyPatch as a PtrList.
Definition polyPatch.H:61
List< label > labelList
A List of labels.
Definition List.H:62
messageStream Info
Information stream (stdout output on master, null elsewhere).
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
Inplace reorder the elements of a list.
errorManip< error > abort(error &err)
Definition errorManip.H:139
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition exprTraits.C:127
messageStream Warning
Warning stream (stdout output on master, null elsewhere), with additional 'FOAM Warning' header text.
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
labelList f(nPoints)
label nPatches
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299