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 -------------------------------------------------------------------------------
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 "ensightOutput.H"
29 #include "cell.H"
30 #include "cellShape.H"
31 #include "face.H"
32 #include "polyMesh.H"
33 #include "ListOps.H"
35 #include "debug.H"
36 #include "defineDebugSwitch.H"
37 #include "registerSwitch.H"
38 
39 // * * * * * * * * * * * * * * * * Globals * * * * * * * * * * * * * * * * * //
40 
42 
43 registerDebugSwitchWithName(Foam::ensightOutput, ensightOutput, "ensight");
44 
46 (
47  Foam::debug::optimisationSwitch("ensight.maxChunk", 0)
48 );
49 
50 registerOptSwitch("ensight.maxChunk", int, Foam::ensightOutput::maxChunk_);
51 
52 
53 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
54 
55 // Sizes
56 
58 (
59  const UList<face>& faces
60 )
61 {
62  labelList list(faces.size());
63 
64  auto outIter = list.begin();
65 
66  for (const face& f : faces)
67  {
68  *outIter = f.size();
69  ++outIter;
70  }
71 
72  return list;
73 }
74 
75 
77 (
78  const UIndirectList<face>& faces
79 )
80 {
81  labelList list(faces.size());
82 
83  auto outIter = list.begin();
84 
85  for (const face& f : faces)
86  {
87  *outIter = f.size();
88  ++outIter;
89  }
90 
91  return list;
92 }
93 
94 
96 (
97  const polyMesh& mesh,
98  const labelUList& addr
99 )
100 {
102  const cellList& meshCells = manifoldCellsMeshObject::New(mesh).cells();
103 
104  labelList list(addr.size());
105 
106  auto outIter = list.begin();
107 
108  // The number of faces per element
109  for (const label cellId : addr)
110  {
111  *outIter = meshCells[cellId].size();
112  ++outIter;
113  }
114 
115  return list;
116 }
117 
118 
120 (
121  const polyMesh& mesh,
122  const labelUList& addr
123 )
124 {
126  const cellList& meshCells = manifoldCellsMeshObject::New(mesh).cells();
127  const faceList& meshFaces = mesh.faces();
128 
129  // Count the number of faces per element
130 
131  label nTotFaces = 0;
132  for (const label cellId : addr)
133  {
134  nTotFaces += meshCells[cellId].size();
135  }
136 
137  labelList list(nTotFaces);
138 
139  auto outIter = list.begin();
140 
141  // The number of points per element face
142  for (const label cellId : addr)
143  {
144  for (const label facei : meshCells[cellId])
145  {
146  *outIter = meshFaces[facei].size();
147  ++outIter;
148  }
149  }
150 
151  return list;
152 }
153 
154 
156 (
158  const labelUList& offsets,
159  const labelUList& values,
160  const label pointOffset
161 )
162 {
163  const label off = (pointOffset + 1); // 1-based for Ensight
164 
165  const label nLists = (offsets.size() - 1);
166 
167  for (label i = 0; i < nLists; ++i)
168  {
169  const labelUList list
170  (
171  values.slice(offsets[i], (offsets[i+i] - offsets[i]))
172  );
173  for (const label pointi : list)
174  {
175  os.write(pointi + off);
176  }
177  os.newline(); // One list (cell/faces) per line (ASCII)
178  }
179 }
180 
181 
183 (
184  ensightGeoFile& os,
185  const UList<face>& faces,
186  const label pointOffset
187 )
188 {
189  ensightOutput::Detail::writeLabelListList(os, faces, pointOffset);
190 }
191 
192 
194 (
196  const UIndirectList<face>& faces,
197  const label pointOffset
198 )
199 {
200  ensightOutput::Detail::writeLabelListList(os, faces, pointOffset);
201 }
202 
203 
205 (
207  const CompactListList<label>& faces,
208  const label pointOffset
209 )
210 {
211  ensightOutput::Detail::writeLabelListList(os, faces, pointOffset);
212 }
213 
214 
216 (
218  const UList<cellShape>& shapes,
219  const label pointOffset
220 )
221 {
222  ensightOutput::Detail::writeLabelListList(os, shapes, pointOffset);
223 }
224 
225 
228 (
229  const polyMesh& mesh,
230  const labelUList& addr,
231  const labelList& pointMap
232 )
233 {
235  const cellList& meshCells = manifoldCellsMeshObject::New(mesh).cells();
236  const faceList& meshFaces = mesh.faces();
237  const labelList& owner = mesh.faceOwner();
238 
239 
240  // The caller should have already checked for possible overflow,
241  // so can skip that here.
242  // but still need the sizing for allocations
243 
244  label nFaces = 0, nPoints = 0;
245  for (const label cellId : addr)
246  {
247  nFaces += meshCells[cellId].size();
248 
249  for (const label faceId : meshCells[cellId])
250  {
251  nPoints += meshFaces[faceId].size();
252  }
253  }
254 
255 
256  CompactListList<label> compact(nFaces, nPoints);
257  labelList& offsets = compact.offsets();
258  labelList& verts = compact.values();
259 
260  // Restart counts
261  nFaces = nPoints = 0;
262 
263  for (const label cellId : addr)
264  {
265  for (const label faceId : meshCells[cellId])
266  {
267  const face& f = meshFaces[faceId];
268 
269  offsets[nFaces++] = nPoints;
270 
271  if (faceId < owner.size() && owner[faceId] != cellId)
272  {
273  // The neighbour of an internal face
274  // - handle like face::reverseFace()
275 
276  verts[nPoints++] = pointMap[f[0]];
277  for (label pti = f.size()-1; pti > 0; --pti)
278  {
279  verts[nPoints++] = pointMap[f[pti]];
280  }
281  }
282  else
283  {
284  for (const label pointi : f)
285  {
286  verts[nPoints++] = pointMap[pointi];
287  }
288  }
289  }
290  }
291 
292  // Finally
293  if (nFaces)
294  {
295  offsets[nFaces] = nPoints;
296  }
297 
298  return compact;
299 }
300 
301 
303 (
304  ensightGeoFile& os,
305  const polyMesh& mesh,
306  const labelUList& addr,
307  const labelList& pointMap
308 )
309 {
311  const cellList& meshCells = manifoldCellsMeshObject::New(mesh).cells();
312  const faceList& meshFaces = mesh.faces();
313  const labelList& owner = mesh.faceOwner();
314 
315  const label off = (1); // 1-based for Ensight
316 
317  for (const label cellId : addr)
318  {
319  for (const label faceId : meshCells[cellId])
320  {
321  const face& f = meshFaces[faceId];
322 
323  if (faceId < owner.size() && owner[faceId] != cellId)
324  {
325  // The neighbour of an internal face
326  // - write as face::reverseFace()
327 
328  os.write(pointMap[f[0]] + off);
329  for (label pti = f.size()-1; pti > 0; --pti)
330  {
331  os.write(pointMap[f[pti]] + off);
332  }
333  }
334  else
335  {
336  for (const label pointi : f)
337  {
338  os.write(pointMap[pointi] + off);
339  }
340  }
341 
342  os.newline(); // One face per line (ASCII)
343  }
344  }
345 }
346 
347 
349 (
350  ensightGeoFile& os,
351  const cellUList& meshCells,
352  const labelUList& addr,
353  const faceUList& meshFaces,
354  const labelUList& owner
355 )
356 {
357  const label off = (1); // 1-based for Ensight
358 
359  for (const label cellId : addr)
360  {
361  for (const label faceId : meshCells[cellId])
362  {
363  const face& f = meshFaces[faceId];
364 
365  if (faceId < owner.size() && owner[faceId] != cellId)
366  {
367  // The neighbour of an internal face
368  // - write as face::reverseFace()
369 
370  os.write(f[0] + off);
371  for (label pti = f.size()-1; pti > 0; --pti)
372  {
373  os.write(f[pti] + off);
374  }
375  }
376  else
377  {
378  for (const label pointi : f)
379  {
380  os.write(pointi + off);
381  }
382  }
383 
384  os.newline(); // One face per line (ASCII)
385  }
386  }
387 }
388 
389 
391 (
392  ensightGeoFile& os,
393  const ensightFaces::elemType etype,
394  const label nTotal,
395  const faceUList& faces,
396  bool parallel
397 )
398 {
399  if (!nTotal)
400  {
401  return;
402  }
403 
404  parallel = parallel && Pstream::parRun();
405 
406  const IntRange<int> senders =
407  (
408  parallel
409  ? Pstream::subProcs()
410  : IntRange<int>()
411  );
412 
413  if (Pstream::master())
414  {
415  os.writeKeyword(ensightFaces::key(etype));
416  os.write(nTotal);
417  os.newline();
418  }
419 
420  if (etype == ensightFaces::elemType::NSIDED)
421  {
422  // Face sizes (number of points per face)
423 
425 
426  if (Pstream::master())
427  {
428  // Main
429  os.writeLabels(send);
430 
431  // Others
432  for (const int proci : senders)
433  {
434  IPstream fromOther(Pstream::commsTypes::scheduled, proci);
435  labelList recv(fromOther);
436 
437  os.writeLabels(recv);
438  }
439  }
440  else if (senders)
441  {
442  OPstream toMaster
443  (
444  Pstream::commsTypes::scheduled,
445  Pstream::masterNo()
446  );
447 
448  toMaster << send;
449  }
450  }
451 
452 
453  // List of points id for each face
454  if (Pstream::master())
455  {
456  // Main
457  writeFaceList(os, faces);
458 
459  // Others
460  for (const int proci : senders)
461  {
462  IPstream fromOther(Pstream::commsTypes::scheduled, proci);
463  List<face> recv(fromOther);
464 
465  writeFaceList(os, recv);
466  }
467  }
468  else if (senders)
469  {
470  OPstream toMaster
471  (
472  Pstream::commsTypes::scheduled,
473  Pstream::masterNo()
474  );
476  toMaster << faces;
477  }
478 }
479 
480 
482 (
483  ensightGeoFile& os,
484  const ensightFaces::elemType etype,
485  const label nTotal,
486  const UIndirectList<face>& faces,
487  bool parallel
488 )
489 {
490  if (!nTotal)
491  {
492  return;
493  }
494 
495  parallel = parallel && Pstream::parRun();
496 
497  const IntRange<int> senders =
498  (
499  parallel
500  ? Pstream::subProcs()
501  : IntRange<int>()
502  );
503 
504 
505  if (Pstream::master())
506  {
507  os.writeKeyword(ensightFaces::key(etype));
508  os.write(nTotal);
509  os.newline();
510  }
511 
512  if (etype == ensightFaces::elemType::NSIDED)
513  {
514  // Face sizes (number of points per face)
515 
517 
518  if (Pstream::master())
519  {
520  // Main
521  os.writeLabels(send);
522 
523  // Others
524  for (const int proci : senders)
525  {
526  IPstream fromOther(Pstream::commsTypes::scheduled, proci);
527  labelList recv(fromOther);
528 
529  os.writeLabels(recv);
530  }
531  }
532  else if (senders)
533  {
534  OPstream toMaster
535  (
536  Pstream::commsTypes::scheduled,
537  Pstream::masterNo()
538  );
539 
540  toMaster << send;
541  }
542  }
543 
544 
545  // List of points id per face
546 
547  if (Pstream::master())
548  {
549  // Main
550  writeFaceList(os, faces);
551 
552  // Others
553  for (const int proci : senders)
554  {
555  IPstream fromOther(Pstream::commsTypes::scheduled, proci);
556  List<face> recv(fromOther);
557 
558  writeFaceList(os, recv);
559  }
560  }
561  else if (senders)
562  {
563  OPstream toMaster
564  (
565  Pstream::commsTypes::scheduled,
566  Pstream::masterNo()
567  );
569  toMaster << faces;
570  }
571 }
572 
573 
575 (
576  ensightGeoFile& os,
577  const ensightFaces& part,
578  const faceUList& faces,
579  bool parallel
580 )
581 {
582  for (label typei=0; typei < ensightFaces::nTypes; ++typei)
583  {
584  const auto etype = ensightFaces::elemType(typei);
585 
587  (
588  os,
589  etype,
590  part.total(etype),
591  UIndirectList<face>(faces, part.faceIds(etype)),
592  parallel
593  );
594  }
595 }
596 
597 
599 (
600  ensightGeoFile& os,
601  const ensightFaces& part,
602  const faceUList& faces,
603  bool parallel
604 )
605 {
606  for (label typei=0; typei < ensightFaces::nTypes; ++typei)
607  {
608  const auto etype = ensightFaces::elemType(typei);
609 
611  (
612  os,
613  etype,
614  part.total(etype),
615  SubList<face>(faces, part.range(etype)),
616  parallel
617  );
618  }
619 }
620 
621 
622 // ************************************************************************* //
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
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.
Specialized Ensight output with extra geometry file header.
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:78
Various functions to operate on Lists.
CompactListList< label > getPolysFacePoints(const polyMesh &mesh, const labelUList &addr, const labelList &pointMap)
Generate 0-based point ids for each poly element face.
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
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:391
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.
OBJstream os(runTime.globalPath()/outputName)
labelList f(nPoints)
labelList getPolysNFaces(const polyMesh &mesh, const labelUList &addr)
The number of faces per poly element.
Definition: ensightOutput.C:89
void writeLabelListList(ensightGeoFile &os, const labelUList &offsets, const labelUList &values, const label pointOffset)
Write CompactListList<label> by components.
auto key(const Type &t) -> typename std::enable_if< std::is_enum< Type >::value, typename std::underlying_type< Type >::type >::type
Definition: foamGltfBase.H:103
Macro definitions for debug switches.
labelList getFaceSizes(const UList< face > &faces)
Return sizes of faces in the list.
Definition: ensightOutput.C:51
A List with indirect addressing. Like IndirectList but does not store addressing. ...
Definition: faMatrix.H:56
label cellId
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
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:62
defineDebugSwitchWithName(Foam::ensightOutput, "ensight", 0)
void writeCellShapes(ensightGeoFile &os, const UList< cellShape > &shapes, const label pointOffset=0)
Write cell connectivity via cell shapes.