Dune Core Modules (2.9.0)

basicwriter.hh
1// SPDX-FileCopyrightText: Copyright (C) DUNE Project contributors, see file LICENSE.md in module root
2// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
3// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
4// vi: set et ts=4 sw=2 sts=2:
5
6#ifndef DUNE_GRID_IO_FILE_VTK_BASICWRITER_HH
7#define DUNE_GRID_IO_FILE_VTK_BASICWRITER_HH
8
9#include <fstream>
10#include <iomanip>
11#include <iterator>
12#include <list>
13#include <memory>
14#include <sstream>
15#include <string>
16
18#include <dune/common/path.hh>
19
20#include <dune/geometry/referenceelements.hh>
21
23#include <dune/grid/io/file/vtk/functionwriter.hh>
24#include <dune/grid/io/file/vtk/pvtuwriter.hh>
25#include <dune/grid/io/file/vtk/vtuwriter.hh>
26
27namespace Dune
28{
31
32 namespace VTK {
33
34 template<typename IteratorFactory>
35 class BasicWriter {
36 typedef typename IteratorFactory::CellIterator CellIterator;
37 typedef typename IteratorFactory::CornerIterator CornerIterator;
38 typedef typename IteratorFactory::PointIterator PointIterator;
39
40 typedef typename IteratorFactory::Cell Cell;
41
42 public:
43 typedef FunctionWriterBase<Cell> FunctionWriter;
44
45 private:
46 typedef std::list<std::shared_ptr<FunctionWriter> > WriterList;
47 typedef typename WriterList::const_iterator WIterator;
48
49 typedef typename Cell::Geometry::ctype ctype;
50 static const unsigned celldim = Cell::mydimension;
51 typedef ReferenceElements<ctype, celldim> Refelems;
52
53 static const FileType fileType = celldim == 1
55
56 const IteratorFactory& factory;
57
58 WriterList cellData;
59 WriterList pointData;
60
61 CoordinatesWriter<Cell> coords;
62 typename IteratorFactory::ConnectivityWriter connectivity;
63 OffsetsWriter<Cell> offsets;
64 TypesWriter<Cell> types;
65
66 public:
67 BasicWriter(const IteratorFactory& factory_)
68 : factory(factory_), connectivity(factory.makeConnectivity())
69 { }
70
72 //
73 // Methods for adding data
74 //
75
76 void addCellData(const std::shared_ptr<FunctionWriter>& writer) {
77 cellData.push_back(writer);
78 }
79
80 void addPointData(const std::shared_ptr<FunctionWriter>& writer) {
81 pointData.push_back(writer);
82 }
83
84 void clear() {
85 cellData.clear();
86 pointData.clear();
87 }
88
89 protected:
91 //
92 // Methods for writing single functions
93 //
94
95 void writeCellFunction(VTUWriter& vtuWriter,
96 FunctionWriter& functionWriter,
97 unsigned ncells) const
98 {
99 if(functionWriter.beginWrite(vtuWriter, ncells)) {
100 const CellIterator& cellend = factory.endCells();
101 for(CellIterator cellit = factory.beginCells(); cellit != cellend;
102 ++cellit)
103 functionWriter.write(*cellit, Refelems::general(cellit->type()).
104 position(0,0));
105 }
106 functionWriter.endWrite();
107 }
108
109 void writePointFunction(VTUWriter& vtuWriter,
110 FunctionWriter& functionWriter,
111 unsigned npoints) const
112 {
113 if(functionWriter.beginWrite(vtuWriter, npoints)) {
114 const PointIterator& pend = factory.endPoints();
115 for(PointIterator pit = factory.beginPoints(); pit != pend; ++pit)
116 functionWriter.write(pit->cell(), pit->duneIndex());
117 }
118 functionWriter.endWrite();
119 }
120
121 void writeCornerFunction(VTUWriter& vtuWriter,
122 FunctionWriter& functionWriter,
123 unsigned ncorners) const
124 {
125 if(functionWriter.beginWrite(vtuWriter, ncorners)) {
126 const CornerIterator& cend = factory.endCorners();
127 for(CornerIterator cit = factory.beginCorners(); cit != cend; ++cit)
128 functionWriter.write(cit->cell(), cit->duneIndex());
129 }
130 functionWriter.endWrite();
131 }
132
134 //
135 // Methods for writing whole sections
136 //
137
138 static std::string getFirstScalar(const WriterList& data) {
139 const WIterator& wend = data.end();
140 for(WIterator wit = data.begin(); wit != wend; ++wit)
141 if((*wit)->ncomps() == 1)
142 return (*wit)->name();
143 return "";
144 }
145
146 static std::string getFirstVector(const WriterList& data) {
147 const WIterator& wend = data.end();
148 for(WIterator wit = data.begin(); wit != wend; ++wit)
149 if((*wit)->ncomps() == 3)
150 return (*wit)->name();
151 return "";
152 }
153
154 void writeCellData(VTUWriter& vtuWriter, unsigned ncells) const {
155 if(cellData.empty()) return;
156
157 vtuWriter.beginCellData(getFirstScalar(cellData),
158 getFirstVector(cellData));
159 const WIterator& wend = cellData.end();
160 for(WIterator wit = cellData.begin(); wit != wend; ++wit)
161 writeCellFunction(vtuWriter, **wit, ncells);
162 vtuWriter.endCellData();
163 }
164
165 void writePointData(VTUWriter& vtuWriter, unsigned npoints) const {
166 if(pointData.empty()) return;
167
168 vtuWriter.beginPointData(getFirstScalar(pointData),
169 getFirstVector(pointData));
170 const WIterator& wend = pointData.end();
171 for(WIterator wit = pointData.begin(); wit != wend; ++wit)
172 writePointFunction(vtuWriter, **wit, npoints);
173 vtuWriter.endPointData();
174 }
175
176 void writeGrid(VTUWriter& vtuWriter, unsigned ncells, unsigned npoints,
177 unsigned ncorners) {
178 vtuWriter.beginPoints();
179 writePointFunction(vtuWriter, coords, npoints);
180 vtuWriter.endPoints();
181
182 vtuWriter.beginCells();
183 writeCornerFunction(vtuWriter, connectivity, ncorners);
184 writeCellFunction(vtuWriter, offsets, ncells);
185 if(fileType != polyData)
186 writeCellFunction(vtuWriter, types, ncells);
187 vtuWriter.endCells();
188 }
189
190 void writeAll(VTUWriter& vtuWriter, unsigned ncells, unsigned npoints,
191 unsigned ncorners) {
192 writeCellData(vtuWriter, ncells);
193 writePointData(vtuWriter, npoints);
194 writeGrid(vtuWriter, ncells, npoints, ncorners);
195 }
196
197 public:
198 void writePiece(const std::string& filename, OutputType outputType) {
199 std::ofstream stream;
200 stream.exceptions(std::ios_base::badbit | std::ios_base::failbit |
201 std::ios_base::eofbit);
202 stream.open(filename.c_str(), std::ios::binary);
203
204 VTUWriter vtuWriter(stream, outputType, fileType);
205
206 unsigned ncells = std::distance(factory.beginCells(),
207 factory.endCells());
208 unsigned npoints = std::distance(factory.beginPoints(),
209 factory.endPoints());
210 unsigned ncorners = std::distance(factory.beginCorners(),
211 factory.endCorners());
212
213 vtuWriter.beginMain(ncells, npoints);
214 writeAll(vtuWriter, ncells, npoints, ncorners);
215 vtuWriter.endMain();
216
217 if(vtuWriter.beginAppended())
218 writeAll(vtuWriter, ncells, npoints, ncorners);
219 vtuWriter.endAppended();
220
221 }
222
224
240 void writeCollection(const std::string name,
241 const std::string& piecename,
242 const std::string& piecepath)
243 {
244 std::ofstream stream;
245 stream.exceptions(std::ios_base::badbit | std::ios_base::failbit |
246 std::ios_base::eofbit);
247 stream.open(name.c_str(), std::ios::binary);
248
249 PVTUWriter writer(stream, fileType);
250
251 writer.beginMain();
252
253 // PPointData
254 writer.beginPointData(getFirstScalar(pointData),
255 getFirstVector(pointData));
256 for(WIterator it=pointData.begin(); it!=pointData.end(); ++it)
257 (*it)->addArray(writer);
258 writer.endPointData();
259
260 // PCellData
261 writer.beginCellData(getFirstScalar(cellData),
262 getFirstVector(cellData));
263 for(WIterator it=cellData.begin(); it!=cellData.end(); ++it)
264 (*it)->addArray(writer);
265 writer.endCellData();
266
267 // PPoints
268 writer.beginPoints();
269 coords.addArray(writer);
270 writer.endPoints();
271
272 // Pieces
273 for( int i = 0; i < factory.comm().size(); ++i )
274 writer.addPiece(getParallelPieceName(piecename, piecepath, i));
275
276 writer.endMain();
277 }
278
280 //
281 // Filename generators
282 //
283
285
295 std::string getParallelPieceName(const std::string& name,
296 const std::string& path, int rank) const
297 {
298 std::ostringstream s;
299 if(path.size() > 0) {
300 s << path;
301 if(path[path.size()-1] != '/')
302 s << '/';
303 }
304 s << 's' << std::setw(4) << std::setfill('0') << factory.comm().size()
305 << ':';
306 s << 'p' << std::setw(4) << std::setfill('0') << rank << ':';
307 s << name;
308 switch(fileType) {
309 case polyData : s << ".vtp"; break;
310 case unstructuredGrid : s << ".vtu"; break;
311 }
312 return s.str();
313 }
314
316
325 std::string getParallelHeaderName(const std::string& name,
326 const std::string& path) const
327 {
328 std::ostringstream s;
329 if(path.size() > 0) {
330 s << path;
331 if(path[path.size()-1] != '/')
332 s << '/';
333 }
334 s << 's' << std::setw(4) << std::setfill('0') << factory.comm().size()
335 << ':';
336 s << name;
337 switch(fileType) {
338 case polyData : s << ".pvtp"; break;
339 case unstructuredGrid : s << ".pvtu"; break;
340 }
341 return s.str();
342 }
343
345
357 std::string getSerialPieceName(const std::string& name,
358 const std::string& path) const
359 {
360 switch(fileType) {
361 case polyData : return concatPaths(path, name+".vtp");
362 case unstructuredGrid : return concatPaths(path, name+".vtu");
363 }
364 return concatPaths(path, name); // unknown fileType
365 }
366
368 //
369 // User interface functions for writing
370 //
371
373
395 std::string pwrite(const std::string& name, const std::string& path,
396 const std::string& extendpath, OutputType outputType)
397 {
398 MPIGuard guard(factory.comm());
399
400 // do some magic because paraview can only cope with relative paths to
401 // piece files
402 std::ofstream file;
403 file.exceptions(std::ios_base::badbit | std::ios_base::failbit |
404 std::ios_base::eofbit);
405 std::string piecepath = concatPaths(path, extendpath);
406 std::string relpiecepath = relativePath(path, piecepath);
407
408 // write this processes .vtu/.vtp piece file
409 std::string fullname = getParallelPieceName(name, piecepath,
410 factory.comm().rank());
411 writePiece(fullname, outputType);
412
413 // if we are rank 0, write .pvtu/.pvtp parallel header
414 fullname = getParallelHeaderName(name, path);
415 if(factory.comm().rank() == 0)
416 writeCollection(fullname, name, relpiecepath);
417
418 guard.finalize();
419
420 return fullname;
421 }
422
436 std::string write(const std::string &name, OutputType outputType)
437 {
438 // in the parallel case, just use pwrite, it has all the necessary
439 // stuff, so we don't need to reimplement it here.
440 if(factory.comm().size() > 1)
441 return pwrite(name, "", "", outputType);
442
443 // generate filename for process data
444 std::string pieceName = getSerialPieceName(name, "");
445
446 writePiece(pieceName, outputType);
447
448 return pieceName;
449 }
450
451 };
452
453 } // namespace VTK
454
456
457} // namespace Dune
458
459#endif // DUNE_GRID_IO_FILE_VTK_BASICWRITER_HH
Common stuff for the VTKWriter.
FileType
which type of VTK file to write
Definition: common.hh:252
@ polyData
for .vtp files (PolyData)
Definition: common.hh:254
@ unstructuredGrid
for .vtu files (UnstructuredGrid)
Definition: common.hh:256
std::string relativePath(const std::string &newbase, const std::string &p)
compute a relative path between two paths
Definition: path.cc:153
std::string concatPaths(const std::string &base, const std::string &p)
concatenate two paths
Definition: path.cc:32
Implements a MPIGuard which detects an error on a remote process.
Dune namespace.
Definition: alignedallocator.hh:13
Utilities for handling filesystem paths.
static const ReferenceElement & general(const GeometryType &type)
get general reference elements
Definition: referenceelements.hh:198
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Dec 21, 23:30, 2024)