From fcaec46cbc8f480003d202c5ee6c1fcb8efc4a27 Mon Sep 17 00:00:00 2001
From: Simon Praetorius <simon.praetorius@tu-dresden.de>
Date: Thu, 23 Aug 2018 10:54:53 +0200
Subject: [PATCH] cleanup of datacollectors

---
 dune/vtk/datacollector.hh | 270 +++++++++++++++++++++-----------------
 src/vtkreader.cc          |  20 +--
 2 files changed, 161 insertions(+), 129 deletions(-)

diff --git a/dune/vtk/datacollector.hh b/dune/vtk/datacollector.hh
index 328a86a..d1f7fc8 100644
--- a/dune/vtk/datacollector.hh
+++ b/dune/vtk/datacollector.hh
@@ -15,20 +15,32 @@ struct Cells
   std::vector<std::int64_t> connectivity;
 };
 
+template <class GridView, class Derived>
 class DataCollectorInterface
 {
-private:
-  DataCollectorInterface () = default;
-
 public:
+
+  DataCollectorInterface (GridView const& gridView)
+    : gridView_(gridView)
+  {}
+
   /// \brief Return the number of points in the grid
-  std::uint64_t numPoints () const;
+  std::uint64_t numPoints () const
+  {
+    return asDerived().numPointsImpl();
+  }
 
   /// \brief Return the number of cells in the grid
-  std::uint64_t numCells () const;
+  std::uint64_t numCells () const
+  {
+    return asDerived().numCellsImpl();
+  }
 
   /// Update the DataCollector on the current GridView
-  void update ();
+  void update ()
+  {
+    asDerived().updateImpl();
+  }
 
   /// \brief Return a flat vector of point coordinates
   /**
@@ -38,10 +50,16 @@ public:
    * set to 0
    **/
   template <class T>
-  std::vector<T> points () const;
+  std::vector<T> points () const
+  {
+    return asDerived().template pointsImpl<T>();
+  }
 
   /// \brief Return cell types, offsets, and connectivity. \see Cells
-  Cells cells () const;
+  Cells cells () const
+  {
+    return asDerived().cellsImpl();
+  }
 
   /// \brief Return a flat vector of function values evaluated at the grid points.
   /**
@@ -53,41 +71,93 @@ public:
    * where the tensor dimension must be 3x3 (possible extended by 0s)
    **/
   template <class T, class GlobalFunction>
-  std::vector<T> pointData (GlobalFunction const& fct) const;
+  std::vector<T> pointData (GlobalFunction const& fct) const
+  {
+    return asDerived().template pointDataImpl<T>(fct);
+  }
 
   /// \brief Return a flat vector of function values evaluated at the grid cells. \see pointData.
   template <class T, class GlobalFunction>
-  std::vector<T> cellData (GlobalFunction const& fct) const;
+  std::vector<T> cellData (GlobalFunction const& fct) const
+  {
+    return asDerived().template cellDataImpl<T>(fct);
+  }
+
+
+protected: // cast to derived type
+
+  Derived& asDerived ()
+  {
+    return static_cast<Derived&>(*this);
+  }
+
+  const Derived& asDerived () const
+  {
+    return static_cast<const Derived&>(*this);
+  }
+
+
+protected: // default implementations
+
+  std::uint64_t numCellsImpl () const
+  {
+    return gridView_.size(0);
+  }
+
+  void updateImpl () { /* do nothing */ }
+
+  // Evaluate `fct` in center of cell
+  template <class T, class GlobalFunction>
+  std::vector<T> cellDataImpl (GlobalFunction const& fct) const
+  {
+    std::vector<T> data(numCells() * fct.ncomps());
+    auto const& indexSet = gridView_.indexSet();
+    auto localFct = localFunction(fct);
+    for (auto const& e : elements(gridView_)) {
+      localFct.bind(e);
+      auto geometry = e.geometry();
+      std::size_t idx = fct.ncomps() * indexSet.index(e);
+      for (int comp = 0; comp < fct.ncomps(); ++comp)
+        data[idx + comp] = T(localFct.evaluate(comp, geometry.center()));
+      localFct.unbind();
+    }
+    return data;
+  }
+
+
+protected:
+
+  GridView gridView_;
 };
 
 
 /// Implementation of \ref DataCollector for linear cells, with continuous data.
 template <class GridView>
 class DefaultDataCollector
