From cb6ec8cdec817f1725f7ebe59bc3a99b41927589 Mon Sep 17 00:00:00 2001
From: Thomas Fischer <thomas.fischer@ufz.de>
Date: Thu, 2 Mar 2017 12:10:05 +0100
Subject: [PATCH] [A/U/MP] Refactor NodeWiseMeshPartitioner::partitionByMETIS.

The refactorization is the first step to also partition PropertyVectors by the same schema.
---
 .../PartitionMesh/NodeWiseMeshPartitioner.cpp | 176 ++++++++++--------
 .../PartitionMesh/NodeWiseMeshPartitioner.h   |  26 +++
 2 files changed, 128 insertions(+), 74 deletions(-)

diff --git a/Applications/Utils/ModelPreparation/PartitionMesh/NodeWiseMeshPartitioner.cpp b/Applications/Utils/ModelPreparation/PartitionMesh/NodeWiseMeshPartitioner.cpp
index 544b8d23727..aaa9e9a125f 100644
--- a/Applications/Utils/ModelPreparation/PartitionMesh/NodeWiseMeshPartitioner.cpp
+++ b/Applications/Utils/ModelPreparation/PartitionMesh/NodeWiseMeshPartitioner.cpp
@@ -85,103 +85,131 @@ void NodeWiseMeshPartitioner::readMetisData(const std::string& file_name_base)
     std::remove(fname_eparts.c_str());
 }
 
