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