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-2019 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 "fvMesh.H"
31 #include "globalMeshData.H"
33 #include "emptyPolyPatch.H"
34 #include "processorPolyPatch.H"
35 #include "mapDistribute.H"
36 #include "stringListOps.H"
37 
38 #include "ensightFile.H"
39 #include "ensightGeoFile.H"
40 #include "demandDrivenData.H"
41 
42 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
43 
44 void Foam::ensightMesh::clear()
45 {
46  meshCells_.clear();
47  boundaryPatchFaces_.clear();
48  faceZoneFaces_.clear();
49  patchLookup_.clear();
50  globalPointsPtr_.clear();
51 }
52 
53 
54 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
55 
56 Foam::ensightMesh::ensightMesh
57 (
58  const fvMesh& mesh,
59  const ensightMesh::options& opts
60 )
61 :
62  options_(new options(opts)),
63  mesh_(mesh),
64  needsUpdate_(true)
65 {
66  if (!option().lazy())
67  {
68  correct();
69  }
70 }
71 
72 
73 Foam::ensightMesh::ensightMesh(const fvMesh& mesh)
74 :
75  ensightMesh(mesh, IOstream::streamFormat::BINARY)
76 {}
77 
78 
79 Foam::ensightMesh::ensightMesh
80 (
81  const fvMesh& mesh,
83 )
84 :
85  options_(new options(format)),
86  mesh_(mesh),
87  needsUpdate_(true)
88 {
89  if (!option().lazy())
90  {
91  correct();
92  }
93 }
94 
95 
96 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
97 
99 {
100  deleteDemandDrivenData(options_);
101 }
102 
103 
104 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
105 
107 {
108  return needsUpdate_;
109 }
110 
111 
113 {
114  clear();
115 
116  // Already marked as expired
117  if (needsUpdate_)
118  {
119  return false;
120  }
121 
122  needsUpdate_ = true;
123  return true;
124 }
125 
126 
128 {
129  clear();
130 
131  // Part number
132  label nParts = 0;
133 
134  if (useInternalMesh())
135  {
136  meshCells_.index() = nParts++;
137  meshCells_.classify(mesh_);
138 
139  // Determine parallel shared points
140  globalPointsPtr_ = mesh_.globalData().mergePoints
141  (
142  pointToGlobal_,
143  uniquePointMap_
144  );
145  }
146  meshCells_.reduce();
147 
148 
149  if (useBoundaryMesh())
150  {
151  // Patches are output. Check that they are synced.
152  mesh_.boundaryMesh().checkParallelSync(true);
153 
154  wordList patchNames = mesh_.boundaryMesh().names();
155  if (Pstream::parRun())
156  {
157  // Do not include processor patches in matching
158  patchNames.resize(mesh_.boundaryMesh().nNonProcessor());
159  }
160 
161  const wordRes& matcher = option().patchSelection();
162 
163  const labelList patchIds =
164  (
165  matcher.empty()
166  ? identity(patchNames.size()) // Use all
167  : findStrings(matcher, patchNames) // Use specified names
168  );
169 
170  for (const label patchId : patchIds)
171  {
172  const word& patchName = patchNames[patchId];
173 
174  // Use fvPatch (not polyPatch) to automatically remove empty patches
175  const fvPatch& p = mesh_.boundary()[patchId];
176 
177  ensightFaces& ensFaces = boundaryPatchFaces_(patchName);
178  ensFaces.clear();
179 
180  if (p.size())
181  {
182  // Local face addressing (offset = 0),
183  // - this is what we'll need later when writing fields
184  ensFaces.classify(p.patch());
185  }
186  else
187  {
188  // The patch is empty (on this processor)
189  // or the patch is 'empty' (as fvPatch type)
190  ensFaces.clear();
191  }
192 
193  // Finalize
194  ensFaces.reduce();
195 
196  if (ensFaces.total())
197  {
198  patchLookup_.set(patchId, patchName);
199  ensFaces.index() = nParts++;
200  }
201  else
202  {
203  boundaryPatchFaces_.erase(patchName);
204  }
205  }
206 
207  // At this point,
208  // * patchLookup_ is a map of (patchId, name)
209  // * boundaryPatchFaces_ is a lookup by name for the faces elements
210  }
211 
212 
213  if (option().useFaceZones())
214  {
215  // Mark boundary faces to be excluded from export
216  bitSet excludeFace(mesh_.nFaces());
217 
218  for (const polyPatch& pp : mesh_.boundaryMesh())
219  {
220  const auto* procPatch = isA<processorPolyPatch>(pp);
221 
222  if (isA<emptyPolyPatch>(pp))
223  {
224  excludeFace.set(pp.range());
225  }
226  else if (procPatch && !procPatch->owner())
227  {
228  // Exclude neighbour-side, retain owner-side only
229  excludeFace.set(pp.range());
230  }
231  }
232 
233  // Use sorted order for later consistency
234  const wordList zoneNames =
235  mesh_.faceZones().sortedNames(option().faceZoneSelection());
236 
237  // Count face types in each selected faceZone
238  for (const word& zoneName : zoneNames)
239  {
240  const label zoneID = mesh_.faceZones().findZoneID(zoneName);
241  const faceZone& fz = mesh_.faceZones()[zoneID];
242 
243  ensightFaces& ensFaces = faceZoneFaces_(zoneName);
244  ensFaces.clear();
245 
246  if (fz.size())
247  {
248  ensFaces.classify
249  (
250  mesh_.faces(),
251  fz,
252  fz.flipMap(),
253  excludeFace
254  );
255  }
256 
257  // Finalize
258  ensFaces.reduce();
259 
260  if (ensFaces.total())
261  {
262  ensFaces.index() = nParts++;
263  }
264  else
265  {
266  faceZoneFaces_.erase(zoneName);
267  }
268  }
269  }
270 
271  needsUpdate_ = false;
272 }
273 
274 
276 {
277  //
278  // Write internalMesh
279  //
280  if (useInternalMesh())
281  {
282  const label nPoints = globalPoints().size();
283 
284  const pointField uniquePoints(mesh_.points(), uniquePointMap_);
285 
286  // writePartHeader(os, 0, "internalMesh");
287  // beginCoordinates(os, nPoints);
288  writeAllPoints
289  (
290  meshCells_.index(),
291  "internalMesh",
292  nPoints,
293  uniquePoints,
294  os
295  );
296 
297  writeCellConnectivity(meshCells_, pointToGlobal_, os);
298  }
299 
300 
301  //
302  // Write patches - sorted by Id
303  //
304  for (const label patchId : patchLookup_.sortedToc())
305  {
306  const word& patchName = patchLookup_[patchId];
307  const ensightFaces& ensFaces = boundaryPatchFaces_[patchName];
308 
309  const polyPatch& pp = mesh_.boundaryMesh()[patchId];
310 
311  // Renumber the patch points/faces into unique points
312  labelList pointToGlobal;
313  labelList uniqueMeshPointLabels;
314  autoPtr<globalIndex> globalPointsPtr =
315  mesh_.globalData().mergePoints
316  (
317  pp.meshPoints(),
318  pp.meshPointMap(),
319  pointToGlobal, // local point to unique global index
320  uniqueMeshPointLabels // unique global points
321  );
322 
323  // Renumber the patch faces,
324  // from local patch indexing to unique global index
325  faceList patchFaces(pp.localFaces());
326  for (face& f : patchFaces)
327  {
328  inplaceRenumber(pointToGlobal, f);
329  }
330 
331  writeAllPoints
332  (
333  ensFaces.index(),
334  patchName,
335  globalPointsPtr().size(),
336  pointField(mesh_.points(), uniqueMeshPointLabels),
337  os
338  );
339 
340  writeFaceConnectivity(ensFaces, patchFaces, os);
341  }
342 
343 
344  //
345  // Write faceZones, if requested
346  //
347  for (const word& zoneName : faceZoneFaces_.sortedToc())
348  {
349  const ensightFaces& ensFaces = faceZoneFaces_[zoneName];
350 
351  // Use the properly sorted faceIds (ensightFaces) and do NOT use the
352  // faceZone directly, otherwise the point-maps will not correspond.
353  // - perform face-flipping later
354 
356  (
357  IndirectList<face>(mesh_.faces(), ensFaces.faceIds()),
358  mesh_.points()
359  );
360 
361  // Renumber the points/faces into unique points
362  labelList pointToGlobal;
363  labelList uniqueMeshPointLabels;
364  autoPtr<globalIndex> globalPointsPtr =
365  mesh_.globalData().mergePoints
366  (
367  pp.meshPoints(),
368  pp.meshPointMap(),
369  pointToGlobal, // local point to unique global index
370  uniqueMeshPointLabels // unique global points
371  );
372 
373  // Renumber the faces belonging to the faceZone,
374  // from local numbering to unique global index.
375  // Also a good place to perform face flipping
376  const boolList& flip = ensFaces.flipMap();
377  faceList patchFaces(pp.localFaces());
378  forAll(patchFaces, facei)
379  {
380  face& f = patchFaces[facei];
381 
382  if (flip[facei])
383  {
384  f.flip();
385  }
386 
387  inplaceRenumber(pointToGlobal, f);
388  }
389 
390  writeAllPoints
391  (
392  ensFaces.index(),
393  zoneName,
394  globalPointsPtr().size(),
395  pointField(mesh_.points(), uniqueMeshPointLabels),
396  os
397  );
398 
399  writeFaceConnectivity(ensFaces, patchFaces, os, true);
400  }
401 }
402 
403 
404 // ************************************************************************* //
Foam::ensightFaces::flipMap
const boolList & flipMap() const
Return the processor local flip-map of all elements.
Definition: ensightFacesI.H:95
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
Foam::ensightMesh
Encapsulation of volume meshes for writing in ensight format.
Definition: ensightMesh.H:68
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::globalPoints
Calculates points shared by more than two processor patches or cyclic patches.
Definition: globalPoints.H:102
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::ensightMesh::needsUpdate
bool needsUpdate() const
Does the content need an update?
Definition: ensightMesh.C:106
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:64
globalMeshData.H
demandDrivenData.H
Template functions to aid in the implementation of demand driven data.
Foam::ensightMesh::correct
void correct()
Update for new mesh.
Definition: ensightMesh.C:127
Foam::UPstream::parRun
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:414
Foam::IOstream
An IOstream is an abstract base class for all input/output systems; be they streams,...
Definition: IOstream.H:75
Foam::ensightFaces
Sorting/classification of faces (2D) into corresponding ensight types.
Definition: ensightFaces.H:51
Foam::inplaceRenumber
void inplaceRenumber(const labelUList &oldToNew, IntListType &input)
Inplace renumber the values (not the indices) of a list.
Definition: ListOpsTemplates.C:61
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
Foam::ensightFaces::total
label total() const
The global number of all element types.
Definition: ensightFaces.C:162
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
PstreamCombineReduceOps.H
Combination-Reduction operation for a parallel run. The information from all nodes is collected on th...
Foam::deleteDemandDrivenData
void deleteDemandDrivenData(DataPtr &dataPtr)
Definition: demandDrivenData.H:42
Foam::ensightMesh::~ensightMesh
~ensightMesh()
Destructor.
Definition: ensightMesh.C:98
format
word format(conversionProperties.get< word >("format"))
Foam::ensightGeoFile
Specialized Ensight output with extra geometry file header.
Definition: ensightGeoFile.H:48
ensightMesh.H
patchIds
labelList patchIds
Definition: convertProcessorPatches.H:67
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:62
Foam::Field< vector >
Foam::polyPatch::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundaryMesh reference.
Definition: polyPatch.C:305
Foam::faceZone
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:65
Foam::ensightFaces::reduce
void reduce()
Sum element counts across all processes.
Definition: ensightFaces.C:180
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:66
ensightFile.H
correct
fvOptions correct(rho)
Foam::fvPatch
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:63
Foam::IndirectList
A List with indirect addressing.
Definition: IndirectList.H:56
patchNames
wordList patchNames(nPatches)
Foam::ensightFaces::faceIds
const labelUList faceIds(const enum elemType) const
Return the (local) face ids of the specified element type.
Definition: ensightFacesI.H:81
Foam::ensightMesh::expire
bool expire()
Mark as needing an update.
Definition: ensightMesh.C:112
Foam::List::resize
void resize(const label newSize)
Adjust allocated size of list.
Definition: ListI.H:139
Foam::IOstreamOption::streamFormat
streamFormat
Data format (ascii | binary)
Definition: IOstreamOption.H:64
processorPolyPatch.H
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
zoneID
const labelIOList & zoneID
Definition: interpolatedFaces.H:22
Foam::ensightFaces::classify
void classify(const faceList &faces)
Classify the face types, set element list.
Definition: ensightFaces.C:229
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:84
fvMesh.H
Foam::findStrings
labelList findStrings(const regExp &matcher, const UList< StringType > &input, const bool invert=false)
Return list indices for strings matching the regular expression.
Definition: stringListOps.H:75
emptyPolyPatch.H
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:53
ensightGeoFile.H
Foam::ensightFaces::index
label index() const
The index in a list.
Definition: ensightFacesI.H:38
clear
patchWriters clear()
Foam::ensightMesh::options
Configuration options for the ensightMesh.
Definition: ensightMesh.H:394
mapDistribute.H
f
labelList f(nPoints)
Foam::List< word >
Foam::ensightFaces::clear
void clear()
Set addressable sizes to zero, free up addressing memory.
Definition: ensightFaces.C:173
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::PrimitivePatch::localFaces
const List< Face > & localFaces() const
Return patch faces addressing into local point list.
Definition: PrimitivePatch.C:398
Foam::ensightMesh::write
void write(autoPtr< ensightGeoFile > &os) const
Write to file.
Definition: ensightMeshI.H:86
stringListOps.H
Operations on lists of strings.
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:74
patchId
label patchId(-1)
Foam::PrimitivePatch::meshPointMap
const Map< label > & meshPointMap() const
Mesh point map.
Definition: PrimitivePatch.C:438
Foam::PrimitivePatch::meshPoints
const labelList & meshPoints() const
Return labelList of mesh points in patch.
Definition: PrimitivePatch.C:418
Foam::faceZone::flipMap
const boolList & flipMap() const
Return face flip map.
Definition: faceZone.H:271
Foam::ensightCells::clear
void clear()
Set addressable sizes to zero, free up addressing memory.
Definition: ensightCells.C:128
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatch.H:90