From 8c62075c55e1a76f3ec4fd3a7eeb76f164eedf98 Mon Sep 17 00:00:00 2001
From: Thomas Fischer <thomas.fischer@ufz.de>
Date: Fri, 8 Oct 2021 13:43:24 +0200
Subject: [PATCH] [ParamLib] Use map instead of vector in
 GroupedBasedParameter.

In parallel simulations not every domain needs to
contains all MaterialIDs. Using a vector is thus
unpractical, sometimes memory will be wasted and
it is also error prone. Hence, a map solves these
issues.
---
 ParameterLib/GroupBasedParameter.cpp | 34 +++++++++++-----------------
 ParameterLib/GroupBasedParameter.h   | 11 +++++----
 2 files changed, 19 insertions(+), 26 deletions(-)

diff --git a/ParameterLib/GroupBasedParameter.cpp b/ParameterLib/GroupBasedParameter.cpp
index 6fd3ed05c1e..f9caac1e618 100644
--- a/ParameterLib/GroupBasedParameter.cpp
+++ b/ParameterLib/GroupBasedParameter.cpp
@@ -34,8 +34,7 @@ std::unique_ptr<ParameterBase> createGroupBasedParameter(
 
     // parse mapping data
     using Values = std::vector<double>;
-    using Index_Values = std::pair<int, Values>;
-    std::vector<Index_Values> vec_index_values;
+    std::map<int, Values> vec_index_values;
     //! \ogs_file_param{prj__parameters__parameter__Group__index_values}
     for (auto p : config.getConfigSubtreeList("index_values"))
     {
@@ -48,7 +47,7 @@ std::unique_ptr<ParameterBase> createGroupBasedParameter(
             if (value)
             {
                 Values values(1, *value);
-                vec_index_values.emplace_back(index, values);
+                vec_index_values.emplace(index, values);
                 continue;
             }
         }
@@ -62,53 +61,46 @@ std::unique_ptr<ParameterBase> createGroupBasedParameter(
             OGS_FATAL("No value available for constant parameter.");
         }
 
-        vec_index_values.emplace_back(index, values);
+        vec_index_values.emplace(index, values);
     }
 
     // check the input
-    unsigned n_values = vec_index_values.front().second.size();
     for (auto p : vec_index_values)
     {
-        auto itr = std::find(group_id_property->begin(),
-                             group_id_property->end(), p.first);
-        if (itr == group_id_property->end())
+#ifndef USE_PETSC  // In case of partitioned meshes not all of the material ids
+                   // might be available in the particular partition, therefore
+                   // the check is omitted.
+        if (std::find(group_id_property->begin(), group_id_property->end(),
+                      p.first) == group_id_property->end())
         {
             OGS_FATAL(
                 "Specified property index {:d} does not exist in the property "
                 "vector {:s}",
                 p.first, group_id_property_name);
         }
+#endif
 
+        auto const n_values = vec_index_values.begin()->second.size();
         if (p.second.size() != n_values)
         {
             OGS_FATAL(
                 "The length of some values ({:d}) is different from the first "
-                "one ({:d}). "
-                "The length should be same for all index_values.",
+                "one ({:d}). The length should be same for all index_values.",
                 p.second.size(), n_values);
         }
     }
 
-    // create a mapping table
-    const int max_index =
-        *std::max_element(group_id_property->begin(), group_id_property->end());
-    std::vector<Values> vec_values(max_index + 1);
-    for (auto p : vec_index_values)
-    {
-        vec_values[p.first] = p.second;
-    }
-
     if (group_id_property->getMeshItemType() == MeshLib::MeshItemType::Node)
     {
         return std::make_unique<
             GroupBasedParameter<double, MeshLib::MeshItemType::Node>>(
-            name, mesh, *group_id_property, vec_values);
+            name, mesh, *group_id_property, vec_index_values);
     }
     if (group_id_property->getMeshItemType() == MeshLib::MeshItemType::Cell)
     {
         return std::make_unique<
             GroupBasedParameter<double, MeshLib::MeshItemType::Cell>>(
-            name, mesh, *group_id_property, vec_values);
+            name, mesh, *group_id_property, vec_index_values);
     }
 
     OGS_FATAL("Mesh item type of the specified property is not supported.");
diff --git a/ParameterLib/GroupBasedParameter.h b/ParameterLib/GroupBasedParameter.h
index 627293178c0..294e0c8b14a 100644
--- a/ParameterLib/GroupBasedParameter.h
+++ b/ParameterLib/GroupBasedParameter.h
@@ -41,7 +41,7 @@ struct GroupBasedParameter final : public Parameter<T>
     GroupBasedParameter(std::string const& name_,
                         MeshLib::Mesh const& mesh,
                         MeshLib::PropertyVector<int> const& property,
-                        std::vector<std::vector<double>>
+                        std::map<int, std::vector<double>>
                             vec_values)
         : Parameter<T>(name_, &mesh),
           _property_index(property),
@@ -55,7 +55,7 @@ struct GroupBasedParameter final : public Parameter<T>
     {
         return _vec_values.empty()
                    ? 0
-                   : static_cast<int>(_vec_values.front().size());
+                   : static_cast<int>(_vec_values.begin()->second.size());
     }
 
     std::vector<T> operator()(double const /*t*/,
@@ -64,11 +64,12 @@ struct GroupBasedParameter final : public Parameter<T>
         auto const item_id = getMeshItemID(pos, type<MeshItemType>());
         assert(item_id);
         int const index = _property_index[item_id.value()];
-        auto const& values = _vec_values[index];
-        if (values.empty())
+        auto const v = _vec_values.find(index);
+        if (v == _vec_values.end())
         {
             OGS_FATAL("No data found for the group index {:d}", index);
         }
+        auto const& values = v->second;
 
         if (!this->_coordinate_system)
         {
@@ -99,7 +100,7 @@ private:
     }
 
     MeshLib::PropertyVector<int> const& _property_index;
-    std::vector<std::vector<T>> const _vec_values;
+    std::map<int, std::vector<T>> const _vec_values;
 };
 
 std::unique_ptr<ParameterBase> createGroupBasedParameter(
-- 
GitLab