+    : public DataCollectorInterface<GridView, DefaultDataCollector<GridView>>
 {
   enum { dim = GridView::dimension };
 
+  using Self = DefaultDataCollector;
+  using Super = DataCollectorInterface<GridView, Self>;
+  using Super::gridView_;
+
 public:
   DefaultDataCollector (GridView const& gridView)
-    : gridView_(gridView)
+    : Super(gridView)
   {}
 
-  void update () {}
-
-  std::uint64_t numPoints () const
+  /// Return number of grid vertices
+  std::uint64_t numPointsImpl () const
   {
     return gridView_.size(dim);
   }
 
-  std::uint64_t numCells () const
-  {
-    return gridView_.size(0);
-  }
-
+  /// Return the coordinates of all grid vertices in the order given by the indexSet
   template <class T>
-  std::vector<T> points () const
+  std::vector<T> pointsImpl () const
   {
-    std::vector<T> data(numPoints() * 3);
+    std::vector<T> data(this->numPoints() * 3);
     auto const& indexSet = gridView_.indexSet();
     for (auto const& vertex : vertices(gridView_)) {
       std::size_t idx = 3 * indexSet.index(vertex);
@@ -100,7 +170,9 @@ public:
     return data;
   }
 
-  Cells cells () const
+  /// Return the types, offsets and connectivity of the cells, using the same connectivity as
+  /// given by the grid.
+  Cells cellsImpl () const
   {
     auto const& indexSet = gridView_.indexSet();
     auto types = indexSet.types(0);
@@ -110,9 +182,9 @@ public:
     });
 
     Cells cells;
-    cells.connectivity.reserve(numCells() * maxVertices);
-    cells.offsets.reserve(numCells());
-    cells.types.reserve(numCells());
+    cells.connectivity.reserve(this->numCells() * maxVertices);
+    cells.offsets.reserve(this->numCells());
+    cells.types.reserve(this->numCells());
 
     std::int64_t old_o = 0;
     for (auto const& c : elements(gridView_)) {
@@ -126,10 +198,11 @@ public:
     return cells;
   }
 
+  /// Evaluate the `fct` at the corners of the elements
   template <class T, class GlobalFunction>
-  std::vector<T> pointData (GlobalFunction const& fct) const
+  std::vector<T> pointDataImpl (GlobalFunction const& fct) const
   {
-    std::vector<T> data(numPoints() * fct.ncomps());
+    std::vector<T> data(this->numPoints() * fct.ncomps());
     auto const& indexSet = gridView_.indexSet();
     auto localFct = localFunction(fct);
     for (auto const& e : elements(gridView_)) {
@@ -145,41 +218,29 @@ public:
     }
     return data;
   }
-
-  template <class T, class GlobalFunction>
-  std::vector<T> cellData (GlobalFunction const& fct) const
-  {
-    std::vector<T> data(numCells() * fct.ncomps());
-    auto const& indexSet = gridView_.indexSet();
-    auto localFct = localFunction(fct);
-    for (auto const& e : elements(gridView_)) {
-      localFct.bind(e);
-      auto refElem = referenceElement(e.geometry());
-      std::size_t idx = fct.ncomps() * indexSet.index(e);
-      for (int comp = 0; comp < fct.ncomps(); ++comp)
-        data[idx + comp] = T(localFct.evaluate(comp, refElem.position(0,0)));
-      localFct.unbind();
-    }
-    return data;
-  }
-
-private:
-  GridView gridView_;
 };
 
 
 /// Implementation of \ref DataCollector for linear cells, with discontinuous data.
 template <class GridView>
 class DiscontinuousDataCollector
+    : public DataCollectorInterface<GridView, DiscontinuousDataCollector<GridView>>
 {
   enum { dim = GridView::dimension };
 
+  using Self = DiscontinuousDataCollector;
+  using Super = DataCollectorInterface<GridView, Self>;
+  using Super::gridView_;
+
 public:
   DiscontinuousDataCollector (GridView const& gridView)
-    : gridView_(gridView)
-  {}
+    : Super(gridView)
+  {
+    this->update();
+  }
 
-  void update ()
+  /// Create an index map the uniquely assignes an index to each pair (element,corner)
+  void updateImpl ()
   {
     numPoints_ = 0;
     indexMap_.resize(gridView_.size(dim));
@@ -192,20 +253,17 @@ public:
     }
   }
 
