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-------------------------------------------------------------------------------
10License
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
34namespace Foam
35{
36
37// The connectivity count for a list of edges
38static 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
45static 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
62void Foam::vtk::polyWriter::beginPiece
63(
64 const pointField& points,
65 const edgeList& edges
66)
67{
68 // Basic sizes
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
100void 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
138void 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
159void 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
227void 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
361void 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
429void 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
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
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
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
615 << abort(FatalError);
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
680
682{
683 return enter_CellData(numberOfCells_, nFields);
684}
685
686
688{
689 return enter_PointData(numberOfPoints_, nFields);
690}
691
692
693// ************************************************************************* //
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
A class for handling file names.
Definition: fileName.H:76
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:68
label localStart() const
My local start.
Definition: globalIndexI.H:195
Base class for VTK output writers that handle geometry and fields (eg, vtp, vtu data)....
bool legacy() const noexcept
Commonly used query.
autoPtr< vtk::formatter > format_
The VTK formatter in use (only valid on master process)
bool parallel_
Parallel writing (via master)
bool parallel() const noexcept
Parallel output requested?
vtk::outputOptions opts_
Requested output options.
virtual bool open(const fileName &file, bool parallel=Pstream::parRun())
Open file for writing (creates parent directory).
vtk::formatter & format()
The VTK formatter in use. FatalError for off-processor.
formatter & beginPointData()
Begin "PointData" XML section.
formatter & tag(const word &t, Args &&... args)
Write XML tag without any attributes. Combines openTag/closeTag.
formatter & beginCellData()
Begin "CellData" XML section.
Encapsulated combinations of output format options. This is primarily useful when defining the output...
bool append() const noexcept
True if output format uses an append mode.
Write faces/points (optionally with fields) as a vtp file or a legacy vtk file.
label nLocalLines_
Local number of lines (edges)
label nLocalPolys_
Local number of polys (faces)
bool writeLineGeometry(const pointField &points, const edgeList &edges)
bool writePolyGeometry(const pointField &points, const faceList &faces)
label numberOfPoints_
The number of field points for the current Piece.
label nLocalPoints_
Local number of points.
label nLocalVerts_
Local number of vertices (points)
label numberOfCells_
The number of field cells (edges or faces) for the current Piece.
virtual bool writeGeometry()
Dummy write mesh topology method - Fatal if called.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
const pointField & points
void beginPolys(std::ostream &os, label nPolys, label nConnectivity)
Emit header for POLYGONS (with trailing newline).
void beginLines(std::ostream &os, label nLines, label nConnectivity=0)
Emit header for LINES (with trailing newline).
void beginPoints(std::ostream &os, label nPoints)
Emit header for POINTS (with trailing newline).
@ NUMBER_OF_POLYS
"NumberOfPolys"
@ NUMBER_OF_LINES
"NumberOfLines"
@ NUMBER_OF_POINTS
"NumberOfPoints"
@ CONNECTIVITY
"connectivity"
fileTag
Some common XML tags for vtk files.
Definition: foamVtkCore.H:114
@ POLY_DATA
"PolyData"
formatType
The output format type for file contents.
Definition: foamVtkCore.H:66
@ INLINE_BASE64
XML inline base64, base64Formatter.
void writeList(vtk::formatter &fmt, const UList< uint8_t > &values)
Write a list of uint8_t values.
void writeListParallel(vtk::formatter &fmt, const UList< Type > &values)
Write a list of values.
Namespace for OpenFOAM.
List< label > labelList
A List of labels.
Definition: List.H:66
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
static label countConnectivity(const edgeList &edges)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
errorManip< error > abort(error &err)
Definition: errorManip.H:144
error FatalError
List< edge > edgeList
A List of edges.
Definition: edgeList.H:63
List< face > faceList
A List of faces.
Definition: faceListFwd.H:47
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
word format(conversionProperties.get< word >("format"))
labelList f(nPoints)
volScalarField & e
Definition: createFields.H:11