From 05a2c9824789e80e822443024753ec9bfd692421 Mon Sep 17 00:00:00 2001
From: Timo Koch <timo.koch@iws.uni-stuttgart.de>
Date: Mon, 30 Jul 2018 16:23:44 +0200
Subject: [PATCH] [io][vtkreader] Reduce code duplication and computational
 effort for reading parallel file names

---
 dumux/io/vtk/vtkreader.hh | 78 +++++++++++++++++++--------------------
 1 file changed, 38 insertions(+), 40 deletions(-)

diff --git a/dumux/io/vtk/vtkreader.hh b/dumux/io/vtk/vtkreader.hh
index 127ce98b80..ed312d6bca 100644
--- a/dumux/io/vtk/vtkreader.hh
+++ b/dumux/io/vtk/vtkreader.hh
@@ -59,14 +59,12 @@ public:
      * \brief The contructor creates a tinyxml2::XMLDocument from file
      */
     explicit VTKReader(const std::string& fileName)
-    : fileName_(fileName)
     {
-        if (Dune::MPIHelper::getCollectiveCommunication().size() > 1)
-            getSequentialNameFromParallelName_();
+        fileName_ = Dune::MPIHelper::getCollectiveCommunication().size() > 1 ?
+                        getProcessFileName_(fileName) : fileName;
 
-        using namespace tinyxml2;
         const auto eResult = doc_.LoadFile(fileName_.c_str());
-        if (eResult != XML_SUCCESS)
+        if (eResult != tinyxml2::XML_SUCCESS)
             DUNE_THROW(Dune::IOError, "Couldn't open XML file " << fileName_ << ".");
     }
 
@@ -138,49 +136,36 @@ public:
 
 private:
     /*!
-     * \brief get sequential Vtk filename from a parallel one
+     * \brief get the vtk filename for the current processor
      */
-    void getSequentialNameFromParallelName_()
+    std::string getProcessFileName_(const std::string& pvtkFileName)
     {
         using namespace tinyxml2;
 
-        const auto eResult = doc_.LoadFile(fileName_.c_str());
+        XMLDocument pDoc;
+        const auto eResult = pDoc.LoadFile(pvtkFileName.c_str());
         if (eResult != XML_SUCCESS)
-            DUNE_THROW(Dune::IOError, "Couldn't open XML file " << fileName_ << ".");
-
-        const XMLElement* pieceNode = doc_.FirstChildElement("VTKFile");
-        if (pieceNode == nullptr)
-            DUNE_THROW(Dune::IOError, "Couldn't get 'VTKFile' node in " << fileName_ << ".");
+            DUNE_THROW(Dune::IOError, "Couldn't open XML file " << pvtkFileName << ".");
 
-        pieceNode = pieceNode->FirstChildElement("PUnstructuredGrid");
+        // get the first piece node
+        const XMLElement* pieceNode = getPieceNode_(pDoc, pvtkFileName);
         if (pieceNode == nullptr)
-            pieceNode = doc_.FirstChildElement("VTKFile")->FirstChildElement("PPolyData");
-        if (pieceNode == nullptr)
-            DUNE_THROW(Dune::IOError, "Couldn't get 'PUnstructuredGrid' or 'PPolyData' node in " << fileName_ << ".");
+            DUNE_THROW(Dune::IOError, "Couldn't get 'Piece' node in " << pvtkFileName << ".");
 
-        pieceNode = pieceNode->FirstChildElement("Piece");
-        const auto& comm = Dune::MPIHelper::getCollectiveCommunication();
-        for (int rank = 0; rank < comm.size(); ++rank)
+        const auto myrank = Dune::MPIHelper::getCollectiveCommunication().rank();
+        for (int rank = 0; rank < myrank; ++rank)
         {
-            if (pieceNode == nullptr)
-                DUNE_THROW(Dune::IOError, "Couldn't get 'Piece' node for rank "
-                                          << rank << " in " << fileName_ << ".");
-
-            const char *seqName = pieceNode->Attribute("Source");
-
-            if (seqName == nullptr)
-                DUNE_THROW(Dune::IOError, "Couldn't get 'Source' attribute of a 'Piece' node in " << fileName_);
-
-            if (comm.rank() == rank)
-            {
-                fileName_ = seqName;
-                break;
-            }
-
             pieceNode = pieceNode->NextSiblingElement("Piece");
+            if (pieceNode == nullptr)
+                DUNE_THROW(Dune::IOError, "Couldn't find 'Piece' node for rank "
+                                          << rank << " in " << pvtkFileName << ".");
         }
 
-        doc_.Clear();
+        const char *vtkFileName = pieceNode->Attribute("Source");
+        if (vtkFileName == nullptr)
+            DUNE_THROW(Dune::IOError, "Couldn't get 'Source' attribute of 'Piece' node no. " << myrank << " in " << pvtkFileName);
+
+        return vtkFileName;
     }
 
     /*!
@@ -324,18 +309,31 @@ private:
      * \note Returns nullptr if the piece node wasn't found
      */
     const tinyxml2::XMLElement* getPieceNode_() const
+    { return getPieceNode_(doc_, fileName_); }
+
+    /*!
+     * \brief Get the piece node an xml document
+     * \note Returns nullptr if the piece node wasn't found
+     * \param doc an xml document
+     * \param fileName a file name the doc was created from
+     */
+    const tinyxml2::XMLElement* getPieceNode_(const tinyxml2::XMLDocument& doc, const std::string& fileName) const
     {
         using namespace tinyxml2;
 
-        const XMLElement* pieceNode = doc_.FirstChildElement("VTKFile");
+        const XMLElement* pieceNode = doc.FirstChildElement("VTKFile");
         if (pieceNode == nullptr)
-            DUNE_THROW(Dune::IOError, "Couldn't get 'VTKFile' node in " << fileName_ << ".");
+            DUNE_THROW(Dune::IOError, "Couldn't get 'VTKFile' node in " << fileName << ".");
 
         pieceNode = pieceNode->FirstChildElement("UnstructuredGrid");
         if (pieceNode == nullptr)
-            pieceNode = doc_.FirstChildElement("VTKFile")->FirstChildElement("PolyData");
+            pieceNode = doc.FirstChildElement("VTKFile")->FirstChildElement("PolyData");
+        if (pieceNode == nullptr)
+            pieceNode = doc.FirstChildElement("VTKFile")->FirstChildElement("PUnstructuredGrid");
+        if (pieceNode == nullptr)
+            pieceNode = doc.FirstChildElement("VTKFile")->FirstChildElement("PPolyData");
         if (pieceNode == nullptr)
-            DUNE_THROW(Dune::IOError, "Couldn't get 'UnstructuredGrid' or 'PolyData' node in " << fileName_ << ".");
+            DUNE_THROW(Dune::IOError, "Couldn't get 'UnstructuredGrid', 'PUnstructuredGrid', 'PolyData', or 'PPolyData' node in " << fileName << ".");
 
         return pieceNode->FirstChildElement("Piece");
     }
-- 
GitLab