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 -------------------------------------------------------------------------------
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 {
115  if (!option().lazy())
116  {
117  correct();
118  }
119 }
120 
121 
122 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
123 
125 {
126  clear();
127 
128  const wordRes& czMatcher = option().cellZoneSelection();
129  const wordRes& fzMatcher = option().faceZoneSelection();
130 
131  // Possible cellZones
132  const wordList czNames =
133  (
134  (
135  option().useCellZones()
136  && (!czMatcher.empty() || option().useInternalMesh())
137  )
138  ? mesh_.cellZones().names()
139  : wordList()
140  );
141 
142  const labelList czoneIds =
143  (
144  czMatcher.empty()
145  ? identity(czNames.size()) // All
146  : czMatcher.matching(czNames) // Selected names
147  );
148 
149 
150  // Possible faceZones
151  const wordList fzNames =
152  (
153  option().useFaceZones()
154  ? mesh_.faceZones().names()
155  : wordList()
156  );
157 
158  const labelList fzoneIds =
159  (
160  fzMatcher.empty()
161  ? identity(fzNames.size()) // All
162  : fzMatcher.matching(fzNames) // Selected names
163  );
164 
165 
166  // Possible patchNames
167  const wordList patchNames =
168  (
169  option().useBoundaryMesh()
170  ? nonProcessorPatchNames(mesh_.boundaryMesh())
171  : wordList()
172  );
173 
174  const labelList patchIds =
175  (
176  option().useBoundaryMesh()
178  (
179  patchNames,
180  option().patchSelection(),
181  option().patchExclude()
182  )
183  : labelList()
184  );
185 
186 
187  // Track which cells are in a zone or not
188  bitSet cellSelection;
189 
190  // Faces to be excluded from export
191  bitSet excludeFace;
192 
193 
194  // cellZones first
195  for (const label zoneId : czoneIds)
196  {
197  const word& zoneName = czNames[zoneId];
198  const cellZone& zn = mesh_.cellZones()[zoneId];
199 
200  if (returnReduce(!zn.empty(), orOp<bool>()))
201  {
202  // Ensure full mesh coverage
203  cellSelection.resize(mesh_.nCells());
204 
205  cellSelection.set(zn);
206 
207  ensightCells& part = cellZoneParts_(zoneId);
208 
209  part.clear();
210  part.identifier() = zoneId;
211  part.rename(zoneName);
212 
213  part.classify(mesh_, zn);
214 
215  // Finalize
216  part.reduce();
217  }
218  }
219 
220  if (option().useInternalMesh() && czMatcher.empty())
221  {
222  // The internal mesh:
223  // Either the entire mesh (if no zones specified)
224  // or whatever is leftover as unzoned
225 
226  if (cellZoneParts_.empty())
227  {
228  ensightCells& part = cellZoneParts_(internalZone);
229 
230  part.clear();
231  part.identifier() = internalZone;
232  part.rename("internalMesh");
233 
234  part.classify(mesh_);
235 
236  // Finalize
237  part.reduce();
238  }
239  else
240  {
241  // Unzoned cells - flip selection from zoned to unzoned
242  cellSelection.flip();
243 
244  if (returnReduce(cellSelection.any(), orOp<bool>()))
245  {
246  ensightCells& part = cellZoneParts_(internalZone);
247 
248  part.clear();
249  part.identifier() = internalZone;
250  part.rename("internalMesh");
251 
252  part.classify(mesh_, cellSelection);
253 
254  // Finalize
255  part.reduce();
256  }
257  }
258 
259  // Handled all cells
260  cellSelection.clearStorage();
261  }
262  else if (cellSelection.none())
263  {
264  // No internal, no cellZones selected - just ignore
265  cellSelection.clearStorage();
266  }
267 
268 
269  // Face exclusion based on cellZones
270 
271  if (returnReduce(!cellSelection.empty(), orOp<bool>()))
272  {
273  // Ensure full mesh coverage
274  excludeFace.resize(mesh_.nFaces());
275 
276  const labelList& owner = mesh_.faceOwner();
277 
278  forAll(owner, facei)
279  {
280  const label celli = owner[facei];
281 
282  if (!cellSelection.test(celli))
283  {
284  excludeFace.set(facei);
285  }
286  }
287  }
288 
289 
290  // Face exclusion for empty/processor types
291  // so they are ignored for face zones
292 
293  if (fzoneIds.size())
294  {
295  // Ensure full mesh coverage
296  excludeFace.resize(mesh_.nFaces());
297 
298  for (const polyPatch& p : mesh_.boundaryMesh())
299  {
300  const auto* procPatch = isA<processorPolyPatch>(p);
301 
302  if (isA<emptyPolyPatch>(p))
303  {
304  excludeFace.set(p.range());
305  }
306  else if (procPatch && !procPatch->owner())
307  {
308  // Exclude neighbour-side, retain owner-side only
309  excludeFace.set(p.range());
310  }
311  }
312  }
313 
314 
315  // Patches
316  for (const label patchId : patchIds)
317  {
318  const word& patchName = patchNames[patchId];
319  const polyPatch& p = mesh_.boundaryMesh()[patchId];
320 
321  if (isA<emptyPolyPatch>(p))
322  {
323  // Skip empty patch types
324  continue;
325  }
326  else if (isA<processorPolyPatch>(p))
327  {
328  // Only real (non-processor) boundaries.
329  break;
330  }
331 
332  ensightFaces& part = boundaryParts_(patchId);
333 
334  part.clear();
335  part.identifier() = patchId;
336  part.rename(patchName);
337 
338  part.classify
339  (
340  mesh_.faces(),
341  identity(p.range()),
342  boolList(), // no flip map
343  excludeFace
344  );
345 
346  // Finalize
347  part.reduce();
348 
349  if (!part.total())
350  {
351  boundaryParts_.erase(patchId);
352  }
353  }
354 
355 
356  // Face zones
357 
358  for (const label zoneId : fzoneIds)
359  {
360  const word& zoneName = fzNames[zoneId];
361  const faceZone& zn = mesh_.faceZones()[zoneId];
362 
363  ensightFaces& part = faceZoneParts_(zoneId);
364 
365  part.clear();
366  part.identifier() = zoneId;
367  part.rename(zoneName);
368 
369  if (zn.size())
370  {
371  part.classify
372  (
373  mesh_.faces(),
374  zn,
375  zn.flipMap(),
376  excludeFace
377  );
378  }
379 
380  // Finalize
381  part.reduce();
382 
383  if (!part.total())
384  {
385  faceZoneParts_.erase(zoneId);
386  }
387  }
388 
389  renumber();
390 
391  needsUpdate_ = false;
392 }
393 
394 
396 (
398  bool parallel
399 ) const
400 {
401  // The internalMesh, cellZones
402  for (const label id : cellZoneParts_.sortedToc())
403  {
404  cellZoneParts_[id].write(os, mesh_, parallel);
405  }
406 
407  // Patches - sorted by index
408  for (const label id : boundaryParts_.sortedToc())
409  {
410  boundaryParts_[id].write(os, mesh_, parallel);
411  }
412 
413  // Requested faceZones - sorted by index
414  for (const label id : faceZoneParts_.sortedToc())
415  {
416  faceZoneParts_[id].write(os, mesh_, parallel);
417  }
418 }
419 
420 
421 // ************************************************************************* //
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:67
Foam::PackedList::resize
void resize(const label numElem, const unsigned int val=0u)
Reset addressable list size, does not shrink the allocated size.
Definition: PackedListI.H:409
Foam::wordRes::matching
labelList matching(const UList< StringType > &input, const bool invert=false) const
Return list indices for all matches.
Foam::ensightMesh
Encapsulation of volume meshes for writing in ensight format. It manages cellZones,...
Definition: ensightMesh.H:82
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::faceZone::flipMap
const boolList & flipMap() const noexcept
Return face flip map.
Definition: faceZone.H:272
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:63
Foam::ensightPart::rename
void rename(const string &value)
Change the part name or description.
Definition: ensightPart.H:166
Foam::List::resize
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:139
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:63
Foam::ensightMesh::correct
void correct()
Update for new mesh.
Definition: ensightMesh.C:124
Foam::bitSet::any
bool any() const
True if any bits in this bitset are set.
Definition: bitSetI.H:468
Foam::bitSet::set
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition: bitSetI.H:574
Foam::boolList
List< bool > boolList
A List of bools.
Definition: List.H:65
Foam::PackedList::empty
bool empty() const noexcept
True if the list is empty (ie, size() is zero).
Definition: PackedListI.H:384
Foam::bitSet::test
bool test(const label pos) const
Test value at specified position, never auto-vivify entries.
Definition: bitSetI.H:520
polyMesh.H
Foam::ensightMesh::write
void write(ensightGeoFile &os, bool parallel=Pstream::parRun()) const
Write geometry to file. Normally in parallel.
Definition: ensightMesh.C:396
Foam::ensightFaces
Sorting/classification of faces (2D) into corresponding ensight types.
Definition: ensightFaces.H:71
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
Foam::polyBoundaryMesh::names
wordList names() const
Return a list of patch names.
Definition: polyBoundaryMesh.C:555
Foam::ensightMesh::internalZone
static const label internalZone
The zone-id for internal mesh or unzoned cells.
Definition: ensightMesh.H:87
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::cellZone
A subset of mesh cells.
Definition: cellZone.H:62
Foam::ensightFaces::total
label total() const
The global size of all element types.
Definition: ensightFaces.C:136
Foam::wordList
List< word > wordList
A List of words.
Definition: fileName.H:62
Foam::ensightGeoFile
Specialized Ensight output with extra geometry file header.
Definition: ensightGeoFile.H:48
Foam::polyBoundaryMesh::checkParallelSync
bool checkParallelSync(const bool report=false) const
Check whether all procs have all patches and in same order. Return.
Definition: polyBoundaryMesh.C:972
ensightMesh.H
patchIds
labelList patchIds
Definition: convertProcessorPatches.H:67
Foam::faceZone
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:64
Foam::ensightFaces::reduce
void reduce()
Sum element counts across all processes.
Definition: ensightFaces.C:164
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:68
correct
fvOptions correct(rho)
patchNames
wordList patchNames(nPatches)
Foam::stringListOps::findMatching
labelList findMatching(const StringListType &input, const wordRes &allow, const wordRes &deny=wordRes(), AccessOp aop=noOp())
Return ids for items with matching names.
Foam::ensightCells
Sorting/classification of cells (3D) into corresponding ensight element types.
Definition: ensightCells.H:54
Foam::bitSet::flip
void flip()
Invert all bits in the addressable region.
Definition: bitSetI.H:618
processorPolyPatch.H
os
OBJstream os(runTime.globalPath()/outputName)
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
emptyPolyPatch.H
Foam::polyBoundaryMesh::nNonProcessor
label nNonProcessor() const
The number of patches before the first processor patch.
Definition: polyBoundaryMesh.C:535
Foam::bitSet::none
bool none() const
True if no bits in this bitset are set.
Definition: bitSetI.H:487
Foam::renumber
IntListType renumber(const labelUList &oldToNew, const IntListType &input)
Renumber the values (not the indices) of a list.
Definition: ListOpsTemplates.C:37
ensightGeoFile.H
clear
patchWriters clear()
Foam::ensightMesh::options
Configuration options for the ensightMesh.
Definition: ensightMesh.H:228
Foam::List< word >
Foam::ensightFaces::clear
void clear()
Set addressable sizes to zero, free up addressing memory.
Definition: ensightFaces.C:147
Foam::identity
labelList identity(const label len, label start=0)
Create identity map of the given length with (map[i] == i)
Definition: labelList.C:38
Foam::wordRes
A List of wordRe with additional matching capabilities.
Definition: wordRes.H:51
Foam::PackedList::clearStorage
void clearStorage()
Clear the list and delete storage.
Definition: PackedListI.H:520
Foam::ensightPart::identifier
label identifier() const noexcept
OpenFOAM identifier (patch, zone, etc), -1 when not in use.
Definition: ensightPart.H:136
patchId
label patchId(-1)
Foam::ensightCells::classify
void classify(const polyMesh &mesh)
Classify cell types and set the element lists.
Definition: ensightCells.C:238
Foam::orOp
Definition: ops.H:234
Foam::ensightCells::reduce
void reduce()
Sum element counts across all processes.
Definition: ensightCells.C:135
Foam::ensightCells::clear
void clear()
Set addressable sizes to zero, free up addressing memory.
Definition: ensightCells.C:120
Foam::ensightFaces::classify
void classify(const UList< face > &faces)
Classify the face types and set the element lists.
Definition: ensightFaces.C:219
Foam::nonProcessorPatchNames
static wordList nonProcessorPatchNames(const polyBoundaryMesh &bmesh)
Definition: ensightMesh.C:46