From 2629167f0526526ef282499934f0a31454ce012f Mon Sep 17 00:00:00 2001 From: "Yu-Hsiang M. Tsai" Date: Mon, 13 May 2024 16:56:19 +0200 Subject: [PATCH] update documentation, rename, complex number and rm stop::, index_type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Thomas Grützmacher Co-authored-by: Tobias Ribizel Co-authored-by: Marcel Koch --- core/config/config_helper.cpp | 42 ++++++-- core/config/config_helper.hpp | 53 ++++++---- core/config/stop_config.cpp | 43 ++------ core/config/stop_config.hpp | 35 ++++++ core/config/type_descriptor.cpp | 7 +- core/config/type_descriptor_helper.hpp | 13 +-- core/solver/cg.cpp | 9 +- core/test/config/config.cpp | 40 +++---- core/test/config/registry.cpp | 43 ++++---- include/ginkgo/core/config/config.hpp | 100 ++++++++++++------ include/ginkgo/core/config/registry.hpp | 50 +++++---- .../ginkgo/core/config/type_descriptor.hpp | 15 +-- include/ginkgo/core/solver/cg.hpp | 13 +++ 13 files changed, 279 insertions(+), 184 deletions(-) create mode 100644 core/config/stop_config.hpp diff --git a/core/config/config_helper.cpp b/core/config/config_helper.cpp index 4423080866c..5f26d927cad 100644 --- a/core/config/config_helper.cpp +++ b/core/config/config_helper.cpp @@ -12,30 +12,54 @@ #include "core/config/config_helper.hpp" #include "core/config/registry_accessor.hpp" - +#include "core/config/stop_config.hpp" namespace gko { namespace config { template <> -deferred_factory_parameter get_factory( - const pnode& config, const registry& context, const type_descriptor& td) +deferred_factory_parameter +parse_or_get_factory(const pnode& config, + const registry& context, + const type_descriptor& td) { - deferred_factory_parameter ptr; if (config.get_tag() == pnode::tag_t::string) { - ptr = detail::registry_accessor::get_data( + return detail::registry_accessor::get_data( context, config.get_string()); } else if (config.get_tag() == pnode::tag_t::map) { - ptr = parse(config, context, td); + return parse(config, context, td); } else { GKO_INVALID_STATE("The data of config is not valid."); } - GKO_THROW_IF_INVALID(!ptr.is_empty(), "Parse get nullptr in the end"); - - return ptr; } +template <> +deferred_factory_parameter +parse_or_get_factory(const pnode& config, + const registry& context, + const type_descriptor& td) +{ + if (config.get_tag() == pnode::tag_t::string) { + return detail::registry_accessor::get_data( + context, config.get_string()); + } else if (config.get_tag() == pnode::tag_t::map) { + static std::map( + const pnode&, const registry&, type_descriptor)>> + criterion_map{ + {{"Time", configure_time}, + {"Iteration", configure_iter}, + {"ResidualNorm", configure_residual}, + {"ImplicitResidualNorm", configure_implicit_residual}}}; + return criterion_map.at(config.get("type").get_string())(config, + context, td); + } else { + GKO_INVALID_STATE("The data of config is not valid."); + } +} + } // namespace config } // namespace gko diff --git a/core/config/config_helper.hpp b/core/config/config_helper.hpp index 19aadda71e7..798d3623856 100644 --- a/core/config/config_helper.hpp +++ b/core/config/config_helper.hpp @@ -60,45 +60,47 @@ inline std::shared_ptr get_stored_obj(const pnode& config, /** - * get_factory builds the factory from config (map) or searches the pointers in + * Build the factory from config (map) or search the pointers in * the registry by string. */ template -deferred_factory_parameter get_factory(const pnode& config, - const registry& context, - const type_descriptor& td); +deferred_factory_parameter parse_or_get_factory(const pnode& config, + const registry& context, + const type_descriptor& td); /** * specialize for const LinOpFactory */ template <> -deferred_factory_parameter get_factory( - const pnode& config, const registry& context, const type_descriptor& td); +deferred_factory_parameter +parse_or_get_factory(const pnode& config, + const registry& context, + const type_descriptor& td); /** * specialize for const stop::CriterionFactory */ template <> deferred_factory_parameter -get_factory(const pnode& config, - const registry& context, - const type_descriptor& td); +parse_or_get_factory(const pnode& config, + const registry& context, + const type_descriptor& td); /** - * get_factory_vector will gives a vector of factory by calling get_factory. + * give a vector of factory by calling parse_or_get_factory. */ template -inline std::vector> get_factory_vector( +inline std::vector> parse_or_get_factory_vector( const pnode& config, const registry& context, const type_descriptor& td) { std::vector> res; if (config.get_tag() == pnode::tag_t::array) { for (const auto& it : config.get_array()) { - res.push_back(get_factory(it, context, td)); + res.push_back(parse_or_get_factory(it, context, td)); } } else { // only one config can be passed without array - res.push_back(get_factory(config, context, td)); + res.push_back(parse_or_get_factory(config, context, td)); } return res; @@ -111,9 +113,8 @@ inline std::vector> get_factory_vector( * This is specialization for integral type */ template -inline - typename std::enable_if::value, IndexType>::type - get_value(const pnode& config) +inline std::enable_if_t::value, IndexType> +get_value(const pnode& config) { auto val = config.get_integer(); GKO_THROW_IF_INVALID( @@ -130,8 +131,7 @@ inline * This is specialization for floating point type */ template -inline typename std::enable_if::value, - ValueType>::type +inline std::enable_if_t::value, ValueType> get_value(const pnode& config) { auto val = config.get_real(); @@ -149,16 +149,25 @@ get_value(const pnode& config) * This is specialization for complex type */ template -inline typename std::enable_if::value, - ValueType>::type +inline std::enable_if_t::value, ValueType> get_value(const pnode& config) { using real_type = gko::remove_complex; if (config.get_tag() == pnode::tag_t::real) { return static_cast(get_value(config)); } else if (config.get_tag() == pnode::tag_t::array) { - return ValueType{get_value(config.get(0)), - get_value(config.get(1))}; + real_type real(0); + real_type imag(0); + if (config.get_array().size() >= 1) { + real = get_value(config.get(0)); + } + if (config.get_array().size() >= 2) { + imag = get_value(config.get(1)); + } + GKO_THROW_IF_INVALID( + config.get_array().size() <= 2, + "complex value array expression only accept up to two elements"); + return ValueType{real, imag}; } GKO_INVALID_STATE("Can not get complex value"); } diff --git a/core/config/stop_config.cpp b/core/config/stop_config.cpp index 55670377b27..63148cbfcd9 100644 --- a/core/config/stop_config.cpp +++ b/core/config/stop_config.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -15,6 +16,7 @@ #include "core/config/config_helper.hpp" #include "core/config/dispatch.hpp" #include "core/config/registry_accessor.hpp" +#include "core/config/stop_config.hpp" #include "core/config/type_descriptor_helper.hpp" @@ -22,7 +24,7 @@ namespace gko { namespace config { -inline deferred_factory_parameter configure_time( +deferred_factory_parameter configure_time( const pnode& config, const registry& context, const type_descriptor& td) { auto factory = stop::Time::build(); @@ -33,7 +35,7 @@ inline deferred_factory_parameter configure_time( } -inline deferred_factory_parameter configure_iter( +deferred_factory_parameter configure_iter( const pnode& config, const registry& context, const type_descriptor& td) { auto factory = stop::Iteration::build(); @@ -44,7 +46,7 @@ inline deferred_factory_parameter configure_iter( } -stop::mode get_mode(const std::string& str) +inline stop::mode get_mode(const std::string& str) { if (str == "absolute") { return stop::mode::absolute; @@ -79,7 +81,7 @@ class ResidualNormConfigurer { }; -inline deferred_factory_parameter configure_residual( +deferred_factory_parameter configure_residual( const pnode& config, const registry& context, const type_descriptor& td) { auto updated = update_type(config, td); @@ -111,9 +113,8 @@ class ImplicitResidualNormConfigurer { }; -inline deferred_factory_parameter -configure_implicit_residual(const pnode& config, const registry& context, - const type_descriptor& td) +deferred_factory_parameter configure_implicit_residual( + const pnode& config, const registry& context, const type_descriptor& td) { auto updated = update_type(config, td); return dispatch( @@ -122,33 +123,5 @@ configure_implicit_residual(const pnode& config, const registry& context, } -template <> -deferred_factory_parameter -get_factory(const pnode& config, - const registry& context, - const type_descriptor& td) -{ - deferred_factory_parameter ptr; - if (config.get_tag() == pnode::tag_t::string) { - return detail::registry_accessor::get_data( - context, config.get_string()); - } else if (config.get_tag() == pnode::tag_t::map) { - static std::map( - const pnode&, const registry&, type_descriptor)>> - criterion_map{ - {{"stop::Time", configure_time}, - {"stop::Iteration", configure_iter}, - {"stop::ResidualNorm", configure_residual}, - {"stop::ImplicitResidualNorm", configure_implicit_residual}}}; - return criterion_map.at(config.get("type").get_string())(config, - context, td); - } - GKO_THROW_IF_INVALID(!ptr.is_empty(), "Parse get nullptr in the end"); - return ptr; -} - - } // namespace config } // namespace gko diff --git a/core/config/stop_config.hpp b/core/config/stop_config.hpp new file mode 100644 index 00000000000..edb99c6a634 --- /dev/null +++ b/core/config/stop_config.hpp @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors +// +// SPDX-License-Identifier: BSD-3-Clause + +#ifndef GKO_CORE_CONFIG_STOP_CONFIG_HPP_ +#define GKO_CORE_CONFIG_STOP_CONFIG_HPP_ + + +#include +#include +#include +#include + + +namespace gko { +namespace config { + + +deferred_factory_parameter configure_time( + const pnode& config, const registry& context, const type_descriptor& td); + +deferred_factory_parameter configure_iter( + const pnode& config, const registry& context, const type_descriptor& td); + +deferred_factory_parameter configure_residual( + const pnode& config, const registry& context, const type_descriptor& td); + +deferred_factory_parameter configure_implicit_residual( + const pnode& config, const registry& context, const type_descriptor& td); + +} // namespace config +} // namespace gko + + +#endif // GKO_CORE_CONFIG_STOP_CONFIG_HPP_ diff --git a/core/config/type_descriptor.cpp b/core/config/type_descriptor.cpp index de44d19700c..c2885407cad 100644 --- a/core/config/type_descriptor.cpp +++ b/core/config/type_descriptor.cpp @@ -5,6 +5,9 @@ #include +#include + + #include "core/config/type_descriptor_helper.hpp" @@ -21,7 +24,9 @@ type_descriptor update_type(const pnode& config, const type_descriptor& td) value_typestr = obj.get_string(); } if (auto& obj = config.get("index_type")) { - index_typestr = obj.get_string(); + GKO_INVALID_STATE( + "Setting index_type in the config is not allowed. Please set the " + "proper index_type through type_descriptor of parse"); } return type_descriptor{value_typestr, index_typestr}; } diff --git a/core/config/type_descriptor_helper.hpp b/core/config/type_descriptor_helper.hpp index 1a4ca1ac613..3917e317773 100644 --- a/core/config/type_descriptor_helper.hpp +++ b/core/config/type_descriptor_helper.hpp @@ -7,16 +7,11 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include namespace gko { @@ -49,6 +44,8 @@ TYPE_STRING_OVERLOAD(std::complex, "complex"); TYPE_STRING_OVERLOAD(int32, "int32"); TYPE_STRING_OVERLOAD(int64, "int64"); +#undef TYPE_STRING_OVERLOAD + } // namespace config } // namespace gko diff --git a/core/solver/cg.cpp b/core/solver/cg.cpp index 5452fe2bb7a..71e5fcfbb3b 100644 --- a/core/solver/cg.cpp +++ b/core/solver/cg.cpp @@ -69,12 +69,13 @@ typename Cg::parameters_type Cg::parse( } if (auto& obj = config.get("criteria")) { params.with_criteria( - gko::config::get_factory_vector( - obj, context, td_for_child)); + gko::config::parse_or_get_factory_vector< + const stop::CriterionFactory>(obj, context, td_for_child)); } if (auto& obj = config.get("preconditioner")) { - params.with_preconditioner(gko::config::get_factory( - obj, context, td_for_child)); + params.with_preconditioner( + gko::config::parse_or_get_factory( + obj, context, td_for_child)); } return params; } diff --git a/core/test/config/config.cpp b/core/test/config/config.cpp index a791667b8e2..163f6936de2 100644 --- a/core/test/config/config.cpp +++ b/core/test/config/config.cpp @@ -5,9 +5,6 @@ #include -#include - - #include @@ -38,8 +35,7 @@ class Config : public ::testing::Test { : exec(gko::ReferenceExecutor::create()), mtx(gko::initialize( {{2, -1.0, 0.0}, {-1.0, 2, -1.0}, {0.0, -1.0, 2}}, exec)), - stop_config( - {{"type", pnode{"stop::Iteration"}}, {"max_iters", pnode{1}}}) + stop_config({{"type", pnode{"Iteration"}}, {"max_iters", pnode{1}}}) {} std::shared_ptr exec; @@ -139,10 +135,12 @@ TEST(GetValue, IndexType) ASSERT_EQ(get_value(config), value); ASSERT_EQ(get_value(config), value); ASSERT_EQ(get_value(config), value); - ASSERT_EQ(typeid(get_value(config)), typeid(int)); - ASSERT_EQ(typeid(get_value(config)), typeid(long)); - ASSERT_EQ(typeid(get_value(config)), typeid(unsigned)); - ASSERT_EQ(typeid(get_value(config)), typeid(long long int)); + testing::StaticAssertTypeEq(config)), int>(); + testing::StaticAssertTypeEq(config)), long>(); + testing::StaticAssertTypeEq(config)), + unsigned>(); + testing::StaticAssertTypeEq(config)), + long long int>(); } @@ -153,8 +151,8 @@ TEST(GetValue, RealType) ASSERT_EQ(get_value(config), value); ASSERT_EQ(get_value(config), value); - ASSERT_EQ(typeid(get_value(config)), typeid(float)); - ASSERT_EQ(typeid(get_value(config)), typeid(double)); + testing::StaticAssertTypeEq(config)), float>(); + testing::StaticAssertTypeEq(config)), double>(); } @@ -170,19 +168,23 @@ TEST(GetValue, ComplexType) std::complex(real)); ASSERT_EQ(get_value>(config), std::complex(real)); - ASSERT_EQ(typeid(get_value>(config)), - typeid(std::complex)); - ASSERT_EQ(typeid(get_value>(config)), - typeid(std::complex)); + testing::StaticAssertTypeEq>( + config)), + std::complex>(); + testing::StaticAssertTypeEq>( + config)), + std::complex>(); // Two value [real, imag] ASSERT_EQ(get_value>(array_config), std::complex(real, imag)); ASSERT_EQ(get_value>(array_config), std::complex(real, imag)); - ASSERT_EQ(typeid(get_value>(array_config)), - typeid(std::complex)); - ASSERT_EQ(typeid(get_value>(array_config)), - typeid(std::complex)); + testing::StaticAssertTypeEq>( + array_config)), + std::complex>(); + testing::StaticAssertTypeEq>( + array_config)), + std::complex>(); } diff --git a/core/test/config/registry.cpp b/core/test/config/registry.cpp index 78137fd95bf..e6fc8eef671 100644 --- a/core/test/config/registry.cpp +++ b/core/test/config/registry.cpp @@ -5,10 +5,6 @@ #include -#include -#include - - #include @@ -95,13 +91,12 @@ TEST_F(Registry, SearchData) ASSERT_EQ(found_solver_factory, solver_factory); ASSERT_EQ(found_stop_factory, stop_factory); // get correct types - ASSERT_TRUE((std::is_same>::value)); - ASSERT_TRUE((std::is_same>::value)); - ASSERT_TRUE( - (std::is_same>::value)); + testing::StaticAssertTypeEq>(); + testing::StaticAssertTypeEq>(); + testing::StaticAssertTypeEq>(); } @@ -124,13 +119,12 @@ TEST_F(Registry, SearchDataWithType) ASSERT_EQ(found_solver_factory, solver_factory); ASSERT_EQ(found_stop_factory, stop_factory); // get correct types - ASSERT_TRUE( - (std::is_same>::value)); - ASSERT_TRUE( - (std::is_same>::value)); - ASSERT_TRUE((std::is_same>::value)); + testing::StaticAssertTypeEq>(); + testing::StaticAssertTypeEq>(); + testing::StaticAssertTypeEq>(); } @@ -153,13 +147,12 @@ TEST_F(Registry, BuildFromConstructor) ASSERT_EQ(found_solver_factory, solver_factory); ASSERT_EQ(found_stop_factory, stop_factory); // get correct types - ASSERT_TRUE( - (std::is_same>::value)); - ASSERT_TRUE( - (std::is_same>::value)); - ASSERT_TRUE((std::is_same>::value)); + testing::StaticAssertTypeEq>(); + testing::StaticAssertTypeEq>(); + testing::StaticAssertTypeEq>(); } diff --git a/include/ginkgo/core/config/config.hpp b/include/ginkgo/core/config/config.hpp index 376ee14f7c7..5d77c6f71c7 100644 --- a/include/ginkgo/core/config/config.hpp +++ b/include/ginkgo/core/config/config.hpp @@ -27,52 +27,82 @@ class pnode; /** - * parse is the main entry point to create an Ginkgo object based on + * parse is the main entry point to create an Ginkgo LinOpFactory based on * some file configuration. It reads a configuration stored as a property tree * and creates the desired type. * * General rules for configuration - * 1. all parameter and template usage are according to the class directly. It - * has the same behavior as the class like default setting without specifying - * anything. When the class factory parameters allows `with_(value)`, - * the file configuration will allow `"": value` - * 2. all key will use snake_case including template. For example, ValueType -> - * value_type - * 3. If the value is not bool, integer, or floating point, we will use string - * to represent everything. For example, we will use string to select the - * enum value. `"baseline": "absolute"` will select the absolute baseline in - * ResidualNorm critrion - * 4. `"type"` is the new key to select the class without template type. We also - * prepend the namespace except for gko. For example, we use "solver::Cg" for - * Cg solver. Note. the template type is given by the another entry or from - * the type_descriptor. - * 5. the data type uses fixed-width representation - * void, int32, int64, float32, float64, complex, complex - * 6. We use [real, imag] to represent complex value. If it only contains one - * value or without [], we will treat it as the complex number with imaginary - * part = 0. - * 7. In many cases, the parameter allows vector input and we handle it by array - * of property tree. If the array only contains one object, users can - * directly provide the object without putting it into an array. - * `"criteria": [{...}]` and `"criteria": {...}` are the same. + * 1. The configuration can be used to define factory parameters and class + * template parameters. Any factory parameter that is not defined in the + * configuration will fallback to their default value. Any template parameter + * that is not defined will fallback to the type_descriptor argument + * 2. The new `"type"` key determines which Ginkgo object to create. The value + * for this key is the desired class name with namespaces (except for + * `gko::`, `experimental::`, `stop::`). Any template parameters a class + * might have are left out. Only classes with a factory are supported. For + * example, the configuration `"type": "solver::Cg"` specifies that a Cg + * solver will be created. Note: template parameters can either be given in + * the configuration as separate key-value pairs, or in the type_descriptor. + * 3. Factory and class template parameters can be defined with key-value pairs + * that are derived from the class they are referring to. When a factory has + * a parameter with the function `with_(value)`, then the configuration + * allows `"": value` to define this parameter. When a class has a + * template parameter `template class`, then + * the configuration allows `"": value` to the template parameter. The + * supported values of the template parameter depend on the context. For + * index and value types, these are listed under 4. + * 4. Values for template parameters are represented with strings. The following + * datatypes, with postfix to indicate their size, are supported: int32, + * int64, float32, float64, complex, complex. + * 5. All keys use snake_case including template parameters. Factory parameter + * keys are already defined with snake_case in their factories, while class + * template arguments need to be translated, i.e. `ValueType -> value_type`. + * 6. The allowed values for factory parameters depend on the type the parameter + * is stored as. There are three distinct options: + * - POD types (bool, integer, floating point, or enum): Except for enum, + * the value has to be the POD type. For enums, a string value is used to + * represent them. The string has to be one of the possible enum values. + * An example of this type of parameter is the `krylov_dim` parameter for + * the Gmres solver. + * - LinOp (smart) pointers: The value has to be a string. The string is used + * to look up a LinOp object in the registry. + * An example is the `generated_preconditioner` parameter for iterative + * solvers such as Cg. + * - LinOpFactory (smart) pointers: The value can either be a string, or a + * nested configuration. The string has the same behavior as for LinOp + * pointers, i.e. an LinOpFactory object from the registry is taken. The + * nested configuration has to adhere to the general configuration rules + * again. See the examples below for some use-cases. + * An example is the `preconditioner` parameter for iterative solvers + * such as Cg. + * - CriterionFactory (smart) pointers: The value can either be a string, or + * a nested configuration. It has the same behavior as for LinOpFactory. + * - A vector of the types above: The value has to be an array with the + * inner values specified as above. + * 7. Complex values are represented as an 2-element array [real, imag]. If the + * array contains only one value, it will be considered as a complex number + * with an imaginary part = 0. An empty array will be treated as zero. + * 8. Keys that expect array of objects also accept single object which is + * interpreted as a 1-element array. This means the following configurations + * are equivalent if the key expects an array value: `"": [{object}]` + * and `"": {object}`. * - * The configuration needs - * to specify the resulting type by the field: + * All configurations need to specify the resulting type by the field: * ``` * "type": "some_supported_ginkgo_type" * ``` - * The result will be a deferred_factory_parameter, - * which can be thought of as an intermediate step before a LinOpFactory. - * Providing the result an Executor through the function `.on(exec)` will then - * create the factory with the parameters as defined in the configuration. + * The result will be a deferred_factory_parameter, which is an intermediate + * step before a LinOpFactory. Providing an Executor through the function + * `.on(exec)` will then create the factory with the parameters as defined in + * the configuration. * * Given a configuration that is defined as * ``` * "type": "solver::Gmres", * "krylov_dim": 20, * "criteria": [ - * {"type": "stop::Iteration", "max_iters": 10}, - * {"type": "stop::ResidualNorm", "reduction_factor": 1e-6} + * {"type": "Iteration", "max_iters": 10}, + * {"type": "ResidualNorm", "reduction_factor": 1e-6} * ] * ``` * then passing it to this function like this: @@ -96,7 +126,6 @@ class pnode; * Additionally, the config can be used to set these types through the fields: * ``` * value_type: "some_value_type" - * index_type: "some_index_type" * ``` * These types take precedence over the type descriptor and they are used for * every created object beginning from the config level they are defined on and @@ -125,7 +154,10 @@ class pnode; * templated type, then the value and/or index type from * the descriptor will be used. Any definition of the * value and/or index type within the config will take - * precedence over the descriptor. + * precedence over the descriptor. If `void` is used for + * one or both of the types, then the corresponding type + * has to be defined in the config, otherwise the + * parsing will fail. * * @return a deferred_factory_parameter which creates an LinOpFactory after * `.on(exec)` is called on it. diff --git a/include/ginkgo/core/config/registry.hpp b/include/ginkgo/core/config/registry.hpp index b4c1658c037..2efa160ee65 100644 --- a/include/ginkgo/core/config/registry.hpp +++ b/include/ginkgo/core/config/registry.hpp @@ -51,20 +51,20 @@ template struct base_type {}; template -struct base_type< - T, typename std::enable_if::value>::type> { +struct base_type::value>> { using type = LinOp; }; template -struct base_type::value>::type> { +struct base_type< + T, std::enable_if_t::value>> { using type = LinOpFactory; }; template -struct base_type::value>::type> { +struct base_type< + T, + std::enable_if_t::value>> { using type = stop::CriterionFactory; }; @@ -76,11 +76,11 @@ struct base_type allowed_ptr(std::shared_ptr obj); @@ -110,7 +110,12 @@ class allowed_ptr { template struct concrete_container : generic_container { - concrete_container(std::shared_ptr obj) : ptr{obj} {} + concrete_container(std::shared_ptr obj) : ptr{obj} + { + static_assert( + std::is_same::type>::value, + "The given type must be a base_type"); + } std::shared_ptr ptr; }; @@ -151,7 +156,8 @@ inline std::shared_ptr allowed_ptr::get() const * This class stores additional context for creating Ginkgo objects from * configuration files. * - * The context can contain user provided objects of the following types: + * The context can contain user-provided objects that derive from the following + * base types: * - LinOp * - LinOpFactory * - CriterionFactory @@ -168,8 +174,10 @@ class registry final { * registry constructor * * @param additional_map the additional map to dispatch the class base. - * Users can extend map to fit their own - * LinOpFactory. + * Users can extend the map to fit their own + * LinOpFactory. We suggest using "usr::" as the + * prefix in the key to simply avoid conflict with + * ginkgo's map. */ registry(const configuration_map& additional_map = {}); @@ -187,15 +195,17 @@ class registry final { * }} * ``` * @param additional_map the additional map to dispatch the class base. - * Users can extend map to fit their own - * LinOpFactory. + * Users can extend the map to fit their own + * LinOpFactory. We suggest using "usr::" as the + * prefix in the key to simply avoid conflict with + * ginkgo's map. */ registry( const std::unordered_map& stored_map, const configuration_map& additional_map = {}); /** - * insert_data stores the data with the key. + * Store the data with the key. * * @tparam T the type * @@ -207,7 +217,7 @@ class registry final { protected: /** - * get_data searches the key on the corresponding map. + * Search the key on the corresponding map. * * @tparam T the type * @@ -219,7 +229,7 @@ class registry final { std::shared_ptr get_data(std::string key) const; /** - * get the stored build map + * Get the stored build map */ const configuration_map& get_build_map() const { return build_map_; } diff --git a/include/ginkgo/core/config/type_descriptor.hpp b/include/ginkgo/core/config/type_descriptor.hpp index 3a05ee33aac..48475f7f469 100644 --- a/include/ginkgo/core/config/type_descriptor.hpp +++ b/include/ginkgo/core/config/type_descriptor.hpp @@ -16,17 +16,18 @@ namespace config { * This class describes the value and index types to be used when building a * Ginkgo type from a configuration file. * - * A type_descriptor is passed to the parse function defines which - * template parameters, in terms of value_type and/or index_type, the created - * object will have. For example, a CG solver created like this: + * A type_descriptor is passed in order to define the parse function defines + * which template parameters, in terms of value_type and/or index_type, the + * created object will have. For example, a CG solver created like this: * ``` * auto cg = parse(config, context, type_descriptor("float64", "int32")); * ``` * will have the value type `float64` and the index type `int32`. Any Ginkgo - * object that does not require one of these types will just ignore it. We used - * void type to specify no default type. + * object that does not require one of these types will just ignore it. The + * value `void` can be used to specify that no default type is provided. In this + * case, the configuration has to provide the necessary template types. * - * If the configurations specifies one of the fields (or both): + * If the configuration specifies one of the fields (or both): * ``` * value_type: "some_value_type" * index_type: "some_index_type" @@ -65,7 +66,7 @@ class type_descriptor final { /** - * make_type_descriptor is a helper function to properly set up the descriptor + * A helper function to properly set up the descriptor * from template type directly. * * @tparam ValueType the value type in descriptor diff --git a/include/ginkgo/core/solver/cg.hpp b/include/ginkgo/core/solver/cg.hpp index 6678d8ac618..9302f2297b3 100644 --- a/include/ginkgo/core/solver/cg.hpp +++ b/include/ginkgo/core/solver/cg.hpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -75,6 +76,18 @@ class Cg : public EnableLinOp>, GKO_ENABLE_LIN_OP_FACTORY(Cg, parameters, Factory); GKO_ENABLE_BUILD_METHOD(Factory); + /** + * Create the parameters from the property_tree. + * Because this is directly tied to the specific type. The value/index type + * settings are ignored and type_descriptor is for children objects. + * + * @param config the property tree for setting + * @param context the registry + * @param td_for_child the type descriptor for children objects. The + * default will directly from the specific type. + * + * @return parameters + */ static parameters_type parse(const config::pnode& config, const config::registry& context, const config::type_descriptor& td_for_child =