GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: dumux/dumux/io/vtk/vtkreader.hh
Date: 2025-05-03 19:19:02
Exec Total Coverage
Lines: 194 217 89.4%
Functions: 26 34 76.5%
Branches: 170 860 19.8%

Line Branch Exec Source
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 //
4 // SPDX-FileCopyrightText: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5 // SPDX-License-Identifier: GPL-3.0-or-later
6 //
7 /*!
8 * \file
9 * \ingroup InputOutput
10 * \brief A vtk file reader using tinyxml2 as xml backend
11 */
12 #ifndef DUMUX_IO_VTK_VTKREADER_HH
13 #define DUMUX_IO_VTK_VTKREADER_HH
14
15 #include <iostream>
16 #include <iterator>
17 #include <algorithm>
18 #include <memory>
19 #include <type_traits>
20 #include <unordered_map>
21 #include <utility>
22 #include <filesystem>
23
24 #include <dune/common/parallel/mpihelper.hh>
25 #include <dune/common/exceptions.hh>
26 #include <dune/grid/common/capabilities.hh>
27 #include <dune/grid/io/file/vtk/common.hh>
28 #include <dune/grid/common/gridfactory.hh>
29
30 #include <dumux/io/container.hh>
31
32 #if DUMUX_HAVE_GRIDFORMAT
33
34 #include <gridformat/gridformat.hpp>
35 #include <gridformat/traits/dune.hpp>
36 #include <gridformat/reader.hpp>
37 #include <gridformat/decorators/reader_polylines_subdivider.hpp>
38
39 #include "imagegrid_.hh"
40
41 namespace Dumux::Detail::VTKReader {
42
43 template<GridFormat::Concepts::Communicator C>
44 auto makeGridformatReaderFactory(const C& c)
45 {
46 return [fac = GridFormat::AnyReaderFactory<C>{c}] (const std::string& f)
47 -> std::unique_ptr<GridFormat::GridReader> {
48 // use adapter for poly data that splits polylines into segments
49 if (f.ends_with("vtp"))
50 return std::make_unique<GridFormat::ReaderDecorators::PolylinesSubdivider>(fac.make_for(f));
51 return fac.make_for(f);
52 };
53 }
54
55 } // end namespace Dumux::Detail::VTKReader
56
57 namespace Dumux {
58
59 /*!
60 * \ingroup InputOutput
61 * \brief A vtk file reader using gridformat
62 */
63 class VTKReader
64 {
65 public:
66 enum class DataType { cellData, pointData, fieldData };
67
68 //! the cell / point data type for point data read from a grid file
69 using Data = std::unordered_map<std::string, std::vector<double>>;
70
71 explicit VTKReader(const std::string& fileName)
72 : reader_(std::make_shared<GridFormat::Reader>(GridFormat::Reader::from(fileName,
73 Detail::VTKReader::makeGridformatReaderFactory(
74 Dune::MPIHelper::instance().getCommunicator()
75 )
76 )))
77 {}
78
79 /*!
80 * \brief Reviews data from the vtk file to check if there is a data array with a specified name
81 * \param name the name attribute of the data array to read
82 * \param type the data array type
83 */
84 bool hasData(const std::string& name, const DataType& type) const
85 {
86 if (type == DataType::cellData)
87 return std::ranges::any_of(
88 cell_field_names(*reader_),
89 [&] (const auto& n) { return name == n; }
90 );
91 else if (type == DataType::pointData)
92 return std::ranges::any_of(
93 point_field_names(*reader_),
94 [&] (const auto& n) { return name == n; }
95 );
96 else if (type == DataType::fieldData)
97 return std::ranges::any_of(
98 meta_data_field_names(*reader_),
99 [&] (const auto& n) { return name == n; }
100 );
101 else
102 DUNE_THROW(Dune::IOError, "Unknown data type for field '" << name << "'");
103 }
104
105 /*!
106 * \brief read data from the vtk file to a container, e.g. std::vector<double>
107 * \tparam Container a container type that has begin(), end(), push_back(), e.g. std::vector<>
108 * \param name the name attribute of the data array to read
109 * \param type the data array type
110 */
111 template<class Container>
112 Container readData(const std::string& name, const DataType& type) const
113 {
114 if (type == DataType::cellData)
115 {
116 Container values(reader_->number_of_cells());
117 reader_->cell_field(name)->export_to(values);
118 return values;
119 }
120 else if (type == DataType::pointData)
121 {
122 Container values(reader_->number_of_points());
123 reader_->point_field(name)->export_to(values);
124 return values;
125 }
126 else if (type == DataType::fieldData)
127 {
128 DUNE_THROW(Dune::NotImplemented, "Reading meta data not yet implemented");
129 }
130 else
131 DUNE_THROW(Dune::IOError, "Unknown data type for field '" << name << "'");
132 }
133
134 /*!
135 * \brief Read a grid from a vtk/vtu/vtp file, ignoring cell and point data
136 * \param verbose if the output should be verbose
137 */
138 template<class Grid>
139 std::unique_ptr<Grid> readGrid(bool verbose = false) const
140 {
141 Dune::GridFactory<Grid> factory;
142 return readGrid(factory, verbose);
143 }
144
145 /*!
146 * \brief Read a grid from a vtk/vtu/vtp file, ignoring cell and point data
147 * \note use this signature if the factory might be needed outside to interpret the data via the factory's insertion indices
148 * \param verbose if the output should be verbose
149 * \param factory the (empty) grid factory
150 */
151 template<class Grid>
152 std::unique_ptr<Grid> readGrid(Dune::GridFactory<Grid>& factory, bool verbose = false) const
153 {
154 if (Dune::MPIHelper::instance().rank() == 0)
155 {
156 if (verbose)
157 std::cout << "Reading " << Grid::dimension << "d grid from vtk file " << reader_->filename() << "." << std::endl;
158
159 {
160 GridFormat::Dune::GridFactoryAdapter<Grid> adapter{ factory };
161 reader_->export_grid(adapter);
162 }
163 }
164
165 return std::unique_ptr<Grid>(factory.createGrid());
166 }
167
168 /*!
169 * \brief Read a grid from a vtk/vtu/vtp file (unstructured), reading all cell and point data
170 * \note the factory will be needed outside to interpret the data via the factory's insertion indices
171 * \param factory the (empty) grid factory
172 * \param cellData the cell data arrays to be filled
173 * \param pointData the point data arrays to be filled
174 * \param verbose if the output should be verbose
175 */
176 template<class Grid>
177 std::unique_ptr<Grid> readGrid(Dune::GridFactory<Grid>& factory, Data& cellData, Data& pointData, bool verbose = false) const
178 {
179 auto grid = readGrid(factory, verbose);
180
181 // read field names on all processes
182 for (const auto& name : cell_field_names(*reader_))
183 cellData[name] = Data::mapped_type{};
184 for (const auto& name : point_field_names(*reader_))
185 pointData[name] = Data::mapped_type{};
186
187 // read data arrays only on rank 0
188 if (Dune::MPIHelper::instance().rank() == 0)
189 {
190 for (const auto& [name, field_ptr] : cell_fields(*reader_))
191 {
192 if (verbose) std::cout << "-- reading cell data '" << name << "'." << std::endl;
193 field_ptr->export_to(cellData[name]);
194 }
195
196 for (const auto& [name, field_ptr] : point_fields(*reader_))
197 {
198 if (verbose) std::cout << "-- reading point data '" << name << "'." << std::endl;
199 field_ptr->export_to(pointData[name]);
200 }
201 }
202
203 return std::unique_ptr<Grid>(std::move(grid));
204 }
205
206 /*!
207 * \brief Read a grid from a vti file (structured), reading all cell and point data
208 * \note the factory will be needed outside to interpret the data via the factory's insertion indices
209 * \param factory the (empty) grid factory
210 * \param cellData the cell data arrays to be filled
211 * \param pointData the point data arrays to be filled
212 * \param verbose if the output should be verbose
213 *
214 * \return an instance of an image grid that contains information to construct a structured grid
215 */
216 template<class ct, int dim>
217 std::unique_ptr<Detail::VTKReader::ImageGrid<ct, dim>> readStructuredGrid(bool verbose = false) const
218 {
219 if (verbose)
220 std::cout << "Reading " << dim << "d grid from vtk file " << reader_->filename() << "." << std::endl;
221
222 return std::make_unique<Detail::VTKReader::ImageGrid<ct, dim>>(reader_);
223 }
224
225 /*!
226 * \brief Read a grid from a vti file (structured), reading all cell and point data
227 * \note the factory will be needed outside to interpret the data via the factory's insertion indices
228 * \param factory the (empty) grid factory
229 * \param cellData the cell data arrays to be filled
230 * \param pointData the point data arrays to be filled
231 * \param verbose if the output should be verbose
232 */
233 template<class ct, int dim>
234 std::unique_ptr<Detail::VTKReader::ImageGrid<ct, dim>> readStructuredGrid(Data& cellData, Data& pointData, bool verbose = false) const
235 {
236 auto grid = readStructuredGrid<ct, dim>(verbose);
237
238 // read field names on all processes
239 for (const auto& name : cell_field_names(*reader_))
240 cellData[name] = Data::mapped_type{};
241 for (const auto& name : point_field_names(*reader_))
242 pointData[name] = Data::mapped_type{};
243
244 // read data arrays only on rank 0
245 if (Dune::MPIHelper::instance().rank() == 0)
246 {
247 for (const auto& [name, field_ptr] : cell_fields(*reader_))
248 {
249 if (verbose) std::cout << "-- reading cell data '" << name << "'." << std::endl;
250 field_ptr->export_to(cellData[name]);
251 }
252
253 for (const auto& [name, field_ptr] : point_fields(*reader_))
254 {
255 if (verbose) std::cout << "-- reading point data '" << name << "'." << std::endl;
256 field_ptr->export_to(pointData[name]);
257 }
258 }
259 return { std::move(grid) };
260 }
261
262 private:
263 std::shared_ptr<GridFormat::Reader> reader_;
264 };
265
266 } // namespace Dumux
267
268 #else // DUMUX_HAVE_GRIDFORMAT
269
270 #include <dumux/io/xml/tinyxml2.h>
271 // fallback to simple vtk reader using tinyxml2
272 // this reader only support ascii files and limited VTK file formats
273
274 namespace Dumux::Detail::VTKReader {
275
276 /*!
277 * \brief Get the piece node an xml document
278 * \note Returns nullptr if the piece node wasn't found
279 * \param doc an xml document
280 * \param fileName a file name the doc was created from
281 */
282 491 const tinyxml2::XMLElement* getPieceNode(const tinyxml2::XMLDocument& doc, const std::string& fileName)
283 {
284 491 using namespace tinyxml2;
285
286 491 const XMLElement* pieceNode = doc.FirstChildElement("VTKFile");
287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 491 times.
491 if (pieceNode == nullptr)
288 DUNE_THROW(Dune::IOError, "Couldn't get 'VTKFile' node in " << fileName << ".");
289
290 491 pieceNode = pieceNode->FirstChildElement("UnstructuredGrid");
291
2/2
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 367 times.
491 if (pieceNode == nullptr)
292 248 pieceNode = doc.FirstChildElement("VTKFile")->FirstChildElement("PolyData");
293
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 122 times.
124 if (pieceNode == nullptr)
294 4 pieceNode = doc.FirstChildElement("VTKFile")->FirstChildElement("PUnstructuredGrid");
295
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 369 times.
369 if (pieceNode == nullptr)
296 pieceNode = doc.FirstChildElement("VTKFile")->FirstChildElement("PPolyData");
297 if (pieceNode == nullptr)
298 DUNE_THROW(Dune::IOError, "Couldn't get 'UnstructuredGrid', 'PUnstructuredGrid', 'PolyData', or 'PPolyData' node in " << fileName << ".");
299
300 982 return pieceNode->FirstChildElement("Piece");
301 }
302
303 /*!
304 * \brief get the vtk filename for the current processor
305 */
306 2 std::string getProcessPieceFileName(const std::string& pvtkFileName)
307 {
308 2 using namespace tinyxml2;
309
310 2 XMLDocument pDoc;
311
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 const auto eResult = pDoc.LoadFile(pvtkFileName.c_str());
312
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (eResult != XML_SUCCESS)
313 DUNE_THROW(Dune::IOError, "Couldn't open XML file " << pvtkFileName << ".");
314
315 // get the first piece node
316
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 const XMLElement* pieceNode = getPieceNode(pDoc, pvtkFileName);
317
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 const auto myrank = Dune::MPIHelper::instance().rank();
318
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 for (int rank = 0; rank < myrank; ++rank)
319 {
320 1 pieceNode = pieceNode->NextSiblingElement("Piece");
321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pieceNode == nullptr)
322
0/34
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
1 DUNE_THROW(Dune::IOError, "Couldn't find 'Piece' node for rank "
323 << rank << " in " << pvtkFileName << ".");
324 }
325
326 2 const char *vtkFileName = pieceNode->Attribute("Source");
327
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (vtkFileName == nullptr)
328 DUNE_THROW(Dune::IOError, "Couldn't get 'Source' attribute of 'Piece' node no. " << myrank << " in " << pvtkFileName);
329
330
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 return vtkFileName;
331 2 }
332
333 } // end namespace Dumux::Detail::VTKReader
334
335 namespace Dumux {
336
337 /*!
338 * \ingroup InputOutput
339 * \brief A vtk file reader using tinyxml2 as xml backend
340 */
341 69 class VTKReader
342 {
343 public:
344 /*!
345 * \brief The data array types
346 */
347 enum class DataType { cellData, pointData };
348
349 //! the cell / point data type for point data read from a grid file
350 using Data = std::unordered_map<std::string, std::vector<double>>;
351
352 /*!
353 * \brief The constructor creates a tinyxml2::XMLDocument from file
354 */
355 69 explicit VTKReader(const std::string& fileName)
356 69 {
357 69 using namespace tinyxml2;
358
2/4
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
138 const auto ext = std::filesystem::path(fileName).extension().string();
359 // If in parallel and the file to read is a parallel piece collection (pvtu/pvtp)
360 // read only the piece belonging to the own process. For this to work, the files
361 // have to have exactly the same amount of pieces than processes.
362
6/8
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 63 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 4 times.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
69 fileName_ = Dune::MPIHelper::instance().size() > 1 && ext[1] == 'p' ?
363
1/2
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
138 Detail::VTKReader::getProcessPieceFileName(fileName) : fileName;
364
365
1/2
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
69 const auto eResult = doc_.LoadFile(fileName_.c_str());
366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
69 if (eResult != tinyxml2::XML_SUCCESS)
367 DUNE_THROW(Dune::IOError, "Couldn't open XML file " << fileName_ << ".");
368
369 138 const XMLElement* pieceNode = getPieceNode_();
370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
69 if (pieceNode == nullptr)
371
0/30
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
69 DUNE_THROW(Dune::IOError, "Couldn't get 'Piece' node in " << fileName_ << ".");
372 69 }
373
374 /*!
375 * \brief Reviews data from the vtk file to check if there is a data array with a specified name
376 * \param name the name attribute of the data array to read
377 * \param type the data array type
378 */
379 273 bool hasData(const std::string& name, const DataType& type) const
380 {
381 273 using namespace tinyxml2;
382
383 546 const XMLElement* pieceNode = getPieceNode_();
384 273 const XMLElement* dataNode = getDataNode_(pieceNode, type);
385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 273 times.
273 if (dataNode == nullptr)
386 return false;
387
388 273 const XMLElement* dataArray = findDataArray_(dataNode, name);
389
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 271 times.
273 if (dataArray == nullptr)
390 return false;
391
392 return true;
393 }
394
395 /*!
396 * \brief read data from the vtk file to a container, e.g. std::vector<double>
397 * \tparam Container a container type that has begin(), end(), push_back(), e.g. std::vector<>
398 * \param name the name attribute of the data array to read
399 * \param type the data array type
400 */
401 template<class Container>
402 139 Container readData(const std::string& name, const DataType& type) const
403 {
404 using namespace tinyxml2;
405
406 139 const XMLElement* pieceNode = getPieceNode_();
407 139 const XMLElement* dataNode = getDataNode_(pieceNode, type);
408
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
139 if (dataNode == nullptr)
409 DUNE_THROW(Dune::IOError, "Couldn't get 'PointData' or 'CellData' node in " << fileName_ << ".");
410
411 139 const XMLElement* dataArray = findDataArray_(dataNode, name);
412
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
139 if (dataArray == nullptr)
413 DUNE_THROW(Dune::IOError, "Couldn't find the data array " << name << ".");
414
415 139 return parseDataArray_<Container>(dataArray);
416 }
417
418 /*!
419 * \brief Read a grid from a vtk/vtu/vtp file, ignoring cell and point data
420 * \param verbose if the output should be verbose
421 */
422 template<class Grid>
423 std::unique_ptr<Grid> readGrid(bool verbose = false) const
424 {
425 static_assert(!Dune::Capabilities::isCartesian<Grid>::v, "Grid reader only supports unstructured grid implementations");
426
427 // make a grid factory
428 Dune::GridFactory<Grid> factory;
429
430 // only read on rank 0
431 if (Dune::MPIHelper::instance().rank() == 0)
432 {
433 if (verbose)
434 std::cout << "Reading " << Grid::dimension << "d grid from vtk file " << fileName_ << "." << std::endl;
435 readGrid_(factory, verbose);
436 }
437
438 return std::unique_ptr<Grid>(factory.createGrid());
439 }
440
441 /*!
442 * \brief Read a grid from a vtk/vtu/vtp file, ignoring cell and point data
443 * \note use this signature if the factory might be needed outside to interpret the data via the factory's insertion indices
444 * \param verbose if the output should be verbose
445 * \param factory the (empty) grid factory
446 */
447 template<class Grid>
448 std::unique_ptr<Grid> readGrid(Dune::GridFactory<Grid>& factory, bool verbose = false) const
449 {
450 static_assert(!Dune::Capabilities::isCartesian<Grid>::v, "Grid reader only supports unstructured grid implementations");
451
452 if (Dune::MPIHelper::instance().rank() == 0)
453 {
454 if (verbose)
455 std::cout << "Reading " << Grid::dimension << "d grid from vtk file " << fileName_ << "." << std::endl;
456 readGrid_(factory, verbose);
457 }
458
459 return std::unique_ptr<Grid>(factory.createGrid());
460 }
461
462 /*!
463 * \brief Read a grid from a vtk/vtu/vtp file, reading all cell and point data
464 * \note the factory will be needed outside to interpret the data via the factory's insertion indices
465 * \param factory the (empty) grid factory
466 * \param cellData the cell data arrays to be filled
467 * \param pointData the point data arrays to be filled
468 * \param verbose if the output should be verbose
469 */
470 template<class Grid>
471 13 std::unique_ptr<Grid> readGrid(Dune::GridFactory<Grid>& factory, Data& cellData, Data& pointData, bool verbose = false) const
472 {
473 static_assert(!Dune::Capabilities::isCartesian<Grid>::v, "Grid reader only supports unstructured grid implementations");
474
475
2/2
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 2 times.
13 if (Dune::MPIHelper::instance().rank() == 0)
476 {
477
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (verbose)
478 11 std::cout << "Reading " << Grid::dimension << "d grid from vtk file " << fileName_ << "." << std::endl;
479 11 readGrid_(factory, verbose);
480 11 readGridData_(cellData, pointData, verbose);
481 }
482
483 13 return std::unique_ptr<Grid>(factory.createGrid());
484 }
485
486 private:
487 /*!
488 * \brief Read a grid from a vtk/vtu/vtp file
489 * \param factory the (empty) grid factory
490 * \param verbose if the output should be verbose
491 */
492 template<class Grid>
493 11 void readGrid_(Dune::GridFactory<Grid>& factory, bool verbose = false) const
494 {
495 using namespace tinyxml2;
496
497 11 const XMLElement* pieceNode = getPieceNode_();
498 22 const XMLElement* pointsNode = pieceNode->FirstChildElement("Points")->FirstChildElement("DataArray");
499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (pointsNode == nullptr)
500 DUNE_THROW(Dune::IOError, "Couldn't get data array of points in " << fileName_ << ".");
501
502 using Point3D = Dune::FieldVector<double, 3>;
503
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
11 std::vector<Point3D> points3D;
504
4/10
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 11 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
22 std::stringstream dataStream(pointsNode->GetText());
505
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
11 std::istream_iterator<Point3D> it(dataStream);
506
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
11 std::copy(it, std::istream_iterator<Point3D>(), std::back_inserter(points3D));
507
508 // adapt point dimensions if grid dimension is smaller than 3
509
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
11 auto points = adaptPointDimension_<Grid::dimensionworld>(std::move(points3D));
510
511
7/11
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 5 times.
✓ Branch 6 taken 6 times.
✓ Branch 7 taken 5 times.
✓ Branch 9 taken 6 times.
✗ Branch 10 not taken.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ Branch 8 not taken.
17 if (verbose) std::cout << "Found " << points.size() << " vertices." << std::endl;
512
513 // insert vertices to the grid factory
514
2/2
✓ Branch 0 taken 18389 times.
✓ Branch 1 taken 11 times.
18400 for (auto&& point : points)
515
1/2
✓ Branch 1 taken 18389 times.
✗ Branch 2 not taken.
18389 factory.insertVertex(std::move(point));
516
517 11 const XMLElement* cellsNode = pieceNode->FirstChildElement("Cells");
518 11 const XMLElement* linesNode = pieceNode->FirstChildElement("Lines");
519
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
11 if (cellsNode)
520 {
521
3/6
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
8 const XMLElement* connectivityNode = findDataArray_(cellsNode, "connectivity");
522
3/6
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
8 const XMLElement* offsetsNode = findDataArray_(cellsNode, "offsets");
523
2/6
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
8 const XMLElement* typesNode = findDataArray_(cellsNode, "types");
524
525
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 const auto connectivity = parseDataArray_<std::vector<unsigned int>>(connectivityNode);
526
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 const auto offsets = parseDataArray_<std::vector<unsigned int>>(offsetsNode);
527
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 const auto types = parseDataArray_<std::vector<unsigned int>>(typesNode);
528
529
4/8
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 8 times.
✗ Branch 10 not taken.
16 if (verbose) std::cout << "Found " << offsets.size() << " elements." << std::endl;
530
531 unsigned int lastOffset = 0;
532
2/2
✓ Branch 0 taken 18827 times.
✓ Branch 1 taken 8 times.
18835 for (unsigned int i = 0; i < offsets.size(); ++i)
533 {
534
1/2
✓ Branch 1 taken 18827 times.
✗ Branch 2 not taken.
18827 const auto geomType = vtkToDuneGeomType_(types[i]);
535
1/2
✓ Branch 1 taken 18827 times.
✗ Branch 2 not taken.
18827 unsigned int offset = offsets[i];
536
1/2
✓ Branch 1 taken 18827 times.
✗ Branch 2 not taken.
18827 std::vector<unsigned int> corners; corners.resize(offset-lastOffset);
537
2/2
✓ Branch 0 taken 77461 times.
✓ Branch 1 taken 18827 times.
96288 for (unsigned int j = 0; j < offset-lastOffset; ++j)
538 77461 corners[Dune::VTK::renumber(geomType, j)] = connectivity[lastOffset+j];
539
1/2
✓ Branch 1 taken 18827 times.
✗ Branch 2 not taken.
18827 factory.insertElement(geomType, std::move(corners));
540
1/2
✓ Branch 0 taken 15231 times.
✗ Branch 1 not taken.
18827 lastOffset = offset;
541 }
542 13 }
543 // for poly data
544
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 else if (linesNode)
545 {
546 // sanity check
547 if (Grid::dimension != 1)
548
1/28
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
3 DUNE_THROW(Dune::IOError, "Grid expects dimension " << Grid::dimension
549 << " but " << fileName_ << " contains a 1D grid.");
550
551
3/6
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
3 const XMLElement* connectivityNode = findDataArray_(linesNode, "connectivity");
552
2/6
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
3 const XMLElement* offsetsNode = findDataArray_(linesNode, "offsets");
553
554
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 const auto connectivity = parseDataArray_<std::vector<unsigned int>>(connectivityNode);
555
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 const auto offsets = parseDataArray_<std::vector<unsigned int>>(offsetsNode);
556
557
4/8
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
6 if (verbose) std::cout << "Found " << offsets.size() << " polylines." << std::endl;
558
559 unsigned int lastOffset = 0;
560
2/2
✓ Branch 0 taken 3479 times.
✓ Branch 1 taken 3 times.
3482 for (unsigned int i = 0; i < offsets.size(); ++i)
561 {
562 // a polyline can have many points in the VTK format
563 // split the line in segments with two points
564 3479 unsigned int offset = offsets[i];
565
2/2
✓ Branch 0 taken 3496 times.
✓ Branch 1 taken 3479 times.
6975 for (unsigned int j = 0; j < offset-lastOffset-1; ++j)
566
2/4
✓ Branch 1 taken 3496 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3496 times.
✗ Branch 5 not taken.
3496 factory.insertElement(Dune::GeometryTypes::line,
567
1/4
✓ Branch 1 taken 3496 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6992 std::vector<unsigned int>({ connectivity[lastOffset+j], connectivity[lastOffset+j+1] }));
568 3479 lastOffset = offset;
569 }
570 4 }
571 else
572
2/40
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✓ Branch 39 taken 1 times.
✗ Branch 40 not taken.
✓ Branch 0 taken 6 times.
✗ Branch 3 not taken.
✗ Branch 6 not taken.
✗ Branch 9 not taken.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 18 not taken.
✗ Branch 21 not taken.
✗ Branch 24 not taken.
✗ Branch 27 not taken.
✗ Branch 30 not taken.
✗ Branch 33 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
7 DUNE_THROW(Dune::IOError, "No Cells or Lines element found in " << fileName_);
573 27 }
574
575 /*!
576 * \brief Read a grid data from a vtk/vtu/vtp file
577 * \param cellData the cell data arrays to be filled
578 * \param pointData the point data arrays to be filled
579 * \param verbose if the output should be verbose
580 */
581 11 void readGridData_(Data& cellData, Data& pointData, bool verbose = false) const
582 {
583 11 using namespace tinyxml2;
584
585 22 const XMLElement* pieceNode = getPieceNode_();
586 11 const XMLElement* cellDataNode = getDataNode_(pieceNode, DataType::cellData);
587
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if (cellDataNode != nullptr)
588 {
589 11 const XMLElement* cellsNode = pieceNode->FirstChildElement("Cells");
590 11 const XMLElement* linesNode = pieceNode->FirstChildElement("Lines");
591
592
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
11 if (cellsNode)
593 {
594 8 const XMLElement* dataArray = cellDataNode->FirstChildElement("DataArray");
595
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 8 times.
54 for (; dataArray != nullptr; dataArray = dataArray->NextSiblingElement("DataArray"))
596 {
597 23 const char *attributeText = dataArray->Attribute("Name");
598
599
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (attributeText == nullptr)
600 DUNE_THROW(Dune::IOError, "Couldn't get Name attribute of a cell data array.");
601
602
2/6
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 23 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
46 cellData[std::string(attributeText)] = parseDataArray_<std::vector<double>>(dataArray);
603
604
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 if (verbose)
605 23 std::cout << "Read cell data field " << attributeText << std::endl;
606 }
607 }
608 // for poly data
609
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 else if (linesNode)
610 {
611 // first parse all the cell data (each cell in this sense can be a polyline)
612 3 const XMLElement* dataArray = cellDataNode->FirstChildElement("DataArray");
613
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (dataArray)
614 {
615 3 Data polyLineCellData;
616
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
13 for (; dataArray != nullptr; dataArray = dataArray->NextSiblingElement("DataArray"))
617 {
618 7 const char *attributeText = dataArray->Attribute("Name");
619
620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (attributeText == nullptr)
621 DUNE_THROW(Dune::IOError, "Couldn't get Name attribute of a cell data array.");
622
623
3/8
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 7 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
14 polyLineCellData[std::string(attributeText)] = parseDataArray_<std::vector<double>>(dataArray);
624
625
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (verbose)
626
3/6
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 7 times.
✗ Branch 8 not taken.
7 std::cout << "Read cell data field " << attributeText << std::endl;
627 }
628
629 // a polyline can have many points in the VTK format
630 // we split the line in segments with two points
631 // so we also need to duplicate the cell data to fit the increased line number
632
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 const XMLElement* offsetsNode = findDataArray_(linesNode, "offsets");
633
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 const auto offsets = parseDataArray_<std::vector<unsigned int>>(offsetsNode);
634
635
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 if (offsets.size() != polyLineCellData.begin()->second.size())
636 DUNE_THROW(Dune::IOError, "Expected the same number of cell data entries (is "
637 << polyLineCellData.begin()->second.size()
638 << ") as polylines (" << offsets.size() << ")!");
639
640 // count the number of Dune cells to be able to resize the data vectors
641 unsigned int lastOffset = 0;
642 std::size_t numCells = 0;
643
2/2
✓ Branch 0 taken 3479 times.
✓ Branch 1 taken 3 times.
3482 for (unsigned int i = 0; i < offsets.size(); ++i)
644 {
645 3479 unsigned int offset = offsets[i];
646
2/2
✓ Branch 0 taken 3496 times.
✓ Branch 1 taken 3479 times.
6975 for (unsigned int j = 0; j < offset-lastOffset-1; ++j)
647 3496 ++numCells;
648 3479 lastOffset = offset;
649 }
650
651 // create the data arrays
652
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
10 for (const auto& dArray : polyLineCellData)
653 {
654
3/8
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 7 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
7 cellData[dArray.first] = std::vector<double>(numCells);
655
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 auto& cd = cellData[dArray.first];
656 const auto& pd = dArray.second;
657
658 lastOffset = 0;
659 std::size_t cellIdx = 0;
660
2/2
✓ Branch 0 taken 8696 times.
✓ Branch 1 taken 7 times.
8703 for (unsigned int i = 0; i < offsets.size(); ++i)
661 {
662 8696 unsigned int offset = offsets[i];
663
2/2
✓ Branch 0 taken 8730 times.
✓ Branch 1 taken 8696 times.
17426 for (unsigned int j = 0; j < offset-lastOffset-1; ++j)
664 8730 cd[cellIdx++] = pd[i];
665 8696 lastOffset = offset;
666 }
667 }
668 3 }
669 }
670 else
671 DUNE_THROW(Dune::IOError, "No Cells or Lines element found in " << fileName_);
672 }
673
674 11 const XMLElement* pointDataNode = getDataNode_(pieceNode, DataType::pointData);
675
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 4 times.
11 if (pointDataNode != nullptr)
676 {
677 7 const XMLElement* dataArray = pointDataNode->FirstChildElement("DataArray");
678
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 7 times.
39 for (; dataArray != nullptr; dataArray = dataArray->NextSiblingElement("DataArray"))
679 {
680 16 const char *attributeText = dataArray->Attribute("Name");
681
682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (attributeText == nullptr)
683 DUNE_THROW(Dune::IOError, "Couldn't get Name attribute of a point data array.");
684
685
2/6
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 16 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
32 pointData[std::string(attributeText)] = parseDataArray_<std::vector<double>>(dataArray);
686
687
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (verbose)
688 16 std::cout << "Read point data field " << attributeText << std::endl;
689 }
690 }
691 11 }
692
693 /*!
694 * \brief Get the piece node of the XMLDocument
695 * \note Returns nullptr if the piece node wasn't found
696 */
697 489 const tinyxml2::XMLElement* getPieceNode_() const
698
2/4
✓ Branch 3 taken 62 times.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
489 { return Detail::VTKReader::getPieceNode(doc_, fileName_); }
699
700 /*!
701 * \brief Get the piece node of the XMLDocument
702 * \param pieceNode the pieceNode of the vtk file
703 * \param type the vtk data type (cell data or point data)
704 * \note Returns nullptr if the data node wasn't found
705 */
706 420 const tinyxml2::XMLElement* getDataNode_(const tinyxml2::XMLElement* pieceNode, const DataType& type) const
707 {
708 420 using namespace tinyxml2;
709
710 420 const XMLElement* dataNode = nullptr;
711
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 288 times.
420 if (type == DataType::pointData)
712 132 dataNode = pieceNode->FirstChildElement("PointData");
713
1/2
✓ Branch 0 taken 288 times.
✗ Branch 1 not taken.
288 else if (type == DataType::cellData)
714 288 dataNode = pieceNode->FirstChildElement("CellData");
715 else
716 DUNE_THROW(Dune::IOError, "Only cell and point data are supported.");
717
718 420 return dataNode;
719 }
720
721 /*!
722 * \brief Find a data array with a specific name
723 * \param dataNode a cell or point data node
724 * \param name the name of the data array to be found
725 * \note Returns nullptr if the data array wasn't found
726 */
727 431 const tinyxml2::XMLElement* findDataArray_(const tinyxml2::XMLElement* dataNode, const std::string& name) const
728 {
729 431 using namespace tinyxml2;
730
731 // loop over XML node siblings to find the correct data array
732 431 const XMLElement* dataArray = dataNode->FirstChildElement("DataArray");
733
2/2
✓ Branch 0 taken 2805 times.
✓ Branch 1 taken 2 times.
5183 for (; dataArray != nullptr; dataArray = dataArray->NextSiblingElement("DataArray"))
734 {
735 2805 const char *attributeText = dataArray->Attribute("Name");
736
737
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2805 times.
2805 if (attributeText == nullptr)
738 DUNE_THROW(Dune::IOError, "Couldn't get Name attribute of a data array.");
739
740
2/2
✓ Branch 0 taken 2376 times.
✓ Branch 1 taken 429 times.
2805 if (attributeText == name)
741 break;
742 }
743
744 431 return dataArray;
745 }
746
747 /*!
748 * \brief Parses the text of a data array into a container
749 * \tparam Container a container type that has begin(), end(), push_back(), e.g. std::vector<double>
750 * \param dataArray the data array node to be parsed
751 */
752 template<class Container>
753 297 Container parseDataArray_(const tinyxml2::XMLElement* dataArray) const
754 {
755
1/2
✓ Branch 3 taken 204 times.
✗ Branch 4 not taken.
297 std::stringstream dataStream(dataArray->GetText());
756
1/2
✓ Branch 1 taken 204 times.
✗ Branch 2 not taken.
594 return readStreamToContainer<Container>(dataStream);
757 297 }
758
759 /*!
760 * \brief Return the Dune::GeometryType for a given VTK geometry type
761 * \param vtkCellType the vtk cell type
762 */
763 18827 Dune::GeometryType vtkToDuneGeomType_(unsigned int vtkCellType) const
764 {
765
3/9
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 10639 times.
✓ Branch 3 taken 4990 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3198 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
18827 switch (vtkCellType)
766 {
767 case Dune::VTK::GeometryType::vertex: return Dune::GeometryTypes::vertex;
768 case Dune::VTK::GeometryType::line: return Dune::GeometryTypes::line;
769 10639 case Dune::VTK::GeometryType::triangle: return Dune::GeometryTypes::triangle;
770 4990 case Dune::VTK::GeometryType::quadrilateral: return Dune::GeometryTypes::quadrilateral;
771 case Dune::VTK::GeometryType::tetrahedron: return Dune::GeometryTypes::tetrahedron;
772 3198 case Dune::VTK::GeometryType::hexahedron: return Dune::GeometryTypes::hexahedron;
773 case Dune::VTK::GeometryType::prism: return Dune::GeometryTypes::prism;
774 case Dune::VTK::GeometryType::pyramid: return Dune::GeometryTypes::pyramid;
775 default: DUNE_THROW(Dune::NotImplemented, "VTK cell type " << vtkCellType);
776 }
777 }
778
779 template<int dim, std::enable_if_t<(dim < 3), int> = 0>
780 std::vector<Dune::FieldVector<double, dim>>
781 6 adaptPointDimension_(std::vector<Dune::FieldVector<double, 3>>&& points3D) const
782 {
783 6 std::vector<Dune::FieldVector<double, dim>> points(points3D.size());
784
2/2
✓ Branch 0 taken 10490 times.
✓ Branch 1 taken 6 times.
10496 for (std::size_t i = 0; i < points.size(); ++i)
785
2/2
✓ Branch 0 taken 20980 times.
✓ Branch 1 taken 10490 times.
31470 for (int j = 0; j < dim; ++j)
786 20980 points[i][j] = points3D[i][j];
787 6 return points;
788 }
789
790 template<int dim, std::enable_if_t<(dim == 3), int> = 0>
791 std::vector<Dune::FieldVector<double, dim>>
792
1/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 adaptPointDimension_(std::vector<Dune::FieldVector<double, 3>>&& points3D) const
793
1/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 { return std::move(points3D); }
794
795 std::string fileName_; //!< the vtk file name
796 tinyxml2::XMLDocument doc_; //!< the xml document created from file with name fileName_
797 };
798
799 } // end namespace Dumux
800
801 #endif // DUMUX_HAVE_GRIDFORMAT
802
803 #endif
804