From 10dc7b1c3a526334c9d9a26b4e090a5cc97c8916 Mon Sep 17 00:00:00 2001
From: Simon Praetorius <simon.praetorius@tu-dresden.de>
Date: Sat, 1 Sep 2018 13:33:28 +0200
Subject: [PATCH] pass ostream to writeSerialFile and writeParallelFile and set
 locale to "C"

---
 dune/vtk/pvdwriter.hh                         |  2 +-
 dune/vtk/pvdwriter.impl.hh                    | 23 ++++++------
 dune/vtk/vtktimeserieswriter.impl.hh          | 33 +++++++++++++----
 dune/vtk/vtkwriterinterface.hh                |  4 +--
 dune/vtk/vtkwriterinterface.impl.hh           | 30 +++++++++++++---
 dune/vtk/writers/vtkimagedatawriter.hh        |  4 +--
 dune/vtk/writers/vtkimagedatawriter.impl.hh   | 18 ++--------
 dune/vtk/writers/vtkrectilineargridwriter.hh  |  4 +--
 .../writers/vtkrectilineargridwriter.impl.hh  | 17 ++-------
 dune/vtk/writers/vtkstructuredgridwriter.hh   |  4 +--
 .../writers/vtkstructuredgridwriter.impl.hh   | 17 ++-------
 dune/vtk/writers/vtkunstructuredgridwriter.hh |  9 ++---
 .../writers/vtkunstructuredgridwriter.impl.hh | 36 ++++---------------
 13 files changed, 91 insertions(+), 110 deletions(-)

diff --git a/dune/vtk/pvdwriter.hh b/dune/vtk/pvdwriter.hh
index 76fe74b..a752176 100644
--- a/dune/vtk/pvdwriter.hh
+++ b/dune/vtk/pvdwriter.hh
@@ -49,7 +49,7 @@ namespace Dune
 
   protected:
     /// Write a series of vtk files in a .pvd ParaView Data file
-    void writeFile (double time, std::string const& filename) const;
+    void writeFile (double time, std::ofstream& out) const;
 
   protected:
     VtkWriter vtkWriter_;
diff --git a/dune/vtk/pvdwriter.impl.hh b/dune/vtk/pvdwriter.impl.hh
index 83a7666..fd43b80 100644
--- a/dune/vtk/pvdwriter.impl.hh
+++ b/dune/vtk/pvdwriter.impl.hh
@@ -31,23 +31,24 @@ void PvdWriter<W>
   timesteps_.emplace_back(time, filename + ext);
   vtkWriter_.write(filename + ext);
 
-  if (rank == 0)
-    writeFile(time, p.string() + ".pvd");
+  if (rank == 0) {
+    std::ofstream out(p.string() + ".pvd", std::ios_base::ate | std::ios::binary);
+    assert(out.is_open());
+
+    out.imbue(std::locale::classic());
+    out << std::setprecision(datatype_ == Vtk::FLOAT32
+      ? std::numeric_limits<float>::digits10+2
+      : std::numeric_limits<double>::digits10+2);
+
+    writeFile(time, out);
+  }
 }
 
 
 template <class W>
 void PvdWriter<W>
-  ::writeFile (double time, std::string const& filename) const
+  ::writeFile (double time, std::ofstream& out) const
 {
-  std::ofstream out(filename, std::ios_base::ate | std::ios::binary);
-  assert(out.is_open());
-
-  if (datatype_ == Vtk::FLOAT32)
-    out << std::setprecision(std::numeric_limits<float>::digits10+2);
-  else
-    out << std::setprecision(std::numeric_limits<double>::digits10+2);
-
   out << "<?xml version=\"1.0\"?>\n";
   out << "<VTKFile"
       << " type=\"Collection\""
diff --git a/dune/vtk/vtktimeserieswriter.impl.hh b/dune/vtk/vtktimeserieswriter.impl.hh
index beac3b6..3b886ec 100644
--- a/dune/vtk/vtktimeserieswriter.impl.hh
+++ b/dune/vtk/vtktimeserieswriter.impl.hh
@@ -70,7 +70,7 @@ void VtkTimeseriesWriter<W>
   p.remove_filename();
   p /= name.string();
 
-  std::string filenameBase = p.string() + "_ts";
+  std::string filename = p.string() + "_ts";
 
   int rank = 0;
   int num_ranks = 1;
@@ -78,15 +78,36 @@ void VtkTimeseriesWriter<W>
     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
     MPI_Comm_size(MPI_COMM_WORLD, &num_ranks);
     if (num_ranks > 1)
-      filenameBase = p.string() + "_ts_p" + std::to_string(rank);
+      filename = p.string() + "_ts_p" + std::to_string(rank);
 #endif
 
-  std::string filename = filenameBase + "." + vtkWriter_.getFileExtension();
-  vtkWriter_.writeTimeseriesSerialFile(filename, filenameMesh_, timesteps_, blocks_);
+  { // 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_);
+  }
 
 #ifdef HAVE_MPI
-  if (num_ranks > 1 && rank == 0)
-    vtkWriter_.writeTimeseriesParallelFile(p.string() + "_ts", num_ranks, timesteps_);
+  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_);
+  }
 #endif
 
   // remove all temporary data files