-  std::uint64_t numPoints () const
+  /// The number of pointsi approx. #cell * #corners-per-cell
+  std::uint64_t numPointsImpl () const
   {
     return numPoints_;
   }
 
-  std::uint64_t numCells () const
-  {
-    return gridView_.size(0);
-  }
-
+  /// Return the coordinates of the corners of all cells
   template <class T>
-  std::vector<T> points () const
+  std::vector<T> pointsImpl () const
   {
-    std::vector<T> data(numPoints() * 3);
+    std::vector<T> data(this->numPoints() * 3);
     auto const& indexSet = gridView_.indexSet();
     for (auto const& element : elements(gridView_)) {
       for (int i = 0; i < element.subEntities(dim); ++i) {
@@ -220,12 +278,13 @@ public:
     return data;
   }
 
-  Cells cells () const
+  /// Connect the corners of each cell. The leads to a global discontinuous grid
+  Cells cellsImpl () const
   {
     Cells cells;
-    cells.connectivity.reserve(numPoints());
-    cells.offsets.reserve(numCells());
-    cells.types.reserve(numCells());
+    cells.connectivity.reserve(this->numPoints());
+    cells.offsets.reserve(this->numCells());
+    cells.types.reserve(this->numCells());
 
     std::int64_t old_o = 0;
     auto const& indexSet = gridView_.indexSet();
@@ -242,10 +301,11 @@ public:
     return cells;
   }
 
+  /// Evaluate the `fct` in the corners of each cell
   template <class T, class GlobalFunction>
-  std::vector<T> pointData (GlobalFunction const& fct) const
+  std::vector<T> pointDataImpl (GlobalFunction const& fct) const
   {
-    std::vector<T> data(numPoints() * fct.ncomps());
+    std::vector<T> data(this->numPoints() * fct.ncomps());
     auto const& indexSet = gridView_.indexSet();
     auto localFct = localFunction(fct);
     for (auto const& e : elements(gridView_)) {
@@ -262,25 +322,7 @@ public:
     return data;
   }
 
-  template <class T, class GlobalFunction>
-  std::vector<T> cellData (GlobalFunction const& fct) const
-  {
-    std::vector<T> data(numCells() * fct.ncomps());
-    auto const& indexSet = gridView_.indexSet();
-    auto localFct = localFunction(fct);
-    for (auto const& e : elements(gridView_)) {
-      localFct.bind(e);
-      auto refElem = referenceElement(e.geometry());
-      std::size_t idx = fct.ncomps() * indexSet.index(e);
-      for (int comp = 0; comp < fct.ncomps(); ++comp)
-        data[idx + comp] = T(localFct.evaluate(comp, refElem.position(0,0)));
-      localFct.unbind();
-    }
-    return data;
-  }
-
 private:
-  GridView gridView_;
   std::uint64_t numPoints_ = 0;
   std::vector<std::int64_t> indexMap_;
 };
@@ -289,30 +331,34 @@ private:
 /// Implementation of \ref DataCollector for quadratic cells, with continuous data.
 template <class GridView>
 class QuadraticDataCollector
+    : public DataCollectorInterface<GridView, QuadraticDataCollector<GridView>>
 {
   enum { dim = GridView::dimension };
 
+  using Self = QuadraticDataCollector;
+  using Super = DataCollectorInterface<GridView, Self>;
+  using Super::gridView_;
+
 public:
   QuadraticDataCollector (GridView const& gridView)
-    : gridView_(gridView)
+    : Super(gridView)
   {}
 
-  void update () {}
-
-  std::uint64_t numPoints () const
+  /// Return number of vertices + number of edge
+  std::uint64_t numPointsImpl () const
   {
     return gridView_.size(dim) + gridView_.size(dim-1);
   }
 
-  std::uint64_t numCells () const
-  {
-    return gridView_.size(0);
-  }
-
+  /// Return a vector of point coordinates.
+  /**
+   * The vector of point coordinates is composed of vertex coordinates first and second
+   * edge center coordinates.
+   **/
   template <class T>
-  std::vector<T> points () const
+  std::vector<T> pointsImpl () const
   {
-    std::vector<T> data(numPoints() * 3);
+    std::vector<T> data(this->numPoints() * 3);
     auto const& indexSet = gridView_.indexSet();
     for (auto const& element : elements(gridView_)) {
       auto geometry = element.geometry();
@@ -340,12 +386,17 @@ public:
     return data;
   }
 
-  Cells cells () const
+  /// \brief Return cell types, offsets, and connectivity. \see Cells
+  /**
+   * The cell connectivity is composed of cell vertices first and second cell edges,
+   * where the indices are grouped [vertex-indices..., (#vertices)+edge-indices...]
+   **/
+  Cells cellsImpl () const
   {
     Cells cells;
-    cells.connectivity.reserve(numPoints());
-    cells.offsets.reserve(numCells());
-    cells.types.reserve(numCells());
+    cells.connectivity.reserve(this->numPoints());
+    cells.offsets.reserve(this->numCells());
+    cells.types.reserve(this->numCells());
 
     std::int64_t old_o = 0;
     auto const& indexSet = gridView_.indexSet();
@@ -368,10 +419,11 @@ public:
     return cells;
   }
 
+  /// Evaluate the `fct` at element vertices and edge centers in the same order as the point coords.
   template <class T, class GlobalFunction>
-  std::vector<T> pointData (GlobalFunction const& fct) const
+  std::vector<T> pointDataImpl (GlobalFunction const& fct) const
   {
-    std::vector<T> data(numPoints() * fct.ncomps());
+    std::vector<T> data(this->numPoints() * fct.ncomps());
     auto const& indexSet = gridView_.indexSet();
     auto localFct = localFunction(fct);
     for (auto const& e : elements(gridView_)) {
@@ -394,26 +446,6 @@ public:
     }
     return data;
   }
-
-  template <class T, class GlobalFunction>
-  std::vector<T> cellData (GlobalFunction const& fct) const
-  {
-    std::vector<T> data(numCells() * fct.ncomps());
-    auto const& indexSet = gridView_.indexSet();
-    auto localFct = localFunction(fct);
-    for (auto const& e : elements(gridView_)) {
-      localFct.bind(e);
-      auto refElem = referenceElement(e.geometry());
-      std::size_t idx = fct.ncomps() * indexSet.index(e);
-      for (int comp = 0; comp < fct.ncomps(); ++comp)
-        data[idx + comp] = T(localFct.evaluate(comp, refElem.position(0,0)));
-      localFct.unbind();
-    }
-    return data;
-  }
-
-private:
-  GridView gridView_;
 };
 
 }} // end namespace Dune::experimental
diff --git a/src/vtkreader.cc b/src/vtkreader.cc
index 12d0732..6a061b3 100644
--- a/src/vtkreader.cc
+++ b/src/vtkreader.cc
@@ -76,7 +76,7 @@ int main(int argc, char** argv)
     vtkWriter.write("test_ascii_float32_4.vtu", Vtk::ASCII);
   }
 
