3.3.0
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
vtkmultiwriter.hh
Go to the documentation of this file.
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 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
24#ifndef VTK_MULTI_WRITER_HH
25#define VTK_MULTI_WRITER_HH
26
27#warning "This header is deprecated. Use the new vtkoutputmodule."
28
29#include <iostream>
30#include <limits>
31#include <list>
32#include <memory>
33#include <string>
34
35#include <dune/common/fvector.hh>
36#include <dune/istl/bvector.hh>
37
38#include <dune/grid/io/file/vtk/vtkwriter.hh>
39#include <dune/grid/io/file/vtk/function.hh>
40
41#if HAVE_MPI
42#include <mpi.h>
43#endif
44
45namespace Dumux {
46
53template <class GridView, class Mapper, class Buffer>
54class VtkNestedFunction : public Dune::VTKFunction<GridView>
55{
56 enum { dim = GridView::dimension };
57 using ctype = typename GridView::ctype;
58 using Element = typename GridView::template Codim<0>::Entity;
59
60public:
62 const GridView &gridView,
63 const Mapper &mapper,
64 const Buffer &buf,
65 int codim,
66 int numComp)
67 : name_(name)
68 , gridView_(gridView)
69 , mapper_(mapper)
70 , buf_(buf)
71 , codim_(codim)
72 , numComp_(numComp)
73 {
74 assert(std::size_t(buf_.size()) == std::size_t(mapper_.size()));
75 }
76
77 virtual std::string name () const
78 { return name_; }
79
80 virtual int ncomps() const
81 { return numComp_; }
82
83 virtual double evaluate(int mycomp,
84 const Element &element,
85 const Dune::FieldVector< ctype, dim > &xi) const
86 {
87 int idx;
88 if (codim_ == 0) {
89 // cells. map element to the index
90 idx = mapper_.index(element);
91 }
92 else if (codim_ == dim) {
93 // find vertex which is closest to xi in local
94 // coordinates. This code is based on Dune::P1VTKFunction
95 double min=1e100;
96 int imin=-1;
97 int n = element.subEntities(dim);
98
99 for (int i=0; i < n; ++i)
100 {
101 Dune::FieldVector<ctype,dim> local = referenceElement(element).position(i,dim);
102 local -= xi;
103 if (local.infinity_norm()<min)
104 {
105 min = local.infinity_norm();
106 imin = i;
107 }
108 }
109
110 // map vertex to an index
111 idx = mapper_.subIndex(element, imin, codim_);
112 }
113 else
114 DUNE_THROW(Dune::InvalidStateException,
115 "Only element and vertex based vector "
116 " fields are supported so far.");
117
118 double val = buf_[idx][mycomp];
119 using std::abs;
120 if (abs(val) < std::numeric_limits<float>::min())
121 val = 0;
122
123 return val;
124 }
125
126private:
127 const std::string name_;
128 const GridView gridView_;
129 const Mapper &mapper_;
130 const Buffer &buf_;
131 int codim_;
132 int numComp_;
133};
134
144template<class GridView, Dune::VTK::OutputType OutputValue = Dune::VTK::ascii >
145class [[deprecated("Use VtkOutputModule instead!")]] VtkMultiWriter
146{
147 enum { dim = GridView::dimension };
148 using VertexMapper = Dune::MultipleCodimMultipleGeomTypeMapper<GridView>;
149 using ElementMapper = Dune::MultipleCodimMultipleGeomTypeMapper<GridView>;
150public:
151 using VtkWriter = Dune::VTKWriter<GridView>;
152 VtkMultiWriter(const GridView &gridView,
153 const std::string &simName = "",
154 std::string multiFileName = "")
155 : gridView_(gridView)
156 , elementMapper_(gridView, Dune::mcmgElementLayout())
157 , vertexMapper_(gridView, Dune::mcmgVertexLayout())
158 {
159 simName_ = (simName.empty())?"sim":simName;
160 multiFileName_ = multiFileName;
161 if (multiFileName_.empty()) {
162 multiFileName_ = simName_;
163 multiFileName_ += ".pvd";
164 }
165
166 curWriterNum_ = 0;
167
168 commRank_ = 0;
169 commSize_ = 1;
170#if HAVE_MPI
171 MPI_Comm_rank(MPI_COMM_WORLD, &commRank_);
172 MPI_Comm_size(MPI_COMM_WORLD, &commSize_);
173#endif
174 }
175
177 {
178 finishMultiFile_();
179
180 if (commRank_ == 0)
181 multiFile_.close();
182 }
183
187 int curWriterNum() const
188 { return curWriterNum_; }
189
198 {
199 elementMapper_.update();
200 vertexMapper_.update();
201 }
202
207 void beginWrite(double t)
208 {
209 if (!multiFile_.is_open()) {
210 startMultiFile_(multiFileName_);
211 }
212
213 curWriter_ = std::make_shared<VtkWriter>(gridView_, Dune::VTK::conforming);
214 curTime_ = t;
215 curOutFileName_ = fileName_();
216 }
217
224 template <class Scalar, int nComp>
225 Dune::BlockVector<Dune::FieldVector<Scalar, nComp> > *allocateManagedBuffer(int nEntities)
226 {
227 using VectorField = Dune::BlockVector<Dune::FieldVector<Scalar, nComp> >;
228
229 std::shared_ptr<ManagedVectorField_<VectorField> > vfs =
230 std::make_shared<ManagedVectorField_<VectorField> >(nEntities);
231 managedObjects_.push_back(vfs);
232 return &(vfs->vf);
233 }
234
235 template <class Scalar>
236 Dune::BlockVector<Dune::FieldVector<Scalar, 1> > *allocateManagedBuffer(int nEntities)
237 { return allocateManagedBuffer<Scalar, 1>(nEntities); }
238 Dune::BlockVector<Dune::FieldVector<double, 1> > *allocateManagedBuffer(int nEntities)
239 { return allocateManagedBuffer<double, 1>(nEntities); }
240
258 template <class DataBuffer>
259 void attachVertexData(DataBuffer &buf, std::string name, int nComps=1)
260 {
261 sanitizeBuffer_(buf, nComps);
262
263 using FunctionPtr = std::shared_ptr<const typename VtkWriter::VTKFunction>;
265 FunctionPtr fnPtr(new VtkFn(name,
266 gridView_,
267 vertexMapper_,
268 buf,
269 /*codim=*/dim,
270 nComps));
271 curWriter_->addVertexData(fnPtr);
272 }
273
289 template <class DataBuffer>
290 void attachCellData(DataBuffer &buf, std::string name, int nComps = 1)
291 {
292 sanitizeBuffer_(buf, nComps);
293
294 using FunctionPtr = std::shared_ptr<const typename VtkWriter::VTKFunction>;
296 FunctionPtr fnPtr(new VtkFn(name,
297 gridView_,
298 elementMapper_,
299 buf,
300 /*codim=*/0,
301 nComps));
302 curWriter_->addCellData(fnPtr);
303 }
304
312 template <class DataBuffer>
313 void attachDofData(DataBuffer &buf, std::string name, bool isVertexData, int nComps = 1)
314 {
315 if (isVertexData)
316 attachVertexData(buf, name, nComps);
317 else
318 attachCellData(buf, name, nComps);
319 }
320
328 void endWrite(bool onlyDiscard = false)
329 {
330 if (!onlyDiscard) {
331 ++curWriterNum_;
332 curWriter_->write(curOutFileName_.c_str(), OutputValue);
333
334 // determine name to write into the multi-file for the
335 // current time step
336 std::string fileName;
337 std::string suffix = fileSuffix_();
338 if (commSize_ == 1) {
339 fileName = curOutFileName_;
340 multiFile_.precision(16);
341 multiFile_ << " <DataSet timestep=\""
342 << curTime_
343 << "\" file=\""
344 << fileName << "." << suffix << "\"/>\n";
345 }
346 if (commSize_ > 1 && commRank_ == 0) {
347 // only the first process updates the multi-file
348 for (int part=0; part < commSize_; ++part) {
349 fileName = fileName_(part);
350 multiFile_.precision(16);
351 multiFile_ << " <DataSet "
352 << " part=\"" << part << "\""
353 << " timestep=\"" << curTime_ << "\""
354 << " file=\"" << fileName << "." << suffix << "\"/>\n";
355 }
356 }
357 }
358
359 // discard managed objects
360 while (managedObjects_.begin() != managedObjects_.end()) {
361 managedObjects_.pop_front();
362 }
363
364 // temporarily write the closing XML mumbo-jumbo to the mashup
365 // file so that the data set can be loaded even if the
366 // simulation is aborted (or not yet finished)
367 finishMultiFile_();
368 }
369
373 template <class Restarter>
374 void serialize(Restarter &res)
375 {
376 res.serializeSectionBegin("VTKMultiWriter");
377 res.serializeStream() << curWriterNum_ << "\n";
378
379 if (commRank_ == 0) {
380 size_t fileLen = 0;
381 size_t filePos = 0;
382 if (multiFile_.is_open()) {
383 // write the meta file into the restart file
384 filePos = multiFile_.tellp();
385 multiFile_.seekp(0, std::ios::end);
386 fileLen = multiFile_.tellp();
387 multiFile_.seekp(filePos);
388 }
389
390 res.serializeStream() << fileLen << " " << filePos << "\n";
391
392 if (fileLen > 0) {
393 std::ifstream multiFileIn(multiFileName_.c_str());
394 char *tmp = new char[fileLen];
395 multiFileIn.read(tmp, fileLen);
396 res.serializeStream().write(tmp, fileLen);
397 delete[] tmp;
398 }
399 }
400
401 res.serializeSectionEnd();
402 }
403
407 template <class Restarter>
408 void deserialize(Restarter &res)
409 {
410 res.deserializeSectionBegin("VTKMultiWriter");
411 res.deserializeStream() >> curWriterNum_;
412
413 if (commRank_ == 0) {
414 std::string dummy;
415 std::getline(res.deserializeStream(), dummy);
416
417 // recreate the meta file from the restart file
418 size_t filePos, fileLen;
419 res.deserializeStream() >> fileLen >> filePos;
420 std::getline(res.deserializeStream(), dummy);
421 if (multiFile_.is_open())
422 multiFile_.close();
423
424 if (fileLen > 0) {
425 multiFile_.open(multiFileName_.c_str());
426
427 char *tmp = new char[fileLen];
428 res.deserializeStream().read(tmp, fileLen);
429 multiFile_.write(tmp, fileLen);
430 delete[] tmp;
431 }
432
433 multiFile_.seekp(filePos);
434 }
435 else {
436 std::string tmp;
437 std::getline(res.deserializeStream(), tmp);
438 }
439 res.deserializeSectionEnd();
440 }
441
442private:
443 std::string fileName_()
444 {
445 std::ostringstream oss;
446 oss << simName_ << "-" << std::setw(5) << std::setfill('0') << curWriterNum_;
447 return oss.str();
448 }
449
450 std::string fileName_(int rank)
451 {
452 if (commSize_ > 1) {
453 std::ostringstream oss;
454 oss << "s" << std::setw(4) << std::setfill('0') << commSize_
455 << "-p" << std::setw(4) << std::setfill('0') << rank
456 << "-" << simName_ << "-"
457 << std::setw(5) << curWriterNum_;
458 return oss.str();
459
460 return oss.str();
461 }
462 else {
463 std::ostringstream oss;
464 oss << simName_ << "-" << std::setw(5) << std::setfill('0') << curWriterNum_;
465 return oss.str();
466 }
467 }
468
469 std::string fileSuffix_()
470 {
471 return (GridView::dimension == 1)?"vtp":"vtu";
472 }
473
474
475 void startMultiFile_(const std::string &multiFileName)
476 {
477 // only the first process writes to the multi-file
478 if (commRank_ == 0) {
479 // generate one meta vtk-file holding the individual time steps
480 multiFile_.open(multiFileName.c_str());
481 multiFile_ <<
482 "<?xml version=\"1.0\"?>\n"
483 "<VTKFile type=\"Collection\"\n"
484 " version=\"0.1\"\n"
485 " byte_order=\"LittleEndian\"\n"
486 " compressor=\"vtkZLibDataCompressor\">\n"
487 " <Collection>\n";
488 }
489 }
490
491 void finishMultiFile_()
492 {
493 // only the first process writes to the multi-file
494 if (commRank_ == 0) {
495 // make sure that we always have a working meta file
496 std::ofstream::pos_type pos = multiFile_.tellp();
497 multiFile_ <<
498 " </Collection>\n"
499 "</VTKFile>\n";
500 multiFile_.seekp(pos);
501 multiFile_.flush();
502 }
503 }
504
505 // make sure that all values can be displayed by paraview
506 template <class DataBuffer>
507 void sanitizeBuffer_(DataBuffer &b, int nComps)
508 {
509 for (unsigned int i = 0; i < b.size(); ++i) {
510 for (int j = 0; j < nComps; ++j) {
511 // set values which are too small to 0 to avoid
512 // problems with paraview
513 if (std::abs(b[i][j])
514 < std::numeric_limits<float>::min())
515 {
516 b[i][j] = 0.0;
517 }
518 }
519 }
520 }
521
523 // Trick: when ever we attach some data we need to copy the
524 // vector field (that's because Dune::VTKWriter is not
525 // able to write fields one at a time and using
526 // VTKWriter::add*Data doesn't copy the data's
527 // representation so that once we arrive at the point
528 // where we want to write the data to disk, it might
529 // exist anymore). The problem we encounter there is
530 // that add*Data accepts arbitrary types as vector
531 // fields, but we need a single type for the linked list
532 // which keeps track of the data added. The trick we use
533 // here is to define a non-template base class with a
534 // virtual destructor for the type given to the linked
535 // list and a derived template class which actually
536 // knows the type of the vector field it must delete.
537
538 class ManagedObject_
539 {
540 public:
541 virtual ~ManagedObject_()
542 {}
543 };
544
545 template <class VF>
546 class ManagedVectorField_ : public ManagedObject_
547 {
548 public:
549 ManagedVectorField_(int size)
550 : vf(size)
551 { }
552 VF vf;
553 };
554 // end hack
556
557 const GridView gridView_;
558 ElementMapper elementMapper_;
559 VertexMapper vertexMapper_;
560
561 std::string simName_;
562 std::ofstream multiFile_;
563 std::string multiFileName_;
564
565 int commSize_; // number of processes in the communicator
566 int commRank_; // rank of the current process in the communicator
567
568 std::shared_ptr<VtkWriter> curWriter_;
569 double curTime_;
570 std::string curOutFileName_;
571 int curWriterNum_;
572
573 std::list<std::shared_ptr<ManagedObject_> > managedObjects_;
574};
575}
576
577#endif
Definition: adapt.hh:29
Definition: common/pdesolver.hh:35
Provides a vector-valued function using Dune::FieldVectors as elements. DEPRECATED will be removed on...
Definition: vtkmultiwriter.hh:55
virtual int ncomps() const
Definition: vtkmultiwriter.hh:80
virtual double evaluate(int mycomp, const Element &element, const Dune::FieldVector< ctype, dim > &xi) const
Definition: vtkmultiwriter.hh:83
virtual std::string name() const
Definition: vtkmultiwriter.hh:77
VtkNestedFunction(std::string name, const GridView &gridView, const Mapper &mapper, const Buffer &buf, int codim, int numComp)
Definition: vtkmultiwriter.hh:61
Simplifies writing multi-file VTK datasets.
Definition: vtkmultiwriter.hh:146
void serialize(Restarter &res)
Write the multi-writer's state to a restart file.
Definition: vtkmultiwriter.hh:374
int curWriterNum() const
Returns the number of the current VTK file.
Definition: vtkmultiwriter.hh:187
Dune::BlockVector< Dune::FieldVector< Scalar, nComp > > * allocateManagedBuffer(int nEntities)
Allocate a managed buffer for a scalar field.
Definition: vtkmultiwriter.hh:225
void beginWrite(double t)
Called when ever a new time step or a new grid must be written.
Definition: vtkmultiwriter.hh:207
Dune::BlockVector< Dune::FieldVector< double, 1 > > * allocateManagedBuffer(int nEntities)
Definition: vtkmultiwriter.hh:238
void attachVertexData(DataBuffer &buf, std::string name, int nComps=1)
Add a finished vertex centered vector field to the output.
Definition: vtkmultiwriter.hh:259
void gridChanged()
Updates the internal data structures after mesh refinement.
Definition: vtkmultiwriter.hh:197
void deserialize(Restarter &res)
Read the multi-writer's state from a restart file.
Definition: vtkmultiwriter.hh:408
Dune::VTKWriter< GridView > VtkWriter
Definition: vtkmultiwriter.hh:151
void attachDofData(DataBuffer &buf, std::string name, bool isVertexData, int nComps=1)
Add data associated with degrees of freedom to the output.
Definition: vtkmultiwriter.hh:313
Dune::BlockVector< Dune::FieldVector< Scalar, 1 > > * allocateManagedBuffer(int nEntities)
Definition: vtkmultiwriter.hh:236
void attachCellData(DataBuffer &buf, std::string name, int nComps=1)
Add a cell centered quantity to the output.
Definition: vtkmultiwriter.hh:290
~VtkMultiWriter()
Definition: vtkmultiwriter.hh:176
VtkMultiWriter(const GridView &gridView, const std::string &simName="", std::string multiFileName="")
Definition: vtkmultiwriter.hh:152
void endWrite(bool onlyDiscard=false)
Finalizes the current writer.
Definition: vtkmultiwriter.hh:328
A VTK output module to simplify writing dumux simulation data to VTK format.
Definition: io/vtkoutputmodule.hh:305