diff --git a/dune/vtk/vtkwriterinterface.hh b/dune/vtk/vtkwriterinterface.hh
index 4fa6b7f..ffc1a5b 100644
--- a/dune/vtk/vtkwriterinterface.hh
+++ b/dune/vtk/vtkwriterinterface.hh
@@ -80,12 +80,12 @@ namespace Dune
 
   private:
     /// Write a serial VTK file in Unstructured format
-    virtual void writeSerialFile (std::string const& filename) const = 0;
+    virtual void writeSerialFile (std::ofstream& out) const = 0;
 
     /// Write a parallel VTK file `pfilename.pvtu` in Unstructured format,
     /// with `size` the number of pieces and serial files given by `pfilename_p[i].vtu`
     /// for [i] in [0,...,size).
-    virtual void writeParallelFile (std::string const& pfilename, int size) const = 0;
+    virtual void writeParallelFile (std::ofstream& out, std::string const& pfilename, int size) const = 0;
 
     /// Return the file extension of the serial file (not including the dot)
     virtual std::string fileExtension () const = 0;
diff --git a/dune/vtk/vtkwriterinterface.impl.hh b/dune/vtk/vtkwriterinterface.impl.hh
index 28692e8..4242cf6 100644
--- a/dune/vtk/vtkwriterinterface.impl.hh
+++ b/dune/vtk/vtkwriterinterface.impl.hh
@@ -28,7 +28,7 @@ void VtkWriterInterface<GV,DC>
   p.remove_filename();
   p /= name.string();
 
-  std::string filename = p.string() + "." + fileExtension();
+  std::string filename = p.string();
 
   int rank = 0;
   int num_ranks = 1;
@@ -37,14 +37,34 @@ void VtkWriterInterface<GV,DC>
   MPI_Comm_rank(MPI_COMM_WORLD, &rank);
   MPI_Comm_size(MPI_COMM_WORLD, &num_ranks);
   if (num_ranks > 1)
-    filename = p.string() + "_p" + std::to_string(rank) + "." + fileExtension();
+    filename = p.string() + "_p" + std::to_string(rank);
 #endif
 
-  writeSerialFile(filename);
+  { // write serial file
+    std::ofstream serial_out(filename + "." + fileExtension(), std::ios_base::ate | std::ios::binary);
+    assert(serial_out.is_open());
+
+    serial_out.imbue(std::locale::classic());
+    serial_out << std::setprecision(datatype_ == Vtk::FLOAT32
+      ? std::numeric_limits<float>::digits10+2
+      : std::numeric_limits<double>::digits10+2);
+
+    writeSerialFile(serial_out);
+  }
 
 #ifdef HAVE_MPI
-  if (num_ranks > 1 && rank == 0)
-    writeParallelFile(p.string(), num_ranks);
+  if (num_ranks > 1 && rank == 0) {
+    // write parallel file
+    std::ofstream parallel_out(p.string() + ".p" + fileExtension(), std::ios_base::ate | std::ios::binary);
+    assert(parallel_out.is_open());
+
+    parallel_out.imbue(std::locale::classic());
+    parallel_out << std::setprecision(datatype_ == Vtk::FLOAT32
+      ? std::numeric_limits<float>::digits10+2
+      : std::numeric_limits<double>::digits10+2);
+
+    writeParallelFile(parallel_out, p.string(), num_ranks);
+  }
 #endif
 }
 
diff --git a/dune/vtk/writers/vtkimagedatawriter.hh b/dune/vtk/writers/vtkimagedatawriter.hh
index cc6f04e..50db5b7 100644
--- a/dune/vtk/writers/vtkimagedatawriter.hh
+++ b/dune/vtk/writers/vtkimagedatawriter.hh
@@ -37,12 +37,12 @@ namespace Dune
 
   private:
     /// Write a serial VTK file in Unstructured format