-void NodeWiseMeshPartitioner::partitionByMETIS(
-    const bool is_mixed_high_order_linear_elems)
+void NodeWiseMeshPartitioner::findNonGhostNodesInPartition(
+    std::size_t const part_id,
+    const bool is_mixed_high_order_linear_elems,
+    std::vector<MeshLib::Node*>& extra_nodes)
 {
     std::vector<MeshLib::Node*> const& nodes = _mesh->getNodes();
-    for (std::size_t part_id = 0; part_id < _partitions.size(); part_id++)
+    auto& partition = _partitions[part_id];
+    // -- Extra nodes for high order elements
+    for (std::size_t i = 0; i < _mesh->getNumberOfNodes(); i++)
     {
-        auto& partition = _partitions[part_id];
-
-        INFO("Processing partition: %d", part_id);
-
-        // Find non-ghost nodes in this partition
-        // -- Extra nodes for high order elements
-        std::vector<MeshLib::Node*> extra_nodes;
-        for (std::size_t i = 0; i < _mesh->getNumberOfNodes(); i++)
+        if (_nodes_partition_ids[i] == part_id)
         {
-            if (_nodes_partition_ids[i] == part_id)
-            {
-                if (is_mixed_high_order_linear_elems)
-                { // TODO: Test it once there is a case
-                    if (i < _mesh->getNumberOfBaseNodes())
-                        partition.nodes.push_back(nodes[i]);
-                    else
-                        extra_nodes.push_back(nodes[i]);
-                }
-                else
-                {
+            if (is_mixed_high_order_linear_elems)
+            {  // TODO: Test it once there is a case
+                if (i < _mesh->getNumberOfBaseNodes())
                     partition.nodes.push_back(nodes[i]);
-                }
+                else
+                    extra_nodes.push_back(nodes[i]);
+            }
+            else
+            {
+                partition.nodes.push_back(nodes[i]);
             }
         }
-        partition.number_of_non_ghost_base_nodes = partition.nodes.size();
-        partition.number_of_non_ghost_nodes =
-            partition.number_of_non_ghost_base_nodes + extra_nodes.size();
+    }
+    partition.number_of_non_ghost_base_nodes = partition.nodes.size();
+    partition.number_of_non_ghost_nodes =
+        partition.number_of_non_ghost_base_nodes + extra_nodes.size();
+}
 
-        // Find elements that belong to this partition
-        std::vector<MeshLib::Element*> const& elements = _mesh->getElements();
-        for (std::size_t elem_id = 0; elem_id < elements.size(); elem_id++)
-        {
-            const auto* elem = elements[elem_id];
-            if (_elements_status[elem_id])
-                continue;
+void NodeWiseMeshPartitioner::findElementsInPartition(
+    std::size_t const part_id, const bool is_mixed_high_order_linear_elems)
+{
+    auto& partition = _partitions[part_id];
+    std::vector<MeshLib::Element*> const& elements = _mesh->getElements();
+    for (std::size_t elem_id = 0; elem_id < elements.size(); elem_id++)
+    {
+        const auto* elem = elements[elem_id];
+        if (_elements_status[elem_id])
+            continue;
 
-            std::size_t non_ghost_node_number = 0;
-            for (unsigned i = 0; i < elem->getNumberOfNodes(); i++)
+        std::size_t non_ghost_node_number = 0;
+        for (unsigned i = 0; i < elem->getNumberOfNodes(); i++)
+        {
+            if (_nodes_partition_ids[elem->getNodeIndex(i)] == part_id)
             {
-                if (_nodes_partition_ids[elem->getNodeIndex(i)] == part_id)
-                {
-                    non_ghost_node_number++;
-                }
+                non_ghost_node_number++;
             }
+        }
 
-            if (non_ghost_node_number == 0)
-                continue;
+        if (non_ghost_node_number == 0)
+            continue;
 
-            if (non_ghost_node_number == elem->getNumberOfNodes())
-            {
-                partition.regular_elements.push_back(elem);
-                _elements_status[elem_id] = true;
-            }
-            else
-            {
-                partition.ghost_elements.push_back(elem);
-            }
+        if (non_ghost_node_number == elem->getNumberOfNodes())
+        {
+            partition.regular_elements.push_back(elem);
+            _elements_status[elem_id] = true;
+        }
+        else
+        {
+            partition.ghost_elements.push_back(elem);
         }
+    }
+}
 
-        // Find the ghost nodes of this partition
-        std::vector<bool> nodes_reserved(_mesh->getNumberOfNodes(), false);
-        for (const auto* ghost_elem : partition.ghost_elements)
+void NodeWiseMeshPartitioner::findGhostNodesInPartition(
+    std::size_t const part_id,
+    const bool is_mixed_high_order_linear_elems,
+    std::vector<MeshLib::Node*>& extra_nodes)
+{
+    auto& partition = _partitions[part_id];
+    std::vector<MeshLib::Node*> const& nodes = _mesh->getNodes();
+    std::vector<bool> nodes_reserved(_mesh->getNumberOfNodes(), false);
+    for (const auto* ghost_elem : partition.ghost_elements)
+    {
+        for (unsigned i = 0; i < ghost_elem->getNumberOfNodes(); i++)
         {
-            for (unsigned i = 0; i < ghost_elem->getNumberOfNodes(); i++)
-            {
-                const unsigned node_id = ghost_elem->getNodeIndex(i);
-                if (nodes_reserved[node_id])
-                    continue;
+            const unsigned node_id = ghost_elem->getNodeIndex(i);
+            if (nodes_reserved[node_id])
+                continue;
 
-                if (_nodes_partition_ids[node_id] != part_id)
+            if (_nodes_partition_ids[node_id] != part_id)
+            {
+                if (is_mixed_high_order_linear_elems)
                 {
-                    if (is_mixed_high_order_linear_elems)
-                    {
-                        if (node_id < _mesh->getNumberOfBaseNodes())
-                            partition.nodes.push_back(nodes[node_id]);
-                        else
-                            extra_nodes.push_back(nodes[node_id]);
-                    }
-                    else
-                    {
+                    if (node_id < _mesh->getNumberOfBaseNodes())
                         partition.nodes.push_back(nodes[node_id]);
-                    }
-                    nodes_reserved[node_id] = true;
+                    else
+                        extra_nodes.push_back(nodes[node_id]);
                 }
+                else
+                {
+                    partition.nodes.push_back(nodes[node_id]);
+                }
+                nodes_reserved[node_id] = true;
             }
         }
-        partition.number_of_base_nodes = partition.nodes.size();
+    }
+}
 
-        if (is_mixed_high_order_linear_elems)
-            partition.nodes.insert(partition.nodes.end(), extra_nodes.begin(),
-                                   extra_nodes.end());
+void NodeWiseMeshPartitioner::processPartition(std::size_t const part_id,
+    const bool is_mixed_high_order_linear_elems)
+{
+    std::vector<MeshLib::Node*> extra_nodes;
+    findNonGhostNodesInPartition(part_id, is_mixed_high_order_linear_elems,
+                                 extra_nodes);
+
+    findElementsInPartition(part_id, is_mixed_high_order_linear_elems);
+    findGhostNodesInPartition(part_id, is_mixed_high_order_linear_elems,
+                              extra_nodes);
+    auto& partition = _partitions[part_id];
+    partition.number_of_base_nodes = partition.nodes.size();
+
+    if (is_mixed_high_order_linear_elems)
+        partition.nodes.insert(partition.nodes.end(), extra_nodes.begin(),
+                               extra_nodes.end());
+}
+
+void NodeWiseMeshPartitioner::partitionByMETIS(
+    const bool is_mixed_high_order_linear_elems)
+{
+    for (std::size_t part_id = 0; part_id < _partitions.size(); part_id++)
+    {
+        INFO("Processing partition: %d", part_id);
+        processPartition(part_id, is_mixed_high_order_linear_elems);
     }
 
     renumberNodeIndices(is_mixed_high_order_linear_elems);
diff --git a/Applications/Utils/ModelPreparation/PartitionMesh/NodeWiseMeshPartitioner.h b/Applications/Utils/ModelPreparation/PartitionMesh/NodeWiseMeshPartitioner.h
index 66fbb920623..6c42f31a75f 100644
--- a/Applications/Utils/ModelPreparation/PartitionMesh/NodeWiseMeshPartitioner.h
+++ b/Applications/Utils/ModelPreparation/PartitionMesh/NodeWiseMeshPartitioner.h
@@ -130,6 +130,32 @@ private:
 
     void writePropertiesBinary(std::string const& file_name_base) const;
 
+    /// 1 copy pointers to nodes belonging to the partition part_id
+    /// 2 collect non-linear element nodes belonging to the partition part_id in
+    /// extra_nodes
+    void findNonGhostNodesInPartition(
+        std::size_t const part_id,
+        const bool is_mixed_high_order_linear_elems,
+        std::vector<MeshLib::Node*>& extra_nodes);
+
+    /// 1 find elements belonging to the partition part_id:
+    /// fills vector partition.regular_elements
+    /// 2 find ghost elements belonging to the partition part_id
+    /// fills vector partition.ghost_elements
+    void findElementsInPartition(std::size_t const part_id,
+                                 const bool is_mixed_high_order_linear_elems);
+
+    /// Prerequisite: the ghost elements has to be found (using
+    /// findElementsInPartition).
+    /// Finds ghost nodes and non-linear element ghost nodes by walking over
+    /// ghost elements.
+    void findGhostNodesInPartition(std::size_t const part_id,
+                                   const bool is_mixed_high_order_linear_elems,
+                                   std::vector<MeshLib::Node*>& extra_nodes);
+
+    void processPartition(std::size_t const part_id,
+                          const bool is_mixed_high_order_linear_elems);
+
     template <typename T>
     void writePropertyVectorValuesBinary(
         std::ostream& os, MeshLib::PropertyVector<T> const& pv) const
-- 
GitLab