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