-    virtual void writeSerialFile (std::string const& filename) const override;
+    virtual void writeSerialFile (std::ofstream& out) const override;
 
     /// Write a parallel VTK file `pfilename.pvtu` in Unstructured format,
     /// with `size` the number of pieces and serial files given by `pfilename_p[i].vtu`
     /// for [i] in [0,...,size).
-    virtual void writeParallelFile (std::string const& pfilename, int size) const override;
+    virtual void writeParallelFile (std::ofstream& out, std::string const& pfilename, int size) const override;
 
     virtual std::string fileExtension () const override
     {
diff --git a/dune/vtk/writers/vtkimagedatawriter.impl.hh b/dune/vtk/writers/vtkimagedatawriter.impl.hh
index b976b42..f37691c 100644
--- a/dune/vtk/writers/vtkimagedatawriter.impl.hh
+++ b/dune/vtk/writers/vtkimagedatawriter.impl.hh
@@ -18,18 +18,8 @@ namespace Dune {
 
 template <class GV, class DC>
 void VtkImageDataWriter<GV,DC>
-  ::writeSerialFile (std::string const& filename) const
+  ::writeSerialFile (std::ofstream& out) const
 {
-  std::ofstream out(filename, std::ios_base::ate | std::ios::binary);
-  assert(out.is_open());
-
-  if (format_ == Vtk::ASCII) {
-    if (datatype_ == Vtk::FLOAT32)
-      out << std::setprecision(std::numeric_limits<float>::digits10+2);
-    else
-      out << std::setprecision(std::numeric_limits<double>::digits10+2);
-  }
-
   std::vector<pos_type> offsets; // pos => offset
   out << "<VTKFile"
       << " type=\"ImageData\""
@@ -74,12 +64,8 @@ void VtkImageDataWriter<GV,DC>
 
 template <class GV, class DC>
 void VtkImageDataWriter<GV,DC>
-  ::writeParallelFile (std::string const& pfilename, int /*size*/) const
+  ::writeParallelFile (std::ofstream& out, std::string const& pfilename, int /*size*/) const
 {
-  std::string filename = pfilename + ".p" + this->fileExtension();
-  std::ofstream out(filename, std::ios_base::ate | std::ios::binary);
-  assert(out.is_open());
-
   out << "<VTKFile"
       << " type=\"PImageData\""
       << " version=\"1.0\""
diff --git a/dune/vtk/writers/vtkrectilineargridwriter.hh b/dune/vtk/writers/vtkrectilineargridwriter.hh
index 050e899..f7c0317 100644
--- a/dune/vtk/writers/vtkrectilineargridwriter.hh
+++ b/dune/vtk/writers/vtkrectilineargridwriter.hh
@@ -37,12 +37,12 @@ namespace Dune
 
   private:
     /// Write a serial VTK file in Unstructured format
-    virtual void writeSerialFile (std::string const& filename) const override;
+    virtual void writeSerialFile (std::ofstream& out) const override;
 
     /// Write a parallel VTK file `pfilename.pvtu` in Unstructured format,
     /// with `size` the number of pieces and serial files given by `pfilename_p[i].vtu`
     /// for [i] in [0,...,size).
-    virtual void writeParallelFile (std::string const& pfilename, int size) const override;
+    virtual void writeParallelFile (std::ofstream& out, std::string const& pfilename, int size) const override;
 
     void writeCoordinates (std::ofstream& out, std::vector<pos_type>& offsets,
                            Std::optional<std::size_t> timestep = {}) const;
diff --git a/dune/vtk/writers/vtkrectilineargridwriter.impl.hh b/dune/vtk/writers/vtkrectilineargridwriter.impl.hh
index 48a650e..3ac7235 100644
--- a/dune/vtk/writers/vtkrectilineargridwriter.impl.hh
+++ b/dune/vtk/writers/vtkrectilineargridwriter.impl.hh
@@ -18,17 +18,8 @@ namespace Dune {
 
 template <class GV, class DC>
 void VtkRectilinearGridWriter<GV,DC>
-  ::writeSerialFile (std::string const& filename) const
+  ::writeSerialFile (std::ofstream& out) const
 {
-  std::ofstream out(filename, std::ios_base::ate | std::ios::binary);
-  assert(out.is_open());
-  if (format_ == Vtk::ASCII) {
-    if (datatype_ == Vtk::FLOAT32)
-      out << std::setprecision(std::numeric_limits<float>::digits10+2);
-    else
-      out << std::setprecision(std::numeric_limits<double>::digits10+2);
-  }
-
   std::vector<pos_type> offsets; // pos => offset
   out << "<VTKFile"
       << " type=\"RectilinearGrid\""
@@ -74,12 +65,8 @@ void VtkRectilinearGridWriter<GV,DC>
 
 template <class GV, class DC>
 void VtkRectilinearGridWriter<GV,DC>
-  ::writeParallelFile (std::string const& pfilename, int /*size*/) const
+  ::writeParallelFile (std::ofstream& out, std::string const& pfilename, int /*size*/) const
 {
-  std::string filename = pfilename + ".p" + this->fileExtension();
-  std::ofstream out(filename, std::ios_base::ate | std::ios::binary);
-  assert(out.is_open());
-
   out << "<VTKFile"
       << " type=\"PRectilinearGrid\""
       << " version=\"1.0\""
diff --git a/dune/vtk/writers/vtkstructuredgridwriter.hh b/dune/vtk/writers/vtkstructuredgridwriter.hh
index f6ebc6a..522d472 100644
--- a/dune/vtk/writers/vtkstructuredgridwriter.hh
+++ b/dune/vtk/writers/vtkstructuredgridwriter.hh
@@ -37,12 +37,12 @@ namespace Dune
 
   private:
     /// Write a serial VTK file in Unstructured format
-    virtual void writeSerialFile (std::string const& filename) const override;
+    virtual void writeSerialFile (std::ofstream& out) const override;
 
     /// Write a parallel VTK file `pfilename.pvtu` in Unstructured format,
     /// with `size` the number of pieces and serial files given by `pfilename_p[i].vtu`
     /// for [i] in [0,...,size).
-    virtual void writeParallelFile (std::string const& pfilename, int size) const override;
+    virtual void writeParallelFile (std::ofstream& out, std::string const& pfilename, int size) const override;
 
     virtual std::string fileExtension () const override
     {
diff --git a/dune/vtk/writers/vtkstructuredgridwriter.impl.hh b/dune/vtk/writers/vtkstructuredgridwriter.impl.hh
index 1dcd724..30e6323 100644
--- a/dune/vtk/writers/vtkstructuredgridwriter.impl.hh
+++ b/dune/vtk/writers/vtkstructuredgridwriter.impl.hh
@@ -18,17 +18,8 @@ namespace Dune {
 
 template <class GV, class DC>
 void VtkStructuredGridWriter<GV,DC>
-  ::writeSerialFile (std::string const& filename) const
+  ::writeSerialFile (std::ofstream& out) const
 {
-  std::ofstream out(filename, std::ios_base::ate | std::ios::binary);
-  assert(out.is_open());
-  if (format_ == Vtk::ASCII) {
-    if (datatype_ == Vtk::FLOAT32)
-      out << std::setprecision(std::numeric_limits<float>::digits10+2);
-    else
-      out << std::setprecision(std::numeric_limits<double>::digits10+2);
-  }
-
   std::vector<pos_type> offsets; // pos => offset
   out << "<VTKFile"
       << " type=\"StructuredGrid\""
@@ -72,12 +63,8 @@ void VtkStructuredGridWriter<GV,DC>
 
 template <class GV, class DC>
 void VtkStructuredGridWriter<GV,DC>
-  ::writeParallelFile (std::string const& pfilename, int /*size*/) const
+  ::writeParallelFile (std::ofstream& out, std::string const& pfilename, int /*size*/) const
 {
-  std::string filename = pfilename + ".p" + this->fileExtension();
-  std::ofstream out(filename, std::ios_base::ate | std::ios::binary);
-  assert(out.is_open());
-
   out << "<VTKFile"
       << " type=\"PStructuredGrid\""
       << " version=\"1.0\""
diff --git a/dune/vtk/writers/vtkunstructuredgridwriter.hh b/dune/vtk/writers/vtkunstructuredgridwriter.hh
index 2429214..fb2003f 100644
--- a/dune/vtk/writers/vtkunstructuredgridwriter.hh
+++ b/dune/vtk/writers/vtkunstructuredgridwriter.hh
@@ -39,12 +39,12 @@ namespace Dune
 
   private:
     /// Write a serial VTK file in Unstructured format
-    virtual void writeSerialFile (std::string const& filename) const override;
+    virtual void writeSerialFile (std::ofstream& out) const override;
 
     /// Write a parallel VTK file `pfilename.pvtu` in Unstructured format,
     /// with `size` the number of pieces and serial files given by `pfilename_p[i].vtu`
     /// for [i] in [0,...,size).
-    virtual void writeParallelFile (std::string const& pfilename, int size) const override;
+    virtual void writeParallelFile (std::ofstream& out, std::string const& pfilename, int size) const override;
 
     /// Write a series of timesteps in one file
     /**
@@ -55,13 +55,14 @@ namespace Dune
      * \param blocks        A list of block sizes of the binary data stored in the files.
      *                      Order: (points, cells, pointdata[0], celldata[0], pointdata[1], celldata[1],...)
      **/
-    void writeTimeseriesSerialFile (std::string const& filename,
+    void writeTimeseriesSerialFile (std::ofstream& out,
                                     std::string const& filenameMesh,
                                     std::vector<std::pair<double, std::string>> const& timesteps,
                                     std::vector<std::uint64_t> const& blocks) const;
 
     /// Write parallel VTK file for series of timesteps
-    void writeTimeseriesParallelFile (std::string const& pfilename, int size,
+    void writeTimeseriesParallelFile (std::ofstream& out,
+                                      std::string const& pfilename, int size,
                                       std::vector<std::pair<double, std::string>> const& timesteps) const;
 
     virtual std::string fileExtension () const override
diff --git a/dune/vtk/writers/vtkunstructuredgridwriter.impl.hh b/dune/vtk/writers/vtkunstructuredgridwriter.impl.hh
index 9bc4482..0a4e8b7 100644
--- a/dune/vtk/writers/vtkunstructuredgridwriter.impl.hh
+++ b/dune/vtk/writers/vtkunstructuredgridwriter.impl.hh
@@ -18,18 +18,8 @@ namespace Dune {
 
 template <class GV, class DC>
 void VtkUnstructuredGridWriter<GV,DC>
-  ::writeSerialFile (std::string const& filename) const
+  ::writeSerialFile (std::ofstream& out) const
 {
-  std::ofstream out(filename, std::ios_base::ate | std::ios::binary);
-  assert(out.is_open());
-
-  if (format_ == Vtk::ASCII) {
-    if (datatype_ == Vtk::FLOAT32)
-      out << std::setprecision(std::numeric_limits<float>::digits10+2);
-    else
-      out << std::setprecision(std::numeric_limits<double>::digits10+2);
-  }
-
   std::vector<pos_type> offsets; // pos => offset
   out << "<VTKFile"
       << " type=\"UnstructuredGrid\""
@@ -77,12 +67,8 @@ void VtkUnstructuredGridWriter<GV,DC>
 
 template <class GV, class DC>
 void VtkUnstructuredGridWriter<GV,DC>
-  ::writeParallelFile (std::string const& pfilename, int size) const
+  ::writeParallelFile (std::ofstream& out, std::string const& pfilename, int size) const
 {
-  std::string filename = pfilename + ".pvtu";
-  std::ofstream out(filename, std::ios_base::ate | std::ios::binary);
-  assert(out.is_open());
-
   out << "<VTKFile"
       << " type=\"PUnstructuredGrid\""
       << " version=\"1.0\""
@@ -136,19 +122,12 @@ void VtkUnstructuredGridWriter<GV,DC>
 
 template <class GV, class DC>
 void VtkUnstructuredGridWriter<GV,DC>
-  ::writeTimeseriesSerialFile (std::string const& filename,
+  ::writeTimeseriesSerialFile (std::ofstream& out,
                                std::string const& filenameMesh,
                                std::vector<std::pair<double, std::string>> const& timesteps,
                                std::vector<std::uint64_t> const& blocks) const
 {
-  std::ofstream out(filename, std::ios_base::ate | std::ios::binary);
-  assert(out.is_open());
-
   assert(is_a(format_, Vtk::APPENDED));
-  if (datatype_ == Vtk::FLOAT32)
-    out << std::setprecision(std::numeric_limits<float>::digits10+2);
-  else
-    out << std::setprecision(std::numeric_limits<double>::digits10+2);
 
   std::vector<std::vector<pos_type>> offsets(timesteps.size()); // pos => offset
   out << "<VTKFile"
@@ -253,12 +232,11 @@ void VtkUnstructuredGridWriter<GV,DC>
 
 template <class GV, class DC>
 void VtkUnstructuredGridWriter<GV,DC>
-  ::writeTimeseriesParallelFile (std::string const& pfilename, int size, std::vector<std::pair<double, std::string>> const& timesteps) const
+  ::writeTimeseriesParallelFile (std::ofstream& out,
+                                 std::string const& pfilename,
+                                 int size,
+                                 std::vector<std::pair<double, std::string>> const& timesteps) const
 {
-  std::string filename = pfilename + ".pvtu";
-  std::ofstream out(filename, std::ios_base::ate | std::ios::binary);
-  assert(out.is_open());
-
   out << "<VTKFile"
       << " type=\"PUnstructuredGrid\""
       << " version=\"1.0\""
-- 
GitLab