vtktimeserieswriter.impl.hh 3.46 KB
Newer Older
1
2
3
#pragma once

#include <algorithm>
4
#include <cstdio>
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iomanip>
#include <iostream>
#include <iterator>
#include <fstream>
#include <sstream>
#include <string>

#ifdef HAVE_ZLIB
#include <zlib.h>
#endif

#include <dune/geometry/referenceelements.hh>
#include <dune/geometry/type.hh>

#include <dune/vtk/utility/enum.hh>
#include <dune/vtk/utility/filesystem.hh>
#include <dune/vtk/utility/string.hh>

namespace Dune {

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
template <class W>
VtkTimeseriesWriter<W>::~VtkTimeseriesWriter ()
{
  if (initialized_) {
    int ec = std::remove(filenameMesh_.c_str());
    assert(ec == 0);
    for (auto const& timestep : timesteps_) {
      ec = std::remove(timestep.second.c_str());
      assert(ec == 0);
    }
  }
  std::remove(tmpDir_.string().c_str());
}


40
41
template <class W>
void VtkTimeseriesWriter<W>
42
  ::writeTimestep (double time, std::string const& fn, bool writeCollection) const
43
{
44
45
46
  auto name = filesystem::path(fn).stem();
  auto tmp = tmpDir_;
  tmp /= name.string();
47

48
  vtkWriter_.dataCollector_.update();
49

50
51
52
53
54
55
56
57
58
59
60
  std::string filenameBase = tmp.string();

  int rank = 0;
  int num_ranks = 1;
  #ifdef HAVE_MPI
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &num_ranks);
    if (num_ranks > 1)
      filenameBase = tmp.string() + "_p" + std::to_string(rank);
  #endif

61
62
  if (!initialized_) {
    // write points and cells only once
63
    filenameMesh_ = filenameBase + ".mesh.vtkdata";
64
65
    std::ofstream out(filenameMesh_, std::ios_base::ate | std::ios::binary);
    vtkWriter_.writeGridAppended(out, blocks_);
66
67
68
    initialized_ = true;
  }

69
  std::string filenameData = filenameBase + "_t" + std::to_string(timesteps_.size()) + ".vtkdata";
70
71
  std::ofstream out(filenameData, std::ios_base::ate | std::ios::binary);
  vtkWriter_.writeDataAppended(out, blocks_);
72
  timesteps_.emplace_back(time, filenameData);
73
74
75

  if (writeCollection)
    write(fn);
76
77
78
79
80
}


template <class W>
void VtkTimeseriesWriter<W>
81
  ::write (std::string const& fn) const
82
{
83
84
  assert( initialized_ );

85
86
87
88
  auto p = filesystem::path(fn);
  auto name = p.stem();
  p.remove_filename();
  p /= name.string();
89

90
  std::string filename = p.string() + "_ts";
91
92
93
94
95
96
97

  int rank = 0;
  int num_ranks = 1;
#ifdef HAVE_MPI
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &num_ranks);
    if (num_ranks > 1)
98
      filename = p.string() + "_ts_p" + std::to_string(rank);
99
100
#endif

101
102
103
104
105
106
107
108
109
110
111
112
  { // write serial file
    std::ofstream serial_out(filename + "." + vtkWriter_.getFileExtension(),
                             std::ios_base::ate | std::ios::binary);
    assert(serial_out.is_open());

    serial_out.imbue(std::locale::classic());
    serial_out << std::setprecision(vtkWriter_.getDatatype() == Vtk::FLOAT32
      ? std::numeric_limits<float>::digits10+2
      : std::numeric_limits<double>::digits10+2);

    vtkWriter_.writeTimeseriesSerialFile(serial_out, filenameMesh_, timesteps_, blocks_);
  }
113
114

#ifdef HAVE_MPI
115
116
117
118
119
120
121
122
123
124
125
126
127
  if (num_ranks > 1 && rank == 0) {
    // write parallel file
    std::ofstream parallel_out(p.string() + "_ts.p" + vtkWriter_.getFileExtension(),
                               std::ios_base::ate | std::ios::binary);
    assert(parallel_out.is_open());

    parallel_out.imbue(std::locale::classic());
    parallel_out << std::setprecision(vtkWriter_.getDatatype() == Vtk::FLOAT32
      ? std::numeric_limits<float>::digits10+2
      : std::numeric_limits<double>::digits10+2);

    vtkWriter_.writeTimeseriesParallelFile(parallel_out, p.string() + "_ts", num_ranks, timesteps_);
  }
128
#endif
129
130
131
}

} // end namespace Dune