From fa05944bf98ea4ed8557859362420cf90767e0d4 Mon Sep 17 00:00:00 2001
From: Bernd Flemisch <bernd@iws.uni-stuttgart.de>
Date: Thu, 26 Jul 2018 16:09:44 +0200
Subject: [PATCH] [io][vtk] read from parallel Vtk file into a solution vector
 with state

---
 dumux/io/loadsolution.hh | 60 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 54 insertions(+), 6 deletions(-)

diff --git a/dumux/io/loadsolution.hh b/dumux/io/loadsolution.hh
index c047c386d3..4b06ce1835 100644
--- a/dumux/io/loadsolution.hh
+++ b/dumux/io/loadsolution.hh
@@ -146,11 +146,6 @@ auto loadSolutionFromParallelVtkFile(const std::string fileName,
     {
         const auto pvName = pvNamesFunc(pvIdx);
         auto vec = vtu.readData<std::vector<Scalar>>(pvName, dataType);
-        if (vec.size() != sol.size() && fvGridGeometry.gridView().comm().size() == 1)
-        {
-            DUNE_THROW(Dune::IOError, "Size mismatch between solution vector and read data ("
-                                      << sol.size() << " != " << vec.size() << ")");
-        }
 
         std::vector<bool> visited;
         if (dataType == VTKReader::DataType::pointData)
@@ -239,7 +234,60 @@ auto loadSolutionFromParallelVtkFile(const std::string fileName,
                                      const FVGridGeometry& fvGridGeometry)
 -> typename std::enable_if_t<decltype(isValid(Detail::hasState())(sol[0]))::value, void>
 {
-    DUNE_THROW(Dune::NotImplemented, "reading solution with state from a parallel Vtk file");
+    VTKReader vtu(fileName);
+
+    // get states at dof locations
+    const auto stateAtDof = vtu.readData<std::vector<int>>("phase presence", dataType);
+
+    // determine which states are present
+    std::unordered_set<int> states;
+    for (size_t i = 0; i < sol.size(); ++i)
+        states.insert(stateAtDof[i]);
+
+    // declare a vector to determine which vertices have been visited already
+    std::vector<bool> visited;
+    using GridView = typename FVGridGeometry::GridView;
+    static constexpr auto dim = GridView::dimension;
+    if (dataType == VTKReader::DataType::pointData)
+        visited.resize(fvGridGeometry.gridView().size(dim));
+
+    using PrimaryVariables = typename SolutionVector::block_type;
+    using Scalar = typename PrimaryVariables::field_type;
+    for (size_t pvIdx = 0; pvIdx < PrimaryVariables::dimension; ++pvIdx)
+    {
+        std::unordered_map<int, std::vector<Scalar>> switchedPvsSol;
+        for (const auto& state : states)
+            switchedPvsSol[state] = vtu.readData<std::vector<Scalar>>(pvNamesFunc(pvIdx, state), dataType);
+
+        std::fill(visited.begin(), visited.end(), false);
+        std::size_t i = 0;
+        for (const auto& element : elements(fvGridGeometry.gridView(), Dune::Partitions::interior))
+        {
+            if (dataType == VTKReader::DataType::cellData)
+            {
+                auto eIdx = fvGridGeometry.elementMapper().index(element);
+                auto state = stateAtDof[i];
+                sol[eIdx].setState(state);
+                sol[eIdx][pvIdx] = switchedPvsSol[state][i];
+                ++i;
+            }
+            else
+            {
+                for (int vIdxLocal = 0; vIdxLocal < element.subEntities(dim); ++vIdxLocal)
+                {
+                    auto vIdxGlobal = fvGridGeometry.vertexMapper().subIndex(element, vIdxLocal, dim);
+                    if (!visited[vIdxGlobal])
+                    {
+                        auto state = stateAtDof[i];
+                        sol[vIdxGlobal].setState(state);
+                        sol[vIdxGlobal][pvIdx] = switchedPvsSol[state][i];
+                        visited[vIdxGlobal] = true;
+                        ++i;
+                    }
+                }
+            }
+        }
+    }
 }
 
 /*!
-- 
GitLab