ensightOutput.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) 2020-2022 OpenCFD Ltd.
9  Copyright (C) 2026 Keysight Technologies
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 "ensightOutput.H"
30 #include "cell.H"
31 #include "cellShape.H"
32 #include "face.H"
33 #include "polyMesh.H"
34 #include "ListOps.H"
36 #include "debug.H"
37 #include "defineDebugSwitch.H"
38 #include "registerSwitch.H"
39 
40 // * * * * * * * * * * * * * * * * Globals * * * * * * * * * * * * * * * * * //
41 
43 
44 registerDebugSwitchWithName(Foam::ensightOutput, ensightOutput, "ensight");
45 
47 (
48  Foam::debug::optimisationSwitch("ensight.maxChunk", 0)
49 );
50 
51 registerOptSwitch("ensight.maxChunk", int, Foam::ensightOutput::maxChunk_);
52 
53 
54 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
55 
56 // Sizes
57 
59 (
60  const UList<face>& faces
61 )
62 {
63  labelList list(faces.size());
64 
65  auto outIter = list.begin();
66 
67  for (const face& f : faces)
68  {
69  *outIter = f.size();
70  ++outIter;
71  }
72 
73  return list;
74 }
75 
76 
78 (
79  const UIndirectList<face>& faces
80 )
81 {
82  labelList list(faces.size());
83 
84  auto outIter = list.begin();
85 
86  for (const face& f : faces)
87  {
88  *outIter = f.size();
89  ++outIter;
90  }
91 
92  return list;
93 }
94 
95 
97 (
98  const polyMesh& mesh,
99  const labelUList& addr
100 )
101 {
103  const cellList& meshCells = manifoldCellsMeshObject::New(mesh).cells();
104 
105  labelList list(addr.size());
106 
107  auto outIter = list.begin();
108 
109  // The number of faces per element
110  for (const label cellId : addr)
111  {
112  *outIter = meshCells[cellId].size();
113  ++outIter;
114  }
115 
116  return list;
117 }
118 
119 
121 (
122  const polyMesh& mesh,
123  const labelUList& addr
124 )
125 {
127  const cellList& meshCells = manifoldCellsMeshObject::New(mesh).cells();
128  const faceList& meshFaces = mesh.faces();
129 
130  // Count the number of faces per element
131 
132  label nTotFaces = 0;
133  for (const label cellId : addr)
134  {
135  nTotFaces += meshCells[cellId].size();
136  }
137 
138  labelList list(nTotFaces);
139 
140  auto outIter = list.begin();
141 
142  // The number of points per element face
143  for (const label cellId : addr)
144  {
145  for (const label facei : meshCells[cellId])
146  {
147  *outIter = meshFaces[facei].size();
148  ++outIter;
149  }
150  }
151 
152  return list;
153 }
154 
155 
157 (
158  ensightGeoFile& os,
159  const labelUList& offsets,
160  const labelUList& values,
161  const label pointOffset
162 )
163 {
164  const label off = (pointOffset + 1); // 1-based for Ensight
165 
166  const label nLists = (offsets.size() - 1);
167 
168  for (label i = 0; i < nLists; ++i)
169  {
170  const labelUList list
171  (
172  values.slice(offsets[i], (offsets[i+i] - offsets[i]))
173  );
174  for (const label pointi : list)
175  {
176  os.write(pointi + off);
177  }
178  os.newline(); // One list (cell/faces) per line (ASCII)
179  }
180 }
181 
182 
184 (
185  ensightGeoFile& os,
186  const UList<face>& faces,
187  const label pointOffset
188 )
189 {
190  ensightOutput::Detail::writeLabelListList(os, faces, pointOffset);
191 }
192 
193 
195 (
196  ensightGeoFile& os,
197  const UIndirectList<face>& faces,
198  const label pointOffset
199 )
200 {
201  ensightOutput::Detail::writeLabelListList(os, faces, pointOffset);
202 }
203 
204 
206 (
207  ensightGeoFile& os,
208  const CompactListList<label>& faces,
209  const label pointOffset
210 )
211 {
212  ensightOutput::Detail::writeLabelListList(os, faces, pointOffset);
213 }
214 
215 
217 (
218  ensightGeoFile& os,
219  const UList<cellShape>& shapes,
220  const label pointOffset
221 )
222 {
223  ensightOutput::Detail::writeLabelListList(os, shapes, pointOffset);
224 }
225 
226 
229 (
230  const polyMesh& mesh,
231  const labelUList& addr,
232  const labelUList& pointMap
233 )
234 {
236  const cellList& meshCells = manifoldCellsMeshObject::New(mesh).cells();
237  const faceList& meshFaces = mesh.faces();
238  const auto& owner = mesh.faceOwner();
239 
240 
241  // The caller should have already checked for possible overflow,
242  // so can skip that here.
243  // but still need the sizing for allocations
244 
245  label nFaces = 0, nPoints = 0;
246  for (const label cellId : addr)
247  {
248  nFaces += meshCells[cellId].size();
249 
250  for (const label faceId : meshCells[cellId])
251  {
252  nPoints += meshFaces[faceId].size();
253  }
254  }
255 
256 
257  CompactListList<label> compact(nFaces, nPoints);
258  labelList& offsets = compact.offsets();
259  labelList& verts = compact.values();
260 
261  // Restart counts
262  nFaces = nPoints = 0;
263 
264  for (const label cellId : addr)
265  {
266  for (const label faceId : meshCells[cellId])
267  {
268  const face& f = meshFaces[faceId];
269 
270  offsets[nFaces++] = nPoints;
271 
272  if (faceId < owner.size() && owner[faceId] != cellId)
273  {
274  // The neighbour of an internal face
275  // - handle like face::reverseFace()
276 
277  verts[nPoints++] = pointMap[f[0]];
278  for (label pti = f.size()-1; pti > 0; --pti)
279  {
280  verts[nPoints++] = pointMap[f[pti]];
281  }
282  }
283  else
284  {
285  for (const label pointi : f)
286  {
287  verts[nPoints++] = pointMap[pointi];
288  }
289  }
290  }
291  }
292 
293  // Finally
294  if (nFaces)
295  {
296  offsets[nFaces] = nPoints;
297  }
298 
299  return compact;
300 }
301 
302 
304 (
305  ensightGeoFile& os,
306  const polyMesh& mesh,
307  const labelUList& addr,
308  const labelUList& pointMap
309 )
310 {
312  const cellList& meshCells = manifoldCellsMeshObject::New(mesh).cells();
313  const faceList& meshFaces = mesh.faces();
314  const auto& owner = mesh.faceOwner();
315 
316  const label off = (1); // 1-based for Ensight
317 
318  for (const label cellId : addr)
319  {
320  for (const label faceId : meshCells[cellId])
321  {
322  const face& f = meshFaces[faceId];
323 
324  if (faceId < owner.size() && owner[faceId] != cellId)
325  {
326  // The neighbour of an internal face
327  // - write as face::reverseFace()
328 
329  os.write(pointMap[f[0]] + off);
330  for (label pti = f.size()-1; pti > 0; --pti)
331  {
332  os.write(pointMap[f[pti]] + off);
333  }
334  }
335  else
336  {
337  for (const label pointi : f)
338  {
339  os.write(pointMap[pointi] + off);
340  }
341  }
342 
343  os.newline(); // One face per line (ASCII)
344  }
345  }
346 }
347 
348 
350 (
351  ensightGeoFile& os,
352  const cellUList& meshCells,
353  const labelUList& addr,
354  const faceUList& meshFaces,
355  const labelUList& owner
356 )
357 {
358  const label off = (1); // 1-based for Ensight
359 
360  for (const label cellId : addr)
361  {
362  for (const label faceId : meshCells[cellId])
363  {
364  const face& f = meshFaces[faceId];
365 
366  if (faceId < owner.size() && owner[faceId] != cellId)
367  {
368  // The neighbour of an internal face
369  // - write as face::reverseFace()
370 
371  os.write(f[0] + off);
372  for (label pti = f.size()-1; pti > 0; --pti)
373  {
374  os.write(f[pti] + off);
375  }
376  }
377  else
378  {
379  for (const label pointi : f)
380  {
381  os.write(pointi + off);
382  }
383  }
384 
385  os.newline(); // One face per line (ASCII)
386  }
387  }
388 }
389 
390 
392 (
393  ensightGeoFile& os,
394  const ensightFaces::elemType etype,
395  const label nTotal,
396  const faceUList& faces,
397  bool parallel
398 )
399 {
400  if (!nTotal)
401  {
402  return;
403  }
404 
405  const IntRange<int> senders =
406  (
407  (parallel && UPstream::parRun())
408  ? UPstream::subProcs()
409  : IntRange<int>()
410  );
411 
412  if (UPstream::master())
413  {
414  os.writeKeyword(ensightFaces::key(etype));
415  os.write(nTotal);
416  os.newline();
417  }
418 
419  if (etype == ensightFaces::elemType::NSIDED)
420  {
421  // Face sizes (number of points per face)
422 
424 
425  if (UPstream::master())
426  {
427  // Main
428  os.writeLabels(sizes);
429 
430  // Others
431  for (int proci : senders)
432  {
434  IPstream::recv(values, proci);
435 
436  os.writeLabels(values);
437  }
438  }
439  else if (senders)
440  {
441  OPstream::send(sizes, UPstream::masterNo());
442  }
443  }
444 
445 
446  // List of points id for each face
447  if (UPstream::master())
448  {
449  // Main
450  writeFaceList(os, faces);
451 
452  // Others
453  for (int proci : senders)
454  {
455  List<face> values;
456  IPstream::recv(values, proci);
457 
458  writeFaceList(os, values);
459  }
460  }
461  else if (senders)
462  {
463  OPstream::send(faces, UPstream::masterNo());
464  }
465 }
466 
467 
469 (
470  ensightGeoFile& os,
471  const ensightFaces::elemType etype,
472  const label nTotal,
473  const UIndirectList<face>& faces,
474  bool parallel
475 )
476 {
477  if (!nTotal)
478  {
479  return;
480  }
481 
482  const IntRange<int> senders =
483  (
484  (parallel && UPstream::parRun())
485  ? UPstream::subProcs()
486  : IntRange<int>()
487  );
488 
489  if (UPstream::master())
490  {
491  os.writeKeyword(ensightFaces::key(etype));
492  os.write(nTotal);
493  os.newline();
494  }
495 
496  if (etype == ensightFaces::elemType::NSIDED)
497  {
498  // Face sizes (number of points per face)
499 
501 
502  if (UPstream::master())
503  {
504  // Main
505  os.writeLabels(send);
506 
507  // Others
508  for (int proci : senders)
509  {
511  IPstream::recv(values, proci);
512 
513  os.writeLabels(values);
514  }
515  }
516  else if (senders)
517  {
518  OPstream::send(send, UPstream::masterNo());
519  }
520  }
521 
522 
523  // List of points id per face
524 
525  if (UPstream::master())
526  {
527  // Main
528  writeFaceList(os, faces);
529 
530  // Others
531  for (int proci : senders)
532  {
533  List<face> values;
534  IPstream::recv(values, proci);
535 
536  writeFaceList(os, values);
537  }
538  }
539  else if (senders)
540  {
541  OPstream::send(faces, UPstream::masterNo());
542  }
543 }
544 
545 
547 (
548  ensightGeoFile& os,
549  const ensightFaces& part,
550  const faceUList& faces,
551  bool parallel
552 )
553 {
554  for (int typei = 0; typei < ensightFaces::nTypes; ++typei)
555  {
556  const auto etype = ensightFaces::elemType(typei);
557 
559  (
560  os,
561  etype,
562  part.total(etype),
563  UIndirectList<face>(faces, part.faceIds(etype)),
564  parallel
565  );
566  }
567 }
568 
569 
571 (
572  ensightGeoFile& os,
573  const ensightFaces& part,
574  const faceUList& faces,
575  bool parallel
576 )
577 {
578  for (int typei = 0; typei < ensightFaces::nTypes; ++typei)
579  {
580  const auto etype = ensightFaces::elemType(typei);
581 
583  (
584  os,
585  etype,
586  part.total(etype),
587  SubList<face>(faces, part.range(etype)),
588  parallel
589  );
590  }
591 }
592 
593 
594 // ************************************************************************* //
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:119
label faceId(-1)
registerDebugSwitchWithName(Foam::ensightOutput, ensightOutput, "ensight")
List< cell > cellList
List of cell.
Definition: cellListFwd.H:39
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:68
void writeFaceConnectivity(ensightGeoFile &os, const ensightFaces::elemType etype, const label nTotal, const UIndirectList< face > &faces, bool parallel)
Write the regular face connectivity for specified type and and specified faces.
A variant of ensightFile (Ensight writing) that includes the extra geometry file header information...
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.
void writeFaceConnectivityPresorted(ensightGeoFile &os, const ensightFaces &part, const faceUList &faces, bool parallel)
Write the presorted face connectivity for the part.
labelList getPolysNPointsPerFace(const polyMesh &mesh, const labelUList &addr)
The number of points for each face of the poly elements.
void writeFaceList(ensightGeoFile &os, const UList< face > &faces, const label pointOffset=0)
Write list of faces.
UList< label > labelUList
A UList of labels.
Definition: UList.H:76
Various functions to operate on Lists.
List< face > faceList
List of faces.
Definition: faceListFwd.H:39
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
Definition: HashOps.H:164
UList< cell > cellUList
UList of cell.
Definition: cellListFwd.H:43
dynamicFvMesh & mesh
UList< face > faceUList
UList of faces.
Definition: faceListFwd.H:43
label nPoints
CompactListList< label > getPolysFacePoints(const polyMesh &mesh, const labelUList &addr, const labelUList &pointMap)
Generate 0-based point ids for each poly element face.
registerOptSwitch("ensight.maxChunk", int, Foam::ensightOutput::maxChunk_)
label size() const noexcept
The number of elements in the list.
A collection of functions for writing ensight file content.
iterator begin() noexcept
Return an iterator to begin traversing the UList.
Definition: UListI.H:403
A packed storage of objects of type <T> using an offset table for access.
int optimisationSwitch(const char *name, const int deflt=0)
Lookup optimisation switch or add default value.
Definition: debug.C:234
void writePolysPoints(ensightGeoFile &os, const cellUList &meshCells, const labelUList &addr, const faceUList &meshFaces, const labelUList &faceOwner)
Write the point ids per poly element.
labelList f(nPoints)
constexpr auto key(const Type &t) noexcept
Helper function to return the enum value.
Definition: foamGltfBase.H:105
virtual bool write(const token &) override
Writing token does not make sense.
Definition: ensightFile.H:311
void newline()
Add carriage return to ascii stream.
Definition: ensightFile.C:403
labelList getPolysNFaces(const polyMesh &mesh, const labelUList &addr)
The number of faces per poly element.
Definition: ensightOutput.C:90
void writeLabelListList(ensightGeoFile &os, const labelUList &offsets, const labelUList &values, const label pointOffset)
Write CompactListList<label> by components.
Macro definitions for debug switches.
labelList getFaceSizes(const UList< face > &faces)
Return sizes of faces in the list.
Definition: ensightOutput.C:52
A List with indirect addressing. Like IndirectList but does not store addressing. ...
Definition: faMatrix.H:52
label cellId
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:76
int maxChunk_
Upper limit on number of items for bundled off-processor field transfers. The component-wise transfer...
List< label > labelList
A List of labels.
Definition: List.H:61
defineDebugSwitchWithName(Foam::ensightOutput, "ensight", 0)
void writeCellShapes(ensightGeoFile &os, const UList< cellShape > &shapes, const label pointOffset=0)
Write cell connectivity via cell shapes.