foamVtkPolyWriter.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) 2018-2021 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 "foamVtkPolyWriter.H"
29 #include "foamVtkOutput.H"
30 #include "globalIndex.H"
31 
32 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
33 
34 namespace Foam
35 {
36 
37 // The connectivity count for a list of edges
38 static inline label countConnectivity(const edgeList& edges)
39 {
40  return 2 * edges.size(); // An edge always has two ends
41 }
42 
43 
44 // The connectivity count for a list of faces
45 static label countConnectivity(const faceList& faces)
46 {
47  label nConnectivity = 0;
48 
49  for (const face& f : faces)
50  {
51  nConnectivity += f.size();
52  }
53 
54  return nConnectivity;
55 }
56 
57 } // End namespace Foam
58 
59 
60 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
61 
62 void Foam::vtk::polyWriter::beginPiece
63 (
64  const pointField& points,
65  const edgeList& edges
66 )
67 {
68  // Basic sizes
69  nLocalPoints_ = points.size();
70  nLocalVerts_ = 0;
71  nLocalLines_ = edges.size();
72  nLocalPolys_ = 0;
73 
76 
77  if (parallel_)
78  {
79  reduce(numberOfPoints_, sumOp<label>());
80  reduce(numberOfCells_, sumOp<label>());
81  }
82 
83 
84  // Nothing else to do for legacy
85  if (legacy()) return;
86 
87  if (format_)
88  {
89  format().tag
90  (
94  // AND: vtk::fileAttr::NUMBER_OF_POLYS, 0
95  );
96  }
97 }
98 
99 
100 void Foam::vtk::polyWriter::beginPiece
101 (
102  const pointField& points,
103  const faceList& faces
104 )
105 {
106  // Basic sizes
107  nLocalPoints_ = points.size();
108  nLocalVerts_ = 0;
109  nLocalLines_ = 0;
110  nLocalPolys_ = faces.size();
111 
112  numberOfPoints_ = nLocalPoints_;
113  numberOfCells_ = nLocalPolys_;
114 
115  if (parallel_)
116  {
117  reduce(numberOfPoints_, sumOp<label>());
118  reduce(numberOfCells_, sumOp<label>());
119  }
120 
121 
122  // Nothing else to do for legacy
123  if (legacy()) return;
124 
125  if (format_)
126  {
127  format().tag
128  (
130  vtk::fileAttr::NUMBER_OF_POINTS, numberOfPoints_,
131  vtk::fileAttr::NUMBER_OF_POLYS, numberOfCells_
132  // AND: vtk::fileAttr::NUMBER_OF_LINES, 0
133  );
134  }
135 }
136 
137 
138 void Foam::vtk::polyWriter::writePoints
139 (
140  const pointField& points
141 )
142 {
143  this->beginPoints(numberOfPoints_);
144 
145  if (parallel_)
146  {
147  vtk::writeListParallel(format_.ref(), points);
148  }
149  else
150  {
152 
153  }
154 
155  this->endPoints();
156 }
157 
158 
159 void Foam::vtk::polyWriter::writeLinesLegacy
160 (
161  const edgeList& edges,
162  const label pointOffset
163 )
164 {
165  // Connectivity count without additional storage (done internally)
166  const label nLocalConns = countConnectivity(edges);
167 
168  label nLines = nLocalLines_;
169  label nConns = nLocalConns;
170 
171  if (parallel_)
172  {
173  reduce(nLines, sumOp<label>());
174  reduce(nConns, sumOp<label>());
175  }
176 
177  if (nLines != numberOfCells_)
178  {
180  << "Expecting " << numberOfCells_
181  << " edges, but found " << nLines
182  << exit(FatalError);
183  }
184 
185  legacy::beginLines(os_, nLines, nConns);
186 
187  labelList vertLabels(nLocalLines_ + nLocalConns);
188 
189  {
190  // Legacy: size + connectivity together
191  // [nPts, id1, id2, ..., nPts, id1, id2, ...]
192 
193  auto iter = vertLabels.begin();
194 
195  const label off = pointOffset;
196 
197  for (const edge& e : edges)
198  {
199  *iter = e.size(); // The size prefix (always 2 for an edge)
200  ++iter;
201 
202  *iter = off + e.first(); // Vertex labels
203  ++iter;
204 
205  *iter = off + e.second();
206  ++iter;
207  }
208  }
209 
210 
211  if (parallel_)
212  {
213  vtk::writeListParallel(format_.ref(), vertLabels);
214  }
215  else
216  {
217  vtk::writeList(format(), vertLabels);
218  }
219 
220  if (format_)
221  {
222  format().flush();
223  }
224 }
225 
226 
227 void Foam::vtk::polyWriter::writeLines
228 (
229  const edgeList& edges,
230  const label pointOffset
231 )
232 {
233  // Connectivity count without additional storage (done internally)
234  const label nLocalConns = countConnectivity(edges);
235 
236  if (format_)
237  {
239  }
240 
241  //
242  // 'connectivity'
243  //
244  {
245  labelList vertLabels(nLocalConns);
246 
247  label nConns = nLocalConns;
248 
249  if (parallel_)
250  {
251  reduce(nConns, sumOp<label>());
252  }
253 
254  if (format_)
255  {
256  const uint64_t payLoad = vtk::sizeofData<label>(nConns);
257 
258  format().beginDataArray<label>(vtk::dataArrayAttr::CONNECTIVITY);
259  format().writeSize(payLoad * sizeof(label));
260  }
261 
262  {
263  // XML: connectivity only
264  // [id1, id2, ..., id1, id2, ...]
265 
266  auto iter = vertLabels.begin();
267 
268  const label off = pointOffset;
269 
270  for (const edge& e : edges)
271  {
272  // Edge vertex labels
273  *iter = off + e.first();
274  ++iter;
275 
276  *iter = off + e.second();
277  ++iter;
278  }
279  }
280 
281 
282  if (parallel_)
283  {
284  vtk::writeListParallel(format_.ref(), vertLabels);
285  }
286  else
287  {
288  vtk::writeList(format(), vertLabels);
289  }
290 
291  if (format_)
292  {
293  format().flush();
294  format().endDataArray();
295  }
296  }
297 
298 
299  //
300  // 'offsets' (connectivity offsets)
301  //
302  {
303  labelList vertOffsets(nLocalLines_);
304  label nOffs = vertOffsets.size();
305 
306  if (parallel_)
307  {
308  reduce(nOffs, sumOp<label>());
309  }
310 
311  if (format_)
312  {
313  const uint64_t payLoad = vtk::sizeofData<label>(nOffs);
314 
315  format().beginDataArray<label>(vtk::dataArrayAttr::OFFSETS);
316  format().writeSize(payLoad);
317  }
318 
319 
320  // processor-local connectivity offsets
321  label off =
322  (
323  parallel_ ? globalIndex(nLocalConns).localStart() : 0
324  );
325 
326 
327  auto iter = vertOffsets.begin();
328 
329  for (const edge& e : edges)
330  {
331  off += e.size(); // End offset
332  *iter = off;
333  ++iter;
334  }
335 
336 
337  if (parallel_)
338  {
339  vtk::writeListParallel(format_.ref(), vertOffsets);
340  }
341  else
342  {
343  vtk::writeList(format_.ref(), vertOffsets);
344  }
345 
346 
347  if (format_)
348  {
349  format().flush();
350  format().endDataArray();
351  }
352  }
353 
354  if (format_)
355  {
356  format().endTag(vtk::fileTag::LINES);
357  }
358 }
359 
360 
361 void Foam::vtk::polyWriter::writePolysLegacy
362 (
363  const faceList& faces,
364  const label pointOffset
365 )
366 {
367  // Connectivity count without additional storage (done internally)
368  const label nLocalConns = countConnectivity(faces);
369 
370  label nPolys = nLocalPolys_;
371  label nConns = nLocalConns;
372 
373  if (parallel_)
374  {
375  reduce(nPolys, sumOp<label>());
376  reduce(nConns, sumOp<label>());
377  }
378 
379  if (nPolys != numberOfCells_)
380  {
382  << "Expecting " << numberOfCells_
383  << " faces, but found " << nPolys
384  << exit(FatalError);
385  }
386 
387  legacy::beginPolys(os_, nPolys, nConns);
388 
389  labelList vertLabels(nLocalPolys_ + nLocalConns);
390 
391  {
392  // Legacy: size + connectivity together
393  // [nPts, id1, id2, ..., nPts, id1, id2, ...]
394 
395  auto iter = vertLabels.begin();
396 
397  const label off = pointOffset;
398 
399  for (const face& f : faces)
400  {
401  *iter = f.size(); // The size prefix
402  ++iter;
403 
404  for (const label id : f)
405  {
406  *iter = id + off; // Vertex label
407  ++iter;
408  }
409  }
410  }
411 
412 
413  if (parallel_)
414  {
415  vtk::writeListParallel(format_.ref(), vertLabels);
416  }
417  else
418  {
419  vtk::writeList(format(), vertLabels);
420  }
421 
422  if (format_)
423  {
424  format().flush();
425  }
426 }
427 
428 
429 void Foam::vtk::polyWriter::writePolys
430 (
431  const faceList& faces,
432  const label pointOffset
433 )
434 {
435  // Connectivity count without additional storage (done internally)
436  const label nLocalConns = countConnectivity(faces);
437 
438  if (format_)
439  {
441  }
442 
443  //
444  // 'connectivity'
445  //
446  {
447  labelList vertLabels(nLocalConns);
448 
449  label nConns = nLocalConns;
450 
451  if (parallel_)
452  {
453  reduce(nConns, sumOp<label>());
454  }
455 
456  if (format_)
457  {
458  const uint64_t payLoad = vtk::sizeofData<label>(nConns);
459 
460  format().beginDataArray<label>(vtk::dataArrayAttr::CONNECTIVITY);
461  format().writeSize(payLoad * sizeof(label));
462  }
463 
464  {
465  // XML: connectivity only
466  // [id1, id2, ..., id1, id2, ...]
467 
468  auto iter = vertLabels.begin();
469 
470  label off = pointOffset;
471 
472  for (const face& f : faces)
473  {
474  for (const label id : f)
475  {
476  *iter = id + off; // Face vertex label
477  ++iter;
478  }
479  }
480  }
481 
482 
483  if (parallel_)
484  {
485  vtk::writeListParallel(format_.ref(), vertLabels);
486  }
487  else
488  {
489  vtk::writeList(format(), vertLabels);
490  }
491 
492  if (format_)
493  {
494  format().flush();
495  format().endDataArray();
496  }
497  }
498 
499 
500  //
501  // 'offsets' (connectivity offsets)
502  //
503  {
504  labelList vertOffsets(nLocalPolys_);
505  label nOffs = vertOffsets.size();
506 
507  if (parallel_)
508  {
509  reduce(nOffs, sumOp<label>());
510  }
511 
512  if (format_)
513  {
514  const uint64_t payLoad = vtk::sizeofData<label>(nOffs);
515 
516  format().beginDataArray<label>(vtk::dataArrayAttr::OFFSETS);
517  format().writeSize(payLoad);
518  }
519 
520 
521  // processor-local connectivity offsets
522  label off =
523  (
524  parallel_ ? globalIndex(nLocalConns).localStart() : 0
525  );
526 
527 
528  auto iter = vertOffsets.begin();
529 
530  for (const face& f : faces)
531  {
532  off += f.size(); // End offset
533  *iter = off;
534  ++iter;
535  }
536 
537 
538  if (parallel_)
539  {
540  vtk::writeListParallel(format_.ref(), vertOffsets);
541  }
542  else
543  {
544  vtk::writeList(format_.ref(), vertOffsets);
545  }
546 
547 
548  if (format_)
549  {
550  format().flush();
551  format().endDataArray();
552  }
553  }
554 
555  if (format_)
556  {
557  format().endTag(vtk::fileTag::POLYS);
558  }
559 }
560 
561 
562 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
563 
564 Foam::vtk::polyWriter::polyWriter
565 (
566  const vtk::outputOptions opts
567 )
568 :
569  vtk::fileWriter(vtk::fileTag::POLY_DATA, opts),
570  numberOfPoints_(0),
571  numberOfCells_(0),
572  nLocalPoints_(0),
573  nLocalVerts_(0),
574  nLocalLines_(0),
575  nLocalPolys_(0)
576 {
577  // We do not currently support append mode
578  opts_.append(false);
579 }
580 
581 
582 Foam::vtk::polyWriter::polyWriter
583 (
584  const fileName& file,
585  bool parallel
586 )
587 :
588  // Default parameter fails for gcc-4.8.5, thus specify format here
590 {
591  open(file, parallel);
592 }
593 
594 
595 Foam::vtk::polyWriter::polyWriter
596 (
597  const vtk::outputOptions opts,
598  const fileName& file,
599  bool parallel
600 )
601 :
602  polyWriter(opts)
603 {
604  open(file, parallel);
605 }
606 
607 
608 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
609 
611 {
613  << "Method was not overloaded, called without a geometry!!" << nl
614  << " Indicates a programming error" << nl << endl
616 
617  return false;
618 }
619 
620 
622 (
623  const pointField& points,
624  const edgeList& edges
625 )
626 {
627  enter_Piece();
628 
629  beginPiece(points, edges);
630 
631  writePoints(points);
632 
633  const label pointOffset =
634  (
635  parallel_ ? globalIndex(nLocalPoints_).localStart() : 0
636  );
637 
638  if (legacy())
639  {
640  writeLinesLegacy(edges, pointOffset);
641  }
642  else
643  {
644  writeLines(edges, pointOffset);
645  }
646 
647  return true;
648 }
649 
650 
652 (
653  const pointField& points,
654  const faceList& faces
655 )
656 {
657  enter_Piece();
658 
659  beginPiece(points, faces);
660 
661  writePoints(points);
662 
663  const label pointOffset =
664  (
665  parallel_ ? globalIndex(nLocalPoints_).localStart() : 0
666  );
667 
668  if (legacy())
669  {
670  writePolysLegacy(faces, pointOffset);
671  }
672  else
673  {
674  writePolys(faces, pointOffset);
675  }
676 
677  return true;
678 }
679 
681 bool Foam::vtk::polyWriter::beginCellData(label nFields)
682 {
683  return enter_CellData(numberOfCells_, nFields);
684 }
685 
686 
687 bool Foam::vtk::polyWriter::beginPointData(label nFields)
688 {
689  return enter_PointData(numberOfPoints_, nFields);
690 }
691 
692 
693 // ************************************************************************* //
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
autoPtr< vtk::formatter > format_
The VTK formatter in use (only valid on master process)
A class for handling file names.
Definition: fileName.H:72
label nLocalVerts_
Local number of vertices (points)
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
vtk::formatter & format()
The VTK formatter in use. FatalError for off-processor.
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
List< edge > edgeList
List of edge.
Definition: edgeList.H:32
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
virtual bool writeGeometry()
Dummy write mesh topology method - Fatal if called.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
void beginPolys(std::ostream &os, label nPolys, label nConnectivity)
Emit header for POLYGONS (with trailing newline).
label numberOfPoints_
The number of field points for the current Piece.
bool parallel_
Parallel writing (via master)
bool legacy() const noexcept
Commonly used query.
Encapsulated combinations of output format options. This is primarily useful when defining the output...
List< face > faceList
List of faces.
Definition: faceListFwd.H:39
void beginPoints(std::ostream &os, label nPoints)
Emit header for POINTS (with trailing newline).
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:61
label nLocalLines_
Local number of lines (edges)
virtual bool beginPointData(label nFields=0)
Begin PointData for specified number of fields.
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
const pointField & points
formatType
The output format type for file contents.
Definition: foamVtkCore.H:66
label nLocalPoints_
Local number of points.
errorManip< error > abort(error &err)
Definition: errorManip.H:139
void beginLines(std::ostream &os, label nLines, label nConnectivity=0)
Emit header for LINES (with trailing newline).
virtual bool beginCellData(label nFields=0)
Begin CellData output section for specified number of fields.
void writeList(vtk::formatter &fmt, const UList< uint8_t > &values)
Write a list of uint8_t values.
labelList f(nPoints)
word format(conversionProperties.get< word >("format"))
fileTag
Some common XML tags for vtk files.
Definition: foamVtkCore.H:122
bool writePolyGeometry(const pointField &points, const faceList &faces)
Low-level write face/point topology. Normally used by writeGeometry() in a derived class...
label nLocalPolys_
Local number of polys (faces)
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
Reduce inplace (cf. MPI Allreduce) using specified communication schedule.
label localStart(const label proci) const
Start of proci data.
Definition: globalIndexI.H:233
void writeListParallel(vtk::formatter &fmt, const UList< Type > &values)
Write a list of values.
Write faces/points (optionally with fields) as a vtp file or a legacy vtk file.
XML inline base64, base64Formatter.
bool writeLineGeometry(const pointField &points, const edgeList &edges)
Low-level write edge/point topology. Normally used by writeGeometry() in a derived class...
List< label > labelList
A List of labels.
Definition: List.H:62
static label countConnectivity(const edgeList &edges)
formatter & tag(const word &t, Args &&... args)
Write XML tag without any attributes. Combines openTag/closeTag.
label numberOfCells_
The number of field cells (edges or faces) for the current Piece.
Namespace for OpenFOAM.