ensightMesh.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) 2011-2016 OpenFOAM Foundation
9 Copyright (C) 2016-2021 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
29#include "ensightMesh.H"
30#include "ensightGeoFile.H"
31#include "polyMesh.H"
32#include "emptyPolyPatch.H"
33#include "processorPolyPatch.H"
34
35// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36
37const Foam::label Foam::ensightMesh::internalZone = -1;
38
39
40// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
41
42namespace Foam
43{
44
45// Patch names without processor patches
47{
48 #ifdef FULLDEBUG
49 // Patches are output. Check that they are synced.
50 bmesh.checkParallelSync(true);
51 #endif
52
53 wordList patchNames(bmesh.names());
55
56 return patchNames;
57}
58
59
60} // End namespace Foam
61
62
63// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
64
65void Foam::ensightMesh::clear()
66{
67 cellZoneParts_.clear();
68 faceZoneParts_.clear();
69 boundaryParts_.clear();
70}
71
72
73void Foam::ensightMesh::renumber()
74{
75 label partNo = 0;
76
77 for (const label id : cellZoneParts_.sortedToc())
78 {
79 cellZoneParts_[id].index() = partNo++;
80 }
81
82 for (const label id : boundaryParts_.sortedToc())
83 {
84 boundaryParts_[id].index() = partNo++;
85 }
86
87 for (const label id : faceZoneParts_.sortedToc())
88 {
89 faceZoneParts_[id].index() = partNo++;
90 }
91}
92
93
94// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
95
97(
98 const polyMesh& mesh
99)
100:
102{}
103
104
106(
107 const polyMesh& mesh,
108 const ensightMesh::options& opts
109)
110:
111 options_(new options(opts)),
112 mesh_(mesh),
113 needsUpdate_(true),
114 verbose_(0)
115{
116 if (!option().lazy())
117 {
118 correct();
119 }
120}
121
122
123// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
124
126{
127 return verbose_;
128}
129
130
131int Foam::ensightMesh::verbose(const int level) noexcept
132{
133 int old(verbose_);
134 verbose_ = level;
135 return old;
136}
137
138
140{
141 clear();
142
143 const wordRes& czMatcher = option().cellZoneSelection();
144 const wordRes& fzMatcher = option().faceZoneSelection();
145
146 // Possible cellZones
147 const wordList czNames =
148 (
149 (
150 option().useCellZones()
151 && (!czMatcher.empty() || option().useInternalMesh())
152 )
153 ? mesh_.cellZones().names()
154 : wordList()
155 );
156
157 const labelList czoneIds =
158 (
159 czMatcher.empty()
160 ? identity(czNames.size()) // All
161 : czMatcher.matching(czNames) // Selected names
162 );
163
164
165 // Possible faceZones
166 const wordList fzNames =
167 (
168 option().useFaceZones()
169 ? mesh_.faceZones().names()
170 : wordList()
171 );
172
173 const labelList fzoneIds =
174 (
175 fzMatcher.empty()
176 ? identity(fzNames.size()) // All
177 : fzMatcher.matching(fzNames) // Selected names
178 );
179
180
181 // Possible patchNames
182 const wordList patchNames =
183 (
184 option().useBoundaryMesh()
185 ? nonProcessorPatchNames(mesh_.boundaryMesh())
186 : wordList()
187 );
188
189 const labelList patchIds =
190 (
191 option().useBoundaryMesh()
193 (
195 option().patchSelection(),
196 option().patchExclude()
197 )
198 : labelList()
199 );
200
201
202 // Track which cells are in a zone or not
203 bitSet cellSelection;
204
205 // Faces to be excluded from export
206 bitSet excludeFace;
207
208
209 // cellZones first
210 for (const label zoneId : czoneIds)
211 {
212 const word& zoneName = czNames[zoneId];
213 const cellZone& zn = mesh_.cellZones()[zoneId];
214
215 if (returnReduce(!zn.empty(), orOp<bool>()))
216 {
217 // Ensure full mesh coverage
218 cellSelection.resize(mesh_.nCells());
219
220 cellSelection.set(zn);
221
222 ensightCells& part = cellZoneParts_(zoneId);
223
224 part.clear();
225 part.identifier() = zoneId;
226 part.rename(zoneName);
227
228 part.classify(mesh_, zn);
229
230 // Finalize
231 part.reduce();
232 if (verbose_)
233 {
234 Info<< part.info();
235 }
236 }
237 }
238
239 if (option().useInternalMesh() && czMatcher.empty())
240 {
241 // The internal mesh:
242 // Either the entire mesh (if no zones specified)
243 // or whatever is leftover as unzoned
244
245 if (cellZoneParts_.empty())
246 {
247 ensightCells& part = cellZoneParts_(internalZone);
248
249 part.clear();
250 part.identifier() = internalZone;
251 part.rename("internalMesh");
252
253 part.classify(mesh_);
254
255 // Finalize
256 part.reduce();
257 if (verbose_)
258 {
259 Info<< part.info();
260 }
261 }
262 else
263 {
264 // Unzoned cells - flip selection from zoned to unzoned
265 cellSelection.flip();
266
267 if (returnReduce(cellSelection.any(), orOp<bool>()))
268 {
269 ensightCells& part = cellZoneParts_(internalZone);
270
271 part.clear();
272 part.identifier() = internalZone;
273 part.rename("internalMesh");
274
275 part.classify(mesh_, cellSelection);
276
277 // Finalize
278 part.reduce();
279 if (verbose_)
280 {
281 Info<< part.info();
282 }
283 }
284 }
285
286 // Handled all cells
287 cellSelection.clearStorage();
288 }
289 else if (cellSelection.none())
290 {
291 // No internal, no cellZones selected - just ignore
292 cellSelection.clearStorage();
293 }
294
295
296 // Face exclusion based on cellZones
297
298 if (returnReduce(!cellSelection.empty(), orOp<bool>()))
299 {
300 // Ensure full mesh coverage
301 excludeFace.resize(mesh_.nFaces());
302
303 const labelList& owner = mesh_.faceOwner();
304
305 forAll(owner, facei)
306 {
307 const label celli = owner[facei];
308
309 if (!cellSelection.test(celli))
310 {
311 excludeFace.set(facei);
312 }
313 }
314 }
315
316
317 // Face exclusion for empty/processor types
318 // so they are ignored for face zones
319
320 if (fzoneIds.size())
321 {
322 // Ensure full mesh coverage
323 excludeFace.resize(mesh_.nFaces());
324
325 for (const polyPatch& p : mesh_.boundaryMesh())
326 {
327 const auto* procPatch = isA<processorPolyPatch>(p);
328
329 if (isA<emptyPolyPatch>(p))
330 {
331 excludeFace.set(p.range());
332 }
333 else if (procPatch && !procPatch->owner())
334 {
335 // Exclude neighbour-side, retain owner-side only
336 excludeFace.set(p.range());
337 }
338 }
339 }
340
341
342 // Patches
343 for (const label patchId : patchIds)
344 {
345 const word& patchName = patchNames[patchId];
346 const polyPatch& p = mesh_.boundaryMesh()[patchId];
347
348 if (isA<emptyPolyPatch>(p))
349 {
350 // Skip empty patch types
351 continue;
352 }
353 else if (isA<processorPolyPatch>(p))
354 {
355 // Only real (non-processor) boundaries.
356 break;
357 }
358
359 ensightFaces& part = boundaryParts_(patchId);
360
361 part.clear();
362 part.identifier() = patchId;
363 part.rename(patchName);
364
365 part.classify
366 (
367 mesh_.faces(),
368 identity(p.range()),
369 boolList(), // no flip map
370 excludeFace
371 );
372
373 // Finalize
374 part.reduce();
375 if (verbose_)
376 {
377 Info<< part.info();
378 }
379 if (!part.total())
380 {
381 boundaryParts_.erase(patchId);
382 }
383 }
384
385
386 // Face zones
387
388 for (const label zoneId : fzoneIds)
389 {
390 const word& zoneName = fzNames[zoneId];
391 const faceZone& zn = mesh_.faceZones()[zoneId];
392
393 ensightFaces& part = faceZoneParts_(zoneId);
394
395 part.clear();
396 part.identifier() = zoneId;
397 part.rename(zoneName);
398
399 if (zn.size())
400 {
401 part.classify
402 (
403 mesh_.faces(),
404 zn,
405 zn.flipMap(),
406 excludeFace
407 );
408 }
409
410 // Finalize
411 part.reduce();
412 if (verbose_)
413 {
414 Info<< part.info();
415 }
416 if (!part.total())
417 {
418 faceZoneParts_.erase(zoneId);
419 }
420 }
421
422 renumber();
423
424 needsUpdate_ = false;
425}
426
427
429(
431 bool parallel
432) const
433{
434 // The internalMesh, cellZones
435 for (const label id : cellZoneParts_.sortedToc())
436 {
437 cellZoneParts_[id].write(os, mesh_, parallel);
438 }
439
440 // Patches - sorted by index
441 for (const label id : boundaryParts_.sortedToc())
442 {
443 boundaryParts_[id].write(os, mesh_, parallel);
444 }
445
446 // Requested faceZones - sorted by index
447 for (const label id : faceZoneParts_.sortedToc())
448 {
449 faceZoneParts_[id].write(os, mesh_, parallel);
450 }
451}
452
453
454// ************************************************************************* //
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:139
bool empty() const noexcept
True if the list is empty (ie, size() is zero).
Definition: PackedListI.H:384
void resize(const label numElem, const unsigned int val=0u)
Reset addressable list size, does not shrink the allocated size.
Definition: PackedListI.H:409
void clearStorage()
Clear the list and delete storage.
Definition: PackedListI.H:520
bool empty() const noexcept
True if the UList is empty (ie, size() is zero)
Definition: UListI.H:427
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:66
void flip()
Invert all bits in the addressable region.
Definition: bitSetI.H:634
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition: bitSetI.H:590
bool none() const
True if no bits in this bitset are set.
Definition: bitSetI.H:488
bool test(const label pos) const
Test value at specified position, never auto-vivify entries.
Definition: bitSetI.H:521
bool any() const
True if any bits in this bitset are set.
Definition: bitSetI.H:469
A subset of mesh cells.
Definition: cellZone.H:65
Sorting/classification of cells (3D) into corresponding ensight element types.
Definition: ensightCells.H:58
void reduce()
Sum element counts across all processes.
Definition: ensightCells.C:138
void classify(const polyMesh &mesh)
Classify cell types and set the element lists.
Definition: ensightCells.C:243
void clear()
Set addressable sizes to zero, free up addressing memory.
Definition: ensightCells.C:122
InfoProxy< ensightCells > info() const
Return info proxy.
Definition: ensightCells.H:254
Sorting/classification of faces (2D) into corresponding ensight types.
Definition: ensightFaces.H:75
void classify(const UList< face > &faces)
Classify the face types and set the element lists.
Definition: ensightFaces.C:219
void reduce()
Sum element counts across all processes.
Definition: ensightFaces.C:164
label total() const
The global size of all element types.
Definition: ensightFaces.C:136
void clear()
Set addressable sizes to zero, free up addressing memory.
Definition: ensightFaces.C:147
InfoProxy< ensightFaces > info() const
Return info proxy.
Definition: ensightFaces.H:247
Specialized Ensight output with extra geometry file header.
Configuration options for the ensightMesh.
Definition: ensightMesh.H:240
Encapsulation of volume meshes for writing in ensight format. It manages cellZones,...
Definition: ensightMesh.H:83
void correct()
Update for new mesh.
Definition: ensightMesh.C:139
int verbose() const noexcept
Output verbosity level.
Definition: ensightMesh.C:125
const ensightMesh::options & option() const
Reference to the writer/mesh options.
Definition: ensightMeshI.H:30
static const label internalZone
The zone-id for internal mesh or unzoned cells.
Definition: ensightMesh.H:90
void rename(const string &value)
Change the part name or description.
Definition: ensightPart.H:166
label identifier() const noexcept
OpenFOAM identifier (patch, zone, etc), -1 when not in use.
Definition: ensightPart.H:136
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:67
const boolList & flipMap() const noexcept
Return face flip map.
Definition: faceZone.H:272
virtual bool write()
Write the output fields.
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
label nNonProcessor() const
The number of patches before the first processor patch.
wordList names() const
Return a list of patch names.
bool checkParallelSync(const bool report=false) const
Check whether all procs have all patches and in same order.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:81
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:75
A List of wordRe with additional matching capabilities.
Definition: wordRes.H:54
labelList matching(const UList< StringType > &input, const bool invert=false) const
Return list indices for all matches.
A class for handling words, derived from Foam::string.
Definition: word.H:68
volScalarField & p
labelList patchIds
patchWriters clear()
dynamicFvMesh & mesh
OBJstream os(runTime.globalPath()/outputName)
label patchId(-1)
labelList findMatching(const StringListType &input, const wordRes::filter &pred, AccessOp aop=identityOp())
Return ids for items with matching names.
Namespace for OpenFOAM.
List< word > wordList
A List of words.
Definition: fileName.H:63
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i)
Definition: labelList.C:38
List< label > labelList
A List of labels.
Definition: List.H:66
messageStream Info
Information stream (stdout output on master, null elsewhere)
IntListType renumber(const labelUList &oldToNew, const IntListType &input)
Renumber the values (not the indices) of a list.
static wordList nonProcessorPatchNames(const polyBoundaryMesh &bmesh)
Definition: ensightMesh.C:46
const direction noexcept
Definition: Scalar.H:223
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce (copy) and return value.
wordList patchNames(nPatches)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333