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-2022 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
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 
37 const Foam::label Foam::ensightMesh::internalZone = -1;
38 
39 
40 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
41 
42 namespace 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 
65 void Foam::ensightMesh::clear()
66 {
67  cellZoneParts_.clear();
68  faceZoneParts_.clear();
69  boundaryParts_.clear();
70 }
71 
72 
73 void 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 
96 Foam::ensightMesh::ensightMesh
97 (
98  const polyMesh& mesh
99 )
100 :
102 {}
103 
104 
105 Foam::ensightMesh::ensightMesh
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  {
119  }
120 }
121 
122 
123 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
126 {
127  return verbose_;
128 }
129 
130 
131 int 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  (
194  patchNames,
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 (returnReduceOr(!zn.empty()))
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 (returnReduceOr(cellSelection.any()))
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 (returnReduceOr(!cellSelection.empty()))
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 types and neighbour side of coupled
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* cpp = isA<coupledPolyPatch>(p);
328 
329  if
330  (
331  isA<emptyPolyPatch>(p)
332  || (cpp && !cpp->owner())
333  )
334  {
335  // Ignore empty patch
336  // Ignore neighbour side of coupled
337  excludeFace.set(p.range());
338  }
339  }
340  }
341 
342 
343  // Patches
344  for (const label patchId : patchIds)
345  {
346  const word& patchName = patchNames[patchId];
347  const polyPatch& p = mesh_.boundaryMesh()[patchId];
348 
349  if (isA<emptyPolyPatch>(p))
350  {
351  // Skip empty patch types
352  continue;
353  }
354  else if (isA<processorPolyPatch>(p))
355  {
356  // Only real (non-processor) boundaries.
357  break;
358  }
359 
360  ensightFaces& part = boundaryParts_(patchId);
361 
362  part.clear();
363  part.identifier() = patchId;
364  part.rename(patchName);
365 
366  part.classify
367  (
368  mesh_.faces(),
369  identity(p.range()),
370  boolList(), // no flip map
371  excludeFace
372  );
373 
374  // Finalize
375  part.reduce();
376  if (verbose_)
377  {
378  Info<< part.info();
379  }
380  if (!part.total())
381  {
382  boundaryParts_.erase(patchId);
383  }
384  }
385 
386 
387  // Face zones
388 
389  for (const label zoneId : fzoneIds)
390  {
391  const word& zoneName = fzNames[zoneId];
392  const faceZone& zn = mesh_.faceZones()[zoneId];
393 
394  ensightFaces& part = faceZoneParts_(zoneId);
395 
396  part.clear();
397  part.identifier() = zoneId;
398  part.rename(zoneName);
399 
400  if (zn.size())
401  {
402  part.classify
403  (
404  mesh_.faces(),
405  zn,
406  zn.flipMap(),
407  excludeFace
408  );
409  }
410 
411  // Finalize
412  part.reduce();
413  if (verbose_)
414  {
415  Info<< part.info();
416  }
417  if (!part.total())
418  {
419  faceZoneParts_.erase(zoneId);
420  }
421  }
422 
424 
425  needsUpdate_ = false;
426 }
427 
428 
430 (
432  bool parallel
433 ) const
434 {
435  // The internalMesh, cellZones
436  for (const label id : cellZoneParts_.sortedToc())
437  {
438  cellZoneParts_[id].write(os, mesh_, parallel);
439  }
440 
441  // Patches - sorted by index
442  for (const label id : boundaryParts_.sortedToc())
443  {
444  boundaryParts_[id].write(os, mesh_, parallel);
445  }
446 
447  // Requested faceZones - sorted by index
448  for (const label id : faceZoneParts_.sortedToc())
449  {
450  faceZoneParts_[id].write(os, mesh_, parallel);
451  }
452 }
453 
454 
455 // ************************************************************************* //
label patchId(-1)
labelList patchIds
void classify(const polyMesh &mesh)
Classify cell types and set the element lists.
Definition: ensightCells.C:235
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition: bitSetI.H:504
void write(ensightGeoFile &os, bool parallel=Pstream::parRun()) const
Write geometry to file. Normally in parallel.
Definition: ensightMesh.C:423
labelList matching(const UList< StringType > &input, const bool invert=false) const
Return list indices for all matches.
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:160
const ensightMesh::options & option() const
Reference to the writer/mesh options.
Definition: ensightMeshI.H:23
InfoProxy< ensightCells > info() const noexcept
Return info proxy, used to print information to a stream.
Definition: ensightCells.H:338
IntListType renumber(const labelUList &oldToNew, const IntListType &input)
Renumber the values (not the indices) of a list.
void flip()
Invert all bits in the addressable region.
Definition: bitSetI.H:548
bool empty() const noexcept
True if List is empty (ie, size() is zero)
Definition: UList.H:666
Specialized Ensight output with extra geometry file header.
bool any() const
True if any bits in this bitset are set.
Definition: bitSetI.H:414
void resize(const label numElem, const unsigned int val=0u)
Reset addressable list size, does not shrink the allocated size.
Definition: PackedListI.H:455
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
void correct()
Update for new mesh.
Definition: ensightMesh.C:132
dynamicFvMesh & mesh
static wordList nonProcessorPatchNames(const polyBoundaryMesh &bmesh)
Definition: ensightMesh.C:39
label identifier() const noexcept
OpenFOAM identifier (patch, zone, etc), -1 when not in use.
Definition: ensightPart.H:169
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i), works like std::iota() but returning a...
Definition: labelLists.C:44
A class for handling words, derived from Foam::string.
Definition: word.H:63
Sorting/classification of cells (3D) into corresponding ensight element types.
Definition: ensightCells.H:49
wordList names() const
Return a list of patch names.
wordList patchNames(nPatches)
labelList findMatching(const StringListType &input, const wordRes::filter &pred, AccessOp aop=identityOp())
Return ids for items with matching names.
A List of wordRe with additional matching capabilities.
Definition: wordRes.H:53
patchWriters clear()
bool test(const label pos) const
Test for True value at specified position, never auto-vivify entries.
Definition: bitSet.H:326
void reduce()
Sum element counts across all processes.
Definition: ensightCells.C:131
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO...
const direction noexcept
Definition: Scalar.H:258
bool checkParallelSync(const bool report=false) const
Check whether all procs have all patches and in same order.
void clear()
Set addressable sizes to zero, free up addressing memory.
Definition: ensightCells.C:115
Encapsulation of volume meshes for writing in ensight format. It manages cellZones, facesZone, patches.
Definition: ensightMesh.H:78
OBJstream os(runTime.globalPath()/outputName)
A subset of mesh cells.
Definition: cellZone.H:58
List< word > wordList
List of word.
Definition: fileName.H:59
bool empty() const noexcept
True if the list is empty (ie, size() is zero).
Definition: PackedList.H:366
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:59
messageStream Info
Information stream (stdout output on master, null elsewhere)
static const label internalZone
The zone-id for internal mesh or unzoned cells.
Definition: ensightMesh.H:83
Configuration options for the ensightMesh.
Definition: ensightMesh.H:299
void clearStorage()
Clear the list and delete storage.
Definition: PackedListI.H:566
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
int verbose() const noexcept
Output verbosity level.
Definition: ensightMesh.C:118
List< label > labelList
A List of labels.
Definition: List.H:62
volScalarField & p
label nNonProcessor() const
The number of patches before the first processor patch.
bool returnReduceOr(const bool value, const label comm=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
List< bool > boolList
A List of bools.
Definition: List.H:60
bool none() const
True if no bits in this bitset are set.
Definition: bitSetI.H:420
void rename(const string &value)
Change the part name or description.
Definition: ensightPart.H:209
Namespace for OpenFOAM.