From c526c8b63d8f0653886f02adef2db85d68e4d951 Mon Sep 17 00:00:00 2001
From: Simon Praetorius <simon.praetorius@tu-dresden.de>
Date: Mon, 24 Jun 2019 12:42:39 +0200
Subject: [PATCH] add vtk sequence writer and modified the default filewriter
 settings accordingly

---
 src/amdis/CMakeLists.txt           |   1 +
 src/amdis/FileWriter.hpp           |  13 +--
 src/amdis/io/CMakeLists.txt        |   3 +
 src/amdis/io/VTKSequenceWriter.hpp | 154 +++++++++++++++++++++++++++++
 4 files changed, 165 insertions(+), 6 deletions(-)
 create mode 100644 src/amdis/io/CMakeLists.txt
 create mode 100644 src/amdis/io/VTKSequenceWriter.hpp

diff --git a/src/amdis/CMakeLists.txt b/src/amdis/CMakeLists.txt
index 1237bbc9..261e70af 100644
--- a/src/amdis/CMakeLists.txt
+++ b/src/amdis/CMakeLists.txt
@@ -71,6 +71,7 @@ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amdis)
 add_subdirectory("common")
 add_subdirectory("functions")
 add_subdirectory("gridfunctions")
+add_subdirectory("io")
 add_subdirectory("linearalgebra")
 add_subdirectory("localoperators")
 add_subdirectory("operations")
diff --git a/src/amdis/FileWriter.hpp b/src/amdis/FileWriter.hpp
index d45a086e..50ee4bb5 100644
--- a/src/amdis/FileWriter.hpp
+++ b/src/amdis/FileWriter.hpp
@@ -5,8 +5,7 @@
 
 #include <dune/functions/functionspacebases/lagrangebasis.hh>
 #include <dune/grid/io/file/vtk/vtkwriter.hh>
-#include <dune/grid/io/file/vtk/vtksequencewriter.hh>
-//#include <dune/geometry/referenceelements.hh>
+#include <dune/grid/io/file/vtk/subsamplingvtkwriter.hh>
 #include <dune/typetree/childextraction.hh>
 
 #include <amdis/FileWriterInterface.hpp>
@@ -15,6 +14,7 @@
 #include <amdis/common/StaticSize.hpp>
 #include <amdis/common/ValueCategory.hpp>
 #include <amdis/gridfunctions/DiscreteFunction.hpp>
+#include <amdis/io/VTKSequenceWriter.hpp>
 
 namespace AMDiS
 {
@@ -86,7 +86,7 @@ namespace AMDiS
         vtkWriter_ = std::make_shared<Dune::VTKWriter<GridView>>(gridView());
 
       if (animation_)
-        vtkSeqWriter_ = std::make_shared<Dune::VTKSequenceWriter<GridView>>(vtkWriter_, filename_, dir_, "");
+        vtkSeqWriter_ = std::make_shared<VTKSequenceWriter<GridView>>(vtkWriter_);
 
       vtkWriter_->addVertexData(discreteFct_, Dune::VTK::FieldInfo(name_, VTKFieldType<Range>, VTKFieldSize<Range>));
     }
@@ -97,11 +97,12 @@ namespace AMDiS
     void writeFiles(AdaptInfo& adaptInfo, bool force) override
     {
       test_exit(dir_ == "." || filesystem::exists(dir_), "Output directory '{}' does not exist!",dir_);
+      filesystem::create_directories(dir_ + "/_piecefiles");
 
       if (vtkSeqWriter_)
-        vtkSeqWriter_->write(adaptInfo.time(), mode_);
+        vtkSeqWriter_->pwrite(adaptInfo.time(), filename_, dir_, "_piecefiles", mode_);
       else if (vtkWriter_)
-        vtkWriter_->write(filesystem::path({dir_, filename_}).string(), mode_);
+        vtkWriter_->pwrite(filename_, dir_, "_piecefiles", mode_);
     }
 
   protected:
@@ -114,7 +115,7 @@ namespace AMDiS
     DiscreteFunction<GB,VT,TP> discreteFct_;
 
     std::shared_ptr<Dune::VTKWriter<GridView>> vtkWriter_;
-    std::shared_ptr<Dune::VTKSequenceWriter<GridView>> vtkSeqWriter_;
+    std::shared_ptr<VTKSequenceWriter<GridView>> vtkSeqWriter_;
 
     // write .pvd if animation=true, otherwise write only .vtu
     bool animation_;
