From 267c8b1a51f77dd55698843442c3db0a6b7e9d4f Mon Sep 17 00:00:00 2001
From: Wenqing Wang <wenqing.wang@ufz.de>
Date: Wed, 25 Jan 2017 17:51:19 +0100
Subject: [PATCH] [Coupling] Replaced ProcessType with std::type_index

---
 BaseLib/uniqueInsert.h                    | 104 ++++++++++++++--------
 ProcessLib/StaggeredCouplingTerm.cpp      |   7 +-
 ProcessLib/StaggeredCouplingTerm.h        |  34 ++++---
 ProcessLib/UncoupledProcessesTimeLoop.cpp |  24 ++---
 ProcessLib/UncoupledProcessesTimeLoop.h   |   6 +-
 ProcessLib/VectorMatrixAssembler.cpp      |  21 ++---
 6 files changed, 118 insertions(+), 78 deletions(-)

diff --git a/BaseLib/uniqueInsert.h b/BaseLib/uniqueInsert.h
index 25aa7e28479..d7a7b00040e 100644
--- a/BaseLib/uniqueInsert.h
+++ b/BaseLib/uniqueInsert.h
@@ -15,40 +15,64 @@
 #pragma once
 
 #include <algorithm>
-
+#include <typeinfo>
+#include <typeindex>
 #include "Error.h"
 