-  {
+  if (filesystem::exists("paraview_3d.vtu")) {
     using GridType3d = UGGrid<3>;
     using GridView3d = typename GridType3d::LeafGridView;
     auto gridPtr = VtkReader<GridType3d>::read("paraview_3d.vtu");
@@ -86,14 +86,14 @@ int main(int argc, char** argv)
     vtkWriter.write("paraview_3d_ascii.vtu", Vtk::ASCII, Vtk::FLOAT64);
   }
 
-  // {
-  //   std::cout << "paraview_2d_ascii...\n";
-  //   using GridType2d = UGGrid<2>;
-  //   using GridView2d = typename GridType2d::LeafGridView;
-  //   auto gridPtr = VtkReader<GridType2d>::read("paraview_2d.vtu");
-  //   auto& grid = *gridPtr;
+  if (filesystem::exists("paraview_2d.vtu")) {
+    std::cout << "paraview_2d_ascii...\n";
+    using GridType2d = UGGrid<2>;
+    using GridView2d = typename GridType2d::LeafGridView;
+    auto gridPtr = VtkReader<GridType2d>::read("paraview_2d.vtu");
+    auto& grid = *gridPtr;
 
-  //   VtkWriter<GridView2d> vtkWriter(grid.leafGridView());
-  //   vtkWriter.write("paraview_2d_ascii.vtu", Vtk::ASCII, Vtk::FLOAT64);
-  // }
+    VtkWriter<GridView2d> vtkWriter(grid.leafGridView());
+    vtkWriter.write("paraview_2d_ascii.vtu", Vtk::ASCII, Vtk::FLOAT64);
+  }
 }
-- 
GitLab