diff --git a/src/amdis/io/CMakeLists.txt b/src/amdis/io/CMakeLists.txt
new file mode 100644
index 00000000..09203370
--- /dev/null
+++ b/src/amdis/io/CMakeLists.txt
@@ -0,0 +1,3 @@
+install(FILES
+    VtkSequenceWriter.hpp
+DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amdis/io)
diff --git a/src/amdis/io/VTKSequenceWriter.hpp b/src/amdis/io/VTKSequenceWriter.hpp
new file mode 100644
index 00000000..e8be67ce
--- /dev/null
+++ b/src/amdis/io/VTKSequenceWriter.hpp
@@ -0,0 +1,154 @@
+#pragma once
+
+#include <vector>
+#include <iostream>
+#include <sstream>
+#include <fstream>
+#include <iomanip>
+#include <memory>
+
+#include <dune/grid/io/file/vtk/common.hh>
+#include <dune/common/path.hh>
+
+#include <dune/grid/io/file/vtk/vtkwriter.hh>
+
+namespace AMDiS
+{
+  /// \brief class to write pvd-files which contains a list of all collected vtk-files
+  /**
+   * Write pvd-file suitable for easy visualization with
+   * <a href="http://www.vtk.org/">The Visualization Toolkit (VTK)</a>.
+   *
+   * \tparam GridView Grid view of the grid we are writing
+   */
+  template <class GridView>
+  class VTKSequenceWriter
+  {
+    using VTKWriter = Dune::VTKWriter<GridView>;
+
+  public:
+    /// \brief Set up the VTKSequenceWriter class
+    /**
+     * \param vtkWriter Writer object used to write the individual time step data files
+     */
+    VTKSequenceWriter(std::shared_ptr<VTKWriter> vtkWriter)
+      : vtkWriter_(std::move(vtkWriter))
+    {}
+
+    /// \brief Set up the VTKSequenceWriter class by creating a timestep writer of type \ref VTKWriter
+    /**
+     * \param gridView  GridView object passed to the constructor of the VTKWriter
+     * \param args...   Additional arguments forwarded to the VTKWriter constructor.
+     */
+    template <class... Args>
+    VTKSequenceWriter(GridView const& gridView, Args&&... args)
+      : VTKSequenceWriter<GridView>(std::make_shared<VTKWriter>(gridView, FWD(args)...))
+    {}
+
+
+    /// accessor for the underlying VTKWriter instance
+    std::shared_ptr<VTKWriter> const& vtkWriter() const
+    {
+      return vtkWriter_;
+    }
+
+    /// \brief Adds a field of cell data to the VTK file
+    template <class... Args>
+    void addCellData(Args&&... args)
+    {
+      vtkWriter_->addCellData(FWD(args)...);
+    }
+
+    /// \brief Adds a field of vertex data to the VTK file
+    template <class... Args>
+    void addVertexData (Args&&... args)
+    {
+      vtkWriter_->addVertexData(FWD(args)...);
+    }
+
+    /// \brief Writes VTK data for the given time,
+    /**
+     * \param time The time(step) for the data to be written.
+     * \param name The basename of the .pvd file (without file extension)
+     * \param type VTK output type.
+     */
+    virtual void write(double time, std::string const& name, Dune::VTK::OutputType type = Dune::VTK::ascii)
+    {
+      pwrite(time, name, ".", "", type);
+    }
+
+    /// \brief Writes VTK data for the given time,
+    /**
+     * \param time The time(step) for the data to be written.
+     * \param name The basename of the .pvd file (without file extension)
+     * \param path The directory where to put the .pvd file
+     * \param extendpath The (relative) subdirectory to path, where to put the timestep files
+     * \param type VTK output type.
+     */
+    virtual void pwrite(double time, std::string const& name, std::string const& path, std::string const& extendpath,
+                        Dune::VTK::OutputType type = Dune::VTK::ascii)
+    {
+      // remember current time step
+      unsigned int count = timesteps_.size();
+      timesteps_.push_back(time);
+
+      // write VTK file
+      vtkWriter_->pwrite(seqName(name, count), Dune::concatPaths(path, extendpath), "", type);
+
+      // write pvd file ... only on rank 0
+      if (Environment::mpiRank() == 0) {
+        std::ofstream pvdFile;
+        pvdFile.exceptions(std::ios_base::badbit | std::ios_base::failbit |
+                           std::ios_base::eofbit);
+        std::string pvdname = path + "/" + name + ".pvd";
+        pvdFile.open(pvdname.c_str());
+        pvdFile << "<?xml version=\"1.0\"?>\n"
+                << "<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"" << Dune::VTK::getEndiannessString() << "\">\n"
+                << "<Collection>\n";
+        for (unsigned int i = 0; i <= count; ++i) {
+          std::string piecepath = extendpath;
+          std::string fullname = getParallelHeaderName(seqName(name,i), piecepath, Environment::mpiSize());
+          pvdFile << "<DataSet timestep=\"" << timesteps_[i]
+                  << "\" part=\"0\" file=\""
+                  << fullname << "\"/>\n";
+        }
+        pvdFile << "</Collection>\n"
+                << "</VTKFile>\n" << std::flush;
+        pvdFile.close();
+      }
+    }
+
+  protected:
+    // create sequence name
+    static std::string seqName(std::string const& name, unsigned int count)
+    {
+      std::stringstream n;
+      n.fill('0');
+      n << name << "-" << std::setw(5) << count;
+      return n.str();
+    }
+
+    static std::string getParallelHeaderName(std::string const& name, std::string const& path, int commSize)
+    {
+      std::ostringstream s;
+      if (path.size() > 0) {
+        s << path;
+        if (path[path.size()-1] != '/')
+          s << '/';
+      }
+      s << 's' << std::setw(4) << std::setfill('0') << commSize << '-';
+      s << name;
+      if (GridView::dimension > 1)
+        s << ".pvtu";
+      else
+        s << ".pvtp";
+      return s.str();
+    }
+
+  private:
+    std::shared_ptr<VTKWriter> vtkWriter_;
+    std::vector<double> timesteps_;
+  };
+
+} // end namespace AMDiS
+
-- 
GitLab