-namespace BaseLib {
-
-template<typename Container>
-void uniquePushBack(Container& container, typename Container::value_type const& element)
+namespace BaseLib
+{
+template <typename Container>
+void uniquePushBack(Container& container,
+                    typename Container::value_type const& element)
 {
-    if (std::find(container.begin(), container.end(), element) == container.end())
+    if (std::find(container.begin(), container.end(), element) ==
+        container.end())
         container.push_back(element);
 }
 
+//! Inserts the given \c key with the given \c value into the \c map if an entry
+//! with the
+//! given \c key does not yet exist; otherwise an \c error_message is printed
+//! and the
+//! program is aborted.
+//! Note: The type of \c key must be std::type_index.
+template <typename Map, typename Key, typename Value>
+void insertIfTypeIndexKeyUniqueElseError(Map& map, Key const& key,
+                                         Value&& value,
+                                         std::string const& error_message)
+{
+    auto const inserted = map.emplace(key, std::forward<Value>(value));
+    if (!inserted.second)
+    {  // insertion failed, i.e., key already exists
+        OGS_FATAL("%s Key `%s' already exists.", error_message.c_str(),
+                  tostring(key.hash_code()).c_str());
+    }
+}
 
-//! Inserts the given \c key with the given \c value into the \c map if an entry with the
-//! given \c key does not yet exist; otherwise an \c error_message is printed and the
+//! Inserts the given \c key with the given \c value into the \c map if an entry
+//! with the
+//! given \c key does not yet exist; otherwise an \c error_message is printed
+//! and the
 //! program is aborted.
-template<typename Map, typename Key, typename Value>
-void insertIfKeyUniqueElseError(
-    Map& map, Key const& key, Value&& value,
-    std::string const& error_message)
+template <typename Map, typename Key, typename Value>
+void insertIfKeyUniqueElseError(Map& map, Key const& key, Value&& value,
+                                std::string const& error_message)
 {
     auto const inserted = map.emplace(key, std::forward<Value>(value));
-    if (!inserted.second) { // insertion failed, i.e., key already exists
-        OGS_FATAL("%s Key `%s' already exists.", error_message.c_str(), tostring(key).c_str());
+    if (!inserted.second)
+    {  // insertion failed, i.e., key already exists
+        OGS_FATAL("%s Key `%s' already exists.", error_message.c_str(),
+                  tostring(key).c_str());
     }
 }
 
-//! Inserts the given \c key with the given \c value into the \c map if neither an entry
+//! Inserts the given \c key with the given \c value into the \c map if neither
+//! an entry
 //! with the given \c key nor an entry with the given \c value already exists;
 //! otherwise an \c error_message is printed and the program is aborted.
-template<typename Map, typename Key, typename Value>
-void insertIfKeyValueUniqueElseError(
-    Map& map, Key const& key, Value&& value,
-    std::string const& error_message)
+template <typename Map, typename Key, typename Value>
+void insertIfKeyValueUniqueElseError(Map& map, Key const& key, Value&& value,
+                                     std::string const& error_message)
 {
     auto value_compare = [&value](typename Map::value_type const& elem) {
         return value == elem.second;
@@ -56,45 +80,49 @@ void insertIfKeyValueUniqueElseError(
 
     if (std::find_if(map.cbegin(), map.cend(), value_compare) != map.cend())
     {
-        OGS_FATAL("%s Value `%s' already exists.", error_message.c_str(), tostring(value).c_str());
+        OGS_FATAL("%s Value `%s' already exists.", error_message.c_str(),
+                  tostring(value).c_str());
     }
 
     auto const inserted = map.emplace(key, std::forward<Value>(value));
-    if (!inserted.second) { // insertion failed, i.e., key already exists
-        OGS_FATAL("%s Key `%s' already exists.", error_message.c_str(), tostring(key).c_str());
+    if (!inserted.second)
+    {  // insertion failed, i.e., key already exists
+        OGS_FATAL("%s Key `%s' already exists.", error_message.c_str(),
+                  tostring(key).c_str());
     }
 }
 
 //! Returns the value of \c key from the given \c map if such an entry exists;
 //! otherwise an \c error_message is printed and the program is aborted.
 //! Cf. also the const overload below.
-//! \remark Use as: \code{.cpp} get_or_error<Value>(some_map, some_key, "error message") \endcode
-template<typename Map, typename Key>
-typename Map::mapped_type&
-getOrError(
-    Map& map, Key const& key,
-    std::string const& error_message)
+//! \remark Use as: \code{.cpp} get_or_error<Value>(some_map, some_key, "error
+//! message") \endcode
+template <typename Map, typename Key>
+typename Map::mapped_type& getOrError(Map& map, Key const& key,
+                                      std::string const& error_message)
 {
     auto it = map.find(key);
-    if (it == map.end()) {
-        OGS_FATAL("%s Key `%s' does not exist.", error_message.c_str(), tostring(key).c_str());
+    if (it == map.end())
+    {
+        OGS_FATAL("%s Key `%s' does not exist.", error_message.c_str(),
+                  tostring(key).c_str());
     }
 
     return it->second;
 }
 //! \overload
-template<typename Map, typename Key>
-typename Map::mapped_type const&
-getOrError(
-    Map const& map, Key const& key,
-    std::string const& error_message)
+template <typename Map, typename Key>
+typename Map::mapped_type const& getOrError(Map const& map, Key const& key,
+                                            std::string const& error_message)
 {
     auto it = map.find(key);
-    if (it == map.end()) {
-        OGS_FATAL("%s Key `%s' does not exist.", error_message.c_str(), tostring(key).c_str());
+    if (it == map.end())
+    {
+        OGS_FATAL("%s Key `%s' does not exist.", error_message.c_str(),
+                  tostring(key).c_str());
     }
 
     return it->second;
 }
 
-} // end namespace BaseLib
+}  // end namespace BaseLib
diff --git a/ProcessLib/StaggeredCouplingTerm.cpp b/ProcessLib/StaggeredCouplingTerm.cpp
index 0e17509afd4..a6468487e85 100644
--- a/ProcessLib/StaggeredCouplingTerm.cpp
+++ b/ProcessLib/StaggeredCouplingTerm.cpp
@@ -17,11 +17,10 @@ namespace ProcessLib
 {
 const StaggeredCouplingTerm createVoidStaggeredCouplingTerm()
 {
-    std::map<ProcessType, Process const&> coupled_processes;
-    std::map<ProcessType, GlobalVector const&> coupled_xs;
+    std::unordered_map<std::type_index, Process const&> coupled_processes;
+    std::unordered_map<std::type_index, GlobalVector const&> coupled_xs;
     const bool empty = true;
     return StaggeredCouplingTerm(coupled_processes, coupled_xs, 0.0, empty);
 }
 
-} // end of ProcessLib
-
+}  // end of ProcessLib
diff --git a/ProcessLib/StaggeredCouplingTerm.h b/ProcessLib/StaggeredCouplingTerm.h
index 88e27222099..f8a93d6e08c 100644
--- a/ProcessLib/StaggeredCouplingTerm.h
+++ b/ProcessLib/StaggeredCouplingTerm.h
@@ -12,12 +12,11 @@
 
 #pragma once
 
-#include <map>
+#include <unordered_map>
+#include <typeindex>
 
 #include "MathLib/LinAlg/GlobalMatrixVectorTypes.h"
 
-#include "ProcessType.h"
-
 namespace ProcessLib
 {
 class Process;
@@ -32,8 +31,10 @@ class Process;
 struct StaggeredCouplingTerm
 {
     StaggeredCouplingTerm(
-        std::map<ProcessType, Process const&> const& coupled_processes_,
-        std::map<ProcessType, GlobalVector const&> const& coupled_xs_,
+        std::unordered_map<std::type_index, Process const&> const&
+            coupled_processes_,
+        std::unordered_map<std::type_index, GlobalVector const&> const&
+            coupled_xs_,
         const double dt_, const bool empty_ = false)
         : coupled_processes(coupled_processes_),
           coupled_xs(coupled_xs_),
@@ -44,11 +45,12 @@ struct StaggeredCouplingTerm
 
     /// References to the coupled processes are distinguished by the keys of
     /// process types.
-    std::map<ProcessType, Process const&> const& coupled_processes;
+    std::unordered_map<std::type_index, Process const&> const&
+        coupled_processes;
 
     /// References to the current solutions of the coupled processes.
     /// The coupled solutions are distinguished by the keys of process types.
-    std::map<ProcessType, GlobalVector const&> const& coupled_xs;
+    std::unordered_map<std::type_index, GlobalVector const&> const& coupled_xs;
 
     const double dt;   ///< Time step size.
     const bool empty;  ///< Flag to indicate whether the couping term is empty.
@@ -66,9 +68,12 @@ struct LocalCouplingTerm
 {
     LocalCouplingTerm(
         const double dt_,
-        std::map<ProcessType, Process const&> const& coupled_processes_,
-        std::map<ProcessType, const std::vector<double>>&& local_coupled_xs0_,
-        std::map<ProcessType, const std::vector<double>>&& local_coupled_xs_)
+        std::unordered_map<std::type_index, Process const&> const&
+            coupled_processes_,
+        std::unordered_map<std::type_index, const std::vector<double>>&&
+            local_coupled_xs0_,
+        std::unordered_map<std::type_index, const std::vector<double>>&&
+            local_coupled_xs_)
         : dt(dt_),
           coupled_processes(coupled_processes_),
           local_coupled_xs0(std::move(local_coupled_xs0_)),
@@ -80,12 +85,15 @@ struct LocalCouplingTerm
 
     /// References to the coupled processes are distinguished by the keys of
     /// process types.
-    std::map<ProcessType, Process const&> const& coupled_processes;
+    std::unordered_map<std::type_index, Process const&> const&
+        coupled_processes;
 
     /// Local solutions of the previous time step.
-    std::map<ProcessType, const std::vector<double>> const local_coupled_xs0;
+    std::unordered_map<std::type_index, const std::vector<double>> const
+        local_coupled_xs0;
     /// Local solutions of the current time step.
-    std::map<ProcessType, const std::vector<double>> const local_coupled_xs;
+    std::unordered_map<std::type_index, const std::vector<double>> const
+        local_coupled_xs;
 };
 
 /**
diff --git a/ProcessLib/UncoupledProcessesTimeLoop.cpp b/ProcessLib/UncoupledProcessesTimeLoop.cpp
index 05bd6ae7174..e2dcbe75eab 100644
--- a/ProcessLib/UncoupledProcessesTimeLoop.cpp
+++ b/ProcessLib/UncoupledProcessesTimeLoop.cpp
@@ -132,7 +132,8 @@ struct SingleProcessData
         std::unique_ptr<NumLib::ConvergenceCriterion>&& conv_crit_,
         std::unique_ptr<NumLib::TimeDiscretization>&& time_disc_,
         Process& process_,
-        std::map<ProcessType, Process const&>&& coupled_processes_,
+        std::unordered_map<std::type_index, Process const&>&&
+            coupled_processes_,
         ProcessOutput&& process_output_);
 
     SingleProcessData(SingleProcessData&& spd);
@@ -151,7 +152,7 @@ struct SingleProcessData
 
     Process& process;
     /// Coupled processes.
-    std::map<ProcessType, Process const&> const coupled_processes;
+    std::unordered_map<std::type_index, Process const&> const coupled_processes;
     ProcessOutput process_output;
 };
 
@@ -161,7 +162,7 @@ SingleProcessData::SingleProcessData(
     std::unique_ptr<NumLib::ConvergenceCriterion>&& conv_crit_,
     std::unique_ptr<NumLib::TimeDiscretization>&& time_disc_,
     Process& process_,
-    std::map<ProcessType, Process const&>&& coupled_processes_,
+    std::unordered_map<std::type_index, Process const&>&& coupled_processes_,
     ProcessOutput&& process_output_)
     : nonlinear_solver_tag(NLTag),
       nonlinear_solver(nonlinear_solver),
@@ -245,7 +246,7 @@ std::unique_ptr<SingleProcessData> makeSingleProcessData(
     Process& process,
     std::unique_ptr<NumLib::TimeDiscretization>&& time_disc,
     std::unique_ptr<NumLib::ConvergenceCriterion>&& conv_crit,
-    std::map<ProcessType, Process const&>&& coupled_processes,
+    std::unordered_map<std::type_index, Process const&>&& coupled_processes,
     ProcessOutput&& process_output)
 {
     using Tag = NumLib::NonlinearSolverTag;
@@ -309,7 +310,7 @@ std::vector<std::unique_ptr<SingleProcessData>> createPerProcessData(
         auto const& coupled_process_tree
             //! \ogs_file_param{prj__time_loop__processes__process__coupled_processes}
             = pcs_config.getConfigSubtreeOptional("coupled_processes");
-        std::map<ProcessType, Process const&> coupled_processes;
+        std::unordered_map<std::type_index, Process const&> coupled_processes;
         if (coupled_process_tree)
         {
             for (
@@ -318,13 +319,12 @@ std::vector<std::unique_ptr<SingleProcessData>> createPerProcessData(
                 coupled_process_tree->getConfigParameterList<std::string>(
                     "coupled_process"))
             {
-                auto& cpl_pcs_ptr = BaseLib::getOrError(
+                auto const& cpl_pcs_ptr = BaseLib::getOrError(
                     processes, cpl_pcs_name,
                     "A process with the given name has not been defined.");
 
-                auto const cpl_pcs = cpl_pcs_ptr.get();
                 auto const inserted = coupled_processes.emplace(
-                    cpl_pcs_ptr->getProcessType(), *cpl_pcs);
+                    std::type_index(typeid(*cpl_pcs_ptr)), *cpl_pcs_ptr);
                 if (!inserted.second)
                 {  // insertion failed, i.e., key already exists
                     OGS_FATAL("Coupled process `%s' already exists.",
@@ -501,7 +501,7 @@ bool UncoupledProcessesTimeLoop::setCoupledSolutions()
         time_timestep_process.start();
 
         auto const& coupled_processes = spd->coupled_processes;
-        std::map<ProcessType, GlobalVector const&> coupled_xs;
+        std::unordered_map<std::type_index, GlobalVector const&> coupled_xs;
         for (auto const& coupled_process_map : coupled_processes)
         {
             ProcessLib::Process const& coupled_process =
@@ -511,8 +511,8 @@ bool UncoupledProcessesTimeLoop::setCoupledSolutions()
                 _per_process_data.end(),
                 [&coupled_process](
                     std::unique_ptr<SingleProcessData> const& item) {
-                    return coupled_process.getProcessType() ==
-                           item->process.getProcessType();
+                    return std::type_index(typeid(coupled_process)) ==
+                           std::type_index(typeid(item->process));
                 });
 
             if (found_item != _per_process_data.end())
@@ -520,7 +520,7 @@ bool UncoupledProcessesTimeLoop::setCoupledSolutions()
                 // Id of the coupled process:
                 const std::size_t c_id = found_item - _per_process_data.begin();
 
-                BaseLib::insertIfKeyUniqueElseError(
+                BaseLib::insertIfTypeIndexKeyUniqueElseError(
                     coupled_xs, coupled_process_map.first,
                     *_process_solutions[c_id], "global_coupled_x");
             }
diff --git a/ProcessLib/UncoupledProcessesTimeLoop.h b/ProcessLib/UncoupledProcessesTimeLoop.h
index dac90c5919c..8036448a9b2 100644
--- a/ProcessLib/UncoupledProcessesTimeLoop.h
+++ b/ProcessLib/UncoupledProcessesTimeLoop.h
@@ -10,6 +10,10 @@
 #pragma once
 
 #include <memory>
+#include <unordered_map>
+#include <typeinfo>
+#include <typeindex>
+
 #include <logog/include/logog.hpp>
 
 #include "NumLib/ODESolver/NonlinearSolver.h"
@@ -70,7 +74,7 @@ private:
      *  Each vector element stores the references of the solution vectors
      *  (stored in _process_solutions) of the coupled processes of a process.
      */
-    std::vector<std::map<ProcessType, GlobalVector const&>>
+    std::vector<std::unordered_map<std::type_index, GlobalVector const&>>
         _solutions_of_coupled_processes;
 
     /// Solutions of the previous coupling iteration for the convergence
diff --git a/ProcessLib/VectorMatrixAssembler.cpp b/ProcessLib/VectorMatrixAssembler.cpp
index bf257e72943..32851bf2a87 100644
--- a/ProcessLib/VectorMatrixAssembler.cpp
+++ b/ProcessLib/VectorMatrixAssembler.cpp
@@ -19,12 +19,12 @@
 
 namespace ProcessLib
 {
-static std::map<ProcessLib::ProcessType, const std::vector<double>>
+static std::unordered_map<std::type_index, const std::vector<double>>
 getPreviousLocalSolutionsOfCoupledProcesses(
     const StaggeredCouplingTerm& coupled_term,
     const std::vector<GlobalIndexType>& indices)
 {
-    std::map<ProcessLib::ProcessType, const std::vector<double>>
+    std::unordered_map<std::type_index, const std::vector<double>>
         local_coupled_xs0;
 
     for (auto const& coupled_process_map : coupled_term.coupled_processes)
@@ -34,14 +34,14 @@ getPreviousLocalSolutionsOfCoupledProcesses(
         if (prevous_time_x)
         {
             auto const local_coupled_x0 = prevous_time_x->get(indices);
-            BaseLib::insertIfKeyUniqueElseError(
+            BaseLib::insertIfTypeIndexKeyUniqueElseError(
                 local_coupled_xs0, coupled_process_map.first, local_coupled_x0,
                 "local_coupled_x0");
         }
         else
         {
             const std::vector<double> local_coupled_x0;
-            BaseLib::insertIfKeyUniqueElseError(
+            BaseLib::insertIfTypeIndexKeyUniqueElseError(
                 local_coupled_xs0, coupled_process_map.first, local_coupled_x0,
                 "local_coupled_x0");
         }
@@ -49,21 +49,22 @@ getPreviousLocalSolutionsOfCoupledProcesses(
     return local_coupled_xs0;
 }
 
-static std::map<ProcessLib::ProcessType, const std::vector<double>>
+static std::unordered_map<std::type_index, const std::vector<double>>
 getCurrentLocalSolutionsOfCoupledProcesses(
-    const std::map<ProcessType, GlobalVector const&>& global_coupled_xs,
+    const std::unordered_map<std::type_index, GlobalVector const&>&
+        global_coupled_xs,
     const std::vector<GlobalIndexType>& indices)
 {
-    std::map<ProcessLib::ProcessType, const std::vector<double>>
+    std::unordered_map<std::type_index, const std::vector<double>>
         local_coupled_xs;
 
     for (auto const& global_coupled_x_map : global_coupled_xs)
     {
         auto const coupled_x = global_coupled_x_map.second;
         auto const local_coupled_x = coupled_x.get(indices);
-        BaseLib::insertIfKeyUniqueElseError(local_coupled_xs,
-                                            global_coupled_x_map.first,
-                                            local_coupled_x, "local_coupled_x");
+        BaseLib::insertIfTypeIndexKeyUniqueElseError(
+            local_coupled_xs, global_coupled_x_map.first, local_coupled_x,
+            "local_coupled_x");
     }
     return local_coupled_xs;
 }
-- 
GitLab