foamVtkWritePointSet.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) 2017-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 <fstream>
29 #include "foamVtkWriteTopoSet.H"
30 #include "polyMesh.H"
31 #include "pointSet.H"
32 #include "globalIndex.H"
33 #include "OSspecific.H"
34 
35 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
36 
38 (
39  const polyMesh& mesh,
40  const pointSet& set,
41  const vtk::outputOptions opts,
42  const fileName& file,
43  bool parallel
44 )
45 {
46  vtk::outputOptions opts_(opts);
47  opts_.append(false); // Do not support append
48 
49  const bool legacy = opts_.legacy();
50 
51  // Only allow parallel if really is a parallel run.
52  parallel = parallel && Pstream::parRun();
53 
54 
55  std::ofstream os_;
57 
58  // Open a file and attach a formatter
59  // - on master (always)
60  // - on slave if not parallel
61  //
62  // This means we can always check if format_ is defined to know if output
63  // is desired on any particular process.
64 
65  if (Pstream::master() || !parallel)
66  {
67  mkDir(file.path());
68 
69  // Extension is inappropriate. Legacy instead of xml, or vice versa.
70  const word ext = vtk::fileExtension[vtk::fileTag::POLY_DATA];
71 
72  if (file.has_ext(ext))
73  {
74  // Extension is correct
75  os_.open(file);
76  }
77  else if
78  (
79  legacy
80  ? file.has_ext(ext)
82  )
83  {
84  // Extension is inappropriate. Legacy instead of xml, or vice versa.
85  os_.open(file.lessExt() + "." + ext);
86  }
87  else
88  {
89  // Extension added automatically
90  os_.open(file + "." + ext);
91  }
92 
93  format = opts_.newFormatter(os_);
94  }
95 
96 
97  //-------------------------------------------------------------------------
98 
100 
101  label numberOfPoints = pointLabels.size();
102 
103  if (parallel)
104  {
105  reduce(numberOfPoints, sumOp<label>());
106  }
107 
108  if (format)
109  {
110  const auto& title = set.name();
111 
112  if (legacy)
113  {
114  // beginFile:
115 
116  legacy::fileHeader<vtk::fileTag::POLY_DATA>(format(), title);
117 
118  // beginPoints:
119 
120  legacy::beginPoints(os_, numberOfPoints);
121  }
122  else
123  {
124  // XML (inline)
125 
126  // beginFile:
127 
128  format()
129  .xmlHeader()
130  .xmlComment(title)
131  .beginVTKFile<vtk::fileTag::POLY_DATA>();
132 
133  // beginPiece:
134  format()
135  .tag
136  (
137  vtk::fileTag::PIECE,
138  vtk::fileAttr::NUMBER_OF_POINTS, numberOfPoints
139  );
140 
141  // beginPoints:
142  const uint64_t payLoad = vtk::sizeofData<float,3>(numberOfPoints);
143 
144  format()
145  .tag(vtk::fileTag::POINTS)
146  .beginDataArray<float,3>(vtk::dataArrayAttr::POINTS);
147  format().writeSize(payLoad);
148  }
149  }
150 
151 
152  //-------------------------------------------------------------------------
153 
154  // pointLabels are the addressing for an indirect list
155 
156  if (parallel)
157  {
158  vtk::writeListParallel(format.ref(), mesh.points(), pointLabels);
159  }
160  else
161  {
162  vtk::writeList(format(), mesh.points(), pointLabels);
163  }
164 
165  if (format)
166  {
167  format().flush();
168  format().endDataArray();
169 
170  if (!legacy)
171  {
172  format()
173  .endTag(vtk::fileTag::POINTS);
174  }
175 
176 
177  // beginPointData:
178  if (legacy)
179  {
180  legacy::beginPointData(format(), numberOfPoints, 1); // 1 field
181  }
182  else
183  {
184  format().beginPointData();
185  }
186  }
187 
188  if (format)
189  {
190  // pointID
191 
192  if (legacy)
193  {
194  // 1 component
195  legacy::intField<1>(format(), "pointID", numberOfPoints);
196  }
197  else
198  {
199  const uint64_t payLoad = vtk::sizeofData<label>(numberOfPoints);
200 
201  format().beginDataArray<label>("pointID");
202  format().writeSize(payLoad);
203  }
204  }
205 
206 
207  if (parallel)
208  {
209  const globalIndex pointIdOffset(mesh.nPoints());
210 
211  vtk::writeListParallel(format.ref(), pointLabels, pointIdOffset);
212  }
213  else
214  {
216  }
217 
218 
219  if (format)
220  {
221  format().flush();
222  format().endDataArray();
223  format().endPointData();
224  format().endPiece();
225 
226  format().endTag(vtk::fileTag::POLY_DATA)
227  .endVTKFile();
228  }
229 
230  return true;
231 }
232 
233 
234 // ************************************************************************* //
A class for handling file names.
Definition: fileName.H:72
autoPtr< formatter > newFormatter(std::ostream &os) const
Return new formatter based on the selected output options.
A set of point labels.
Definition: pointSet.H:47
labelList pointLabels(nPoints, -1)
bool writePointSet(const polyMesh &mesh, const pointSet &set, const vtk::outputOptions opts, const fileName &file, bool parallel=UPstream::parRun())
Write pointSet to VTK polydata file.
bool append() const noexcept
True if output format uses an append mode.
static std::string path(const std::string &str)
Return directory path name (part before last /)
Definition: fileNameI.H:169
void beginPointData(vtk::formatter &fmt, label nPoints, label nFields)
Emit legacy POINT_DATA nPoints, FIELD FieldData nFields.
Encapsulated combinations of output format options. This is primarily useful when defining the output...
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
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
dynamicFvMesh & mesh
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:614
A class for handling words, derived from Foam::string.
Definition: word.H:63
Write topoSet in VTK format.
void writeList(vtk::formatter &fmt, const UList< uint8_t > &values)
Write a list of uint8_t values.
word format(conversionProperties.get< word >("format"))
const Foam::Enum< fileTag > fileExtension
File extension (without ".") for some vtk XML file content types.
fileName lessExt() const
Return file name without extension (part before last .)
Definition: fileNameI.H:238
bool legacy() const noexcept
True if writer uses legacy file format.
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.
List< label > sortedToc(const UList< bool > &bools)
Return the (sorted) values corresponding to &#39;true&#39; entries.
Definition: BitOps.C:195
bool has_ext() const
Various checks for extensions.
Definition: stringI.H:43
void writeListParallel(vtk::formatter &fmt, const UList< Type > &values)
Write a list of values.
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74