ensightOutputVolFieldTemplates.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 -------------------------------------------------------------------------------
10 License
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 "ensightOutputVolField.H"
29 #include "ensightMesh.H"
30 
31 #include "fvMesh.H"
32 #include "linear.H"
33 #include "volPointInterpolation.H"
34 #include "interpolation.H"
36 #include "DynamicField.H"
37 
38 // * * * * * * * * * * * * * * * * Detail * * * * * * * * * * * * * * * * * //
39 
40 template<class Type>
42 (
44  ensightFile& os,
46  const ensightMesh& ensMesh
47 )
48 {
49  bool parallel = Pstream::parRun();
50 
51  const fvMesh& mesh = vf.mesh();
52  const polyBoundaryMesh& bmesh = mesh.boundaryMesh();
53 
54  const Map<ensightCells>& cellZoneParts = ensMesh.cellZoneParts();
55  const Map<ensightFaces>& faceZoneParts = ensMesh.faceZoneParts();
56  const Map<ensightFaces>& boundaryParts = ensMesh.boundaryParts();
57 
58  // Write internalMesh and cellZones - sorted by index
59  for (const label zoneId : cellZoneParts.sortedToc())
60  {
61  const ensightCells& part = cellZoneParts[zoneId];
62 
63  ensightOutput::writeField(scratch, os, vf, part, parallel);
64  }
65 
66 
67  // Write patches - sorted by index
68  for (const label patchId : boundaryParts.sortedToc())
69  {
70  const ensightFaces& part = boundaryParts[patchId];
71 
72  if (patchId < 0 || patchId >= bmesh.size())
73  {
74  // Future handling of combined patches?
75  continue;
76  }
77 
78  const label patchStart = bmesh[patchId].start();
79 
80  // Either use a flat boundary field for all patches,
81  // or patch-local face ids
82 
83  // Operate on a copy
84  ensightFaces localPart(part);
85 
86  // Change from global faceIds to patch-local
87  localPart.decrFaceIds(patchStart);
88 
90  (
91  scratch,
92  os,
93  vf.boundaryField()[patchId],
94  localPart,
95  parallel
96  );
97  }
98 
99 
100  // No face zones data
101  if (faceZoneParts.empty())
102  {
103  return true;
104  }
105 
106 
107  // Flat boundary field
108  // similar to volPointInterpolation::flatBoundaryField()
109 
110  Field<Type> flat(mesh.nBoundaryFaces(), Zero);
111 
112  const fvBoundaryMesh& bm = mesh.boundary();
113  forAll(vf.boundaryField(), patchi)
114  {
115  const polyPatch& pp = bm[patchi].patch();
116  const auto& bf = vf.boundaryField()[patchi];
117 
118  if (isA<processorFvPatch>(bm[patchi]))
119  {
120  // Use average value for processor faces
121  // own cell value = patchInternalField
122  // nei cell value = evaluated boundary values
124  (
125  flat,
126  bf.size(),
127  pp.offset()
128  ) = (0.5 * (bf.patchInternalField() + bf));
129  }
130  else if (!isA<emptyFvPatch>(bm[patchi]))
131  {
133  (
134  flat,
135  bf.size(),
136  pp.offset()
137  ) = bf;
138  }
139  }
140 
141 
142  // Interpolate cell values to faces
143  // - only needed when exporting faceZones...
144 
147 
148  const auto& sfld = tsfld();
149 
150 
151  // Local output buffer
152  label maxLen = 0;
153 
154  forAllConstIters(faceZoneParts, iter)
155  {
156  maxLen = max(maxLen, iter.val().size());
157  }
158 
159  DynamicField<Type> values(maxLen);
160 
161 
162  //
163  // Write requested faceZones - sorted by index
164  //
165  for (const label zoneId : faceZoneParts.sortedToc())
166  {
167  const ensightFaces& part = faceZoneParts[zoneId];
168 
169  // Loop over face ids to store the needed field values
170  // - internal faces use linear interpolation
171  // - boundary faces use the corresponding patch value
172 
173  // Local copy of the field
174  values.resize_nocopy(part.size());
175  values = Zero;
176 
177  auto valIter = values.begin();
178 
179  for (const label faceId : part.faceIds())
180  {
181  *valIter =
182  (
183  mesh.isInternalFace(faceId)
184  ? sfld[faceId]
185  : flat[faceId - mesh.nInternalFaces()]
186  );
187 
188  ++valIter;
189  }
190 
191  // The field is already in the proper element order
192  // - just need its corresponding sub-fields
194  (
195  scratch, os, values, part, parallel
196  );
197  }
199  return true;
200 }
201 
202 
203 template<class Type>
205 (
207  ensightFile& os,
209  const ensightMesh& ensMesh
210 )
211 {
212  bool parallel = Pstream::parRun();
213 
214  const polyMesh& mesh = ensMesh.mesh();
215 
216  const Map<ensightCells>& cellZoneParts = ensMesh.cellZoneParts();
217  const Map<ensightFaces>& faceZoneParts = ensMesh.faceZoneParts();
218  const Map<ensightFaces>& boundaryParts = ensMesh.boundaryParts();
219 
220  //
221  // Write internalMesh and cellZones - sorted by index
222  //
223  for (const label zoneId : cellZoneParts.sortedToc())
224  {
225  const ensightCells& part = cellZoneParts[zoneId];
226 
227  labelList uniquePointLabels;
228  part.uniqueMeshPoints(mesh, uniquePointLabels, parallel);
229 
230  if (Pstream::master())
231  {
232  os.beginPart(part.index());
233  }
234 
235  // Skip if empty
236  if
237  (
238  parallel
239  ? returnReduceAnd(uniquePointLabels.empty())
240  : uniquePointLabels.empty()
241  )
242  {
243  continue;
244  }
245 
247  (
248  scratch,
249  os,
251  UIndirectList<Type>(pf.internalField(), uniquePointLabels),
252  parallel
253  );
254  }
255 
256 
257  //
258  // Write patches - sorted by index
259  //
260  for (const label patchId : boundaryParts.sortedToc())
261  {
262  const ensightFaces& part = boundaryParts[patchId];
263 
264  labelList uniquePointLabels;
265  part.uniqueMeshPoints(mesh, uniquePointLabels, parallel);
266 
267  if (Pstream::master())
268  {
269  os.beginPart(part.index());
270  }
271 
272  // Skip if empty
273  if
274  (
275  parallel
276  ? returnReduceAnd(uniquePointLabels.empty())
277  : uniquePointLabels.empty()
278  )
279  {
280  continue;
281  }
282 
283  const auto& bfld = pf.boundaryField()[patchId];
284 
285  // Only valuePointPatchField is actually derived from Field
286  const auto* vpp = isA<Field<Type>>(bfld);
287  if (vpp)
288  {
289  // Require patch local indices, not mesh point labels.
290  // But need to use polyPatch meshPointMap() to recover the
291  // local indices since the ensight output will have jumbled
292  // the face output order
293 
294  const polyPatch& pp = mesh.boundaryMesh()[patchId];
295 
296  for (label& pointi : uniquePointLabels)
297  {
298  pointi = pp.meshPointMap()[pointi];
299  }
300 
302  (
303  scratch,
304  os,
306  UIndirectList<Type>(*vpp, uniquePointLabels),
307  parallel
308  );
309  }
310  else
311  {
313  (
314  scratch,
315  os,
317  UIndirectList<Type>(pf.internalField(), uniquePointLabels),
318  parallel
319  );
320  }
321  }
322 
323  //
324  // Write requested faceZones - sorted by index
325  //
326  for (const label zoneId : faceZoneParts.sortedToc())
327  {
328  const ensightFaces& part = faceZoneParts[zoneId];
329 
330  labelList uniquePointLabels;
331  part.uniqueMeshPoints(mesh, uniquePointLabels, parallel);
332 
333  if (Pstream::master())
334  {
335  os.beginPart(part.index());
336  }
337 
338  // Skip if empty
339  if
340  (
341  parallel
342  ? returnReduceAnd(uniquePointLabels.empty())
343  : uniquePointLabels.empty()
344  )
345  {
346  continue;
347  }
348 
349  // CAVEAT - does not properly handle valuePointPatchField,
350  // uses internalField only
351 
353  (
354  scratch,
355  os,
357  UIndirectList<Type>(pf.internalField(), uniquePointLabels),
358  parallel
359  );
360  }
361 
362  return true;
363 }
364 
365 
366 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
367 
368 template<class Type>
370 (
372  ensightFile& os,
374  const ensightMesh& ensMesh,
375  const bool nodeValues
376 )
377 {
378  if (nodeValues)
379  {
381  (
383  );
384  pfld.ref().checkOut();
385  pfld.ref().rename(vf.name());
386 
387  return ensightOutput::writePointField<Type>(scratch, os, pfld, ensMesh);
388  }
389 
390  return ensightOutput::writeVolField<Type>(scratch, os, vf, ensMesh);
391 }
392 
393 
394 // ************************************************************************* //
Ensight output with specialized write() for strings, integers and floats. Correctly handles binary wr...
Definition: ensightFile.H:46
label patchId(-1)
label uniqueMeshPoints(const polyMesh &mesh, labelList &uniqueMeshPointLabels, bool parallel) const
Globally unique mesh points. Required when writing point fields.
label faceId(-1)
tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > linearInterpolate(const GeometricField< Type, fvPatchField, volMesh > &vf)
Definition: linear.H:120
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:195
T & ref() const
Return non-const reference to the contents of a non-null managed pointer.
Definition: tmpI.H:235
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
static tmp< GeometricField< Type, faePatchField, edgeMesh > > interpolate(const GeometricField< Type, faPatchField, areaMesh > &tvf, const edgeScalarField &faceFlux, Istream &schemeData)
Interpolate field onto faces using scheme given by Istream.
const Internal & internalField() const noexcept
Return a const-reference to the dimensioned internal field.
label start() const noexcept
The start label of boundary faces in the polyMesh face list.
bool empty() const noexcept
True if List is empty (ie, size() is zero)
Definition: UList.H:666
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
Sorting/classification of faces (2D) into corresponding ensight types.
Definition: ensightFaces.H:66
bool writeFaceSubField(ensightOutput::floatBufferType &scratch, ensightFile &os, const Field< Type > &fld, const ensightFaces &part, bool parallel)
Write a sub-field of faces values as an indirect list, using the sub-list sizing information from ens...
Generic GeometricField class.
Definition: areaFieldsFwd.H:50
A collection of functions for writing volField content in ensight format.
bool writeField(ensightOutput::floatBufferType &scratch, ensightFile &os, const Field< Type > &fld, const ensightCells &part, bool parallel)
Write a field of cell values as an indirect list, using the cell ids from ensightCells.
const polyMesh & mesh() const noexcept
Reference to the underlying polyMesh.
Definition: ensightMesh.H:191
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
Definition: HashOps.H:164
bool returnReduceAnd(const bool value, const label comm=UPstream::worldComm)
Perform logical (and) MPI Allreduce on a copy. Uses UPstream::reduceAnd.
dynamicFvMesh & mesh
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:51
void writeFieldComponents(ensightOutput::floatBufferType &scratch, ensightFile &os, const char *key, const FieldContainer< Type > &fld, bool parallel)
Write field content (component-wise) for the given ensight element type.
Generic templated field type.
Definition: Field.H:62
label size(const elemType etype) const
Processor-local size of the specified element type.
Definition: ensightFacesI.H:60
Sorting/classification of cells (3D) into corresponding ensight element types.
Definition: ensightCells.H:49
label size() const noexcept
The number of entries in the list.
Definition: UPtrListI.H:106
const Map< ensightFaces > & boundaryParts() const noexcept
Face elements per selected patch, lookup by patch index.
Definition: ensightMesh.H:227
Dynamically sized Field.
Definition: DynamicField.H:45
const Map< ensightFaces > & faceZoneParts() const noexcept
Face elements per faceZone, lookup by zone index.
Definition: ensightMesh.H:217
const Map< ensightCells > & cellZoneParts() const noexcept
Face elements per selected patch, lookup by patch index.
Definition: ensightMesh.H:207
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO...
const labelList & faceIds() const noexcept
Processor-local face ids of all elements.
Definition: ensightFacesI.H:72
const Mesh & mesh() const noexcept
Return mesh.
bool empty() const noexcept
True if the hash table is empty.
Definition: HashTable.H:337
Encapsulation of volume meshes for writing in ensight format. It manages cellZones, facesZone, patches.
Definition: ensightMesh.H:78
OBJstream os(runTime.globalPath()/outputName)
void decrFaceIds(const label off)
Decrease face ids by specified offset value.
label index() const noexcept
The index in a list (0-based)
Definition: ensightPart.H:153
PtrList< coordinateSystem > coordinates(solidRegions.size())
Foam::fvBoundaryMesh.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
List< label > sortedToc() const
The table of contents (the keys) in sorted order.
Definition: HashTable.C:139
A List with indirect addressing. Like IndirectList but does not store addressing. ...
Definition: faMatrix.H:56
bool writePointField(ensightOutput::floatBufferType &scratch, ensightFile &os, const GeometricField< Type, pointPatchField, pointMesh > &pf, const ensightMesh &ensMesh)
Write point field component-wise.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
List< label > labelList
A List of labels.
Definition: List.H:62
A class for managing temporary objects.
Definition: HashPtrTable.H:50
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:69
const Boundary & boundaryField() const noexcept
Return const-reference to the boundary field.
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
A HashTable to objects of type <T> with a label key.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127
bool writeVolField(ensightOutput::floatBufferType &scratch, ensightFile &os, const GeometricField< Type, fvPatchField, volMesh > &vf, const ensightMesh &ensMesh)
Write volume field component-wise.